From 00727d6b6db92dc1cf98f028f26fd6168594b905 Mon Sep 17 00:00:00 2001 From: LeeChunHei Date: Tue, 23 Feb 2021 17:05:01 +0800 Subject: [PATCH 01/65] provide possibility for multi usb host --- components/drivers/include/drivers/usb_host.h | 10 +++--- components/drivers/usb/usbhost/core/driver.c | 19 +++++++---- components/drivers/usb/usbhost/core/hub.c | 34 ++++++++++--------- components/drivers/usb/usbhost/core/usbhost.c | 20 ++++++++--- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/components/drivers/include/drivers/usb_host.h b/components/drivers/include/drivers/usb_host.h index 2a68f4edb5..f8e4b52f8b 100644 --- a/components/drivers/include/drivers/usb_host.h +++ b/components/drivers/include/drivers/usb_host.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2011-3-12 Yi Qiu first version + * 2021-02-23 Leslie Lee provide possibility for multi usb host */ #ifndef __RT_USB_HOST_H__ @@ -136,7 +137,8 @@ struct uhcd struct rt_device parent; uhcd_ops_t ops; rt_uint8_t num_ports; - uhub_t roothub; + uhub_t roothub; + struct rt_messagequeue *usb_mq; }; typedef struct uhcd* uhcd_t; @@ -163,7 +165,7 @@ struct uhost_msg typedef struct uhost_msg* uhost_msg_t; /* usb host system interface */ -rt_err_t rt_usb_host_init(void); +rt_err_t rt_usb_host_init(const char *name); void rt_usbh_hub_init(struct uhcd *hcd); /* usb host core interface */ @@ -203,7 +205,7 @@ rt_err_t rt_usbh_hub_clear_port_feature(uhub_t uhub, rt_uint16_t port, rt_err_t rt_usbh_hub_set_port_feature(uhub_t uhub, rt_uint16_t port, rt_uint16_t feature); rt_err_t rt_usbh_hub_reset_port(uhub_t uhub, rt_uint16_t port); -rt_err_t rt_usbh_event_signal(struct uhost_msg* msg); +rt_err_t rt_usbh_event_signal(uhcd_t uhcd, struct uhost_msg* msg); void rt_usbh_root_hub_connect_handler(struct uhcd *hcd, rt_uint8_t port, rt_bool_t isHS); @@ -265,5 +267,3 @@ rt_inline int rt_usb_hcd_setup_xfer(uhcd_t hcd, upipe_t pipe, ureq_t setup, int #endif #endif - - diff --git a/components/drivers/usb/usbhost/core/driver.c b/components/drivers/usb/usbhost/core/driver.c index 37327108c1..542d456ff1 100644 --- a/components/drivers/usb/usbhost/core/driver.c +++ b/components/drivers/usb/usbhost/core/driver.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2011-03-12 Yi Qiu first version + * 2021-02-23 Leslie Lee provide possibility for multi usb host */ #include @@ -13,6 +14,7 @@ #include static rt_list_t _driver_list; +static rt_bool_t _driver_list_created = RT_FALSE; /** * This function will initilize the usb class driver related data structure, @@ -22,8 +24,11 @@ static rt_list_t _driver_list; */ rt_err_t rt_usbh_class_driver_init(void) { - rt_list_init(&_driver_list); - + if (_driver_list_created == RT_FALSE) + { + rt_list_init(&_driver_list); + _driver_list_created = RT_TRUE; + } return RT_EOK; } @@ -39,8 +44,11 @@ rt_err_t rt_usbh_class_driver_register(ucd_t drv) { if (drv == RT_NULL) return -RT_ERROR; - /* insert class driver into driver list */ - rt_list_insert_after(&_driver_list, &(drv->list)); + if (rt_usbh_class_driver_find(drv->class_code, drv->subclass_code) == RT_NULL) + { + /* insert class driver into driver list */ + rt_list_insert_after(&_driver_list, &(drv->list)); + } return RT_EOK; } @@ -136,5 +144,4 @@ ucd_t rt_usbh_class_driver_find(int class_code, int subclass_code) /* not found */ return RT_NULL; -} - +} \ No newline at end of file diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c index eefa571472..e8c8dfff72 100644 --- a/components/drivers/usb/usbhost/core/hub.c +++ b/components/drivers/usb/usbhost/core/hub.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2011-12-12 Yi Qiu first version + * 2021-02-23 Leslie Lee provide possibility for multi usb host */ #include @@ -13,9 +14,9 @@ #define USB_THREAD_STACK_SIZE 4096 -static struct rt_messagequeue *usb_mq; +// static struct rt_messagequeue *usb_mq; static struct uclass_driver hub_driver; -static struct uhub root_hub; +// static struct uhub root_hub; static rt_err_t root_hub_ctrl(struct uhcd *hcd, rt_uint16_t port, rt_uint8_t cmd, void *args) { @@ -92,7 +93,7 @@ void rt_usbh_root_hub_connect_handler(struct uhcd *hcd, rt_uint8_t port, rt_bool { hcd->roothub->port_status[port - 1] |= PORT_LSDA; } - rt_usbh_event_signal(&msg); + rt_usbh_event_signal(hcd, &msg); } void rt_usbh_root_hub_disconnect_handler(struct uhcd *hcd, rt_uint8_t port) @@ -102,7 +103,7 @@ void rt_usbh_root_hub_disconnect_handler(struct uhcd *hcd, rt_uint8_t port) msg.content.hub = hcd->roothub; hcd->roothub->port_status[port - 1] |= PORT_CCSC; hcd->roothub->port_status[port - 1] &= ~PORT_CCS; - rt_usbh_event_signal(&msg); + rt_usbh_event_signal(hcd, &msg); } /** @@ -647,12 +648,13 @@ ucd_t rt_usbh_class_driver_hub(void) */ static void rt_usbh_hub_thread_entry(void* parameter) { + uhcd_t hcd = (uhcd_t)parameter; while(1) { struct uhost_msg msg; /* receive message */ - if(rt_mq_recv(usb_mq, &msg, sizeof(struct uhost_msg), RT_WAITING_FOREVER) + if(rt_mq_recv(hcd->usb_mq, &msg, sizeof(struct uhost_msg), RT_WAITING_FOREVER) != RT_EOK ) continue; //RT_DEBUG_LOG(RT_DEBUG_USB, ("msg type %d\n", msg.type)); @@ -679,12 +681,12 @@ static void rt_usbh_hub_thread_entry(void* parameter) * * @return the error code, RT_EOK on successfully. */ -rt_err_t rt_usbh_event_signal(struct uhost_msg* msg) +rt_err_t rt_usbh_event_signal(uhcd_t hcd, struct uhost_msg* msg) { RT_ASSERT(msg != RT_NULL); /* send message to usb message queue */ - rt_mq_send(usb_mq, (void*)msg, sizeof(struct uhost_msg)); + rt_mq_send(hcd->usb_mq, (void*)msg, sizeof(struct uhost_msg)); return RT_EOK; } @@ -698,21 +700,21 @@ rt_err_t rt_usbh_event_signal(struct uhost_msg* msg) void rt_usbh_hub_init(uhcd_t hcd) { rt_thread_t thread; - /* link root hub to hcd */ - root_hub.is_roothub = RT_TRUE; - hcd->roothub = &root_hub; - root_hub.hcd = hcd; - root_hub.num_ports = hcd->num_ports; + /* create root hub for hcd */ + hcd->roothub = rt_malloc(sizeof(struct uhub)); + rt_memset(hcd->roothub, 0, sizeof(struct uhub)); + hcd->roothub->is_roothub = RT_TRUE; + hcd->roothub->hcd = hcd; + hcd->roothub->num_ports = hcd->num_ports; /* create usb message queue */ - usb_mq = rt_mq_create("usbh", 32, 16, RT_IPC_FLAG_FIFO); + hcd->usb_mq = rt_mq_create(hcd->parent.parent.name, 32, 16, RT_IPC_FLAG_FIFO); /* create usb hub thread */ - thread = rt_thread_create("usbh", rt_usbh_hub_thread_entry, RT_NULL, + thread = rt_thread_create(hcd->parent.parent.name, rt_usbh_hub_thread_entry, hcd, USB_THREAD_STACK_SIZE, 8, 20); if(thread != RT_NULL) { /* startup usb host thread */ rt_thread_startup(thread); } -} - +} \ No newline at end of file diff --git a/components/drivers/usb/usbhost/core/usbhost.c b/components/drivers/usb/usbhost/core/usbhost.c index f0294238c4..201ec2229b 100644 --- a/components/drivers/usb/usbhost/core/usbhost.c +++ b/components/drivers/usb/usbhost/core/usbhost.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2011-12-12 Yi Qiu first version + * 2021-02-23 Leslie Lee provide possibility for multi usb host */ #include #include @@ -22,15 +23,15 @@ * * @return none. */ -rt_err_t rt_usb_host_init(void) +rt_err_t rt_usb_host_init(const char *name) { ucd_t drv; rt_device_t uhc; - uhc = rt_device_find(USB_HOST_CONTROLLER_NAME); + uhc = rt_device_find(name); if(uhc == RT_NULL) { - rt_kprintf("can't find usb host controller %s\n", USB_HOST_CONTROLLER_NAME); + rt_kprintf("can't find usb host controller %s\n", name); return -RT_ERROR; } @@ -44,6 +45,16 @@ rt_err_t rt_usb_host_init(void) /* register mass storage class driver */ drv = rt_usbh_class_driver_storage(); rt_usbh_class_driver_register(drv); +#endif +#ifdef RT_USBH_HID + /* register mass storage class driver */ + drv = rt_usbh_class_driver_hid(); + rt_usbh_class_driver_register(drv); +#ifdef RT_USBH_HID_MOUSE + uprotocal_t protocal; + protocal = rt_usbh_hid_protocal_mouse(); + rt_usbh_hid_protocal_register(protocal); +#endif #endif /* register hub class driver */ @@ -54,5 +65,4 @@ rt_err_t rt_usb_host_init(void) rt_device_init(uhc); return RT_EOK; -} - +} \ No newline at end of file From 433e5f81473f71e36fbfb2a4ca5fcbb6b28f57b2 Mon Sep 17 00:00:00 2001 From: jiladahe1997 <972931182@qq.com> Date: Thu, 9 Dec 2021 11:22:46 +0800 Subject: [PATCH 02/65] =?UTF-8?q?[bugfix]=20libcpu/arm/cortex-m/context=5F?= =?UTF-8?q?gcc:=20=E4=BF=AE=E5=A4=8Dthumb=E6=8C=87=E4=BB=A4=E9=9B=86?= =?UTF-8?q?=E6=B1=87=E7=BC=96=E8=AF=AD=E6=B3=95=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当使用thumb指令集时,要求汇编语法中的“条件执行”要跟在IT指令后面,否则会编译不通过。 报错如下:Error: thumb conditional instruction should be in IT block -- `moveq r4,#0x01' 虽然可以通过指定"-Wa,-mimplicit-it=thumb"选项来告诉编译器识别隐式的IT指令,但是能在代码里面直接加上IT指令的话更好。 thumb指令集“条件执行”arm官网文档: https://developer.arm.com/documentation/dui0473/m/condition-codes/conditional-execution-in-thumb-state 参考论坛帖子: https://club.rt-thread.org/ask/question/433887.html https://club.rt-thread.org/ask/question/4188.html Signed-off-by: Mingrui Ren --- libcpu/arm/cortex-m33/context_gcc.S | 2 ++ libcpu/arm/cortex-m4/context_gcc.S | 4 ++++ libcpu/arm/cortex-m7/context_gcc.S | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/libcpu/arm/cortex-m33/context_gcc.S b/libcpu/arm/cortex-m33/context_gcc.S index 27596bf787..3c4ac8a236 100644 --- a/libcpu/arm/cortex-m33/context_gcc.S +++ b/libcpu/arm/cortex-m33/context_gcc.S @@ -143,6 +143,7 @@ contex_ns_store: #if defined (__VFP_FP__) && !defined(__SOFTFP__) TST lr, #0x10 /* if(!EXC_RETURN[4]) */ + IT EQ VSTMDBEQ r1!, {d8 - d15} /* push FPU register s16~s31 */ #endif @@ -187,6 +188,7 @@ contex_ns_load: #if defined (__VFP_FP__) && !defined(__SOFTFP__) TST lr, #0x10 /* if(!EXC_RETURN[4]) */ + IT EQ VLDMIAEQ r1!, {d8 - d15} /* pop FPU register s16~s31 */ #endif diff --git a/libcpu/arm/cortex-m4/context_gcc.S b/libcpu/arm/cortex-m4/context_gcc.S index f569a35863..0c69b4d4dd 100644 --- a/libcpu/arm/cortex-m4/context_gcc.S +++ b/libcpu/arm/cortex-m4/context_gcc.S @@ -107,6 +107,7 @@ PendSV_Handler: #if defined (__VFP_FP__) && !defined(__SOFTFP__) TST lr, #0x10 /* if(!EXC_RETURN[4]) */ + IT EQ VSTMDBEQ r1!, {d8 - d15} /* push FPU register s16~s31 */ #endif @@ -116,6 +117,7 @@ PendSV_Handler: MOV r4, #0x00 /* flag = 0 */ TST lr, #0x10 /* if(!EXC_RETURN[4]) */ + IT EQ MOVEQ r4, #0x01 /* flag = 1 */ STMFD r1!, {r4} /* push flag */ @@ -137,6 +139,7 @@ switch_to_thread: #if defined (__VFP_FP__) && !defined(__SOFTFP__) CMP r3, #0 /* if(flag_r3 != 0) */ + IT NE VLDMIANE r1!, {d8 - d15} /* pop FPU register s16~s31 */ #endif @@ -145,6 +148,7 @@ switch_to_thread: #if defined (__VFP_FP__) && !defined(__SOFTFP__) ORR lr, lr, #0x10 /* lr |= (1 << 4), clean FPCA. */ CMP r3, #0 /* if(flag_r3 != 0) */ + IT NE BICNE lr, lr, #0x10 /* lr &= ~(1 << 4), set FPCA. */ #endif diff --git a/libcpu/arm/cortex-m7/context_gcc.S b/libcpu/arm/cortex-m7/context_gcc.S index f569a35863..0c69b4d4dd 100644 --- a/libcpu/arm/cortex-m7/context_gcc.S +++ b/libcpu/arm/cortex-m7/context_gcc.S @@ -107,6 +107,7 @@ PendSV_Handler: #if defined (__VFP_FP__) && !defined(__SOFTFP__) TST lr, #0x10 /* if(!EXC_RETURN[4]) */ + IT EQ VSTMDBEQ r1!, {d8 - d15} /* push FPU register s16~s31 */ #endif @@ -116,6 +117,7 @@ PendSV_Handler: MOV r4, #0x00 /* flag = 0 */ TST lr, #0x10 /* if(!EXC_RETURN[4]) */ + IT EQ MOVEQ r4, #0x01 /* flag = 1 */ STMFD r1!, {r4} /* push flag */ @@ -137,6 +139,7 @@ switch_to_thread: #if defined (__VFP_FP__) && !defined(__SOFTFP__) CMP r3, #0 /* if(flag_r3 != 0) */ + IT NE VLDMIANE r1!, {d8 - d15} /* pop FPU register s16~s31 */ #endif @@ -145,6 +148,7 @@ switch_to_thread: #if defined (__VFP_FP__) && !defined(__SOFTFP__) ORR lr, lr, #0x10 /* lr |= (1 << 4), clean FPCA. */ CMP r3, #0 /* if(flag_r3 != 0) */ + IT NE BICNE lr, lr, #0x10 /* lr &= ~(1 << 4), set FPCA. */ #endif From 1f2e93f1a39590af9a71ecc31b12045696ca6055 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 27 Dec 2021 20:34:35 -0500 Subject: [PATCH 03/65] [kernel] remove .init_priority --- include/rtdef.h | 1 - src/thread.c | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/rtdef.h b/include/rtdef.h index c22c20beee..6592c27110 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -631,7 +631,6 @@ struct rt_thread /* priority */ rt_uint8_t current_priority; /**< current priority */ - rt_uint8_t init_priority; /**< initialized priority */ #if RT_THREAD_PRIORITY_MAX > 32 rt_uint8_t number; rt_uint8_t high_mask; diff --git a/src/thread.c b/src/thread.c index 7913e12f5d..2f06cedd44 100644 --- a/src/thread.c +++ b/src/thread.c @@ -28,6 +28,7 @@ * add support for tasks bound to cpu * 2021-02-24 Meco Man rearrange rt_thread_control() - schedule the thread when close it * 2021-11-15 THEWON Remove duplicate work between idle and _thread_exit + * 2021-12-27 Meco Man remove .init_priority */ #include @@ -138,7 +139,6 @@ static rt_err_t _thread_init(struct rt_thread *thread, /* priority init */ RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); - thread->init_priority = priority; thread->current_priority = priority; thread->number_mask = 0; @@ -297,9 +297,6 @@ rt_err_t rt_thread_startup(rt_thread_t thread) RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); - /* set current priority to initialize priority */ - thread->current_priority = thread->init_priority; - /* calculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ @@ -310,7 +307,7 @@ rt_err_t rt_thread_startup(rt_thread_t thread) #endif /* RT_THREAD_PRIORITY_MAX > 32 */ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n", - thread->name, thread->init_priority)); + thread->name, thread->current_priority)); /* change thread stat */ thread->stat = RT_THREAD_SUSPEND; /* then resume it */ From 6d2a7d00db2808f26b96efaebfa3aa18b6fd47b8 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 5 Jan 2022 14:38:20 +0800 Subject: [PATCH 04/65] Update drivers. 1. Improve LVGL avg FPS. 2. Sync configuration to 4.1.0. --- .../libraries/m2354/StdDriver/src/nu_crypto.c | 5 + .../libraries/n9h30/Driver/Include/nu_spi.h | 2 +- bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig | 24 +- .../libraries/n9h30/rtt_port/drv_common.c | 37 +++ .../libraries/n9h30/rtt_port/drv_ge2d.c | 11 +- .../libraries/n9h30/rtt_port/drv_qspi.c | 6 +- .../libraries/n9h30/rtt_port/drv_vpost.c | 20 +- .../libraries/nuc980/rtt_port/drv_emac.c | 18 +- bsp/nuvoton/nk-980iot/.config | 257 +++++++++++++----- bsp/nuvoton/nk-980iot/board/Kconfig | 5 + bsp/nuvoton/nk-980iot/rtconfig.py | 2 +- bsp/nuvoton/nk-n9h30/.config | 77 ++++-- .../nk-n9h30/applications/lvgl/lv_conf.h | 12 +- .../nk-n9h30/applications/lvgl/lv_port_disp.c | 70 ++++- bsp/nuvoton/nk-n9h30/applications/mnt.c | 2 +- bsp/nuvoton/nk-n9h30/board/nu_pin_init.c | 2 +- bsp/nuvoton/nk-n9h30/rtconfig.py | 4 +- bsp/nuvoton/nk-rtu980/.config | 234 ++++++++++++---- bsp/nuvoton/numaker-iot-m487/.config | 86 ++++-- bsp/nuvoton/numaker-m2354/.config | 83 ++++-- bsp/nuvoton/numaker-pfm-m487/.config | 83 ++++-- 21 files changed, 761 insertions(+), 279 deletions(-) diff --git a/bsp/nuvoton/libraries/m2354/StdDriver/src/nu_crypto.c b/bsp/nuvoton/libraries/m2354/StdDriver/src/nu_crypto.c index 3e0bf6480e..c7db7a504d 100644 --- a/bsp/nuvoton/libraries/m2354/StdDriver/src/nu_crypto.c +++ b/bsp/nuvoton/libraries/m2354/StdDriver/src/nu_crypto.c @@ -9,6 +9,11 @@ #include #include +#ifdef __has_include + #if __has_include("strings.h") + #include + #endif +#endif #include "NuMicro.h" #define ENABLE_DEBUG 0 diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h index a453e1dddc..3cb1500f2a 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_spi.h @@ -40,7 +40,7 @@ extern "C" #define TX2 0x18 /*!< Transfer Register 2 Address */ #define TX3 0x1C /*!< Transfer Register 3 Address */ -#define SPI_INPUT_CLOCK 75000000 /* Unit: Hz */ +#define SPI_INPUT_CLOCK (sysGetClock(SYS_PCLK)*1000000) /* Unit: Hz */ /// @endcond HIDDEN_SYMBOLS #define SPI_NUMBER 2 /*!< 2 spi interfaces */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig index 7b898c79b5..f57b439f00 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig @@ -480,18 +480,30 @@ config SOC_SERIES_N9H30 config VPOST_USING_LCD_IDX int default 0 if LCM_USING_E50A2V1 - default 2 if LCM_USING_LSA40AT9001 default 3 if LCM_USING_FW070TFT default 4 if LCM_USING_FW043TFT - config LCM_USING_BPP + config BSP_LCD_BPP int - default 2 if LCM_USING_E50A2V1 + default 16 if LCM_USING_E50A2V1 + default 16 if LCM_USING_LSA40AT9001 + default 32 if LCM_USING_FW070TFT + default 32 if LCM_USING_FW043TFT - default 2 if LCM_USING_LSA40AT9001 - default 4 if LCM_USING_FW070TFT - default 4 if LCM_USING_FW043TFT + config BSP_LCD_WIDTH + int + default 800 if LCM_USING_E50A2V1 + default 800 if LCM_USING_LSA40AT9001 + default 800 if LCM_USING_FW070TFT + default 480 if LCM_USING_FW043TFT + + config BSP_LCD_HEIGHT + int + default 480 if LCM_USING_E50A2V1 + default 600 if LCM_USING_LSA40AT9001 + default 480 if LCM_USING_FW070TFT + default 272 if LCM_USING_FW043TFT config BSP_USING_VPOST_OSD bool "Enable VPOST OSD layer" diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c index b96c9b7b04..a5e55dffc2 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_common.c @@ -76,3 +76,40 @@ RT_WEAK void rt_hw_board_init(void) rt_kprintf("Heap: Begin@%08x, END@%08x, SIZE:%d\n", BOARD_HEAP_START, BOARD_HEAP_END, (rt_uint32_t)BOARD_HEAP_END - (rt_uint32_t)BOARD_HEAP_START); #endif } + + +void devmem(int argc, char *argv[]) +{ + volatile unsigned int u32Addr; + unsigned int value = 0, mode = 0; + + if (argc < 2 || argc > 3) + { + goto exit_devmem; + } + + if (argc == 3) + { + if (sscanf(argv[2], "0x%x", &value) != 1) + goto exit_devmem; + mode = 1; //Write + } + + if (sscanf(argv[1], "0x%x", &u32Addr) != 1) + goto exit_devmem; + else if (!u32Addr || u32Addr & (4 - 1)) + goto exit_devmem; + + if (mode) + { + *((volatile uint32_t *)u32Addr) = value; + } + rt_kprintf("0x%08x\n", *((volatile uint32_t *)u32Addr)); + + return; +exit_devmem: + rt_kprintf("Read: devmem \n"); + rt_kprintf("Write: devmem \n"); + return; +} +MSH_CMD_EXPORT(devmem, dump device registers); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c index 6862dce23e..ddbcfd18dc 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_ge2d.c @@ -629,11 +629,10 @@ static struct nu_ge2d g_sNuGe2d = } #define NU_GE2D_COND_WAIT() { \ - if( (inpw(REG_GE2D_INTSTS) & 0x01) == 0 ) \ - { \ - rt_thread_mdelay(1); \ - rt_completion_wait(&g_sNuGe2d.signal, 100); \ - } \ + if( (inpw(REG_GE2D_INTSTS) & 0x01) == 0 ) \ + { \ + rt_completion_wait(&g_sNuGe2d.signal, 60); \ + } \ } #define NU_GE2D_SIGNAL() { \ @@ -3179,7 +3178,7 @@ void ge2dInitMonoPattern(int opt, int fore_color, int back_color) * @param[in] back_color is color of background * @return none */ -void ge2dInitMonoInputPattern(UINT32 PatternA, UINT32 PatternB, int fore_color, int back_color) +void ge2dInitMonoInputPattern(uint32_t PatternA, uint32_t PatternB, int fore_color, int back_color) { UINT32 color32; diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c index 1cbcbc58a1..67bfa8b0f9 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_qspi.c @@ -154,7 +154,11 @@ static rt_err_t nu_qspi_bus_configure(struct rt_spi_device *device, /* Set speed */ u32SPISpeed = configuration->max_hz; - if (u32SPISpeed > DEF_SPI_MAX_SPEED) + + /* Limitation: SPI clock must be lower than 37.5MHz. */ + if ((SPI_INPUT_CLOCK / 2) > 37500000) + u32SPISpeed = SPI_INPUT_CLOCK / 4; + else if (u32SPISpeed > DEF_SPI_MAX_SPEED) u32SPISpeed = DEF_SPI_MAX_SPEED; u32SPISpeed = spiIoctl(qspi_bus->idx, SPI_IOC_SET_SPEED, u32SPISpeed, 0); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c index 72baa151a4..41fae42ae4 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c @@ -41,12 +41,12 @@ struct nu_vpost IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; + uint32_t last_commit; struct rt_device_graphic_info info; }; typedef struct nu_vpost *nu_vpost_t; static volatile uint32_t g_u32VSyncBlank = 0; -static volatile uint32_t g_u32VSyncLastCommit = 0; static struct rt_completion vsync_wq; static struct nu_vpost nu_fbdev[eVpost_Cnt] = @@ -87,7 +87,7 @@ static rt_err_t vpost_layer_open(rt_device_t dev, rt_uint16_t oflag) /* Set scale to 1:1 */ vpostOSDScalingCtrl(1, 0, 0); -#if (LCM_USING_BPP==4) +#if (BSP_LCD_BPP==32) vpostOSDSetColMask(0xff, 0xff, 0xff); #else vpostOSDSetColMask(0x1f, 0x3f, 0x1f); @@ -163,7 +163,7 @@ static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) { uint8_t *pu8BufPtr = (uint8_t *)args; - g_u32VSyncLastCommit = g_u32VSyncBlank; + psVpost->last_commit = g_u32VSyncBlank; /* Pan display */ switch (psVpost->layer) @@ -191,9 +191,9 @@ static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) case RTGRAPHIC_CTRL_WAIT_VSYNC: { if (args != RT_NULL) - g_u32VSyncLastCommit = g_u32VSyncBlank + 1; + psVpost->last_commit = g_u32VSyncBlank + 1; - if (g_u32VSyncLastCommit >= g_u32VSyncBlank) + if (psVpost->last_commit >= g_u32VSyncBlank) { rt_completion_init(&vsync_wq); rt_completion_wait(&vsync_wq, RT_TICK_PER_SECOND / 60); @@ -287,9 +287,9 @@ int rt_hw_vpost_init(void) rt_memset((void *)&psVpost->info, 0, sizeof(struct rt_device_graphic_info)); /* Register VPOST information */ - psVpost->info.bits_per_pixel = LCM_USING_BPP * 8; - psVpost->info.pixel_format = (LCM_USING_BPP == 4) ? RTGRAPHIC_PIXEL_FORMAT_ARGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565; - psVpost->info.pitch = psVpostLcmInst->u32DevWidth * LCM_USING_BPP; + psVpost->info.bits_per_pixel = BSP_LCD_BPP; + psVpost->info.pixel_format = (BSP_LCD_BPP == 32) ? RTGRAPHIC_PIXEL_FORMAT_ARGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565; + psVpost->info.pitch = psVpostLcmInst->u32DevWidth * (BSP_LCD_BPP / 8); psVpost->info.width = psVpostLcmInst->u32DevWidth; psVpost->info.height = psVpostLcmInst->u32DevHeight; @@ -298,7 +298,7 @@ int rt_hw_vpost_init(void) /* Note: before get pointer of frame buffer, must set display color depth first */ if (psVpost->layer == eVpost_LCD) { -#if (LCM_USING_BPP==4) +#if (BSP_LCD_BPP==32) vpostSetVASrc(VA_SRC_RGB888); #else vpostSetVASrc(VA_SRC_RGB565); @@ -310,7 +310,7 @@ int rt_hw_vpost_init(void) { vpostOSDSetWindow(0, 0, psVpost->info.width, psVpost->info.height); -#if (LCM_USING_BPP==4) +#if (BSP_LCD_BPP==32) vpostSetOSDSrc(OSD_SRC_RGB888); #else vpostSetOSDSrc(OSD_SRC_RGB565); diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c index 81c3e31372..252ca1e1ae 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c @@ -57,7 +57,7 @@ struct nu_emac_lwip_pbuf struct pbuf_custom p; // lwip pbuf EMAC_FRAME_T *psPktFrameDataBuf; // gmac descriptor EMAC_MEMMGR_T *psMemMgr; - EMAC_DESCRIPTOR_T * rx_desc; + EMAC_DESCRIPTOR_T *rx_desc; const struct memp_desc *memp_rx_pool; }; typedef struct nu_emac_lwip_pbuf *nu_emac_lwip_pbuf_t; @@ -107,11 +107,11 @@ static void nu_emac_rx_isr(int vector, void *param); /* Private variables ------------------------------------------------------------*/ #if defined(BSP_USING_EMAC0) -LWIP_MEMPOOL_DECLARE(emac0_rx, EMAC_RX_DESC_SIZE, sizeof(struct nu_emac_lwip_pbuf), "EMAC0 RX PBUF pool"); + LWIP_MEMPOOL_DECLARE(emac0_rx, EMAC_RX_DESC_SIZE, sizeof(struct nu_emac_lwip_pbuf), "EMAC0 RX PBUF pool"); #endif #if defined(BSP_USING_EMAC1) -LWIP_MEMPOOL_DECLARE(emac1_rx, EMAC_RX_DESC_SIZE, sizeof(struct nu_emac_lwip_pbuf), "EMAC1 RX PBUF pool"); + LWIP_MEMPOOL_DECLARE(emac1_rx, EMAC_RX_DESC_SIZE, sizeof(struct nu_emac_lwip_pbuf), "EMAC1 RX PBUF pool"); #endif static struct nu_emac nu_emac_arr[] = @@ -479,7 +479,7 @@ static struct pbuf *nu_emac_rx(rt_device_t dev) /* Check available data. */ if ((avaialbe_size = EMAC_GetAvailRXBufSize(&psNuEmac->memmgr, &pu8DataBuf)) > 0) { - EMAC_DESCRIPTOR_T * cur_rx = EMAC_RecvPktDoneWoRxTrigger(&psNuEmac->memmgr); + EMAC_DESCRIPTOR_T *cur_rx = EMAC_RecvPktDoneWoRxTrigger(&psNuEmac->memmgr); nu_emac_lwip_pbuf_t my_pbuf = (nu_emac_lwip_pbuf_t)memp_malloc_pool(psNuEmac->memp_rx_pool); if (my_pbuf != RT_NULL) { @@ -495,11 +495,11 @@ static struct pbuf *nu_emac_rx(rt_device_t dev) #endif //rt_kprintf("%08x, %08x, %d\n", my_pbuf, cur_rx, avaialbe_size); p = pbuf_alloced_custom(PBUF_RAW, - avaialbe_size, - PBUF_REF, - &my_pbuf->p, - pu8DataBuf, - EMAC_MAX_PKT_SIZE); + avaialbe_size, + PBUF_REF, + &my_pbuf->p, + pu8DataBuf, + EMAC_MAX_PKT_SIZE); if (p == RT_NULL) { rt_kprintf("%s : failed to alloted %08x\n", __func__, p); diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config index 6fd5ff95c5..42875bffe8 100644 --- a/bsp/nuvoton/nk-980iot/.config +++ b/bsp/nuvoton/nk-980iot/.config @@ -28,7 +28,8 @@ CONFIG_IDLE_THREAD_STACK_SIZE=2048 # # CONFIG_RT_KSERVICE_USING_STDLIB is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_ASM_MEMCPY is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,13 +57,18 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_MEMHEAP=y -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_MEMHEAP_FAST_MODE=y +# CONFIG_RT_MEMHEAP_BSET_MODE is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_MEMTRACE=y +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -74,8 +80,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_VER_NUM=0x40004 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_ARM9=y @@ -88,6 +93,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -117,6 +123,7 @@ CONFIG_FINSH_ARG_MAX=10 # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=16 CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 @@ -154,7 +161,6 @@ CONFIG_RT_USING_DFS_DEVFS=y # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=512 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 @@ -196,7 +202,8 @@ CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096 CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2 CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048 # CONFIG_RT_USING_SENSOR is not set -# CONFIG_RT_USING_TOUCH is not set +CONFIG_RT_USING_TOUCH=y +# CONFIG_RT_TOUCH_PIN_IRQ is not set CONFIG_RT_USING_HWCRYPTO=y CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto" CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16 @@ -257,17 +264,33 @@ CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -CONFIG_RT_LIBC_USING_TIME=y -# CONFIG_RT_LIBC_USING_FILEIO is not set # CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +# CONFIG_RT_USING_POSIX_DEVIO is not set +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -432,22 +455,25 @@ CONFIG_PKG_NETUTILS_TFTP=y CONFIG_PKG_NETUTILS_IPERF=y # CONFIG_PKG_NETUTILS_NETIO is not set CONFIG_PKG_NETUTILS_NTP=y -CONFIG_NETUTILS_NTP_TIMEZONE=8 +CONFIG_NTP_USING_AUTO_SYNC=y +CONFIG_NTP_AUTO_SYNC_FIRST_DELAY=30 +CONFIG_NTP_AUTO_SYNC_PERIOD=3600 CONFIG_NETUTILS_NTP_HOSTNAME="0.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME2="1.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME3="2.tw.pool.ntp.org" # CONFIG_PKG_NETUTILS_TELNET is not set # CONFIG_PKG_NETUTILS_TCPDUMP is not set -CONFIG_PKG_USING_NETUTILS_V120=y -# CONFIG_PKG_USING_NETUTILS_V110 is not set -# CONFIG_PKG_USING_NETUTILS_V100 is not set # CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set -CONFIG_PKG_NETUTILS_VER="v1.2.0" +CONFIG_PKG_USING_NETUTILS_V131=y +# CONFIG_PKG_USING_NETUTILS_V130 is not set +CONFIG_PKG_NETUTILS_VER="v1.3.1" +CONFIG_PKG_NETUTILS_VER_NUM=0x10301 # CONFIG_PKG_USING_CMUX is not set # CONFIG_PKG_USING_PPP_DEVICE is not set # CONFIG_PKG_USING_AT_DEVICE is not set # CONFIG_PKG_USING_ATSRV_SOCKET is not set # CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set # # IoT Cloud @@ -488,12 +514,19 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_AGILE_MODBUS is not set # CONFIG_PKG_USING_AGILE_FTP is not set # CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -504,10 +537,33 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_LUA is not set # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set # # multimedia packages # + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +CONFIG_PKG_USING_LVGL=y +CONFIG_PKG_LVGL_PATH="/packages/multimedia/LVGL/LVGL" +# CONFIG_PKG_USING_LVGL_EXAMPLES is not set +CONFIG_PKG_USING_LVGL_V810=y +# CONFIG_PKG_USING_LVGL_LATEST_VERSION is not set +CONFIG_PKG_LVGL_VER="v8.1.0" +CONFIG_PKG_LVGL_VER_NUM=0x08010 +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +CONFIG_PKG_USING_LV_MUSIC_DEMO=y +CONFIG_PKG_LV_MUSIC_DEMO_PATH="/packages/multimedia/LVGL/lv_music_demo" +CONFIG_PKG_USING_LV_MUSIC_DEMO_LATEST_VERSION=y +CONFIG_PKG_LV_MUSIC_DEMO_VER="latest" + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set @@ -526,6 +582,18 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_AZUREGUIX is not set # CONFIG_PKG_USING_TOUCHGFX2RTT is not set # CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -534,6 +602,7 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_EASYFLASH is not set # CONFIG_PKG_USING_EASYLOGGER is not set # CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set # CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set @@ -549,10 +618,66 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_BS8116A is not set # CONFIG_PKG_USING_GPS_RMC is not set # CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set # # system packages # + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set @@ -562,8 +687,6 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set -# CONFIG_PKG_USING_LITTLEVGL2RTT is not set -# CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set # CONFIG_PKG_USING_DFS_JFFS2 is not set @@ -591,26 +714,16 @@ CONFIG_PKG_USING_RAMDISK_LATEST_VERSION=y CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UCOSII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set -# CONFIG_PKG_USING_UC_MODBUS is not set # CONFIG_PKG_USING_PPOOL is not set # CONFIG_PKG_USING_OPENAMP is not set -# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set -# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set -# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set -# CONFIG_PKG_USING_QFPLIB_M3 is not set # CONFIG_PKG_USING_LPM is not set # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -622,7 +735,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -635,7 +747,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set -# CONFIG_PKG_USING_ROSSERIAL is not set # CONFIG_PKG_USING_AGILE_BUTTON is not set # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set @@ -679,6 +790,17 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_MFOC is not set # CONFIG_PKG_USING_TMC51XX is not set # CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set # # AI packages @@ -696,6 +818,28 @@ CONFIG_PKG_RAMDISK_VER="latest" # # miscellaneous packages # + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set CONFIG_PKG_USING_OPTPARSE=y CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" @@ -710,42 +854,22 @@ CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_CANFESTIVAL is not set # CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set # CONFIG_PKG_USING_DSTR is not set # CONFIG_PKG_USING_TINYFRAME is not set # CONFIG_PKG_USING_KENDRYTE_DEMO is not set # CONFIG_PKG_USING_DIGITALCTRL is not set # CONFIG_PKG_USING_UPACKER is not set # CONFIG_PKG_USING_UPARAM is not set - -# -# samples: kernel and components samples -# -# CONFIG_PKG_USING_KERNEL_SAMPLES is not set -# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set -# CONFIG_PKG_USING_NETWORK_SAMPLES is not set -# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_VI_LATEST_VERSION is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set - -# -# entertainment: terminal games and other interesting software packages -# -# CONFIG_PKG_USING_THREES is not set -# CONFIG_PKG_USING_2048 is not set -# CONFIG_PKG_USING_SNAKE is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_DONUT is not set -# CONFIG_PKG_USING_ACLOCK is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Nuvoton Packages Config @@ -757,7 +881,11 @@ CONFIG_NU_PKG_USING_DEMO=y # CONFIG_NU_PKG_USING_NAU88L25 is not set CONFIG_NU_PKG_USING_NAU8822=y # CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set +CONFIG_NU_PKG_USING_ILI9341=y +CONFIG_NU_PKG_USING_ILI9341_SPI=y +# CONFIG_NU_PKG_USING_ILI9341_EBI is not set +CONFIG_NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER=y +CONFIG_NU_PKG_ILI9341_HORIZONTAL=y CONFIG_NU_PKG_USING_SPINAND=y # @@ -866,7 +994,10 @@ CONFIG_BOARD_USING_USB1_HOST=y # Board extended module drivers # # CONFIG_BOARD_USING_MAX31875 is not set -# CONFIG_BOARD_USING_LCD_ILI9341 is not set +CONFIG_BOARD_USING_LCD_ILI9341=y +CONFIG_BOARD_USING_ILI9341_PIN_BACKLIGHT=103 +CONFIG_BOARD_USING_ILI9341_PIN_RESET=90 +CONFIG_BOARD_USING_ILI9341_PIN_DC=89 # CONFIG_BOARD_USING_ESP8266 is not set CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." diff --git a/bsp/nuvoton/nk-980iot/board/Kconfig b/bsp/nuvoton/nk-980iot/board/Kconfig index 98e24aeba6..06547f567b 100644 --- a/bsp/nuvoton/nk-980iot/board/Kconfig +++ b/bsp/nuvoton/nk-980iot/board/Kconfig @@ -71,9 +71,14 @@ menu "Hardware Drivers Config" config BOARD_USING_LCD_ILI9341 bool "LCD ILI9341 (over spi0)" + select RT_USING_TOUCH select NU_PKG_USING_ILI9341 select NU_PKG_USING_ILI9341_SPI + select NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER + select NU_PKG_ILI9341_HORIZONTAL select BSP_USING_SPI0 + select PKG_USING_LVGL + select PKG_USING_LV_MUSIC_DEMO default n if BOARD_USING_LCD_ILI9341 diff --git a/bsp/nuvoton/nk-980iot/rtconfig.py b/bsp/nuvoton/nk-980iot/rtconfig.py index c246b656ad..1f8263adae 100644 --- a/bsp/nuvoton/nk-980iot/rtconfig.py +++ b/bsp/nuvoton/nk-980iot/rtconfig.py @@ -79,7 +79,7 @@ elif PLATFORM == 'armcc': LFLAGS += ' --scatter ' + LINK_FILE + '.sct' if BUILD == 'debug': - CFLAGS += ' -g -O0' + CFLAGS += ' -g -O2' AFLAGS += ' -g' else: CFLAGS += ' -O2' diff --git a/bsp/nuvoton/nk-n9h30/.config b/bsp/nuvoton/nk-n9h30/.config index 3da0dba2c2..355b9e90c3 100644 --- a/bsp/nuvoton/nk-n9h30/.config +++ b/bsp/nuvoton/nk-n9h30/.config @@ -28,7 +28,8 @@ CONFIG_IDLE_THREAD_STACK_SIZE=2048 # # CONFIG_RT_KSERVICE_USING_STDLIB is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_ASM_MEMCPY is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,13 +57,18 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_MEMHEAP=y -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_MEMHEAP_FAST_MODE=y +# CONFIG_RT_MEMHEAP_BSET_MODE is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_MEMTRACE=y +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -74,8 +80,7 @@ CONFIG_RT_USING_INTERRUPT_INFO=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_VER_NUM=0x40004 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_ARM9=y @@ -88,6 +93,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -117,6 +123,7 @@ CONFIG_FINSH_ARG_MAX=10 # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=16 CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 @@ -154,7 +161,6 @@ CONFIG_RT_USING_DFS_DEVFS=y # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=512 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 @@ -240,17 +246,33 @@ CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -CONFIG_RT_LIBC_USING_TIME=y -# CONFIG_RT_LIBC_USING_FILEIO is not set # CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -462,6 +484,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set # CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages @@ -489,10 +512,11 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_LVGL=y CONFIG_PKG_LVGL_PATH="/packages/multimedia/LVGL/LVGL" -# CONFIG_PKG_LVGL_ENABLE_LOG is not set -# CONFIG_PKG_USING_LVGL_LATEST_VERSION is not set +# CONFIG_PKG_USING_LVGL_EXAMPLES is not set CONFIG_PKG_USING_LVGL_V810=y +# CONFIG_PKG_USING_LVGL_LATEST_VERSION is not set CONFIG_PKG_LVGL_VER="v8.1.0" +CONFIG_PKG_LVGL_VER_NUM=0x08010 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set CONFIG_PKG_USING_LV_MUSIC_DEMO=y CONFIG_PKG_LV_MUSIC_DEMO_PATH="/packages/multimedia/LVGL/lv_music_demo" @@ -523,6 +547,9 @@ CONFIG_PKG_LV_MUSIC_DEMO_VER="latest" # # CONFIG_PKG_USING_PAINTERENGINE is not set # CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -578,6 +605,12 @@ CONFIG_PKG_LV_MUSIC_DEMO_VER="latest" # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set + # # acceleration: Assembly language or algorithmic acceleration packages # @@ -648,10 +681,10 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set # CONFIG_PKG_USING_USB_STACK is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -725,6 +758,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_BLUETRUM_SDK is not set # CONFIG_PKG_USING_MISAKA_AT24CXX is not set # CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set @@ -766,6 +800,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set # CONFIG_PKG_USING_FASTLZ is not set @@ -787,14 +822,11 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Nuvoton Packages Config @@ -892,8 +924,11 @@ CONFIG_BSP_USING_VPOST=y # CONFIG_LCM_USING_E50A2V1 is not set # CONFIG_LCM_USING_LSA40AT9001 is not set CONFIG_LCM_USING_FW070TFT=y +# CONFIG_LCM_USING_FW043TFT is not set CONFIG_VPOST_USING_LCD_IDX=3 -CONFIG_LCM_USING_BPP=4 +CONFIG_BSP_LCD_BPP=32 +CONFIG_BSP_LCD_WIDTH=800 +CONFIG_BSP_LCD_HEIGHT=480 CONFIG_BSP_USING_VPOST_OSD=y CONFIG_BSP_USING_USBD=y CONFIG_BSP_USING_USBH=y diff --git a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h index cb73e49358..232cbc0f4f 100644 --- a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h +++ b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h @@ -11,16 +11,18 @@ #ifndef LV_CONF_H #define LV_CONF_H -#define LV_USE_GPU_N9H30_GE2D 1 +#include "rtconfig.h" -#define LV_USE_PERF_MONITOR 1 -#define LV_COLOR_DEPTH 32 +//#define LV_USE_GPU_N9H30_GE2D 1 -#define LV_HOR_RES_MAX (800) -#define LV_VER_RES_MAX (480) +#define LV_COLOR_DEPTH BSP_LCD_BPP +#define LV_HOR_RES_MAX BSP_LCD_WIDTH +#define LV_VER_RES_MAX BSP_LCD_HEIGHT #define LV_FONT_MONTSERRAT_12 1 #define LV_FONT_MONTSERRAT_16 1 +#define LV_USE_PERF_MONITOR 1 + #define LV_USE_DEMO_RTT_MUSIC 1 #define LV_DEMO_RTT_MUSIC_AUTO_PLAY 1 diff --git a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c index 193c9fddc3..266be12a31 100644 --- a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c +++ b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c @@ -9,6 +9,7 @@ */ #include #include "nu_2d.h" +#include "mmu.h" #define LOG_TAG "lvgl.disp" #define DBG_ENABLE @@ -23,11 +24,17 @@ static rt_device_t lcd_device = 0; static struct rt_device_graphic_info info; static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ +static void *buf3_next = RT_NULL; + static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { lv_disp_t *psDisp = _lv_refr_get_disp_refreshing(); void *pvDstReDraw; +#if (LV_USE_GPU_N9H30_GE2D==0) + mmu_clean_dcache((uint32_t)color_p, disp_drv->draw_buf->size * sizeof(lv_color_t)); +#endif + /* Use PANDISPLAY */ rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, color_p); @@ -44,6 +51,10 @@ static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_c ge2dSpriteBlt_Screen(0, 0, info.width, info.height, (void *)color_p); // -> Leave GE2D +#if (LV_USE_GPU_N9H30_GE2D==0) + mmu_invalidate_dcache((uint32_t)pvDstReDraw, disp_drv->draw_buf->size * sizeof(lv_color_t)); +#endif + /* WAIT_VSYNC */ rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); @@ -52,9 +63,29 @@ static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_c static void nu_flush_full_refresh(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - /* Use PANDISPLAY+WAIT_VSYNC without H/W copying. */ +#if (LV_USE_GPU_N9H30_GE2D==0) + mmu_clean_dcache((uint32_t)color_p, disp_drv->draw_buf->size * sizeof(lv_color_t)); +#endif + + /* Use PANDISPLAY without H/W copying */ rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, color_p); - rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + + if (buf3_next) + { + /* vsync-none: Use triple screen-sized buffers. */ + if (disp_drv->draw_buf->buf1 == color_p) + disp_drv->draw_buf->buf1 = buf3_next; + else + disp_drv->draw_buf->buf2 = buf3_next; + + disp_drv->draw_buf->buf_act = buf3_next; + buf3_next = color_p; + } + else + { + /* vsync-after: Use ping-pong screen-sized buffers only.*/ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + } lv_disp_flush_ready(disp_drv); } @@ -78,7 +109,6 @@ static void nu_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t lv_disp_flush_ready(disp_drv); } - static void nu_fill_cb(struct _lv_disp_drv_t *disp_drv, lv_color_t *dest_buf, lv_coord_t dest_width, const lv_area_t *fill_area, lv_color_t color) { @@ -100,6 +130,10 @@ static void nu_fill_cb(struct _lv_disp_drv_t *disp_drv, lv_color_t *dest_buf, lv } else { +#if (LV_USE_GPU_N9H30_GE2D==0) + mmu_clean_invalidated_dcache((uint32_t)dest_buf, disp_drv->draw_buf->size * sizeof(lv_color_t)); +#endif + /*Hardware filling*/ if (disp_drv->direct_mode || disp_drv->full_refresh) { @@ -134,8 +168,8 @@ void nu_perf_monitor(struct _lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px void lv_port_disp_init(void) { rt_err_t result; - void *buf_1 = RT_NULL; - void *buf_2 = RT_NULL; + void *buf1 = RT_NULL; + void *buf2 = RT_NULL; uint32_t u32FBSize; lcd_device = rt_device_find("lcd"); @@ -162,15 +196,23 @@ void lv_port_disp_init(void) /*Set the resolution of the display*/ disp_drv.hor_res = info.width; disp_drv.ver_res = info.height; - //disp_drv.full_refresh = 1; - disp_drv.direct_mode = 1; u32FBSize = info.height * info.width * (info.bits_per_pixel / 8); +#if (LV_USE_GPU_N9H30_GE2D==0) + disp_drv.full_refresh = 1; + //disp_drv.direct_mode = 1; +#endif + if (disp_drv.full_refresh || disp_drv.direct_mode) { - buf_1 = (void *)info.framebuffer; - buf_2 = (void *)((uint32_t)buf_1 + u32FBSize); - rt_kprintf("LVGL: Two screen-sized buffers(%s) - buf_1@%08x, buf_2@%08x\n", (disp_drv.full_refresh == 1) ? "full_refresh" : "direct_mode", buf_1, buf_2); +#if (LV_USE_GPU_N9H30_GE2D==1) + buf1 = (void *)info.framebuffer; // Use Non-cacheable VRAM +#else + buf1 = (void *)((uint32_t)info.framebuffer & ~0x80000000); // Use Cacheable VRAM +#endif + buf2 = (void *)((uint32_t)buf1 + u32FBSize); + buf3_next = (void *)((uint32_t)buf2 + u32FBSize); + rt_kprintf("LVGL: Use triple screen-sized buffers(%s) - buf1@%08x, buf2@%08x, buf3_next@%08x\n", (disp_drv.full_refresh == 1) ? "full_refresh" : "direct_mode", buf1, buf2, buf3_next); if (disp_drv.direct_mode) disp_drv.flush_cb = nu_flush_direct; @@ -179,16 +221,16 @@ void lv_port_disp_init(void) } else { - buf_1 = (void *)(((uint32_t)info.framebuffer) + u32FBSize); - buf_2 = (void *)((uint32_t)buf_1 + u32FBSize); - rt_kprintf("LVGL: Two screen-sized buffers - buf_1@%08x, buf_2@%08x\n", buf_1, buf_2); + buf1 = (void *)(((uint32_t)info.framebuffer) + u32FBSize); + buf2 = (void *)((uint32_t)buf1 + u32FBSize); + rt_kprintf("LVGL: Use two screen-sized buffers - buf1@%08x, buf2@%08x\n", buf1, buf2); rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, info.framebuffer); disp_drv.flush_cb = nu_flush; } /*Initialize `disp_buf` with the buffer(s).*/ - lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, info.width * info.height); + lv_disp_draw_buf_init(&disp_buf, buf1, buf2, info.width * info.height); result = rt_device_open(lcd_device, 0); if (result != RT_EOK) diff --git a/bsp/nuvoton/nk-n9h30/applications/mnt.c b/bsp/nuvoton/nk-n9h30/applications/mnt.c index 23c44a7282..03e7481242 100644 --- a/bsp/nuvoton/nk-n9h30/applications/mnt.c +++ b/bsp/nuvoton/nk-n9h30/applications/mnt.c @@ -238,6 +238,6 @@ exit_mnt_init_spiflash0: return 0; } -INIT_ENV_EXPORT(mnt_init_spiflash0); +INIT_APP_EXPORT(mnt_init_spiflash0); #endif diff --git a/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c b/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c index d6038a4a2e..719df0d252 100644 --- a/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c +++ b/bsp/nuvoton/nk-n9h30/board/nu_pin_init.c @@ -115,7 +115,7 @@ static void nu_pin_vpost_init(void) outpw(REG_SYS_GPA_MFPL, 0x22222222); /* PA[8, 15] */ outpw(REG_SYS_GPA_MFPH, 0x22222222); -#if (LCM_USING_BPP==4) +#if (BSP_LCD_BPP==32) /* PD[8, 15 ] */ outpw(REG_SYS_GPD_MFPH, 0x22222222); #endif diff --git a/bsp/nuvoton/nk-n9h30/rtconfig.py b/bsp/nuvoton/nk-n9h30/rtconfig.py index f99f6be692..79a4da1d49 100644 --- a/bsp/nuvoton/nk-n9h30/rtconfig.py +++ b/bsp/nuvoton/nk-n9h30/rtconfig.py @@ -53,10 +53,10 @@ if PLATFORM == 'gcc': LPATH = '' if BUILD == 'debug': - CFLAGS += ' -O0 -gdwarf-2' + CFLAGS += ' -O2 -gdwarf-2' AFLAGS += ' -gdwarf-2' else: - CFLAGS += ' -O0' + CFLAGS += ' -O2' POST_ACTION = OBJCPY + ' -O binary $TARGET ' + TARGET_NAME + '\n' POST_ACTION += SIZE + ' $TARGET\n' diff --git a/bsp/nuvoton/nk-rtu980/.config b/bsp/nuvoton/nk-rtu980/.config index b78fa15e9f..f29e87bfab 100644 --- a/bsp/nuvoton/nk-rtu980/.config +++ b/bsp/nuvoton/nk-rtu980/.config @@ -28,7 +28,8 @@ CONFIG_IDLE_THREAD_STACK_SIZE=2048 # # CONFIG_RT_KSERVICE_USING_STDLIB is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_ASM_MEMCPY is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,13 +57,18 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_MEMHEAP=y -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_MEMHEAP_FAST_MODE=y +# CONFIG_RT_MEMHEAP_BSET_MODE is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_MEMTRACE=y +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -74,8 +80,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_VER_NUM=0x40004 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_ARM9=y @@ -88,6 +93,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -117,6 +123,7 @@ CONFIG_FINSH_ARG_MAX=10 # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=16 CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 @@ -154,7 +161,6 @@ CONFIG_RT_USING_DFS_DEVFS=y # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=512 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 @@ -256,17 +262,33 @@ CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -CONFIG_RT_LIBC_USING_TIME=y -# CONFIG_RT_LIBC_USING_FILEIO is not set # CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -431,22 +453,25 @@ CONFIG_PKG_NETUTILS_TFTP=y CONFIG_PKG_NETUTILS_IPERF=y # CONFIG_PKG_NETUTILS_NETIO is not set CONFIG_PKG_NETUTILS_NTP=y -CONFIG_NETUTILS_NTP_TIMEZONE=8 +CONFIG_NTP_USING_AUTO_SYNC=y +CONFIG_NTP_AUTO_SYNC_FIRST_DELAY=30 +CONFIG_NTP_AUTO_SYNC_PERIOD=3600 CONFIG_NETUTILS_NTP_HOSTNAME="0.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME2="1.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME3="2.tw.pool.ntp.org" # CONFIG_PKG_NETUTILS_TELNET is not set # CONFIG_PKG_NETUTILS_TCPDUMP is not set -CONFIG_PKG_USING_NETUTILS_V120=y -# CONFIG_PKG_USING_NETUTILS_V110 is not set -# CONFIG_PKG_USING_NETUTILS_V100 is not set # CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set -CONFIG_PKG_NETUTILS_VER="v1.2.0" +CONFIG_PKG_USING_NETUTILS_V131=y +# CONFIG_PKG_USING_NETUTILS_V130 is not set +CONFIG_PKG_NETUTILS_VER="v1.3.1" +CONFIG_PKG_NETUTILS_VER_NUM=0x10301 # CONFIG_PKG_USING_CMUX is not set # CONFIG_PKG_USING_PPP_DEVICE is not set # CONFIG_PKG_USING_AT_DEVICE is not set # CONFIG_PKG_USING_ATSRV_SOCKET is not set # CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set # # IoT Cloud @@ -487,12 +512,19 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_AGILE_MODBUS is not set # CONFIG_PKG_USING_AGILE_FTP is not set # CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -503,10 +535,24 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_LUA is not set # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set # # multimedia packages # + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set @@ -517,6 +563,18 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_AZUREGUIX is not set # CONFIG_PKG_USING_TOUCHGFX2RTT is not set # CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -525,6 +583,7 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_EASYFLASH is not set # CONFIG_PKG_USING_EASYLOGGER is not set # CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set # CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set @@ -540,10 +599,66 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_BS8116A is not set # CONFIG_PKG_USING_GPS_RMC is not set # CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set # # system packages # + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set @@ -567,8 +682,6 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set -# CONFIG_PKG_USING_LITTLEVGL2RTT is not set -# CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set # CONFIG_PKG_USING_DFS_JFFS2 is not set @@ -587,26 +700,16 @@ CONFIG_PKG_USING_RAMDISK_LATEST_VERSION=y CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UCOSII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set -# CONFIG_PKG_USING_UC_MODBUS is not set # CONFIG_PKG_USING_PPOOL is not set # CONFIG_PKG_USING_OPENAMP is not set -# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set -# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set -# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set -# CONFIG_PKG_USING_QFPLIB_M3 is not set # CONFIG_PKG_USING_LPM is not set # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -618,7 +721,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -631,7 +733,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set -# CONFIG_PKG_USING_ROSSERIAL is not set # CONFIG_PKG_USING_AGILE_BUTTON is not set # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set @@ -675,6 +776,17 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_MFOC is not set # CONFIG_PKG_USING_TMC51XX is not set # CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set # # AI packages @@ -692,6 +804,28 @@ CONFIG_PKG_RAMDISK_VER="latest" # # miscellaneous packages # + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set CONFIG_PKG_USING_OPTPARSE=y CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" @@ -706,42 +840,22 @@ CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_CANFESTIVAL is not set # CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set # CONFIG_PKG_USING_DSTR is not set # CONFIG_PKG_USING_TINYFRAME is not set # CONFIG_PKG_USING_KENDRYTE_DEMO is not set # CONFIG_PKG_USING_DIGITALCTRL is not set # CONFIG_PKG_USING_UPACKER is not set # CONFIG_PKG_USING_UPARAM is not set - -# -# samples: kernel and components samples -# -# CONFIG_PKG_USING_KERNEL_SAMPLES is not set -# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set -# CONFIG_PKG_USING_NETWORK_SAMPLES is not set -# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_VI_LATEST_VERSION is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set - -# -# entertainment: terminal games and other interesting software packages -# -# CONFIG_PKG_USING_THREES is not set -# CONFIG_PKG_USING_2048 is not set -# CONFIG_PKG_USING_SNAKE is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_DONUT is not set -# CONFIG_PKG_USING_ACLOCK is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Nuvoton Packages Config diff --git a/bsp/nuvoton/numaker-iot-m487/.config b/bsp/nuvoton/numaker-iot-m487/.config index af27ea8b60..3d2feddd4b 100644 --- a/bsp/nuvoton/numaker-iot-m487/.config +++ b/bsp/nuvoton/numaker-iot-m487/.config @@ -28,7 +28,8 @@ CONFIG_IDLE_THREAD_STACK_SIZE=1024 # # CONFIG_RT_KSERVICE_USING_STDLIB is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_ASM_MEMCPY is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,12 +57,16 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -# CONFIG_RT_USING_MEMHEAP is not set -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -73,8 +78,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_VER_NUM=0x40004 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_M=y @@ -88,6 +92,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -117,6 +122,7 @@ CONFIG_FINSH_ARG_MAX=10 # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=8 CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 @@ -153,7 +159,6 @@ CONFIG_RT_USING_DFS_DEVFS=y # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=64 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 @@ -178,6 +183,11 @@ CONFIG_RT_USING_PWM=y # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set CONFIG_RT_USING_PM=y +CONFIG_PM_TICKLESS_THRESHOLD_TIME=2 +# CONFIG_PM_USING_CUSTOM_CONFIG is not set +# CONFIG_PM_ENABLE_DEBUG is not set +# CONFIG_PM_ENABLE_SUSPEND_SLEEP_MODE is not set +# CONFIG_PM_ENABLE_THRESHOLD_SLEEP_MODE is not set CONFIG_RT_USING_RTC=y # CONFIG_RT_USING_ALARM is not set # CONFIG_RT_USING_SOFT_RTC is not set @@ -266,17 +276,33 @@ CONFIG_RT_USB_DEVICE_HID_MOUSE=y # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -CONFIG_RT_LIBC_USING_TIME=y -# CONFIG_RT_LIBC_USING_FILEIO is not set # CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -390,9 +416,6 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_COAP is not set # CONFIG_PKG_USING_NOPOLL is not set # CONFIG_PKG_USING_NETUTILS is not set -# CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set -# CONFIG_PKG_USING_NETUTILS_V131 is not set -# CONFIG_PKG_USING_NETUTILS_V130 is not set # CONFIG_PKG_USING_CMUX is not set # CONFIG_PKG_USING_PPP_DEVICE is not set CONFIG_PKG_USING_AT_DEVICE=y @@ -477,12 +500,13 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set # CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -504,6 +528,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # # CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set # # u8g2: a monochrome graphic library @@ -514,8 +539,6 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set -# CONFIG_PKG_USING_WAVPLAYER_V020 is not set -# CONFIG_PKG_USING_WAVPLAYER_LATEST_VERSION is not set # CONFIG_PKG_USING_TJPGD is not set # CONFIG_PKG_USING_PDFGEN is not set # CONFIG_PKG_USING_HELIX is not set @@ -531,6 +554,9 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # # CONFIG_PKG_USING_PAINTERENGINE is not set # CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -580,15 +606,21 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # # -# rt_kprintf: enhanced rt_kprintf packages +# enhanced kernel services # +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set + # # acceleration: Assembly language or algorithmic acceleration packages # -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set @@ -597,7 +629,6 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_5_AUX is not set # CONFIG_PKG_USING_CMSIS_RTOS2 is not set # @@ -609,6 +640,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set @@ -651,10 +683,10 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set # CONFIG_PKG_USING_USB_STACK is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -728,6 +760,7 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_BLUETRUM_SDK is not set # CONFIG_PKG_USING_MISAKA_AT24CXX is not set # CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set @@ -769,9 +802,9 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set -# CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION is not set # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set # CONFIG_PKG_USING_QUICKLZ is not set @@ -791,14 +824,11 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Nuvoton Packages Config diff --git a/bsp/nuvoton/numaker-m2354/.config b/bsp/nuvoton/numaker-m2354/.config index 9e3dae1da1..523f845231 100644 --- a/bsp/nuvoton/numaker-m2354/.config +++ b/bsp/nuvoton/numaker-m2354/.config @@ -28,7 +28,8 @@ CONFIG_IDLE_THREAD_STACK_SIZE=2048 # # CONFIG_RT_KSERVICE_USING_STDLIB is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_ASM_MEMCPY is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,12 +57,16 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -# CONFIG_RT_USING_MEMHEAP is not set -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -73,8 +78,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_VER_NUM=0x40004 +CONFIG_RT_VER_NUM=0x40100 # CONFIG_RT_USING_CPU_FFS is not set # CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set @@ -85,6 +89,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -114,6 +119,7 @@ CONFIG_FINSH_ARG_MAX=10 # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=4 CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 @@ -150,7 +156,6 @@ CONFIG_RT_USING_DFS_DEVFS=y # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=64 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 @@ -175,6 +180,11 @@ CONFIG_RT_USING_PWM=y # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set CONFIG_RT_USING_PM=y +CONFIG_PM_TICKLESS_THRESHOLD_TIME=2 +# CONFIG_PM_USING_CUSTOM_CONFIG is not set +# CONFIG_PM_ENABLE_DEBUG is not set +# CONFIG_PM_ENABLE_SUSPEND_SLEEP_MODE is not set +# CONFIG_PM_ENABLE_THRESHOLD_SLEEP_MODE is not set CONFIG_RT_USING_RTC=y # CONFIG_RT_USING_ALARM is not set # CONFIG_RT_USING_SOFT_RTC is not set @@ -263,17 +273,33 @@ CONFIG_RT_USB_DEVICE_HID_MOUSE=y # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -CONFIG_RT_LIBC_USING_TIME=y -# CONFIG_RT_LIBC_USING_FILEIO is not set # CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -386,9 +412,6 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_COAP is not set # CONFIG_PKG_USING_NOPOLL is not set # CONFIG_PKG_USING_NETUTILS is not set -# CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set -# CONFIG_PKG_USING_NETUTILS_V131 is not set -# CONFIG_PKG_USING_NETUTILS_V130 is not set # CONFIG_PKG_USING_CMUX is not set # CONFIG_PKG_USING_PPP_DEVICE is not set CONFIG_PKG_USING_AT_DEVICE=y @@ -473,12 +496,13 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set # CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -500,6 +524,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # # CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set # # u8g2: a monochrome graphic library @@ -525,6 +550,9 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # # CONFIG_PKG_USING_PAINTERENGINE is not set # CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -574,15 +602,21 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # # -# rt_kprintf: enhanced rt_kprintf packages +# enhanced kernel services # +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set + # # acceleration: Assembly language or algorithmic acceleration packages # -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set @@ -591,7 +625,6 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_5_AUX is not set # CONFIG_PKG_USING_CMSIS_RTOS2 is not set # @@ -603,6 +636,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set @@ -644,10 +678,10 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set # CONFIG_PKG_USING_USB_STACK is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -721,6 +755,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_BLUETRUM_SDK is not set # CONFIG_PKG_USING_MISAKA_AT24CXX is not set # CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set @@ -762,6 +797,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set # CONFIG_PKG_USING_FASTLZ is not set @@ -783,14 +819,11 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Nuvoton Packages Config diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index a76b5f8361..71c36043b5 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -28,7 +28,8 @@ CONFIG_IDLE_THREAD_STACK_SIZE=1024 # # CONFIG_RT_KSERVICE_USING_STDLIB is not set # CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_ASM_MEMCPY is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -56,12 +57,16 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -# CONFIG_RT_USING_MEMHEAP is not set -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -73,8 +78,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_VER_NUM=0x40004 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_M=y @@ -88,6 +92,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -117,6 +122,7 @@ CONFIG_FINSH_ARG_MAX=10 # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=8 CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 @@ -154,7 +160,6 @@ CONFIG_RT_USING_DFS_DEVFS=y # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=64 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 @@ -179,6 +184,11 @@ CONFIG_RT_USING_PWM=y # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set CONFIG_RT_USING_PM=y +CONFIG_PM_TICKLESS_THRESHOLD_TIME=2 +# CONFIG_PM_USING_CUSTOM_CONFIG is not set +# CONFIG_PM_ENABLE_DEBUG is not set +# CONFIG_PM_ENABLE_SUSPEND_SLEEP_MODE is not set +# CONFIG_PM_ENABLE_THRESHOLD_SLEEP_MODE is not set CONFIG_RT_USING_RTC=y # CONFIG_RT_USING_ALARM is not set # CONFIG_RT_USING_SOFT_RTC is not set @@ -268,17 +278,33 @@ CONFIG_RT_USB_DEVICE_HID_MOUSE=y # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -CONFIG_RT_LIBC_USING_TIME=y -# CONFIG_RT_LIBC_USING_FILEIO is not set # CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +# CONFIG_RT_USING_POSIX_POLL is not set +# CONFIG_RT_USING_POSIX_SELECT is not set # CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set # CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -491,12 +517,13 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set # CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -518,6 +545,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # # CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set # # u8g2: a monochrome graphic library @@ -528,8 +556,6 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set -# CONFIG_PKG_USING_WAVPLAYER_V020 is not set -# CONFIG_PKG_USING_WAVPLAYER_LATEST_VERSION is not set # CONFIG_PKG_USING_TJPGD is not set # CONFIG_PKG_USING_PDFGEN is not set # CONFIG_PKG_USING_HELIX is not set @@ -545,6 +571,9 @@ CONFIG_UTEST_THR_PRIORITY=20 # # CONFIG_PKG_USING_PAINTERENGINE is not set # CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set # # tools packages @@ -594,15 +623,21 @@ CONFIG_UTEST_THR_PRIORITY=20 # # -# rt_kprintf: enhanced rt_kprintf packages +# enhanced kernel services # +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set + # # acceleration: Assembly language or algorithmic acceleration packages # -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set @@ -611,7 +646,6 @@ CONFIG_UTEST_THR_PRIORITY=20 # CMSIS: ARM Cortex-M Microcontroller Software Interface Standard # # CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_5_AUX is not set # CONFIG_PKG_USING_CMSIS_RTOS2 is not set # @@ -623,6 +657,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set @@ -665,10 +700,10 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set # CONFIG_PKG_USING_USB_STACK is not set +# CONFIG_PKG_USING_LUATOS_SOC is not set # # peripheral libraries and drivers @@ -742,6 +777,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_BLUETRUM_SDK is not set # CONFIG_PKG_USING_MISAKA_AT24CXX is not set # CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set # CONFIG_PKG_USING_MB85RS16 is not set @@ -783,9 +819,9 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set -# CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION is not set # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set # CONFIG_PKG_USING_QUICKLZ is not set @@ -805,14 +841,11 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set # # Nuvoton Packages Config From 0547395eb59549af1857751665020f90cc0889eb Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 10 Jan 2022 14:42:31 +0800 Subject: [PATCH 05/65] [Nuvoton] Update drivers. 1. Fix open-control order issue in CAN driver. 2. [N9H30] Improve N9H30 I2C busy-wait implementation. 3. [N9H30] Support 1024x600x32b LCD panel. 4. Move nu_packages menu into sub-menu of board. --- .../libraries/m2354/rtt_port/drv_can.c | 435 ++-- .../Device/Nuvoton/M480/Include/can_reg.h | 8 +- bsp/nuvoton/libraries/m480/rtt_port/drv_can.c | 451 ++-- .../libraries/n9h30/Driver/Include/nu_can.h | 4 +- .../libraries/n9h30/Driver/Include/nu_lcd.h | 16 +- .../libraries/n9h30/Driver/Source/nu_lcd.c | 75 +- bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig | 7 + .../libraries/n9h30/rtt_port/drv_adc_touch.c | 28 +- .../libraries/n9h30/rtt_port/drv_can.c | 375 ++-- .../libraries/n9h30/rtt_port/drv_i2c.c | 108 +- .../libraries/n9h30/rtt_port/drv_vpost.c | 21 + .../libraries/nuc980/Driver/Include/nu_can.h | 4 +- .../libraries/nuc980/Driver/Source/nu_emac.c | 4 +- .../libraries/nuc980/rtt_port/drv_can.c | 375 ++-- bsp/nuvoton/nk-980iot/.config | 2 + bsp/nuvoton/nk-980iot/Kconfig | 6 - bsp/nuvoton/nk-980iot/board/Kconfig | 1 + bsp/nuvoton/nk-980iot/project.uvproj | 1877 ---------------- bsp/nuvoton/nk-980iot/project.uvprojx | 1869 ---------------- bsp/nuvoton/nk-980iot/rtconfig.h | 459 ---- bsp/nuvoton/nk-n9h30/.config | 36 +- bsp/nuvoton/nk-n9h30/Kconfig | 6 - .../nk-n9h30/applications/lvgl/lv_port_disp.c | 61 +- bsp/nuvoton/nk-n9h30/board/Kconfig | 53 +- bsp/nuvoton/nk-n9h30/board/board_dev.c | 61 +- bsp/nuvoton/nk-n9h30/project.uvproj | 1791 --------------- bsp/nuvoton/nk-n9h30/project.uvprojx | 1783 --------------- bsp/nuvoton/nk-n9h30/rtconfig.h | 422 ---- bsp/nuvoton/nk-rtu980/.config | 2 + bsp/nuvoton/nk-rtu980/Kconfig | 6 - bsp/nuvoton/nk-rtu980/board/Kconfig | 1 + bsp/nuvoton/nk-rtu980/project.uvproj | 1774 --------------- bsp/nuvoton/nk-rtu980/project.uvprojx | 1766 --------------- bsp/nuvoton/nk-rtu980/rtconfig.h | 431 ---- bsp/nuvoton/numaker-iot-m487/.config | 2 + bsp/nuvoton/numaker-iot-m487/Kconfig | 6 - bsp/nuvoton/numaker-iot-m487/board/Kconfig | 1 + bsp/nuvoton/numaker-iot-m487/project.uvproj | 1814 --------------- bsp/nuvoton/numaker-iot-m487/project.uvprojx | 1809 --------------- bsp/nuvoton/numaker-iot-m487/rtconfig.h | 400 ---- bsp/nuvoton/numaker-m032ki/.config | 2 + bsp/nuvoton/numaker-m032ki/Kconfig | 6 - bsp/nuvoton/numaker-m032ki/board/Kconfig | 1 + bsp/nuvoton/numaker-m032ki/project.uvprojx | 1228 ---------- bsp/nuvoton/numaker-m032ki/rtconfig.h | 286 --- bsp/nuvoton/numaker-m2354/.config | 2 + bsp/nuvoton/numaker-m2354/Kconfig | 8 +- bsp/nuvoton/numaker-m2354/board/Kconfig | 2 + bsp/nuvoton/numaker-m2354/project.uvprojx | 1768 --------------- bsp/nuvoton/numaker-m2354/rtconfig.h | 383 ---- bsp/nuvoton/numaker-pfm-m487/.config | 2 + bsp/nuvoton/numaker-pfm-m487/Kconfig | 6 - bsp/nuvoton/numaker-pfm-m487/board/Kconfig | 2 + bsp/nuvoton/numaker-pfm-m487/project.uvproj | 1966 ----------------- bsp/nuvoton/numaker-pfm-m487/project.uvprojx | 1961 ---------------- bsp/nuvoton/numaker-pfm-m487/rtconfig.h | 413 ---- 56 files changed, 1258 insertions(+), 25128 deletions(-) delete mode 100644 bsp/nuvoton/nk-980iot/project.uvproj delete mode 100644 bsp/nuvoton/nk-980iot/project.uvprojx delete mode 100644 bsp/nuvoton/nk-980iot/rtconfig.h delete mode 100644 bsp/nuvoton/nk-n9h30/project.uvproj delete mode 100644 bsp/nuvoton/nk-n9h30/project.uvprojx delete mode 100644 bsp/nuvoton/nk-n9h30/rtconfig.h delete mode 100644 bsp/nuvoton/nk-rtu980/project.uvproj delete mode 100644 bsp/nuvoton/nk-rtu980/project.uvprojx delete mode 100644 bsp/nuvoton/nk-rtu980/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-iot-m487/project.uvproj delete mode 100644 bsp/nuvoton/numaker-iot-m487/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-iot-m487/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-m032ki/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-m032ki/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-m2354/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-m2354/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-pfm-m487/project.uvproj delete mode 100644 bsp/nuvoton/numaker-pfm-m487/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-pfm-m487/rtconfig.h diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c index 614705fcc5..511fb592a2 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c @@ -7,6 +7,7 @@ * Change Logs: * Date Author Notes * 2020-6-22 ChingI First version +* 2022-1-8 Wayne Fix IE issue * ******************************************************************************/ @@ -42,7 +43,7 @@ enum #if defined(BSP_USING_CAN0) CAN0_IDX, #endif - CAN_CNT, + CAN_CNT }; /* Private Typedef --------------------------------------------------------------*/ @@ -50,9 +51,10 @@ struct nu_can { struct rt_can_device dev; char *name; - CAN_T *can_base; - uint32_t can_rst; - IRQn_Type can_irq_n; + CAN_T *base; + IRQn_Type irqn; + uint32_t rstidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -68,12 +70,11 @@ static struct nu_can nu_can_arr[] = #if defined(BSP_USING_CAN0) { .name = "can0", - .can_base = CAN0, - .can_rst = CAN0_RST, - .can_irq_n = CAN0_IRQn, + .base = CAN0, + .rstidx = CAN0_RST, + .irqn = CAN0_IRQn, }, #endif - {0} }; /* struct nu_can */ /* Public functions ------------------------------------------------------------*/ @@ -106,266 +107,271 @@ void CAN0_IRQHandler(void) /* Private Variables ------------------------------------------------------------*/ -static void nu_can_isr(nu_can_t can) +static void nu_can_isr(nu_can_t psNuCAN) { - uint32_t u32IIDRstatus; /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(can_base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ /**************************/ - if (can_base->STATUS & CAN_STATUS_TXOK_Msk) + if (base->STATUS & CAN_STATUS_TXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ + base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif - //rt_kprintf("[%s]TX OK INT\n", can->name) ; } - if (can_base->STATUS & CAN_STATUS_RXOK_Msk) + if (base->STATUS & CAN_STATUS_RXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ + base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif - //rt_kprintf("[%s]RX OK INT\n", can->name) ; } /**************************/ /* Error Status interrupt */ /**************************/ - if (can_base->STATUS & CAN_STATUS_EWARN_Msk) + if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("[%s]EWARN INT\n", can->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } - if (can_base->STATUS & CAN_STATUS_BOFF_Msk) + if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("[%s]BUSOFF INT\n", can->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - can_base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - can_base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (can_base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } + + if (base->STATUS & CAN_STATUS_LEC_Msk) + { + rt_kprintf("[%s] Last Error Code %03x\n", psNuCAN->name, base->STATUS & CAN_STATUS_LEC_Msk) ; + } + } #ifdef RT_CAN_USING_HDR /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } - CAN_CLR_INT_PENDING_BIT(can_base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ + CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + NVIC_EnableIRQ(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + NVIC_DisableIRQ(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { + nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); + CAN_T *base = psNuCAN->base; /* Reset this module */ - SYS_ResetModule(((nu_can_t)can)->can_rst); + SYS_ResetModule(psNuCAN->rstidx); - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(can_base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); - + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR - CAN_LeaveTestMode(can_base); + CAN_LeaveTestMode(base); #else - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk); #endif break; case RT_CAN_MODE_LISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); break; case RT_CAN_MODE_LOOPBACK: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); break; case RT_CAN_MODE_LOOPBACKANLISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); break; default: rt_kprintf("Unsupported Operating mode"); goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; exit_nu_can_configure: - CAN_Close(can_base); + CAN_Close(base); return -(RT_ERROR); } static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Status Change Interrupt */ - CAN_DisableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Error Interrupt */ - CAN_DisableInt(can_base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } } else - { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -375,20 +381,29 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) return nu_can_configure(can, &can->config); } break; + case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = can_base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(can_base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(can_base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; + default: return -(RT_EINVAL); @@ -400,61 +415,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; + + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(can_base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(can_base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -466,32 +511,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -506,13 +532,12 @@ static int rt_hw_can_init(void) for (i = (CAN_START + 1); i < CAN_CNT; i++) { - - nu_can_arr[i].dev.ops = &nu_can_ops; nu_can_arr[i].dev.config = nu_can_default_config; #ifdef RT_CAN_USING_HDR nu_can_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ; #endif + /* Register can device */ ret = rt_hw_can_register(&nu_can_arr[i].dev, nu_can_arr[i].name, &nu_can_ops, NULL); RT_ASSERT(ret == RT_EOK); } diff --git a/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h b/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h index 86340d99d8..b0152f8011 100644 --- a/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h +++ b/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h @@ -10,7 +10,7 @@ #define __CAN_REG_H__ #if defined ( __CC_ARM ) -#pragma anon_unions + #pragma anon_unions #endif /** @@ -586,8 +586,8 @@ typedef struct #define CAN_BTIME_TSEG2_Pos (12) /*!< CAN_T::BTIME: TSeg2 Position */ #define CAN_BTIME_TSEG2_Msk (0x7ul << CAN_BTIME_TSEG2_Pos) /*!< CAN_T::BTIME: TSeg2 Mask */ -#define CAN_IIDR_IntId_Pos (0) /*!< CAN_T::IIDR: IntId Position */ -#define CAN_IIDR_IntId_Msk (0xfffful << CAN_IIDR_IntId_Pos) /*!< CAN_T::IIDR: IntId Mask */ +#define CAN_IIDR_INTID_Pos (0) /*!< CAN_T::IIDR: IntId Position */ +#define CAN_IIDR_INTID_Msk (0xfffful << CAN_IIDR_INTID_Pos) /*!< CAN_T::IIDR: IntId Mask */ #define CAN_TEST_BASIC_Pos (2) /*!< CAN_T::TEST: Basic Position */ #define CAN_TEST_BASIC_Msk (0x1ul << CAN_TEST_BASIC_Pos) /*!< CAN_T::TEST: Basic Mask */ @@ -753,7 +753,7 @@ typedef struct /**@}*/ /* end of REGISTER group */ #if defined ( __CC_ARM ) -#pragma no_anon_unions + #pragma no_anon_unions #endif #endif /* __CAN_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c index a667e34979..14926076c3 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c @@ -1,12 +1,13 @@ /**************************************************************************//** * -* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes -* 2020-2-07 ChingI First version +* 2020-6-22 ChingI First version +* 2022-1-8 Wayne Fix IE issue * ******************************************************************************/ @@ -56,9 +57,10 @@ struct nu_can { struct rt_can_device dev; char *name; - CAN_T *can_base; - uint32_t can_rst; - IRQn_Type can_irq_n; + CAN_T *base; + IRQn_Type irqn; + uint32_t rstidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -74,29 +76,27 @@ static struct nu_can nu_can_arr[] = #if defined(BSP_USING_CAN0) { .name = "can0", - .can_base = CAN0, - .can_rst = CAN0_RST, - .can_irq_n = CAN0_IRQn, + .base = CAN0, + .rstidx = CAN0_RST, + .irqn = CAN0_IRQn, }, #endif #if defined(BSP_USING_CAN1) { .name = "can1", - .can_base = CAN1, - .can_rst = CAN1_RST, - .can_irq_n = CAN1_IRQn, + .base = CAN1, + .rstidx = CAN1_RST, + .irqn = CAN1_IRQn, }, #endif - #if defined(BSP_USING_CAN2) { .name = "can2", - .can_base = CAN2, - .can_rst = CAN2_RST, - .can_irq_n = CAN2_IRQn, + .base = CAN2, + .rstidx = CAN2_RST, + .irqn = CAN2_IRQn, }, #endif - {0} }; /* struct nu_can */ /* Public functions ------------------------------------------------------------*/ @@ -158,267 +158,271 @@ void CAN2_IRQHandler(void) /* Private Variables ------------------------------------------------------------*/ - -static void nu_can_isr(nu_can_t can) +static void nu_can_isr(nu_can_t psNuCAN) { - uint32_t u32IIDRstatus; /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(can_base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ /**************************/ - if (can_base->STATUS & CAN_STATUS_TXOK_Msk) + if (base->STATUS & CAN_STATUS_TXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ + base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif - //rt_kprintf("[%s]TX OK INT\n", can->name) ; } - if (can_base->STATUS & CAN_STATUS_RXOK_Msk) + if (base->STATUS & CAN_STATUS_RXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ + base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif - //rt_kprintf("[%s]RX OK INT\n", can->name) ; } /**************************/ /* Error Status interrupt */ /**************************/ - if (can_base->STATUS & CAN_STATUS_EWARN_Msk) + if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("[%s]EWARN INT\n", can->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } - if (can_base->STATUS & CAN_STATUS_BOFF_Msk) + if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("[%s]BUSOFF INT\n", can->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - can_base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - can_base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (can_base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } + + if (base->STATUS & CAN_STATUS_LEC_Msk) + { + rt_kprintf("[%s] Last Error Code %03x\n", psNuCAN->name, base->STATUS & CAN_STATUS_LEC_Msk) ; + } + } #ifdef RT_CAN_USING_HDR /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } - CAN_CLR_INT_PENDING_BIT(can_base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ + CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + NVIC_EnableIRQ(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + NVIC_DisableIRQ(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { + nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); + CAN_T *base = psNuCAN->base; /* Reset this module */ - SYS_ResetModule(((nu_can_t)can)->can_rst); + SYS_ResetModule(psNuCAN->rstidx); - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(can_base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); - + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR - CAN_LeaveTestMode(can_base); + CAN_LeaveTestMode(base); #else - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk); #endif break; case RT_CAN_MODE_LISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); break; case RT_CAN_MODE_LOOPBACK: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); break; case RT_CAN_MODE_LOOPBACKANLISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); break; default: rt_kprintf("Unsupported Operating mode"); goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; exit_nu_can_configure: - CAN_Close(can_base); + CAN_Close(base); return -(RT_ERROR); } static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Status Change Interrupt */ - CAN_DisableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Error Interrupt */ - CAN_DisableInt(can_base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } } else - { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -428,20 +432,29 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) return nu_can_configure(can, &can->config); } break; + case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = can_base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(can_base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(can_base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; + default: return -(RT_EINVAL); @@ -453,61 +466,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; + + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(can_base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(can_base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -519,32 +562,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -559,13 +583,12 @@ static int rt_hw_can_init(void) for (i = (CAN_START + 1); i < CAN_CNT; i++) { - - nu_can_arr[i].dev.ops = &nu_can_ops; nu_can_arr[i].dev.config = nu_can_default_config; #ifdef RT_CAN_USING_HDR nu_can_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ; #endif + /* Register can device */ ret = rt_hw_can_register(&nu_can_arr[i].dev, nu_can_arr[i].name, &nu_can_ops, NULL); RT_ASSERT(ret == RT_EOK); } diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h index b13064996d..8eb3a1463c 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h @@ -151,8 +151,8 @@ typedef struct #define CAN_BTIME_TSEG2_Pos (12) /*!< CAN_T::BTIME: TSeg2 Position */ #define CAN_BTIME_TSEG2_Msk (0x7ul << CAN_BTIME_TSEG2_Pos) /*!< CAN_T::BTIME: TSeg2 Mask */ -#define CAN_IIDR_IntId_Pos (0) /*!< CAN_T::IIDR: IntId Position */ -#define CAN_IIDR_IntId_Msk (0xfffful << CAN_IIDR_IntId_Pos) /*!< CAN_T::IIDR: IntId Mask */ +#define CAN_IIDR_INTID_Pos (0) /*!< CAN_T::IIDR: IntId Position */ +#define CAN_IIDR_INTID_Msk (0xfffful << CAN_IIDR_INTID_Pos) /*!< CAN_T::IIDR: IntId Mask */ #define CAN_TEST_BASIC_Pos (2) /*!< CAN_T::TEST: Basic Position */ #define CAN_TEST_BASIC_Msk (0x1ul << CAN_TEST_BASIC_Pos) /*!< CAN_T::TEST: Basic Mask */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h index bf05c3f9a9..69b7c747a8 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h @@ -171,11 +171,17 @@ typedef struct uint32_t *pFrameBuffer; /*!< User input, The address of OSD source image */ } OSDFORMATEX; -#define DIS_PANEL_E50A2V1 0 -#define DIS_PANEL_ILI9341_MPU80 1 -#define DIS_LSA40AT9001 2 -#define DIS_PANEL_FW070TFT 3 -#define DIS_PANEL_FW043TFT 4 +enum DIS_PANEL +{ + DIS_PANEL_E50A2V1 = 0, + DIS_PANEL_ILI9341_MPU80, + DIS_LSA40AT9001, + DIS_PANEL_FW070TFT, + DIS_PANEL_FW043TFT, + DIS_PANEL_FW070TFT_WSVGA, + DIS_PANEL_CNT +}; + typedef struct { uint32_t u32DevWidth; /*!< Panel width */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c index d71d110096..82887e427f 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c @@ -168,9 +168,82 @@ static VPOST_T DEF_FW043TFT = } }; +#define FW070TFT_WSVGA_WIDTH 1024 /*!< XRES */ +#define FW070TFT_WSVGA_HEIGHT 600 /*!< YRES */ +#define FW070TFT_WSVGA_MARGIN_LEFT 160 /*!< HBP (Horizontal Back Porch) */ +#define FW070TFT_WSVGA_MARGIN_RIGHT 160 /*!< HFP (Horizontal Front Porch) */ +#define FW070TFT_WSVGA_MARGIN_UPPER 12 /*!< VBP (Vertical Back Porch) */ +#define FW070TFT_WSVGA_MARGIN_LOWER 23 /*!< VFP (Vertical Front Porch) */ +#define FW070TFT_WSVGA_HSYNC_LEN 1 /*!< HPW (HSYNC plus width) */ +#define FW070TFT_WSVGA_VSYNC_LEN 1 /*!< VPW (VSYNC width) */ +static VPOST_T DEF_FW070TFT_WSVGA = +{ + FW070TFT_WSVGA_WIDTH, /*!< Panel width */ + FW070TFT_WSVGA_HEIGHT, /*!< Panel height */ + 0, /*!< MPU command line low indicator */ + 0, /*!< MPU command width */ + 0, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + 0, /*!< MPU mode */ + VPOSTB_COLORTYPE_16M, /*!< Display colors */ + VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */ + + .sCRTCSIZE = + { + /*!< Horizontal Total */ + .HTT = FW070TFT_WSVGA_MARGIN_LEFT + FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_RIGHT, + + /*!< Vertical Total */ + .VTT = FW070TFT_WSVGA_MARGIN_UPPER + FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_LOWER, + }, + .sCRTCDEND = + { + /*!< Horizontal Display Enable End */ + .HDEND = FW070TFT_WSVGA_WIDTH, + + /*!< Vertical Display Enable End */ + .VDEND = FW070TFT_WSVGA_HEIGHT, + }, + .sCRTCHR = + { + /*!< Internal Horizontal Retrace Start Timing */ + .HRS = FW070TFT_WSVGA_WIDTH + 1, + + /*!< Internal Horizontal Retrace End Low */ + .HRE = FW070TFT_WSVGA_WIDTH + 5, + }, + .sCRTCHSYNC = + { + /*!< Horizontal Sync Start Timing */ + .HSYNC_S = FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_LEFT, + + /*!< Horizontal Sync End Timing */ + .HSYNC_E = FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_LEFT + FW070TFT_WSVGA_HSYNC_LEN, + + /*!< Hsync Signal Adjustment For Multi-Cycles Per Pixel Mode Of Sync-Based Unipac-LCD */ + .HSYNC_SHIFT = 0, + }, + .sCRTCVR = + { + /*!< Vertical Internal Retrace Start Timing */ + .VRS = FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_UPPER, + + /*!< Vertical Internal Retrace End Low */ + .VRE = FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_UPPER + FW070TFT_WSVGA_VSYNC_LEN, + } +}; /* LCD build-in support list */ -static VPOST_T *DisplayDevList[5] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT, &DEF_FW043TFT}; +static VPOST_T *DisplayDevList[DIS_PANEL_CNT] = +{ + &DEF_E50A2V1, + &DEF_ILI9341_MPU80, + &DEF_LSA40AT9001, + &DEF_FW070TFT, + &DEF_FW043TFT, + &DEF_FW070TFT_WSVGA +}; + static VPOST_T curDisplayDev; static OSDFORMATEX curOSDDev = {0}; static LCDFORMATEX curVADev = {0}; diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig index f57b439f00..4d863f6126 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig @@ -475,6 +475,9 @@ config SOC_SERIES_N9H30 config LCM_USING_FW043TFT bool "LCM_FW043TFT(480x272-RGB888)" + config LCM_USING_FW070TFT_WSVGA + bool "LCM_USING_FW070TFT_WSVGA(1024x600-RGB888)" + endchoice config VPOST_USING_LCD_IDX @@ -483,6 +486,7 @@ config SOC_SERIES_N9H30 default 2 if LCM_USING_LSA40AT9001 default 3 if LCM_USING_FW070TFT default 4 if LCM_USING_FW043TFT + default 5 if LCM_USING_FW070TFT_WSVGA config BSP_LCD_BPP int @@ -490,6 +494,7 @@ config SOC_SERIES_N9H30 default 16 if LCM_USING_LSA40AT9001 default 32 if LCM_USING_FW070TFT default 32 if LCM_USING_FW043TFT + default 32 if LCM_USING_FW070TFT_WSVGA config BSP_LCD_WIDTH int @@ -497,6 +502,7 @@ config SOC_SERIES_N9H30 default 800 if LCM_USING_LSA40AT9001 default 800 if LCM_USING_FW070TFT default 480 if LCM_USING_FW043TFT + default 1024 if LCM_USING_FW070TFT_WSVGA config BSP_LCD_HEIGHT int @@ -504,6 +510,7 @@ config SOC_SERIES_N9H30 default 600 if LCM_USING_LSA40AT9001 default 480 if LCM_USING_FW070TFT default 272 if LCM_USING_FW043TFT + default 600 if LCM_USING_FW070TFT_WSVGA config BSP_USING_VPOST_OSD bool "Enable VPOST OSD layer" diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c index fb1f4433cf..22c98e6c32 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c @@ -30,18 +30,12 @@ static nu_adc_touch s_NuAdcTouch = {0}; #define DEF_CALDATA_LENGTH 7 -#if defined(LCM_USING_FW043TFT) - #define LCM_WIDTH 480 - #define LCM_HEIGHT 272 +#if (BSP_LCD_WIDTH==480) && (BSP_LCD_HEIGHT==272) static int cal_data_a[DEF_CALDATA_LENGTH] = { 8824, -34, -2261272, -70, -6302, 21805816, 65536 }; -#else - #define LCM_WIDTH 800 - #define LCM_HEIGHT 480 - #if defined(LCM_USING_FW070TFT) +#elif (BSP_LCD_WIDTH==800) && (BSP_LCD_HEIGHT==480) static int cal_data_a[DEF_CALDATA_LENGTH] = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; - #else +#else static int cal_data_a[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; - #endif #endif static const int cal_zero[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; @@ -166,8 +160,8 @@ int rt_hw_adc_touch_init(void) s_NuAdcTouch.dev.info.type = RT_TOUCH_TYPE_RESISTANCE; s_NuAdcTouch.dev.info.vendor = RT_TOUCH_VENDOR_UNKNOWN; s_NuAdcTouch.dev.info.point_num = 1; - s_NuAdcTouch.dev.info.range_x = LCM_WIDTH; - s_NuAdcTouch.dev.info.range_y = LCM_HEIGHT; + s_NuAdcTouch.dev.info.range_x = BSP_LCD_WIDTH; + s_NuAdcTouch.dev.info.range_y = BSP_LCD_HEIGHT; s_NuAdcTouch.dev.ops = &touch_ops; @@ -203,11 +197,11 @@ static void adc_touch_entry(void *parameter) result = rt_device_set_rx_indicate(pdev, adc_touch_rx_callback); RT_ASSERT(result == RT_EOK); - max_range = LCM_WIDTH; + max_range = BSP_LCD_WIDTH; result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_X_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); - max_range = LCM_HEIGHT; + max_range = BSP_LCD_HEIGHT; result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); @@ -270,7 +264,7 @@ static rt_err_t nu_touch_start(int argc, char **argv) adc_touch_thread = rt_thread_create("adc_touch_thread", adc_touch_entry, RT_NULL, - 1024, + 2048, 25, 5); adc_touch_worker_run = 1; @@ -281,6 +275,12 @@ static rt_err_t nu_touch_start(int argc, char **argv) } MSH_CMD_EXPORT(nu_touch_start, e.g: start adc touch); +static int nu_touch_autostart(void) +{ + return nu_touch_start(0, RT_NULL); +} +INIT_APP_EXPORT(nu_touch_autostart); + /* Support "nu_touch_stop" command line in msh mode */ static rt_err_t nu_touch_stop(int argc, char **argv) { diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c index a4da2879cf..aedd61f018 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c @@ -58,6 +58,7 @@ struct nu_can IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -106,16 +107,16 @@ static const struct can_configure nu_can_default_config = NU_CAN_CONFIG_DEFAULT; /* Interrupt Handle Function ----------------------------------------------------*/ static void nu_can_isr(int vector, void *param) { - uint32_t u32IIDRstatus; nu_can_t psNuCAN = (nu_can_t)param; /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ @@ -123,20 +124,24 @@ static void nu_can_isr(int vector, void *param) if (base->STATUS & CAN_STATUS_TXOK_Msk) { base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - //rt_kprintf("%s: TX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif } if (base->STATUS & CAN_STATUS_RXOK_Msk) { base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - //rt_kprintf("%s: RX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif } @@ -145,17 +150,16 @@ static void nu_can_isr(int vector, void *param) /**************************/ if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("%s: EWARN\n", psNuCAN->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("%s: BUSOFF\n", psNuCAN->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } if (base->STATUS & CAN_STATUS_LEC_Msk) @@ -168,66 +172,83 @@ static void nu_can_isr(int vector, void *param) /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; - RT_ASSERT(base != RT_NULL); - - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } - + /* Reset this module */ nu_sys_ip_reset(psNuCAN->rstidx); - /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; + /*Set the CAN Bit Rate and Operating mode*/ + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR CAN_LeaveTestMode(base); @@ -249,6 +270,7 @@ static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; @@ -261,73 +283,33 @@ exit_nu_can_configure: static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; - nu_can_t psNuCAN = (nu_can_t)can; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *base = psNuCAN->base; - - RT_ASSERT(base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Status Change Interrupt */ - CAN_DisableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Error Interrupt */ - CAN_DisableInt(base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } @@ -335,46 +317,61 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) else { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -387,16 +384,23 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; @@ -411,64 +415,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + RT_ASSERT(can); + RT_ASSERT(buf); - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + pmsg = (struct rt_can_msg *) buf; - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -480,32 +511,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -540,5 +552,4 @@ static int rt_hw_can_init(void) return (int)ret; } INIT_DEVICE_EXPORT(rt_hw_can_init); - #endif //#if defined(BSP_USING_CAN) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c index 0b4fbaabf1..4fd7f335cc 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c @@ -34,6 +34,8 @@ #define I2C_ENABLE(dev) I2C_REG_WRITE(dev, I2C_CSR, 0x3) /* Enable i2c core and interrupt */ #define I2C_ISBUSFREE(dev) (((I2C_REG_READ(dev, I2C_SWR) & 0x18) == 0x18 && (I2C_REG_READ(dev, I2C_CSR) & 0x0400) == 0) ? 1 : 0) +#define I2C_SIGNAL_TIMEOUT 5000 + enum { I2C_START = -1, @@ -50,7 +52,7 @@ enum typedef struct { int32_t base; /* i2c bus number */ - int32_t state; + volatile int32_t state; int32_t addr; uint32_t last_error; int32_t bNackValid; @@ -58,9 +60,11 @@ typedef struct uint32_t subaddr; int32_t subaddr_len; - uint8_t buffer[I2C_MAX_BUF_LEN]; - uint32_t pos, len; + volatile uint32_t pos; + volatile uint32_t len; + uint8_t *buffer; + struct rt_completion signal; } nu_i2c_dev; typedef nu_i2c_dev *nu_i2c_dev_t; @@ -68,7 +72,6 @@ typedef struct { struct rt_i2c_bus_device parent; char *name; - IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; @@ -113,13 +116,13 @@ static nu_i2c_bus nu_i2c_arr [ ] = * @brief Set i2c interface speed * @param[in] dev i2c device structure pointer * @param[in] sp i2c speed - * @return always 0 + * @return 0 or I2C_ERR_NOTTY */ static int32_t nu_i2c_set_speed(nu_i2c_dev_t psNuI2cDev, int32_t sp) { uint32_t d; - if (sp != 100 && sp != 400) + if ((sp != 100) && (sp != 400)) return (I2C_ERR_NOTTY); d = (sysGetClock(SYS_PCLK) * 1000) / (sp * 5) - 1; @@ -205,6 +208,7 @@ static void nu_i2c_isr(int vector, void *param) psNuI2CDev->last_error = I2C_ERR_NACK; nu_i2c_command(psNuI2CDev, I2C_CMD_STOP); psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } /* Arbitration lost */ else if (csr & 0x200) @@ -212,6 +216,7 @@ static void nu_i2c_isr(int vector, void *param) rt_kprintf("Arbitration lost\n"); psNuI2CDev->last_error = I2C_ERR_LOSTARBITRATION; psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } /* Transmit complete */ else if (!(csr & 0x100)) @@ -225,6 +230,7 @@ static void nu_i2c_isr(int vector, void *param) } else if (psNuI2CDev->state == I2C_STATE_READ) { + /* Sub-address send over, begin restart a read command */ if (psNuI2CDev->pos == psNuI2CDev->subaddr_len + 1) { @@ -246,6 +252,7 @@ static void nu_i2c_isr(int vector, void *param) else { psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } } } @@ -270,13 +277,13 @@ static void nu_i2c_isr(int vector, void *param) else { psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } } } + } - - /** * @brief Read data from I2C slave. * @param[in] psNuI2cDev is interface structure pointer. @@ -294,6 +301,9 @@ static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) uint8_t *buf = pmsg->buf; uint32_t len = pmsg->len; + RT_ASSERT(len); + RT_ASSERT(buf); + if (len > I2C_MAX_BUF_LEN - 10) len = I2C_MAX_BUF_LEN - 10; @@ -317,9 +327,22 @@ static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (!I2C_ISBUSFREE(psNuI2cDev)) return (I2C_ERR_BUSY); + rt_completion_init(&psNuI2cDev->signal); + nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE); - while (psNuI2cDev->state != I2C_STATE_NOP); + if ((RT_EOK == rt_completion_wait(&psNuI2cDev->signal, I2C_SIGNAL_TIMEOUT))) + { + rt_memcpy(buf, psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 3, len); + + psNuI2cDev->subaddr += len; + } + else + { + rt_kprintf("[%s]Wait signal timeout.\n", __func__); + + len = 0; + } /* Disable I2C-EN */ I2C_DISABLE(psNuI2cDev); @@ -327,10 +350,6 @@ static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (psNuI2cDev->last_error) return (psNuI2cDev->last_error); - rt_memcpy(buf, psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 3, len); - - psNuI2cDev->subaddr += len; - return len; } @@ -351,6 +370,9 @@ static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) uint8_t *buf = pmsg->buf; uint32_t len = pmsg->len; + RT_ASSERT(len); + RT_ASSERT(buf); + if (len > I2C_MAX_BUF_LEN - 10) len = I2C_MAX_BUF_LEN - 10; @@ -373,9 +395,20 @@ static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (!I2C_ISBUSFREE(psNuI2cDev)) return (I2C_ERR_BUSY); + rt_completion_init(&psNuI2cDev->signal); + nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE); - while (psNuI2cDev->state != I2C_STATE_NOP); + if ((RT_EOK == rt_completion_wait(&psNuI2cDev->signal, I2C_SIGNAL_TIMEOUT))) + { + psNuI2cDev->subaddr += len; + } + else + { + rt_kprintf("[%s]Wait signal timeout.\n", __func__); + + len = 0; + } /* Disable I2C-EN */ I2C_DISABLE(psNuI2cDev); @@ -383,8 +416,6 @@ static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (psNuI2cDev->last_error) return (psNuI2cDev->last_error); - psNuI2cDev->subaddr += len; - return len; } @@ -405,16 +436,13 @@ static int32_t nu_i2c_ioctl(nu_i2c_dev_t psNuI2cDev, uint32_t cmd, uint32_t arg0 switch (cmd) { case I2C_IOC_SET_DEV_ADDRESS: - psNuI2cDev->addr = arg0; break; case I2C_IOC_SET_SPEED: - - return (nu_i2c_set_speed(psNuI2cDev, (int32_t)arg0)); + return nu_i2c_set_speed(psNuI2cDev, (int32_t)arg0); case I2C_IOC_SET_SUB_ADDRESS: - if (arg1 > 4) { return (I2C_ERR_NOTTY); @@ -441,7 +469,8 @@ static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, rt_err_t ret; struct rt_i2c_msg *pmsg; - RT_ASSERT(bus != RT_NULL); + RT_ASSERT(bus); + psNuI2cBus = (nu_i2c_bus_t) bus; psNuI2cDev = &psNuI2cBus->dev; @@ -459,6 +488,7 @@ static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, /* Set device address */ nu_i2c_reset(psNuI2cDev); + nu_i2c_ioctl(psNuI2cDev, I2C_IOC_SET_DEV_ADDRESS, pmsg->addr, 0); if (pmsg->flags & RT_I2C_RD) @@ -470,18 +500,39 @@ static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, ret = nu_i2c_write(psNuI2cDev, pmsg); } - if (ret != pmsg->len) break; } return i; } +static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u32Cmd, rt_uint32_t u32Value) +{ + nu_i2c_bus_t psNuI2cBus; + nu_i2c_dev_t psNuI2cDev; + + RT_ASSERT(bus); + + psNuI2cBus = (nu_i2c_bus_t) bus; + psNuI2cDev = &psNuI2cBus->dev; + + switch (RT_I2C_DEV_CTRL_CLK) + { + case RT_I2C_DEV_CTRL_CLK: + nu_i2c_set_speed(psNuI2cDev, (int32_t)u32Value); + break; + default: + return -RT_EIO; + } + + return RT_EOK; +} + static const struct rt_i2c_bus_device_ops nu_i2c_ops = { .master_xfer = nu_i2c_mst_xfer, .slave_xfer = NULL, - .i2c_bus_control = NULL, + .i2c_bus_control = nu_i2c_bus_control, }; @@ -489,17 +540,17 @@ static const struct rt_i2c_bus_device_ops nu_i2c_ops = int rt_hw_i2c_init(void) { int i; - rt_err_t ret = RT_EOK; + rt_err_t ret; for (i = (I2C_START + 1); i < I2C_CNT; i++) { nu_i2c_dev_t psNuI2cDev = &nu_i2c_arr[i].dev; - ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].name); - RT_ASSERT(RT_EOK == ret); - nu_i2c_arr[i].parent.ops = &nu_i2c_ops; + psNuI2cDev->buffer = rt_malloc(I2C_MAX_BUF_LEN); + RT_ASSERT(psNuI2cDev->buffer); + /* Enable I2C engine clock and reset. */ nu_sys_ipclk_enable(nu_i2c_arr[i].clkidx); nu_sys_ip_reset(nu_i2c_arr[i].rstidx); @@ -509,6 +560,9 @@ int rt_hw_i2c_init(void) /* Register ISR and Respond IRQ. */ rt_hw_interrupt_install(nu_i2c_arr[i].irqn, nu_i2c_isr, &nu_i2c_arr[i], nu_i2c_arr[i].name); rt_hw_interrupt_umask(nu_i2c_arr[i].irqn); + + ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].name); + RT_ASSERT(RT_EOK == ret); } return 0; diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c index 41fae42ae4..bf5498c8a4 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c @@ -49,6 +49,10 @@ typedef struct nu_vpost *nu_vpost_t; static volatile uint32_t g_u32VSyncBlank = 0; static struct rt_completion vsync_wq; +RT_WEAK void nu_lcd_backlight_on(void) { } + +RT_WEAK void nu_lcd_backlight_off(void) { } + static struct nu_vpost nu_fbdev[eVpost_Cnt] = { { @@ -149,6 +153,18 @@ static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) switch (cmd) { + case RTGRAPHIC_CTRL_POWERON: + { + nu_lcd_backlight_on(); + } + break; + + case RTGRAPHIC_CTRL_POWEROFF: + { + nu_lcd_backlight_off(); + } + break; + case RTGRAPHIC_CTRL_GET_INFO: { struct rt_device_graphic_info *info = (struct rt_device_graphic_info *) args; @@ -324,6 +340,11 @@ int rt_hw_vpost_init(void) rt_kprintf("Fail to get VRAM buffer.\n"); RT_ASSERT(0); } + else + { + uint32_t u32FBSize = psVpost->info.pitch * psVpostLcmInst->u32DevHeight; + rt_memset(psVpost->info.framebuffer, 0, u32FBSize); + } /* Register member functions of lcd device */ psVpost->dev.type = RT_Device_Class_Graphic; diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_can.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_can.h index 5ac83bf1cb..c62af68489 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_can.h +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_can.h @@ -151,8 +151,8 @@ typedef struct #define CAN_BTIME_TSEG2_Pos (12) /*!< CAN_T::BTIME: TSeg2 Position */ #define CAN_BTIME_TSEG2_Msk (0x7ul << CAN_BTIME_TSEG2_Pos) /*!< CAN_T::BTIME: TSeg2 Mask */ -#define CAN_IIDR_IntId_Pos (0) /*!< CAN_T::IIDR: IntId Position */ -#define CAN_IIDR_IntId_Msk (0xfffful << CAN_IIDR_IntId_Pos) /*!< CAN_T::IIDR: IntId Mask */ +#define CAN_IIDR_INTID_Pos (0) /*!< CAN_T::IIDR: IntId Position */ +#define CAN_IIDR_INTID_Msk (0xfffful << CAN_IIDR_INTID_Pos) /*!< CAN_T::IIDR: IntId Mask */ #define CAN_TEST_BASIC_Pos (2) /*!< CAN_T::TEST: Basic Position */ #define CAN_TEST_BASIC_Msk (0x1ul << CAN_TEST_BASIC_Pos) /*!< CAN_T::TEST: Basic Mask */ diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c index 52caa234ec..9df47d6f2b 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c +++ b/bsp/nuvoton/libraries/nuc980/Driver/Source/nu_emac.c @@ -1129,7 +1129,7 @@ uint32_t EMAC_GetAvailRXBufSize(EMAC_MEMMGR_T *psMemMgr, uint8_t **ppuDataBuf) * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1 * @note This function is without doing EMAC_TRIGGER_RX. */ -EMAC_DESCRIPTOR_T * EMAC_RecvPktDoneWoRxTrigger(EMAC_MEMMGR_T *psMemMgr) +EMAC_DESCRIPTOR_T *EMAC_RecvPktDoneWoRxTrigger(EMAC_MEMMGR_T *psMemMgr) { /* Get Rx Frame Descriptor */ EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)psMemMgr->psCurrentRxDesc; @@ -1151,7 +1151,7 @@ EMAC_DESCRIPTOR_T * EMAC_RecvPktDoneWoRxTrigger(EMAC_MEMMGR_T *psMemMgr) return ret; } -void EMAC_RxTrigger(EMAC_MEMMGR_T *psMemMgr, EMAC_DESCRIPTOR_T * rx_desc) +void EMAC_RxTrigger(EMAC_MEMMGR_T *psMemMgr, EMAC_DESCRIPTOR_T *rx_desc) { EMAC_T *EMAC = psMemMgr->psEmac; diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c index 3b48867bb2..fcdbbe8d74 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c @@ -64,6 +64,7 @@ struct nu_can IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -130,16 +131,16 @@ static const struct can_configure nu_can_default_config = NU_CAN_CONFIG_DEFAULT; /* Interrupt Handle Function ----------------------------------------------------*/ static void nu_can_isr(int vector, void *param) { - uint32_t u32IIDRstatus; nu_can_t psNuCAN = (nu_can_t)param; /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ @@ -147,20 +148,24 @@ static void nu_can_isr(int vector, void *param) if (base->STATUS & CAN_STATUS_TXOK_Msk) { base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - //rt_kprintf("%s: TX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif } if (base->STATUS & CAN_STATUS_RXOK_Msk) { base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - //rt_kprintf("%s: RX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif } @@ -169,17 +174,16 @@ static void nu_can_isr(int vector, void *param) /**************************/ if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("%s: EWARN\n", psNuCAN->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("%s: BUSOFF\n", psNuCAN->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } if (base->STATUS & CAN_STATUS_LEC_Msk) @@ -192,66 +196,83 @@ static void nu_can_isr(int vector, void *param) /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; - RT_ASSERT(base != RT_NULL); - - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } - + /* Reset this module */ nu_sys_ip_reset(psNuCAN->rstidx); - /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; + /*Set the CAN Bit Rate and Operating mode*/ + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR CAN_LeaveTestMode(base); @@ -273,6 +294,7 @@ static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; @@ -285,73 +307,33 @@ exit_nu_can_configure: static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; - nu_can_t psNuCAN = (nu_can_t)can; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *base = psNuCAN->base; - - RT_ASSERT(base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Status Change Interrupt */ - CAN_DisableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Error Interrupt */ - CAN_DisableInt(base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } @@ -359,46 +341,61 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) else { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -411,16 +408,23 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; @@ -435,64 +439,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + RT_ASSERT(can); + RT_ASSERT(buf); - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + pmsg = (struct rt_can_msg *) buf; - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -504,32 +535,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -564,5 +576,4 @@ static int rt_hw_can_init(void) return (int)ret; } INIT_DEVICE_EXPORT(rt_hw_can_init); - #endif //#if defined(BSP_USING_CAN) diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config index fa6f45f046..dd0c4cefb2 100644 --- a/bsp/nuvoton/nk-980iot/.config +++ b/bsp/nuvoton/nk-980iot/.config @@ -1003,3 +1003,5 @@ CONFIG_BOARD_USING_ILI9341_PIN_BACKLIGHT=103 CONFIG_BOARD_USING_ILI9341_PIN_RESET=90 CONFIG_BOARD_USING_ILI9341_PIN_DC=89 # CONFIG_BOARD_USING_ESP8266 is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." diff --git a/bsp/nuvoton/nk-980iot/Kconfig b/bsp/nuvoton/nk-980iot/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/nk-980iot/Kconfig +++ b/bsp/nuvoton/nk-980iot/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-980iot/board/Kconfig b/bsp/nuvoton/nk-980iot/board/Kconfig index 06547f567b..ff8ddf85ec 100644 --- a/bsp/nuvoton/nk-980iot/board/Kconfig +++ b/bsp/nuvoton/nk-980iot/board/Kconfig @@ -113,5 +113,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/nk-980iot/project.uvproj b/bsp/nuvoton/nk-980iot/project.uvproj deleted file mode 100644 index edb52cb8a3..0000000000 --- a/bsp/nuvoton/nk-980iot/project.uvproj +++ /dev/null @@ -1,1877 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\Objects\ - rtthread - 1 - 0 - 0 - 1 - 1 - .\Listings\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARM.DLL - -cAT91SAM9 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 0 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 6 - - - - - - - - - - - - - ..\libraries\nuc980\Script\NUC980xx61.ini - Segger\JLTAgdi.dll - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nu_packages\ILI9341;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\SPINAND;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - mtd_nand.c - 1 - ..\..\..\components\drivers\mtd\mtd_nand.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - - - - - - - - - - - Drivers - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - Libraries - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - LVGL-port - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_ili9341 - - - lcd_ili9341.c - 1 - ..\libraries\nu_packages\ILI9341\lcd_ili9341.c - - - - - ili9341_spi.c - 1 - ..\libraries\nu_packages\ILI9341\ili9341_spi.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - nu_pkgs_spinand - - - spinand.c - 1 - ..\libraries\nu_packages\SPINAND\spinand.c - - - - - drv_spinand.c - 1 - ..\libraries\nu_packages\SPINAND\drv_spinand.c - - - - - nuc980_usbhostlib - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/nk-980iot/project.uvprojx b/bsp/nuvoton/nk-980iot/project.uvprojx deleted file mode 100644 index 7d23d354b5..0000000000 --- a/bsp/nuvoton/nk-980iot/project.uvprojx +++ /dev/null @@ -1,1869 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - 0 - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARM.DLL - -cAT91SAM9260 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - ARM926EJ-S - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x20000000 - 0x800000 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x100000 - 0x8000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x20800000 - 0x1800000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 0 - 0x300000 - 0x1000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nu_packages\ILI9341;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\SPINAND;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - board - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - mtd_nand.c - 1 - ..\..\..\components\drivers\mtd\mtd_nand.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - - - - - - - - - - - Drivers - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - Libraries - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - LVGL-port - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_ili9341 - - - lcd_ili9341.c - 1 - ..\libraries\nu_packages\ILI9341\lcd_ili9341.c - - - - - ili9341_spi.c - 1 - ..\libraries\nu_packages\ILI9341\ili9341_spi.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - nu_pkgs_spinand - - - spinand.c - 1 - ..\libraries\nu_packages\SPINAND\spinand.c - - - - - drv_spinand.c - 1 - ..\libraries\nu_packages\SPINAND\drv_spinand.c - - - - - nuc980_usbhostlib - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/nk-980iot/rtconfig.h b/bsp/nuvoton/nk-980iot/rtconfig.h deleted file mode 100644 index b77df08b3f..0000000000 --- a/bsp/nuvoton/nk-980iot/rtconfig.h +++ /dev/null @@ -1,459 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 16 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_MEMHEAP -#define RT_MEMHEAP_FAST_MODE -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_ARM9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 16 -#define DFS_FILESYSTEM_TYPES_MAX 16 -#define DFS_FD_MAX 64 -#define RT_USING_DFS_MNTTABLE -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_CAN_USING_HDR -#define RT_USING_HWTIMER -#define RT_USING_CPUTIME -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_MTD_NAND -#define RT_MTD_NAND_DEBUG -#define RT_USING_RTC -#define RT_USING_ALARM -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_TOUCH -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_CDC -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_MSTORAGE -#define RT_VCOM_TASK_STK_SIZE 2048 -#define RT_CDC_RX_BUFSIZE 128 -#define RT_VCOM_SERNO "32021919830108" -#define RT_VCOM_SER_LEN 14 -#define RT_VCOM_TX_TIMEOUT 1000 -#define RT_USB_MSTORAGE_DISK_NAME "ramdisk1" - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP212 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.31.55" -#define RT_LWIP_GWADDR "192.168.31.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 16 -#define RT_LWIP_PBUF_NUM 256 -#define RT_LWIP_RAW_PCB_NUM 16 -#define RT_LWIP_UDP_PCB_NUM 16 -#define RT_LWIP_TCP_PCB_NUM 16 -#define RT_LWIP_TCP_SEG_NUM 64 -#define RT_LWIP_TCP_SND_BUF 16384 -#define RT_LWIP_TCP_WND 65535 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 256 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 256 -#define RT_LWIP_REASSEMBLY_FRAG -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define RT_LWIP_NETIF_LOOPBACK -#define LWIP_NETIF_LOOPBACK 1 -#define RT_LWIP_STATS -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_NETUTILS -#define PKG_NETUTILS_TFTP -#define PKG_NETUTILS_IPERF -#define PKG_NETUTILS_NTP -#define NTP_USING_AUTO_SYNC -#define NTP_AUTO_SYNC_FIRST_DELAY 30 -#define NTP_AUTO_SYNC_PERIOD 3600 -#define NETUTILS_NTP_HOSTNAME "0.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME2 "1.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME3 "2.tw.pool.ntp.org" -#define PKG_USING_NETUTILS_V131 -#define PKG_NETUTILS_VER_NUM 0x10301 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - -#define PKG_USING_LVGL -#define PKG_USING_LVGL_V810 -#define PKG_LVGL_VER_NUM 0x08010 -#define PKG_USING_LV_MUSIC_DEMO - -/* u8g2: a monochrome graphic library */ - -#define PKG_USING_WAVPLAYER -#define PKG_WP_USING_PLAY -#define PKG_WP_PLAY_DEVICE "sound0" -#define PKG_WP_USING_RECORD -#define PKG_WP_RECORD_DEVICE "sound0" -#define PKG_USING_WAVPLAYER_LATEST_VERSION - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_DFS_UFFS -#define RT_USING_DFS_UFFS -#define RT_UFFS_ECC_MODE_3 -#define RT_UFFS_ECC_MODE 3 -#define PKG_USING_DFS_UFFS_LATEST_VERSION -#define PKG_USING_RAMDISK -#define PKG_USING_RAMDISK_LATEST_VERSION - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define PKG_USING_OPTPARSE -#define PKG_USING_OPTPARSE_LATEST_VERSION - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO -#define NU_PKG_USING_NAU8822 -#define NU_PKG_USING_ILI9341 -#define NU_PKG_USING_ILI9341_SPI -#define NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER -#define NU_PKG_ILI9341_HORIZONTAL -#define NU_PKG_USING_SPINAND - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_NUC980 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_MMU -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define BSP_USING_GPIO -#define BSP_USING_EMAC -#define BSP_USING_EMAC0 -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_IO_RW -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_ADC -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TIMER0 -#define BSP_USING_TMR1 -#define BSP_USING_TIMER1 -#define BSP_USING_TMR2 -#define BSP_USING_TIMER2 -#define BSP_USING_TMR3 -#define BSP_USING_TIMER3 -#define BSP_USING_TMR4 -#define BSP_USING_TIMER4 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART1_TX_DMA -#define BSP_USING_UART1_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C0 -#define BSP_USING_I2C2 -#define BSP_USING_SDH -#define BSP_USING_SDH1 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define BSP_USING_PWM -#define BSP_USING_PWM0 -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0 -#define BSP_USING_SPI0_PDMA -#define BSP_USING_SPI1_NONE -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 4096 -#define BSP_USING_QSPI -#define BSP_USING_QSPI_PDMA -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI0_PDMA -#define BSP_USING_CRYPTO -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_USBH - -/* On-board Peripheral Drivers */ - -#define BSP_USING_CONSOLE -#define BOARD_USING_IP101GR -#define BOARD_USING_NAU8822 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPINAND -#define BOARD_USING_USB0_DEVICE_HOST -#define BOARD_USING_USB1_HOST - -/* Board extended module drivers */ - -#define BOARD_USING_LCD_ILI9341 -#define BOARD_USING_ILI9341_PIN_BACKLIGHT 103 -#define BOARD_USING_ILI9341_PIN_RESET 90 -#define BOARD_USING_ILI9341_PIN_DC 89 - -#endif diff --git a/bsp/nuvoton/nk-n9h30/.config b/bsp/nuvoton/nk-n9h30/.config index d235edc087..f3e8600372 100644 --- a/bsp/nuvoton/nk-n9h30/.config +++ b/bsp/nuvoton/nk-n9h30/.config @@ -744,6 +744,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -832,19 +833,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -# CONFIG_NU_PKG_USING_DEMO is not set -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -CONFIG_NU_PKG_USING_NAU8822=y -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set - # # Hardware Drivers Config # @@ -929,6 +917,7 @@ CONFIG_BSP_USING_VPOST=y # CONFIG_LCM_USING_LSA40AT9001 is not set CONFIG_LCM_USING_FW070TFT=y # CONFIG_LCM_USING_FW043TFT is not set +# CONFIG_LCM_USING_FW070TFT_WSVGA is not set CONFIG_VPOST_USING_LCD_IDX=3 CONFIG_BSP_LCD_BPP=32 CONFIG_BSP_LCD_WIDTH=800 @@ -946,10 +935,29 @@ CONFIG_BOARD_USING_NAU8822=y CONFIG_BOARD_USING_STORAGE_SDCARD=y CONFIG_BOARD_USING_STORAGE_SPIFLASH=y CONFIG_BOARD_USING_BUZZER=y -CONFIG_BOARD_USING_LCM=y CONFIG_BOARD_USING_USB0_DEVICE_HOST=y CONFIG_BOARD_USING_USB1_HOST=y # # Board extended module drivers # +CONFIG_BOARD_USING_LCM_FW070TFT_WVGA=y +# CONFIG_BOARD_USING_LCM_FW043TFT_HVGA is not set +# CONFIG_BOARD_USING_LCM_FW070TFT_WSVGA is not set +CONFIG_BOARD_USING_ADCTOUCH=y +# CONFIG_BOARD_USING_GT911 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +# CONFIG_NU_PKG_USING_DEMO is not set +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk-n9h30.test.utest." diff --git a/bsp/nuvoton/nk-n9h30/Kconfig b/bsp/nuvoton/nk-n9h30/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/nk-n9h30/Kconfig +++ b/bsp/nuvoton/nk-n9h30/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c index 266be12a31..3162bf8d2b 100644 --- a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c +++ b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c @@ -26,9 +26,30 @@ static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ static void *buf3_next = RT_NULL; +static uint32_t u32FirstFlush = 0; + +static void nu_antitearing(lv_disp_draw_buf_t *draw_buf, lv_color_t *color_p) +{ + if (buf3_next) + { + /* vsync-none: Use triple screen-sized buffers. */ + if (draw_buf->buf1 == color_p) + draw_buf->buf1 = buf3_next; + else + draw_buf->buf2 = buf3_next; + + draw_buf->buf_act = buf3_next; + buf3_next = color_p; + } + else + { + /* vsync-after: Use ping-pong screen-sized buffers only.*/ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + } +} + static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - lv_disp_t *psDisp = _lv_refr_get_disp_refreshing(); void *pvDstReDraw; #if (LV_USE_GPU_N9H30_GE2D==0) @@ -55,8 +76,14 @@ static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_c mmu_invalidate_dcache((uint32_t)pvDstReDraw, disp_drv->draw_buf->size * sizeof(lv_color_t)); #endif - /* WAIT_VSYNC */ - rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + nu_antitearing(disp_drv->draw_buf, color_p); + + if (!u32FirstFlush) + { + /* Enable backlight at first flushing. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + u32FirstFlush = 1; + } lv_disp_flush_ready(disp_drv); } @@ -70,21 +97,13 @@ static void nu_flush_full_refresh(lv_disp_drv_t *disp_drv, const lv_area_t *area /* Use PANDISPLAY without H/W copying */ rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, color_p); - if (buf3_next) - { - /* vsync-none: Use triple screen-sized buffers. */ - if (disp_drv->draw_buf->buf1 == color_p) - disp_drv->draw_buf->buf1 = buf3_next; - else - disp_drv->draw_buf->buf2 = buf3_next; + nu_antitearing(disp_drv->draw_buf, color_p); - disp_drv->draw_buf->buf_act = buf3_next; - buf3_next = color_p; - } - else + if (!u32FirstFlush) { - /* vsync-after: Use ping-pong screen-sized buffers only.*/ - rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + /* Enable backlight at first flushing. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + u32FirstFlush = 1; } lv_disp_flush_ready(disp_drv); @@ -106,6 +125,13 @@ static void nu_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t ge2dSpriteBlt_Screen(area->x1, area->y1, flush_area_w, flush_area_h, (void *)color_p); // -> Leave GE2D + if (!u32FirstFlush) + { + /* Enable backlight at first flushing. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + u32FirstFlush = 1; + } + lv_disp_flush_ready(disp_drv); } @@ -188,6 +214,9 @@ void lv_port_disp_init(void) return; } + /* Disable backlight at startup. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWEROFF, RT_NULL); + RT_ASSERT(info.bits_per_pixel == 8 || info.bits_per_pixel == 16 || info.bits_per_pixel == 24 || info.bits_per_pixel == 32); diff --git a/bsp/nuvoton/nk-n9h30/board/Kconfig b/bsp/nuvoton/nk-n9h30/board/Kconfig index c26e25fb65..293dedbbc9 100644 --- a/bsp/nuvoton/nk-n9h30/board/Kconfig +++ b/bsp/nuvoton/nk-n9h30/board/Kconfig @@ -45,12 +45,6 @@ menu "Hardware Drivers Config" select BSP_USING_PWM0 default n - config BOARD_USING_LCM - bool "NuDesign TFT-LCD7(over vpost)" - select BSP_USING_VPOST - select LCM_USING_FW070TFT - default y - config BOARD_USING_USB0_DEVICE_HOST select BSP_USING_USBH select BSP_USING_USBD @@ -69,7 +63,54 @@ menu "Hardware Drivers Config" menu "Board extended module drivers" + choice + prompt "Select LCD panel devices.(Over VPOST)" + + config BOARD_USING_LCM_FW070TFT_WVGA + bool "NuDesign TFT-LCD7-WVGA" + select BSP_USING_VPOST + select LCM_USING_FW070TFT + default y + help + Choose this option if you use 7" 800x480x32b LCD panel. + + config BOARD_USING_LCM_FW043TFT_HVGA + bool "NuDesign TFT-LCD43-HVGA" + select BSP_USING_VPOST + select LCM_USING_FW043TFT + help + Choose this option if you use 4.3" 480x272x32b LCD panel. + + config BOARD_USING_LCM_FW070TFT_WSVGA + bool "NuDesign TFT-LCD7-WSVGA" + select BSP_USING_VPOST + select LCM_USING_FW070TFT_WSVGA + help + Choose this option if you use 7" 1024x600x32b LCD panel. + endchoice + + choice + prompt "Select Touch devices." + + config BOARD_USING_ADCTOUCH + bool "ADC touching" + select BSP_USING_ADC_TOUCH + default y + help + Choose this option if you use internal ADC touching function. + + config BOARD_USING_GT911 + bool "GT911 TSC" + select BSP_USING_I2C + select BSP_USING_I2C0 + select PKG_USING_GT911 + help + Choose this option if you use GT911 external TSC touching function. + + endchoice + endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/nk-n9h30/board/board_dev.c b/bsp/nuvoton/nk-n9h30/board/board_dev.c index 42d1bdac94..7284ef5d58 100644 --- a/bsp/nuvoton/nk-n9h30/board/board_dev.c +++ b/bsp/nuvoton/nk-n9h30/board/board_dev.c @@ -173,6 +173,34 @@ int rt_hw_nau8822_port(void) INIT_COMPONENT_EXPORT(rt_hw_nau8822_port); #endif /* BOARD_USING_NAU8822 */ +//#if defined(BOARD_USING_GT911) && defined(PKG_USING_GT911) +#if defined(PKG_USING_GT911) +#include "drv_gpio.h" +#include "gt911.h" + +#define GT911_RST_PIN NU_GET_PININDEX(NU_PG, 4) +#define GT911_IRQ_PIN NU_GET_PININDEX(NU_PG, 5) + +extern int gt911_sample(const char *name, rt_uint16_t x, rt_uint16_t y); +int rt_hw_gt911_port(void) +{ + struct rt_touch_config cfg; + rt_uint8_t rst_pin; + + rst_pin = GT911_RST_PIN; + cfg.dev_name = "i2c0"; + cfg.irq_pin.pin = GT911_IRQ_PIN; + cfg.irq_pin.mode = PIN_MODE_INPUT_PULLDOWN; + cfg.user_data = &rst_pin; + + rt_hw_gt911_init("gt911", &cfg); + gt911_sample("gt911", BSP_LCD_WIDTH, BSP_LCD_HEIGHT); + + return 0; +} +INIT_ENV_EXPORT(rt_hw_gt911_port); +#endif /* if defined(BOARD_USING_GT911) && defined(PKG_USING_GT911) */ + #if defined(BOARD_USING_BUZZER) #define PWM_DEV_NAME "pwm0" @@ -227,10 +255,11 @@ static void PlayRingTone(void) #define LCM_BLEN NU_GET_PININDEX(NU_PH, 3) #endif -#define PWM_DEV_NAME "pwm0" -#define LCM_PWM_CHANNEL (0) +#define PWM_DEV_NAME "pwm0" +#define LCM_PWM_CHANNEL (0) +#define LCM_BACKLIGHT_CTRL NU_GET_PININDEX(NU_PH, 3) -static void LCMLightOn(void) +void nu_lcd_backlight_on(void) { struct rt_device_pwm *pwm_dev; @@ -243,10 +272,27 @@ static void LCMLightOn(void) { rt_kprintf("Can't find %s\n", PWM_DEV_NAME); } + + rt_pin_mode(LCM_BACKLIGHT_CTRL, PIN_MODE_OUTPUT); + rt_pin_write(LCM_BACKLIGHT_CTRL, PIN_HIGH); +} + +void nu_lcd_backlight_off(void) +{ + struct rt_device_pwm *pwm_dev; + + if ((pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME)) != RT_NULL) + { + rt_pwm_disable(pwm_dev, LCM_PWM_CHANNEL); + } + else + { + rt_kprintf("Can't find %s\n", PWM_DEV_NAME); + } + + rt_pin_mode(LCM_BACKLIGHT_CTRL, PIN_MODE_OUTPUT); + rt_pin_write(LCM_BACKLIGHT_CTRL, PIN_LOW); } -#ifdef FINSH_USING_MSH - MSH_CMD_EXPORT(LCMLightOn, LCM - light on panel); -#endif int rt_hw_lcm_port(void) { @@ -259,9 +305,6 @@ int rt_hw_lcm_port(void) } #endif - /* Use PWM to control backlight. */ - LCMLightOn(); - return 0; } INIT_COMPONENT_EXPORT(rt_hw_lcm_port); diff --git a/bsp/nuvoton/nk-n9h30/project.uvproj b/bsp/nuvoton/nk-n9h30/project.uvproj deleted file mode 100644 index f3ff2ed8d7..0000000000 --- a/bsp/nuvoton/nk-n9h30/project.uvproj +++ /dev/null @@ -1,1791 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\Objects\ - rtthread - 1 - 0 - 0 - 1 - 1 - .\Listings\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARM.DLL - -cAT91SAM9 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 6 - - - - - - - - - - - - - ..\libraries\nuc980\Script\NUC980xx61.ini - Segger\JLTAgdi.dll - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\n9h30\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\n9h30\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\n9h30\UsbHostLib\inc;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - .\linking_scripts\n9h30.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - board_dev.c - 1 - board\board_dev.c - - - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - rt_inputcapture.c - 1 - ..\..\..\components\drivers\misc\rt_inputcapture.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_usbd.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbd.c - - - - - drv_timer.c - 1 - ..\libraries\n9h30\rtt_port\drv_timer.c - - - - - drv_vpost.c - 1 - ..\libraries\n9h30\rtt_port\drv_vpost.c - - - - - drv_adc.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc.c - - - - - drv_can.c - 1 - ..\libraries\n9h30\rtt_port\drv_can.c - - - - - drv_pwm.c - 1 - ..\libraries\n9h30\rtt_port\drv_pwm.c - - - - - drv_systick.c - 1 - ..\libraries\n9h30\rtt_port\drv_systick.c - - - - - drv_common.c - 1 - ..\libraries\n9h30\rtt_port\drv_common.c - - - - - drv_jpegcodec.c - 1 - ..\libraries\n9h30\rtt_port\drv_jpegcodec.c - - - - - drv_usbhost.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbhost.c - - - - - drv_emac.c - 1 - ..\libraries\n9h30\rtt_port\drv_emac.c - - - - - drv_scuart.c - 1 - ..\libraries\n9h30\rtt_port\drv_scuart.c - - - - - drv_adc_touch.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc_touch.c - - - - - drv_qspi.c - 1 - ..\libraries\n9h30\rtt_port\drv_qspi.c - - - - - drv_sys.c - 1 - ..\libraries\n9h30\rtt_port\drv_sys.c - - - - - drv_gpio.c - 1 - ..\libraries\n9h30\rtt_port\drv_gpio.c - - - - - drv_etimer.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\n9h30\rtt_port\drv_wdt.c - - - - - drv_ge2d.c - 1 - ..\libraries\n9h30\rtt_port\drv_ge2d.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer_capture.c - - - - - drv_uart.c - 1 - ..\libraries\n9h30\rtt_port\drv_uart.c - - - - - drv_i2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2c.c - - - - - drv_sdh.c - 1 - ..\libraries\n9h30\rtt_port\drv_sdh.c - - - - - drv_rtc.c - 1 - ..\libraries\n9h30\rtt_port\drv_rtc.c - - - - - drv_crypto.c - 1 - ..\libraries\n9h30\rtt_port\drv_crypto.c - - - - - drv_softi2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_softi2c.c - - - - - drv_i2s.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2s.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - Libraries - - - nu_timer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_timer.c - - - - - nu_emac.c - 1 - ..\libraries\n9h30\Driver\Source\nu_emac.c - - - - - nu_sys.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sys.c - - - - - nu_gpio.c - 1 - ..\libraries\n9h30\Driver\Source\nu_gpio.c - - - - - nu_wwdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wwdt.c - - - - - nu_etimer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_etimer.c - - - - - nu_spi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_spi.c - - - - - nu_can.c - 1 - ..\libraries\n9h30\Driver\Source\nu_can.c - - - - - nu_wdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wdt.c - - - - - nu_fmi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_fmi.c - - - - - nu_lcd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_lcd.c - - - - - nu_sdh.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sdh.c - - - - - nu_usbd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_usbd.c - - - - - nu_cap.c - 1 - ..\libraries\n9h30\Driver\Source\nu_cap.c - - - - - nu_scuart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_scuart.c - - - - - nu_i2s.c - 1 - ..\libraries\n9h30\Driver\Source\nu_i2s.c - - - - - nu_rtc.c - 1 - ..\libraries\n9h30\Driver\Source\nu_rtc.c - - - - - nu_pwm.c - 1 - ..\libraries\n9h30\Driver\Source\nu_pwm.c - - - - - nu_crypto.c - 1 - ..\libraries\n9h30\Driver\Source\nu_crypto.c - - - - - nu_uart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_uart.c - - - - - LVGL-port - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - n9h30_usbhostlib - - - ehci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci.c - - - - - ohci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ohci.c - - - - - mem_alloc.c - 1 - ..\libraries\n9h30\UsbHostLib\src\mem_alloc.c - - - - - ehci_iso.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci_iso.c - - - - - support.c - 1 - ..\libraries\n9h30\UsbHostLib\src\support.c - - - - - usb_core.c - 1 - ..\libraries\n9h30\UsbHostLib\src\usb_core.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - SAL - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/nk-n9h30/project.uvprojx b/bsp/nuvoton/nk-n9h30/project.uvprojx deleted file mode 100644 index 6dc5488c5c..0000000000 --- a/bsp/nuvoton/nk-n9h30/project.uvprojx +++ /dev/null @@ -1,1783 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - 0 - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARM.DLL - -cAT91SAM9260 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - ARM926EJ-S - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x20000000 - 0x800000 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x100000 - 0x8000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x20800000 - 0x1800000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 0 - 0x300000 - 0x1000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\n9h30\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\n9h30\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\n9h30\UsbHostLib\inc;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - - .\linking_scripts\n9h30.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - board - - - board_dev.c - 1 - board\board_dev.c - - - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - rt_inputcapture.c - 1 - ..\..\..\components\drivers\misc\rt_inputcapture.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_common.c - 1 - ..\libraries\n9h30\rtt_port\drv_common.c - - - - - drv_can.c - 1 - ..\libraries\n9h30\rtt_port\drv_can.c - - - - - drv_emac.c - 1 - ..\libraries\n9h30\rtt_port\drv_emac.c - - - - - drv_timer.c - 1 - ..\libraries\n9h30\rtt_port\drv_timer.c - - - - - drv_pwm.c - 1 - ..\libraries\n9h30\rtt_port\drv_pwm.c - - - - - drv_usbd.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbd.c - - - - - drv_usbhost.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbhost.c - - - - - drv_crypto.c - 1 - ..\libraries\n9h30\rtt_port\drv_crypto.c - - - - - drv_systick.c - 1 - ..\libraries\n9h30\rtt_port\drv_systick.c - - - - - drv_gpio.c - 1 - ..\libraries\n9h30\rtt_port\drv_gpio.c - - - - - drv_scuart.c - 1 - ..\libraries\n9h30\rtt_port\drv_scuart.c - - - - - drv_etimer.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\n9h30\rtt_port\drv_wdt.c - - - - - drv_adc.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc.c - - - - - drv_qspi.c - 1 - ..\libraries\n9h30\rtt_port\drv_qspi.c - - - - - drv_i2s.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2s.c - - - - - drv_sdh.c - 1 - ..\libraries\n9h30\rtt_port\drv_sdh.c - - - - - drv_i2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2c.c - - - - - drv_softi2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_softi2c.c - - - - - drv_uart.c - 1 - ..\libraries\n9h30\rtt_port\drv_uart.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer_capture.c - - - - - drv_vpost.c - 1 - ..\libraries\n9h30\rtt_port\drv_vpost.c - - - - - drv_adc_touch.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc_touch.c - - - - - drv_rtc.c - 1 - ..\libraries\n9h30\rtt_port\drv_rtc.c - - - - - drv_sys.c - 1 - ..\libraries\n9h30\rtt_port\drv_sys.c - - - - - drv_jpegcodec.c - 1 - ..\libraries\n9h30\rtt_port\drv_jpegcodec.c - - - - - drv_ge2d.c - 1 - ..\libraries\n9h30\rtt_port\drv_ge2d.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - Libraries - - - nu_wwdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wwdt.c - - - - - nu_lcd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_lcd.c - - - - - nu_usbd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_usbd.c - - - - - nu_i2s.c - 1 - ..\libraries\n9h30\Driver\Source\nu_i2s.c - - - - - nu_rtc.c - 1 - ..\libraries\n9h30\Driver\Source\nu_rtc.c - - - - - nu_pwm.c - 1 - ..\libraries\n9h30\Driver\Source\nu_pwm.c - - - - - nu_emac.c - 1 - ..\libraries\n9h30\Driver\Source\nu_emac.c - - - - - nu_sys.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sys.c - - - - - nu_spi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_spi.c - - - - - nu_etimer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_etimer.c - - - - - nu_timer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_timer.c - - - - - nu_can.c - 1 - ..\libraries\n9h30\Driver\Source\nu_can.c - - - - - nu_fmi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_fmi.c - - - - - nu_gpio.c - 1 - ..\libraries\n9h30\Driver\Source\nu_gpio.c - - - - - nu_wdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wdt.c - - - - - nu_scuart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_scuart.c - - - - - nu_crypto.c - 1 - ..\libraries\n9h30\Driver\Source\nu_crypto.c - - - - - nu_uart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_uart.c - - - - - nu_sdh.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sdh.c - - - - - nu_cap.c - 1 - ..\libraries\n9h30\Driver\Source\nu_cap.c - - - - - LVGL-port - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - n9h30_usbhostlib - - - ohci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ohci.c - - - - - usb_core.c - 1 - ..\libraries\n9h30\UsbHostLib\src\usb_core.c - - - - - mem_alloc.c - 1 - ..\libraries\n9h30\UsbHostLib\src\mem_alloc.c - - - - - support.c - 1 - ..\libraries\n9h30\UsbHostLib\src\support.c - - - - - ehci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci_iso.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/nk-n9h30/rtconfig.h b/bsp/nuvoton/nk-n9h30/rtconfig.h deleted file mode 100644 index 1138f94322..0000000000 --- a/bsp/nuvoton/nk-n9h30/rtconfig.h +++ /dev/null @@ -1,422 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 16 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_MEMHEAP -#define RT_MEMHEAP_FAST_MODE -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_INTERRUPT_INFO -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_ARM9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 16 -#define DFS_FILESYSTEM_TYPES_MAX 16 -#define DFS_FD_MAX 64 -#define RT_USING_DFS_MNTTABLE -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_RTC -#define RT_USING_ALARM -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_USING_QSPI -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_TOUCH -#define RT_USING_INPUT_CAPTURE -#define RT_INPUT_CAPTURE_RB_SIZE 100 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_CDC -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_MSTORAGE -#define RT_VCOM_TASK_STK_SIZE 512 -#define RT_CDC_RX_BUFSIZE 128 -#define RT_VCOM_SERNO "32021919830108" -#define RT_VCOM_SER_LEN 14 -#define RT_VCOM_TX_TIMEOUT 1000 -#define RT_USB_MSTORAGE_DISK_NAME "ramdisk1" - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP202 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 32 -#define RT_LWIP_PBUF_NUM 256 -#define RT_LWIP_RAW_PCB_NUM 32 -#define RT_LWIP_UDP_PCB_NUM 32 -#define RT_LWIP_TCP_PCB_NUM 32 -#define RT_LWIP_TCP_SEG_NUM 256 -#define RT_LWIP_TCP_SND_BUF 32768 -#define RT_LWIP_TCP_WND 10240 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 32 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 32 -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define RT_LWIP_NETIF_LOOPBACK -#define LWIP_NETIF_LOOPBACK 1 -#define RT_LWIP_STATS -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - -#define PKG_USING_LVGL -#define PKG_USING_LVGL_V810 -#define PKG_LVGL_VER_NUM 0x08010 -#define PKG_USING_LV_MUSIC_DEMO - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define FAL_USING_SFUD_PORT -#define FAL_USING_NOR_FLASH_DEV_NAME "norflash0" -#define PKG_USING_FAL_LATEST_VERSION -#define PKG_FAL_VER_NUM 0x99999 -#define PKG_USING_RAMDISK -#define PKG_USING_RAMDISK_LATEST_VERSION - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_NAU8822 - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_N9H30 -#define BSP_USING_MMU -#define BSP_USING_GPIO -#define BSP_USING_EMAC -#define BSP_USING_EMAC0 -#define BSP_USING_EMAC1 -#define BSP_USING_RTC -#define BSP_USING_ADC -#define BSP_USING_ADC_TOUCH -#define BSP_USING_ETMR -#define BSP_USING_ETIMER -#define BSP_USING_ETIMER_CAPTURE -#define BSP_USING_ETMR0 -#define BSP_USING_ETIMER0 -#define BSP_USING_ETMR1 -#define BSP_USING_ETIMER1 -#define BSP_USING_ETMR2 -#define BSP_USING_ETIMER2_CAPTURE -#define BSP_USING_ETMR3 -#define BSP_USING_ETIMER3_CAPTURE -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TIMER0 -#define BSP_USING_TIMER1 -#define BSP_USING_TIMER2 -#define BSP_USING_TIMER3 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_I2C -#define BSP_USING_I2C0 -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define BSP_USING_SDH1 -#define NU_SDH_HOTPLUG -#define BSP_USING_CAN -#define BSP_USING_CAN0 -#define BSP_USING_PWM -#define BSP_USING_PWM0 -#define BSP_USING_QSPI -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI1_NONE -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 2048 -#define BSP_USING_WDT -#define BSP_USING_EBI -#define BSP_USING_VPOST -#define LCM_USING_FW070TFT -#define VPOST_USING_LCD_IDX 3 -#define BSP_LCD_BPP 32 -#define BSP_LCD_WIDTH 800 -#define BSP_LCD_HEIGHT 480 -#define BSP_USING_VPOST_OSD -#define BSP_USING_USBD -#define BSP_USING_USBH - -/* On-board Peripheral Drivers */ - -#define BSP_USING_CONSOLE -#define BOARD_USING_IP101GR -#define BOARD_USING_NAU8822 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_BUZZER -#define BOARD_USING_LCM -#define BOARD_USING_USB0_DEVICE_HOST -#define BOARD_USING_USB1_HOST - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/nk-rtu980/.config b/bsp/nuvoton/nk-rtu980/.config index 853e905aed..566468f589 100644 --- a/bsp/nuvoton/nk-rtu980/.config +++ b/bsp/nuvoton/nk-rtu980/.config @@ -974,3 +974,5 @@ CONFIG_BOARD_USING_USB0_DEVICE_HOST=y # Board extended module drivers # CONFIG_BOARD_USING_IP101GR=y +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk-rtu980.test.utest." diff --git a/bsp/nuvoton/nk-rtu980/Kconfig b/bsp/nuvoton/nk-rtu980/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/nk-rtu980/Kconfig +++ b/bsp/nuvoton/nk-rtu980/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-rtu980/board/Kconfig b/bsp/nuvoton/nk-rtu980/board/Kconfig index 2682f8b89f..04cc595e7a 100644 --- a/bsp/nuvoton/nk-rtu980/board/Kconfig +++ b/bsp/nuvoton/nk-rtu980/board/Kconfig @@ -44,5 +44,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/nk-rtu980/project.uvproj b/bsp/nuvoton/nk-rtu980/project.uvproj deleted file mode 100644 index 9c0d498aed..0000000000 --- a/bsp/nuvoton/nk-rtu980/project.uvproj +++ /dev/null @@ -1,1774 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\Objects\ - rtthread - 1 - 0 - 0 - 1 - 1 - .\Listings\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARM.DLL - -cAT91SAM9 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 0 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 6 - - - - - - - - - - - - - ..\libraries\nuc980\Script\NUC980xx61.ini - Segger\JLTAgdi.dll - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - board - - - board_dev.c - 1 - board\board_dev.c - - - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - DeviceDrivers - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - Libraries - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nuc980_usbhostlib - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/nk-rtu980/project.uvprojx b/bsp/nuvoton/nk-rtu980/project.uvprojx deleted file mode 100644 index bc477201f8..0000000000 --- a/bsp/nuvoton/nk-rtu980/project.uvprojx +++ /dev/null @@ -1,1766 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - 0 - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARM.DLL - -cAT91SAM9260 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - ARM926EJ-S - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x20000000 - 0x800000 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x100000 - 0x8000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x20800000 - 0x1800000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 0 - 0x300000 - 0x1000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - DeviceDrivers - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - Libraries - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nuc980_usbhostlib - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/nk-rtu980/rtconfig.h b/bsp/nuvoton/nk-rtu980/rtconfig.h deleted file mode 100644 index 6da5ab3233..0000000000 --- a/bsp/nuvoton/nk-rtu980/rtconfig.h +++ /dev/null @@ -1,431 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 16 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_MEMHEAP -#define RT_MEMHEAP_FAST_MODE -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_ARM9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 16 -#define DFS_FILESYSTEM_TYPES_MAX 16 -#define DFS_FD_MAX 64 -#define RT_USING_DFS_MNTTABLE -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_CAN_USING_HDR -#define RT_USING_HWTIMER -#define RT_USING_CPUTIME -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_USING_QSPI -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_CDC -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_MSTORAGE -#define RT_VCOM_TASK_STK_SIZE 2048 -#define RT_CDC_RX_BUFSIZE 128 -#define RT_VCOM_SERNO "32021919830108" -#define RT_VCOM_SER_LEN 14 -#define RT_VCOM_TX_TIMEOUT 1000 -#define RT_USB_MSTORAGE_DISK_NAME "ramdisk1" - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP212 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.31.55" -#define RT_LWIP_GWADDR "192.168.31.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 16 -#define RT_LWIP_PBUF_NUM 256 -#define RT_LWIP_RAW_PCB_NUM 16 -#define RT_LWIP_UDP_PCB_NUM 16 -#define RT_LWIP_TCP_PCB_NUM 16 -#define RT_LWIP_TCP_SEG_NUM 64 -#define RT_LWIP_TCP_SND_BUF 16384 -#define RT_LWIP_TCP_WND 65535 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 256 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 256 -#define RT_LWIP_REASSEMBLY_FRAG -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define RT_LWIP_NETIF_LOOPBACK -#define LWIP_NETIF_LOOPBACK 1 -#define RT_LWIP_STATS -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_NETUTILS -#define PKG_NETUTILS_TFTP -#define PKG_NETUTILS_IPERF -#define PKG_NETUTILS_NTP -#define NTP_USING_AUTO_SYNC -#define NTP_AUTO_SYNC_FIRST_DELAY 30 -#define NTP_AUTO_SYNC_PERIOD 3600 -#define NETUTILS_NTP_HOSTNAME "0.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME2 "1.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME3 "2.tw.pool.ntp.org" -#define PKG_USING_NETUTILS_V131 -#define PKG_NETUTILS_VER_NUM 0x10301 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define FAL_USING_SFUD_PORT -#define FAL_USING_NOR_FLASH_DEV_NAME "norflash0" -#define PKG_USING_FAL_LATEST_VERSION -#define PKG_FAL_VER_NUM 0x99999 -#define PKG_USING_RAMDISK -#define PKG_USING_RAMDISK_LATEST_VERSION - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define PKG_USING_OPTPARSE -#define PKG_USING_OPTPARSE_LATEST_VERSION - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_NUC980 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_MMU -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define BSP_USING_GPIO -#define BSP_USING_EMAC -#define BSP_USING_EMAC1 -#define NU_EMAC_PDMA_MEMCOPY -#define NU_EMAC_PDMA_MEMCOPY_THRESHOLD 128 -#define BSP_USING_ADC -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TIMER0 -#define BSP_USING_TMR1 -#define BSP_USING_TIMER1 -#define BSP_USING_TMR2 -#define BSP_USING_TIMER2 -#define BSP_USING_TMR3 -#define BSP_USING_TIMER3 -#define BSP_USING_TMR4 -#define BSP_USING_TIMER4 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART4 -#define BSP_USING_UART4_TX_DMA -#define BSP_USING_UART4_RX_DMA -#define BSP_USING_UART8 -#define BSP_USING_UART8_TX_DMA -#define BSP_USING_UART8_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C1 -#define BSP_USING_CAN -#define BSP_USING_CAN3 -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0 -#define BSP_USING_SPI0_PDMA -#define BSP_USING_SPI1_NONE -#define BSP_USING_QSPI -#define BSP_USING_QSPI_PDMA -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI0_PDMA -#define BSP_USING_CRYPTO -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_USBH - -/* On-board Peripheral Drivers */ - -#define BSP_USING_CONSOLE -#define BOARD_USING_UART8_RS485 -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_USB0_DEVICE_HOST - -/* Board extended module drivers */ - -#define BOARD_USING_IP101GR - -#endif diff --git a/bsp/nuvoton/numaker-iot-m487/.config b/bsp/nuvoton/numaker-iot-m487/.config index c10d9235f9..58d95746ed 100644 --- a/bsp/nuvoton/numaker-iot-m487/.config +++ b/bsp/nuvoton/numaker-iot-m487/.config @@ -973,3 +973,5 @@ CONFIG_BOARD_USING_HSUSBH_USBD=y # # CONFIG_BOARD_USING_MAX31875 is not set # CONFIG_BOARD_USING_LCD_ILI9341 is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-iot-m487.test.utest." diff --git a/bsp/nuvoton/numaker-iot-m487/Kconfig b/bsp/nuvoton/numaker-iot-m487/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/numaker-iot-m487/Kconfig +++ b/bsp/nuvoton/numaker-iot-m487/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-iot-m487/board/Kconfig b/bsp/nuvoton/numaker-iot-m487/board/Kconfig index 7b2fb2683a..0e81a45529 100644 --- a/bsp/nuvoton/numaker-iot-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-iot-m487/board/Kconfig @@ -129,5 +129,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/numaker-iot-m487/project.uvproj b/bsp/nuvoton/numaker-iot-m487/project.uvproj deleted file mode 100644 index b26994de86..0000000000 --- a/bsp/nuvoton/numaker-iot-m487/project.uvproj +++ /dev/null @@ -1,1814 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - - - M487JIDAE - Nuvoton - IRAM(0x20000000-0x20027FFF) IROM(0-0x7FFFF) CLOCK(192000000) CPUTYPE("Cortex-M4") FPU2 - - undefined - - 0 - - - - - - - - - - - SFD\Nuvoton\M481_v1.SFR - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil4\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil4\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 10 - - - - - - - - - - - - - - NULink\Nu_Link.dll - - - - - 1 - 0 - 0 - 1 - 1 - 4101 - - 0 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 8 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\components\net\at\include;..\..\..\components\net\at\at_socket;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\BMX055;..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver;..\libraries\nu_packages\BMX055\libraries\BMG160_driver;..\libraries\nu_packages\BMX055\libraries\BMM050_driver;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\drivers\sensors;..\..\..\components\drivers\include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - AT - - - at_socket.c - 1 - ..\..\..\components\net\at\at_socket\at_socket.c - - - - - at_utils.c - 1 - ..\..\..\components\net\at\src\at_utils.c - - - - - at_client.c - 1 - ..\..\..\components\net\at\src\at_client.c - - - - - at_cli.c - 1 - ..\..\..\components\net\at\src\at_cli.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - Libraries - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - m480_usbhostlib - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - nu_pkgs_bmx055 - - - bmg160.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMG160_driver\bmg160.c - - - - - bma2x2.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver\bma2x2.c - - - - - sensor_bmx055.c - 1 - ..\libraries\nu_packages\BMX055\sensor_bmx055.c - - - - - bmm050.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMM050_driver\bmm050.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - af_inet_at.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_at.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - Sensors - - - sensor_cmd.c - 1 - ..\..\..\components\drivers\sensors\sensor_cmd.c - - - - - sensor.c - 1 - ..\..\..\components\drivers\sensors\sensor.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/numaker-iot-m487/project.uvprojx b/bsp/nuvoton/numaker-iot-m487/project.uvprojx deleted file mode 100644 index bf9144d3c4..0000000000 --- a/bsp/nuvoton/numaker-iot-m487/project.uvprojx +++ /dev/null @@ -1,1809 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - 0 - - - M487JIDAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.5 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x28000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M481_AP_512 -FS00 -FL080000 -FP0($$Device:M487JIDAE$Flash\M481_AP_512.FLM)) - 0 - $$Device:M487JIDAE$Device\M480\Include\M480.h - - - - - - - - - - $$Device:M487JIDAE$SVD\Nuvoton\M481_v1.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4103 - - 1 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\components\net\at\include;..\..\..\components\net\at\at_socket;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\BMX055;..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver;..\libraries\nu_packages\BMX055\libraries\BMG160_driver;..\libraries\nu_packages\BMX055\libraries\BMM050_driver;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\drivers\sensors;..\..\..\components\drivers\include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - AT - - - at_client.c - 1 - ..\..\..\components\net\at\src\at_client.c - - - - - at_cli.c - 1 - ..\..\..\components\net\at\src\at_cli.c - - - - - at_utils.c - 1 - ..\..\..\components\net\at\src\at_utils.c - - - - - at_socket.c - 1 - ..\..\..\components\net\at\at_socket\at_socket.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - device.c - 1 - ..\..\..\src\device.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - Libraries - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - m480_usbhostlib - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - nu_pkgs_bmx055 - - - bmg160.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMG160_driver\bmg160.c - - - - - bma2x2.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver\bma2x2.c - - - - - sensor_bmx055.c - 1 - ..\libraries\nu_packages\BMX055\sensor_bmx055.c - - - - - bmm050.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMM050_driver\bmm050.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_at.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_at.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - Sensors - - - sensor_cmd.c - 1 - ..\..\..\components\drivers\sensors\sensor_cmd.c - - - - - sensor.c - 1 - ..\..\..\components\drivers\sensors\sensor.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-iot-m487/rtconfig.h b/bsp/nuvoton/numaker-iot-m487/rtconfig.h deleted file mode 100644 index 670d11e494..0000000000 --- a/bsp/nuvoton/numaker-iot-m487/rtconfig.h +++ /dev/null @@ -1,400 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 1024 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M4 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 2048 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 8 -#define DFS_FILESYSTEM_TYPES_MAX 4 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_SENSOR -#define RT_USING_SENSOR_CMD -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_DES -#define RT_HWCRYPTO_USING_DES_ECB -#define RT_HWCRYPTO_USING_DES_CBC -#define RT_HWCRYPTO_USING_3DES -#define RT_HWCRYPTO_USING_3DES_ECB -#define RT_HWCRYPTO_USING_3DES_CBC -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG -#define RT_HWCRYPTO_USING_CRC -#define RT_HWCRYPTO_USING_CRC_07 -#define RT_HWCRYPTO_USING_CRC_8005 -#define RT_HWCRYPTO_USING_CRC_1021 -#define RT_HWCRYPTO_USING_CRC_04C11DB7 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk/" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define _RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_AT -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - - -/* AT commands */ - -#define RT_USING_AT -#define AT_USING_CLIENT -#define AT_CLIENT_NUM_MAX 1 -#define AT_USING_SOCKET -#define AT_USING_CLI -#define AT_CMD_MAX_LEN 512 -#define AT_SW_VERSION_NUM 0x10301 - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_AT_DEVICE -#define AT_DEVICE_USING_ESP8266 -#define AT_DEVICE_ESP8266_INIT_ASYN -#define PKG_USING_AT_DEVICE_LATEST_VERSION -#define PKG_AT_DEVICE_VER_NUM 0x99999 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define PKG_USING_FAL_LATEST_VERSION -#define PKG_FAL_VER_NUM 0x99999 - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO -#define NU_PKG_USING_BMX055 -#define NU_PKG_USING_NAU88L25 - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M480 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_FMC -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_TMR -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART1_TX_DMA -#define BSP_USING_UART1_RX_DMA -#define BSP_USING_UART2 -#define BSP_USING_UART2_TX_DMA -#define BSP_USING_UART2_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C0 -#define BSP_USING_I2C1 -#define BSP_USING_I2C2 -#define BSP_USING_USCI -#define BSP_USING_UUART -#define BSP_USING_USCI0 -#define BSP_USING_UUART0 -#define BSP_USING_UUART0_TX_DMA -#define BSP_USING_UUART0_RX_DMA -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0_NONE -#define BSP_USING_SPI1 -#define BSP_USING_SPI1_PDMA -#define BSP_USING_SPI2 -#define BSP_USING_SPI3_NONE -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 2048 -#define BSP_USING_QSPI -#define BSP_USING_QSPI0 -#define BSP_USING_CRYPTO -#define BSP_USING_TRNG -#define BSP_USING_CRC -#define NU_CRC_USE_PDMA -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_HSUSBH -#define NU_USBHOST_HUB_POLLING_INTERVAL 100 - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME -#define BOARD_USING_ESP8266 -#define BOARD_USING_BMX055 -#define BOARD_USING_NAU88L25 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_HSUSBH_USBD - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/numaker-m032ki/.config b/bsp/nuvoton/numaker-m032ki/.config index acdfc2eb88..13bed80dd6 100644 --- a/bsp/nuvoton/numaker-m032ki/.config +++ b/bsp/nuvoton/numaker-m032ki/.config @@ -797,3 +797,5 @@ CONFIG_BSP_USING_NULINKME=y # Board extended module drivers # # CONFIG_BOARD_USING_STORAGE_SPIFLASH is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-m032ki.test.utest." diff --git a/bsp/nuvoton/numaker-m032ki/Kconfig b/bsp/nuvoton/numaker-m032ki/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/numaker-m032ki/Kconfig +++ b/bsp/nuvoton/numaker-m032ki/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-m032ki/board/Kconfig b/bsp/nuvoton/numaker-m032ki/board/Kconfig index a3f0437b7b..bc112e0583 100644 --- a/bsp/nuvoton/numaker-m032ki/board/Kconfig +++ b/bsp/nuvoton/numaker-m032ki/board/Kconfig @@ -24,4 +24,5 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/numaker-m032ki/project.uvprojx b/bsp/nuvoton/numaker-m032ki/project.uvprojx deleted file mode 100644 index dbefa40af7..0000000000 --- a/bsp/nuvoton/numaker-m032ki/project.uvprojx +++ /dev/null @@ -1,1228 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m031 - 0x4 - ARM-ADS - 5060750::V5.06 update 6 (build 750)::ARMCC - 5060750::V5.06 update 6 (build 750)::ARMCC - 0 - - - M032KIAAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.10 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x18000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M0") CLOCK(12000000) - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M031_AP_512 -FS00 -FL080000 -FP0($$Device:M032KIAAE$Flash\M031_AP_512.FLM)) - 0 - $$Device:M032KIAAE$Device\M031\Include\M031Series.h - - - - - - - - - - $$Device:M032KIAAE$SVD\Nuvoton\M031AE_v1.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 1 - fromelf --bin ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.bin" - fromelf --text -c ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.txt" - 0 - 0 - 0 - 0 - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - -pCM0 - SARMCM3.DLL - - TARMCM1.DLL - -pCM0 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4103 - - 1 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M0" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x18000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x18000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 5 - 3 - 0 - 0 - 0 - 1 - 0 - - - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m031\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m0;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\m031\Device\Nuvoton\M031\Include;..\libraries\m031\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m031\StdDriver\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel;..\..\..\examples\utest\testcases\utest - - - - 1 - 0 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m031_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m0\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m0\cpuport.c - - - - - DeviceDrivers - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - Drivers - - - system_M031Series.c - 1 - ..\libraries\m031\Device\Nuvoton\M031\Source\system_M031Series.c - - - - - startup_M031Series.s - 2 - ..\libraries\m031\Device\Nuvoton\M031\Source\ARM\startup_M031Series.s - - - - - drv_timer.c - 1 - ..\libraries\m031\rtt_port\drv_timer.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m031\rtt_port\drv_bpwm_capture.c - - - - - drv_pwm_capture.c - 1 - ..\libraries\m031\rtt_port\drv_pwm_capture.c - - - - - drv_ebi.c - 1 - ..\libraries\m031\rtt_port\drv_ebi.c - - - - - drv_adc.c - 1 - ..\libraries\m031\rtt_port\drv_adc.c - - - - - drv_common.c - 1 - ..\libraries\m031\rtt_port\drv_common.c - - - - - drv_uuart.c - 1 - ..\libraries\m031\rtt_port\drv_uuart.c - - - - - drv_wdt.c - 1 - ..\libraries\m031\rtt_port\drv_wdt.c - - - - - drv_uspi.c - 1 - ..\libraries\m031\rtt_port\drv_uspi.c - - - - - drv_qspi.c - 1 - ..\libraries\m031\rtt_port\drv_qspi.c - - - - - drv_spi.c - 1 - ..\libraries\m031\rtt_port\drv_spi.c - - - - - drv_fmc.c - 1 - ..\libraries\m031\rtt_port\drv_fmc.c - - - - - drv_crc.c - 1 - ..\libraries\m031\rtt_port\drv_crc.c - - - - - drv_i2c.c - 1 - ..\libraries\m031\rtt_port\drv_i2c.c - - - - - drv_gpio.c - 1 - ..\libraries\m031\rtt_port\drv_gpio.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m031\rtt_port\drv_timer_capture.c - - - - - drv_crypto.c - 1 - ..\libraries\m031\rtt_port\drv_crypto.c - - - - - drv_rtc.c - 1 - ..\libraries\m031\rtt_port\drv_rtc.c - - - - - drv_bpwm.c - 1 - ..\libraries\m031\rtt_port\drv_bpwm.c - - - - - drv_uart.c - 1 - ..\libraries\m031\rtt_port\drv_uart.c - - - - - drv_spii2s.c - 1 - ..\libraries\m031\rtt_port\drv_spii2s.c - - - - - drv_pdma.c - 1 - ..\libraries\m031\rtt_port\drv_pdma.c - - - - - drv_pwm.c - 1 - ..\libraries\m031\rtt_port\drv_pwm.c - - - - - drv_softi2c.c - 1 - ..\libraries\m031\rtt_port\drv_softi2c.c - - - - - drv_clk.c - 1 - ..\libraries\m031\rtt_port\drv_clk.c - - - - - drv_ui2c.c - 1 - ..\libraries\m031\rtt_port\drv_ui2c.c - - - - - drv_usbd.c - 1 - ..\libraries\m031\rtt_port\drv_usbd.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - Libraries - - - nu_ebi.c - 1 - ..\libraries\m031\StdDriver\src\nu_ebi.c - - - - - nu_adc.c - 1 - ..\libraries\m031\StdDriver\src\nu_adc.c - - - - - nu_clk.c - 1 - ..\libraries\m031\StdDriver\src\nu_clk.c - - - - - nu_uart.c - 1 - ..\libraries\m031\StdDriver\src\nu_uart.c - - - - - nu_usbd.c - 1 - ..\libraries\m031\StdDriver\src\nu_usbd.c - - - - - nu_pdma.c - 1 - ..\libraries\m031\StdDriver\src\nu_pdma.c - - - - - nu_i2c.c - 1 - ..\libraries\m031\StdDriver\src\nu_i2c.c - - - - - nu_spi.c - 1 - ..\libraries\m031\StdDriver\src\nu_spi.c - - - - - nu_wwdt.c - 1 - ..\libraries\m031\StdDriver\src\nu_wwdt.c - - - - - nu_pwm.c - 1 - ..\libraries\m031\StdDriver\src\nu_pwm.c - - - - - nu_rtc.c - 1 - ..\libraries\m031\StdDriver\src\nu_rtc.c - - - - - nu_bpwm.c - 1 - ..\libraries\m031\StdDriver\src\nu_bpwm.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m031\StdDriver\src\nu_usci_i2c.c - - - - - nu_gpio.c - 1 - ..\libraries\m031\StdDriver\src\nu_gpio.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m031\StdDriver\src\nu_usci_spi.c - - - - - nu_wdt.c - 1 - ..\libraries\m031\StdDriver\src\nu_wdt.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m031\StdDriver\src\nu_usci_uart.c - - - - - nu_sys.c - 1 - ..\libraries\m031\StdDriver\src\nu_sys.c - - - - - nu_qspi.c - 1 - ..\libraries\m031\StdDriver\src\nu_qspi.c - - - - - nu_timer.c - 1 - ..\libraries\m031\StdDriver\src\nu_timer.c - - - - - nu_acmp.c - 1 - ..\libraries\m031\StdDriver\src\nu_acmp.c - - - - - nu_fmc.c - 1 - ..\libraries\m031\StdDriver\src\nu_fmc.c - - - - - nu_crc.c - 1 - ..\libraries\m031\StdDriver\src\nu_crc.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - utestcases - - - mem_tc.c - 1 - ..\..\..\examples\utest\testcases\kernel\mem_tc.c - - - - - pass_tc.c - 1 - ..\..\..\examples\utest\testcases\utest\pass_tc.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-m032ki/rtconfig.h b/bsp/nuvoton/numaker-m032ki/rtconfig.h deleted file mode 100644 index f2184d36fa..0000000000 --- a/bsp/nuvoton/numaker-m032ki/rtconfig.h +++ /dev/null @@ -1,286 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 512 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 512 - -/* kservice optimization */ - -#define RT_DEBUG - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M0 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 -#define DFS_FD_MAX 16 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_HWTIMER -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_WDT - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - - -/* Network interface device */ - - -/* light weight TCP/IP stack */ - - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - -#define RT_USING_UTESTCASES - -/* Utest Self Testcase */ - -#define UTEST_SELF_PASS_TC - -/* Kernel Testcase */ - -#define UTEST_SMALL_MEM_TC - -/* Utest Serial Testcase */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M032 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 4 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_IO_RW -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_ADC -#define BSP_USING_ADC0 -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TIMER0 -#define BSP_USING_TMR1 -#define BSP_USING_TIMER1 -#define BSP_USING_TMR2 -#define BSP_USING_TIMER2 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART1_TX_DMA -#define BSP_USING_UART1_RX_DMA -#define BSP_USING_UART2 -#define BSP_USING_UART3 -#define BSP_USING_UART4 -#define BSP_USING_UART5 -#define BSP_USING_UART6 -#define BSP_USING_UART7 -#define BSP_USING_WDT -#define BSP_USING_USBD - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/numaker-m2354/.config b/bsp/nuvoton/numaker-m2354/.config index 0ff7f7a969..6aaea5e9ef 100644 --- a/bsp/nuvoton/numaker-m2354/.config +++ b/bsp/nuvoton/numaker-m2354/.config @@ -947,3 +947,5 @@ CONFIG_BOARD_USING_OTG=y # Board extended module drivers # CONFIG_BOARD_USING_SEGMENT_LCD=y +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-m2354.test.utest." diff --git a/bsp/nuvoton/numaker-m2354/Kconfig b/bsp/nuvoton/numaker-m2354/Kconfig index 90354447b3..b396340d12 100644 --- a/bsp/nuvoton/numaker-m2354/Kconfig +++ b/bsp/nuvoton/numaker-m2354/Kconfig @@ -9,7 +9,7 @@ config RTT_DIR string option env="RTT_ROOT" default "../../.." - + # you can change the RTT_ROOT default "../../.." to your rtthread_root, # example : default "F:/git_repositories/rt-thread" @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-m2354/board/Kconfig b/bsp/nuvoton/numaker-m2354/board/Kconfig index a3e751aa42..3c71934493 100644 --- a/bsp/nuvoton/numaker-m2354/board/Kconfig +++ b/bsp/nuvoton/numaker-m2354/board/Kconfig @@ -68,4 +68,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" + endmenu diff --git a/bsp/nuvoton/numaker-m2354/project.uvprojx b/bsp/nuvoton/numaker-m2354/project.uvprojx deleted file mode 100644 index c15ccbb19a..0000000000 --- a/bsp/nuvoton/numaker-m2354/project.uvprojx +++ /dev/null @@ -1,1768 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m2354 - 0x4 - ARM-ADS - 6100001::V6.10.1::.\ARMCLANG - 1 - - - M2354KJFAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.10 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x40000) IROM(0x00000000,0x100000) CPUTYPE("Cortex-M23") TZ CLOCK(12000000) ESEL ELITTLE - - - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M2354_AP_1M -FS00 -FL0100000 -FP0($$Device:M2354KJFAE$Flash\M2354_AP_1M.FLM)) - 0 - $$Device:M2354KJFAE$Device\M2354\Include\M2354.h - - - - - - - - - - $$Device:M2354KJFAE$SVD\Nuvoton\M2354.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 1 - fromelf --bin ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.bin" - fromelf --text -c ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.txt" - 0 - 0 - 0 - 0 - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - - - - - SARMV8M.DLL - -MPU - TCM.DLL - -pCM23 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4101 - - 1 - BIN\UL2V8M.DLL - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M23" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 0 - 1 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x40000 - - - 1 - 0x0 - 0x100000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x100000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x40000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 5 - 3 - 0 - 0 - 0 - 1 - 0 - - - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\components\net\at\include;..\..\..\components\net\at\at_socket;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m2354\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m23;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\m2354\Device\Nuvoton\M2354\Include;..\libraries\m2354\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m2354\StdDriver\inc;..\libraries\m2354\USBHostLib\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\SLCD;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\drivers\sensors;..\..\..\components\drivers\include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m2354_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - AT - - - at_socket.c - 1 - ..\..\..\components\net\at\at_socket\at_socket.c - - - - - at_cli.c - 1 - ..\..\..\components\net\at\src\at_cli.c - - - - - at_utils.c - 1 - ..\..\..\components\net\at\src\at_utils.c - - - - - at_client.c - 1 - ..\..\..\components\net\at\src\at_client.c - - - - - board - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m23\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m23\cpuport.c - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - -std=c99 - - - - - - - - - - Drivers - - - startup_M2354.s - 2 - ..\libraries\m2354\Device\Nuvoton\M2354\Source\ARM\startup_M2354.s - - - - - system_M2354.c - 1 - ..\libraries\m2354\Device\Nuvoton\M2354\Source\system_M2354.c - - - - - drv_crc.c - 1 - ..\libraries\m2354\rtt_port\drv_crc.c - - - - - drv_usbd.c - 1 - ..\libraries\m2354\rtt_port\drv_usbd.c - - - - - drv_ecap.c - 1 - ..\libraries\m2354\rtt_port\drv_ecap.c - - - - - drv_common.c - 1 - ..\libraries\m2354\rtt_port\drv_common.c - - - - - drv_eadc.c - 1 - ..\libraries\m2354\rtt_port\drv_eadc.c - - - - - drv_pdma.c - 1 - ..\libraries\m2354\rtt_port\drv_pdma.c - - - - - drv_qspi.c - 1 - ..\libraries\m2354\rtt_port\drv_qspi.c - - - - - drv_gpio.c - 1 - ..\libraries\m2354\rtt_port\drv_gpio.c - - - - - drv_tpwm.c - 1 - ..\libraries\m2354\rtt_port\drv_tpwm.c - - - - - drv_spi.c - 1 - ..\libraries\m2354\rtt_port\drv_spi.c - - - - - drv_wdt.c - 1 - ..\libraries\m2354\rtt_port\drv_wdt.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m2354\rtt_port\drv_bpwm_capture.c - - - - - drv_spii2s.c - 1 - ..\libraries\m2354\rtt_port\drv_spii2s.c - - - - - drv_bpwm.c - 1 - ..\libraries\m2354\rtt_port\drv_bpwm.c - - - - - drv_usbhost.c - 1 - ..\libraries\m2354\rtt_port\drv_usbhost.c - - - - - drv_epwm.c - 1 - ..\libraries\m2354\rtt_port\drv_epwm.c - - - - - drv_can.c - 1 - ..\libraries\m2354\rtt_port\drv_can.c - - - - - drv_sdh.c - 1 - ..\libraries\m2354\rtt_port\drv_sdh.c - - - - - drv_trng.c - 1 - ..\libraries\m2354\rtt_port\drv_trng.c - - - - - drv_timer.c - 1 - ..\libraries\m2354\rtt_port\drv_timer.c - - - - - drv_fmc.c - 1 - ..\libraries\m2354\rtt_port\drv_fmc.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m2354\rtt_port\drv_timer_capture.c - - - - - drv_softi2c.c - 1 - ..\libraries\m2354\rtt_port\drv_softi2c.c - - - - - drv_uspi.c - 1 - ..\libraries\m2354\rtt_port\drv_uspi.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m2354\rtt_port\drv_epwm_capture.c - - - - - drv_i2s.c - 1 - ..\libraries\m2354\rtt_port\drv_i2s.c - - - - - drv_uart.c - 1 - ..\libraries\m2354\rtt_port\drv_uart.c - - - - - drv_ebi.c - 1 - ..\libraries\m2354\rtt_port\drv_ebi.c - - - - - drv_clk.c - 1 - ..\libraries\m2354\rtt_port\drv_clk.c - - - - - drv_otg.c - 1 - ..\libraries\m2354\rtt_port\drv_otg.c - - - - - drv_i2c.c - 1 - ..\libraries\m2354\rtt_port\drv_i2c.c - - - - - drv_rtc.c - 1 - ..\libraries\m2354\rtt_port\drv_rtc.c - - - - - drv_scuart.c - 1 - ..\libraries\m2354\rtt_port\drv_scuart.c - - - - - drv_uuart.c - 1 - ..\libraries\m2354\rtt_port\drv_uuart.c - - - - - drv_crypto.c - 1 - ..\libraries\m2354\rtt_port\drv_crypto.c - - - - - drv_qei.c - 1 - ..\libraries\m2354\rtt_port\drv_qei.c - - - - - drv_slcd.c - 1 - ..\libraries\m2354\rtt_port\drv_slcd.c - - - - - drv_ui2c.c - 1 - ..\libraries\m2354\rtt_port\drv_ui2c.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - Libraries - - - nu_ewwdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ewwdt.c - - - - - nu_wwdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_wwdt.c - - - - - nu_usbd.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usbd.c - - - - - nu_crypto.c - 1 - ..\libraries\m2354\StdDriver\src\nu_crypto.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usci_i2c.c - - - - - nu_qspi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_qspi.c - - - - - nu_clk.c - 1 - ..\libraries\m2354\StdDriver\src\nu_clk.c - - - - - nu_lcd.c - 1 - ..\libraries\m2354\StdDriver\src\nu_lcd.c - - - - - nu_scuart.c - 1 - ..\libraries\m2354\StdDriver\src\nu_scuart.c - - - - - nu_sys.c - 1 - ..\libraries\m2354\StdDriver\src\nu_sys.c - - - - - nu_sc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_sc.c - - - - - nu_sdh.c - 1 - ..\libraries\m2354\StdDriver\src\nu_sdh.c - - - - - nu_spi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_spi.c - - - - - nu_ewdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ewdt.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usci_uart.c - - - - - nu_acmp.c - 1 - ..\libraries\m2354\StdDriver\src\nu_acmp.c - - - - - nu_wdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_wdt.c - - - - - nu_i2c.c - 1 - ..\libraries\m2354\StdDriver\src\nu_i2c.c - - - - - nu_fmc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_fmc.c - - - - - nu_dac.c - 1 - ..\libraries\m2354\StdDriver\src\nu_dac.c - - - - - nu_rtc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_rtc.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_timer_pwm.c - - - - - nu_uart.c - 1 - ..\libraries\m2354\StdDriver\src\nu_uart.c - - - - - nu_ecap.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ecap.c - - - - - nu_eadc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_eadc.c - - - - - nu_can.c - 1 - ..\libraries\m2354\StdDriver\src\nu_can.c - - - - - nu_epwm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_epwm.c - - - - - nu_bpwm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_bpwm.c - - - - - nu_dpm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_dpm.c - - - - - nu_pdma.c - 1 - ..\libraries\m2354\StdDriver\src\nu_pdma.c - - - - - nu_qei.c - 1 - ..\libraries\m2354\StdDriver\src\nu_qei.c - - - - - nu_timer.c - 1 - ..\libraries\m2354\StdDriver\src\nu_timer.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usci_spi.c - - - - - nu_ebi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ebi.c - - - - - nu_crc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_crc.c - - - - - nu_fvc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_fvc.c - - - - - nu_i2s.c - 1 - ..\libraries\m2354\StdDriver\src\nu_i2s.c - - - - - nu_rng.c - 1 - ..\libraries\m2354\StdDriver\src\nu_rng.c - - - - - nu_gpio.c - 1 - ..\libraries\m2354\StdDriver\src\nu_gpio.c - - - - - nu_keystore.c - 1 - ..\libraries\m2354\StdDriver\src\nu_keystore.c - - - - - nu_tamper.c - 1 - ..\libraries\m2354\StdDriver\src\nu_tamper.c - - - - - m2354_usbhostlib - - - mem_alloc.c - 1 - ..\libraries\m2354\USBHostLib\src\mem_alloc.c - - - - - ohci.c - 1 - ..\libraries\m2354\USBHostLib\src\ohci.c - - - - - usb_core.c - 1 - ..\libraries\m2354\USBHostLib\src\usb_core.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_slcd - - - slcd_rhe6616tp01.c - 1 - ..\libraries\nu_packages\SLCD\slcd_rhe6616tp01.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - rt_usbh - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_at.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_at.c - - - - - Sensors - - - sensor_cmd.c - 1 - ..\..\..\components\drivers\sensors\sensor_cmd.c - - - - - sensor.c - 1 - ..\..\..\components\drivers\sensors\sensor.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-m2354/rtconfig.h b/bsp/nuvoton/numaker-m2354/rtconfig.h deleted file mode 100644 index 81c3909d82..0000000000 --- a/bsp/nuvoton/numaker-m2354/rtconfig.h +++ /dev/null @@ -1,383 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 4 -#define DFS_FILESYSTEM_TYPES_MAX 4 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 2 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_USING_QSPI -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_DEBUG_SFUD -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_SENSOR -#define RT_USING_SENSOR_CMD -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_DES -#define RT_HWCRYPTO_USING_DES_ECB -#define RT_HWCRYPTO_USING_DES_CBC -#define RT_HWCRYPTO_USING_3DES -#define RT_HWCRYPTO_USING_3DES_ECB -#define RT_HWCRYPTO_USING_3DES_CBC -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG -#define RT_HWCRYPTO_USING_CRC -#define RT_HWCRYPTO_USING_CRC_07 -#define RT_HWCRYPTO_USING_CRC_8005 -#define RT_HWCRYPTO_USING_CRC_1021 -#define RT_HWCRYPTO_USING_CRC_04C11DB7 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define _RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_AT -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - - -/* AT commands */ - -#define RT_USING_AT -#define AT_USING_CLIENT -#define AT_CLIENT_NUM_MAX 1 -#define AT_USING_SOCKET -#define AT_USING_CLI -#define AT_CMD_MAX_LEN 2048 -#define AT_SW_VERSION_NUM 0x10301 - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_AT_DEVICE -#define AT_DEVICE_USING_ESP8266 -#define AT_DEVICE_ESP8266_INIT_ASYN -#define PKG_USING_AT_DEVICE_LATEST_VERSION -#define PKG_AT_DEVICE_VER_NUM 0x99999 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define PKG_USING_FAL_V00500 -#define PKG_FAL_VER_NUM 0x00500 - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M2354 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_FMC -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_EADC -#define BSP_USING_EADC0 -#define BSP_USING_TMR -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART4 -#define BSP_USING_UART4_TX_DMA -#define BSP_USING_UART4_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C1 -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define NU_SDH_MOUNT_ON_ROOT -#define BSP_USING_SPI -#define BSP_USING_SPI0 -#define BSP_USING_SPI1 -#define BSP_USING_SPI2_NONE -#define BSP_USING_SPI3_NONE -#define BSP_USING_CRYPTO -#define BSP_USING_TRNG -#define BSP_USING_CRC -#define NU_CRC_USE_PDMA -#define BSP_USING_WDT -#define BSP_USING_SLCD -#define BSP_USING_USBD -#define BSP_USING_USBH -#define NU_USBHOST_HUB_POLLING_INTERVAL 100 -#define BSP_USING_OTG - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME -#define BOARD_USING_ESP8266 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_OTG - -/* Board extended module drivers */ - -#define BOARD_USING_SEGMENT_LCD - -#endif diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index d0bd4b04bf..a9899d212f 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -975,3 +975,5 @@ CONFIG_BOARD_USING_HSUSBH_USBD=y # Board extended module drivers # # CONFIG_BOARD_USING_ADVANCE_V4 is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-pfm-m487.test.utest." diff --git a/bsp/nuvoton/numaker-pfm-m487/Kconfig b/bsp/nuvoton/numaker-pfm-m487/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/numaker-pfm-m487/Kconfig +++ b/bsp/nuvoton/numaker-pfm-m487/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig index fc56305c9d..a4f4e0c69a 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig @@ -162,4 +162,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" + endmenu diff --git a/bsp/nuvoton/numaker-pfm-m487/project.uvproj b/bsp/nuvoton/numaker-pfm-m487/project.uvproj deleted file mode 100644 index 9e8d850de2..0000000000 --- a/bsp/nuvoton/numaker-pfm-m487/project.uvproj +++ /dev/null @@ -1,1966 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - - - M487JIDAE - Nuvoton - IRAM(0x20000000-0x20027FFF) IROM(0-0x7FFFF) CLOCK(192000000) CPUTYPE("Cortex-M4") FPU2 - - undefined - - 0 - - - - - - - - - - - SFD\Nuvoton\M481_v1.SFR - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil4\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil4\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 10 - - - - - - - - - - - - - - NULink\Nu_Link.dll - - - - - 1 - 0 - 0 - 1 - 1 - 4101 - - 0 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 8 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - Compiler - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - Libraries - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - m480_usbhostlib - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/numaker-pfm-m487/project.uvprojx b/bsp/nuvoton/numaker-pfm-m487/project.uvprojx deleted file mode 100644 index 0050c2f13a..0000000000 --- a/bsp/nuvoton/numaker-pfm-m487/project.uvprojx +++ /dev/null @@ -1,1961 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - 0 - - - M487JIDAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.5 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x28000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M481_AP_512 -FS00 -FL080000 -FP0($$Device:M487JIDAE$Flash\M481_AP_512.FLM)) - 0 - $$Device:M487JIDAE$Device\M480\Include\M480.h - - - - - - - - - - $$Device:M487JIDAE$SVD\Nuvoton\M481_v1.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4103 - - 1 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - Libraries - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - m480_usbhostlib - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-pfm-m487/rtconfig.h b/bsp/nuvoton/numaker-pfm-m487/rtconfig.h deleted file mode 100644 index 4f9e169ee4..0000000000 --- a/bsp/nuvoton/numaker-pfm-m487/rtconfig.h +++ /dev/null @@ -1,413 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 1024 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M4 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 2048 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 8 -#define DFS_FILESYSTEM_TYPES_MAX 4 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 128 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_DES -#define RT_HWCRYPTO_USING_DES_ECB -#define RT_HWCRYPTO_USING_DES_CBC -#define RT_HWCRYPTO_USING_3DES -#define RT_HWCRYPTO_USING_3DES_ECB -#define RT_HWCRYPTO_USING_3DES_CBC -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG -#define RT_HWCRYPTO_USING_CRC -#define RT_HWCRYPTO_USING_CRC_07 -#define RT_HWCRYPTO_USING_CRC_8005 -#define RT_HWCRYPTO_USING_CRC_1021 -#define RT_HWCRYPTO_USING_CRC_04C11DB7 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk/" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define _RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_SOCKETS_NUM 16 - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP202 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 8 -#define RT_LWIP_PBUF_NUM 16 -#define RT_LWIP_RAW_PCB_NUM 4 -#define RT_LWIP_UDP_PCB_NUM 4 -#define RT_LWIP_TCP_PCB_NUM 4 -#define RT_LWIP_TCP_SEG_NUM 40 -#define RT_LWIP_TCP_SND_BUF 8196 -#define RT_LWIP_TCP_WND 8196 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 -#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define LWIP_NETIF_LOOPBACK 0 -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define PKG_USING_FAL_V00400 -#define PKG_FAL_VER_NUM 0x00400 - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO -#define NU_PKG_USING_NAU88L25 - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M480 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_FMC -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_EMAC -#define NU_EMAC_PDMA_MEMCOPY -#define NU_EMAC_PDMA_MEMCOPY_THRESHOLD 128 -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_TMR -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_I2C -#define BSP_USING_I2C1 -#define BSP_USING_I2C2 -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0_NONE -#define BSP_USING_SPI1_NONE -#define BSP_USING_SPI2_NONE -#define BSP_USING_SPI3 -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 2048 -#define BSP_USING_QSPI -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI0_PDMA -#define BSP_USING_CRYPTO -#define BSP_USING_TRNG -#define BSP_USING_CRC -#define NU_CRC_USE_PDMA -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_HSUSBH -#define NU_USBHOST_HUB_POLLING_INTERVAL 100 - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME -#define BOARD_USING_IP101GR -#define BOARD_USING_NAU88L25 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_HSUSBH_USBD - -/* Board extended module drivers */ - - -#endif From f28619fde66732fcfba77ad9613fe1cacbe2da0f Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Mon, 10 Jan 2022 15:53:24 +0800 Subject: [PATCH 06/65] Update menu-option. 1. Set BOARD_USING_LCM is on by default. 2. Fix default value setting in choice-option. --- bsp/nuvoton/nk-n9h30/.config | 1 + bsp/nuvoton/nk-n9h30/board/Kconfig | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/bsp/nuvoton/nk-n9h30/.config b/bsp/nuvoton/nk-n9h30/.config index f3e8600372..5fc517cbdb 100644 --- a/bsp/nuvoton/nk-n9h30/.config +++ b/bsp/nuvoton/nk-n9h30/.config @@ -941,6 +941,7 @@ CONFIG_BOARD_USING_USB1_HOST=y # # Board extended module drivers # +CONFIG_BOARD_USING_LCM=y CONFIG_BOARD_USING_LCM_FW070TFT_WVGA=y # CONFIG_BOARD_USING_LCM_FW043TFT_HVGA is not set # CONFIG_BOARD_USING_LCM_FW070TFT_WSVGA is not set diff --git a/bsp/nuvoton/nk-n9h30/board/Kconfig b/bsp/nuvoton/nk-n9h30/board/Kconfig index 293dedbbc9..379add6d0b 100644 --- a/bsp/nuvoton/nk-n9h30/board/Kconfig +++ b/bsp/nuvoton/nk-n9h30/board/Kconfig @@ -63,14 +63,20 @@ menu "Hardware Drivers Config" menu "Board extended module drivers" - choice - prompt "Select LCD panel devices.(Over VPOST)" + config BOARD_USING_LCM + bool "Use LCD panel." + default y + + if BOARD_USING_LCM + + choice + prompt "Select LCD panel devices.(Over VPOST)" + default BOARD_USING_LCM_FW070TFT_WVGA config BOARD_USING_LCM_FW070TFT_WVGA bool "NuDesign TFT-LCD7-WVGA" select BSP_USING_VPOST select LCM_USING_FW070TFT - default y help Choose this option if you use 7" 800x480x32b LCD panel. @@ -87,15 +93,15 @@ menu "Hardware Drivers Config" select LCM_USING_FW070TFT_WSVGA help Choose this option if you use 7" 1024x600x32b LCD panel. - endchoice + endchoice - choice - prompt "Select Touch devices." + choice + prompt "Select Touch devices." + default BOARD_USING_ADCTOUCH config BOARD_USING_ADCTOUCH bool "ADC touching" select BSP_USING_ADC_TOUCH - default y help Choose this option if you use internal ADC touching function. @@ -106,9 +112,10 @@ menu "Hardware Drivers Config" select PKG_USING_GT911 help Choose this option if you use GT911 external TSC touching function. + endchoice - endchoice - + endif + endmenu source "$BSP_DIR/../libraries/nu_packages/Kconfig" From 0b99eee439f2402ca89b97703f73cac2f590089a Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Tue, 11 Jan 2022 10:58:37 +0800 Subject: [PATCH 07/65] Fix control function in I2C driver. --- bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c | 2 +- bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c | 2 +- bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c | 2 +- bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h | 4 ++++ bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c | 2 +- bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c | 7 +++---- bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c | 2 +- bsp/nuvoton/nk-n9h30/board/board_dev.c | 3 +-- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c index e507ca6cbe..7487414dec 100644 --- a/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c @@ -90,7 +90,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c index fbc38e6e2a..30bffc49bf 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c @@ -99,7 +99,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c index d1f71407ac..b7082d1ae4 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c @@ -99,7 +99,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h index 4f24a2d10d..898c181eb5 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h @@ -770,4 +770,8 @@ void UART_SetLineConfig(UART_T *uart, uint32_t u32baudrate, uint32_t u32data_wid /*@}*/ /* end of group N9H30_Device_Driver */ +#ifdef __cplusplus +} +#endif + #endif diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c index 4fd7f335cc..987f8b3fd5 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c @@ -516,7 +516,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 psNuI2cBus = (nu_i2c_bus_t) bus; psNuI2cDev = &psNuI2cBus->dev; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: nu_i2c_set_speed(psNuI2cDev, (int32_t)u32Value); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c index bf5498c8a4..0f5f1e23a3 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c @@ -49,10 +49,6 @@ typedef struct nu_vpost *nu_vpost_t; static volatile uint32_t g_u32VSyncBlank = 0; static struct rt_completion vsync_wq; -RT_WEAK void nu_lcd_backlight_on(void) { } - -RT_WEAK void nu_lcd_backlight_off(void) { } - static struct nu_vpost nu_fbdev[eVpost_Cnt] = { { @@ -73,6 +69,9 @@ static struct nu_vpost nu_fbdev[eVpost_Cnt] = #endif }; +RT_WEAK void nu_lcd_backlight_on(void) { } + +RT_WEAK void nu_lcd_backlight_off(void) { } static rt_err_t vpost_layer_open(rt_device_t dev, rt_uint16_t oflag) { nu_vpost_t psVpost = (nu_vpost_t)dev; diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c index 423740dfc0..89e80b662f 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c @@ -118,7 +118,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/nk-n9h30/board/board_dev.c b/bsp/nuvoton/nk-n9h30/board/board_dev.c index 7284ef5d58..ba21df17dd 100644 --- a/bsp/nuvoton/nk-n9h30/board/board_dev.c +++ b/bsp/nuvoton/nk-n9h30/board/board_dev.c @@ -252,12 +252,11 @@ static void PlayRingTone(void) #include /* defined the LCM_BLEN pin: PH3 */ - #define LCM_BLEN NU_GET_PININDEX(NU_PH, 3) + #define LCM_BACKLIGHT_CTRL NU_GET_PININDEX(NU_PH, 3) #endif #define PWM_DEV_NAME "pwm0" #define LCM_PWM_CHANNEL (0) -#define LCM_BACKLIGHT_CTRL NU_GET_PININDEX(NU_PH, 3) void nu_lcd_backlight_on(void) { From eaf54ca571d5141dcc06b1fdc4dc4240c8e13607 Mon Sep 17 00:00:00 2001 From: Rbb666 Date: Fri, 24 Dec 2021 11:01:53 +0800 Subject: [PATCH 08/65] Refresh using dma2d,screen refresh average 25fps --- .../libraries/HAL_Drivers/drv_lcd_mipi.c | 14 +- .../applications/lvgl/lv_conf.h | 2 +- .../applications/lvgl/lv_demo.c | 26 ++- .../applications/lvgl/lv_port_disp.c | 172 ++++++------------ 4 files changed, 78 insertions(+), 136 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_lcd_mipi.c b/bsp/stm32/libraries/HAL_Drivers/drv_lcd_mipi.c index 275a18e925..e3bb847c5c 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_lcd_mipi.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_lcd_mipi.c @@ -23,7 +23,7 @@ struct stm32_lcd struct rt_device parent; struct rt_device_graphic_info info; }; -static struct stm32_lcd lcd; +struct stm32_lcd lcd; extern void stm32_mipi_lcd_init(void); extern void stm32_mipi_lcd_config(rt_uint32_t pixel_format); @@ -76,7 +76,7 @@ rt_err_t ltdc_init(void) HAL_DSI_Init(&hdsi, &dsi_pll); hdsi_video.VirtualChannelID = 0; - hdsi_video.ColorCoding = DSI_RGB888; + hdsi_video.ColorCoding = DSI_RGB565; hdsi_video.VSPolarity = DSI_VSYNC_ACTIVE_HIGH; hdsi_video.HSPolarity = DSI_HSYNC_ACTIVE_HIGH; hdsi_video.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH; @@ -130,7 +130,7 @@ rt_err_t ltdc_init(void) HAL_DSI_Start(&(hdsi)); - stm32_mipi_lcd_config(RTGRAPHIC_PIXEL_FORMAT_ARGB888); + stm32_mipi_lcd_config(RTGRAPHIC_PIXEL_FORMAT_RGB565); return RT_EOK; } @@ -143,7 +143,7 @@ void ltdc_layer_init(uint16_t index, uint32_t framebuffer) layer_cfg.WindowX1 = LCD_WIDTH; layer_cfg.WindowY0 = 0; layer_cfg.WindowY1 = LCD_HEIGHT; - layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888; + layer_cfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA; layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA; layer_cfg.Alpha = 255; @@ -169,9 +169,9 @@ static rt_err_t stm32_lcd_init(rt_device_t device) { lcd.info.width = LCD_WIDTH; lcd.info.height = LCD_HEIGHT; - lcd.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_ARGB888; - lcd.info.bits_per_pixel = 32; - lcd.info.framebuffer = (void *)rt_malloc_align(LCD_WIDTH * LCD_HEIGHT * (lcd.info.bits_per_pixel / 8), 32); + lcd.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; + lcd.info.bits_per_pixel = 16; + lcd.info.framebuffer = (void *)rt_malloc_align(LCD_WIDTH * LCD_HEIGHT * (lcd.info.bits_per_pixel / 8), 32);; memset(lcd.info.framebuffer, 0, LCD_WIDTH * LCD_HEIGHT * (lcd.info.bits_per_pixel / 8)); ltdc_init(); ltdc_layer_init(0, (uint32_t)lcd.info.framebuffer); diff --git a/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_conf.h b/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_conf.h index a657bd6a47..7f3d0ad633 100644 --- a/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_conf.h +++ b/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_conf.h @@ -12,7 +12,7 @@ #define LV_CONF_H #define LV_USE_PERF_MONITOR 1 -#define LV_COLOR_DEPTH 32 +#define LV_COLOR_DEPTH 16 #define LV_USE_GPU_STM32_DMA2D 1 #define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32f469xx.h" diff --git a/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_demo.c b/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_demo.c index 17d01e09cc..0026e0c06b 100644 --- a/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_demo.c +++ b/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_demo.c @@ -15,14 +15,17 @@ #include #ifndef LV_THREAD_STACK_SIZE -#define LV_THREAD_STACK_SIZE 4096 + #define LV_THREAD_STACK_SIZE 4096 #endif #ifndef LV_THREAD_PRIO -#define LV_THREAD_PRIO (RT_THREAD_PRIORITY_MAX*2/3) + #define LV_THREAD_PRIO (RT_THREAD_PRIORITY_MAX * 2 / 8) #endif -static void lvgl_thread(void *parameter) +static struct rt_thread lvgl_thread; +static rt_uint8_t lvgl_thread_stack[LV_THREAD_STACK_SIZE]; + +static void lvgl_entry(void *parameter) { extern void lv_demo_music(void); lv_demo_music(); @@ -30,7 +33,7 @@ static void lvgl_thread(void *parameter) while(1) { lv_task_handler(); - rt_thread_mdelay(1); + rt_thread_mdelay(5); } } @@ -38,12 +41,15 @@ static int lvgl_demo_init(void) { rt_thread_t tid; - tid = rt_thread_create("LVGL", lvgl_thread, RT_NULL, LV_THREAD_STACK_SIZE, LV_THREAD_PRIO, 10); - if(tid == RT_NULL) - { - LOG_E("Fail to create 'LVGL' thread"); - } - rt_thread_startup(tid); + rt_thread_init(&lvgl_thread, + "LVGL", + lvgl_entry, + RT_NULL, + &lvgl_thread_stack[0], + sizeof(lvgl_thread_stack), + LV_THREAD_PRIO, + 10); + rt_thread_startup(&lvgl_thread); return 0; } diff --git a/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_port_disp.c b/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_port_disp.c index 2bc5743edf..6660e08b50 100644 --- a/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_port_disp.c +++ b/bsp/stm32/stm32f469-st-disco/applications/lvgl/lv_port_disp.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2021-10-18 Meco Man The first version + * 2021-12-24 Rb Refresh using dma2d */ #include #include @@ -22,133 +23,79 @@ static struct rt_device_graphic_info info; static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ -static DMA_HandleTypeDef DmaHandle; -#define DMA_STREAM DMA2_Stream0 -#define DMA_CHANNEL DMA_CHANNEL_0 -#define DMA_STREAM_IRQ DMA2_Stream0_IRQn -#define DMA_STREAM_IRQHANDLER DMA2_Stream0_IRQHandler +#define DISP_BUF_SIZE (LV_HOR_RES_MAX * LV_VER_RES_MAX / 4) -static int32_t x1_flush; -static int32_t y1_flush; -static int32_t x2_flush; -static int32_t y2_fill; -static int32_t y_fill_act; -static const lv_color_t * buf_to_flush; - -static void DMA_TransferComplete(DMA_HandleTypeDef *han) -{ - y_fill_act ++; - - if(y_fill_act > y2_fill) - { - lv_disp_flush_ready(&disp_drv); - } - else - { - buf_to_flush += (x2_flush - x1_flush + 1); - - if (HAL_DMA_Start_IT(han,(uint32_t)buf_to_flush, - (uint32_t)&((uint32_t *)info.framebuffer)[y_fill_act * info.width + x1_flush], - (x2_flush - x1_flush + 1)) != HAL_OK) - { - LOG_E("HAL_DMA_Start_IT error"); - RT_ASSERT(0); - } - } -} - -static void DMA_TransferError(DMA_HandleTypeDef *han) -{ - LOG_E("DMA_TransferError"); - RT_ASSERT(0); -} - -void DMA_STREAM_IRQHANDLER(void) -{ - rt_interrupt_enter(); - - HAL_DMA_IRQHandler(&DmaHandle); - - rt_interrupt_leave(); -} +static lv_disp_drv_t g_disp_drv; +extern LTDC_HandleTypeDef hltdc; +volatile rt_bool_t g_gpu_state = RT_FALSE; static void lvgl_dma_config(void) { - /*## -1- Enable DMA2 clock #################################################*/ - __HAL_RCC_DMA2_CLK_ENABLE(); - - /*##-2- Select the DMA functional Parameters ###############################*/ - DmaHandle.Init.Channel = DMA_CHANNEL; /* DMA_CHANNEL_0 */ - DmaHandle.Init.Direction = DMA_MEMORY_TO_MEMORY; /* M2M transfer mode */ - DmaHandle.Init.PeriphInc = DMA_PINC_ENABLE; /* Peripheral increment mode Enable */ - DmaHandle.Init.MemInc = DMA_MINC_ENABLE; /* Memory increment mode Enable */ - DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; /* Peripheral data alignment : 32bit */ - DmaHandle.Init.MemDataAlignment = DMA_PDATAALIGN_WORD; /* memory data alignment : 32bit */ - DmaHandle.Init.Mode = DMA_NORMAL; /* Normal DMA mode */ - DmaHandle.Init.Priority = DMA_PRIORITY_HIGH; /* priority level : high */ - DmaHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE; /* FIFO mode enabled */ - DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; /* FIFO threshold: 1/4 full */ - DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE; /* Memory burst */ - DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Peripheral burst */ - - DmaHandle.Instance = DMA_STREAM; - - if (HAL_DMA_Init(&DmaHandle) != HAL_OK) - { - LOG_E("HAL_DMA_Init error"); - RT_ASSERT(0); - } - - HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_CPLT_CB_ID, DMA_TransferComplete); - HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_ERROR_CB_ID, DMA_TransferError); - - HAL_NVIC_SetPriority(DMA_STREAM_IRQ, 0, 0); - HAL_NVIC_EnableIRQ(DMA_STREAM_IRQ); + HAL_NVIC_SetPriority(DMA2D_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2D_IRQn); + __HAL_RCC_DMA2D_CLK_ENABLE(); } static void lcd_fb_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - /*Return if the area is out the screen*/ - if (area->x2 < 0) return; - if (area->y2 < 0) return; - if (area->x1 > info.width - 1) return; - if (area->y1 > info.height - 1) return; + uint32_t OffLineSrc = LV_HOR_RES_MAX - (area->x2 - area->x1 + 1); + uint32_t addr = (uint32_t) hltdc.LayerCfg[0].FBStartAdress + 2 * (LV_HOR_RES_MAX * area->y1 + area->x1); - /*Truncate the area to the screen*/ - int32_t act_x1 = area->x1 < 0 ? 0 : area->x1; - int32_t act_y1 = area->y1 < 0 ? 0 : area->y1; - int32_t act_x2 = area->x2 > info.width - 1 ? info.width - 1 : area->x2; - int32_t act_y2 = area->y2 > info.height - 1 ? info.height - 1 : area->y2; + DMA2D->CR = 0x00000000UL | (1 << 9); + DMA2D->FGMAR = (uint32_t) (uint16_t*) (color_p); + DMA2D->OMAR = (uint32_t) addr; - x1_flush = act_x1; - y1_flush = act_y1; - x2_flush = act_x2; - y2_fill = act_y2; - y_fill_act = act_y1; - buf_to_flush = color_p; + DMA2D->FGOR = 0; + DMA2D->OOR = OffLineSrc; - if (HAL_DMA_Start_IT(&DmaHandle,(uint32_t)buf_to_flush, - (uint32_t)&((uint32_t *)info.framebuffer)[y_fill_act * info.width + x1_flush], - (x2_flush - x1_flush + 1)) != HAL_OK) + DMA2D->FGPFCCR = DMA2D_OUTPUT_RGB565; + DMA2D->OPFCCR = DMA2D_OUTPUT_RGB565; + + DMA2D->NLR = (area->y2 - area->y1 + 1) | ((area->x2 - area->x1 + 1) << 16); + DMA2D->CR |= DMA2D_IT_TC | DMA2D_IT_TE | DMA2D_IT_CE; + DMA2D->CR |= DMA2D_CR_START; + + g_gpu_state = RT_TRUE; +} + +void DMA2D_IRQHandler(void) +{ + rt_interrupt_enter(); + + if ((DMA2D->ISR & DMA2D_FLAG_TC) != 0U) { - LOG_E("HAL_DMA_Start_IT error"); - RT_ASSERT(0); + if ((DMA2D->CR & DMA2D_IT_TC) != 0U) + { + + DMA2D->CR &= ~DMA2D_IT_TC; + DMA2D->IFCR = DMA2D_FLAG_TC; + + if (g_gpu_state == RT_TRUE) + { + g_gpu_state = RT_FALSE; + lv_disp_flush_ready(&g_disp_drv); + } + } } + + rt_interrupt_leave(); } void lv_port_disp_init(void) { rt_err_t result; - void* buf_1 = RT_NULL; - void* buf_2 = RT_NULL; + static lv_color_t lv_disp_buf1[DISP_BUF_SIZE] = {0}; lcd_device = rt_device_find("lcd"); + if (lcd_device == 0) { - LOG_E("error!"); + LOG_E("lcd_device error!"); return; } + result = rt_device_open(lcd_device, 0); + if (result != RT_EOK) { LOG_E("error!"); @@ -157,6 +104,7 @@ void lv_port_disp_init(void) /* get framebuffer address */ result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK) { LOG_E("error!"); @@ -165,26 +113,12 @@ void lv_port_disp_init(void) } RT_ASSERT (info.bits_per_pixel == 8 || info.bits_per_pixel == 16 || - info.bits_per_pixel == 24 || info.bits_per_pixel == 32); + info.bits_per_pixel == 24 || info.bits_per_pixel == 32); lvgl_dma_config(); - buf_1 = rt_malloc(info.width * info.height * sizeof(lv_color_t)); - if (buf_1 == RT_NULL) - { - LOG_E("malloc memory failed"); - return; - } - - buf_2 = rt_malloc(info.width * info.height * sizeof(lv_color_t)); - if (buf_2 == RT_NULL) - { - LOG_E("malloc memory failed"); - return; - } - /*Initialize `disp_buf` with the buffer(s).*/ - lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, info.width * info.height); + lv_disp_draw_buf_init(&disp_buf, lv_disp_buf1, RT_NULL, DISP_BUF_SIZE); lv_disp_drv_init(&disp_drv); /*Basic initialization*/ @@ -200,4 +134,6 @@ void lv_port_disp_init(void) /*Finally register the driver*/ lv_disp_drv_register(&disp_drv); + + g_disp_drv = disp_drv; } From f7ba146a01fcf23a2b06a141d1b1a56cb27b878c Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Fri, 14 Jan 2022 18:29:19 +0800 Subject: [PATCH 09/65] Add sdk_dist.py and ADC touching calibration function. --- .../libraries/n9h30/rtt_port/drv_adc.c | 253 ++++--- .../libraries/n9h30/rtt_port/drv_adc.h | 32 +- .../libraries/n9h30/rtt_port/drv_adc_touch.c | 525 ++++++++++++-- .../nu_packages/ILI9341/lcd_ili9341.c | 3 +- bsp/nuvoton/libraries/nu_packages/Kconfig | 18 +- .../libraries/nuc980/Driver/Include/nu_adc.h | 119 ++- .../libraries/nuc980/Driver/Include/nuc980.h | 49 +- bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig | 7 + .../libraries/nuc980/rtt_port/drv_adc.c | 483 ++++++++++++- .../libraries/nuc980/rtt_port/drv_adc.h | 84 +++ .../libraries/nuc980/rtt_port/drv_adc_touch.c | 681 ++++++++++++++++++ .../libraries/nuc980/rtt_port/drv_emac.c | 2 +- bsp/nuvoton/nk-980iot/.config | 57 +- bsp/nuvoton/nk-980iot/board/Kconfig | 1 + bsp/nuvoton/nk-980iot/board/nu_pin_init.c | 2 + bsp/nuvoton/nk-980iot/rtconfig.py | 8 +- bsp/nuvoton/nk-980iot/spinor.config | 407 ++++++++--- bsp/nuvoton/nk-n9h30/rtconfig.py | 8 +- bsp/nuvoton/nk-rtu980/rtconfig.py | 8 +- bsp/nuvoton/numaker-iot-m487/rtconfig.py | 8 + bsp/nuvoton/numaker-m032ki/rtconfig.py | 8 + bsp/nuvoton/numaker-m2354/.config | 40 +- bsp/nuvoton/numaker-m2354/rtconfig.py | 8 + bsp/nuvoton/numaker-pfm-m487/.config | 40 +- bsp/nuvoton/numaker-pfm-m487/rtconfig.py | 8 + bsp/nuvoton/tools/sdk_dist.py | 39 + 26 files changed, 2475 insertions(+), 423 deletions(-) create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c create mode 100644 bsp/nuvoton/tools/sdk_dist.py diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c index 5ce1c64276..d1dcba7d5b 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c @@ -35,24 +35,27 @@ struct nu_adc uint32_t chn_mask; rt_sem_t m_psSem; +#if defined(BSP_USING_ADC_TOUCH) rt_touch_t psRtTouch; rt_timer_t psRtTouchMenuTimer; + rt_mq_t m_pmqTouchXYZ; +#endif nu_adc_cb m_isr[eAdc_ISR_CNT]; nu_adc_cb m_wkisr[eAdc_WKISR_CNT]; - - rt_mq_t m_pmqTouchXYZ; }; typedef struct nu_adc *nu_adc_t; +#if defined(BSP_USING_ADC_TOUCH) struct nu_adc_touch_data { - uint16_t u16X; - uint16_t u16Y; - uint16_t u16Z0; - uint16_t u16Z1; + uint32_t u32X; + uint32_t u32Y; + uint32_t u32Z0; + uint32_t u32Z1; }; typedef struct nu_adc_touch_data *nu_adc_touch_data_t; +#endif /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); @@ -134,6 +137,64 @@ static rt_err_t _nu_adc_init(rt_device_t dev) return RT_EOK; } +static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) +{ + nu_adc_t psNuAdc = (nu_adc_t)userData; + +#if defined(BSP_USING_ADC_TOUCH) + + static struct nu_adc_touch_data point; + static rt_bool_t bDrop = RT_FALSE; + static uint32_t u32LastZ0 = 0xffffu; + + if (psNuAdc->psRtTouch != RT_NULL) + { + uint32_t value; + + value = inpw(REG_ADC_XYDATA); + point.u32X = (value & 0x0ffful); + point.u32Y = ((value >> 16) & 0x0ffful); + + value = inpw(REG_ADC_ZDATA); + point.u32Z0 = (value & 0x0ffful); + point.u32Z1 = ((value >> 16) & 0x0ffful); + + /* Trigger next or not. */ + if (point.u32Z0 == 0) + { + /* Stop sampling procedure. */ + rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); + + /* Re-start pendown detection */ + nu_adc_touch_detect(RT_TRUE); + + bDrop = RT_TRUE; + } + else + { + bDrop = RT_FALSE; + } + + /* Notify upper layer. */ + if ((!bDrop || (u32LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) + { + rt_hw_touch_isr(psNuAdc->psRtTouch); + } + + u32LastZ0 = point.u32Z0; + } + else +#endif + { + rt_err_t result = rt_sem_release(psNuAdc->m_psSem); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} + +#if defined(BSP_USING_ADC_TOUCH) + void nu_adc_touch_detect(rt_bool_t bStartDetect) { nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; @@ -150,60 +211,6 @@ void nu_adc_touch_detect(rt_bool_t bStartDetect) } } -static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) -{ - static struct nu_adc_touch_data point; - static rt_bool_t bDrop = RT_FALSE; - static uint16_t u16LastZ0 = 0xfffful; - - nu_adc_t psNuAdc = (nu_adc_t)userData; - - if (psNuAdc->psRtTouch != RT_NULL) - { - uint32_t value; - - value = inpw(REG_ADC_XYDATA); - point.u16X = (uint16_t)(value & 0x0ffful); - point.u16Y = (uint16_t)((value >> 16) & 0x0ffful); - - value = inpw(REG_ADC_ZDATA); - point.u16Z0 = (uint16_t)(value & 0x0ffful); - point.u16Z1 = (uint16_t)((value >> 16) & 0x0ffful); - - /* Trigger next or not. */ - if (point.u16Z0 == 0) - { - /* Stop sampling procedure. */ - rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); - - /* Re-start pendown detection */ - nu_adc_touch_detect(RT_TRUE); - - bDrop = RT_TRUE; - } - else - { - bDrop = RT_FALSE; - } - - /* Notify upper layer. */ - if ((!bDrop || (u16LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) - { - rt_hw_touch_isr(psNuAdc->psRtTouch); - } - - u16LastZ0 = point.u16Z0; - } - else - { - rt_err_t result = rt_sem_release(psNuAdc->m_psSem); - RT_ASSERT(result == RT_EOK); - } - - return 0; -} - - static int32_t PenDownCallback(uint32_t status, uint32_t userData) { nu_adc_touch_detect(RT_FALSE); @@ -213,7 +220,7 @@ static int32_t PenDownCallback(uint32_t status, uint32_t userData) return 0; } -int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, uint16_t *bufZ1, int32_t dataCnt) +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt) { int i; struct nu_adc_touch_data value; @@ -223,14 +230,71 @@ int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, u if (rt_mq_recv(g_sNuADC.m_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT) break; - bufX[i] = value.u16X; - bufY[i] = value.u16Y; - bufZ0[i] = value.u16Z0; - bufZ1[i] = value.u16Z1; + bufX[i] = value.u32X; + bufY[i] = value.u32Y; + bufZ0[i] = value.u32Z0; + bufZ1[i] = value.u32Z1; } return i; } +void nu_adc_touch_start_conv(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); +} + +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + nu_adc_cb sNuAdcCb; + + rt_adc_enable((rt_adc_device_t)psNuAdc, 4); + rt_adc_enable((rt_adc_device_t)psNuAdc, 5); + rt_adc_enable((rt_adc_device_t)psNuAdc, 6); + rt_adc_enable((rt_adc_device_t)psNuAdc, 7); + + outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); + + /* Register touch device. */ + psNuAdc->psRtTouch = psRtTouch; + + /* Enable TouchXY. */ + _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); + + /* Enable TouchZZ. */ + _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); + + /* Register PenDown callback. */ + sNuAdcCb.cbfunc = PenDownCallback; + sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); + + nu_adc_touch_detect(RT_TRUE); + + return RT_EOK; +} + +rt_err_t nu_adc_touch_disable(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + nu_adc_touch_detect(RT_FALSE); + + _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); + + rt_adc_disable((rt_adc_device_t)psNuAdc, 4); + rt_adc_disable((rt_adc_device_t)psNuAdc, 5); + rt_adc_disable((rt_adc_device_t)psNuAdc, 6); + rt_adc_disable((rt_adc_device_t)psNuAdc, 7); + + return RT_EOK; +} + +#endif + static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) { rt_err_t ret = RT_EINVAL ; @@ -443,7 +507,9 @@ static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) case Z_OFF: /* Disable Press measure function */ { outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_ZEN); +#if defined(BSP_USING_ADC_TOUCH) rt_mq_control(psNuAdc->m_pmqTouchXYZ, RT_IPC_CMD_RESET, RT_NULL); +#endif } break; @@ -522,61 +588,6 @@ static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } -void nu_adc_touch_start_conv(void) -{ - nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; - _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); -} - -rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) -{ - nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; - nu_adc_cb sNuAdcCb; - - rt_adc_enable((rt_adc_device_t)psNuAdc, 4); - rt_adc_enable((rt_adc_device_t)psNuAdc, 5); - rt_adc_enable((rt_adc_device_t)psNuAdc, 6); - rt_adc_enable((rt_adc_device_t)psNuAdc, 7); - - outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); - - /* Register touch device. */ - psNuAdc->psRtTouch = psRtTouch; - - /* Enable TouchXY. */ - _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); - - /* Enable TouchZZ. */ - _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); - - /* Register PenDown callback. */ - sNuAdcCb.cbfunc = PenDownCallback; - sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; - _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); - - nu_adc_touch_detect(RT_TRUE); - - return RT_EOK; -} - -rt_err_t nu_adc_touch_disable(void) -{ - nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; - - nu_adc_touch_detect(RT_FALSE); - - _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); - _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); - _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); - - rt_adc_disable((rt_adc_device_t)psNuAdc, 4); - rt_adc_disable((rt_adc_device_t)psNuAdc, 5); - rt_adc_disable((rt_adc_device_t)psNuAdc, 6); - rt_adc_disable((rt_adc_device_t)psNuAdc, 7); - - return RT_EOK; -} - static rt_err_t _nu_adc_open(rt_device_t dev, rt_uint16_t oflag) { nu_adc_t psNuAdc = (nu_adc_t)dev; @@ -709,11 +720,13 @@ int rt_hw_adc_init(void) g_sNuADC.m_psSem = rt_sem_create("adc_mst_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(g_sNuADC.m_psSem != RT_NULL); +#if defined(BSP_USING_ADC_TOUCH) g_sNuADC.m_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_XYZ", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO); RT_ASSERT(g_sNuADC.m_pmqTouchXYZ != RT_NULL); g_sNuADC.psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)&g_sNuADC, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC); RT_ASSERT(g_sNuADC.psRtTouchMenuTimer != RT_NULL); +#endif rt_memset(&g_sNuADC.m_isr, 0, sizeof(g_sNuADC.m_isr)); rt_memset(&g_sNuADC.m_wkisr, 0, sizeof(g_sNuADC.m_wkisr)); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h index 2269f1f35c..ead185e0c1 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h @@ -15,9 +15,13 @@ #include #include "nu_adc.h" -#include "touch.h" +#if defined(BSP_USING_ADC_TOUCH) + #include "touch.h" +#endif -#define TOUCH_MQ_LENGTH 128 +#define TOUCH_MQ_LENGTH 64 + +#define DEF_CAL_POINT_NUM 5 typedef enum { @@ -52,13 +56,29 @@ typedef struct typedef nu_adc_cb *nu_adc_cb_t; -int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, uint16_t *bufZ1, int32_t dataCnt); +#if defined(BSP_USING_ADC_TOUCH) +typedef struct +{ + int32_t x; + int32_t y; +} S_COORDINATE_POINT; + +typedef struct +{ + int32_t a; + int32_t b; + int32_t c; + int32_t d; + int32_t e; + int32_t f; + int32_t div; +} S_CALIBRATION_MATRIX; + +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt); rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch); rt_err_t nu_adc_touch_disable(void); void nu_adc_touch_detect(rt_bool_t bStartDetect); void nu_adc_touch_start_conv(void); - -void nu_adc_touch_update_caldata(int *psi32NewValue); -void nu_adc_touch_reset_caldata(int *psi32NewValue); +#endif #endif /* __DRV_ADC_H__ */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c index 22c98e6c32..9d4848251c 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c @@ -15,9 +15,15 @@ #include "NuMicro.h" #include +#include #include "drv_adc.h" #include "touch.h" +#if !defined(PATH_CALIBRATION_FILE) + #define PATH_CALIBRATION_FILE "/mnt/filesystem/ts_calibration" +#endif + + typedef struct { struct rt_touch_device dev; @@ -28,35 +34,135 @@ typedef nu_adc_touch *nu_adc_touch_t; static nu_adc_touch s_NuAdcTouch = {0}; -#define DEF_CALDATA_LENGTH 7 - #if (BSP_LCD_WIDTH==480) && (BSP_LCD_HEIGHT==272) - static int cal_data_a[DEF_CALDATA_LENGTH] = { 8824, -34, -2261272, -70, -6302, 21805816, 65536 }; +static S_CALIBRATION_MATRIX g_sCalMat = { 8824, -34, -2261272, -70, -6302, 21805816, 65536 }; +static volatile uint32_t g_u32Calibrated = 1; #elif (BSP_LCD_WIDTH==800) && (BSP_LCD_HEIGHT==480) - static int cal_data_a[DEF_CALDATA_LENGTH] = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; +static S_CALIBRATION_MATRIX g_sCalMat = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; +static volatile uint32_t g_u32Calibrated = 1; #else - static int cal_data_a[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; +static S_CALIBRATION_MATRIX g_sCalMat = { 1, 0, 0, 0, 1, 0, 1 }; +static volatile uint32_t g_u32Calibrated = 0; #endif -static const int cal_zero[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; +static int nu_adc_touch_readfile(void); -static void nu_adc_touch_cal(int *sumx, int *sumy) +static const S_CALIBRATION_MATRIX g_sCalZero = { 1, 0, 0, 0, 1, 0, 1 }; + +static int nu_adc_cal_mat_get(const S_COORDINATE_POINT *psDispCP, S_COORDINATE_POINT *psADCCP, S_CALIBRATION_MATRIX *psCM) { - int xtemp, ytemp; +#if (DEF_CAL_POINT_NUM==3) + + psCM->div = ((psADCCP[0].x - psADCCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psADCCP[1].x - psADCCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + if (psCM->div == 0) + { + return -1; + } + else + { + psCM->a = ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].x - psDispCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->b = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].x - psDispCP[2].x)) - + ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->c = (psADCCP[2].x * psDispCP[1].x - psADCCP[1].x * psDispCP[2].x) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].x - psADCCP[2].x * psDispCP[0].x) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].x - psADCCP[0].x * psDispCP[1].x) * psADCCP[2].y ; + + psCM->d = ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].y - psDispCP[2].y) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->e = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].y - psDispCP[2].y)) - + ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->f = (psADCCP[2].x * psDispCP[1].y - psADCCP[1].x * psDispCP[2].y) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].y - psADCCP[2].x * psDispCP[0].y) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].y - psADCCP[0].x * psDispCP[1].y) * psADCCP[2].y ; + } + +#elif (DEF_CAL_POINT_NUM==5) + + int i; + float n, x, y, xx, yy, xy, z, zx, zy; + float a, b, c, d, e, f, g; + float scaling = 65536.0f; + + n = x = y = xx = yy = xy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + n += 1.0; + x += (float)psADCCP[i].x; + y += (float)psADCCP[i].y; + xx += (float)psADCCP[i].x * psADCCP[i].x; + yy += (float)psADCCP[i].y * psADCCP[i].y; + xy += (float)psADCCP[i].x * psADCCP[i].y; + } + + d = n * (xx * yy - xy * xy) + x * (xy * y - x * yy) + y * (x * xy - y * xx); + if (d < 0.1 && d > -0.1) + { + return -1; + } + + a = (xx * yy - xy * xy) / d; + b = (xy * y - x * yy) / d; + c = (x * xy - y * xx) / d; + e = (n * yy - y * y) / d; + f = (x * y - n * xy) / d; + g = (n * xx - x * x) / d; + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].x; + zx += (float)psDispCP[i].x * psADCCP[i].x; + zy += (float)psDispCP[i].x * psADCCP[i].y; + } + + psCM->c = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->a = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->b = (int32_t)((c * z + f * zx + g * zy) * scaling); + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].y; + zx += (float)psDispCP[i].y * psADCCP[i].x; + zy += (float)psDispCP[i].y * psADCCP[i].y; + } + + psCM->f = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->d = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->e = (int32_t)((c * z + f * zx + g * zy) * scaling); + + psCM->div = (int32_t)scaling; + +#else +#error "Not supported calibration method" +#endif + return 0; +} + +static void nu_adc_touch_cal(int32_t *sumx, int32_t *sumy) +{ + int32_t xtemp, ytemp; xtemp = *sumx; ytemp = *sumy; - *sumx = (cal_data_a[2] + - cal_data_a[0] * xtemp + - cal_data_a[1] * ytemp) / cal_data_a[6]; - *sumy = (cal_data_a[5] + - cal_data_a[3] * xtemp + - cal_data_a[4] * ytemp) / cal_data_a[6]; + *sumx = (g_sCalMat.c + + g_sCalMat.a * xtemp + + g_sCalMat.b * ytemp) / g_sCalMat.div; + *sumy = (g_sCalMat.f + + g_sCalMat.d * xtemp + + g_sCalMat.e * ytemp) / g_sCalMat.div; } static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *buf, rt_size_t read_num) { - static int last_report_x = 0, last_report_y = 0; + static uint32_t last_report_x = 0, last_report_y = 0; struct rt_touch_data *pPoint = (struct rt_touch_data *)buf; nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; @@ -67,38 +173,44 @@ static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *bu for (i = 0; i < read_num; i++) { - int bufZ0 = 0, bufZ1 = 0; - int sumx = 0, sumy = 0; + uint32_t bufZ0 = 0, bufZ1 = 0; + int32_t sumx = 0, sumy = 0; pPoint[i].timestamp = rt_touch_get_ts(); pPoint[i].track_id = 0; - if (nu_adc_read_touch_xyz((uint16_t *)&sumx, (uint16_t *)&sumy, (uint16_t *)&bufZ0, (uint16_t *)&bufZ1, 1) != 1) + if (nu_adc_touch_read_xyz((uint32_t *)&sumx, (uint32_t *)&sumy, &bufZ0, &bufZ1, 1) != 1) break; if (bufZ0 == 0) { /* Workaround: In this case, x, y values are unstable. so, report last point's coordinate.*/ pPoint[i].event = RT_TOUCH_EVENT_UP; - pPoint[i].x_coordinate = last_report_x; - pPoint[i].y_coordinate = last_report_y; + pPoint[i].x_coordinate = (uint16_t)last_report_x; + pPoint[i].y_coordinate = (uint16_t)last_report_y; } else { - nu_adc_touch_cal(&sumx, &sumy); - pPoint[i].event = RT_TOUCH_EVENT_DOWN; - pPoint[i].x_coordinate = sumx; - pPoint[i].y_coordinate = sumy; + if (g_u32Calibrated) + { + nu_adc_touch_cal(&sumx, &sumy); + } last_report_x = sumx; last_report_y = sumy; + + pPoint[i].event = RT_TOUCH_EVENT_DOWN; + pPoint[i].x_coordinate = (uint16_t)sumx; + pPoint[i].y_coordinate = (uint16_t)sumy; } - bufZ0 = bufZ0 >> 3; + if (g_u32Calibrated) + { + bufZ0 = bufZ0 >> 3; + pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; - pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; - - //Limit max x, y coordinate if value is over its range. - pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; - pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + //Limit max x, y coordinate if value is over its range. + pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; + pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + } } return (rt_size_t)i; } @@ -144,14 +256,29 @@ static struct rt_touch_ops touch_ops = .touch_control = nu_adc_touch_control, }; -void nu_adc_touch_update_caldata(int *psi32NewValue) +static void nu_adc_touch_update_calmat(S_CALIBRATION_MATRIX *psNewCalMat) { - rt_memcpy(&cal_data_a[0], &psi32NewValue[0], sizeof(cal_data_a)); + if (psNewCalMat && + psNewCalMat->div != 0) + { + rt_memcpy(&g_sCalMat, psNewCalMat, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 1; + rt_kprintf("Applied calibration data: %d, %d, %d, %d, %d, %d, %d\n", + g_sCalMat.a, + g_sCalMat.b, + g_sCalMat.c, + g_sCalMat.d, + g_sCalMat.e, + g_sCalMat.f, + g_sCalMat.div); + + } } -void nu_adc_touch_reset_caldata(int *psi32NewValue) +static void nu_adc_touch_reset_calmat(void) { - rt_memcpy(&cal_data_a[0], &cal_zero[0], sizeof(cal_data_a)); + rt_memcpy(&g_sCalMat, &g_sCalZero, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 0; } int rt_hw_adc_touch_init(void) @@ -173,10 +300,268 @@ INIT_DEVICE_EXPORT(rt_hw_adc_touch_init); static rt_thread_t adc_touch_thread = RT_NULL; static rt_sem_t adc_touch_sem = RT_NULL; static int adc_touch_worker_run = 0; + static rt_err_t adc_touch_rx_callback(rt_device_t dev, rt_size_t size) { - rt_sem_release(adc_touch_sem); + //rt_kprintf("[%s %d] %d\n", __func__, __LINE__, size); + return rt_sem_release(adc_touch_sem); +} + +static rt_err_t adc_request_point(rt_device_t pdev, struct rt_touch_data *psTouchPoint) +{ + rt_err_t ret = -RT_ERROR; + + if ((ret = rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(500))) == RT_EOK) + { + rt_memset(psTouchPoint, 0, sizeof(struct rt_touch_data)); + + if (rt_device_read(pdev, 0, psTouchPoint, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + { + ret = RT_EOK; + } + + } + + return ret; +} + +RT_WEAK void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t event) +{ +} + +static rt_device_t lcd_device = 0; +static struct rt_device_graphic_info info; + +static void lcd_cleanscreen(void) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + + rt_memset(info.framebuffer, 0, (info.pitch * info.height)); + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#define DEF_DOT_NUMBER 9 +#define DOTS_NUMBER (DEF_DOT_NUMBER*DEF_DOT_NUMBER) +static void nu_draw_bots(int x, int y) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + int i, j; + int start_x = x - (DEF_DOT_NUMBER / 2); + int start_y = y - (DEF_DOT_NUMBER / 2); + + if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) + { + uint16_t *pu16Start = (uint16_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 2)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu16Start[i] = 0x07E0; //Green, RGB + pu16Start += info.width; + } + } + else if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888) + { + uint32_t *pu32Start = (uint32_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 4)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu32Start[i] = 0xff00ff00; //Green, ARGB + pu32Start += info.width; + } + } + else + { + //Not supported + } + + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#if (DEF_CAL_POINT_NUM==3) +const S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ + {BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 2}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 4}, + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / 4} +}; +#elif (DEF_CAL_POINT_NUM==5) +const static S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ +#define DEF_CUT_PIECES 8 + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT / 2} +}; +#endif + +static int nu_adc_touch_readfile(void) +{ + int fd; + + S_CALIBRATION_MATRIX sCalMat; + + if ((fd = open(PATH_CALIBRATION_FILE, O_RDONLY, 0)) < 0) + { + goto exit_nu_adc_touch_readfile; + } + else if (read(fd, &sCalMat, sizeof(S_CALIBRATION_MATRIX)) == sizeof(S_CALIBRATION_MATRIX)) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + nu_adc_touch_update_calmat(&sCalMat); + return 0; + +exit_nu_adc_touch_readfile: + + return -1; +} + +static int nu_adc_touch_writefile(void *buf, int buf_len) +{ + int fd; + + if ((fd = open(PATH_CALIBRATION_FILE, O_WRONLY | O_CREAT, 0)) < 0) + { + goto exit_nu_adc_touch_writefile; + } + else if (write(fd, buf, buf_len) == buf_len) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + return 0; + +exit_nu_adc_touch_writefile: + + return -1; +} + +static void nu_touch_do_calibration(rt_device_t pdev) +{ + int i; + rt_err_t result; + + S_CALIBRATION_MATRIX sCalMat; + S_COORDINATE_POINT sADCPoints[DEF_CAL_POINT_NUM]; + + lcd_device = rt_device_find("lcd"); + if (!lcd_device) + { + rt_kprintf("Not supported graphics ops\n"); + return; + } + + result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK) + { + rt_kprintf("error!"); + return; + } + + result = rt_device_open(lcd_device, 0); + if (result != RT_EOK) + { + rt_kprintf("opened?"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, info.framebuffer); + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + struct rt_touch_data sTouchPoint; + int count = 0; + + lcd_cleanscreen(); + + /* Drain RX queue before doing calibrate. */ + while (adc_request_point(pdev, &sTouchPoint) == RT_EOK); + + rt_thread_mdelay(100); + + /* Ready to calibrate */ + nu_draw_bots(sDispPoints[i].x, sDispPoints[i].y); + +#define DEF_MAX_GET_POINT_NUM 5 + + sADCPoints[i].x = 0; + sADCPoints[i].y = 0; + + while (count < DEF_MAX_GET_POINT_NUM) + { + if (adc_request_point(pdev, &sTouchPoint) == RT_EOK) + { + sADCPoints[i].x += (int32_t)sTouchPoint.x_coordinate; + sADCPoints[i].y += (int32_t)sTouchPoint.y_coordinate; + rt_kprintf("[%d %d] - Disp:[%d, %d] -> ADC:[%d, %d]\n", i, count, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + count++; + } + } + + sADCPoints[i].x = (int32_t)((float)sADCPoints[i].x / DEF_MAX_GET_POINT_NUM); + sADCPoints[i].y = (int32_t)((float)sADCPoints[i].y / DEF_MAX_GET_POINT_NUM); + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + + rt_thread_mdelay(300); + } + + lcd_cleanscreen(); + + /* Get calibration matrix. */ + if (nu_adc_cal_mat_get(&sDispPoints[0], &sADCPoints[0], &sCalMat) == 0) + { + /* Finally, update calibration matrix to drivers. */ + nu_adc_touch_update_calmat(&sCalMat); + + nu_adc_touch_writefile(&sCalMat, sizeof(sCalMat)); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + } + } + else + { + rt_kprintf("Failed to calibrate.\n"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWEROFF, RT_NULL); + rt_device_close(lcd_device); + + return; } static void adc_touch_entry(void *parameter) @@ -184,13 +569,22 @@ static void adc_touch_entry(void *parameter) struct rt_touch_data touch_point; rt_err_t result; - rt_device_t pdev = &s_NuAdcTouch.dev.parent; + rt_device_t pdev; int max_range; adc_touch_sem = rt_sem_create("adc_touch_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(adc_touch_sem != RT_NULL); + pdev = rt_device_find("adc_touch"); + if (!pdev) + { + rt_kprintf("Not found\n"); + return ; + } + + nu_adc_touch_readfile(); + result = rt_device_open(pdev, RT_DEVICE_FLAG_INT_RX); RT_ASSERT(result == RT_EOK); @@ -205,45 +599,33 @@ static void adc_touch_entry(void *parameter) result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); - // nu_adc_touch_reset_caldata(int *psi32NewValue); - // nu_adc_touch_update_caldata(int *psi32NewValue); - result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_ON, RT_NULL); RT_ASSERT(result == RT_EOK); while (adc_touch_worker_run) { - if ((-RT_ETIMEOUT == rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(100)))) + if (!g_u32Calibrated) + { + rt_kprintf("Start ADC touching calibration.\n"); + nu_touch_do_calibration(pdev); + rt_kprintf("Stop ADC touching calibration.\n"); continue; + } - rt_memset(&touch_point, 0, sizeof(struct rt_touch_data)); - - if (rt_device_read(pdev, 0, &touch_point, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + if (adc_request_point(pdev, &touch_point) == RT_EOK) { if (touch_point.event == RT_TOUCH_EVENT_DOWN || touch_point.event == RT_TOUCH_EVENT_UP || touch_point.event == RT_TOUCH_EVENT_MOVE) { - -#if defined(PKG_USING_LVGL) - extern void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t state); nu_touch_inputevent_cb(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); -#elif defined(PKG_USING_LITTLEVGL2RTT) - extern void littlevgl2rtt_send_input_event(rt_int16_t x, rt_int16_t y, rt_uint8_t state); - littlevgl2rtt_send_input_event(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); -#endif -#if defined(PKG_USING_NUEMWIN) - extern void nuemwin_send_input_event(rt_int16_t x, rt_int16_t y, rt_uint8_t state); - nuemwin_send_input_event(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); -#endif - rt_kprintf("[%d-%d] id=%d width=%d x=%d y=%d\n", - touch_point.timestamp, - touch_point.event, - touch_point.track_id, - touch_point.width, + rt_kprintf("x=%d y=%d event=%s%s%s\n", touch_point.x_coordinate, - touch_point.y_coordinate); + touch_point.y_coordinate, + (touch_point.event == RT_TOUCH_EVENT_DOWN) ? "DOWN" : "", + (touch_point.event == RT_TOUCH_EVENT_UP) ? "UP" : "", + (touch_point.event == RT_TOUCH_EVENT_MOVE) ? "MOVE" : ""); } } } @@ -264,7 +646,7 @@ static rt_err_t nu_touch_start(int argc, char **argv) adc_touch_thread = rt_thread_create("adc_touch_thread", adc_touch_entry, RT_NULL, - 2048, + 4096, 25, 5); adc_touch_worker_run = 1; @@ -275,12 +657,6 @@ static rt_err_t nu_touch_start(int argc, char **argv) } MSH_CMD_EXPORT(nu_touch_start, e.g: start adc touch); -static int nu_touch_autostart(void) -{ - return nu_touch_start(0, RT_NULL); -} -INIT_APP_EXPORT(nu_touch_autostart); - /* Support "nu_touch_stop" command line in msh mode */ static rt_err_t nu_touch_stop(int argc, char **argv) { @@ -290,4 +666,19 @@ static rt_err_t nu_touch_stop(int argc, char **argv) } MSH_CMD_EXPORT(nu_touch_stop, e.g: stop adc touch); +static int nu_touch_autostart(void) +{ + return nu_touch_start(0, RT_NULL); +} +INIT_APP_EXPORT(nu_touch_autostart); + +static rt_err_t nu_touch_calibration(int argc, char **argv) +{ + /* Clean calibration matrix data for getting raw adc value. */ + nu_adc_touch_reset_calmat(); + + return 0; +} +MSH_CMD_EXPORT(nu_touch_calibration, for adc touch); + #endif //#if defined(BSP_USING_ADC_TOUCH) diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c index 31cb6c6d02..5f87e038c1 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c @@ -27,6 +27,7 @@ static struct rt_device_graphic_info g_Ili9341Info = .pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565, .framebuffer = RT_NULL, .width = XSIZE_PHYS, + .pitch = XSIZE_PHYS * 2, .height = YSIZE_PHYS }; @@ -324,7 +325,7 @@ int rt_hw_lcd_ili9341_init(void) lcd_device.user_data = &ili9341_ops; #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) - g_Ili9341Info.framebuffer = rt_malloc_align((DEF_VRAM_BUFFER_NUMBER * g_Ili9341Info.width * g_Ili9341Info.height * (g_Ili9341Info.bits_per_pixel / 8)) + 32, 32); + g_Ili9341Info.framebuffer = rt_malloc_align((DEF_VRAM_BUFFER_NUMBER * g_Ili9341Info.pitch * g_Ili9341Info.height) + 32, 32); RT_ASSERT(g_Ili9341Info.framebuffer != RT_NULL); #endif diff --git a/bsp/nuvoton/libraries/nu_packages/Kconfig b/bsp/nuvoton/libraries/nu_packages/Kconfig index ab3bba4331..b27797f36a 100644 --- a/bsp/nuvoton/libraries/nu_packages/Kconfig +++ b/bsp/nuvoton/libraries/nu_packages/Kconfig @@ -38,7 +38,7 @@ menu "Nuvoton Packages Config" bool "ILI9341 LCD Panel" select BSP_USING_GPIO default n - + if NU_PKG_USING_ILI9341 choice @@ -62,8 +62,20 @@ menu "Nuvoton Packages Config" default n config NU_PKG_ILI9341_HORIZONTAL - bool "Set horizontal view. (320x240)" - default n + bool + default y + + config BSP_LCD_BPP + int + default 16 if NU_PKG_USING_ILI9341 + + config BSP_LCD_WIDTH + int + default 320 if NU_PKG_ILI9341_HORIZONTAL + + config BSP_LCD_HEIGHT + int + default 240 if NU_PKG_ILI9341_HORIZONTAL endif diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h index 341e2606f0..6e814049ff 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h @@ -35,51 +35,142 @@ extern "C" #define ADC_ERR_CMD 2 /*!< The command is wrong */ /// @cond HIDDEN_SYMBOLS -typedef INT32(*ADC_CALLBACK)(UINT32 status, UINT32 userData); +typedef int32_t(*ADC_CALLBACK)(uint32_t status, uint32_t userData); /// @endcond HIDDEN_SYMBOLS /*---------------------------------------------------------------------------------------------------------*/ /* ADC_CTL constant definitions */ /*---------------------------------------------------------------------------------------------------------*/ #define ADC_CTL_ADEN 0x00000001 /*!< ADC Power Control */ -#define ADC_CTL_VBGEN 0x00000002 /*!< ADC Internal Bandgap Power Control */ +#define ADC_CTL_VBGEN 0x00000002 /*!< ADC Internal Bandgap Power Control */ +#define ADC_CTL_PWKPEN 0x00000004 /*!< ADC Keypad Power Enable Control */ #define ADC_CTL_MST 0x00000100 /*!< Menu Start Conversion */ +#define ADC_CTL_PEDEEN 0x00000200 /*!< Pen Down Event Enable */ +#define ADC_CTL_WKPEN 0x00000400 /*!< Keypad Press Wake Up Enable */ +#define ADC_CTL_WKTEN 0x00000800 /*!< Touch Wake Up Enable */ +#define ADC_CTL_WMSWCH 0x00010000 /*!< Wire Mode Switch For 5-Wire/4-Wire Configuration */ /*---------------------------------------------------------------------------------------------------------*/ /* ADC_CONF constant definitions */ /*---------------------------------------------------------------------------------------------------------*/ +#define ADC_CONF_TEN 0x00000001 /*!< Touch Enable */ +#define ADC_CONF_ZEN 0x00000002 /*!< Press Enable */ #define ADC_CONF_NACEN 0x00000004 /*!< Normal AD Conversion Enable */ +#define ADC_CONF_VBATEN 0x00000100 /*!< Voltage Battery Enable */ +#define ADC_CONF_KPCEN 0x00000200 /*!< Keypad Press Conversion Enable */ #define ADC_CONF_SELFTEN 0x00000400 /*!< Selft Test Enable */ +#define ADC_CONF_DISTMAVEN (1<<20) /*!< Display T Mean Average Enable */ +#define ADC_CONF_DISZMAVEN (1<<21) /*!< Display Z Mean Average Enable */ #define ADC_CONF_HSPEED (1<<22) /*!< High Speed Enable */ -#define ADC_CONF_CHSEL_Pos 12 /*!< Channel Selection Position */ -#define ADC_CONF_CHSEL_Msk (0xF< #include "NuMicro.h" -#include +#include "drv_sys.h" +#include "nu_bitutil.h" +#include "drv_adc.h" /* Private define ---------------------------------------------------------------*/ +#define DEF_ADC_TOUCH_SMPL_TICK 40 /* Private Typedef --------------------------------------------------------------*/ struct nu_adc @@ -31,12 +34,33 @@ struct nu_adc int chn_num; uint32_t chn_mask; rt_sem_t m_psSem; + +#if defined(BSP_USING_ADC_TOUCH) + rt_touch_t psRtTouch; + rt_timer_t psRtTouchMenuTimer; + rt_mq_t m_pmqTouchXYZ; +#endif + + nu_adc_cb m_isr[eAdc_ISR_CNT]; + nu_adc_cb m_wkisr[eAdc_WKISR_CNT]; }; typedef struct nu_adc *nu_adc_t; +#if defined(BSP_USING_ADC_TOUCH) +struct nu_adc_touch_data +{ + uint32_t u32X; + uint32_t u32Y; + uint32_t u32Z0; + uint32_t u32Z1; +}; +typedef struct nu_adc_touch_data *nu_adc_touch_data_t; +#endif + /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); static rt_err_t nu_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value); +static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args); /* Public functions ------------------------------------------------------------*/ int rt_hw_adc_init(void); @@ -56,24 +80,41 @@ static struct nu_adc g_sNuADC = static void nu_adc_isr(int vector, void *param) { - uint32_t isr, conf; + rt_int32_t isr, wkisr; nu_adc_t psNuAdc = (nu_adc_t)param; + rt_int32_t irqidx; - conf = inpw(REG_ADC_CONF); isr = inpw(REG_ADC_ISR); + wkisr = inpw(REG_ADC_WKISR); - if ((isr & ADC_ISR_NACF) && (conf & ADC_CONF_NACEN)) + while ((irqidx = nu_ctz(isr)) < eAdc_ISR_CNT) { - outpw(REG_ADC_ISR, ADC_ISR_NACF); - } + uint32_t u32IsrBitMask = 1 << irqidx ; - if (isr & ADC_ISR_MF) + if (psNuAdc->m_isr[irqidx].cbfunc != RT_NULL) + { + //rt_kprintf("[%s] %d %x\n", __func__, irqidx, psNuAdc->m_isr[irqidx].cbfunc); + psNuAdc->m_isr[irqidx].cbfunc(isr, psNuAdc->m_isr[irqidx].private_data); + } + + /* Clear sent bit */ + outpw(REG_ADC_ISR, u32IsrBitMask); + isr &= ~(u32IsrBitMask); + } //while + + while ((irqidx = nu_ctz(wkisr)) < eAdc_WKISR_CNT) { - rt_err_t result; - outpw(REG_ADC_ISR, ADC_ISR_MF); - result = rt_sem_release(psNuAdc->m_psSem); - RT_ASSERT(result == RT_EOK); - } + uint32_t u32IsrBitMask = 1 << irqidx ; + + if (psNuAdc->m_wkisr[irqidx].cbfunc != RT_NULL) + { + psNuAdc->m_wkisr[irqidx].cbfunc(wkisr, psNuAdc->m_wkisr[irqidx].private_data); + } + + /* Clear sent bit */ + outpw(REG_ADC_WKISR, u32IsrBitMask); + wkisr &= ~(u32IsrBitMask); + } //while } static rt_err_t _nu_adc_init(rt_device_t dev) @@ -96,11 +137,171 @@ static rt_err_t _nu_adc_init(rt_device_t dev) return RT_EOK; } +static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) +{ + nu_adc_t psNuAdc = (nu_adc_t)userData; + +#if defined(BSP_USING_ADC_TOUCH) + + static struct nu_adc_touch_data point; + static rt_bool_t bDrop = RT_FALSE; + static uint32_t u32LastZ0 = 0xffffu; + + if (psNuAdc->psRtTouch != RT_NULL) + { + uint32_t value; + + value = inpw(REG_ADC_XYDATA); + point.u32X = (value & 0x0ffful); + point.u32Y = ((value >> 16) & 0x0ffful); + + value = inpw(REG_ADC_ZDATA); + point.u32Z0 = (value & 0x0ffful); + point.u32Z1 = ((value >> 16) & 0x0ffful); + + /* Trigger next or not. */ + if (point.u32Z0 == 0) + { + /* Stop sampling procedure. */ + rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); + + /* Re-start pendown detection */ + nu_adc_touch_detect(RT_TRUE); + + bDrop = RT_TRUE; + } + else + { + bDrop = RT_FALSE; + } + + /* Notify upper layer. */ + if ((!bDrop || (u32LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) + { + rt_hw_touch_isr(psNuAdc->psRtTouch); + } + + u32LastZ0 = point.u32Z0; + } + else +#endif + { + rt_err_t result = rt_sem_release(psNuAdc->m_psSem); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} + +#if defined(BSP_USING_ADC_TOUCH) + +void nu_adc_touch_detect(rt_bool_t bStartDetect) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + if (bStartDetect) + { + /* Start detect PenDown */ + _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_ON, RT_NULL); + } + else + { + /* Stop detect PenDown */ + _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_OFF, RT_NULL); + } +} + +static int32_t PenDownCallback(uint32_t status, uint32_t userData) +{ + nu_adc_touch_detect(RT_FALSE); + + rt_timer_start(g_sNuADC.psRtTouchMenuTimer); + + return 0; +} + +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt) +{ + int i; + struct nu_adc_touch_data value; + + for (i = 0 ; i < dataCnt; i++) + { + if (rt_mq_recv(g_sNuADC.m_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT) + break; + + bufX[i] = value.u32X; + bufY[i] = value.u32Y; + bufZ0[i] = value.u32Z0; + bufZ1[i] = value.u32Z1; + } + return i; +} + +void nu_adc_touch_start_conv(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); +} + +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + nu_adc_cb sNuAdcCb; + + rt_adc_enable((rt_adc_device_t)psNuAdc, 4); + rt_adc_enable((rt_adc_device_t)psNuAdc, 5); + rt_adc_enable((rt_adc_device_t)psNuAdc, 6); + rt_adc_enable((rt_adc_device_t)psNuAdc, 7); + + outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); + + /* Register touch device. */ + psNuAdc->psRtTouch = psRtTouch; + + /* Enable TouchXY. */ + _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); + + /* Enable TouchZZ. */ + _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); + + /* Register PenDown callback. */ + sNuAdcCb.cbfunc = PenDownCallback; + sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); + + nu_adc_touch_detect(RT_TRUE); + + return RT_EOK; +} + +rt_err_t nu_adc_touch_disable(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + nu_adc_touch_detect(RT_FALSE); + + _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); + + rt_adc_disable((rt_adc_device_t)psNuAdc, 4); + rt_adc_disable((rt_adc_device_t)psNuAdc, 5); + rt_adc_disable((rt_adc_device_t)psNuAdc, 6); + rt_adc_disable((rt_adc_device_t)psNuAdc, 7); + + return RT_EOK; +} + +#endif + static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) { rt_err_t ret = RT_EINVAL ; nu_adc_t psNuAdc = (nu_adc_t)dev; + nu_adc_cb_t psAdcCb = (nu_adc_cb_t)args; + switch (cmd) { case START_MST: /* Menu Start Conversion */ @@ -116,29 +317,259 @@ static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) RT_ASSERT(ret == RT_EOK); /* Get data: valid data is 12-bit */ - *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF; + if (args != RT_NULL) + *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF; } break; + + /* case START_MST_POLLING: Not supported. */ + case VBPOWER_ON: /* Enable ADC Internal Bandgap Power */ { outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_VBGEN); } break; + case VBPOWER_OFF: /* Disable ADC Internal Bandgap Power */ { outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_VBGEN); } break; + + case KPPOWER_ON: /* Enable ADC Keypad Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PWKPEN); + } + break; + + case KPPOWER_OFF: /* Disable ADC Keypad Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PWKPEN); + } + break; + + case PEPOWER_ON: /* Enable Pen Power */ + { + int retry = 100; + uint32_t treg = inpw(REG_ADC_IER); + outpw(REG_ADC_IER, treg & ~(ADC_IER_PEDEIEN | ADC_IER_PEUEIEN)); + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PEDEEN); + do + { + outpw(REG_ADC_ISR, ADC_ISR_PEDEF | ADC_ISR_PEUEF); + rt_thread_mdelay(1); + if (retry-- == 0) + break; + } + while (inpw(REG_ADC_ISR) & (ADC_ISR_PEDEF | ADC_ISR_PEUEF)); + outpw(REG_ADC_IER, treg); + } + break; + + case PEPOWER_OFF: /* Disable Pen Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PEDEEN); + } + break; + + case KPPRESS_ON: /* Enable Keypad press event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN); + } + break; + + case KPPRESS_OFF: /* Disable Keypad press event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER & ~ADC_IER_KPEIEN)); + } + break; + + case KPUP_ON: /* Enable Keypad up event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPUEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPUEIEN); + } + break; + + case KPUP_OFF: /* Disable Keypad up event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_KPUEIEN); + } + break; + + case PEDEF_ON: /* Enable Pen Down Event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_PEDEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_PEDEIEN); + } + break; + + case PEDEF_OFF: /* Disable Pen Down Event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_PEDEIEN); + } + break; + + case WKP_ON: /* Enable Keypad Press Wake Up */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_wkisr[eAdc_WKPEF], psAdcCb, sizeof(nu_adc_cb)); + } + + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKPEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKPIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26)); + } + break; + + case WKP_OFF: /* Disable Keypad Press Wake Up */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKPEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKPIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26)); + } + break; + + case WKT_ON: /* Enable Touch Wake Up */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_wkisr[eAdc_WPEDEF], psAdcCb, sizeof(nu_adc_cb)); + } + + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKTEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKTIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26)); + } + break; + + case WKT_OFF: /* Disable Touch Wake Up */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKTEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKTIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26)); + } + break; + + case SWITCH_5WIRE_ON: /* Wire Mode Switch to 5-Wire */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WMSWCH); + } + break; + + case SWITCH_5WIRE_OFF: /* Wire Mode Switch to 4-Wire */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WMSWCH); + } + break; + + case T_ON: /* Enable Touch detection function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_TEN); + } + break; + + case T_OFF: /* Disable Touch detection function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_TEN); + } + break; + + case TAVG_ON: /* Enable Touch Mean average for X and Y function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISTMAVEN); + } + break; + + case TAVG_OFF: /* Disable Touch Mean average for X and Y function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISTMAVEN); + } + break; + + case Z_ON: /* Enable Press measure function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_ZEN); + } + break; + + case Z_OFF: /* Disable Press measure function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_ZEN); +#if defined(BSP_USING_ADC_TOUCH) + rt_mq_control(psNuAdc->m_pmqTouchXYZ, RT_IPC_CMD_RESET, RT_NULL); +#endif + } + break; + + case TZAVG_ON: /* Enable Pressure Mean average for Z1 and Z2 function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISZMAVEN); + } + break; + + case TZAVG_OFF: /* Disable Pressure Mean average for Z1 and Z2 function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISZMAVEN); + } + break; + case NAC_ON: /* Enable Normal AD Conversion */ { outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_NACEN | ADC_CONF_REFSEL_AVDD33); } break; + case NAC_OFF: /* Disable Normal AD Conversion */ { outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_NACEN); } break; + + case VBAT_ON: /* Enable Voltage Battery Conversion */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_VBF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_VBATEN); + } + break; + + case VBAT_OFF: /* Disable Voltage Battery */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_VBATEN); + } + break; + + case KPCONV_ON: /* Enable Keypad conversion function */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPCF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_KPCEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN); + } + break; + + case KPCONV_OFF: /* Disable Keypad conversion function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_KPCEN); + } + break; + case SWITCH_CH: { int chn = (int)args; @@ -265,6 +696,16 @@ exit_nu_adc_convert: return (-ret) ; } +static void nu_adc_touch_smpl(void *p) +{ + /* Enable interrupt */ + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_MIEN); + + /* Start conversion */ + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_MST); +} + + int rt_hw_adc_init(void) { rt_err_t result = RT_ERROR; @@ -279,8 +720,22 @@ int rt_hw_adc_init(void) g_sNuADC.m_psSem = rt_sem_create("adc_mst_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(g_sNuADC.m_psSem != RT_NULL); +#if defined(BSP_USING_ADC_TOUCH) + g_sNuADC.m_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_XYZ", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO); + RT_ASSERT(g_sNuADC.m_pmqTouchXYZ != RT_NULL); + + g_sNuADC.psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)&g_sNuADC, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC); + RT_ASSERT(g_sNuADC.psRtTouchMenuTimer != RT_NULL); +#endif + + rt_memset(&g_sNuADC.m_isr, 0, sizeof(g_sNuADC.m_isr)); + rt_memset(&g_sNuADC.m_wkisr, 0, sizeof(g_sNuADC.m_wkisr)); + + g_sNuADC.m_isr[eAdc_MF].cbfunc = AdcMenuStartCallback; + g_sNuADC.m_isr[eAdc_MF].private_data = (UINT32)&g_sNuADC; + return (int)result; } INIT_BOARD_EXPORT(rt_hw_adc_init); -#endif //#if defined(BSP_USING_EADC) +#endif //#if defined(BSP_USING_ADC) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h new file mode 100644 index 0000000000..ead185e0c1 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h @@ -0,0 +1,84 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-4-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_ADC_H__ +#define __DRV_ADC_H__ + +#include +#include "nu_adc.h" +#if defined(BSP_USING_ADC_TOUCH) + #include "touch.h" +#endif + +#define TOUCH_MQ_LENGTH 64 + +#define DEF_CAL_POINT_NUM 5 + +typedef enum +{ + eAdc_MF, //0 + eAdc_KPEF, //1 + eAdc_PEDEF, //2 + eAdc_KPUEF, //3 + eAdc_PEUEF, //4 + eAdc_TF = 8, //8 + eAdc_ZF, //9 + eAdc_NACF, //10 + eAdc_VBF, //11 + eAdc_KPCF, //12 + eAdc_SELFTF, //13 + eAdc_INTKP = 16, //16 + eAdc_INTTC, //17 + eAdc_ISR_CNT //18 +} E_ADC_ISR_EVENT; + +typedef enum +{ + eAdc_WKPEF, + eAdc_WPEDEF, + eAdc_WKISR_CNT +} E_ADC_WKISR_EVENT; + +typedef struct +{ + ADC_CALLBACK cbfunc; + uint32_t private_data; +} nu_adc_cb; + +typedef nu_adc_cb *nu_adc_cb_t; + +#if defined(BSP_USING_ADC_TOUCH) +typedef struct +{ + int32_t x; + int32_t y; +} S_COORDINATE_POINT; + +typedef struct +{ + int32_t a; + int32_t b; + int32_t c; + int32_t d; + int32_t e; + int32_t f; + int32_t div; +} S_CALIBRATION_MATRIX; + +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt); +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch); +rt_err_t nu_adc_touch_disable(void); +void nu_adc_touch_detect(rt_bool_t bStartDetect); +void nu_adc_touch_start_conv(void); +#endif + +#endif /* __DRV_ADC_H__ */ diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c new file mode 100644 index 0000000000..e995f249af --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c @@ -0,0 +1,681 @@ +/**************************************************************************//** +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-04-20 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_ADC_TOUCH) + +#include "NuMicro.h" +#include +#include +#include "drv_adc.h" +#include "touch.h" + +#if !defined(PATH_CALIBRATION_FILE) + #define PATH_CALIBRATION_FILE "/mnt/filesystem/ts_calibration" +#endif + + +typedef struct +{ + struct rt_touch_device dev; + rt_uint32_t x_range; + rt_uint32_t y_range; +} nu_adc_touch; +typedef nu_adc_touch *nu_adc_touch_t; + +static nu_adc_touch s_NuAdcTouch = {0}; + +#if (BSP_LCD_WIDTH==320) && (BSP_LCD_HEIGHT==240) +static S_CALIBRATION_MATRIX g_sCalMat = { 43, -5839, 21672848, 4193, -11, -747882, 65536 }; +static volatile uint32_t g_u32Calibrated = 1; +#else +static S_CALIBRATION_MATRIX g_sCalMat = { 1, 0, 0, 0, 1, 0, 1 }; +static volatile uint32_t g_u32Calibrated = 0; +#endif + +static int nu_adc_touch_readfile(void); + +static const S_CALIBRATION_MATRIX g_sCalZero = { 1, 0, 0, 0, 1, 0, 1 }; + +static int nu_adc_cal_mat_get(const S_COORDINATE_POINT *psDispCP, S_COORDINATE_POINT *psADCCP, S_CALIBRATION_MATRIX *psCM) +{ +#if (DEF_CAL_POINT_NUM==3) + + psCM->div = ((psADCCP[0].x - psADCCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psADCCP[1].x - psADCCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + if (psCM->div == 0) + { + return -1; + } + else + { + psCM->a = ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].x - psDispCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->b = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].x - psDispCP[2].x)) - + ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->c = (psADCCP[2].x * psDispCP[1].x - psADCCP[1].x * psDispCP[2].x) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].x - psADCCP[2].x * psDispCP[0].x) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].x - psADCCP[0].x * psDispCP[1].x) * psADCCP[2].y ; + + psCM->d = ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].y - psDispCP[2].y) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->e = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].y - psDispCP[2].y)) - + ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->f = (psADCCP[2].x * psDispCP[1].y - psADCCP[1].x * psDispCP[2].y) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].y - psADCCP[2].x * psDispCP[0].y) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].y - psADCCP[0].x * psDispCP[1].y) * psADCCP[2].y ; + } + +#elif (DEF_CAL_POINT_NUM==5) + + int i; + float n, x, y, xx, yy, xy, z, zx, zy; + float a, b, c, d, e, f, g; + float scaling = 65536.0f; + + n = x = y = xx = yy = xy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + n += 1.0; + x += (float)psADCCP[i].x; + y += (float)psADCCP[i].y; + xx += (float)psADCCP[i].x * psADCCP[i].x; + yy += (float)psADCCP[i].y * psADCCP[i].y; + xy += (float)psADCCP[i].x * psADCCP[i].y; + } + + d = n * (xx * yy - xy * xy) + x * (xy * y - x * yy) + y * (x * xy - y * xx); + if (d < 0.1 && d > -0.1) + { + return -1; + } + + a = (xx * yy - xy * xy) / d; + b = (xy * y - x * yy) / d; + c = (x * xy - y * xx) / d; + e = (n * yy - y * y) / d; + f = (x * y - n * xy) / d; + g = (n * xx - x * x) / d; + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].x; + zx += (float)psDispCP[i].x * psADCCP[i].x; + zy += (float)psDispCP[i].x * psADCCP[i].y; + } + + psCM->c = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->a = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->b = (int32_t)((c * z + f * zx + g * zy) * scaling); + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].y; + zx += (float)psDispCP[i].y * psADCCP[i].x; + zy += (float)psDispCP[i].y * psADCCP[i].y; + } + + psCM->f = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->d = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->e = (int32_t)((c * z + f * zx + g * zy) * scaling); + + psCM->div = (int32_t)scaling; + +#else +#error "Not supported calibration method" +#endif + return 0; +} + +static void nu_adc_touch_cal(int32_t *sumx, int32_t *sumy) +{ + int32_t xtemp, ytemp; + + xtemp = *sumx; + ytemp = *sumy; + *sumx = (g_sCalMat.c + + g_sCalMat.a * xtemp + + g_sCalMat.b * ytemp) / g_sCalMat.div; + *sumy = (g_sCalMat.f + + g_sCalMat.d * xtemp + + g_sCalMat.e * ytemp) / g_sCalMat.div; +} + +static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *buf, rt_size_t read_num) +{ + static uint32_t last_report_x = 0, last_report_y = 0; + struct rt_touch_data *pPoint = (struct rt_touch_data *)buf; + nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + int i; + + for (i = 0; i < read_num; i++) + { + uint32_t bufZ0 = 0, bufZ1 = 0; + int32_t sumx = 0, sumy = 0; + pPoint[i].timestamp = rt_touch_get_ts(); + pPoint[i].track_id = 0; + + if (nu_adc_touch_read_xyz((uint32_t *)&sumx, (uint32_t *)&sumy, &bufZ0, &bufZ1, 1) != 1) + break; + + if (bufZ0 == 0) + { + /* Workaround: In this case, x, y values are unstable. so, report last point's coordinate.*/ + pPoint[i].event = RT_TOUCH_EVENT_UP; + pPoint[i].x_coordinate = (uint16_t)last_report_x; + pPoint[i].y_coordinate = (uint16_t)last_report_y; + } + else + { + if (g_u32Calibrated) + { + nu_adc_touch_cal(&sumx, &sumy); + } + last_report_x = sumx; + last_report_y = sumy; + + pPoint[i].event = RT_TOUCH_EVENT_DOWN; + pPoint[i].x_coordinate = (uint16_t)sumx; + pPoint[i].y_coordinate = (uint16_t)sumy; + } + + if (g_u32Calibrated) + { + bufZ0 = bufZ0 >> 3; + pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; + + //Limit max x, y coordinate if value is over its range. + pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; + pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + } + } + return (rt_size_t)i; +} + +static rt_err_t nu_adc_touch_control(struct rt_touch_device *device, int cmd, void *data) +{ + nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; + RT_ASSERT(psNuAdcTouch != RT_NULL); + + switch (cmd) + { + case RT_TOUCH_CTRL_SET_X_RANGE: /* set x range */ + psNuAdcTouch->x_range = *((rt_int32_t *)data); + break; + + case RT_TOUCH_CTRL_SET_Y_RANGE: /* set y range */ + psNuAdcTouch->y_range = *((rt_int32_t *)data); + break; + + case RT_TOUCH_CTRL_ENABLE_INT: /* enable pen_down interrupt */ + nu_adc_touch_detect(RT_TRUE); + break; + + case RT_TOUCH_CTRL_DISABLE_INT: /* disable pen_down interrupt */ + nu_adc_touch_detect(RT_FALSE); + break; + + case RT_TOUCH_CTRL_POWER_ON: /* Touch Power On */ + return nu_adc_touch_enable(device); + + case RT_TOUCH_CTRL_POWER_OFF: /* Touch Power Off */ + return nu_adc_touch_disable(); + + default: + return -RT_ERROR; + } + return RT_EOK; +} + +static struct rt_touch_ops touch_ops = +{ + .touch_readpoint = nu_adc_touch_readpoint, + .touch_control = nu_adc_touch_control, +}; + +static void nu_adc_touch_update_calmat(S_CALIBRATION_MATRIX *psNewCalMat) +{ + if (psNewCalMat && + psNewCalMat->div != 0) + { + rt_memcpy(&g_sCalMat, psNewCalMat, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 1; + rt_kprintf("Applied calibration data: %d, %d, %d, %d, %d, %d, %d\n", + g_sCalMat.a, + g_sCalMat.b, + g_sCalMat.c, + g_sCalMat.d, + g_sCalMat.e, + g_sCalMat.f, + g_sCalMat.div); + + } +} + +static void nu_adc_touch_reset_calmat(void) +{ + rt_memcpy(&g_sCalMat, &g_sCalZero, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 0; +} + +int rt_hw_adc_touch_init(void) +{ + /* Register touch device */ + s_NuAdcTouch.dev.info.type = RT_TOUCH_TYPE_RESISTANCE; + s_NuAdcTouch.dev.info.vendor = RT_TOUCH_VENDOR_UNKNOWN; + s_NuAdcTouch.dev.info.point_num = 1; + s_NuAdcTouch.dev.info.range_x = BSP_LCD_WIDTH; + s_NuAdcTouch.dev.info.range_y = BSP_LCD_HEIGHT; + + s_NuAdcTouch.dev.ops = &touch_ops; + + return (int)rt_hw_touch_register(&s_NuAdcTouch.dev, "adc_touch", RT_DEVICE_FLAG_INT_RX, RT_NULL); +} +INIT_DEVICE_EXPORT(rt_hw_adc_touch_init); + + +static rt_thread_t adc_touch_thread = RT_NULL; +static rt_sem_t adc_touch_sem = RT_NULL; +static int adc_touch_worker_run = 0; + +static rt_err_t adc_touch_rx_callback(rt_device_t dev, rt_size_t size) +{ + //rt_kprintf("[%s %d] %d\n", __func__, __LINE__, size); + return rt_sem_release(adc_touch_sem); +} + +static rt_err_t adc_request_point(rt_device_t pdev, struct rt_touch_data *psTouchPoint) +{ + rt_err_t ret = -RT_ERROR; + + if ((ret = rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(500))) == RT_EOK) + { + rt_memset(psTouchPoint, 0, sizeof(struct rt_touch_data)); + + if (rt_device_read(pdev, 0, psTouchPoint, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + { + ret = RT_EOK; + } + + } + + return ret; +} + +RT_WEAK void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t event) +{ +} + +static rt_device_t lcd_device = 0; +static struct rt_device_graphic_info info; + +static void lcd_cleanscreen(void) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + + rt_memset(info.framebuffer, 0, (info.pitch * info.height)); + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#define DEF_DOT_NUMBER 9 +#define DOTS_NUMBER (DEF_DOT_NUMBER*DEF_DOT_NUMBER) +static void nu_draw_bots(int x, int y) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + int i, j; + int start_x = x - (DEF_DOT_NUMBER / 2); + int start_y = y - (DEF_DOT_NUMBER / 2); + + if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) + { + uint16_t *pu16Start = (uint16_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 2)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu16Start[i] = 0x07E0; //Green, RGB + pu16Start += info.width; + } + } + else if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888) + { + uint32_t *pu32Start = (uint32_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 4)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu32Start[i] = 0xff00ff00; //Green, ARGB + pu32Start += info.width; + } + } + else + { + //Not supported + } + + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#if (DEF_CAL_POINT_NUM==3) +const S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ + {BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 2}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 4}, + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / 4} +}; +#elif (DEF_CAL_POINT_NUM==5) +const static S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ +#define DEF_CUT_PIECES 8 + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT / 2} +}; +#endif + +static int nu_adc_touch_readfile(void) +{ + int fd; + + S_CALIBRATION_MATRIX sCalMat; + + if ((fd = open(PATH_CALIBRATION_FILE, O_RDONLY, 0)) < 0) + { + goto exit_nu_adc_touch_readfile; + } + else if (read(fd, &sCalMat, sizeof(S_CALIBRATION_MATRIX)) == sizeof(S_CALIBRATION_MATRIX)) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + nu_adc_touch_update_calmat(&sCalMat); + + return 0; + +exit_nu_adc_touch_readfile: + + return -1; +} + +static int nu_adc_touch_writefile(void *buf, int buf_len) +{ + int fd; + + if ((fd = open(PATH_CALIBRATION_FILE, O_WRONLY | O_CREAT, 0)) < 0) + { + goto exit_nu_adc_touch_writefile; + } + else if (write(fd, buf, buf_len) == buf_len) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + return 0; + +exit_nu_adc_touch_writefile: + + return -1; +} + +static void nu_touch_do_calibration(rt_device_t pdev) +{ + int i; + rt_err_t result; + + S_CALIBRATION_MATRIX sCalMat; + S_COORDINATE_POINT sADCPoints[DEF_CAL_POINT_NUM]; + + lcd_device = rt_device_find("lcd"); + if (!lcd_device) + { + rt_kprintf("Not supported graphics ops\n"); + return; + } + + result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK) + { + rt_kprintf("error!"); + return; + } + + result = rt_device_open(lcd_device, 0); + if (result != RT_EOK) + { + rt_kprintf("opened?"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, info.framebuffer); + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + struct rt_touch_data sTouchPoint; + int count = 0; + + lcd_cleanscreen(); + + /* Drain RX queue before doing calibrate. */ + while (adc_request_point(pdev, &sTouchPoint) == RT_EOK); + + rt_thread_mdelay(100); + + /* Ready to calibrate */ + nu_draw_bots(sDispPoints[i].x, sDispPoints[i].y); + +#define DEF_MAX_GET_POINT_NUM 5 + + sADCPoints[i].x = 0; + sADCPoints[i].y = 0; + + while (count < DEF_MAX_GET_POINT_NUM) + { + if (adc_request_point(pdev, &sTouchPoint) == RT_EOK) + { + sADCPoints[i].x += (int32_t)sTouchPoint.x_coordinate; + sADCPoints[i].y += (int32_t)sTouchPoint.y_coordinate; + rt_kprintf("[%d %d] - Disp:[%d, %d] -> ADC:[%d, %d]\n", i, count, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + count++; + } + } + + sADCPoints[i].x = (int32_t)((float)sADCPoints[i].x / DEF_MAX_GET_POINT_NUM); + sADCPoints[i].y = (int32_t)((float)sADCPoints[i].y / DEF_MAX_GET_POINT_NUM); + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + + rt_thread_mdelay(300); + } + + lcd_cleanscreen(); + + /* Get calibration matrix. */ + if (nu_adc_cal_mat_get(&sDispPoints[0], &sADCPoints[0], &sCalMat) == 0) + { + /* Finally, update calibration matrix to drivers. */ + nu_adc_touch_update_calmat(&sCalMat); + + nu_adc_touch_writefile(&sCalMat, sizeof(sCalMat)); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + } + } + else + { + rt_kprintf("Failed to calibrate.\n"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWEROFF, RT_NULL); + rt_device_close(lcd_device); + + return; +} + +static void adc_touch_entry(void *parameter) +{ + struct rt_touch_data touch_point; + + rt_err_t result; + rt_device_t pdev; + + int max_range; + + adc_touch_sem = rt_sem_create("adc_touch_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(adc_touch_sem != RT_NULL); + + pdev = rt_device_find("adc_touch"); + if (!pdev) + { + rt_kprintf("Not found\n"); + return ; + } + + nu_adc_touch_readfile(); + + result = rt_device_open(pdev, RT_DEVICE_FLAG_INT_RX); + RT_ASSERT(result == RT_EOK); + + result = rt_device_set_rx_indicate(pdev, adc_touch_rx_callback); + RT_ASSERT(result == RT_EOK); + + max_range = BSP_LCD_WIDTH; + result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_X_RANGE, (void *)&max_range); + RT_ASSERT(result == RT_EOK); + + max_range = BSP_LCD_HEIGHT; + result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); + RT_ASSERT(result == RT_EOK); + + result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_ON, RT_NULL); + RT_ASSERT(result == RT_EOK); + + while (adc_touch_worker_run) + { + if (!g_u32Calibrated) + { + rt_kprintf("Start ADC touching calibration.\n"); + nu_touch_do_calibration(pdev); + rt_kprintf("Stop ADC touching calibration.\n"); + continue; + } + + if (adc_request_point(pdev, &touch_point) == RT_EOK) + { + if (touch_point.event == RT_TOUCH_EVENT_DOWN + || touch_point.event == RT_TOUCH_EVENT_UP + || touch_point.event == RT_TOUCH_EVENT_MOVE) + { + nu_touch_inputevent_cb(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); + + rt_kprintf("x=%d y=%d event=%s%s%s\n", + touch_point.x_coordinate, + touch_point.y_coordinate, + (touch_point.event == RT_TOUCH_EVENT_DOWN) ? "DOWN" : "", + (touch_point.event == RT_TOUCH_EVENT_UP) ? "UP" : "", + (touch_point.event == RT_TOUCH_EVENT_MOVE) ? "MOVE" : ""); + } + } + } + + result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_OFF, RT_NULL); + RT_ASSERT(result == RT_EOK); + + result = rt_device_close(pdev); + RT_ASSERT(result == RT_EOK); +} + + +/* Support "nu_touch_start" command line in msh mode */ +static rt_err_t nu_touch_start(int argc, char **argv) +{ + if (adc_touch_thread == RT_NULL) + { + adc_touch_thread = rt_thread_create("adc_touch_thread", + adc_touch_entry, + RT_NULL, + 4096, + 25, + 5); + adc_touch_worker_run = 1; + if (adc_touch_thread != RT_NULL) + rt_thread_startup(adc_touch_thread); + } + return 0; +} +MSH_CMD_EXPORT(nu_touch_start, e.g: start adc touch); + +/* Support "nu_touch_stop" command line in msh mode */ +static rt_err_t nu_touch_stop(int argc, char **argv) +{ + adc_touch_worker_run = 0; + adc_touch_thread = RT_NULL; + return 0; +} +MSH_CMD_EXPORT(nu_touch_stop, e.g: stop adc touch); + +static int nu_touch_autostart(void) +{ + return nu_touch_start(0, RT_NULL); +} +INIT_APP_EXPORT(nu_touch_autostart); + +static rt_err_t nu_touch_calibration(int argc, char **argv) +{ + /* Clean calibration matrix data for getting raw adc value. */ + nu_adc_touch_reset_calmat(); + + return 0; +} +MSH_CMD_EXPORT(nu_touch_calibration, for adc touch); + +#endif //#if defined(BSP_USING_ADC_TOUCH) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c index 252ca1e1ae..9e94e347ca 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c @@ -682,7 +682,7 @@ lwiperf_report(void *arg, enum lwiperf_report_type report_type, (int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec); } -void lwiperf_example_init(void) +void lwiperf_example_init(int argc, char **argv) { lwiperf_start_tcp_server_default(lwiperf_report, NULL); } diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config index dd0c4cefb2..1339d389e1 100644 --- a/bsp/nuvoton/nk-980iot/.config +++ b/bsp/nuvoton/nk-980iot/.config @@ -203,8 +203,7 @@ CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096 CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2 CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048 # CONFIG_RT_USING_SENSOR is not set -CONFIG_RT_USING_TOUCH=y -# CONFIG_RT_TOUCH_PIN_IRQ is not set +# CONFIG_RT_USING_TOUCH is not set CONFIG_RT_USING_HWCRYPTO=y CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto" CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16 @@ -550,17 +549,11 @@ CONFIG_PKG_NETUTILS_VER_NUM=0x10301 # # LVGL: powerful and easy-to-use embedded GUI library # -CONFIG_PKG_USING_LVGL=y -CONFIG_PKG_LVGL_PATH="/packages/multimedia/LVGL/LVGL" -# CONFIG_PKG_USING_LVGL_EXAMPLES is not set -CONFIG_PKG_USING_LVGL_V810=y +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LVGL_V810 is not set # CONFIG_PKG_USING_LVGL_LATEST_VERSION is not set -CONFIG_PKG_LVGL_VER="v8.1.0" -CONFIG_PKG_LVGL_VER_NUM=0x08010 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set -CONFIG_PKG_USING_LV_MUSIC_DEMO=y -CONFIG_PKG_LV_MUSIC_DEMO_PATH="/packages/multimedia/LVGL/lv_music_demo" -CONFIG_PKG_LV_MUSIC_DEMO_VER="v0.1.1" +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set # # u8g2: a monochrome graphic library @@ -597,6 +590,7 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -607,7 +601,6 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -658,6 +651,7 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -783,6 +777,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -874,23 +869,8 @@ CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -CONFIG_NU_PKG_USING_NAU8822=y -# CONFIG_NU_PKG_USING_DA9062 is not set -CONFIG_NU_PKG_USING_ILI9341=y -CONFIG_NU_PKG_USING_ILI9341_SPI=y -# CONFIG_NU_PKG_USING_ILI9341_EBI is not set -CONFIG_NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER=y -CONFIG_NU_PKG_ILI9341_HORIZONTAL=y -CONFIG_NU_PKG_USING_SPINAND=y +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -913,6 +893,7 @@ CONFIG_BSP_USING_RTC=y CONFIG_NU_RTC_SUPPORT_IO_RW=y CONFIG_NU_RTC_SUPPORT_MSH_CMD=y CONFIG_BSP_USING_ADC=y +# CONFIG_BSP_USING_ADC_TOUCH is not set CONFIG_BSP_USING_TMR=y CONFIG_BSP_USING_TIMER=y CONFIG_BSP_USING_TMR0=y @@ -998,10 +979,20 @@ CONFIG_BOARD_USING_USB1_HOST=y # Board extended module drivers # # CONFIG_BOARD_USING_MAX31875 is not set -CONFIG_BOARD_USING_LCD_ILI9341=y -CONFIG_BOARD_USING_ILI9341_PIN_BACKLIGHT=103 -CONFIG_BOARD_USING_ILI9341_PIN_RESET=90 -CONFIG_BOARD_USING_ILI9341_PIN_DC=89 +# CONFIG_BOARD_USING_LCD_ILI9341 is not set # CONFIG_BOARD_USING_ESP8266 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +CONFIG_NU_PKG_USING_SPINAND=y CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." diff --git a/bsp/nuvoton/nk-980iot/board/Kconfig b/bsp/nuvoton/nk-980iot/board/Kconfig index ff8ddf85ec..e623161d9e 100644 --- a/bsp/nuvoton/nk-980iot/board/Kconfig +++ b/bsp/nuvoton/nk-980iot/board/Kconfig @@ -72,6 +72,7 @@ menu "Hardware Drivers Config" config BOARD_USING_LCD_ILI9341 bool "LCD ILI9341 (over spi0)" select RT_USING_TOUCH + select BSP_USING_ADC_TOUCH select NU_PKG_USING_ILI9341 select NU_PKG_USING_ILI9341_SPI select NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER diff --git a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c index 97ab099cfa..0ab0bb1f71 100644 --- a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c +++ b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c @@ -57,8 +57,10 @@ static void nu_pin_i2c_init(void) /* I2C0: PA[0, 1] */ outpw(REG_SYS_GPA_MFPL, (inpw(REG_SYS_GPA_MFPL) & ~0x000000FF) | 0x00000033); +#if !defined(BSP_USING_ADC_TOUCH) /* I2C2: PB5, PB7 */ outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & ~0xF0F00000) | 0x20200000); +#endif } diff --git a/bsp/nuvoton/nk-980iot/rtconfig.py b/bsp/nuvoton/nk-980iot/rtconfig.py index 1f8263adae..7412b89abf 100644 --- a/bsp/nuvoton/nk-980iot/rtconfig.py +++ b/bsp/nuvoton/nk-980iot/rtconfig.py @@ -85,4 +85,10 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' - POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file + POST_ACTION += 'fromelf -z $TARGET\n' +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuvoton/nk-980iot/spinor.config b/bsp/nuvoton/nk-980iot/spinor.config index d93d276436..689099bb5b 100644 --- a/bsp/nuvoton/nk-980iot/spinor.config +++ b/bsp/nuvoton/nk-980iot/spinor.config @@ -7,6 +7,7 @@ # RT-Thread Kernel # CONFIG_RT_NAME_MAX=16 +# CONFIG_RT_USING_BIG_ENDIAN is not set # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 @@ -17,10 +18,19 @@ CONFIG_RT_THREAD_PRIORITY_MAX=32 CONFIG_RT_TICK_PER_SECOND=1000 CONFIG_RT_USING_OVERFLOW_CHECK=y CONFIG_RT_USING_HOOK=y +CONFIG_RT_HOOK_USING_FUNC_PTR=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=2048 # CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -48,13 +58,18 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_MEMHEAP=y -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_MEMHEAP_FAST_MODE=y +# CONFIG_RT_MEMHEAP_BSET_MODE is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_MEMTRACE=y +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -66,7 +81,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_ARM9=y @@ -79,6 +94,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -89,25 +105,26 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # Command shell # CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=5 CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set -CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 -CONFIG_FINSH_CMD_SIZE=80 # CONFIG_FINSH_USING_AUTH is not set -CONFIG_FINSH_USING_MSH=y -CONFIG_FINSH_USING_MSH_DEFAULT=y -# CONFIG_FINSH_USING_MSH_ONLY is not set CONFIG_FINSH_ARG_MAX=10 # # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=16 CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 @@ -125,27 +142,32 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y # CONFIG_RT_DFS_ELM_USE_LFN_2 is not set CONFIG_RT_DFS_ELM_USE_LFN_3=y CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y +# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set +CONFIG_RT_DFS_ELM_LFN_UNICODE=0 CONFIG_RT_DFS_ELM_MAX_LFN=255 CONFIG_RT_DFS_ELM_DRIVES=8 CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=4096 # CONFIG_RT_DFS_ELM_USE_ERASE is not set CONFIG_RT_DFS_ELM_REENTRANT=y +CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000 CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set -# CONFIG_RT_USING_DFS_UFFS is not set -# CONFIG_RT_USING_DFS_JFFS2 is not set # CONFIG_RT_USING_DFS_NFS is not set # # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=512 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=2048 CONFIG_RT_USING_CAN=y @@ -167,9 +189,6 @@ CONFIG_RT_USING_PWM=y CONFIG_RT_USING_RTC=y CONFIG_RT_USING_ALARM=y # CONFIG_RT_USING_SOFT_RTC is not set -CONFIG_RTC_SYNC_USING_NTP=y -CONFIG_RTC_NTP_FIRST_SYNC_DELAY=30 -CONFIG_RTC_NTP_SYNC_PERIOD=3600 # CONFIG_RT_USING_SDIO is not set CONFIG_RT_USING_SPI=y CONFIG_RT_USING_QSPI=y @@ -220,9 +239,11 @@ CONFIG_RT_HWCRYPTO_USING_RNG=y # # Using USB # +CONFIG_RT_USING_USB=y CONFIG_RT_USING_USB_HOST=y CONFIG_RT_USBH_MSTORAGE=y CONFIG_UDISK_MOUNTPOINT="/mnt/udisk" +# CONFIG_RT_USBH_HID is not set CONFIG_RT_USING_USB_DEVICE=y CONFIG_RT_USBD_THREAD_STACK_SZ=4096 CONFIG_USB_VENDOR_ID=0x0FFE @@ -247,14 +268,34 @@ CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set -# CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set -# CONFIG_RT_USING_POSIX_AIO is not set # CONFIG_RT_USING_MODULE is not set +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_STDIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y +# CONFIG_RT_USING_POSIX_TERMIOS is not set +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -264,7 +305,7 @@ CONFIG_RT_USING_POSIX=y # Socket abstraction layer # CONFIG_RT_USING_SAL=y -CONFIG_SAL_INTERNET_CHECK=y +# CONFIG_SAL_INTERNET_CHECK is not set # # protocol stack implement @@ -290,8 +331,9 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP212 is not set +# CONFIG_RT_USING_LWIP202 is not set +# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP212=y # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 CONFIG_RT_LWIP_IGMP=y @@ -305,30 +347,30 @@ CONFIG_IP_SOF_BROADCAST_RECV=1 # # Static IPv4 Address # -CONFIG_RT_LWIP_IPADDR="192.168.1.30" -CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_IPADDR="192.168.31.55" +CONFIG_RT_LWIP_GWADDR="192.168.31.1" CONFIG_RT_LWIP_MSKADDR="255.255.255.0" CONFIG_RT_LWIP_UDP=y CONFIG_RT_LWIP_TCP=y CONFIG_RT_LWIP_RAW=y # CONFIG_RT_LWIP_PPP is not set -CONFIG_RT_MEMP_NUM_NETCONN=32 +CONFIG_RT_MEMP_NUM_NETCONN=16 CONFIG_RT_LWIP_PBUF_NUM=256 -CONFIG_RT_LWIP_RAW_PCB_NUM=32 -CONFIG_RT_LWIP_UDP_PCB_NUM=32 -CONFIG_RT_LWIP_TCP_PCB_NUM=32 -CONFIG_RT_LWIP_TCP_SEG_NUM=256 -CONFIG_RT_LWIP_TCP_SND_BUF=32768 -CONFIG_RT_LWIP_TCP_WND=10240 +CONFIG_RT_LWIP_RAW_PCB_NUM=16 +CONFIG_RT_LWIP_UDP_PCB_NUM=16 +CONFIG_RT_LWIP_TCP_PCB_NUM=16 +CONFIG_RT_LWIP_TCP_SEG_NUM=64 +CONFIG_RT_LWIP_TCP_SND_BUF=16384 +CONFIG_RT_LWIP_TCP_WND=65535 CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 -CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=32 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=256 CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=4096 # CONFIG_LWIP_NO_RX_THREAD is not set # CONFIG_LWIP_NO_TX_THREAD is not set CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 -CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024 -CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=32 -# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=4096 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=256 +CONFIG_RT_LWIP_REASSEMBLY_FRAG=y CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 CONFIG_LWIP_NETIF_LINK_CALLBACK=1 CONFIG_SO_REUSE=1 @@ -362,8 +404,15 @@ CONFIG_RT_LWIP_USING_PING=y CONFIG_RT_USING_UTEST=y CONFIG_UTEST_THR_STACK_SIZE=4096 CONFIG_UTEST_THR_PRIORITY=20 +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set # CONFIG_RT_USING_LWP is not set +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + # # RT-Thread online packages # @@ -411,22 +460,25 @@ CONFIG_PKG_NETUTILS_TFTP=y CONFIG_PKG_NETUTILS_IPERF=y # CONFIG_PKG_NETUTILS_NETIO is not set CONFIG_PKG_NETUTILS_NTP=y -CONFIG_NETUTILS_NTP_TIMEZONE=8 +CONFIG_NTP_USING_AUTO_SYNC=y +CONFIG_NTP_AUTO_SYNC_FIRST_DELAY=30 +CONFIG_NTP_AUTO_SYNC_PERIOD=3600 CONFIG_NETUTILS_NTP_HOSTNAME="0.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME2="1.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME3="2.tw.pool.ntp.org" # CONFIG_PKG_NETUTILS_TELNET is not set # CONFIG_PKG_NETUTILS_TCPDUMP is not set -CONFIG_PKG_USING_NETUTILS_V120=y -# CONFIG_PKG_USING_NETUTILS_V110 is not set -# CONFIG_PKG_USING_NETUTILS_V100 is not set # CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set -CONFIG_PKG_NETUTILS_VER="v1.2.0" +CONFIG_PKG_USING_NETUTILS_V131=y +# CONFIG_PKG_USING_NETUTILS_V130 is not set +CONFIG_PKG_NETUTILS_VER="v1.3.1" +CONFIG_PKG_NETUTILS_VER_NUM=0x10301 # CONFIG_PKG_USING_CMUX is not set # CONFIG_PKG_USING_PPP_DEVICE is not set # CONFIG_PKG_USING_AT_DEVICE is not set # CONFIG_PKG_USING_ATSRV_SOCKET is not set # CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set # # IoT Cloud @@ -439,6 +491,7 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_JIOT-C-SDK is not set # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set # CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_EZ_IOT_OS is not set # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set @@ -447,8 +500,6 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -462,12 +513,26 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_PDULIB is not set # CONFIG_PKG_USING_BTSTACK is not set # CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -475,21 +540,51 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # # language packages # +# CONFIG_PKG_USING_LUATOS_SOC is not set # CONFIG_PKG_USING_LUA is not set # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set # # multimedia packages # + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set # CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set # CONFIG_PKG_USING_HELIX is not set # CONFIG_PKG_USING_AZUREGUIX is not set # CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -498,9 +593,11 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_EASYFLASH is not set # CONFIG_PKG_USING_EASYLOGGER is not set # CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set # CONFIG_PKG_USING_ADBD is not set # CONFIG_PKG_USING_COREMARK is not set # CONFIG_PKG_USING_DHRYSTONE is not set @@ -514,15 +611,72 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_UMCN is not set # CONFIG_PKG_USING_LWRB2RTT is not set # CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +CONFIG_PKG_USING_MEM_SANDBOX=y +CONFIG_PKG_MEM_SANDBOX_PATH="/packages/tools/mem_sandbox" +CONFIG_PKG_USING_MEM_SANDBOX_LATEST_VERSION=y +CONFIG_PKG_MEM_SANDBOX_VER="latest" +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set # # system packages # + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set +# CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set CONFIG_PKG_USING_FAL=y CONFIG_PKG_FAL_PATH="/packages/system/fal" @@ -542,10 +696,11 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set -# CONFIG_PKG_USING_LITTLEVGL2RTT is not set -# CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_THREAD_POOL is not set # CONFIG_PKG_USING_ROBOTS is not set # CONFIG_PKG_USING_EV is not set @@ -559,17 +714,15 @@ CONFIG_PKG_USING_RAMDISK_LATEST_VERSION=y CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UCOSII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set -# CONFIG_PKG_USING_UC_MODBUS is not set # CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set # # peripheral libraries and drivers @@ -578,9 +731,9 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -593,7 +746,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set -# CONFIG_PKG_USING_ROSSERIAL is not set # CONFIG_PKG_USING_AGILE_BUTTON is not set # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set @@ -627,16 +779,73 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set +# CONFIG_PKG_USING_CW2015 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set # # miscellaneous packages # + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set CONFIG_PKG_USING_OPTPARSE=y CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" -CONFIG_PKG_USING_OPTPARSE_V100=y -# CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION is not set -CONFIG_PKG_OPTPARSE_VER="v1.0.0" +CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION=y +CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_OPTPARSE_USING_DEMO is not set # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set @@ -646,69 +855,44 @@ CONFIG_PKG_OPTPARSE_VER="v1.0.0" # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_CANFESTIVAL is not set # CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set # CONFIG_PKG_USING_DSTR is not set # CONFIG_PKG_USING_TINYFRAME is not set # CONFIG_PKG_USING_KENDRYTE_DEMO is not set # CONFIG_PKG_USING_DIGITALCTRL is not set # CONFIG_PKG_USING_UPACKER is not set # CONFIG_PKG_USING_UPARAM is not set - -# -# samples: kernel and components samples -# -# CONFIG_PKG_USING_KERNEL_SAMPLES is not set -# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set -# CONFIG_PKG_USING_NETWORK_SAMPLES is not set -# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set CONFIG_PKG_USING_VI=y CONFIG_PKG_VI_PATH="/packages/misc/vi" +CONFIG_VI_SANDBOX_SIZE_KB=20 CONFIG_VI_MAX_LEN=4096 # CONFIG_VI_ENABLE_8BIT is not set CONFIG_VI_ENABLE_COLON=y +CONFIG_VI_ENABLE_COLON_EXPAND=y CONFIG_VI_ENABLE_YANKMARK=y CONFIG_VI_ENABLE_SEARCH=y CONFIG_VI_ENABLE_DOT_CMD=y CONFIG_VI_ENABLE_READONLY=y CONFIG_VI_ENABLE_SETOPTS=y CONFIG_VI_ENABLE_SET=y +# CONFIG_VI_ENABLE_WIN_RESIZE is not set CONFIG_VI_ENABLE_VI_ASK_TERMINAL=y CONFIG_VI_ENABLE_UNDO=y CONFIG_VI_ENABLE_UNDO_QUEUE=y CONFIG_VI_UNDO_QUEUE_MAX=256 +CONFIG_VI_ENABLE_VERBOSE_STATUS=y CONFIG_PKG_USING_VI_LATEST_VERSION=y CONFIG_PKG_VI_VER="latest" # CONFIG_PKG_USING_KI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set - -# -# games: games run on RT-Thread console -# -# CONFIG_PKG_USING_THREES is not set -# CONFIG_PKG_USING_2048 is not set -# CONFIG_PKG_USING_SNAKE is not set -# CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_LWGPS is not set -# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -CONFIG_NU_PKG_USING_NAU8822=y -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -718,12 +902,11 @@ CONFIG_NU_PKG_USING_NAU8822=y # On-chip Peripheral Drivers # CONFIG_SOC_SERIES_NUC980=y -# CONFIG_BSP_USE_STDDRIVER_SOURCE is not set +CONFIG_BSP_USE_STDDRIVER_SOURCE=y CONFIG_BSP_USING_MMU=y CONFIG_BSP_USING_PDMA=y CONFIG_NU_PDMA_MEMFUN_ACTOR_MAX=2 CONFIG_BSP_USING_GPIO=y -# CONFIG_BSP_USING_CLK is not set CONFIG_BSP_USING_EMAC=y CONFIG_BSP_USING_EMAC0=y # CONFIG_BSP_USING_EMAC1 is not set @@ -732,27 +915,23 @@ CONFIG_BSP_USING_RTC=y CONFIG_NU_RTC_SUPPORT_IO_RW=y CONFIG_NU_RTC_SUPPORT_MSH_CMD=y CONFIG_BSP_USING_ADC=y +# CONFIG_BSP_USING_ADC_TOUCH is not set CONFIG_BSP_USING_TMR=y CONFIG_BSP_USING_TIMER=y CONFIG_BSP_USING_TMR0=y CONFIG_BSP_USING_TIMER0=y -# CONFIG_BSP_USING_TPWM0 is not set # CONFIG_BSP_USING_TIMER0_CAPTURE is not set CONFIG_BSP_USING_TMR1=y CONFIG_BSP_USING_TIMER1=y -# CONFIG_BSP_USING_TPWM1 is not set # CONFIG_BSP_USING_TIMER1_CAPTURE is not set CONFIG_BSP_USING_TMR2=y CONFIG_BSP_USING_TIMER2=y -# CONFIG_BSP_USING_TPWM2 is not set # CONFIG_BSP_USING_TIMER2_CAPTURE is not set CONFIG_BSP_USING_TMR3=y CONFIG_BSP_USING_TIMER3=y -# CONFIG_BSP_USING_TPWM3 is not set # CONFIG_BSP_USING_TIMER3_CAPTURE is not set CONFIG_BSP_USING_TMR4=y CONFIG_BSP_USING_TIMER4=y -# CONFIG_BSP_USING_TPWM4 is not set # CONFIG_BSP_USING_TIMER4_CAPTURE is not set CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART0=y @@ -794,8 +973,9 @@ CONFIG_BSP_USING_SPI1_NONE=y CONFIG_BSP_USING_I2S=y CONFIG_NU_I2S_DMA_FIFO_SIZE=4096 CONFIG_BSP_USING_QSPI=y +# CONFIG_BSP_USING_QSPI_PDMA is not set CONFIG_BSP_USING_QSPI0=y -CONFIG_BSP_USING_QSPI0_PDMA=y +# CONFIG_BSP_USING_QSPI0_PDMA is not set # CONFIG_BSP_USING_SCUART is not set CONFIG_BSP_USING_CRYPTO=y # CONFIG_NU_PRNG_USE_SEED is not set @@ -823,5 +1003,18 @@ CONFIG_BOARD_USING_USB1_HOST=y # CONFIG_BOARD_USING_MAX31875 is not set # CONFIG_BOARD_USING_LCD_ILI9341 is not set # CONFIG_BOARD_USING_ESP8266 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." diff --git a/bsp/nuvoton/nk-n9h30/rtconfig.py b/bsp/nuvoton/nk-n9h30/rtconfig.py index 79a4da1d49..cdca30ea1a 100644 --- a/bsp/nuvoton/nk-n9h30/rtconfig.py +++ b/bsp/nuvoton/nk-n9h30/rtconfig.py @@ -85,4 +85,10 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' - POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file + POST_ACTION += 'fromelf -z $TARGET\n' +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuvoton/nk-rtu980/rtconfig.py b/bsp/nuvoton/nk-rtu980/rtconfig.py index c246b656ad..07f75ed3e0 100644 --- a/bsp/nuvoton/nk-rtu980/rtconfig.py +++ b/bsp/nuvoton/nk-rtu980/rtconfig.py @@ -85,4 +85,10 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' - POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file + POST_ACTION += 'fromelf -z $TARGET\n' +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuvoton/numaker-iot-m487/rtconfig.py b/bsp/nuvoton/numaker-iot-m487/rtconfig.py index 902a2bdce9..7beeafe88a 100644 --- a/bsp/nuvoton/numaker-iot-m487/rtconfig.py +++ b/bsp/nuvoton/numaker-iot-m487/rtconfig.py @@ -130,3 +130,11 @@ elif PLATFORM == 'iar': EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/numaker-m032ki/rtconfig.py b/bsp/nuvoton/numaker-m032ki/rtconfig.py index bc7ec5b5c1..1061a7f5fd 100644 --- a/bsp/nuvoton/numaker-m032ki/rtconfig.py +++ b/bsp/nuvoton/numaker-m032ki/rtconfig.py @@ -122,3 +122,11 @@ elif PLATFORM == 'iar': EXEC_PATH += '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/numaker-m2354/.config b/bsp/nuvoton/numaker-m2354/.config index 6aaea5e9ef..12f8e22bcc 100644 --- a/bsp/nuvoton/numaker-m2354/.config +++ b/bsp/nuvoton/numaker-m2354/.config @@ -557,6 +557,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -567,7 +568,6 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -618,6 +618,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -652,14 +653,14 @@ CONFIG_FAL_DEBUG_CONFIG=y CONFIG_FAL_DEBUG=1 CONFIG_FAL_PART_HAS_TABLE_CFG=y # CONFIG_FAL_USING_SFUD_PORT is not set -CONFIG_PKG_USING_FAL_V00500=y +# CONFIG_PKG_USING_FAL_V00500 is not set # CONFIG_PKG_USING_FAL_V00400 is not set # CONFIG_PKG_USING_FAL_V00300 is not set # CONFIG_PKG_USING_FAL_V00200 is not set # CONFIG_PKG_USING_FAL_V00100 is not set -# CONFIG_PKG_USING_FAL_LATEST_VERSION is not set -CONFIG_PKG_FAL_VER="v0.5.0" -CONFIG_PKG_FAL_VER_NUM=0x00500 +CONFIG_PKG_USING_FAL_LATEST_VERSION=y +CONFIG_PKG_FAL_VER="latest" +CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set @@ -742,6 +743,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -829,19 +831,8 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -# CONFIG_NU_PKG_USING_NAU8822 is not set -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -947,5 +938,18 @@ CONFIG_BOARD_USING_OTG=y # Board extended module drivers # CONFIG_BOARD_USING_SEGMENT_LCD=y + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +# CONFIG_NU_PKG_USING_NAU8822 is not set +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-m2354.test.utest." diff --git a/bsp/nuvoton/numaker-m2354/rtconfig.py b/bsp/nuvoton/numaker-m2354/rtconfig.py index 2a59f1a4f0..2b2d5c86f7 100644 --- a/bsp/nuvoton/numaker-m2354/rtconfig.py +++ b/bsp/nuvoton/numaker-m2354/rtconfig.py @@ -122,3 +122,11 @@ elif PLATFORM == 'iar': EXEC_PATH += '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index a9899d212f..84c9359e02 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -578,6 +578,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -588,7 +589,6 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -639,6 +639,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -675,13 +676,13 @@ CONFIG_FAL_DEBUG=1 CONFIG_FAL_PART_HAS_TABLE_CFG=y # CONFIG_FAL_USING_SFUD_PORT is not set # CONFIG_PKG_USING_FAL_V00500 is not set -CONFIG_PKG_USING_FAL_V00400=y +# CONFIG_PKG_USING_FAL_V00400 is not set # CONFIG_PKG_USING_FAL_V00300 is not set # CONFIG_PKG_USING_FAL_V00200 is not set # CONFIG_PKG_USING_FAL_V00100 is not set -# CONFIG_PKG_USING_FAL_LATEST_VERSION is not set -CONFIG_PKG_FAL_VER="v0.4.0" -CONFIG_PKG_FAL_VER_NUM=0x00400 +CONFIG_PKG_USING_FAL_LATEST_VERSION=y +CONFIG_PKG_FAL_VER="latest" +CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set @@ -764,6 +765,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -851,19 +853,8 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -CONFIG_NU_PKG_USING_NAU88L25=y -# CONFIG_NU_PKG_USING_NAU8822 is not set -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -975,5 +966,18 @@ CONFIG_BOARD_USING_HSUSBH_USBD=y # Board extended module drivers # # CONFIG_BOARD_USING_ADVANCE_V4 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +CONFIG_NU_PKG_USING_NAU88L25=y +# CONFIG_NU_PKG_USING_NAU8822 is not set +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-pfm-m487.test.utest." diff --git a/bsp/nuvoton/numaker-pfm-m487/rtconfig.py b/bsp/nuvoton/numaker-pfm-m487/rtconfig.py index 902a2bdce9..7beeafe88a 100644 --- a/bsp/nuvoton/numaker-pfm-m487/rtconfig.py +++ b/bsp/nuvoton/numaker-pfm-m487/rtconfig.py @@ -130,3 +130,11 @@ elif PLATFORM == 'iar': EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/tools/sdk_dist.py b/bsp/nuvoton/tools/sdk_dist.py new file mode 100644 index 0000000000..d76f7fcfc8 --- /dev/null +++ b/bsp/nuvoton/tools/sdk_dist.py @@ -0,0 +1,39 @@ +import os +import sys +import shutil +cwd_path = os.getcwd() +sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools')) + +def dist_modify_relative_path(board_kconfig_path): + # Read in the file + with open(board_kconfig_path, 'r') as file : + filedata = file.read() + + # Replace the target string + filedata = filedata.replace('$BSP_DIR/../libraries', './libraries') + + # Write the file out again + with open(board_kconfig_path, 'w') as file: + file.write(filedata) + +# BSP dist function +def dist_do_building(BSP_ROOT, dist_dir): + from mkdist import bsp_copy_files + import rtconfig + + library_path = os.path.join(os.path.dirname(BSP_ROOT), 'libraries') + library_dir = os.path.join(dist_dir, 'libraries') + + print('=> copy nuvoton bsp drivers') + bsp_copy_files(os.path.join(library_path, rtconfig.BSP_LIBRARY_TYPE), + os.path.join(library_dir, rtconfig.BSP_LIBRARY_TYPE)) + + print('=> copy nu_packages') + bsp_copy_files(os.path.join(library_path, 'nu_packages'), + os.path.join(library_dir, 'nu_packages')) + + print('=> copy Kconfig') + shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + print('=> Modify libraries relative path in board/Kconfig ') + dist_modify_relative_path(os.path.join(dist_dir, 'board', 'Kconfig')) \ No newline at end of file From 3ac9eece5a7b38ebdd90e8cd47a4e1d6fde5105d Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 8 Jan 2022 16:30:22 -0500 Subject: [PATCH 10/65] =?UTF-8?q?[kernel]=20rt=5Fthread=5Fsuspend/resume?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/thread.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/thread.c b/src/thread.c index d1cc848777..6c221c1f29 100644 --- a/src/thread.c +++ b/src/thread.c @@ -805,7 +805,11 @@ RTM_EXPORT(rt_thread_control); /** * @brief This function will suspend the specified thread and change it to suspend state. * - * @note This function only can suspend current thread itself. + * @note This function ONLY can suspend current thread itself. + * Do not use the rt_thread_suspend and rt_thread_resume functions to synchronize the activities of threads. + * You have no way of knowing what code a thread is executing when you suspend it. + * If you suspend a thread while it is executing a critical area which is protected by a mutex, + * other threads attempt to use that mutex and have to wait. Deadlocks can occur very easily. * * @param thread is the thread to be suspended. * @@ -833,11 +837,6 @@ rt_err_t rt_thread_suspend(rt_thread_t thread) /* disable interrupt */ temp = rt_hw_interrupt_disable(); - if (stat == RT_THREAD_RUNNING) - { - /* not suspend running status thread on other core */ - RT_ASSERT(thread == rt_thread_self()); - } /* change thread stat */ rt_schedule_remove_thread(thread); @@ -857,6 +856,8 @@ RTM_EXPORT(rt_thread_suspend); /** * @brief This function will resume a thread and put it to system ready queue. * + * @note Do not use the rt_thread_suspend and rt_thread_resume functions to synchronize the activities of threads. + * * @param thread is the thread to be resumed. * * @return Return the operation status. If the return value is RT_EOK, the function is successfully executed. From 211090203b9a15c25211ff88f6765298b7024922 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 12 Jan 2022 18:30:05 -0500 Subject: [PATCH 11/65] [kernel] remove RT_THREAD_BLOCK --- include/rtdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rtdef.h b/include/rtdef.h index 664f4cb396..e9f8cb8068 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -40,6 +40,7 @@ * 2021-12-21 Meco Man re-implement RT_UNUSED * 2022-01-01 Gabriel improve hooking method * 2022-01-07 Gabriel move some __on_rt_xxxxx_hook to dedicated c soure files + * 2022-01-12 Meco Man remove RT_THREAD_BLOCK */ #ifndef __RT_DEF_H__ @@ -545,7 +546,6 @@ typedef siginfo_t rt_siginfo_t; #define RT_THREAD_READY 0x01 /**< Ready status */ #define RT_THREAD_SUSPEND 0x02 /**< Suspend status */ #define RT_THREAD_RUNNING 0x03 /**< Running status */ -#define RT_THREAD_BLOCK RT_THREAD_SUSPEND /**< Blocked status */ #define RT_THREAD_CLOSE 0x04 /**< Closed status */ #define RT_THREAD_STAT_MASK 0x07 From 3d2e23ec1c5140c8750c71ebf37c197f6048b94e Mon Sep 17 00:00:00 2001 From: liukangcc Date: Tue, 11 Jan 2022 15:20:14 +0800 Subject: [PATCH 12/65] [update] move dfs_posix.h to legacy/dfs/dfs_posix.h --- .../ab32vg1-ab-prougen/applications/mnt.c | 6 +++++- bsp/efm32/application.c | 10 +++++++++- bsp/ft2004/drivers/drv_sdcard.c | 6 +++++- bsp/lpc54114-lite/applications/mnt.c | 5 ++++- bsp/mini4020/applications/application.c | 6 +++++- bsp/nrf5x/nrf52832/applications/mnt.c | 6 +++++- bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c | 8 ++++++-- bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c | 8 ++++++-- bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c | 8 ++++++-- .../nu_packages/AudioCodec/audio_test.c | 6 +++++- .../libraries/nuc980/rtt_port/drv_sdh.c | 8 ++++++-- bsp/nuvoton/nk-980iot/applications/mnt.c | 8 ++++++-- bsp/nuvoton/nk-n9h30/applications/mnt.c | 8 ++++++-- bsp/nuvoton/nk-rtu980/applications/mnt.c | 8 ++++++-- .../numaker-iot-m487/applications/mnt.c | 8 ++++++-- bsp/nuvoton/numaker-m032ki/applications/mnt.c | 8 ++++++-- .../numaker-pfm-m487/applications/mnt.c | 8 ++++++-- bsp/simulator/drivers/module_win32.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/drv_sdcard.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/drv_filesystem.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/drv_sdcard.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/drv_ov2640.c | 6 +++++- .../board/ports/drv_sdcard.c | 6 +++++- .../board/ports/sdcard_port.c | 6 +++++- .../board/ports/audio/audio_play.c | 6 +++++- .../board/ports/drv_ov5640.c | 6 +++++- .../stm32mp157a-st-ev1/board/ports/drv_sound.c | 6 +++++- bsp/swm320-lq100/applications/main.c | 18 +++++++++++++++--- bsp/swm320/applications/main.c | 18 +++++++++++++++--- components/drivers/serial/serial.c | 5 ++++- components/drivers/serial/serial_v2.c | 4 +++- components/drivers/src/pipe.c | 5 +++-- components/finsh/msh.c | 5 ++++- components/finsh/msh_file.c | 5 ++++- components/finsh/shell.c | 4 +++- .../{dfs/include => legacy/dfs}/dfs_posix.h | 0 components/libc/compilers/common/sys/ioctl.h | 4 +++- components/libc/libdl/dlmodule.c | 4 +++- components/libc/posix/io/aio/aio.c | 5 ++++- components/libc/posix/io/mman/mman.c | 4 +++- components/libc/posix/io/termios/termios.c | 4 +++- components/lwp/lwp.c | 5 ++++- components/lwp/lwp_syscall.h | 5 ++++- .../net/lwip-2.0.2/src/apps/tftp/tftp_port.c | 4 +++- .../net/lwip-2.0.3/src/apps/tftp/tftp_port.c | 4 +++- .../net/lwip-2.1.2/src/apps/tftp/tftp_port.c | 4 +++- components/net/sal_socket/impl/proto_mbedtls.c | 4 +++- components/utilities/rt-link/src/rtlink_dev.c | 4 +++- components/utilities/ymodem/ry_sy.c | 5 ++++- components/utilities/zmodem/rz.c | 5 +++-- components/utilities/zmodem/sz.c | 5 +++-- components/utilities/zmodem/zcore.c | 5 +++-- components/utilities/zmodem/zdevice.c | 5 +++-- examples/file/listdir.c | 6 +++++- examples/file/readspeed.c | 6 +++++- examples/file/readwrite.c | 6 +++++- examples/file/seekdir.c | 6 +++++- examples/file/writespeed.c | 6 +++++- examples/network/chargen.c | 6 +++++- examples/rt-link/rtlink_dev_example.c | 6 +++++- examples/test/fs_test.c | 6 +++++- examples/ymodem/tofile.c | 6 +++++- 72 files changed, 349 insertions(+), 90 deletions(-) rename components/{dfs/include => legacy/dfs}/dfs_posix.h (100%) diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c b/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c index 50681e7bc6..317dd4c862 100644 --- a/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c +++ b/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include "drv_gpio.h" // #define DRV_DEBUG diff --git a/bsp/efm32/application.c b/bsp/efm32/application.c index 332dcc6ba8..5f2ad9866c 100644 --- a/bsp/efm32/application.c +++ b/bsp/efm32/application.c @@ -65,10 +65,18 @@ #include #include -#if defined(RTGUI_USING_DFS_FILERW) + #if defined(RTGUI_USING_DFS_FILERW) #include #define PATH_SEPARATOR '/' #endif +#if defined(RTGUI_USING_DFS_FILERW) +#include +#include +#include +#include +#include +#define PATH_SEPARATOR '/' +#endif #endif /* Private typedef -----------------------------------------------------------*/ diff --git a/bsp/ft2004/drivers/drv_sdcard.c b/bsp/ft2004/drivers/drv_sdcard.c index a6494089f6..753a70b606 100644 --- a/bsp/ft2004/drivers/drv_sdcard.c +++ b/bsp/ft2004/drivers/drv_sdcard.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include "drv_sdctrl.h" #define DBG_TAG "app.card" diff --git a/bsp/lpc54114-lite/applications/mnt.c b/bsp/lpc54114-lite/applications/mnt.c index 49852b2025..f67c5c21ea 100644 --- a/bsp/lpc54114-lite/applications/mnt.c +++ b/bsp/lpc54114-lite/applications/mnt.c @@ -11,7 +11,10 @@ #if defined(RT_USING_DFS) #include -#include +#include +#include +#include +#include #endif #define BSP_FLASH_MOUNT_PATH "/mnt/flash" diff --git a/bsp/mini4020/applications/application.c b/bsp/mini4020/applications/application.c index f5a77d8c60..722443ac7c 100644 --- a/bsp/mini4020/applications/application.c +++ b/bsp/mini4020/applications/application.c @@ -22,7 +22,11 @@ #include #include #include -#include +#include +#include +#include +#include +#include #endif #ifdef RT_USING_RTGUI diff --git a/bsp/nrf5x/nrf52832/applications/mnt.c b/bsp/nrf5x/nrf52832/applications/mnt.c index c7e4d10235..d4af1d2b6c 100644 --- a/bsp/nrf5x/nrf52832/applications/mnt.c +++ b/bsp/nrf5x/nrf52832/applications/mnt.c @@ -35,7 +35,11 @@ #endif #include "fal.h" -#include +#include +#include +#include +#include +#include #define LOG_TAG "drv.fs" #define DBG_LVL DBG_LOG diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c index 708f653d36..38086cb2d5 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c @@ -20,8 +20,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c index 7c92743bd3..7c5aa68697 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c @@ -20,8 +20,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c index 499311c752..955fe6a645 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c @@ -20,8 +20,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c b/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c index d978fa4ded..6a805b3ba7 100644 --- a/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c +++ b/bsp/nuvoton/libraries/nu_packages/AudioCodec/audio_test.c @@ -16,7 +16,11 @@ #include "wavrecorder.h" #include "wavplayer.h" -#include "dfs_posix.h" +#include +#include +#include +#include +#include /* The routine just for test automatically. diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c index 6990ce215c..4b81a01f52 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c @@ -21,8 +21,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/nk-980iot/applications/mnt.c b/bsp/nuvoton/nk-980iot/applications/mnt.c index 4ff5b1f252..803e4b751b 100644 --- a/bsp/nuvoton/nk-980iot/applications/mnt.c +++ b/bsp/nuvoton/nk-980iot/applications/mnt.c @@ -22,8 +22,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/nk-n9h30/applications/mnt.c b/bsp/nuvoton/nk-n9h30/applications/mnt.c index 03e7481242..f4e7cf5bf3 100644 --- a/bsp/nuvoton/nk-n9h30/applications/mnt.c +++ b/bsp/nuvoton/nk-n9h30/applications/mnt.c @@ -22,8 +22,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/nk-rtu980/applications/mnt.c b/bsp/nuvoton/nk-rtu980/applications/mnt.c index ecfc390243..f99fcb0134 100644 --- a/bsp/nuvoton/nk-rtu980/applications/mnt.c +++ b/bsp/nuvoton/nk-rtu980/applications/mnt.c @@ -22,8 +22,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c index d7e657d852..c0cec18978 100644 --- a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c @@ -13,8 +13,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-m032ki/applications/mnt.c b/bsp/nuvoton/numaker-m032ki/applications/mnt.c index 914fa657f6..00f0f91499 100644 --- a/bsp/nuvoton/numaker-m032ki/applications/mnt.c +++ b/bsp/nuvoton/numaker-m032ki/applications/mnt.c @@ -13,8 +13,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c index 6e7a9ff5de..844ab9960d 100644 --- a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c @@ -13,8 +13,12 @@ #include #if defined(RT_USING_DFS) - #include - #include +#include +#include +#include +#include +#include +#include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/simulator/drivers/module_win32.c b/bsp/simulator/drivers/module_win32.c index 81a98eca87..0f07576964 100644 --- a/bsp/simulator/drivers/module_win32.c +++ b/bsp/simulator/drivers/module_win32.c @@ -193,7 +193,11 @@ RTM_EXPORT(rt_module_find); #ifdef RT_USING_DFS #include -#include +#include +#include +#include +#include +#include extern char * dfs_win32_dirdup(char * path); static char* _module_name(const char *path) { diff --git a/bsp/stm32/stm32f103-atk-warshipv3/board/ports/sdcard_port.c b/bsp/stm32/stm32f103-atk-warshipv3/board/ports/sdcard_port.c index d56fb039d4..df2614c080 100644 --- a/bsp/stm32/stm32f103-atk-warshipv3/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f103-atk-warshipv3/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f103-dofly-M3S/board/ports/drv_sdcard.c b/bsp/stm32/stm32f103-dofly-M3S/board/ports/drv_sdcard.c index 13d235b694..d717da27dd 100644 --- a/bsp/stm32/stm32f103-dofly-M3S/board/ports/drv_sdcard.c +++ b/bsp/stm32/stm32f103-dofly-M3S/board/ports/drv_sdcard.c @@ -14,7 +14,11 @@ #if defined BSP_USING_SDIO_SDCARD || defined BSP_USING_SPI_SDCARD #include #include -#include +#include +#include +#include +#include +#include #include "drv_gpio.h" #define DBG_TAG "app.card" diff --git a/bsp/stm32/stm32f103-fire-arbitrary/board/ports/sdcard_port.c b/bsp/stm32/stm32f103-fire-arbitrary/board/ports/sdcard_port.c index 55baa2c263..c0575f01b2 100644 --- a/bsp/stm32/stm32f103-fire-arbitrary/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f103-fire-arbitrary/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f407-armfly-v5/board/ports/sdcard_port.c b/bsp/stm32/stm32f407-armfly-v5/board/ports/sdcard_port.c index f5427ef265..2b6e48ba3f 100644 --- a/bsp/stm32/stm32f407-armfly-v5/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f407-armfly-v5/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_filesystem.c b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_filesystem.c index 6635c43128..cafb45b107 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_filesystem.c +++ b/bsp/stm32/stm32f407-atk-explorer/board/ports/drv_filesystem.c @@ -15,7 +15,11 @@ #ifdef BSP_USING_FS #include #include -#include +#include +#include +#include +#include +#include #if DFS_FILESYSTEMS_MAX < 4 #error "Please define DFS_FILESYSTEMS_MAX more than 4" diff --git a/bsp/stm32/stm32f427-robomaster-a/board/ports/sdcard_port.c b/bsp/stm32/stm32f427-robomaster-a/board/ports/sdcard_port.c index 6a79c83523..376089ef9e 100644 --- a/bsp/stm32/stm32f427-robomaster-a/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f427-robomaster-a/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f429-armfly-v6/board/ports/sdcard_port.c b/bsp/stm32/stm32f429-armfly-v6/board/ports/sdcard_port.c index 6a79c83523..376089ef9e 100644 --- a/bsp/stm32/stm32f429-armfly-v6/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f429-armfly-v6/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f429-atk-apollo/board/ports/sdcard_port.c b/bsp/stm32/stm32f429-atk-apollo/board/ports/sdcard_port.c index fe2595fa4b..058a948a8a 100644 --- a/bsp/stm32/stm32f429-atk-apollo/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f429-atk-apollo/board/ports/sdcard_port.c @@ -15,7 +15,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f429-fire-challenger/board/ports/sdcard_port.c b/bsp/stm32/stm32f429-fire-challenger/board/ports/sdcard_port.c index 01111ab4d3..93702aed13 100644 --- a/bsp/stm32/stm32f429-fire-challenger/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f429-fire-challenger/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include "drv_gpio.h" #define DBG_TAG "app.card" diff --git a/bsp/stm32/stm32f469-st-disco/board/ports/drv_sdcard.c b/bsp/stm32/stm32f469-st-disco/board/ports/drv_sdcard.c index 9fd2d11fd4..986a562cdd 100644 --- a/bsp/stm32/stm32f469-st-disco/board/ports/drv_sdcard.c +++ b/bsp/stm32/stm32f469-st-disco/board/ports/drv_sdcard.c @@ -15,7 +15,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include "drv_gpio.h" #include "drv_sdio.h" diff --git a/bsp/stm32/stm32f746-st-disco/board/ports/sdcard_port.c b/bsp/stm32/stm32f746-st-disco/board/ports/sdcard_port.c index 66e8dfefab..bcb8a33308 100644 --- a/bsp/stm32/stm32f746-st-disco/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f746-st-disco/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f767-atk-apollo/board/ports/sdcard_port.c b/bsp/stm32/stm32f767-atk-apollo/board/ports/sdcard_port.c index bc7e8b676e..9180edcc7e 100644 --- a/bsp/stm32/stm32f767-atk-apollo/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f767-atk-apollo/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32f767-fire-challenger-v1/board/ports/sdcard_port.c b/bsp/stm32/stm32f767-fire-challenger-v1/board/ports/sdcard_port.c index f1a7b8c27f..edbb295da5 100644 --- a/bsp/stm32/stm32f767-fire-challenger-v1/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32f767-fire-challenger-v1/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include "drv_gpio.h" #define DBG_TAG "app.card" diff --git a/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c index 95e5784654..83058e352c 100644 --- a/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c +++ b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c @@ -12,7 +12,11 @@ #if defined(BSP_USING_OV2640) -#include +#include +#include +#include +#include +#include #include #include #include "pcf8574.h" diff --git a/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_sdcard.c b/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_sdcard.c index 2bed0ef415..ba253aacfa 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_sdcard.c +++ b/bsp/stm32/stm32l475-atk-pandora/board/ports/drv_sdcard.c @@ -15,7 +15,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include "drv_spi.h" #include "spi_msd.h" diff --git a/bsp/stm32/stm32l496-ali-developer/board/ports/sdcard_port.c b/bsp/stm32/stm32l496-ali-developer/board/ports/sdcard_port.c index 6abc52c3ba..3016f583d3 100644 --- a/bsp/stm32/stm32l496-ali-developer/board/ports/sdcard_port.c +++ b/bsp/stm32/stm32l496-ali-developer/board/ports/sdcard_port.c @@ -14,7 +14,11 @@ #include #include -#include +#include +#include +#include +#include +#include #define DBG_TAG "app.card" #define DBG_LVL DBG_INFO diff --git a/bsp/stm32/stm32mp157a-st-discovery/board/ports/audio/audio_play.c b/bsp/stm32/stm32mp157a-st-discovery/board/ports/audio/audio_play.c index 2e045b016b..1f463d99bf 100644 --- a/bsp/stm32/stm32mp157a-st-discovery/board/ports/audio/audio_play.c +++ b/bsp/stm32/stm32mp157a-st-discovery/board/ports/audio/audio_play.c @@ -10,7 +10,11 @@ #include #include -#include +#include +#include +#include +#include +#include #if defined(BSP_USING_AUDIO) && defined(BSP_USING_SDMMC) #define BUFSZ 1024 diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.c index 69af85e27b..303a78fc1d 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.c +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_ov5640.c @@ -13,7 +13,11 @@ #if defined(BSP_USING_DCMI) #include "drv_mfx.h" -#include +#include +#include +#include +#include +#include #include "drv_ov5640.h" //#define DRV_DEBUG diff --git a/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_sound.c b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_sound.c index b9e76a0703..93acea9c1d 100644 --- a/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_sound.c +++ b/bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_sound.c @@ -13,7 +13,11 @@ #ifdef BSP_USING_AUDIO #include "drv_wm8994.h" -#include +#include +#include +#include +#include +#include #define DRV_DEBUG #define LOG_TAG "drv.sound" diff --git a/bsp/swm320-lq100/applications/main.c b/bsp/swm320-lq100/applications/main.c index 5685bf6745..ecc86347c2 100644 --- a/bsp/swm320-lq100/applications/main.c +++ b/bsp/swm320-lq100/applications/main.c @@ -260,7 +260,11 @@ MSH_CMD_EXPORT(wdt_sample, wdt sample); #include "drv_spi.h" #include "spi_flash_sfud.h" -#include "dfs_posix.h" +#include +#include +#include +#include +#include static int rt_hw_spi_flash_init(void) { @@ -380,7 +384,11 @@ MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample); //#define SDCARD_NAME "sd0" //#include "drv_spi.h" -//#include "dfs_posix.h" +// #include +// #include +// #include +// #include +// #include //#include "spi_msd.h" //static int rt_hw_spi1_tfcard(void) @@ -437,7 +445,11 @@ MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample); #ifdef RT_USING_SDIO #define SDCARD_NAME "sd0" -#include "dfs_posix.h" +#include +#include +#include +#include +#include static void sdio_elmfat_sample(void) { diff --git a/bsp/swm320/applications/main.c b/bsp/swm320/applications/main.c index 0ebd6663f6..f34a421727 100644 --- a/bsp/swm320/applications/main.c +++ b/bsp/swm320/applications/main.c @@ -260,7 +260,11 @@ MSH_CMD_EXPORT(wdt_sample, wdt sample); #include "drv_spi.h" #include "spi_flash_sfud.h" -#include "dfs_posix.h" +#include +#include +#include +#include +#include static int rt_hw_spi_flash_init(void) { @@ -380,7 +384,11 @@ MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample); //#define SDCARD_NAME "sd0" //#include "drv_spi.h" -//#include "dfs_posix.h" +// #include +// #include +// #include +// #include +// #include //#include "spi_msd.h" //static int rt_hw_spi1_tfcard(void) @@ -437,7 +445,11 @@ MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample); #ifdef RT_USING_SDIO #define SDCARD_NAME "sd0" -#include "dfs_posix.h" +#include +#include +#include +#include +#include static void sdio_elmfat_sample(void) { diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index da330b5e9c..7182e23c37 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -37,7 +37,10 @@ #include #ifdef RT_USING_POSIX_STDIO -#include +#include +#include +#include +#include #include #include diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c index 16d376eeb9..738afcb081 100644 --- a/components/drivers/serial/serial_v2.c +++ b/components/drivers/serial/serial_v2.c @@ -17,7 +17,9 @@ #include #ifdef RT_USING_POSIX_STDIO -#include +#include +#include +#include #include #include diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 7e1f569b62..2bc0a10083 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -14,8 +14,9 @@ #include #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) -#include -#include +#include +#include +#include #include #include diff --git a/components/finsh/msh.c b/components/finsh/msh.c index acb5445ad1..abf82e992c 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -21,7 +21,10 @@ #include "msh.h" #include "shell.h" #ifdef DFS_USING_POSIX -#include +#include +#include +#include +#include #endif /* DFS_USING_POSIX */ #ifdef RT_USING_MODULE #include diff --git a/components/finsh/msh_file.c b/components/finsh/msh_file.c index 8022b176fc..28f8d4803f 100644 --- a/components/finsh/msh_file.c +++ b/components/finsh/msh_file.c @@ -15,7 +15,10 @@ #include #include "msh.h" -#include +#include +#include +#include +#include static int msh_readline(int fd, char *line_buf, int size) { diff --git a/components/finsh/shell.c b/components/finsh/shell.c index 5398db5370..a326ba1978 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -28,7 +28,9 @@ #include "msh.h" #ifdef DFS_USING_POSIX -#include +#include +#include +#include #endif /* DFS_USING_POSIX */ /* finsh thread */ diff --git a/components/dfs/include/dfs_posix.h b/components/legacy/dfs/dfs_posix.h similarity index 100% rename from components/dfs/include/dfs_posix.h rename to components/legacy/dfs/dfs_posix.h diff --git a/components/libc/compilers/common/sys/ioctl.h b/components/libc/compilers/common/sys/ioctl.h index d93c79115a..49c294eb8d 100644 --- a/components/libc/compilers/common/sys/ioctl.h +++ b/components/libc/compilers/common/sys/ioctl.h @@ -12,7 +12,9 @@ #define __SYS_IOCTL_H__ #include -#include +#include +#include +#include #ifdef _WIN32 #include diff --git a/components/libc/libdl/dlmodule.c b/components/libc/libdl/dlmodule.c index 044c05a994..32d6b6b7e7 100644 --- a/components/libc/libdl/dlmodule.c +++ b/components/libc/libdl/dlmodule.c @@ -15,7 +15,9 @@ #include "dlelf.h" #if defined(RT_USING_POSIX) -#include +#include +#include +#include #endif #define DBG_TAG "DLMD" diff --git a/components/libc/posix/io/aio/aio.c b/components/libc/posix/io/aio/aio.c index 08ef4c634a..bf188728f0 100644 --- a/components/libc/posix/io/aio/aio.c +++ b/components/libc/posix/io/aio/aio.c @@ -10,7 +10,10 @@ #include #include -#include +#include +#include +#include +#include #include "aio.h" struct rt_workqueue* aio_queue = NULL; diff --git a/components/libc/posix/io/mman/mman.c b/components/libc/posix/io/mman/mman.c index 827f2cbb14..d484b3ed7b 100644 --- a/components/libc/posix/io/mman/mman.c +++ b/components/libc/posix/io/mman/mman.c @@ -12,7 +12,9 @@ #include #include -#include +#include +#include +#include #include "sys/mman.h" diff --git a/components/libc/posix/io/termios/termios.c b/components/libc/posix/io/termios/termios.c index 44e0e80853..14d85e9f0c 100644 --- a/components/libc/posix/io/termios/termios.c +++ b/components/libc/posix/io/termios/termios.c @@ -10,7 +10,9 @@ #include #include -#include +#include +#include +#include #include #include "termios.h" diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index 9789595ee7..4b91538b68 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -11,7 +11,10 @@ #include #include -#include +#include +#include +#include +#include #ifndef RT_USING_DFS #error "lwp need file system(RT_USING_DFS)" diff --git a/components/lwp/lwp_syscall.h b/components/lwp/lwp_syscall.h index 02599f4317..749406c1ca 100644 --- a/components/lwp/lwp_syscall.h +++ b/components/lwp/lwp_syscall.h @@ -13,7 +13,10 @@ #include #include -#include +#include +#include +#include +#include #include #include #include diff --git a/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c index 59e64c7a3b..38221ac580 100644 --- a/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c +++ b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c @@ -10,7 +10,9 @@ #include -#include +#include +#include +#include #include static struct tftp_context ctx; diff --git a/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c b/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c index 59e64c7a3b..38221ac580 100644 --- a/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c +++ b/components/net/lwip-2.0.3/src/apps/tftp/tftp_port.c @@ -10,7 +10,9 @@ #include -#include +#include +#include +#include #include static struct tftp_context ctx; diff --git a/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c b/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c index 59e64c7a3b..38221ac580 100644 --- a/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c +++ b/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c @@ -10,7 +10,9 @@ #include -#include +#include +#include +#include #include static struct tftp_context ctx; diff --git a/components/net/sal_socket/impl/proto_mbedtls.c b/components/net/sal_socket/impl/proto_mbedtls.c index 79fbdcc5d4..338792c948 100644 --- a/components/net/sal_socket/impl/proto_mbedtls.c +++ b/components/net/sal_socket/impl/proto_mbedtls.c @@ -11,7 +11,9 @@ #include #ifdef RT_USING_DFS -#include +#include +#include +#include #endif #ifdef SAL_USING_TLS diff --git a/components/utilities/rt-link/src/rtlink_dev.c b/components/utilities/rt-link/src/rtlink_dev.c index e91736251d..702aed32da 100644 --- a/components/utilities/rt-link/src/rtlink_dev.c +++ b/components/utilities/rt-link/src/rtlink_dev.c @@ -20,7 +20,9 @@ #define RTLINK_SERV(dev) (((struct rt_link_device*)dev)->service) #ifdef RT_USING_POSIX_DEVIO -#include +#include +#include +#include #include int rtlink_fops_open(struct dfs_fd *fd) diff --git a/components/utilities/ymodem/ry_sy.c b/components/utilities/ymodem/ry_sy.c index 3f3b022d7e..b77bd7abc2 100644 --- a/components/utilities/ymodem/ry_sy.c +++ b/components/utilities/ymodem/ry_sy.c @@ -11,7 +11,10 @@ #include #include -#include +#include +#include +#include +#include #include #include diff --git a/components/utilities/zmodem/rz.c b/components/utilities/zmodem/rz.c index 224d8f95a8..f4fa4bde6c 100644 --- a/components/utilities/zmodem/rz.c +++ b/components/utilities/zmodem/rz.c @@ -13,8 +13,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include "zdef.h" diff --git a/components/utilities/zmodem/sz.c b/components/utilities/zmodem/sz.c index e6096756b1..bda5d939d4 100644 --- a/components/utilities/zmodem/sz.c +++ b/components/utilities/zmodem/sz.c @@ -12,8 +12,9 @@ #include #include #include -#include -#include +#include +#include +#include #include "zdef.h" diff --git a/components/utilities/zmodem/zcore.c b/components/utilities/zmodem/zcore.c index 75d9647348..b4e23b585a 100644 --- a/components/utilities/zmodem/zcore.c +++ b/components/utilities/zmodem/zcore.c @@ -11,8 +11,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include "zdef.h" diff --git a/components/utilities/zmodem/zdevice.c b/components/utilities/zmodem/zdevice.c index 3a144e79de..980a15f4f8 100644 --- a/components/utilities/zmodem/zdevice.c +++ b/components/utilities/zmodem/zdevice.c @@ -11,8 +11,9 @@ #include #include #include -#include -#include +#include +#include +#include #include "zdef.h" diff --git a/examples/file/listdir.c b/examples/file/listdir.c index 9649347734..d858a00bff 100644 --- a/examples/file/listdir.c +++ b/examples/file/listdir.c @@ -9,7 +9,11 @@ * 2020-04-12 Jianjia Ma add msh cmd */ #include -#include +#include +#include +#include +#include +#include void list_dir(const char* path) { diff --git a/examples/file/readspeed.c b/examples/file/readspeed.c index 5f4cad3190..dfa68ceb32 100644 --- a/examples/file/readspeed.c +++ b/examples/file/readspeed.c @@ -10,7 +10,11 @@ */ #include -#include +#include +#include +#include +#include +#include void readspeed(const char* filename, int block_size) { diff --git a/examples/file/readwrite.c b/examples/file/readwrite.c index d1dd5bc038..5d0defeaa9 100644 --- a/examples/file/readwrite.c +++ b/examples/file/readwrite.c @@ -10,7 +10,11 @@ */ #include -#include +#include +#include +#include +#include +#include #define TEST_DATA_LEN 120 diff --git a/examples/file/seekdir.c b/examples/file/seekdir.c index efadd3a1c8..5198a8056b 100644 --- a/examples/file/seekdir.c +++ b/examples/file/seekdir.c @@ -8,7 +8,11 @@ * 2011-06-02 Bernard first version * 2020-04-12 Jianjia Ma add msh cmd */ -#include +#include +#include +#include +#include +#include void seekdir_test(void) { diff --git a/examples/file/writespeed.c b/examples/file/writespeed.c index f76027d28b..87a4c329bd 100644 --- a/examples/file/writespeed.c +++ b/examples/file/writespeed.c @@ -9,7 +9,11 @@ * 2020-04-12 Jianjia Ma add msh cmd */ #include -#include +#include +#include +#include +#include +#include void writespeed(const char* filename, int total_length, int block_size) { diff --git a/examples/network/chargen.c b/examples/network/chargen.c index 3b4feaca9e..69a6b13a5d 100644 --- a/examples/network/chargen.c +++ b/examples/network/chargen.c @@ -12,7 +12,11 @@ #ifdef SAL_USING_POSIX #include // only dfs_net -#include +#include +#include +#include +#include +#include #else #define read lwip_read #define write lwip_write diff --git a/examples/rt-link/rtlink_dev_example.c b/examples/rt-link/rtlink_dev_example.c index 51b6432d9f..027292769d 100644 --- a/examples/rt-link/rtlink_dev_example.c +++ b/examples/rt-link/rtlink_dev_example.c @@ -46,7 +46,11 @@ static rt_err_t rtlink_dev_tx_done(rt_device_t dev, void *buffer) } #ifdef RT_USING_POSIX_DEVIO -#include +#include +#include +#include +#include +#include #include #include diff --git a/examples/test/fs_test.c b/examples/test/fs_test.c index a86bbd6ac2..7fd70284cf 100644 --- a/examples/test/fs_test.c +++ b/examples/test/fs_test.c @@ -11,7 +11,11 @@ */ #include -#include +#include +#include +#include +#include +#include static rt_uint32_t stop_flag = 0; static rt_thread_t fsrw1_thread = RT_NULL; diff --git a/examples/ymodem/tofile.c b/examples/ymodem/tofile.c index 35dca2f2c1..8fb2d0c06b 100644 --- a/examples/ymodem/tofile.c +++ b/examples/ymodem/tofile.c @@ -9,7 +9,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include #include From 8213bbd92ed8b9186f0c1c12a10da43a8b18ed51 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Thu, 13 Jan 2022 11:27:12 -0500 Subject: [PATCH 13/65] update --- components/drivers/serial/serial.c | 3 +-- components/drivers/serial/serial_v2.c | 3 +-- components/drivers/src/pipe.c | 3 +-- components/finsh/msh.c | 3 +-- components/finsh/msh_file.c | 3 +-- components/finsh/shell.c | 3 +-- components/libc/compilers/common/sys/ioctl.h | 3 --- components/libc/compilers/common/time.c | 5 ++++- components/libc/posix/io/aio/aio.c | 8 ++++---- 9 files changed, 14 insertions(+), 20 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 7182e23c37..c749897a08 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -38,9 +38,8 @@ #ifdef RT_USING_POSIX_STDIO #include +#include #include -#include -#include #include #include diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c index 738afcb081..3e0b057df5 100644 --- a/components/drivers/serial/serial_v2.c +++ b/components/drivers/serial/serial_v2.c @@ -18,8 +18,7 @@ #ifdef RT_USING_POSIX_STDIO #include -#include -#include +#include #include #include diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 2bc0a10083..3a2ad4104d 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -15,8 +15,7 @@ #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) #include -#include -#include +#include #include #include diff --git a/components/finsh/msh.c b/components/finsh/msh.c index abf82e992c..bb649549d4 100644 --- a/components/finsh/msh.c +++ b/components/finsh/msh.c @@ -23,8 +23,7 @@ #ifdef DFS_USING_POSIX #include #include -#include -#include +#include #endif /* DFS_USING_POSIX */ #ifdef RT_USING_MODULE #include diff --git a/components/finsh/msh_file.c b/components/finsh/msh_file.c index 28f8d4803f..9deab4f0bc 100644 --- a/components/finsh/msh_file.c +++ b/components/finsh/msh_file.c @@ -17,8 +17,7 @@ #include "msh.h" #include #include -#include -#include +#include static int msh_readline(int fd, char *line_buf, int size) { diff --git a/components/finsh/shell.c b/components/finsh/shell.c index a326ba1978..824c60392d 100644 --- a/components/finsh/shell.c +++ b/components/finsh/shell.c @@ -29,8 +29,7 @@ #ifdef DFS_USING_POSIX #include -#include -#include +#include #endif /* DFS_USING_POSIX */ /* finsh thread */ diff --git a/components/libc/compilers/common/sys/ioctl.h b/components/libc/compilers/common/sys/ioctl.h index 49c294eb8d..c663025c1f 100644 --- a/components/libc/compilers/common/sys/ioctl.h +++ b/components/libc/compilers/common/sys/ioctl.h @@ -12,9 +12,6 @@ #define __SYS_IOCTL_H__ #include -#include -#include -#include #ifdef _WIN32 #include diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 46bb0c1355..0b34236952 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -25,6 +25,10 @@ #include #include #include +#include +#ifdef RT_USING_POSIX_DELAY +#include +#endif #ifdef RT_USING_RTC #include #endif @@ -489,7 +493,6 @@ RTM_EXPORT(difftime); RTM_EXPORT(strftime); #ifdef RT_USING_POSIX_DELAY -#include int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { sleep(rqtp->tv_sec); diff --git a/components/libc/posix/io/aio/aio.c b/components/libc/posix/io/aio/aio.c index bf188728f0..e12a7047c8 100644 --- a/components/libc/posix/io/aio/aio.c +++ b/components/libc/posix/io/aio/aio.c @@ -8,12 +8,12 @@ * 2017/12/30 Bernard The first version. */ -#include +#include #include +#include #include -#include -#include -#include +#include +#include #include "aio.h" struct rt_workqueue* aio_queue = NULL; From ebe9fc5771f976c889dadb259e381d01b70aaee3 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 8 Jan 2022 17:55:46 -0500 Subject: [PATCH 14/65] [kservice] fix the problem of rt_strlen crashed in win32 --- src/kservice.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/kservice.c b/src/kservice.c index f112ec92de..b992c7e6e1 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -461,7 +461,17 @@ RTM_EXPORT(rt_strncpy); */ char *rt_strcpy(char *dst, const char *src) { - return rt_strncpy(dst, src, (rt_size_t)-1); + char *dest = dst; + + while (*src != '\0') + { + *dst = *src; + dst++; + src++; + } + + *dst = '\0'; + return dest; } RTM_EXPORT(rt_strcpy); From 0f856cc2d2b9037edb2108ea63d5f5d21d6af925 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 15 Jan 2022 23:21:38 -0500 Subject: [PATCH 15/65] =?UTF-8?q?[l475][audio]=20=E6=B6=88=E9=99=A4?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stm32l475-atk-pandora/board/ports/audio/drv_es8388.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bsp/stm32/stm32l475-atk-pandora/board/ports/audio/drv_es8388.c b/bsp/stm32/stm32l475-atk-pandora/board/ports/audio/drv_es8388.c index 5d9844c6bd..d8bb668f59 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/ports/audio/drv_es8388.c +++ b/bsp/stm32/stm32l475-atk-pandora/board/ports/audio/drv_es8388.c @@ -25,7 +25,7 @@ static struct es8388_device es_dev = {0}; static rt_uint16_t reg_read(rt_uint8_t addr) { struct rt_i2c_msg msg[2] = {0}; - uint8_t val = 0xff; + rt_uint8_t val = 0xff; RT_ASSERT(es_dev.i2c != RT_NULL); @@ -97,7 +97,7 @@ static int es8388_set_adc_dac_volume(int mode, int volume, int dot) void es8388_set_voice_mute(rt_bool_t enable) { - uint8_t reg = 0; + rt_uint8_t reg = 0; reg = reg_read(ES8388_DACCONTROL3); reg = reg & 0xFB; @@ -154,7 +154,7 @@ rt_err_t es8388_init(const char *i2c_name, rt_uint16_t pin) rt_err_t es8388_start(enum es8388_mode mode) { int res = 0; - uint8_t prev_data = 0, data = 0; + rt_uint8_t prev_data = 0, data = 0; prev_data = reg_read(ES8388_DACCONTROL21); if (mode == ES_MODE_LINE) @@ -225,7 +225,7 @@ rt_err_t es8388_stop(enum es8388_mode mode) rt_err_t es8388_fmt_set(enum es8388_mode mode, enum es8388_format fmt) { - uint8_t reg = 0; + rt_uint8_t reg = 0; if (mode == ES_MODE_ADC || mode == ES_MODE_DAC_ADC) { From 0d929da6caaca258c74cffa2b97715be41119bf6 Mon Sep 17 00:00:00 2001 From: Ouxiaolong <1576690133@qq.com> Date: Sun, 16 Jan 2022 14:58:05 +0800 Subject: [PATCH 16/65] [bsp]gd32103c-eval,gd32105c-eval,gd32107c-eval,gd32303e-eval,gd32450z-eval --- .github/workflows/action.yml | 5 + bsp/gd32/README.md | 11 +- bsp/gd32/gd32103c-eval/.config | 636 ++++++++++++++ bsp/gd32/gd32103c-eval/Kconfig | 21 + bsp/gd32/gd32103c-eval/README.md | 94 +++ bsp/gd32/gd32103c-eval/SConscript | 15 + bsp/gd32/gd32103c-eval/SConstruct | 60 ++ .../gd32103c-eval/applications/SConscript | 11 + bsp/gd32/gd32103c-eval/applications/main.c | 35 + bsp/gd32/gd32103c-eval/board/Kconfig | 85 ++ bsp/gd32/gd32103c-eval/board/SConscript | 28 + bsp/gd32/gd32103c-eval/board/board.c | 85 ++ bsp/gd32/gd32103c-eval/board/board.h | 47 ++ .../gd32103c-eval/board/gd32f10x_libopt.h | 64 ++ .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 ++++ .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32103c-eval/project.uvoptx | 748 ++++++++++++++++ bsp/gd32/gd32103c-eval/project.uvproj | 737 ++++++++++++++++ bsp/gd32/gd32103c-eval/project.uvprojx | 668 +++++++++++++++ bsp/gd32/gd32103c-eval/rtconfig.h | 200 +++++ bsp/gd32/gd32103c-eval/rtconfig.py | 150 ++++ bsp/gd32/gd32103c-eval/template.uvoptx | 180 ++++ bsp/gd32/gd32103c-eval/template.uvproj | 628 ++++++++++++++ bsp/gd32/gd32103c-eval/template.uvprojx | 418 +++++++++ bsp/gd32/gd32105c-eval/.config | 636 ++++++++++++++ bsp/gd32/gd32105c-eval/Kconfig | 21 + bsp/gd32/gd32105c-eval/README.md | 98 +++ bsp/gd32/gd32105c-eval/SConscript | 15 + bsp/gd32/gd32105c-eval/SConstruct | 60 ++ .../gd32105c-eval/applications/SConscript | 11 + bsp/gd32/gd32105c-eval/applications/main.c | 35 + bsp/gd32/gd32105c-eval/board/Kconfig | 85 ++ bsp/gd32/gd32105c-eval/board/SConscript | 28 + bsp/gd32/gd32105c-eval/board/board.c | 85 ++ bsp/gd32/gd32105c-eval/board/board.h | 47 ++ .../gd32105c-eval/board/gd32f10x_libopt.h | 64 ++ .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 ++++ .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32105c-eval/figures/board.jpg | Bin 0 -> 169187 bytes bsp/gd32/gd32105c-eval/project.uvoptx | 180 ++++ bsp/gd32/gd32105c-eval/project.uvproj | 737 ++++++++++++++++ bsp/gd32/gd32105c-eval/project.uvprojx | 727 ++++++++++++++++ bsp/gd32/gd32105c-eval/rtconfig.h | 200 +++++ bsp/gd32/gd32105c-eval/rtconfig.py | 150 ++++ bsp/gd32/gd32105c-eval/template.uvoptx | 180 ++++ bsp/gd32/gd32105c-eval/template.uvproj | 628 ++++++++++++++ bsp/gd32/gd32105c-eval/template.uvprojx | 418 +++++++++ bsp/gd32/gd32107c-eval/.config | 670 +++++++++++++++ bsp/gd32/gd32107c-eval/Kconfig | 21 + bsp/gd32/gd32107c-eval/README.md | 98 +++ bsp/gd32/gd32107c-eval/SConscript | 15 + bsp/gd32/gd32107c-eval/SConstruct | 60 ++ .../gd32107c-eval/applications/SConscript | 11 + bsp/gd32/gd32107c-eval/applications/main.c | 35 + bsp/gd32/gd32107c-eval/board/Kconfig | 85 ++ bsp/gd32/gd32107c-eval/board/SConscript | 28 + bsp/gd32/gd32107c-eval/board/board.c | 85 ++ bsp/gd32/gd32107c-eval/board/board.h | 47 ++ .../gd32107c-eval/board/gd32f10x_libopt.h | 64 ++ .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 ++++ .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32107c-eval/figures/board.jpg | Bin 0 -> 128732 bytes bsp/gd32/gd32107c-eval/project.uvoptx | 796 ++++++++++++++++++ bsp/gd32/gd32107c-eval/project.uvproj | 777 +++++++++++++++++ bsp/gd32/gd32107c-eval/project.uvprojx | 757 +++++++++++++++++ bsp/gd32/gd32107c-eval/rtconfig.h | 212 +++++ bsp/gd32/gd32107c-eval/rtconfig.py | 150 ++++ bsp/gd32/gd32107c-eval/template.uvoptx | 180 ++++ bsp/gd32/gd32107c-eval/template.uvproj | 628 ++++++++++++++ bsp/gd32/gd32107c-eval/template.uvprojx | 418 +++++++++ bsp/gd32/gd32303e-eval/.config | 636 ++++++++++++++ bsp/gd32/gd32303e-eval/Kconfig | 21 + bsp/gd32/gd32303e-eval/README.md | 94 +++ bsp/gd32/gd32303e-eval/SConscript | 15 + bsp/gd32/gd32303e-eval/SConstruct | 60 ++ .../gd32303e-eval/applications/SConscript | 11 + bsp/gd32/gd32303e-eval/applications/main.c | 35 + bsp/gd32/gd32303e-eval/board/Kconfig | 85 ++ bsp/gd32/gd32303e-eval/board/SConscript | 28 + bsp/gd32/gd32303e-eval/board/board.c | 85 ++ bsp/gd32/gd32303e-eval/board/board.h | 47 ++ .../gd32303e-eval/board/gd32f30x_libopt.h | 65 ++ .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 ++++ .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32303e-eval/project.uvoptx | 748 ++++++++++++++++ bsp/gd32/gd32303e-eval/project.uvproj | 737 ++++++++++++++++ bsp/gd32/gd32303e-eval/project.uvprojx | 668 +++++++++++++++ bsp/gd32/gd32303e-eval/rtconfig.h | 200 +++++ bsp/gd32/gd32303e-eval/rtconfig.py | 150 ++++ bsp/gd32/gd32303e-eval/template.uvoptx | 180 ++++ bsp/gd32/gd32303e-eval/template.uvproj | 628 ++++++++++++++ bsp/gd32/gd32303e-eval/template.uvprojx | 418 +++++++++ bsp/gd32/gd32450z-eval/.config | 636 ++++++++++++++ bsp/gd32/gd32450z-eval/Kconfig | 21 + bsp/gd32/gd32450z-eval/README.md | 94 +++ bsp/gd32/gd32450z-eval/SConscript | 15 + bsp/gd32/gd32450z-eval/SConstruct | 60 ++ .../gd32450z-eval/applications/SConscript | 11 + bsp/gd32/gd32450z-eval/applications/main.c | 35 + bsp/gd32/gd32450z-eval/board/Kconfig | 85 ++ bsp/gd32/gd32450z-eval/board/SConscript | 28 + bsp/gd32/gd32450z-eval/board/board.c | 85 ++ bsp/gd32/gd32450z-eval/board/board.h | 47 ++ .../gd32450z-eval/board/gd32f4xx_libopt.h | 45 + .../board/linker_scripts/link.icf | 40 + .../board/linker_scripts/link.ld | 142 ++++ .../board/linker_scripts/link.sct | 15 + bsp/gd32/gd32450z-eval/project.uvoptx | 778 +++++++++++++++++ bsp/gd32/gd32450z-eval/project.uvproj | 747 ++++++++++++++++ bsp/gd32/gd32450z-eval/project.uvprojx | 677 +++++++++++++++ bsp/gd32/gd32450z-eval/rtconfig.h | 200 +++++ bsp/gd32/gd32450z-eval/rtconfig.py | 150 ++++ bsp/gd32/gd32450z-eval/template.uvoptx | 190 +++++ bsp/gd32/gd32450z-eval/template.uvproj | 628 ++++++++++++++ bsp/gd32/gd32450z-eval/template.uvprojx | 417 +++++++++ 119 files changed, 25310 insertions(+), 3 deletions(-) create mode 100644 bsp/gd32/gd32103c-eval/.config create mode 100644 bsp/gd32/gd32103c-eval/Kconfig create mode 100644 bsp/gd32/gd32103c-eval/README.md create mode 100644 bsp/gd32/gd32103c-eval/SConscript create mode 100644 bsp/gd32/gd32103c-eval/SConstruct create mode 100644 bsp/gd32/gd32103c-eval/applications/SConscript create mode 100644 bsp/gd32/gd32103c-eval/applications/main.c create mode 100644 bsp/gd32/gd32103c-eval/board/Kconfig create mode 100644 bsp/gd32/gd32103c-eval/board/SConscript create mode 100644 bsp/gd32/gd32103c-eval/board/board.c create mode 100644 bsp/gd32/gd32103c-eval/board/board.h create mode 100644 bsp/gd32/gd32103c-eval/board/gd32f10x_libopt.h create mode 100644 bsp/gd32/gd32103c-eval/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32103c-eval/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32103c-eval/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32103c-eval/project.uvoptx create mode 100644 bsp/gd32/gd32103c-eval/project.uvproj create mode 100644 bsp/gd32/gd32103c-eval/project.uvprojx create mode 100644 bsp/gd32/gd32103c-eval/rtconfig.h create mode 100644 bsp/gd32/gd32103c-eval/rtconfig.py create mode 100644 bsp/gd32/gd32103c-eval/template.uvoptx create mode 100644 bsp/gd32/gd32103c-eval/template.uvproj create mode 100644 bsp/gd32/gd32103c-eval/template.uvprojx create mode 100644 bsp/gd32/gd32105c-eval/.config create mode 100644 bsp/gd32/gd32105c-eval/Kconfig create mode 100644 bsp/gd32/gd32105c-eval/README.md create mode 100644 bsp/gd32/gd32105c-eval/SConscript create mode 100644 bsp/gd32/gd32105c-eval/SConstruct create mode 100644 bsp/gd32/gd32105c-eval/applications/SConscript create mode 100644 bsp/gd32/gd32105c-eval/applications/main.c create mode 100644 bsp/gd32/gd32105c-eval/board/Kconfig create mode 100644 bsp/gd32/gd32105c-eval/board/SConscript create mode 100644 bsp/gd32/gd32105c-eval/board/board.c create mode 100644 bsp/gd32/gd32105c-eval/board/board.h create mode 100644 bsp/gd32/gd32105c-eval/board/gd32f10x_libopt.h create mode 100644 bsp/gd32/gd32105c-eval/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32105c-eval/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32105c-eval/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32105c-eval/figures/board.jpg create mode 100644 bsp/gd32/gd32105c-eval/project.uvoptx create mode 100644 bsp/gd32/gd32105c-eval/project.uvproj create mode 100644 bsp/gd32/gd32105c-eval/project.uvprojx create mode 100644 bsp/gd32/gd32105c-eval/rtconfig.h create mode 100644 bsp/gd32/gd32105c-eval/rtconfig.py create mode 100644 bsp/gd32/gd32105c-eval/template.uvoptx create mode 100644 bsp/gd32/gd32105c-eval/template.uvproj create mode 100644 bsp/gd32/gd32105c-eval/template.uvprojx create mode 100644 bsp/gd32/gd32107c-eval/.config create mode 100644 bsp/gd32/gd32107c-eval/Kconfig create mode 100644 bsp/gd32/gd32107c-eval/README.md create mode 100644 bsp/gd32/gd32107c-eval/SConscript create mode 100644 bsp/gd32/gd32107c-eval/SConstruct create mode 100644 bsp/gd32/gd32107c-eval/applications/SConscript create mode 100644 bsp/gd32/gd32107c-eval/applications/main.c create mode 100644 bsp/gd32/gd32107c-eval/board/Kconfig create mode 100644 bsp/gd32/gd32107c-eval/board/SConscript create mode 100644 bsp/gd32/gd32107c-eval/board/board.c create mode 100644 bsp/gd32/gd32107c-eval/board/board.h create mode 100644 bsp/gd32/gd32107c-eval/board/gd32f10x_libopt.h create mode 100644 bsp/gd32/gd32107c-eval/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32107c-eval/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32107c-eval/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32107c-eval/figures/board.jpg create mode 100644 bsp/gd32/gd32107c-eval/project.uvoptx create mode 100644 bsp/gd32/gd32107c-eval/project.uvproj create mode 100644 bsp/gd32/gd32107c-eval/project.uvprojx create mode 100644 bsp/gd32/gd32107c-eval/rtconfig.h create mode 100644 bsp/gd32/gd32107c-eval/rtconfig.py create mode 100644 bsp/gd32/gd32107c-eval/template.uvoptx create mode 100644 bsp/gd32/gd32107c-eval/template.uvproj create mode 100644 bsp/gd32/gd32107c-eval/template.uvprojx create mode 100644 bsp/gd32/gd32303e-eval/.config create mode 100644 bsp/gd32/gd32303e-eval/Kconfig create mode 100644 bsp/gd32/gd32303e-eval/README.md create mode 100644 bsp/gd32/gd32303e-eval/SConscript create mode 100644 bsp/gd32/gd32303e-eval/SConstruct create mode 100644 bsp/gd32/gd32303e-eval/applications/SConscript create mode 100644 bsp/gd32/gd32303e-eval/applications/main.c create mode 100644 bsp/gd32/gd32303e-eval/board/Kconfig create mode 100644 bsp/gd32/gd32303e-eval/board/SConscript create mode 100644 bsp/gd32/gd32303e-eval/board/board.c create mode 100644 bsp/gd32/gd32303e-eval/board/board.h create mode 100644 bsp/gd32/gd32303e-eval/board/gd32f30x_libopt.h create mode 100644 bsp/gd32/gd32303e-eval/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32303e-eval/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32303e-eval/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32303e-eval/project.uvoptx create mode 100644 bsp/gd32/gd32303e-eval/project.uvproj create mode 100644 bsp/gd32/gd32303e-eval/project.uvprojx create mode 100644 bsp/gd32/gd32303e-eval/rtconfig.h create mode 100644 bsp/gd32/gd32303e-eval/rtconfig.py create mode 100644 bsp/gd32/gd32303e-eval/template.uvoptx create mode 100644 bsp/gd32/gd32303e-eval/template.uvproj create mode 100644 bsp/gd32/gd32303e-eval/template.uvprojx create mode 100644 bsp/gd32/gd32450z-eval/.config create mode 100644 bsp/gd32/gd32450z-eval/Kconfig create mode 100644 bsp/gd32/gd32450z-eval/README.md create mode 100644 bsp/gd32/gd32450z-eval/SConscript create mode 100644 bsp/gd32/gd32450z-eval/SConstruct create mode 100644 bsp/gd32/gd32450z-eval/applications/SConscript create mode 100644 bsp/gd32/gd32450z-eval/applications/main.c create mode 100644 bsp/gd32/gd32450z-eval/board/Kconfig create mode 100644 bsp/gd32/gd32450z-eval/board/SConscript create mode 100644 bsp/gd32/gd32450z-eval/board/board.c create mode 100644 bsp/gd32/gd32450z-eval/board/board.h create mode 100644 bsp/gd32/gd32450z-eval/board/gd32f4xx_libopt.h create mode 100644 bsp/gd32/gd32450z-eval/board/linker_scripts/link.icf create mode 100644 bsp/gd32/gd32450z-eval/board/linker_scripts/link.ld create mode 100644 bsp/gd32/gd32450z-eval/board/linker_scripts/link.sct create mode 100644 bsp/gd32/gd32450z-eval/project.uvoptx create mode 100644 bsp/gd32/gd32450z-eval/project.uvproj create mode 100644 bsp/gd32/gd32450z-eval/project.uvprojx create mode 100644 bsp/gd32/gd32450z-eval/rtconfig.h create mode 100644 bsp/gd32/gd32450z-eval/rtconfig.py create mode 100644 bsp/gd32/gd32450z-eval/template.uvoptx create mode 100644 bsp/gd32/gd32450z-eval/template.uvproj create mode 100644 bsp/gd32/gd32450z-eval/template.uvprojx diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 082cd01807..91a3f88a1a 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -35,10 +35,15 @@ jobs: - {RTT_BSP: "asm9260t", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "at91sam9260", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "allwinner_tina", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "gd32/gd32103c-eval", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "gd32/gd32105c-eval", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "gd32/gd32105r-start", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "gd32/gd32107c-eval", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "gd32/gd32205r-start", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "gd32/gd32303e-eval", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "gd32/gd32305r-start", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "gd32/gd32407v-start", RTT_TOOL_CHAIN: "sourcery-arm"} + - {RTT_BSP: "gd32/gd32450z-eval", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "gd32e230k-start", RTT_TOOL_CHAIN: "sourcery-arm"} - {RTT_BSP: "gd32vf103v-eval", RTT_TOOL_CHAIN: "sourcery-riscv-none-embed"} - {RTT_BSP: "gd32303e-eval", RTT_TOOL_CHAIN: "sourcery-arm"} diff --git a/bsp/gd32/README.md b/bsp/gd32/README.md index fb706c2723..5937be20aa 100644 --- a/bsp/gd32/README.md +++ b/bsp/gd32/README.md @@ -6,13 +6,18 @@ GD32 系列 BSP 目前支持情况如下表所示: | **BSP 文件夹名称** | **开发板名称** | |:------------------------- |:-------------------------- | | **F1 系列** | | -| [gd32105r-start](gd32105r-start) | 兆易创新 官方 GD32105r-START 开发板 | +| [gd32103c-eval](gd32103c-eval) | 兆易创新 官方 GD32103C-EVAL 开发板 | +| [gd32105c-eval](gd32105c-eval) | 兆易创新 官方 GD32105C-EVAL 开发板 | +| [gd32105r-start](gd32105r-start) | 兆易创新 官方 GD32105R-START 开发板 | +| [gd32107c-eval](gd32107c-eval) | 兆易创新 官方 GD32107C-EVAL 开发板 | | **F2 系列** | | -| [gd32205r-start](gd32205r-start) | 兆易创新 官方 GD32205r-START 开发板 | +| [gd32205r-start](gd32205r-start) | 兆易创新 官方 GD32205R-START 开发板 | | **F3 系列** | | -| [gd32305r-start](gd32305r-start) | 兆易创新 官方 GD32305r-START 开发板 | +| [gd32303e-eval](gd32303e-eval) | 兆易创新 官方 GD32303E-EVAL 开发板 | +| [gd32305r-start](gd32305r-start) | 兆易创新 官方 GD32305R-START 开发板 | | **F4 系列** | | | [gd32407v-start](gd32407v-start) | 兆易创新 官方 GD32407V-START 开发板 | +| [gd32450z-eval](gd32450z-eval) | 兆易创新 官方 GD32450Z-EVAL 开发板 | 可以通过阅读相应 BSP 下的 README 来快速上手,如果想要使用 BSP 更多功能可参考 docs 文件夹下提供的说明文档,如下表所示: diff --git a/bsp/gd32/gd32103c-eval/.config b/bsp/gd32/gd32103c-eval/.config new file mode 100644 index 0000000000..2b86e3f13b --- /dev/null +++ b/bsp/gd32/gd32103c-eval/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F10x=y +CONFIG_SOC_GD32103V=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32103c-eval/Kconfig b/bsp/gd32/gd32103c-eval/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32103c-eval/README.md b/bsp/gd32/gd32103c-eval/README.md new file mode 100644 index 0000000000..bb7e51279b --- /dev/null +++ b/bsp/gd32/gd32103c-eval/README.md @@ -0,0 +1,94 @@ +# GD32103C-EVAL开发板BSP说明 + +## 简介 + +GD3103C-EVAL是-兆易创新推出的一款GD32F10X系列的评估板,最高主频高达108M,该开发板具有丰富的板载资源,可以充分发挥 GD32103VCT6的芯片性能。 + +该开发板常用 **板载资源** 如下: + +- GD32103VCT6,主频 108MHz,256KB FLASH ,48KB RAM + +- 常用外设 + + - LED :5个,LED1 (电源指示灯),LED2(PC0),LED3(PC2),LED4(PE0),LED5(PE1) + - 按键:3个,K1(用户按键,PA0),K2(用户按键,PC13),K3(用户按键,PB14) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0 - SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 10:00:27 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32103c-eval/SConscript b/bsp/gd32/gd32103c-eval/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32103c-eval/SConstruct b/bsp/gd32/gd32103c-eval/SConstruct new file mode 100644 index 0000000000..49074397d0 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F10x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32103c-eval/applications/SConscript b/bsp/gd32/gd32103c-eval/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32103c-eval/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32103c-eval/applications/main.c b/bsp/gd32/gd32103c-eval/applications/main.c new file mode 100644 index 0000000000..d13b24ab50 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC0 */ +#define LED2_PIN GET_PIN(C, 0) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32103c-eval/board/Kconfig b/bsp/gd32/gd32103c-eval/board/Kconfig new file mode 100644 index 0000000000..01d1240fce --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F10x + bool + default y + +config SOC_GD32103V + bool + select SOC_SERIES_GD32F10x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32103c-eval/board/SConscript b/bsp/gd32/gd32103c-eval/board/SConscript new file mode 100644 index 0000000000..95b0a6e9ac --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_hd.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_hd.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_hd.s'] + +CPPDEFINES = ['GD32F10X_HD'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32103c-eval/board/board.c b/bsp/gd32/gd32103c-eval/board/board.c new file mode 100644 index 0000000000..c409645b37 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32103c-eval/board/board.h b/bsp/gd32/gd32103c-eval/board/board.h new file mode 100644 index 0000000000..2eb804a9af --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f10x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f10x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-48> +// Default: 48 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 48 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32103c-eval/board/gd32f10x_libopt.h b/bsp/gd32/gd32103c-eval/board/gd32f10x_libopt.h new file mode 100644 index 0000000000..5292c8eca7 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/gd32f10x_libopt.h @@ -0,0 +1,64 @@ +/*! + \file gd32f10x_libopt.h + \brief library optional for gd32f10x + + \version 2014-12-26, V1.0.0, demo for GD32F10x + \version 2017-06-30, V2.0.0, demo for GD32F10x + \version 2021-04-30, V2.1.0, demo for GD32F10x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_LIBOPT_H +#define GD32F10X_LIBOPT_H + +#include "gd32f10x_fmc.h" +#include "gd32f10x_pmu.h" +#include "gd32f10x_bkp.h" +#include "gd32f10x_rcu.h" +#include "gd32f10x_exti.h" +#include "gd32f10x_gpio.h" +#include "gd32f10x_crc.h" +#include "gd32f10x_dma.h" +#include "gd32f10x_dbg.h" +#include "gd32f10x_adc.h" +#include "gd32f10x_dac.h" +#include "gd32f10x_fwdgt.h" +#include "gd32f10x_wwdgt.h" +#include "gd32f10x_rtc.h" +#include "gd32f10x_timer.h" +#include "gd32f10x_usart.h" +#include "gd32f10x_i2c.h" +#include "gd32f10x_spi.h" +#include "gd32f10x_sdio.h" +#include "gd32f10x_exmc.h" +#include "gd32f10x_can.h" +#include "gd32f10x_enet.h" +#include "gd32f10x_misc.h" + +#endif /* GD32F10X_LIBOPT_H */ diff --git a/bsp/gd32/gd32103c-eval/board/linker_scripts/link.icf b/bsp/gd32/gd32103c-eval/board/linker_scripts/link.icf new file mode 100644 index 0000000000..c1b7bfa182 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2000BFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32103c-eval/board/linker_scripts/link.ld b/bsp/gd32/gd32103c-eval/board/linker_scripts/link.ld new file mode 100644 index 0000000000..7bacb5ab4a --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-18 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 48k /* 48KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32103c-eval/board/linker_scripts/link.sct b/bsp/gd32/gd32103c-eval/board/linker_scripts/link.sct new file mode 100644 index 0000000000..99f1f72a75 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x0000C000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32103c-eval/project.uvoptx b/bsp/gd32/gd32103c-eval/project.uvoptx new file mode 100644 index 0000000000..3cd7319e9d --- /dev/null +++ b/bsp/gd32/gd32103c-eval/project.uvoptx @@ -0,0 +1,748 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F10x_CL -FL040000 -FS08000000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + Applications + 0 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 5 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + context_rvds.S + 0 + 0 + + + 2 + 6 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + cpuport.c + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 16 + 2 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_hd.s + startup_gd32f10x_hd.s + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 5 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 23 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 24 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 25 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 26 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 7 + 36 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 37 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + gd32f10x_exti.c + 0 + 0 + + + 8 + 38 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + gd32f10x_gpio.c + 0 + 0 + + + 8 + 39 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + gd32f10x_misc.c + 0 + 0 + + + 8 + 40 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + system_gd32f10x.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + gd32f10x_rcu.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + gd32f10x_usart.c + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32103c-eval/project.uvproj b/bsp/gd32/gd32103c-eval/project.uvproj new file mode 100644 index 0000000000..a9b71eca4c --- /dev/null +++ b/bsp/gd32/gd32103c-eval/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F103VC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_HD, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + Drivers + + + startup_gd32f10x_hd.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_hd.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + + +
diff --git a/bsp/gd32/gd32103c-eval/project.uvprojx b/bsp/gd32/gd32103c-eval/project.uvprojx new file mode 100644 index 0000000000..297c9fc433 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/project.uvprojx @@ -0,0 +1,668 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F103VC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x0000C000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F103VC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F103VC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F103VC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0xc000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_HD, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + Drivers + + + startup_gd32f10x_hd.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_hd.s + + + board.c + 1 + board\board.c + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + clock.c + 1 + ..\..\..\src\clock.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + components.c + 1 + ..\..\..\src\components.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + device.c + 1 + ..\..\..\src\device.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + object.c + 1 + ..\..\..\src\object.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32103c-eval/rtconfig.h b/bsp/gd32/gd32103c-eval/rtconfig.h new file mode 100644 index 0000000000..c461a768e1 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F10x +#define SOC_GD32103V + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32103c-eval/rtconfig.py b/bsp/gd32/gd32103c-eval/rtconfig.py new file mode 100644 index 0000000000..4285e6b03c --- /dev/null +++ b/bsp/gd32/gd32103c-eval/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32103c-eval/template.uvoptx b/bsp/gd32/gd32103c-eval/template.uvoptx new file mode 100644 index 0000000000..e99a756fe7 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F10x_CL -FL040000 -FS08000000 -FP0($$Device:GD32F105RC$Flash\GD32F10x_CL.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32103c-eval/template.uvproj b/bsp/gd32/gd32103c-eval/template.uvproj new file mode 100644 index 0000000000..33458e05f7 --- /dev/null +++ b/bsp/gd32/gd32103c-eval/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F103VC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f10x_it.c + 1 + ..\gd32f10x_it.c + + + + + CMSIS + + + system_gd32f10x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + GD32F10x_Peripherals + + + gd32f10x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + gd32f10x_can.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_can.c + + + gd32f10x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_crc.c + + + gd32f10x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ctc.c + + + gd32f10x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dac.c + + + gd32f10x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dbg.c + + + gd32f10x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dci.c + + + gd32f10x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dma.c + + + gd32f10x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_enet.c + + + gd32f10x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exmc.c + + + gd32f10x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fmc.c + + + gd32f10x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fwdgt.c + + + gd32f10x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + gd32f10x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ipa.c + + + gd32f10x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_iref.c + + + gd32f10x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + gd32f10x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_pmu.c + + + gd32f10x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rtc.c + + + gd32f10x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_sdio.c + + + gd32f10x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + gd32f10x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_syscfg.c + + + gd32f10x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_timer.c + + + gd32f10x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_tli.c + + + gd32f10x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_trng.c + + + gd32f10x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + gd32f10x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_wwdgt.c + + + + + GD32F10x_EVAL + + + gd32f103c_eval.c + 1 + ..\..\..\Library\Utilities\gd32f103c_eval.c + + + + + Startup + + + startup_gd32f10x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32103c-eval/template.uvprojx b/bsp/gd32/gd32103c-eval/template.uvprojx new file mode 100644 index 0000000000..efc072e87e --- /dev/null +++ b/bsp/gd32/gd32103c-eval/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F103VC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x0000C000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F103VC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F103VC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F103VC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0xc000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32105c-eval/.config b/bsp/gd32/gd32105c-eval/.config new file mode 100644 index 0000000000..84090ac74e --- /dev/null +++ b/bsp/gd32/gd32105c-eval/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F10x=y +CONFIG_SOC_GD32105V=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32105c-eval/Kconfig b/bsp/gd32/gd32105c-eval/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32105c-eval/README.md b/bsp/gd32/gd32105c-eval/README.md new file mode 100644 index 0000000000..623501ef26 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/README.md @@ -0,0 +1,98 @@ +# GD32105C-EVAL开发板BSP说明 + +## 简介 + +GD3105C-EVAL是-兆易创新推出的一款GD32F10X系列的评估板,最高主频高达108M,该开发板具有丰富的板载资源,可以充分发挥 GD32105VCT6 的芯片性能。 + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32105VCT6,主频 108MHz,256KB FLASH ,96KB RAM + +- 常用外设 + + - LED :5个,LED1 (电源指示灯),LED2(PC0),LED3(PC2),LED4(PE0),LED5(PE1) + - 按键:3个,K1(用户按键,PA0),K2(用户按键,PC13),K3(用户按键,PB14) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0 - SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 10:00:27 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32105c-eval/SConscript b/bsp/gd32/gd32105c-eval/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32105c-eval/SConstruct b/bsp/gd32/gd32105c-eval/SConstruct new file mode 100644 index 0000000000..49074397d0 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F10x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32105c-eval/applications/SConscript b/bsp/gd32/gd32105c-eval/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32105c-eval/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32105c-eval/applications/main.c b/bsp/gd32/gd32105c-eval/applications/main.c new file mode 100644 index 0000000000..4a528128b4 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32105c-eval/board/Kconfig b/bsp/gd32/gd32105c-eval/board/Kconfig new file mode 100644 index 0000000000..72f7f9634a --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F10x + bool + default y + +config SOC_GD32105V + bool + select SOC_SERIES_GD32F10x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32105c-eval/board/SConscript b/bsp/gd32/gd32105c-eval/board/SConscript new file mode 100644 index 0000000000..c1f4a6001b --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s'] + +CPPDEFINES = ['GD32F10X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32105c-eval/board/board.c b/bsp/gd32/gd32105c-eval/board/board.c new file mode 100644 index 0000000000..c409645b37 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32105c-eval/board/board.h b/bsp/gd32/gd32105c-eval/board/board.h new file mode 100644 index 0000000000..11fb4fa084 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f10x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f10x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-96> +// Default: 96 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 96 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32105c-eval/board/gd32f10x_libopt.h b/bsp/gd32/gd32105c-eval/board/gd32f10x_libopt.h new file mode 100644 index 0000000000..5292c8eca7 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/gd32f10x_libopt.h @@ -0,0 +1,64 @@ +/*! + \file gd32f10x_libopt.h + \brief library optional for gd32f10x + + \version 2014-12-26, V1.0.0, demo for GD32F10x + \version 2017-06-30, V2.0.0, demo for GD32F10x + \version 2021-04-30, V2.1.0, demo for GD32F10x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_LIBOPT_H +#define GD32F10X_LIBOPT_H + +#include "gd32f10x_fmc.h" +#include "gd32f10x_pmu.h" +#include "gd32f10x_bkp.h" +#include "gd32f10x_rcu.h" +#include "gd32f10x_exti.h" +#include "gd32f10x_gpio.h" +#include "gd32f10x_crc.h" +#include "gd32f10x_dma.h" +#include "gd32f10x_dbg.h" +#include "gd32f10x_adc.h" +#include "gd32f10x_dac.h" +#include "gd32f10x_fwdgt.h" +#include "gd32f10x_wwdgt.h" +#include "gd32f10x_rtc.h" +#include "gd32f10x_timer.h" +#include "gd32f10x_usart.h" +#include "gd32f10x_i2c.h" +#include "gd32f10x_spi.h" +#include "gd32f10x_sdio.h" +#include "gd32f10x_exmc.h" +#include "gd32f10x_can.h" +#include "gd32f10x_enet.h" +#include "gd32f10x_misc.h" + +#endif /* GD32F10X_LIBOPT_H */ diff --git a/bsp/gd32/gd32105c-eval/board/linker_scripts/link.icf b/bsp/gd32/gd32105c-eval/board/linker_scripts/link.icf new file mode 100644 index 0000000000..283881a728 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32105c-eval/board/linker_scripts/link.ld b/bsp/gd32/gd32105c-eval/board/linker_scripts/link.ld new file mode 100644 index 0000000000..8ba4a0e9f2 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96k /* 96KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32105c-eval/board/linker_scripts/link.sct b/bsp/gd32/gd32105c-eval/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0529ba2b9c --- /dev/null +++ b/bsp/gd32/gd32105c-eval/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00018000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32105c-eval/figures/board.jpg b/bsp/gd32/gd32105c-eval/figures/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3cec090a59b3f4a29df5070bc0df0112b8e8105e GIT binary patch literal 169187 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%0A6ys*Q>g1K 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 literal 0 HcmV?d00001 diff --git a/bsp/gd32/gd32105c-eval/project.uvoptx b/bsp/gd32/gd32105c-eval/project.uvoptx new file mode 100644 index 0000000000..d691bf54c0 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/project.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F10x_CL -FL040000 -FS08000000 -FP0($$Device:GD32F105VC$Flash\GD32F10x_CL.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32105c-eval/project.uvproj b/bsp/gd32/gd32105c-eval/project.uvproj new file mode 100644 index 0000000000..e93bac770b --- /dev/null +++ b/bsp/gd32/gd32105c-eval/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F105VC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + + + startup_gd32f10x_cl.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + + +
diff --git a/bsp/gd32/gd32105c-eval/project.uvprojx b/bsp/gd32/gd32105c-eval/project.uvprojx new file mode 100644 index 0000000000..2600998e70 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/project.uvprojx @@ -0,0 +1,727 @@ + + + 2.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F105VC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105VC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F105VC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F105VC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + + + startup_gd32f10x_cl.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + +
diff --git a/bsp/gd32/gd32105c-eval/rtconfig.h b/bsp/gd32/gd32105c-eval/rtconfig.h new file mode 100644 index 0000000000..67fb740e3b --- /dev/null +++ b/bsp/gd32/gd32105c-eval/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F10x +#define SOC_GD32105V + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32105c-eval/rtconfig.py b/bsp/gd32/gd32105c-eval/rtconfig.py new file mode 100644 index 0000000000..4285e6b03c --- /dev/null +++ b/bsp/gd32/gd32105c-eval/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32105c-eval/template.uvoptx b/bsp/gd32/gd32105c-eval/template.uvoptx new file mode 100644 index 0000000000..d691bf54c0 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F10x_CL -FL040000 -FS08000000 -FP0($$Device:GD32F105VC$Flash\GD32F10x_CL.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32105c-eval/template.uvproj b/bsp/gd32/gd32105c-eval/template.uvproj new file mode 100644 index 0000000000..8ad9e1c662 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F105VC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(10800000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f10x_it.c + 1 + ..\gd32f10x_it.c + + + + + CMSIS + + + system_gd32f10x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + GD32F10x_Peripherals + + + gd32f10x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + gd32f10x_can.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_can.c + + + gd32f10x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_crc.c + + + gd32f10x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ctc.c + + + gd32f10x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dac.c + + + gd32f10x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dbg.c + + + gd32f10x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dci.c + + + gd32f10x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dma.c + + + gd32f10x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_enet.c + + + gd32f10x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exmc.c + + + gd32f10x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fmc.c + + + gd32f10x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fwdgt.c + + + gd32f10x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + gd32f10x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ipa.c + + + gd32f10x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_iref.c + + + gd32f10x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + gd32f10x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_pmu.c + + + gd32f10x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rtc.c + + + gd32f10x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_sdio.c + + + gd32f10x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + gd32f10x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_syscfg.c + + + gd32f10x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_timer.c + + + gd32f10x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_tli.c + + + gd32f10x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_trng.c + + + gd32f10x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + gd32f10x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_wwdgt.c + + + + + GD32F10x_EVAL + + + gd32f105c_eval.c + 1 + ..\..\..\Library\Utilities\gd32f105c_eval.c + + + + + Startup + + + startup_gd32f10x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32105c-eval/template.uvprojx b/bsp/gd32/gd32105c-eval/template.uvprojx new file mode 100644 index 0000000000..2b0da81501 --- /dev/null +++ b/bsp/gd32/gd32105c-eval/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F105VC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F105VC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F105VC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F105VC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32107c-eval/.config b/bsp/gd32/gd32107c-eval/.config new file mode 100644 index 0000000000..595bf9bc01 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/.config @@ -0,0 +1,670 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +# CONFIG_RT_USING_HEAP_ISR is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40100 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +CONFIG_RT_USING_SPI=y +# CONFIG_RT_USING_QSPI is not set +# CONFIG_RT_USING_SPI_MSD is not set +# CONFIG_RT_USING_SFUD is not set +# CONFIG_RT_USING_ENC28J60 is not set +# CONFIG_RT_USING_SPI_WIFI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 + +# +# POSIX (Portable Operating System Interface) layer +# +# CONFIG_RT_USING_POSIX_FS is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_GETLINE is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# +# CONFIG_PKG_USING_LUATOS_SOC is not set + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F10x=y +CONFIG_SOC_GD32107V=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +CONFIG_BSP_USING_SPI=y +CONFIG_BSP_USING_SPI1=y +# CONFIG_BSP_SPI1_TX_USING_DMA is not set +# CONFIG_BSP_SPI1_RX_USING_DMA is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32107c-eval/Kconfig b/bsp/gd32/gd32107c-eval/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32107c-eval/README.md b/bsp/gd32/gd32107c-eval/README.md new file mode 100644 index 0000000000..a5dd4a3132 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/README.md @@ -0,0 +1,98 @@ +# GD32107C-EVAL开发板BSP说明 + +## 简介 + +GD3107C-EVAL是-兆易创新推出的一款GD32F10X系列的评估板,最高主频高达108M,该开发板具有丰富的板载资源,可以充分发挥 GD32107VCT6 的芯片性能。 + +开发板外观如下图所示: + +![board](figures/board.jpg) + +该开发板常用 **板载资源** 如下: + +- GD32107VCT6,主频 108MHz,256KB FLASH ,96KB RAM + +- 常用外设 + + - LED :5个,LED1 (电源指示灯),LED2(PC0),LED3(PC2),LED4(PE0),LED5(PE1) + - 按键:3个,K1(用户按键,PA0),K2(用户按键,PC13),K3(用户按键,PB14) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0 - SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Dec 19 2021 10:00:27 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32107c-eval/SConscript b/bsp/gd32/gd32107c-eval/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32107c-eval/SConstruct b/bsp/gd32/gd32107c-eval/SConstruct new file mode 100644 index 0000000000..49074397d0 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F10x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32107c-eval/applications/SConscript b/bsp/gd32/gd32107c-eval/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32107c-eval/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32107c-eval/applications/main.c b/bsp/gd32/gd32107c-eval/applications/main.c new file mode 100644 index 0000000000..4a528128b4 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PC6 */ +#define LED2_PIN GET_PIN(C, 6) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32107c-eval/board/Kconfig b/bsp/gd32/gd32107c-eval/board/Kconfig new file mode 100644 index 0000000000..c20447d8e7 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F10x + bool + default y + +config SOC_GD32107V + bool + select SOC_SERIES_GD32F10x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32107c-eval/board/SConscript b/bsp/gd32/gd32107c-eval/board/SConscript new file mode 100644 index 0000000000..c1f4a6001b --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/GCC/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/ARM/startup_gd32f10x_cl.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F10x_Firmware_Library/CMSIS/GD/GD32F10x/Source/IAR/startup_gd32f10x_cl.s'] + +CPPDEFINES = ['GD32F10X_CL'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32107c-eval/board/board.c b/bsp/gd32/gd32107c-eval/board/board.c new file mode 100644 index 0000000000..c409645b37 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32107c-eval/board/board.h b/bsp/gd32/gd32107c-eval/board/board.h new file mode 100644 index 0000000000..11fb4fa084 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f10x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f10x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-96> +// Default: 96 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 96 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32107c-eval/board/gd32f10x_libopt.h b/bsp/gd32/gd32107c-eval/board/gd32f10x_libopt.h new file mode 100644 index 0000000000..5292c8eca7 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/gd32f10x_libopt.h @@ -0,0 +1,64 @@ +/*! + \file gd32f10x_libopt.h + \brief library optional for gd32f10x + + \version 2014-12-26, V1.0.0, demo for GD32F10x + \version 2017-06-30, V2.0.0, demo for GD32F10x + \version 2021-04-30, V2.1.0, demo for GD32F10x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F10X_LIBOPT_H +#define GD32F10X_LIBOPT_H + +#include "gd32f10x_fmc.h" +#include "gd32f10x_pmu.h" +#include "gd32f10x_bkp.h" +#include "gd32f10x_rcu.h" +#include "gd32f10x_exti.h" +#include "gd32f10x_gpio.h" +#include "gd32f10x_crc.h" +#include "gd32f10x_dma.h" +#include "gd32f10x_dbg.h" +#include "gd32f10x_adc.h" +#include "gd32f10x_dac.h" +#include "gd32f10x_fwdgt.h" +#include "gd32f10x_wwdgt.h" +#include "gd32f10x_rtc.h" +#include "gd32f10x_timer.h" +#include "gd32f10x_usart.h" +#include "gd32f10x_i2c.h" +#include "gd32f10x_spi.h" +#include "gd32f10x_sdio.h" +#include "gd32f10x_exmc.h" +#include "gd32f10x_can.h" +#include "gd32f10x_enet.h" +#include "gd32f10x_misc.h" + +#endif /* GD32F10X_LIBOPT_H */ diff --git a/bsp/gd32/gd32107c-eval/board/linker_scripts/link.icf b/bsp/gd32/gd32107c-eval/board/linker_scripts/link.icf new file mode 100644 index 0000000000..283881a728 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32107c-eval/board/linker_scripts/link.ld b/bsp/gd32/gd32107c-eval/board/linker_scripts/link.ld new file mode 100644 index 0000000000..8ba4a0e9f2 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 96k /* 96KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32107c-eval/board/linker_scripts/link.sct b/bsp/gd32/gd32107c-eval/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0529ba2b9c --- /dev/null +++ b/bsp/gd32/gd32107c-eval/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00040000 { ; load region size_region + ER_IROM1 0x08000000 0x00040000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00018000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32107c-eval/figures/board.jpg b/bsp/gd32/gd32107c-eval/figures/board.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7eec2d53d55e60efa377e3b748f252bbe8ba942f GIT binary patch literal 128732 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

~E~@JOjnwAtNRWMP3Z)4Z2^n9RF#Wl0 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 L`~NsD{GIt + + + 1.0 + +

### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F10x_CL -FL040000 -FS08000000 -FP0($$Device:GD32F107VC$Flash\GD32F10x_CL.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + Applications + 0 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + cpuport.c + 0 + 0 + + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + context_rvds.S + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\spi\spi_core.c + spi_core.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\spi\spi_dev.c + spi_dev.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 16 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 17 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 18 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 19 + 2 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + startup_gd32f10x_cl.s + 0 + 0 + + + 4 + 20 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 21 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + 4 + 22 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_spi.c + drv_spi.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 5 + 23 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 24 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 25 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 26 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 36 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 6 + 37 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 6 + 38 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 7 + 39 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 40 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + gd32f10x_spi.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + gd32f10x_exti.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + gd32f10x_gpio.c + 0 + 0 + + + 8 + 43 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + gd32f10x_misc.c + 0 + 0 + + + 8 + 44 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + system_gd32f10x.c + 0 + 0 + + + 8 + 45 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + gd32f10x_rcu.c + 0 + 0 + + + 8 + 46 + 1 + 0 + 0 + 0 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + gd32f10x_usart.c + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + + diff --git a/bsp/gd32/gd32107c-eval/project.uvproj b/bsp/gd32/gd32107c-eval/project.uvproj new file mode 100644 index 0000000000..695885d4ba --- /dev/null +++ b/bsp/gd32/gd32107c-eval/project.uvproj @@ -0,0 +1,777 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F107VC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(12000000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + spi_core.c + 1 + ..\..\..\components\drivers\spi\spi_core.c + + + + + spi_dev.c + 1 + ..\..\..\components\drivers\spi\spi_dev.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + + + + + + + + + + + + + Drivers + + + board.c + 1 + board\board.c + + + + + startup_gd32f10x_cl.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + drv_spi.c + 1 + ..\libraries\gd32_drivers\drv_spi.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_spi.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + + +
diff --git a/bsp/gd32/gd32107c-eval/project.uvprojx b/bsp/gd32/gd32107c-eval/project.uvprojx new file mode 100644 index 0000000000..3d5ae39245 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/project.uvprojx @@ -0,0 +1,757 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F107VC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F107VC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F107VC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F107VC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F10X_CL, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m3;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Include;..\libraries\GD32F10x_Firmware_Library\CMSIS;..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m3\cpuport.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m3\context_rvds.S + + + + + DeviceDrivers + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 0 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + + + + + + + + + + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + spi_core.c + 1 + ..\..\..\components\drivers\spi\spi_core.c + + + spi_dev.c + 1 + ..\..\..\components\drivers\spi\spi_dev.c + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + Drivers + + + board.c + 1 + board\board.c + + + startup_gd32f10x_cl.s + 2 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x_cl.s + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + drv_spi.c + 1 + ..\libraries\gd32_drivers\drv_spi.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + thread.c + 1 + ..\..\..\src\thread.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + components.c + 1 + ..\..\..\src\components.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + device.c + 1 + ..\..\..\src\device.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + clock.c + 1 + ..\..\..\src\clock.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + object.c + 1 + ..\..\..\src\object.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f10x_spi.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + gd32f10x_exti.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_gpio.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_misc.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + system_gd32f10x.c + 1 + ..\libraries\GD32F10x_Firmware_Library\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + gd32f10x_rcu.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_usart.c + 1 + ..\libraries\GD32F10x_Firmware_Library\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32107c-eval/rtconfig.h b/bsp/gd32/gd32107c-eval/rtconfig.h new file mode 100644 index 0000000000..21caecd9ee --- /dev/null +++ b/bsp/gd32/gd32107c-eval/rtconfig.h @@ -0,0 +1,212 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40100 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN +#define RT_USING_SPI + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* POSIX (Portable Operating System Interface) layer */ + + +/* Interprocess Communication (IPC) */ + + +/* Socket is in the 'Network' category */ + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F10x +#define SOC_GD32107V + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 +#define BSP_USING_SPI +#define BSP_USING_SPI1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32107c-eval/rtconfig.py b/bsp/gd32/gd32107c-eval/rtconfig.py new file mode 100644 index 0000000000..4285e6b03c --- /dev/null +++ b/bsp/gd32/gd32107c-eval/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m3' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M3.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M3' + CFLAGS += ' -e' + CFLAGS += ' --fpu=None' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M3' + AFLAGS += ' --fpu None' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32107c-eval/template.uvoptx b/bsp/gd32/gd32107c-eval/template.uvoptx new file mode 100644 index 0000000000..4dfb02c5ad --- /dev/null +++ b/bsp/gd32/gd32107c-eval/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 ) -FN1 -FC1000 -FD20000000 -FF0GD32F10x_CL -FL040000 -FS08000000 -FP0($$Device:GD32F107VC$Flash\GD32F10x_CL.FLM) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32107c-eval/template.uvproj b/bsp/gd32/gd32107c-eval/template.uvproj new file mode 100644 index 0000000000..a165464790 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F107VC + GigaDevice + IRAM(0x20000000-0x20018000) IROM(0x08000000-0x08040000) CLOCK(12000000) CPUTYPE("Cortex-M3") + + "Startup\GD\GD32F10x\startup_gd32f10x.s" ("GD32F10x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F10x_3MB -FS08000000 -FL0100000) + 0 + gd32f10x0.h + + + + + + + + + + SFD\GD\GD32F10x\GD32F10x.SFR + 0 + 0 + + + + GD\GD32F10x\ + GD\GD32F10x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x100000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f10x_it.c + 1 + ..\gd32f10x_it.c + + + + + CMSIS + + + system_gd32f10x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\system_gd32f10x.c + + + + + GD32F10x_Peripherals + + + gd32f10x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_adc.c + + + gd32f10x_can.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_can.c + + + gd32f10x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_crc.c + + + gd32f10x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ctc.c + + + gd32f10x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dac.c + + + gd32f10x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dbg.c + + + gd32f10x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dci.c + + + gd32f10x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_dma.c + + + gd32f10x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_enet.c + + + gd32f10x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exmc.c + + + gd32f10x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_exti.c + + + gd32f10x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fmc.c + + + gd32f10x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_fwdgt.c + + + gd32f10x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_gpio.c + + + gd32f10x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_i2c.c + + + gd32f10x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_ipa.c + + + gd32f10x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_iref.c + + + gd32f10x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_misc.c + + + gd32f10x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_pmu.c + + + gd32f10x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rcu.c + + + gd32f10x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_rtc.c + + + gd32f10x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_sdio.c + + + gd32f10x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_spi.c + + + gd32f10x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_syscfg.c + + + gd32f10x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_timer.c + + + gd32f10x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_tli.c + + + gd32f10x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_trng.c + + + gd32f10x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_usart.c + + + gd32f10x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F10x_standard_peripheral\Source\gd32f10x_wwdgt.c + + + + + GD32F10x_EVAL + + + gd32f107c_eval.c + 1 + ..\..\..\Library\Utilities\gd32f107c_eval.c + + + + + Startup + + + startup_gd32f10x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F10x\Source\ARM\startup_gd32f10x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32107c-eval/template.uvprojx b/bsp/gd32/gd32107c-eval/template.uvprojx new file mode 100644 index 0000000000..a80f13ffb9 --- /dev/null +++ b/bsp/gd32/gd32107c-eval/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F107VC + GigaDevice + GigaDevice.GD32F10x_DFP.2.0.1 + http://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IROM(0x08000000,0x00040000) CPUTYPE("Cortex-M3") CLOCK(10800000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F107VC$Flash\GD32F10x_CL.FLM)) + 0 + $$Device:GD32F107VC$Device\Include\gd32f10x.h + + + + + + + + + + $$Device:GD32F107VC$SVD\GD32F10x\GD32F10x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M3" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32303e-eval/.config b/bsp/gd32/gd32303e-eval/.config new file mode 100644 index 0000000000..c8f9feac51 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F30x=y +CONFIG_SOC_GD32305R=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32303e-eval/Kconfig b/bsp/gd32/gd32303e-eval/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32303e-eval/README.md b/bsp/gd32/gd32303e-eval/README.md new file mode 100644 index 0000000000..dd789e8394 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/README.md @@ -0,0 +1,94 @@ +# GD32303E-EVAL开发板BSP说明 + +## 简介 + +GD3303E-EVAL是-兆易创新推出的一款GD32F30X系列的评估板,最高主频高达120M,该开发板具有丰富的板载资源,可以充分发挥 GD32303ZET6 的芯片性能。 + +该开发板常用 **板载资源** 如下: + +- GD32303ZET6,主频 120MHz,512KB FLASH ,64KB RAM + +- 常用外设 + + - LED :5个,LED1 (电源指示灯),LED2(PC0),LED3(PC2),LED4(PE0),LED5(PE1) + - 按键:3个,K1(用户按键,PA0),K2(用户按键,PC13),K3(用户按键,PB14) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0 - SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Jan 9 2021 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32303e-eval/SConscript b/bsp/gd32/gd32303e-eval/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32303e-eval/SConstruct b/bsp/gd32/gd32303e-eval/SConstruct new file mode 100644 index 0000000000..f32e96f624 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F30x_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32303e-eval/applications/SConscript b/bsp/gd32/gd32303e-eval/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32303e-eval/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32303e-eval/applications/main.c b/bsp/gd32/gd32303e-eval/applications/main.c new file mode 100644 index 0000000000..3e85fc86ca --- /dev/null +++ b/bsp/gd32/gd32303e-eval/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED2 pin: PF0 */ +#define LED2_PIN GET_PIN(F, 0) + +int main(void) +{ + int count = 1; + + /* set LED2 pin mode to output */ + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED2_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED2_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32303e-eval/board/Kconfig b/bsp/gd32/gd32303e-eval/board/Kconfig new file mode 100644 index 0000000000..c4b496f179 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F30x + bool + default y + +config SOC_GD32303Z + bool + select SOC_SERIES_GD32F30x + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32303e-eval/board/SConscript b/bsp/gd32/gd32303e-eval/board/SConscript new file mode 100644 index 0000000000..1d4c0408eb --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_hd.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F30x_Firmware_Library/CMSIS/GD/GD32F30x/Source/IAR/startup_gd32f30x_hd.s'] + +CPPDEFINES = ['GD32F30X_HD'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32303e-eval/board/board.c b/bsp/gd32/gd32303e-eval/board/board.c new file mode 100644 index 0000000000..c409645b37 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32303e-eval/board/board.h b/bsp/gd32/gd32303e-eval/board/board.h new file mode 100644 index 0000000000..aecf8beaad --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-18 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f30x.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f30x_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-64> +// Default: 64 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 64 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32303e-eval/board/gd32f30x_libopt.h b/bsp/gd32/gd32303e-eval/board/gd32f30x_libopt.h new file mode 100644 index 0000000000..e026fd658a --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/gd32f30x_libopt.h @@ -0,0 +1,65 @@ +/*! + \file gd32f30x_libopt.h + \brief library optional for gd32f30x + + \version 2021-03-23, V2.0.0, demo for GD32F30x +*/ + +/* + Copyright (c) 2021, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef GD32F30X_LIBOPT_H +#define GD32F30X_LIBOPT_H + +#include "gd32f30x_rcu.h" +#include "gd32f30x_adc.h" +#include "gd32f30x_can.h" +#include "gd32f30x_crc.h" +#include "gd32f30x_ctc.h" +#include "gd32f30x_dac.h" +#include "gd32f30x_dbg.h" +#include "gd32f30x_dma.h" +#include "gd32f30x_exti.h" +#include "gd32f30x_fmc.h" +#include "gd32f30x_fwdgt.h" +#include "gd32f30x_gpio.h" +#include "gd32f30x_i2c.h" +#include "gd32f30x_pmu.h" +#include "gd32f30x_bkp.h" +#include "gd32f30x_rtc.h" +#include "gd32f30x_sdio.h" +#include "gd32f30x_spi.h" +#include "gd32f30x_timer.h" +#include "gd32f30x_usart.h" +#include "gd32f30x_wwdgt.h" +#include "gd32f30x_misc.h" +#include "gd32f30x_exmc.h" +#ifdef GD32F30X_CL +#include "gd32f30x_enet.h" +#endif /* GD32F30X_CL */ + +#endif /* GD32F30X_LIBOPT_H */ diff --git a/bsp/gd32/gd32303e-eval/board/linker_scripts/link.icf b/bsp/gd32/gd32303e-eval/board/linker_scripts/link.icf new file mode 100644 index 0000000000..f68fd14425 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0807FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x200FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x200; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32303e-eval/board/linker_scripts/link.ld b/bsp/gd32/gd32303e-eval/board/linker_scripts/link.ld new file mode 100644 index 0000000000..357cefe333 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F30x with GNU ld + * BruceOu 2021-12-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 512k /* 512KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 64k /* 64KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32303e-eval/board/linker_scripts/link.sct b/bsp/gd32/gd32303e-eval/board/linker_scripts/link.sct new file mode 100644 index 0000000000..0835abf43e --- /dev/null +++ b/bsp/gd32/gd32303e-eval/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00080000 { ; load region size_region + ER_IROM1 0x08000000 0x00080000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00010000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32303e-eval/project.uvoptx b/bsp/gd32/gd32303e-eval/project.uvoptx new file mode 100644 index 0000000000..904a7c0f0e --- /dev/null +++ b/bsp/gd32/gd32303e-eval/project.uvoptx @@ -0,0 +1,748 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + Applications + 0 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 16 + 2 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_hd.s + startup_gd32f30x_hd.s + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + 4 + 18 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 19 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 5 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 21 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 22 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 6 + 23 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 6 + 24 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 6 + 25 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 6 + 26 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + 6 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 6 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 6 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 6 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 7 + 36 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 8 + 37 + 1 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + system_gd32f30x.c + 0 + 0 + + + 8 + 38 + 1 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + gd32f30x_rcu.c + 0 + 0 + + + 8 + 39 + 1 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + gd32f30x_usart.c + 0 + 0 + + + 8 + 40 + 1 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + gd32f30x_exti.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + gd32f30x_gpio.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + gd32f30x_misc.c + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32303e-eval/project.uvproj b/bsp/gd32/gd32303e-eval/project.uvproj new file mode 100644 index 0000000000..aabe6bfeb4 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/project.uvproj @@ -0,0 +1,737 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F303ZE + GigaDevice + IRAM(0x20000000-0x20010000) IROM(0x08000000-0x08080000) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F30x\startup_gd32f30x.s" ("GD32F30x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F30x_3MB -FS08000000 -FL0300000) + 0 + gd32f30x0.h + + + + + + + + + + SFD\GD\GD32F30x\GD32F30x.SFR + 0 + 0 + + + + GD\GD32F30x\ + GD\GD32F30x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F30X_HD, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + Drivers + + + startup_gd32f30x_hd.s + 2 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_hd.s + + + + + board.c + 1 + board\board.c + + + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + object.c + 1 + ..\..\..\src\object.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f30x.c + 1 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + gd32f30x_rcu.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + + + gd32f30x_usart.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + + + gd32f30x_exti.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + + + gd32f30x_gpio.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + + + gd32f30x_misc.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + + + + +
diff --git a/bsp/gd32/gd32303e-eval/project.uvprojx b/bsp/gd32/gd32303e-eval/project.uvprojx new file mode 100644 index 0000000000..126600ce4b --- /dev/null +++ b/bsp/gd32/gd32303e-eval/project.uvprojx @@ -0,0 +1,668 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F303ZE + GigaDevice + GigaDevice.GD32F30x_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x010000) IROM(0x08000000,0x080000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F303ZE$Flash\GD32F30x_CL.FLM)) + 0 + $$Device:GD32F303ZE$Device\Include\gd32f30x.h + + + + + + + + + + $$Device:GD32F303ZE$SVD\GD32F30x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x10000 + + + 1 + 0x8000000 + 0x80000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F30X_HD, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\gd32_drivers;..\..\..\components\finsh;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include;..\libraries\GD32F30x_Firmware_Library\CMSIS;..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + Drivers + + + startup_gd32f30x_hd.s + 2 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x_hd.s + + + board.c + 1 + board\board.c + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + Kernel + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + device.c + 1 + ..\..\..\src\device.c + + + thread.c + 1 + ..\..\..\src\thread.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + components.c + 1 + ..\..\..\src\components.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + clock.c + 1 + ..\..\..\src\clock.c + + + object.c + 1 + ..\..\..\src\object.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + system_gd32f30x.c + 1 + ..\libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + gd32f30x_rcu.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + gd32f30x_usart.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + gd32f30x_exti.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + gd32f30x_gpio.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + gd32f30x_misc.c + 1 + ..\libraries\GD32F30x_Firmware_Library\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32303e-eval/rtconfig.h b/bsp/gd32/gd32303e-eval/rtconfig.h new file mode 100644 index 0000000000..099327af24 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F30x +#define SOC_GD32305R + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32303e-eval/rtconfig.py b/bsp/gd32/gd32303e-eval/rtconfig.py new file mode 100644 index 0000000000..a91905a233 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32303e-eval/template.uvoptx b/bsp/gd32/gd32303e-eval/template.uvoptx new file mode 100644 index 0000000000..18fdad5165 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/template.uvoptx @@ -0,0 +1,180 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 0 + 0 + 1 + + 0 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F305RC$Flash\GD32F30x_CL.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32303e-eval/template.uvproj b/bsp/gd32/gd32303e-eval/template.uvproj new file mode 100644 index 0000000000..c42d8a33b1 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F303ZE + GigaDevice + IRAM(0x20000000-0x20010000) IROM(0x08000000-0x08080000) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F30x\startup_gd32f30x.s" ("GD32F30x Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F30x_3MB -FS08000000 -FL0300000) + 0 + gd32f30x0.h + + + + + + + + + + SFD\GD\GD32F30x\GD32F30x.SFR + 0 + 0 + + + + GD\GD32F30x\ + GD\GD32F30x\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f30x_it.c + 1 + ..\gd32f30x_it.c + + + + + CMSIS + + + system_gd32f30x.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Source\system_gd32f30x.c + + + + + GD32F30x_Peripherals + + + gd32f30x_adc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_adc.c + + + gd32f30x_can.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_can.c + + + gd32f30x_crc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_crc.c + + + gd32f30x_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_ctc.c + + + gd32f30x_dac.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dac.c + + + gd32f30x_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dbg.c + + + gd32f30x_dci.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dci.c + + + gd32f30x_dma.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_dma.c + + + gd32f30x_enet.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_enet.c + + + gd32f30x_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_exmc.c + + + gd32f30x_exti.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_exti.c + + + gd32f30x_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_fmc.c + + + gd32f30x_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_fwdgt.c + + + gd32f30x_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_gpio.c + + + gd32f30x_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_i2c.c + + + gd32f30x_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_ipa.c + + + gd32f30x_iref.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_iref.c + + + gd32f30x_misc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_misc.c + + + gd32f30x_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_pmu.c + + + gd32f30x_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_rcu.c + + + gd32f30x_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_rtc.c + + + gd32f30x_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_sdio.c + + + gd32f30x_spi.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_spi.c + + + gd32f30x_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_syscfg.c + + + gd32f30x_timer.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_timer.c + + + gd32f30x_tli.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_tli.c + + + gd32f30x_trng.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_trng.c + + + gd32f30x_usart.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_usart.c + + + gd32f30x_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F30x_standard_peripheral\Source\gd32f30x_wwdgt.c + + + + + GD32F30x_EVAL + + + gd32f303e_eval.c + 1 + ..\..\..\Library\Utilities\gd32f303e_eval.c + + + + + Startup + + + startup_gd32f30x.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F30x\Source\ARM\startup_gd32f30x.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32303e-eval/template.uvprojx b/bsp/gd32/gd32303e-eval/template.uvprojx new file mode 100644 index 0000000000..7f6137db37 --- /dev/null +++ b/bsp/gd32/gd32303e-eval/template.uvprojx @@ -0,0 +1,418 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 5060750::V5.06 update 6 (build 750)::.\ARMCC + 0 + + + GD32F303ZE + GigaDevice + GigaDevice.GD32F30x_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x010000) IROM(0x08000000,0x080000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F30x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F303ZE$Flash\GD32F30x_CL.FLM)) + 0 + $$Device:GD32F303ZE$Device\Include\gd32f30x.h + + + + + + + + + + $$Device:GD32F303ZE$SVD\GD32F30x_CL.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x40000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x40000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x0 + 0x0 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32450z-eval/.config b/bsp/gd32/gd32450z-eval/.config new file mode 100644 index 0000000000..0acca6c304 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/.config @@ -0,0 +1,636 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_BIG_ENDIAN is not set +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=256 +# CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_ASM_MEMCPY is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +# CONFIG_RT_USING_MEMHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_MEMTRACE is not set +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +# CONFIG_RT_USING_DEVICE_OPS is not set +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +# CONFIG_RT_PRINTF_LONGLONG is not set +CONFIG_RT_VER_NUM=0x40004 +# CONFIG_RT_USING_CPU_FFS is not set +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +# CONFIG_RT_USING_DFS is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 +CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set +CONFIG_RT_SERIAL_USING_DMA=y +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +# CONFIG_RT_USING_RTC is not set +# CONFIG_RT_USING_SDIO is not set +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set +# CONFIG_RT_USING_AUDIO is not set +# CONFIG_RT_USING_SENSOR is not set +# CONFIG_RT_USING_TOUCH is not set +# CONFIG_RT_USING_HWCRYPTO is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set +# CONFIG_RT_USING_INPUT_CAPTURE is not set +# CONFIG_RT_USING_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB is not set +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +# CONFIG_RT_USING_LIBC is not set +CONFIG_RT_LIBC_USING_TIME=y +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 +# CONFIG_RT_USING_PTHREADS is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# Network interface device +# +# CONFIG_RT_USING_NETDEV is not set + +# +# light weight TCP/IP stack +# +# CONFIG_RT_USING_LWIP is not set + +# +# AT commands +# +# CONFIG_RT_USING_AT is not set + +# +# VBUS(Virtual Software BUS) +# +# CONFIG_RT_USING_VBUS is not set + +# +# Utilities +# +# CONFIG_RT_USING_RYM is not set +# CONFIG_RT_USING_ULOG is not set +# CONFIG_RT_USING_UTEST is not set +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set + +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_FREEMODBUS is not set +# CONFIG_PKG_USING_LJSON is not set +# CONFIG_PKG_USING_EZXML is not set +# CONFIG_PKG_USING_NANOPB is not set + +# +# Wi-Fi +# + +# +# Marvell WiFi +# +# CONFIG_PKG_USING_WLANMARVELL is not set + +# +# Wiced WiFi +# +# CONFIG_PKG_USING_WLAN_WICED is not set +# CONFIG_PKG_USING_RW007 is not set +# CONFIG_PKG_USING_COAP is not set +# CONFIG_PKG_USING_NOPOLL is not set +# CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set +# CONFIG_PKG_USING_AT_DEVICE is not set +# CONFIG_PKG_USING_ATSRV_SOCKET is not set +# CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set + +# +# IoT Cloud +# +# CONFIG_PKG_USING_ONENET is not set +# CONFIG_PKG_USING_GAGENT_CLOUD is not set +# CONFIG_PKG_USING_ALI_IOTKIT is not set +# CONFIG_PKG_USING_AZURE is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_NIMBLE is not set +# CONFIG_PKG_USING_OTA_DOWNLOADER is not set +# CONFIG_PKG_USING_IPMSG is not set +# CONFIG_PKG_USING_LSSDP is not set +# CONFIG_PKG_USING_AIRKISS_OPEN is not set +# CONFIG_PKG_USING_LIBRWS is not set +# CONFIG_PKG_USING_TCPSERVER is not set +# CONFIG_PKG_USING_PROTOBUF_C is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set + +# +# multimedia packages +# + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set +# CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +# CONFIG_PKG_USING_MEM_SANDBOX is not set +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set + +# +# system packages +# + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_THREAD_POOL is not set +# CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set + +# +# peripheral libraries and drivers +# +# CONFIG_PKG_USING_SENSORS_DRIVERS is not set +# CONFIG_PKG_USING_REALTEK_AMEBA is not set +# CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set +# CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_ICM20608 is not set +# CONFIG_PKG_USING_BUTTON is not set +# CONFIG_PKG_USING_PCF8574 is not set +# CONFIG_PKG_USING_SX12XX is not set +# CONFIG_PKG_USING_SIGNAL_LED is not set +# CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set +# CONFIG_PKG_USING_WM_LIBRARIES is not set +# CONFIG_PKG_USING_KENDRYTE_SDK is not set +# CONFIG_PKG_USING_INFRARED is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set +# CONFIG_PKG_USING_AT24CXX is not set +# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set +# CONFIG_PKG_USING_AD7746 is not set +# CONFIG_PKG_USING_PCA9685 is not set +# CONFIG_PKG_USING_I2C_TOOLS is not set +# CONFIG_PKG_USING_NRF24L01 is not set +# CONFIG_PKG_USING_TOUCH_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set + +# +# miscellaneous packages +# + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set +# CONFIG_PKG_USING_HELLO is not set +# CONFIG_PKG_USING_VI is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set + +# +# Hardware Drivers Config +# +CONFIG_SOC_SERIES_GD32F4xx=y +CONFIG_SOC_GD32450Z=y + +# +# Onboard Peripheral Drivers +# + +# +# On-chip Peripheral Drivers +# +CONFIG_BSP_USING_GPIO=y +CONFIG_BSP_USING_UART=y +CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_I2C1 is not set + +# +# Board extended module Drivers +# diff --git a/bsp/gd32/gd32450z-eval/Kconfig b/bsp/gd32/gd32450z-eval/Kconfig new file mode 100644 index 0000000000..8cbc7b71a8 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/Kconfig @@ -0,0 +1,21 @@ +mainmenu "RT-Thread Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" +source "../libraries/Kconfig" +source "board/Kconfig" diff --git a/bsp/gd32/gd32450z-eval/README.md b/bsp/gd32/gd32450z-eval/README.md new file mode 100644 index 0000000000..6b398d8661 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/README.md @@ -0,0 +1,94 @@ +# GD32450Z-EVAL开发板BSP说明 + +## 简介 + +GD32450Z-EVAL是-兆易创新推出的一款GD32F4XX系列的评估板,最高主频高达168M,该开发板具有丰富的板载资源,可以充分发挥 GD32F450ZKT6的芯片性能。 + +该开发板常用 **板载资源** 如下: + +- GD32F450ZKT6,主频 200MHz,3072KB FLASH ,256KB RAM + +- 常用外设 + + - LED :3个,LED1 (PD4),LED2(PD5),LED3(PG3) + - 按键:2个,K1(PA0),K2(PC13),K3(PB14) + +- 常用接口:USB 接口 + +- 调试接口:GD-LINK + +## 外设支持 + +本 BSP 目前对外设的支持情况如下: + +| **片上外设** | **支持情况** | **备注** | +|:--------- |:--------:|:------------------------------------- | +| GPIO | 支持 | PA0, PA1... PK15 ---> PIN: 0, 1...144 | +| UART | 支持 | UART0 - UART7 | +| I2C | 支持 | I2C1 | +| SPI | 支持 | SPI0 - SPI2 | +| SPI FLASH | 支持 | | +| **扩展模块** | **支持情况** | **备注** | +| 暂无 | 暂不支持 | 暂不支持 | + +## 使用说明 + +使用说明分为如下两个章节: + +- 快速上手 + + 本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。 + +- 进阶使用 + + 本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。 + +### 快速上手 + +本 BSP 为开发者提供 MDK5 工程,并且支持 GCC 开发环境,也可使用RT-Thread Studio开发。下面以 MDK5 开发环境为例,介绍如何将系统运行起来。 + +#### 硬件连接 + +使用数据线连接开发板到 PC,使用USB转TTL模块连接PA2(MCU TX)和PA3(MCU RX),打开电源开关。 + +#### 编译下载 + +双击 project.uvprojx 文件,打开 MDK5 工程,编译并下载程序到开发板。 + +> 工程默认配置使用 GD-Link 仿真器下载程序,在通过 GD-Link 连接开发板的基础上,点击下载按钮即可下载程序到开发板 + +#### 运行结果 + +下载程序成功之后,系统会自动运行,LED 闪烁。 + +连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息: + +```bash + \ | / +- RT - Thread Operating System + / | \ 4.0.4 build Jan 9 2021 + 2006 - 2021 Copyright by rt-thread team +msh > +``` + +### 进阶使用 + +此 BSP 默认只开启了 GPIO 和 串口1的功能,如果需使用高级功能,需要利用 ENV 工具对BSP 进行配置,步骤如下: + +1. 在 bsp 下打开 env 工具。 + +2. 输入`menuconfig`命令配置工程,配置好之后保存退出。 + +3. 输入`pkgs --update`命令更新软件包。 + +4. 输入`scons --target=mdk4/mdk5` 命令重新生成工程。 + +## 注意事项 + +暂无 + +## 联系人信息 + +维护人: + +- [BruceOu](https://github.com/Ouxiaolong/), 邮箱: \ No newline at end of file diff --git a/bsp/gd32/gd32450z-eval/SConscript b/bsp/gd32/gd32450z-eval/SConscript new file mode 100644 index 0000000000..20f7689c53 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/SConscript @@ -0,0 +1,15 @@ +# for module compiling +import os +Import('RTT_ROOT') +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/gd32/gd32450z-eval/SConstruct b/bsp/gd32/gd32450z-eval/SConstruct new file mode 100644 index 0000000000..71deeebad1 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/SConstruct @@ -0,0 +1,60 @@ +import os +import sys +import rtconfig + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..') + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +try: + from building import * +except: + print('Cannot found RT-Thread root directory, please check RTT_ROOT') + print(RTT_ROOT) + exit(-1) + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +if rtconfig.PLATFORM == 'iar': + env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(ARFLAGS = ['']) + env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') + +Export('RTT_ROOT') +Export('rtconfig') + +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/libraries'): + libraries_path_prefix = SDK_ROOT + '/libraries' +else: + libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/libraries' + +SDK_LIB = libraries_path_prefix +Export('SDK_LIB') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) + +gd32_library = 'GD32F4xx_Firmware_Library' +rtconfig.BSP_LIBRARY_TYPE = gd32_library + +# include libraries +objs.extend(SConscript(os.path.join(libraries_path_prefix, gd32_library, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(libraries_path_prefix, 'gd32_drivers', 'SConscript'))) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/gd32/gd32450z-eval/applications/SConscript b/bsp/gd32/gd32450z-eval/applications/SConscript new file mode 100644 index 0000000000..01eb940dfb --- /dev/null +++ b/bsp/gd32/gd32450z-eval/applications/SConscript @@ -0,0 +1,11 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = os.path.join(str(Dir('#')), 'applications') +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/gd32/gd32450z-eval/applications/main.c b/bsp/gd32/gd32450z-eval/applications/main.c new file mode 100644 index 0000000000..5ce66c9b0c --- /dev/null +++ b/bsp/gd32/gd32450z-eval/applications/main.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ + +#include +#include +#include +#include + +/* defined the LED1 pin: PD4 */ +#define LED1_PIN GET_PIN(D, 4) + +int main(void) +{ + int count = 1; + + /* set LED1 pin mode to output */ + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + + while (count++) + { + rt_pin_write(LED1_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED1_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + + return RT_EOK; +} diff --git a/bsp/gd32/gd32450z-eval/board/Kconfig b/bsp/gd32/gd32450z-eval/board/Kconfig new file mode 100644 index 0000000000..6d37255141 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/Kconfig @@ -0,0 +1,85 @@ +menu "Hardware Drivers Config" + +config SOC_SERIES_GD32F4xx + bool + default y + +config SOC_GD32450Z + bool + select SOC_SERIES_GD32F4xx + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +menu "Onboard Peripheral Drivers" + +endmenu + +menu "On-chip Peripheral Drivers" + + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default y + + menuconfig BSP_USING_UART + bool "Enable UART" + default y + select RT_USING_SERIAL + if BSP_USING_UART + config BSP_USING_UART1 + bool "Enable UART1" + default y + + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI BUS" + default n + select RT_USING_SPI + if BSP_USING_SPI + config BSP_USING_SPI1 + bool "Enable SPI1 BUS" + default n + + config BSP_SPI1_TX_USING_DMA + bool "Enable SPI1 TX DMA" + depends on BSP_USING_SPI1 + default n + + config BSP_SPI1_RX_USING_DMA + bool "Enable SPI1 RX DMA" + depends on BSP_USING_SPI1 + select BSP_SPI1_TX_USING_DMA + default n + endif + + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + if BSP_USING_I2C1 + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 216 + default 24 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 216 + default 25 + endif + source "../libraries/gd32_drivers/Kconfig" + +endmenu + +menu "Board extended module Drivers" + +endmenu + +endmenu diff --git a/bsp/gd32/gd32450z-eval/board/SConscript b/bsp/gd32/gd32450z-eval/board/SConscript new file mode 100644 index 0000000000..77a18f74e1 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/SConscript @@ -0,0 +1,28 @@ +import os +import rtconfig +from building import * + +Import('SDK_LIB') + +cwd = GetCurrentDir() + +# add general drivers +src = Split(''' +board.c +''') + +path = [cwd] + +startup_path_prefix = SDK_LIB + +if rtconfig.CROSS_TOOL == 'gcc': + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/GCC/startup_gd32f4xx.s'] +elif rtconfig.CROSS_TOOL == 'keil': + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/ARM/startup_gd32f4xx.s'] +elif rtconfig.CROSS_TOOL == 'iar': + src += [startup_path_prefix + '/GD32F4xx_Firmware_Library/CMSIS/GD/GD32F4xx/Source/IAR/startup_gd32f4xx.s'] + +CPPDEFINES = ['GD32F450'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) + +Return('group') diff --git a/bsp/gd32/gd32450z-eval/board/board.c b/bsp/gd32/gd32450z-eval/board/board.c new file mode 100644 index 0000000000..0e9f89865a --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/board.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ +#include +#include +#include +#include + +/** + * @brief This function is executed in case of error occurrence. + * @param None + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler */ + /* User can add his own implementation to report the HAL error return state */ + while (1) + { + } + /* USER CODE END Error_Handler */ +} + +/** System Clock Configuration +*/ +void SystemClock_Config(void) +{ + SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); + NVIC_SetPriority(SysTick_IRQn, 0); +} + +/** + * This is the timer interrupt service routine. + * + */ +void SysTick_Handler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial GD32 board. + */ +void rt_hw_board_init() +{ + /* NVIC Configuration */ +#define NVIC_VTOR_MASK 0x3FFFFF80 +#ifdef VECT_TAB_RAM + /* Set the Vector Table base location at 0x10000000 */ + SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); +#else /* VECT_TAB_FLASH */ + /* Set the Vector Table base location at 0x08000000 */ + SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); +#endif + + SystemClock_Config(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif + +#ifdef BSP_USING_SDRAM + rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); +#else + rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); +#endif +} + +/*@}*/ diff --git a/bsp/gd32/gd32450z-eval/board/board.h b/bsp/gd32/gd32450z-eval/board/board.h new file mode 100644 index 0000000000..59e00a88ca --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/board.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + */ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "gd32f4xx.h" +#include "drv_usart.h" +#include "drv_gpio.h" + +#include "gd32f4xx_exti.h" + +#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ +#define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */ + +// Internal SRAM memory size[Kbytes] <8-256> +// Default: 256 +#ifdef __ICCARM__ +// Use *.icf ram symbal, to avoid hardcode. +extern char __ICFEDIT_region_RAM_end__; +#define GD32_SRAM_END &__ICFEDIT_region_RAM_end__ +#else +#define GD32_SRAM_SIZE 256 +#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) +#endif + +#ifdef __CC_ARM +extern int Image$$RW_IRAM1$$ZI$$Limit; +#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit) +#elif __ICCARM__ +#pragma section="HEAP" +#define HEAP_BEGIN (__segment_end("HEAP")) +#else +extern int __bss_end; +#define HEAP_BEGIN (&__bss_end) +#endif + +#define HEAP_END GD32_SRAM_END + +#endif + diff --git a/bsp/gd32/gd32450z-eval/board/gd32f4xx_libopt.h b/bsp/gd32/gd32450z-eval/board/gd32f4xx_libopt.h new file mode 100644 index 0000000000..d26e3d15ec --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/gd32f4xx_libopt.h @@ -0,0 +1,45 @@ +/*! + \file gd32f4xx_libopt.h + \brief library optional for gd32f4xx +*/ + +/* + Copyright (C) 2016 GigaDevice + + 2016-10-19, V1.0.0, firmware for GD32F4xx +*/ + +#ifndef GD32F4XX_LIBOPT_H +#define GD32F4XX_LIBOPT_H +#include "gd32f4xx_rcu.h" +#include "gd32f4xx_adc.h" +#include "gd32f4xx_can.h" +#include "gd32f4xx_crc.h" +#include "gd32f4xx_ctc.h" +#include "gd32f4xx_dac.h" +#include "gd32f4xx_dbg.h" +#include "gd32f4xx_dci.h" +#include "gd32f4xx_dma.h" +//#include "gd32f4xx_enet.h" +#include "gd32f4xx_exmc.h" +#include "gd32f4xx_exti.h" +#include "gd32f4xx_fmc.h" +#include "gd32f4xx_fwdgt.h" +#include "gd32f4xx_gpio.h" +#include "gd32f4xx_syscfg.h" +#include "gd32f4xx_i2c.h" +#include "gd32f4xx_ipa.h" +#include "gd32f4xx_iref.h" +#include "gd32f4xx_pmu.h" +#include "gd32f4xx_rcu.h" +#include "gd32f4xx_rtc.h" +#include "gd32f4xx_sdio.h" +#include "gd32f4xx_spi.h" +#include "gd32f4xx_timer.h" +#include "gd32f4xx_tli.h" +#include "gd32f4xx_trng.h" +#include "gd32f4xx_usart.h" +#include "gd32f4xx_wwdgt.h" +#include "gd32f4xx_misc.h" + +#endif /* GD32F4XX_LIBOPT_H */ diff --git a/bsp/gd32/gd32450z-eval/board/linker_scripts/link.icf b/bsp/gd32/gd32450z-eval/board/linker_scripts/link.icf new file mode 100644 index 0000000000..be287f2c06 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/linker_scripts/link.icf @@ -0,0 +1,40 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x082FFFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2003FFFF; +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x2000; +define symbol __ICFEDIT_size_heap__ = 0x2000; +/**** End of ICF editor section. ###ICF###*/ + +export symbol __ICFEDIT_region_RAM_end__; + +define symbol __region_RAM1_start__ = 0x10000000; +define symbol __region_RAM1_end__ = 0x1000FFFF; + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM1_region = mem:[from __region_RAM1_start__ to __region_RAM1_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +keep { section FSymTab }; +keep { section VSymTab }; +keep { section .rti_fn* }; +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; +place in RAM1_region { section .sram }; \ No newline at end of file diff --git a/bsp/gd32/gd32450z-eval/board/linker_scripts/link.ld b/bsp/gd32/gd32450z-eval/board/linker_scripts/link.ld new file mode 100644 index 0000000000..f39b59d02d --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/linker_scripts/link.ld @@ -0,0 +1,142 @@ +/* + * linker script for GD32F4xx with GNU ld + * bernard.xiong 2009-10-14 + */ + +/* Program Entry, set to mark it as "used" and avoid gc */ +MEMORY +{ + CODE (rx) : ORIGIN = 0x08000000, LENGTH = 3072k /* 3072KB flash */ + DATA (rw) : ORIGIN = 0x20000000, LENGTH = 256k /* 256KB sram */ +} +ENTRY(Reset_Handler) +_system_stack_size = 0x200; + +SECTIONS +{ + .text : + { + . = ALIGN(4); + _stext = .; + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } > CODE = 0 + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + + /* This is used by the startup in order to initialize the .data secion */ + _sidata = .; + } > CODE + __exidx_end = .; + + /* .data section which is used for initialized data */ + + .data : AT (_sidata) + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _sdata = . ; + + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .data secion */ + _edata = . ; + } >DATA + + .stack : + { + . = . + _system_stack_size; + . = ALIGN(4); + _estack = .; + } >DATA + + __bss_start = .; + .bss : + { + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; + + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4); + /* This is used by the startup in order to initialize the .bss secion */ + _ebss = . ; + + *(.bss.init) + } > DATA + __bss_end = .; + + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/gd32/gd32450z-eval/board/linker_scripts/link.sct b/bsp/gd32/gd32450z-eval/board/linker_scripts/link.sct new file mode 100644 index 0000000000..fd32503883 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/board/linker_scripts/link.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** Scatter-Loading Description File generated by uVision *** +; ************************************************************* + +LR_IROM1 0x08000000 0x00300000 { ; load region size_region + ER_IROM1 0x08000000 0x00300000 { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + RW_IRAM1 0x20000000 0x00040000 { ; RW data + .ANY (+RW +ZI) + } +} + diff --git a/bsp/gd32/gd32450z-eval/project.uvoptx b/bsp/gd32/gd32450z-eval/project.uvoptx new file mode 100644 index 0000000000..8117421f4d --- /dev/null +++ b/bsp/gd32/gd32450z-eval/project.uvoptx @@ -0,0 +1,778 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + CMSIS_AGDI + -X"CMSIS-DAP" -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM) + + + 0 + JL2CM3 + -U59401765 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + Applications + 0 + 0 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + applications\main.c + main.c + 0 + 0 + + + + + CPU + 0 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\backtrace.c + backtrace.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\div0.c + div0.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\common\showmem.c + showmem.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + cpuport.c + 0 + 0 + + + 2 + 6 + 2 + 0 + 0 + 0 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + context_rvds.S + 0 + 0 + + + + + DeviceDrivers + 0 + 0 + 0 + 0 + + 3 + 7 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\serial\serial.c + serial.c + 0 + 0 + + + 3 + 9 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\waitqueue.c + waitqueue.c + 0 + 0 + + + 3 + 10 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\workqueue.c + workqueue.c + 0 + 0 + + + 3 + 11 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringbuffer.c + ringbuffer.c + 0 + 0 + + + 3 + 12 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\completion.c + completion.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\pipe.c + pipe.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\ringblk_buf.c + ringblk_buf.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ..\..\..\components\drivers\src\dataqueue.c + dataqueue.c + 0 + 0 + + + + + Drivers + 0 + 0 + 0 + 0 + + 4 + 16 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 17 + 1 + 0 + 0 + 0 + ..\libraries\gd32_drivers\drv_usart.c + drv_usart.c + 0 + 0 + + + + + Finsh + 0 + 0 + 0 + 0 + + 5 + 18 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\shell.c + shell.c + 0 + 0 + + + 5 + 19 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\msh.c + msh.c + 0 + 0 + + + 5 + 20 + 1 + 0 + 0 + 0 + ..\..\..\components\finsh\cmd.c + cmd.c + 0 + 0 + + + + + gd32_drivers + 0 + 0 + 0 + 0 + + 6 + 21 + 2 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + startup_gd32f4xx.s + 0 + 0 + + + 6 + 22 + 1 + 0 + 0 + 0 + board\board.c + board.c + 0 + 0 + + + + + Kernel + 0 + 0 + 0 + 0 + + 7 + 23 + 1 + 0 + 0 + 0 + ..\..\..\src\thread.c + thread.c + 0 + 0 + + + 7 + 24 + 1 + 0 + 0 + 0 + ..\..\..\src\irq.c + irq.c + 0 + 0 + + + 7 + 25 + 1 + 0 + 0 + 0 + ..\..\..\src\timer.c + timer.c + 0 + 0 + + + 7 + 26 + 1 + 0 + 0 + 0 + ..\..\..\src\components.c + components.c + 0 + 0 + + + 7 + 27 + 1 + 0 + 0 + 0 + ..\..\..\src\mem.c + mem.c + 0 + 0 + + + 7 + 28 + 1 + 0 + 0 + 0 + ..\..\..\src\object.c + object.c + 0 + 0 + + + 7 + 29 + 1 + 0 + 0 + 0 + ..\..\..\src\mempool.c + mempool.c + 0 + 0 + + + 7 + 30 + 1 + 0 + 0 + 0 + ..\..\..\src\kservice.c + kservice.c + 0 + 0 + + + 7 + 31 + 1 + 0 + 0 + 0 + ..\..\..\src\idle.c + idle.c + 0 + 0 + + + 7 + 32 + 1 + 0 + 0 + 0 + ..\..\..\src\device.c + device.c + 0 + 0 + + + 7 + 33 + 1 + 0 + 0 + 0 + ..\..\..\src\scheduler.c + scheduler.c + 0 + 0 + + + 7 + 34 + 1 + 0 + 0 + 0 + ..\..\..\src\clock.c + clock.c + 0 + 0 + + + 7 + 35 + 1 + 0 + 0 + 0 + ..\..\..\src\ipc.c + ipc.c + 0 + 0 + + + + + libc + 0 + 0 + 0 + 0 + + 8 + 36 + 1 + 0 + 0 + 0 + ..\..\..\components\libc\compilers\common\time.c + time.c + 0 + 0 + + + + + Libraries + 0 + 0 + 0 + 0 + + 9 + 37 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + gd32f4xx_syscfg.c + 0 + 0 + + + 9 + 38 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + gd32f4xx_exti.c + 0 + 0 + + + 9 + 39 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + gd32f4xx_gpio.c + 0 + 0 + + + 9 + 40 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + gd32f4xx_rcu.c + 0 + 0 + + + 9 + 41 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + gd32f4xx_misc.c + 0 + 0 + + + 9 + 42 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + gd32f4xx_usart.c + 0 + 0 + + + 9 + 43 + 1 + 0 + 0 + 0 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + system_gd32f4xx.c + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32450z-eval/project.uvproj b/bsp/gd32/gd32450z-eval/project.uvproj new file mode 100644 index 0000000000..96217840c7 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/project.uvproj @@ -0,0 +1,747 @@ + + + 1.1 +
### uVision Project, (C) Keil Software
+ + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F450ZK + GigaDevice + IRAM(0x20000000-0x20030000) IROM(0x08000000-0x08300000) CLOCK(20000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F4xx\startup_gd32f4xx.s" ("GD32F4xx Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000) + 0 + gd32f4xx0.h + + + + + + + + + + SFD\GD\GD32F4xx\GD32F4xx.SFR + 0 + 0 + + + + GD\GD32F4xx\ + GD\GD32F4xx\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F450, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\gd32_drivers;..\..\..\components\finsh;board;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_Firmware_Library\CMSIS;..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + + + Drivers + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + gd32_drivers + + + startup_gd32f4xx.s + 2 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + + + + + board.c + 1 + board\board.c + + + + + Kernel + + + object.c + 1 + ..\..\..\src\object.c + + + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + device.c + 1 + ..\..\..\src\device.c + + + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + + + clock.c + 1 + ..\..\..\src\clock.c + + + + + irq.c + 1 + ..\..\..\src\irq.c + + + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + + + thread.c + 1 + ..\..\..\src\thread.c + + + + + idle.c + 1 + ..\..\..\src\idle.c + + + + + timer.c + 1 + ..\..\..\src\timer.c + + + + + mem.c + 1 + ..\..\..\src\mem.c + + + + + components.c + 1 + ..\..\..\src\components.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f4xx_syscfg.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + + + + + gd32f4xx_exti.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + + + + + gd32f4xx_gpio.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + + + + + gd32f4xx_rcu.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + + + + + gd32f4xx_misc.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + + + + + gd32f4xx_usart.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + + + + + system_gd32f4xx.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + + + + + + +
diff --git a/bsp/gd32/gd32450z-eval/project.uvprojx b/bsp/gd32/gd32450z-eval/project.uvprojx new file mode 100644 index 0000000000..da7049b867 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/project.uvprojx @@ -0,0 +1,677 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F450ZK + GigaDevice + GigaDevice.GD32F4xx_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x040000) IROM(0x08000000,0x0300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(20000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM)) + 0 + $$Device:GD32F450ZK$Device\Include\gd32f4xx.h + + + + + + + + + + $$Device:GD32F450ZK$SVD\GD32F4xx.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x40000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + GD32F450, USE_STDPERIPH_DRIVER, __RTTHREAD__, __CLK_TCK=RT_TICK_PER_SECOND + + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\gd32_drivers;..\..\..\components\finsh;board;.;..\..\..\include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Include;..\libraries\GD32F4xx_Firmware_Library\CMSIS;..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Include;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\examples\utest\testcases\kernel + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + Applications + + + main.c + 1 + applications\main.c + + + + + CPU + + + backtrace.c + 1 + ..\..\..\libcpu\arm\common\backtrace.c + + + div0.c + 1 + ..\..\..\libcpu\arm\common\div0.c + + + showmem.c + 1 + ..\..\..\libcpu\arm\common\showmem.c + + + cpuport.c + 1 + ..\..\..\libcpu\arm\cortex-m4\cpuport.c + + + context_rvds.S + 2 + ..\..\..\libcpu\arm\cortex-m4\context_rvds.S + + + + + DeviceDrivers + + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + + + serial.c + 1 + ..\..\..\components\drivers\serial\serial.c + + + waitqueue.c + 1 + ..\..\..\components\drivers\src\waitqueue.c + + + workqueue.c + 1 + ..\..\..\components\drivers\src\workqueue.c + + + ringbuffer.c + 1 + ..\..\..\components\drivers\src\ringbuffer.c + + + completion.c + 1 + ..\..\..\components\drivers\src\completion.c + + + pipe.c + 1 + ..\..\..\components\drivers\src\pipe.c + + + ringblk_buf.c + 1 + ..\..\..\components\drivers\src\ringblk_buf.c + + + dataqueue.c + 1 + ..\..\..\components\drivers\src\dataqueue.c + + + + + Drivers + + + drv_gpio.c + 1 + ..\libraries\gd32_drivers\drv_gpio.c + + + drv_usart.c + 1 + ..\libraries\gd32_drivers\drv_usart.c + + + + + Finsh + + + shell.c + 1 + ..\..\..\components\finsh\shell.c + + + msh.c + 1 + ..\..\..\components\finsh\msh.c + + + cmd.c + 1 + ..\..\..\components\finsh\cmd.c + + + + + gd32_drivers + + + startup_gd32f4xx.s + 2 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + + + board.c + 1 + board\board.c + + + + + Kernel + + + thread.c + 1 + ..\..\..\src\thread.c + + + irq.c + 1 + ..\..\..\src\irq.c + + + timer.c + 1 + ..\..\..\src\timer.c + + + components.c + 1 + ..\..\..\src\components.c + + + mem.c + 1 + ..\..\..\src\mem.c + + + object.c + 1 + ..\..\..\src\object.c + + + mempool.c + 1 + ..\..\..\src\mempool.c + + + kservice.c + 1 + ..\..\..\src\kservice.c + + + idle.c + 1 + ..\..\..\src\idle.c + + + device.c + 1 + ..\..\..\src\device.c + + + scheduler.c + 1 + ..\..\..\src\scheduler.c + + + clock.c + 1 + ..\..\..\src\clock.c + + + ipc.c + 1 + ..\..\..\src\ipc.c + + + + + libc + + + time.c + 1 + ..\..\..\components\libc\compilers\common\time.c + + + + + Libraries + + + gd32f4xx_syscfg.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + + + gd32f4xx_exti.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + + + gd32f4xx_gpio.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + + + gd32f4xx_rcu.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + + + gd32f4xx_misc.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + + + gd32f4xx_usart.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + + + system_gd32f4xx.c + 1 + ..\libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
diff --git a/bsp/gd32/gd32450z-eval/rtconfig.h b/bsp/gd32/gd32450z-eval/rtconfig.h new file mode 100644 index 0000000000..0fbd373786 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/rtconfig.h @@ -0,0 +1,200 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +#define RT_ALIGN_SIZE 4 +#define RT_THREAD_PRIORITY_32 +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + +#define RT_DEBUG +#define RT_DEBUG_COLOR + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_SMALL_MEM +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40004 + +/* RT-Thread Components */ + +#define RT_USING_COMPONENTS_INIT +#define RT_USING_USER_MAIN +#define RT_MAIN_THREAD_STACK_SIZE 2048 +#define RT_MAIN_THREAD_PRIORITY 10 + +/* C++ features */ + + +/* Command shell */ + +#define RT_USING_FINSH +#define RT_USING_MSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 + +/* Device virtual file system */ + + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 +#define RT_USING_SERIAL +#define RT_USING_SERIAL_V1 +#define RT_SERIAL_USING_DMA +#define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN + +/* Using USB */ + + +/* POSIX layer and C standard library */ + +#define RT_LIBC_USING_TIME +#define RT_LIBC_DEFAULT_TIMEZONE 8 + +/* Network */ + +/* Socket abstraction layer */ + + +/* Network interface device */ + + +/* light weight TCP/IP stack */ + + +/* AT commands */ + + +/* VBUS(Virtual Software BUS) */ + + +/* Utilities */ + + +/* RT-Thread Utestcases */ + + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + + +/* Wi-Fi */ + +/* Marvell WiFi */ + + +/* Wiced WiFi */ + + +/* IoT Cloud */ + + +/* security packages */ + + +/* language packages */ + + +/* multimedia packages */ + +/* LVGL: powerful and easy-to-use embedded GUI library */ + + +/* u8g2: a monochrome graphic library */ + + +/* PainterEngine: A cross-platform graphics application framework written in C language */ + + +/* tools packages */ + + +/* system packages */ + +/* enhanced kernel services */ + + +/* acceleration: Assembly language or algorithmic acceleration packages */ + + +/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ + + +/* Micrium: Micrium software products porting for RT-Thread */ + + +/* peripheral libraries and drivers */ + + +/* AI packages */ + + +/* miscellaneous packages */ + +/* samples: kernel and components samples */ + + +/* entertainment: terminal games and other interesting software packages */ + + +/* Hardware Drivers Config */ + +#define SOC_SERIES_GD32F4xx +#define SOC_GD32450Z + +/* Onboard Peripheral Drivers */ + +/* On-chip Peripheral Drivers */ + +#define BSP_USING_GPIO +#define BSP_USING_UART +#define BSP_USING_UART1 + +/* Board extended module Drivers */ + + +#endif diff --git a/bsp/gd32/gd32450z-eval/rtconfig.py b/bsp/gd32/gd32450z-eval/rtconfig.py new file mode 100644 index 0000000000..c0c0b203cf --- /dev/null +++ b/bsp/gd32/gd32450z-eval/rtconfig.py @@ -0,0 +1,150 @@ +import os + +# toolchains options +ARCH='arm' +CPU='cortex-m4' +CROSS_TOOL='keil' + +# bsp lib config +BSP_LIBRARY_TYPE = None + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') + +# cross_tool provides the cross compiler +# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR +if CROSS_TOOL == 'gcc': + PLATFORM = 'gcc' + EXEC_PATH = r'C:\Users\XXYYZZ' +elif CROSS_TOOL == 'keil': + PLATFORM = 'armcc' + EXEC_PATH = r'C:/Keil_v5' +elif CROSS_TOOL == 'iar': + PLATFORM = 'iar' + EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + PREFIX = 'arm-none-eabi-' + CC = PREFIX + 'gcc' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + CXX = PREFIX + 'g++' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -DGD32F450' + CFLAGS = DEVICE + ' -Dgcc' + AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' + LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T board/linker_scripts/link.ld' + + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2 -g' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + + POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' + +elif PLATFORM == 'armcc': + # toolchains + CC = 'armcc' + CXX = 'armcc' + AS = 'armasm' + AR = 'armar' + LINK = 'armlink' + TARGET_EXT = 'axf' + + DEVICE = ' --cpu Cortex-M4.fp ' + CFLAGS = '-c ' + DEVICE + ' --apcs=interwork --c99' + AFLAGS = DEVICE + ' --apcs=interwork ' + LFLAGS = DEVICE + ' --scatter "board\linker_scripts\link.sct" --info sizes --info totals --info unused --info veneers --list rtthread.map --strict' + CFLAGS += ' -I' + EXEC_PATH + '/ARM/ARMCC/include' + LFLAGS += ' --libpath=' + EXEC_PATH + '/ARM/ARMCC/lib' + + CFLAGS += ' -D__MICROLIB ' + AFLAGS += ' --pd "__MICROLIB SETA 1" ' + LFLAGS += ' --library_type=microlib ' + EXEC_PATH += '/ARM/ARMCC/bin/' + + if BUILD == 'debug': + CFLAGS += ' -g -O0' + AFLAGS += ' -g' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + CFLAGS += ' -std=c99' + + POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' + +elif PLATFORM == 'iar': + # toolchains + CC = 'iccarm' + CXX = 'iccarm' + AS = 'iasmarm' + AR = 'iarchive' + LINK = 'ilinkarm' + TARGET_EXT = 'out' + + DEVICE = '-Dewarm' + + CFLAGS = DEVICE + CFLAGS += ' --diag_suppress Pa050' + CFLAGS += ' --no_cse' + CFLAGS += ' --no_unroll' + CFLAGS += ' --no_inline' + CFLAGS += ' --no_code_motion' + CFLAGS += ' --no_tbaa' + CFLAGS += ' --no_clustering' + CFLAGS += ' --no_scheduling' + CFLAGS += ' --endian=little' + CFLAGS += ' --cpu=Cortex-M4' + CFLAGS += ' -e' + CFLAGS += ' --fpu=VFPv4_sp' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --silent' + + AFLAGS = DEVICE + AFLAGS += ' -s+' + AFLAGS += ' -w+' + AFLAGS += ' -r' + AFLAGS += ' --cpu Cortex-M4' + AFLAGS += ' --fpu VFPv4_sp' + AFLAGS += ' -S' + + if BUILD == 'debug': + CFLAGS += ' --debug' + CFLAGS += ' -On' + else: + CFLAGS += ' -Oh' + + LFLAGS = ' --config "board/linker_scripts/link.icf"' + LFLAGS += ' --entry __iar_program_start' + + CXXFLAGS = CFLAGS + + EXEC_PATH = EXEC_PATH + '/arm/bin/' + POST_ACTION = 'ielftool --bin $TARGET rtthread.bin' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/gd32/gd32450z-eval/template.uvoptx b/bsp/gd32/gd32450z-eval/template.uvoptx new file mode 100644 index 0000000000..3947c5e208 --- /dev/null +++ b/bsp/gd32/gd32450z-eval/template.uvoptx @@ -0,0 +1,190 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + 0 + + + + 0 + 0 + + + + rt-thread + 0x4 + ARM-ADS + + 12000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\build\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + 0 + CMSIS_AGDI + -X"CMSIS-DAP" -O206 -S0 -C0 -P00000000 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO65554 -TC10000000 -TT10000000 -TP20 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM) + + + 0 + JL2CM3 + -U59401765 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO15 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB.FLM -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM)) + + + + + 0 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/bsp/gd32/gd32450z-eval/template.uvproj b/bsp/gd32/gd32450z-eval/template.uvproj new file mode 100644 index 0000000000..a23ad93c9a --- /dev/null +++ b/bsp/gd32/gd32450z-eval/template.uvproj @@ -0,0 +1,628 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F450ZK + GigaDevice + IRAM(0x20000000-0x20030000) IROM(0x08000000-0x08300000) CLOCK(20000000) CPUTYPE("Cortex-M4") FPU2 + + "Startup\GD\GD32F4xx\startup_gd32f4xx.s" ("GD32F4xx Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000) + 0 + gd32f4xx0.h + + + + + + + + + + SFD\GD\GD32F4xx\GD32F4xx.SFR + 0 + 0 + + + + GD\GD32F4xx\ + GD\GD32F4xx\ + + 0 + 0 + 0 + 0 + 1 + + .\output\ + rtthread + 1 + 0 + 1 + 1 + 1 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP + DCM.DLL + -pCM3 + SARMCM3.DLL + + TCM.DLL + -pCM3 + + + + 1 + 0 + 0 + 0 + 16 + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\CMSIS_AGDI.dll + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Include;..\..\..\Library\Firmware\CMSIS\GD\GD32F4xx\Include;..\..\..\Library\Utilities;..\ + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + + + + + + + + + + + + Application + + + main.c + 1 + ..\main.c + + + gd32f4xx_it.c + 1 + ..\gd32f4xx_it.c + + + + + CMSIS + + + system_gd32f4xx.c + 1 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + + + + + GD32F4xx_Peripherals + + + gd32f4xx_adc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_adc.c + + + gd32f4xx_can.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_can.c + + + gd32f4xx_crc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_crc.c + + + gd32f4xx_ctc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_ctc.c + + + gd32f4xx_dac.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_dac.c + + + gd32f4xx_dbg.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_dbg.c + + + gd32f4xx_dci.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_dci.c + + + gd32f4xx_dma.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_dma.c + + + gd32f4xx_enet.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_enet.c + + + gd32f4xx_exmc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_exmc.c + + + gd32f4xx_exti.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + + + gd32f4xx_fmc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_fmc.c + + + gd32f4xx_fwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_fwdgt.c + + + gd32f4xx_gpio.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + + + gd32f4xx_i2c.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c + + + gd32f4xx_ipa.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_ipa.c + + + gd32f4xx_iref.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_iref.c + + + gd32f4xx_misc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_misc.c + + + gd32f4xx_pmu.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_pmu.c + + + gd32f4xx_rcu.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + + + gd32f4xx_rtc.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_rtc.c + + + gd32f4xx_sdio.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_sdio.c + + + gd32f4xx_spi.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_spi.c + + + gd32f4xx_syscfg.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + + + gd32f4xx_timer.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_timer.c + + + gd32f4xx_tli.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_tli.c + + + gd32f4xx_trng.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_trng.c + + + gd32f4xx_usart.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c + + + gd32f4xx_wwdgt.c + 1 + ..\..\..\Library\Firmware\GD32F4xx_standard_peripheral\Source\gd32f4xx_wwdgt.c + + + + + GD32F4xx_EVAL + + + gd32f450z_eval.c + 1 + ..\..\..\Library\Utilities\gd32f450z_eval.c + + + + + Startup + + + startup_gd32f4xx.s + 2 + ..\..\..\Library\Firmware\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s + + + + + Doc + + + readme.txt + 5 + ..\readme.txt + + + + + + + +
diff --git a/bsp/gd32/gd32450z-eval/template.uvprojx b/bsp/gd32/gd32450z-eval/template.uvprojx new file mode 100644 index 0000000000..5653f2da1d --- /dev/null +++ b/bsp/gd32/gd32450z-eval/template.uvprojx @@ -0,0 +1,417 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + rt-thread + 0x4 + ARM-ADS + 0 + + + GD32F450ZK + GigaDevice + GigaDevice.GD32F4xx_DFP.2.1.0 + http://gd32mcu.com/data/documents/pack/ + IRAM(0x20000000,0x040000) IROM(0x08000000,0x0300000) CPUTYPE("Cortex-M4") FPU2 CLOCK(20000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F4xx_3MB -FS08000000 -FL0300000 -FP0($$Device:GD32F450ZK$Flash\GD32F4xx_3MB.FLM)) + 0 + $$Device:GD32F450ZK$Device\Include\gd32f4xx.h + + + + + + + + + + $$Device:GD32F450ZK$SVD\GD32F4xx.svd + 0 + 0 + + + + + + + 0 + 0 + 0 + 0 + 1 + + .\build\ + rtthread + 1 + 0 + 0 + 1 + 0 + .\build\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 0 + fromelf --bin !L --output rtthread.bin + + 0 + 0 + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 1 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 8 + 0 + 0 + 0 + 0 + 3 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x40000 + + + 1 + 0x8000000 + 0x300000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x300000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x30000 + + + 0 + 0x10000000 + 0x10000 + + + + + + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + + + + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + 0x08000000 + 0x20000000 + + .\gd32_rom.ld + + + + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + <Project Info> + + + + + + 0 + 1 + + + + +
From 446bde64c8af06abb2fdb53f21780000754673ad Mon Sep 17 00:00:00 2001 From: Wayne Date: Sun, 16 Jan 2022 18:43:27 +0800 Subject: [PATCH 17/65] [Nuvoton] Update drivers (#5501) * Update drivers. 1. Improve LVGL avg FPS. 2. Sync configuration to 4.1.0. * [Nuvoton] Update drivers. 1. Fix open-control order issue in CAN driver. 2. [N9H30] Improve N9H30 I2C busy-wait implementation. 3. [N9H30] Support 1024x600x32b LCD panel. 4. Move nu_packages menu into sub-menu of board. * Update menu-option. 1. Set BOARD_USING_LCM is on by default. 2. Fix default value setting in choice-option. * Fix control function in I2C driver. * Add sdk_dist.py and ADC touching calibration function. Co-authored-by: Wayne Lin --- bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c | 2 +- .../libraries/m2354/rtt_port/drv_can.c | 435 ++-- .../libraries/m2354/rtt_port/drv_i2c.c | 2 +- .../Device/Nuvoton/M480/Include/can_reg.h | 8 +- bsp/nuvoton/libraries/m480/rtt_port/drv_can.c | 451 ++-- bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c | 2 +- .../libraries/n9h30/Driver/Include/nu_can.h | 4 +- .../libraries/n9h30/Driver/Include/nu_lcd.h | 16 +- .../libraries/n9h30/Driver/Include/nu_uart.h | 4 + .../libraries/n9h30/Driver/Source/nu_lcd.c | 75 +- bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig | 7 + .../libraries/n9h30/rtt_port/drv_adc.c | 253 ++- .../libraries/n9h30/rtt_port/drv_adc.h | 32 +- .../libraries/n9h30/rtt_port/drv_adc_touch.c | 537 ++++- .../libraries/n9h30/rtt_port/drv_can.c | 375 ++-- .../libraries/n9h30/rtt_port/drv_i2c.c | 108 +- .../libraries/n9h30/rtt_port/drv_vpost.c | 20 + .../nu_packages/ILI9341/lcd_ili9341.c | 3 +- bsp/nuvoton/libraries/nu_packages/Kconfig | 18 +- .../libraries/nuc980/Driver/Include/nu_adc.h | 119 +- .../libraries/nuc980/Driver/Include/nu_can.h | 4 +- .../libraries/nuc980/Driver/Include/nuc980.h | 49 +- .../libraries/nuc980/Driver/Source/nu_emac.c | 4 +- bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig | 7 + .../libraries/nuc980/rtt_port/drv_adc.c | 483 +++- .../libraries/nuc980/rtt_port/drv_adc.h | 84 + .../libraries/nuc980/rtt_port/drv_adc_touch.c | 681 ++++++ .../libraries/nuc980/rtt_port/drv_can.c | 375 ++-- .../libraries/nuc980/rtt_port/drv_emac.c | 2 +- .../libraries/nuc980/rtt_port/drv_i2c.c | 2 +- bsp/nuvoton/nk-980iot/.config | 59 +- bsp/nuvoton/nk-980iot/Kconfig | 6 - bsp/nuvoton/nk-980iot/board/Kconfig | 2 + bsp/nuvoton/nk-980iot/board/nu_pin_init.c | 2 + bsp/nuvoton/nk-980iot/project.uvproj | 1877 ---------------- bsp/nuvoton/nk-980iot/project.uvprojx | 1869 ---------------- bsp/nuvoton/nk-980iot/rtconfig.h | 459 ---- bsp/nuvoton/nk-980iot/rtconfig.py | 8 +- bsp/nuvoton/nk-980iot/spinor.config | 407 +++- bsp/nuvoton/nk-n9h30/.config | 37 +- bsp/nuvoton/nk-n9h30/Kconfig | 6 - .../nk-n9h30/applications/lvgl/lv_port_disp.c | 61 +- bsp/nuvoton/nk-n9h30/board/Kconfig | 60 +- bsp/nuvoton/nk-n9h30/board/board_dev.c | 62 +- bsp/nuvoton/nk-n9h30/project.uvproj | 1791 --------------- bsp/nuvoton/nk-n9h30/project.uvprojx | 1783 --------------- bsp/nuvoton/nk-n9h30/rtconfig.h | 422 ---- bsp/nuvoton/nk-n9h30/rtconfig.py | 8 +- bsp/nuvoton/nk-rtu980/.config | 2 + bsp/nuvoton/nk-rtu980/Kconfig | 6 - bsp/nuvoton/nk-rtu980/board/Kconfig | 1 + bsp/nuvoton/nk-rtu980/project.uvproj | 1774 --------------- bsp/nuvoton/nk-rtu980/project.uvprojx | 1766 --------------- bsp/nuvoton/nk-rtu980/rtconfig.h | 431 ---- bsp/nuvoton/nk-rtu980/rtconfig.py | 8 +- bsp/nuvoton/numaker-iot-m487/.config | 2 + bsp/nuvoton/numaker-iot-m487/Kconfig | 6 - bsp/nuvoton/numaker-iot-m487/board/Kconfig | 1 + bsp/nuvoton/numaker-iot-m487/project.uvproj | 1814 --------------- bsp/nuvoton/numaker-iot-m487/project.uvprojx | 1809 --------------- bsp/nuvoton/numaker-iot-m487/rtconfig.h | 400 ---- bsp/nuvoton/numaker-iot-m487/rtconfig.py | 8 + bsp/nuvoton/numaker-m032ki/.config | 2 + bsp/nuvoton/numaker-m032ki/Kconfig | 6 - bsp/nuvoton/numaker-m032ki/board/Kconfig | 1 + bsp/nuvoton/numaker-m032ki/project.uvprojx | 1228 ---------- bsp/nuvoton/numaker-m032ki/rtconfig.h | 286 --- bsp/nuvoton/numaker-m032ki/rtconfig.py | 8 + bsp/nuvoton/numaker-m2354/.config | 42 +- bsp/nuvoton/numaker-m2354/Kconfig | 8 +- bsp/nuvoton/numaker-m2354/board/Kconfig | 2 + bsp/nuvoton/numaker-m2354/project.uvprojx | 1768 --------------- bsp/nuvoton/numaker-m2354/rtconfig.h | 383 ---- bsp/nuvoton/numaker-m2354/rtconfig.py | 8 + bsp/nuvoton/numaker-pfm-m487/.config | 42 +- bsp/nuvoton/numaker-pfm-m487/Kconfig | 6 - bsp/nuvoton/numaker-pfm-m487/board/Kconfig | 2 + bsp/nuvoton/numaker-pfm-m487/project.uvproj | 1966 ----------------- bsp/nuvoton/numaker-pfm-m487/project.uvprojx | 1961 ---------------- bsp/nuvoton/numaker-pfm-m487/rtconfig.h | 413 ---- bsp/nuvoton/numaker-pfm-m487/rtconfig.py | 8 + bsp/nuvoton/tools/sdk_dist.py | 39 + 82 files changed, 3740 insertions(+), 25548 deletions(-) create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h create mode 100644 bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c delete mode 100644 bsp/nuvoton/nk-980iot/project.uvproj delete mode 100644 bsp/nuvoton/nk-980iot/project.uvprojx delete mode 100644 bsp/nuvoton/nk-980iot/rtconfig.h delete mode 100644 bsp/nuvoton/nk-n9h30/project.uvproj delete mode 100644 bsp/nuvoton/nk-n9h30/project.uvprojx delete mode 100644 bsp/nuvoton/nk-n9h30/rtconfig.h delete mode 100644 bsp/nuvoton/nk-rtu980/project.uvproj delete mode 100644 bsp/nuvoton/nk-rtu980/project.uvprojx delete mode 100644 bsp/nuvoton/nk-rtu980/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-iot-m487/project.uvproj delete mode 100644 bsp/nuvoton/numaker-iot-m487/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-iot-m487/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-m032ki/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-m032ki/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-m2354/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-m2354/rtconfig.h delete mode 100644 bsp/nuvoton/numaker-pfm-m487/project.uvproj delete mode 100644 bsp/nuvoton/numaker-pfm-m487/project.uvprojx delete mode 100644 bsp/nuvoton/numaker-pfm-m487/rtconfig.h create mode 100644 bsp/nuvoton/tools/sdk_dist.py diff --git a/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c index e507ca6cbe..7487414dec 100644 --- a/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m031/rtt_port/drv_i2c.c @@ -90,7 +90,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c index 614705fcc5..511fb592a2 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_can.c @@ -7,6 +7,7 @@ * Change Logs: * Date Author Notes * 2020-6-22 ChingI First version +* 2022-1-8 Wayne Fix IE issue * ******************************************************************************/ @@ -42,7 +43,7 @@ enum #if defined(BSP_USING_CAN0) CAN0_IDX, #endif - CAN_CNT, + CAN_CNT }; /* Private Typedef --------------------------------------------------------------*/ @@ -50,9 +51,10 @@ struct nu_can { struct rt_can_device dev; char *name; - CAN_T *can_base; - uint32_t can_rst; - IRQn_Type can_irq_n; + CAN_T *base; + IRQn_Type irqn; + uint32_t rstidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -68,12 +70,11 @@ static struct nu_can nu_can_arr[] = #if defined(BSP_USING_CAN0) { .name = "can0", - .can_base = CAN0, - .can_rst = CAN0_RST, - .can_irq_n = CAN0_IRQn, + .base = CAN0, + .rstidx = CAN0_RST, + .irqn = CAN0_IRQn, }, #endif - {0} }; /* struct nu_can */ /* Public functions ------------------------------------------------------------*/ @@ -106,266 +107,271 @@ void CAN0_IRQHandler(void) /* Private Variables ------------------------------------------------------------*/ -static void nu_can_isr(nu_can_t can) +static void nu_can_isr(nu_can_t psNuCAN) { - uint32_t u32IIDRstatus; /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(can_base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ /**************************/ - if (can_base->STATUS & CAN_STATUS_TXOK_Msk) + if (base->STATUS & CAN_STATUS_TXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ + base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif - //rt_kprintf("[%s]TX OK INT\n", can->name) ; } - if (can_base->STATUS & CAN_STATUS_RXOK_Msk) + if (base->STATUS & CAN_STATUS_RXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ + base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif - //rt_kprintf("[%s]RX OK INT\n", can->name) ; } /**************************/ /* Error Status interrupt */ /**************************/ - if (can_base->STATUS & CAN_STATUS_EWARN_Msk) + if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("[%s]EWARN INT\n", can->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } - if (can_base->STATUS & CAN_STATUS_BOFF_Msk) + if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("[%s]BUSOFF INT\n", can->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - can_base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - can_base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (can_base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } + + if (base->STATUS & CAN_STATUS_LEC_Msk) + { + rt_kprintf("[%s] Last Error Code %03x\n", psNuCAN->name, base->STATUS & CAN_STATUS_LEC_Msk) ; + } + } #ifdef RT_CAN_USING_HDR /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } - CAN_CLR_INT_PENDING_BIT(can_base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ + CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + NVIC_EnableIRQ(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + NVIC_DisableIRQ(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { + nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); + CAN_T *base = psNuCAN->base; /* Reset this module */ - SYS_ResetModule(((nu_can_t)can)->can_rst); + SYS_ResetModule(psNuCAN->rstidx); - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(can_base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); - + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR - CAN_LeaveTestMode(can_base); + CAN_LeaveTestMode(base); #else - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk); #endif break; case RT_CAN_MODE_LISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); break; case RT_CAN_MODE_LOOPBACK: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); break; case RT_CAN_MODE_LOOPBACKANLISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); break; default: rt_kprintf("Unsupported Operating mode"); goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; exit_nu_can_configure: - CAN_Close(can_base); + CAN_Close(base); return -(RT_ERROR); } static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Status Change Interrupt */ - CAN_DisableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Error Interrupt */ - CAN_DisableInt(can_base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } } else - { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -375,20 +381,29 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) return nu_can_configure(can, &can->config); } break; + case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = can_base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(can_base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(can_base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; + default: return -(RT_EINVAL); @@ -400,61 +415,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; + + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(can_base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(can_base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -466,32 +511,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -506,13 +532,12 @@ static int rt_hw_can_init(void) for (i = (CAN_START + 1); i < CAN_CNT; i++) { - - nu_can_arr[i].dev.ops = &nu_can_ops; nu_can_arr[i].dev.config = nu_can_default_config; #ifdef RT_CAN_USING_HDR nu_can_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ; #endif + /* Register can device */ ret = rt_hw_can_register(&nu_can_arr[i].dev, nu_can_arr[i].name, &nu_can_ops, NULL); RT_ASSERT(ret == RT_EOK); } diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c index fbc38e6e2a..30bffc49bf 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_i2c.c @@ -99,7 +99,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h b/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h index 86340d99d8..b0152f8011 100644 --- a/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h +++ b/bsp/nuvoton/libraries/m480/Device/Nuvoton/M480/Include/can_reg.h @@ -10,7 +10,7 @@ #define __CAN_REG_H__ #if defined ( __CC_ARM ) -#pragma anon_unions + #pragma anon_unions #endif /** @@ -586,8 +586,8 @@ typedef struct #define CAN_BTIME_TSEG2_Pos (12) /*!< CAN_T::BTIME: TSeg2 Position */ #define CAN_BTIME_TSEG2_Msk (0x7ul << CAN_BTIME_TSEG2_Pos) /*!< CAN_T::BTIME: TSeg2 Mask */ -#define CAN_IIDR_IntId_Pos (0) /*!< CAN_T::IIDR: IntId Position */ -#define CAN_IIDR_IntId_Msk (0xfffful << CAN_IIDR_IntId_Pos) /*!< CAN_T::IIDR: IntId Mask */ +#define CAN_IIDR_INTID_Pos (0) /*!< CAN_T::IIDR: IntId Position */ +#define CAN_IIDR_INTID_Msk (0xfffful << CAN_IIDR_INTID_Pos) /*!< CAN_T::IIDR: IntId Mask */ #define CAN_TEST_BASIC_Pos (2) /*!< CAN_T::TEST: Basic Position */ #define CAN_TEST_BASIC_Msk (0x1ul << CAN_TEST_BASIC_Pos) /*!< CAN_T::TEST: Basic Mask */ @@ -753,7 +753,7 @@ typedef struct /**@}*/ /* end of REGISTER group */ #if defined ( __CC_ARM ) -#pragma no_anon_unions + #pragma no_anon_unions #endif #endif /* __CAN_REG_H__ */ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c index a667e34979..14926076c3 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_can.c @@ -1,12 +1,13 @@ /**************************************************************************//** * -* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes -* 2020-2-07 ChingI First version +* 2020-6-22 ChingI First version +* 2022-1-8 Wayne Fix IE issue * ******************************************************************************/ @@ -56,9 +57,10 @@ struct nu_can { struct rt_can_device dev; char *name; - CAN_T *can_base; - uint32_t can_rst; - IRQn_Type can_irq_n; + CAN_T *base; + IRQn_Type irqn; + uint32_t rstidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -74,29 +76,27 @@ static struct nu_can nu_can_arr[] = #if defined(BSP_USING_CAN0) { .name = "can0", - .can_base = CAN0, - .can_rst = CAN0_RST, - .can_irq_n = CAN0_IRQn, + .base = CAN0, + .rstidx = CAN0_RST, + .irqn = CAN0_IRQn, }, #endif #if defined(BSP_USING_CAN1) { .name = "can1", - .can_base = CAN1, - .can_rst = CAN1_RST, - .can_irq_n = CAN1_IRQn, + .base = CAN1, + .rstidx = CAN1_RST, + .irqn = CAN1_IRQn, }, #endif - #if defined(BSP_USING_CAN2) { .name = "can2", - .can_base = CAN2, - .can_rst = CAN2_RST, - .can_irq_n = CAN2_IRQn, + .base = CAN2, + .rstidx = CAN2_RST, + .irqn = CAN2_IRQn, }, #endif - {0} }; /* struct nu_can */ /* Public functions ------------------------------------------------------------*/ @@ -158,267 +158,271 @@ void CAN2_IRQHandler(void) /* Private Variables ------------------------------------------------------------*/ - -static void nu_can_isr(nu_can_t can) +static void nu_can_isr(nu_can_t psNuCAN) { - uint32_t u32IIDRstatus; /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(can_base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ /**************************/ - if (can_base->STATUS & CAN_STATUS_TXOK_Msk) + if (base->STATUS & CAN_STATUS_TXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ + base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif - //rt_kprintf("[%s]TX OK INT\n", can->name) ; } - if (can_base->STATUS & CAN_STATUS_RXOK_Msk) + if (base->STATUS & CAN_STATUS_RXOK_Msk) { - can_base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ + base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif - //rt_kprintf("[%s]RX OK INT\n", can->name) ; } /**************************/ /* Error Status interrupt */ /**************************/ - if (can_base->STATUS & CAN_STATUS_EWARN_Msk) + if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("[%s]EWARN INT\n", can->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } - if (can_base->STATUS & CAN_STATUS_BOFF_Msk) + if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("[%s]BUSOFF INT\n", can->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - can_base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - can_base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (can_base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } + + if (base->STATUS & CAN_STATUS_LEC_Msk) + { + rt_kprintf("[%s] Last Error Code %03x\n", psNuCAN->name, base->STATUS & CAN_STATUS_LEC_Msk) ; + } + } #ifdef RT_CAN_USING_HDR /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, RT_CAN_EVENT_TX_DONE); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", can->name, u32IIDRstatus); - rt_hw_can_isr(&can->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } - CAN_CLR_INT_PENDING_BIT(can_base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ + CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + NVIC_EnableIRQ(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + NVIC_DisableIRQ(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { + nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); + CAN_T *base = psNuCAN->base; /* Reset this module */ - SYS_ResetModule(((nu_can_t)can)->can_rst); + SYS_ResetModule(psNuCAN->rstidx); - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(can_base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); - + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR - CAN_LeaveTestMode(can_base); + CAN_LeaveTestMode(base); #else - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk); #endif break; case RT_CAN_MODE_LISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk); break; case RT_CAN_MODE_LOOPBACK: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_LBACK_Msk); break; case RT_CAN_MODE_LOOPBACKANLISEN: - CAN_EnterTestMode(can_base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); + CAN_EnterTestMode(base, CAN_TEST_BASIC_Msk | CAN_TEST_SILENT_Msk | CAN_TEST_LBACK_Msk); break; default: rt_kprintf("Unsupported Operating mode"); goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; exit_nu_can_configure: - CAN_Close(can_base); + CAN_Close(base); return -(RT_ERROR); } static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; - - RT_ASSERT(can_base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Status Change Interrupt */ - CAN_DisableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable NVIC interrupt. */ - NVIC_DisableIRQ(((nu_can_t)can)->can_irq_n); - /* Disable Error Interrupt */ - CAN_DisableInt(can_base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(can_base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - /* Enable NVIC interrupt. */ - NVIC_EnableIRQ(((nu_can_t)can)->can_irq_n); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } } else - { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(can_base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -428,20 +432,29 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) return nu_can_configure(can, &can->config); } break; + case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = can_base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(can_base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(can_base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; + default: return -(RT_EINVAL); @@ -453,61 +466,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; + + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(can_base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *can_base = ((nu_can_t)can)->can_base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(can_base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(can_base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -519,32 +562,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -559,13 +583,12 @@ static int rt_hw_can_init(void) for (i = (CAN_START + 1); i < CAN_CNT; i++) { - - nu_can_arr[i].dev.ops = &nu_can_ops; nu_can_arr[i].dev.config = nu_can_default_config; #ifdef RT_CAN_USING_HDR nu_can_arr[i].dev.config.maxhdr = RT_CANMSG_BOX_SZ; #endif + /* Register can device */ ret = rt_hw_can_register(&nu_can_arr[i].dev, nu_can_arr[i].name, &nu_can_ops, NULL); RT_ASSERT(ret == RT_EOK); } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c index d1f71407ac..b7082d1ae4 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_i2c.c @@ -99,7 +99,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h index b13064996d..8eb3a1463c 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_can.h @@ -151,8 +151,8 @@ typedef struct #define CAN_BTIME_TSEG2_Pos (12) /*!< CAN_T::BTIME: TSeg2 Position */ #define CAN_BTIME_TSEG2_Msk (0x7ul << CAN_BTIME_TSEG2_Pos) /*!< CAN_T::BTIME: TSeg2 Mask */ -#define CAN_IIDR_IntId_Pos (0) /*!< CAN_T::IIDR: IntId Position */ -#define CAN_IIDR_IntId_Msk (0xfffful << CAN_IIDR_IntId_Pos) /*!< CAN_T::IIDR: IntId Mask */ +#define CAN_IIDR_INTID_Pos (0) /*!< CAN_T::IIDR: IntId Position */ +#define CAN_IIDR_INTID_Msk (0xfffful << CAN_IIDR_INTID_Pos) /*!< CAN_T::IIDR: IntId Mask */ #define CAN_TEST_BASIC_Pos (2) /*!< CAN_T::TEST: Basic Position */ #define CAN_TEST_BASIC_Msk (0x1ul << CAN_TEST_BASIC_Pos) /*!< CAN_T::TEST: Basic Mask */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h index bf05c3f9a9..69b7c747a8 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h @@ -171,11 +171,17 @@ typedef struct uint32_t *pFrameBuffer; /*!< User input, The address of OSD source image */ } OSDFORMATEX; -#define DIS_PANEL_E50A2V1 0 -#define DIS_PANEL_ILI9341_MPU80 1 -#define DIS_LSA40AT9001 2 -#define DIS_PANEL_FW070TFT 3 -#define DIS_PANEL_FW043TFT 4 +enum DIS_PANEL +{ + DIS_PANEL_E50A2V1 = 0, + DIS_PANEL_ILI9341_MPU80, + DIS_LSA40AT9001, + DIS_PANEL_FW070TFT, + DIS_PANEL_FW043TFT, + DIS_PANEL_FW070TFT_WSVGA, + DIS_PANEL_CNT +}; + typedef struct { uint32_t u32DevWidth; /*!< Panel width */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h index 4f24a2d10d..898c181eb5 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_uart.h @@ -770,4 +770,8 @@ void UART_SetLineConfig(UART_T *uart, uint32_t u32baudrate, uint32_t u32data_wid /*@}*/ /* end of group N9H30_Device_Driver */ +#ifdef __cplusplus +} +#endif + #endif diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c index d71d110096..82887e427f 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c @@ -168,9 +168,82 @@ static VPOST_T DEF_FW043TFT = } }; +#define FW070TFT_WSVGA_WIDTH 1024 /*!< XRES */ +#define FW070TFT_WSVGA_HEIGHT 600 /*!< YRES */ +#define FW070TFT_WSVGA_MARGIN_LEFT 160 /*!< HBP (Horizontal Back Porch) */ +#define FW070TFT_WSVGA_MARGIN_RIGHT 160 /*!< HFP (Horizontal Front Porch) */ +#define FW070TFT_WSVGA_MARGIN_UPPER 12 /*!< VBP (Vertical Back Porch) */ +#define FW070TFT_WSVGA_MARGIN_LOWER 23 /*!< VFP (Vertical Front Porch) */ +#define FW070TFT_WSVGA_HSYNC_LEN 1 /*!< HPW (HSYNC plus width) */ +#define FW070TFT_WSVGA_VSYNC_LEN 1 /*!< VPW (VSYNC width) */ +static VPOST_T DEF_FW070TFT_WSVGA = +{ + FW070TFT_WSVGA_WIDTH, /*!< Panel width */ + FW070TFT_WSVGA_HEIGHT, /*!< Panel height */ + 0, /*!< MPU command line low indicator */ + 0, /*!< MPU command width */ + 0, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + 0, /*!< MPU mode */ + VPOSTB_COLORTYPE_16M, /*!< Display colors */ + VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */ + + .sCRTCSIZE = + { + /*!< Horizontal Total */ + .HTT = FW070TFT_WSVGA_MARGIN_LEFT + FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_RIGHT, + + /*!< Vertical Total */ + .VTT = FW070TFT_WSVGA_MARGIN_UPPER + FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_LOWER, + }, + .sCRTCDEND = + { + /*!< Horizontal Display Enable End */ + .HDEND = FW070TFT_WSVGA_WIDTH, + + /*!< Vertical Display Enable End */ + .VDEND = FW070TFT_WSVGA_HEIGHT, + }, + .sCRTCHR = + { + /*!< Internal Horizontal Retrace Start Timing */ + .HRS = FW070TFT_WSVGA_WIDTH + 1, + + /*!< Internal Horizontal Retrace End Low */ + .HRE = FW070TFT_WSVGA_WIDTH + 5, + }, + .sCRTCHSYNC = + { + /*!< Horizontal Sync Start Timing */ + .HSYNC_S = FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_LEFT, + + /*!< Horizontal Sync End Timing */ + .HSYNC_E = FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_LEFT + FW070TFT_WSVGA_HSYNC_LEN, + + /*!< Hsync Signal Adjustment For Multi-Cycles Per Pixel Mode Of Sync-Based Unipac-LCD */ + .HSYNC_SHIFT = 0, + }, + .sCRTCVR = + { + /*!< Vertical Internal Retrace Start Timing */ + .VRS = FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_UPPER, + + /*!< Vertical Internal Retrace End Low */ + .VRE = FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_UPPER + FW070TFT_WSVGA_VSYNC_LEN, + } +}; /* LCD build-in support list */ -static VPOST_T *DisplayDevList[5] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT, &DEF_FW043TFT}; +static VPOST_T *DisplayDevList[DIS_PANEL_CNT] = +{ + &DEF_E50A2V1, + &DEF_ILI9341_MPU80, + &DEF_LSA40AT9001, + &DEF_FW070TFT, + &DEF_FW043TFT, + &DEF_FW070TFT_WSVGA +}; + static VPOST_T curDisplayDev; static OSDFORMATEX curOSDDev = {0}; static LCDFORMATEX curVADev = {0}; diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig index f57b439f00..4d863f6126 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig @@ -475,6 +475,9 @@ config SOC_SERIES_N9H30 config LCM_USING_FW043TFT bool "LCM_FW043TFT(480x272-RGB888)" + config LCM_USING_FW070TFT_WSVGA + bool "LCM_USING_FW070TFT_WSVGA(1024x600-RGB888)" + endchoice config VPOST_USING_LCD_IDX @@ -483,6 +486,7 @@ config SOC_SERIES_N9H30 default 2 if LCM_USING_LSA40AT9001 default 3 if LCM_USING_FW070TFT default 4 if LCM_USING_FW043TFT + default 5 if LCM_USING_FW070TFT_WSVGA config BSP_LCD_BPP int @@ -490,6 +494,7 @@ config SOC_SERIES_N9H30 default 16 if LCM_USING_LSA40AT9001 default 32 if LCM_USING_FW070TFT default 32 if LCM_USING_FW043TFT + default 32 if LCM_USING_FW070TFT_WSVGA config BSP_LCD_WIDTH int @@ -497,6 +502,7 @@ config SOC_SERIES_N9H30 default 800 if LCM_USING_LSA40AT9001 default 800 if LCM_USING_FW070TFT default 480 if LCM_USING_FW043TFT + default 1024 if LCM_USING_FW070TFT_WSVGA config BSP_LCD_HEIGHT int @@ -504,6 +510,7 @@ config SOC_SERIES_N9H30 default 600 if LCM_USING_LSA40AT9001 default 480 if LCM_USING_FW070TFT default 272 if LCM_USING_FW043TFT + default 600 if LCM_USING_FW070TFT_WSVGA config BSP_USING_VPOST_OSD bool "Enable VPOST OSD layer" diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c index 5ce1c64276..d1dcba7d5b 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.c @@ -35,24 +35,27 @@ struct nu_adc uint32_t chn_mask; rt_sem_t m_psSem; +#if defined(BSP_USING_ADC_TOUCH) rt_touch_t psRtTouch; rt_timer_t psRtTouchMenuTimer; + rt_mq_t m_pmqTouchXYZ; +#endif nu_adc_cb m_isr[eAdc_ISR_CNT]; nu_adc_cb m_wkisr[eAdc_WKISR_CNT]; - - rt_mq_t m_pmqTouchXYZ; }; typedef struct nu_adc *nu_adc_t; +#if defined(BSP_USING_ADC_TOUCH) struct nu_adc_touch_data { - uint16_t u16X; - uint16_t u16Y; - uint16_t u16Z0; - uint16_t u16Z1; + uint32_t u32X; + uint32_t u32Y; + uint32_t u32Z0; + uint32_t u32Z1; }; typedef struct nu_adc_touch_data *nu_adc_touch_data_t; +#endif /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); @@ -134,6 +137,64 @@ static rt_err_t _nu_adc_init(rt_device_t dev) return RT_EOK; } +static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) +{ + nu_adc_t psNuAdc = (nu_adc_t)userData; + +#if defined(BSP_USING_ADC_TOUCH) + + static struct nu_adc_touch_data point; + static rt_bool_t bDrop = RT_FALSE; + static uint32_t u32LastZ0 = 0xffffu; + + if (psNuAdc->psRtTouch != RT_NULL) + { + uint32_t value; + + value = inpw(REG_ADC_XYDATA); + point.u32X = (value & 0x0ffful); + point.u32Y = ((value >> 16) & 0x0ffful); + + value = inpw(REG_ADC_ZDATA); + point.u32Z0 = (value & 0x0ffful); + point.u32Z1 = ((value >> 16) & 0x0ffful); + + /* Trigger next or not. */ + if (point.u32Z0 == 0) + { + /* Stop sampling procedure. */ + rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); + + /* Re-start pendown detection */ + nu_adc_touch_detect(RT_TRUE); + + bDrop = RT_TRUE; + } + else + { + bDrop = RT_FALSE; + } + + /* Notify upper layer. */ + if ((!bDrop || (u32LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) + { + rt_hw_touch_isr(psNuAdc->psRtTouch); + } + + u32LastZ0 = point.u32Z0; + } + else +#endif + { + rt_err_t result = rt_sem_release(psNuAdc->m_psSem); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} + +#if defined(BSP_USING_ADC_TOUCH) + void nu_adc_touch_detect(rt_bool_t bStartDetect) { nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; @@ -150,60 +211,6 @@ void nu_adc_touch_detect(rt_bool_t bStartDetect) } } -static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) -{ - static struct nu_adc_touch_data point; - static rt_bool_t bDrop = RT_FALSE; - static uint16_t u16LastZ0 = 0xfffful; - - nu_adc_t psNuAdc = (nu_adc_t)userData; - - if (psNuAdc->psRtTouch != RT_NULL) - { - uint32_t value; - - value = inpw(REG_ADC_XYDATA); - point.u16X = (uint16_t)(value & 0x0ffful); - point.u16Y = (uint16_t)((value >> 16) & 0x0ffful); - - value = inpw(REG_ADC_ZDATA); - point.u16Z0 = (uint16_t)(value & 0x0ffful); - point.u16Z1 = (uint16_t)((value >> 16) & 0x0ffful); - - /* Trigger next or not. */ - if (point.u16Z0 == 0) - { - /* Stop sampling procedure. */ - rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); - - /* Re-start pendown detection */ - nu_adc_touch_detect(RT_TRUE); - - bDrop = RT_TRUE; - } - else - { - bDrop = RT_FALSE; - } - - /* Notify upper layer. */ - if ((!bDrop || (u16LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) - { - rt_hw_touch_isr(psNuAdc->psRtTouch); - } - - u16LastZ0 = point.u16Z0; - } - else - { - rt_err_t result = rt_sem_release(psNuAdc->m_psSem); - RT_ASSERT(result == RT_EOK); - } - - return 0; -} - - static int32_t PenDownCallback(uint32_t status, uint32_t userData) { nu_adc_touch_detect(RT_FALSE); @@ -213,7 +220,7 @@ static int32_t PenDownCallback(uint32_t status, uint32_t userData) return 0; } -int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, uint16_t *bufZ1, int32_t dataCnt) +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt) { int i; struct nu_adc_touch_data value; @@ -223,14 +230,71 @@ int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, u if (rt_mq_recv(g_sNuADC.m_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT) break; - bufX[i] = value.u16X; - bufY[i] = value.u16Y; - bufZ0[i] = value.u16Z0; - bufZ1[i] = value.u16Z1; + bufX[i] = value.u32X; + bufY[i] = value.u32Y; + bufZ0[i] = value.u32Z0; + bufZ1[i] = value.u32Z1; } return i; } +void nu_adc_touch_start_conv(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); +} + +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + nu_adc_cb sNuAdcCb; + + rt_adc_enable((rt_adc_device_t)psNuAdc, 4); + rt_adc_enable((rt_adc_device_t)psNuAdc, 5); + rt_adc_enable((rt_adc_device_t)psNuAdc, 6); + rt_adc_enable((rt_adc_device_t)psNuAdc, 7); + + outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); + + /* Register touch device. */ + psNuAdc->psRtTouch = psRtTouch; + + /* Enable TouchXY. */ + _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); + + /* Enable TouchZZ. */ + _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); + + /* Register PenDown callback. */ + sNuAdcCb.cbfunc = PenDownCallback; + sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); + + nu_adc_touch_detect(RT_TRUE); + + return RT_EOK; +} + +rt_err_t nu_adc_touch_disable(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + nu_adc_touch_detect(RT_FALSE); + + _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); + + rt_adc_disable((rt_adc_device_t)psNuAdc, 4); + rt_adc_disable((rt_adc_device_t)psNuAdc, 5); + rt_adc_disable((rt_adc_device_t)psNuAdc, 6); + rt_adc_disable((rt_adc_device_t)psNuAdc, 7); + + return RT_EOK; +} + +#endif + static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) { rt_err_t ret = RT_EINVAL ; @@ -443,7 +507,9 @@ static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) case Z_OFF: /* Disable Press measure function */ { outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_ZEN); +#if defined(BSP_USING_ADC_TOUCH) rt_mq_control(psNuAdc->m_pmqTouchXYZ, RT_IPC_CMD_RESET, RT_NULL); +#endif } break; @@ -522,61 +588,6 @@ static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } -void nu_adc_touch_start_conv(void) -{ - nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; - _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); -} - -rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) -{ - nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; - nu_adc_cb sNuAdcCb; - - rt_adc_enable((rt_adc_device_t)psNuAdc, 4); - rt_adc_enable((rt_adc_device_t)psNuAdc, 5); - rt_adc_enable((rt_adc_device_t)psNuAdc, 6); - rt_adc_enable((rt_adc_device_t)psNuAdc, 7); - - outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); - - /* Register touch device. */ - psNuAdc->psRtTouch = psRtTouch; - - /* Enable TouchXY. */ - _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); - - /* Enable TouchZZ. */ - _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); - - /* Register PenDown callback. */ - sNuAdcCb.cbfunc = PenDownCallback; - sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; - _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); - - nu_adc_touch_detect(RT_TRUE); - - return RT_EOK; -} - -rt_err_t nu_adc_touch_disable(void) -{ - nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; - - nu_adc_touch_detect(RT_FALSE); - - _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); - _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); - _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); - - rt_adc_disable((rt_adc_device_t)psNuAdc, 4); - rt_adc_disable((rt_adc_device_t)psNuAdc, 5); - rt_adc_disable((rt_adc_device_t)psNuAdc, 6); - rt_adc_disable((rt_adc_device_t)psNuAdc, 7); - - return RT_EOK; -} - static rt_err_t _nu_adc_open(rt_device_t dev, rt_uint16_t oflag) { nu_adc_t psNuAdc = (nu_adc_t)dev; @@ -709,11 +720,13 @@ int rt_hw_adc_init(void) g_sNuADC.m_psSem = rt_sem_create("adc_mst_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(g_sNuADC.m_psSem != RT_NULL); +#if defined(BSP_USING_ADC_TOUCH) g_sNuADC.m_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_XYZ", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO); RT_ASSERT(g_sNuADC.m_pmqTouchXYZ != RT_NULL); g_sNuADC.psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)&g_sNuADC, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC); RT_ASSERT(g_sNuADC.psRtTouchMenuTimer != RT_NULL); +#endif rt_memset(&g_sNuADC.m_isr, 0, sizeof(g_sNuADC.m_isr)); rt_memset(&g_sNuADC.m_wkisr, 0, sizeof(g_sNuADC.m_wkisr)); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h index 2269f1f35c..ead185e0c1 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc.h @@ -15,9 +15,13 @@ #include #include "nu_adc.h" -#include "touch.h" +#if defined(BSP_USING_ADC_TOUCH) + #include "touch.h" +#endif -#define TOUCH_MQ_LENGTH 128 +#define TOUCH_MQ_LENGTH 64 + +#define DEF_CAL_POINT_NUM 5 typedef enum { @@ -52,13 +56,29 @@ typedef struct typedef nu_adc_cb *nu_adc_cb_t; -int32_t nu_adc_read_touch_xyz(uint16_t *bufX, uint16_t *bufY, uint16_t *bufZ0, uint16_t *bufZ1, int32_t dataCnt); +#if defined(BSP_USING_ADC_TOUCH) +typedef struct +{ + int32_t x; + int32_t y; +} S_COORDINATE_POINT; + +typedef struct +{ + int32_t a; + int32_t b; + int32_t c; + int32_t d; + int32_t e; + int32_t f; + int32_t div; +} S_CALIBRATION_MATRIX; + +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt); rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch); rt_err_t nu_adc_touch_disable(void); void nu_adc_touch_detect(rt_bool_t bStartDetect); void nu_adc_touch_start_conv(void); - -void nu_adc_touch_update_caldata(int *psi32NewValue); -void nu_adc_touch_reset_caldata(int *psi32NewValue); +#endif #endif /* __DRV_ADC_H__ */ diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c index fb1f4433cf..9d4848251c 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c @@ -15,9 +15,15 @@ #include "NuMicro.h" #include +#include #include "drv_adc.h" #include "touch.h" +#if !defined(PATH_CALIBRATION_FILE) + #define PATH_CALIBRATION_FILE "/mnt/filesystem/ts_calibration" +#endif + + typedef struct { struct rt_touch_device dev; @@ -28,41 +34,135 @@ typedef nu_adc_touch *nu_adc_touch_t; static nu_adc_touch s_NuAdcTouch = {0}; -#define DEF_CALDATA_LENGTH 7 - -#if defined(LCM_USING_FW043TFT) - #define LCM_WIDTH 480 - #define LCM_HEIGHT 272 - static int cal_data_a[DEF_CALDATA_LENGTH] = { 8824, -34, -2261272, -70, -6302, 21805816, 65536 }; +#if (BSP_LCD_WIDTH==480) && (BSP_LCD_HEIGHT==272) +static S_CALIBRATION_MATRIX g_sCalMat = { 8824, -34, -2261272, -70, -6302, 21805816, 65536 }; +static volatile uint32_t g_u32Calibrated = 1; +#elif (BSP_LCD_WIDTH==800) && (BSP_LCD_HEIGHT==480) +static S_CALIBRATION_MATRIX g_sCalMat = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; +static volatile uint32_t g_u32Calibrated = 1; #else - #define LCM_WIDTH 800 - #define LCM_HEIGHT 480 - #if defined(LCM_USING_FW070TFT) - static int cal_data_a[DEF_CALDATA_LENGTH] = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; - #else - static int cal_data_a[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; - #endif +static S_CALIBRATION_MATRIX g_sCalMat = { 1, 0, 0, 0, 1, 0, 1 }; +static volatile uint32_t g_u32Calibrated = 0; #endif -static const int cal_zero[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; +static int nu_adc_touch_readfile(void); -static void nu_adc_touch_cal(int *sumx, int *sumy) +static const S_CALIBRATION_MATRIX g_sCalZero = { 1, 0, 0, 0, 1, 0, 1 }; + +static int nu_adc_cal_mat_get(const S_COORDINATE_POINT *psDispCP, S_COORDINATE_POINT *psADCCP, S_CALIBRATION_MATRIX *psCM) { - int xtemp, ytemp; +#if (DEF_CAL_POINT_NUM==3) + + psCM->div = ((psADCCP[0].x - psADCCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psADCCP[1].x - psADCCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + if (psCM->div == 0) + { + return -1; + } + else + { + psCM->a = ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].x - psDispCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->b = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].x - psDispCP[2].x)) - + ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->c = (psADCCP[2].x * psDispCP[1].x - psADCCP[1].x * psDispCP[2].x) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].x - psADCCP[2].x * psDispCP[0].x) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].x - psADCCP[0].x * psDispCP[1].x) * psADCCP[2].y ; + + psCM->d = ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].y - psDispCP[2].y) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->e = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].y - psDispCP[2].y)) - + ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->f = (psADCCP[2].x * psDispCP[1].y - psADCCP[1].x * psDispCP[2].y) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].y - psADCCP[2].x * psDispCP[0].y) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].y - psADCCP[0].x * psDispCP[1].y) * psADCCP[2].y ; + } + +#elif (DEF_CAL_POINT_NUM==5) + + int i; + float n, x, y, xx, yy, xy, z, zx, zy; + float a, b, c, d, e, f, g; + float scaling = 65536.0f; + + n = x = y = xx = yy = xy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + n += 1.0; + x += (float)psADCCP[i].x; + y += (float)psADCCP[i].y; + xx += (float)psADCCP[i].x * psADCCP[i].x; + yy += (float)psADCCP[i].y * psADCCP[i].y; + xy += (float)psADCCP[i].x * psADCCP[i].y; + } + + d = n * (xx * yy - xy * xy) + x * (xy * y - x * yy) + y * (x * xy - y * xx); + if (d < 0.1 && d > -0.1) + { + return -1; + } + + a = (xx * yy - xy * xy) / d; + b = (xy * y - x * yy) / d; + c = (x * xy - y * xx) / d; + e = (n * yy - y * y) / d; + f = (x * y - n * xy) / d; + g = (n * xx - x * x) / d; + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].x; + zx += (float)psDispCP[i].x * psADCCP[i].x; + zy += (float)psDispCP[i].x * psADCCP[i].y; + } + + psCM->c = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->a = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->b = (int32_t)((c * z + f * zx + g * zy) * scaling); + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].y; + zx += (float)psDispCP[i].y * psADCCP[i].x; + zy += (float)psDispCP[i].y * psADCCP[i].y; + } + + psCM->f = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->d = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->e = (int32_t)((c * z + f * zx + g * zy) * scaling); + + psCM->div = (int32_t)scaling; + +#else +#error "Not supported calibration method" +#endif + return 0; +} + +static void nu_adc_touch_cal(int32_t *sumx, int32_t *sumy) +{ + int32_t xtemp, ytemp; xtemp = *sumx; ytemp = *sumy; - *sumx = (cal_data_a[2] + - cal_data_a[0] * xtemp + - cal_data_a[1] * ytemp) / cal_data_a[6]; - *sumy = (cal_data_a[5] + - cal_data_a[3] * xtemp + - cal_data_a[4] * ytemp) / cal_data_a[6]; + *sumx = (g_sCalMat.c + + g_sCalMat.a * xtemp + + g_sCalMat.b * ytemp) / g_sCalMat.div; + *sumy = (g_sCalMat.f + + g_sCalMat.d * xtemp + + g_sCalMat.e * ytemp) / g_sCalMat.div; } static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *buf, rt_size_t read_num) { - static int last_report_x = 0, last_report_y = 0; + static uint32_t last_report_x = 0, last_report_y = 0; struct rt_touch_data *pPoint = (struct rt_touch_data *)buf; nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; @@ -73,38 +173,44 @@ static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *bu for (i = 0; i < read_num; i++) { - int bufZ0 = 0, bufZ1 = 0; - int sumx = 0, sumy = 0; + uint32_t bufZ0 = 0, bufZ1 = 0; + int32_t sumx = 0, sumy = 0; pPoint[i].timestamp = rt_touch_get_ts(); pPoint[i].track_id = 0; - if (nu_adc_read_touch_xyz((uint16_t *)&sumx, (uint16_t *)&sumy, (uint16_t *)&bufZ0, (uint16_t *)&bufZ1, 1) != 1) + if (nu_adc_touch_read_xyz((uint32_t *)&sumx, (uint32_t *)&sumy, &bufZ0, &bufZ1, 1) != 1) break; if (bufZ0 == 0) { /* Workaround: In this case, x, y values are unstable. so, report last point's coordinate.*/ pPoint[i].event = RT_TOUCH_EVENT_UP; - pPoint[i].x_coordinate = last_report_x; - pPoint[i].y_coordinate = last_report_y; + pPoint[i].x_coordinate = (uint16_t)last_report_x; + pPoint[i].y_coordinate = (uint16_t)last_report_y; } else { - nu_adc_touch_cal(&sumx, &sumy); - pPoint[i].event = RT_TOUCH_EVENT_DOWN; - pPoint[i].x_coordinate = sumx; - pPoint[i].y_coordinate = sumy; + if (g_u32Calibrated) + { + nu_adc_touch_cal(&sumx, &sumy); + } last_report_x = sumx; last_report_y = sumy; + + pPoint[i].event = RT_TOUCH_EVENT_DOWN; + pPoint[i].x_coordinate = (uint16_t)sumx; + pPoint[i].y_coordinate = (uint16_t)sumy; } - bufZ0 = bufZ0 >> 3; + if (g_u32Calibrated) + { + bufZ0 = bufZ0 >> 3; + pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; - pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; - - //Limit max x, y coordinate if value is over its range. - pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; - pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + //Limit max x, y coordinate if value is over its range. + pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; + pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + } } return (rt_size_t)i; } @@ -150,14 +256,29 @@ static struct rt_touch_ops touch_ops = .touch_control = nu_adc_touch_control, }; -void nu_adc_touch_update_caldata(int *psi32NewValue) +static void nu_adc_touch_update_calmat(S_CALIBRATION_MATRIX *psNewCalMat) { - rt_memcpy(&cal_data_a[0], &psi32NewValue[0], sizeof(cal_data_a)); + if (psNewCalMat && + psNewCalMat->div != 0) + { + rt_memcpy(&g_sCalMat, psNewCalMat, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 1; + rt_kprintf("Applied calibration data: %d, %d, %d, %d, %d, %d, %d\n", + g_sCalMat.a, + g_sCalMat.b, + g_sCalMat.c, + g_sCalMat.d, + g_sCalMat.e, + g_sCalMat.f, + g_sCalMat.div); + + } } -void nu_adc_touch_reset_caldata(int *psi32NewValue) +static void nu_adc_touch_reset_calmat(void) { - rt_memcpy(&cal_data_a[0], &cal_zero[0], sizeof(cal_data_a)); + rt_memcpy(&g_sCalMat, &g_sCalZero, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 0; } int rt_hw_adc_touch_init(void) @@ -166,8 +287,8 @@ int rt_hw_adc_touch_init(void) s_NuAdcTouch.dev.info.type = RT_TOUCH_TYPE_RESISTANCE; s_NuAdcTouch.dev.info.vendor = RT_TOUCH_VENDOR_UNKNOWN; s_NuAdcTouch.dev.info.point_num = 1; - s_NuAdcTouch.dev.info.range_x = LCM_WIDTH; - s_NuAdcTouch.dev.info.range_y = LCM_HEIGHT; + s_NuAdcTouch.dev.info.range_x = BSP_LCD_WIDTH; + s_NuAdcTouch.dev.info.range_y = BSP_LCD_HEIGHT; s_NuAdcTouch.dev.ops = &touch_ops; @@ -179,10 +300,268 @@ INIT_DEVICE_EXPORT(rt_hw_adc_touch_init); static rt_thread_t adc_touch_thread = RT_NULL; static rt_sem_t adc_touch_sem = RT_NULL; static int adc_touch_worker_run = 0; + static rt_err_t adc_touch_rx_callback(rt_device_t dev, rt_size_t size) { - rt_sem_release(adc_touch_sem); + //rt_kprintf("[%s %d] %d\n", __func__, __LINE__, size); + return rt_sem_release(adc_touch_sem); +} + +static rt_err_t adc_request_point(rt_device_t pdev, struct rt_touch_data *psTouchPoint) +{ + rt_err_t ret = -RT_ERROR; + + if ((ret = rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(500))) == RT_EOK) + { + rt_memset(psTouchPoint, 0, sizeof(struct rt_touch_data)); + + if (rt_device_read(pdev, 0, psTouchPoint, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + { + ret = RT_EOK; + } + + } + + return ret; +} + +RT_WEAK void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t event) +{ +} + +static rt_device_t lcd_device = 0; +static struct rt_device_graphic_info info; + +static void lcd_cleanscreen(void) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + + rt_memset(info.framebuffer, 0, (info.pitch * info.height)); + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#define DEF_DOT_NUMBER 9 +#define DOTS_NUMBER (DEF_DOT_NUMBER*DEF_DOT_NUMBER) +static void nu_draw_bots(int x, int y) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + int i, j; + int start_x = x - (DEF_DOT_NUMBER / 2); + int start_y = y - (DEF_DOT_NUMBER / 2); + + if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) + { + uint16_t *pu16Start = (uint16_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 2)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu16Start[i] = 0x07E0; //Green, RGB + pu16Start += info.width; + } + } + else if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888) + { + uint32_t *pu32Start = (uint32_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 4)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu32Start[i] = 0xff00ff00; //Green, ARGB + pu32Start += info.width; + } + } + else + { + //Not supported + } + + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#if (DEF_CAL_POINT_NUM==3) +const S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ + {BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 2}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 4}, + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / 4} +}; +#elif (DEF_CAL_POINT_NUM==5) +const static S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ +#define DEF_CUT_PIECES 8 + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT / 2} +}; +#endif + +static int nu_adc_touch_readfile(void) +{ + int fd; + + S_CALIBRATION_MATRIX sCalMat; + + if ((fd = open(PATH_CALIBRATION_FILE, O_RDONLY, 0)) < 0) + { + goto exit_nu_adc_touch_readfile; + } + else if (read(fd, &sCalMat, sizeof(S_CALIBRATION_MATRIX)) == sizeof(S_CALIBRATION_MATRIX)) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + nu_adc_touch_update_calmat(&sCalMat); + return 0; + +exit_nu_adc_touch_readfile: + + return -1; +} + +static int nu_adc_touch_writefile(void *buf, int buf_len) +{ + int fd; + + if ((fd = open(PATH_CALIBRATION_FILE, O_WRONLY | O_CREAT, 0)) < 0) + { + goto exit_nu_adc_touch_writefile; + } + else if (write(fd, buf, buf_len) == buf_len) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + return 0; + +exit_nu_adc_touch_writefile: + + return -1; +} + +static void nu_touch_do_calibration(rt_device_t pdev) +{ + int i; + rt_err_t result; + + S_CALIBRATION_MATRIX sCalMat; + S_COORDINATE_POINT sADCPoints[DEF_CAL_POINT_NUM]; + + lcd_device = rt_device_find("lcd"); + if (!lcd_device) + { + rt_kprintf("Not supported graphics ops\n"); + return; + } + + result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK) + { + rt_kprintf("error!"); + return; + } + + result = rt_device_open(lcd_device, 0); + if (result != RT_EOK) + { + rt_kprintf("opened?"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, info.framebuffer); + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + struct rt_touch_data sTouchPoint; + int count = 0; + + lcd_cleanscreen(); + + /* Drain RX queue before doing calibrate. */ + while (adc_request_point(pdev, &sTouchPoint) == RT_EOK); + + rt_thread_mdelay(100); + + /* Ready to calibrate */ + nu_draw_bots(sDispPoints[i].x, sDispPoints[i].y); + +#define DEF_MAX_GET_POINT_NUM 5 + + sADCPoints[i].x = 0; + sADCPoints[i].y = 0; + + while (count < DEF_MAX_GET_POINT_NUM) + { + if (adc_request_point(pdev, &sTouchPoint) == RT_EOK) + { + sADCPoints[i].x += (int32_t)sTouchPoint.x_coordinate; + sADCPoints[i].y += (int32_t)sTouchPoint.y_coordinate; + rt_kprintf("[%d %d] - Disp:[%d, %d] -> ADC:[%d, %d]\n", i, count, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + count++; + } + } + + sADCPoints[i].x = (int32_t)((float)sADCPoints[i].x / DEF_MAX_GET_POINT_NUM); + sADCPoints[i].y = (int32_t)((float)sADCPoints[i].y / DEF_MAX_GET_POINT_NUM); + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + + rt_thread_mdelay(300); + } + + lcd_cleanscreen(); + + /* Get calibration matrix. */ + if (nu_adc_cal_mat_get(&sDispPoints[0], &sADCPoints[0], &sCalMat) == 0) + { + /* Finally, update calibration matrix to drivers. */ + nu_adc_touch_update_calmat(&sCalMat); + + nu_adc_touch_writefile(&sCalMat, sizeof(sCalMat)); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + } + } + else + { + rt_kprintf("Failed to calibrate.\n"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWEROFF, RT_NULL); + rt_device_close(lcd_device); + + return; } static void adc_touch_entry(void *parameter) @@ -190,66 +569,63 @@ static void adc_touch_entry(void *parameter) struct rt_touch_data touch_point; rt_err_t result; - rt_device_t pdev = &s_NuAdcTouch.dev.parent; + rt_device_t pdev; int max_range; adc_touch_sem = rt_sem_create("adc_touch_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(adc_touch_sem != RT_NULL); + pdev = rt_device_find("adc_touch"); + if (!pdev) + { + rt_kprintf("Not found\n"); + return ; + } + + nu_adc_touch_readfile(); + result = rt_device_open(pdev, RT_DEVICE_FLAG_INT_RX); RT_ASSERT(result == RT_EOK); result = rt_device_set_rx_indicate(pdev, adc_touch_rx_callback); RT_ASSERT(result == RT_EOK); - max_range = LCM_WIDTH; + max_range = BSP_LCD_WIDTH; result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_X_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); - max_range = LCM_HEIGHT; + max_range = BSP_LCD_HEIGHT; result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); - // nu_adc_touch_reset_caldata(int *psi32NewValue); - // nu_adc_touch_update_caldata(int *psi32NewValue); - result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_ON, RT_NULL); RT_ASSERT(result == RT_EOK); while (adc_touch_worker_run) { - if ((-RT_ETIMEOUT == rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(100)))) + if (!g_u32Calibrated) + { + rt_kprintf("Start ADC touching calibration.\n"); + nu_touch_do_calibration(pdev); + rt_kprintf("Stop ADC touching calibration.\n"); continue; + } - rt_memset(&touch_point, 0, sizeof(struct rt_touch_data)); - - if (rt_device_read(pdev, 0, &touch_point, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + if (adc_request_point(pdev, &touch_point) == RT_EOK) { if (touch_point.event == RT_TOUCH_EVENT_DOWN || touch_point.event == RT_TOUCH_EVENT_UP || touch_point.event == RT_TOUCH_EVENT_MOVE) { - -#if defined(PKG_USING_LVGL) - extern void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t state); nu_touch_inputevent_cb(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); -#elif defined(PKG_USING_LITTLEVGL2RTT) - extern void littlevgl2rtt_send_input_event(rt_int16_t x, rt_int16_t y, rt_uint8_t state); - littlevgl2rtt_send_input_event(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); -#endif -#if defined(PKG_USING_NUEMWIN) - extern void nuemwin_send_input_event(rt_int16_t x, rt_int16_t y, rt_uint8_t state); - nuemwin_send_input_event(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); -#endif - rt_kprintf("[%d-%d] id=%d width=%d x=%d y=%d\n", - touch_point.timestamp, - touch_point.event, - touch_point.track_id, - touch_point.width, + rt_kprintf("x=%d y=%d event=%s%s%s\n", touch_point.x_coordinate, - touch_point.y_coordinate); + touch_point.y_coordinate, + (touch_point.event == RT_TOUCH_EVENT_DOWN) ? "DOWN" : "", + (touch_point.event == RT_TOUCH_EVENT_UP) ? "UP" : "", + (touch_point.event == RT_TOUCH_EVENT_MOVE) ? "MOVE" : ""); } } } @@ -270,7 +646,7 @@ static rt_err_t nu_touch_start(int argc, char **argv) adc_touch_thread = rt_thread_create("adc_touch_thread", adc_touch_entry, RT_NULL, - 1024, + 4096, 25, 5); adc_touch_worker_run = 1; @@ -290,4 +666,19 @@ static rt_err_t nu_touch_stop(int argc, char **argv) } MSH_CMD_EXPORT(nu_touch_stop, e.g: stop adc touch); +static int nu_touch_autostart(void) +{ + return nu_touch_start(0, RT_NULL); +} +INIT_APP_EXPORT(nu_touch_autostart); + +static rt_err_t nu_touch_calibration(int argc, char **argv) +{ + /* Clean calibration matrix data for getting raw adc value. */ + nu_adc_touch_reset_calmat(); + + return 0; +} +MSH_CMD_EXPORT(nu_touch_calibration, for adc touch); + #endif //#if defined(BSP_USING_ADC_TOUCH) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c index a4da2879cf..aedd61f018 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_can.c @@ -58,6 +58,7 @@ struct nu_can IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -106,16 +107,16 @@ static const struct can_configure nu_can_default_config = NU_CAN_CONFIG_DEFAULT; /* Interrupt Handle Function ----------------------------------------------------*/ static void nu_can_isr(int vector, void *param) { - uint32_t u32IIDRstatus; nu_can_t psNuCAN = (nu_can_t)param; /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ @@ -123,20 +124,24 @@ static void nu_can_isr(int vector, void *param) if (base->STATUS & CAN_STATUS_TXOK_Msk) { base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - //rt_kprintf("%s: TX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif } if (base->STATUS & CAN_STATUS_RXOK_Msk) { base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - //rt_kprintf("%s: RX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif } @@ -145,17 +150,16 @@ static void nu_can_isr(int vector, void *param) /**************************/ if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("%s: EWARN\n", psNuCAN->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("%s: BUSOFF\n", psNuCAN->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } if (base->STATUS & CAN_STATUS_LEC_Msk) @@ -168,66 +172,83 @@ static void nu_can_isr(int vector, void *param) /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; - RT_ASSERT(base != RT_NULL); - - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } - + /* Reset this module */ nu_sys_ip_reset(psNuCAN->rstidx); - /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; + /*Set the CAN Bit Rate and Operating mode*/ + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR CAN_LeaveTestMode(base); @@ -249,6 +270,7 @@ static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; @@ -261,73 +283,33 @@ exit_nu_can_configure: static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; - nu_can_t psNuCAN = (nu_can_t)can; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *base = psNuCAN->base; - - RT_ASSERT(base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Status Change Interrupt */ - CAN_DisableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Error Interrupt */ - CAN_DisableInt(base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } @@ -335,46 +317,61 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) else { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -387,16 +384,23 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; @@ -411,64 +415,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + RT_ASSERT(can); + RT_ASSERT(buf); - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + pmsg = (struct rt_can_msg *) buf; - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -480,32 +511,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -540,5 +552,4 @@ static int rt_hw_can_init(void) return (int)ret; } INIT_DEVICE_EXPORT(rt_hw_can_init); - #endif //#if defined(BSP_USING_CAN) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c index 0b4fbaabf1..987f8b3fd5 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_i2c.c @@ -34,6 +34,8 @@ #define I2C_ENABLE(dev) I2C_REG_WRITE(dev, I2C_CSR, 0x3) /* Enable i2c core and interrupt */ #define I2C_ISBUSFREE(dev) (((I2C_REG_READ(dev, I2C_SWR) & 0x18) == 0x18 && (I2C_REG_READ(dev, I2C_CSR) & 0x0400) == 0) ? 1 : 0) +#define I2C_SIGNAL_TIMEOUT 5000 + enum { I2C_START = -1, @@ -50,7 +52,7 @@ enum typedef struct { int32_t base; /* i2c bus number */ - int32_t state; + volatile int32_t state; int32_t addr; uint32_t last_error; int32_t bNackValid; @@ -58,9 +60,11 @@ typedef struct uint32_t subaddr; int32_t subaddr_len; - uint8_t buffer[I2C_MAX_BUF_LEN]; - uint32_t pos, len; + volatile uint32_t pos; + volatile uint32_t len; + uint8_t *buffer; + struct rt_completion signal; } nu_i2c_dev; typedef nu_i2c_dev *nu_i2c_dev_t; @@ -68,7 +72,6 @@ typedef struct { struct rt_i2c_bus_device parent; char *name; - IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; @@ -113,13 +116,13 @@ static nu_i2c_bus nu_i2c_arr [ ] = * @brief Set i2c interface speed * @param[in] dev i2c device structure pointer * @param[in] sp i2c speed - * @return always 0 + * @return 0 or I2C_ERR_NOTTY */ static int32_t nu_i2c_set_speed(nu_i2c_dev_t psNuI2cDev, int32_t sp) { uint32_t d; - if (sp != 100 && sp != 400) + if ((sp != 100) && (sp != 400)) return (I2C_ERR_NOTTY); d = (sysGetClock(SYS_PCLK) * 1000) / (sp * 5) - 1; @@ -205,6 +208,7 @@ static void nu_i2c_isr(int vector, void *param) psNuI2CDev->last_error = I2C_ERR_NACK; nu_i2c_command(psNuI2CDev, I2C_CMD_STOP); psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } /* Arbitration lost */ else if (csr & 0x200) @@ -212,6 +216,7 @@ static void nu_i2c_isr(int vector, void *param) rt_kprintf("Arbitration lost\n"); psNuI2CDev->last_error = I2C_ERR_LOSTARBITRATION; psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } /* Transmit complete */ else if (!(csr & 0x100)) @@ -225,6 +230,7 @@ static void nu_i2c_isr(int vector, void *param) } else if (psNuI2CDev->state == I2C_STATE_READ) { + /* Sub-address send over, begin restart a read command */ if (psNuI2CDev->pos == psNuI2CDev->subaddr_len + 1) { @@ -246,6 +252,7 @@ static void nu_i2c_isr(int vector, void *param) else { psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } } } @@ -270,13 +277,13 @@ static void nu_i2c_isr(int vector, void *param) else { psNuI2CDev->state = I2C_STATE_NOP; + rt_completion_done(&psNuI2CDev->signal); } } } + } - - /** * @brief Read data from I2C slave. * @param[in] psNuI2cDev is interface structure pointer. @@ -294,6 +301,9 @@ static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) uint8_t *buf = pmsg->buf; uint32_t len = pmsg->len; + RT_ASSERT(len); + RT_ASSERT(buf); + if (len > I2C_MAX_BUF_LEN - 10) len = I2C_MAX_BUF_LEN - 10; @@ -317,9 +327,22 @@ static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (!I2C_ISBUSFREE(psNuI2cDev)) return (I2C_ERR_BUSY); + rt_completion_init(&psNuI2cDev->signal); + nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE); - while (psNuI2cDev->state != I2C_STATE_NOP); + if ((RT_EOK == rt_completion_wait(&psNuI2cDev->signal, I2C_SIGNAL_TIMEOUT))) + { + rt_memcpy(buf, psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 3, len); + + psNuI2cDev->subaddr += len; + } + else + { + rt_kprintf("[%s]Wait signal timeout.\n", __func__); + + len = 0; + } /* Disable I2C-EN */ I2C_DISABLE(psNuI2cDev); @@ -327,10 +350,6 @@ static int32_t nu_i2c_read(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (psNuI2cDev->last_error) return (psNuI2cDev->last_error); - rt_memcpy(buf, psNuI2cDev->buffer + psNuI2cDev->subaddr_len + 3, len); - - psNuI2cDev->subaddr += len; - return len; } @@ -351,6 +370,9 @@ static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) uint8_t *buf = pmsg->buf; uint32_t len = pmsg->len; + RT_ASSERT(len); + RT_ASSERT(buf); + if (len > I2C_MAX_BUF_LEN - 10) len = I2C_MAX_BUF_LEN - 10; @@ -373,9 +395,20 @@ static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (!I2C_ISBUSFREE(psNuI2cDev)) return (I2C_ERR_BUSY); + rt_completion_init(&psNuI2cDev->signal); + nu_i2c_command(psNuI2cDev, I2C_CMD_START | I2C_CMD_WRITE); - while (psNuI2cDev->state != I2C_STATE_NOP); + if ((RT_EOK == rt_completion_wait(&psNuI2cDev->signal, I2C_SIGNAL_TIMEOUT))) + { + psNuI2cDev->subaddr += len; + } + else + { + rt_kprintf("[%s]Wait signal timeout.\n", __func__); + + len = 0; + } /* Disable I2C-EN */ I2C_DISABLE(psNuI2cDev); @@ -383,8 +416,6 @@ static int32_t nu_i2c_write(nu_i2c_dev_t psNuI2cDev, struct rt_i2c_msg *pmsg) if (psNuI2cDev->last_error) return (psNuI2cDev->last_error); - psNuI2cDev->subaddr += len; - return len; } @@ -405,16 +436,13 @@ static int32_t nu_i2c_ioctl(nu_i2c_dev_t psNuI2cDev, uint32_t cmd, uint32_t arg0 switch (cmd) { case I2C_IOC_SET_DEV_ADDRESS: - psNuI2cDev->addr = arg0; break; case I2C_IOC_SET_SPEED: - - return (nu_i2c_set_speed(psNuI2cDev, (int32_t)arg0)); + return nu_i2c_set_speed(psNuI2cDev, (int32_t)arg0); case I2C_IOC_SET_SUB_ADDRESS: - if (arg1 > 4) { return (I2C_ERR_NOTTY); @@ -441,7 +469,8 @@ static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, rt_err_t ret; struct rt_i2c_msg *pmsg; - RT_ASSERT(bus != RT_NULL); + RT_ASSERT(bus); + psNuI2cBus = (nu_i2c_bus_t) bus; psNuI2cDev = &psNuI2cBus->dev; @@ -459,6 +488,7 @@ static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, /* Set device address */ nu_i2c_reset(psNuI2cDev); + nu_i2c_ioctl(psNuI2cDev, I2C_IOC_SET_DEV_ADDRESS, pmsg->addr, 0); if (pmsg->flags & RT_I2C_RD) @@ -470,18 +500,39 @@ static rt_size_t nu_i2c_mst_xfer(struct rt_i2c_bus_device *bus, ret = nu_i2c_write(psNuI2cDev, pmsg); } - if (ret != pmsg->len) break; } return i; } +static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u32Cmd, rt_uint32_t u32Value) +{ + nu_i2c_bus_t psNuI2cBus; + nu_i2c_dev_t psNuI2cDev; + + RT_ASSERT(bus); + + psNuI2cBus = (nu_i2c_bus_t) bus; + psNuI2cDev = &psNuI2cBus->dev; + + switch (u32Cmd) + { + case RT_I2C_DEV_CTRL_CLK: + nu_i2c_set_speed(psNuI2cDev, (int32_t)u32Value); + break; + default: + return -RT_EIO; + } + + return RT_EOK; +} + static const struct rt_i2c_bus_device_ops nu_i2c_ops = { .master_xfer = nu_i2c_mst_xfer, .slave_xfer = NULL, - .i2c_bus_control = NULL, + .i2c_bus_control = nu_i2c_bus_control, }; @@ -489,17 +540,17 @@ static const struct rt_i2c_bus_device_ops nu_i2c_ops = int rt_hw_i2c_init(void) { int i; - rt_err_t ret = RT_EOK; + rt_err_t ret; for (i = (I2C_START + 1); i < I2C_CNT; i++) { nu_i2c_dev_t psNuI2cDev = &nu_i2c_arr[i].dev; - ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].name); - RT_ASSERT(RT_EOK == ret); - nu_i2c_arr[i].parent.ops = &nu_i2c_ops; + psNuI2cDev->buffer = rt_malloc(I2C_MAX_BUF_LEN); + RT_ASSERT(psNuI2cDev->buffer); + /* Enable I2C engine clock and reset. */ nu_sys_ipclk_enable(nu_i2c_arr[i].clkidx); nu_sys_ip_reset(nu_i2c_arr[i].rstidx); @@ -509,6 +560,9 @@ int rt_hw_i2c_init(void) /* Register ISR and Respond IRQ. */ rt_hw_interrupt_install(nu_i2c_arr[i].irqn, nu_i2c_isr, &nu_i2c_arr[i], nu_i2c_arr[i].name); rt_hw_interrupt_umask(nu_i2c_arr[i].irqn); + + ret = rt_i2c_bus_device_register(&nu_i2c_arr[i].parent, nu_i2c_arr[i].name); + RT_ASSERT(RT_EOK == ret); } return 0; diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c index 41fae42ae4..0f5f1e23a3 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c @@ -69,6 +69,9 @@ static struct nu_vpost nu_fbdev[eVpost_Cnt] = #endif }; +RT_WEAK void nu_lcd_backlight_on(void) { } + +RT_WEAK void nu_lcd_backlight_off(void) { } static rt_err_t vpost_layer_open(rt_device_t dev, rt_uint16_t oflag) { nu_vpost_t psVpost = (nu_vpost_t)dev; @@ -149,6 +152,18 @@ static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) switch (cmd) { + case RTGRAPHIC_CTRL_POWERON: + { + nu_lcd_backlight_on(); + } + break; + + case RTGRAPHIC_CTRL_POWEROFF: + { + nu_lcd_backlight_off(); + } + break; + case RTGRAPHIC_CTRL_GET_INFO: { struct rt_device_graphic_info *info = (struct rt_device_graphic_info *) args; @@ -324,6 +339,11 @@ int rt_hw_vpost_init(void) rt_kprintf("Fail to get VRAM buffer.\n"); RT_ASSERT(0); } + else + { + uint32_t u32FBSize = psVpost->info.pitch * psVpostLcmInst->u32DevHeight; + rt_memset(psVpost->info.framebuffer, 0, u32FBSize); + } /* Register member functions of lcd device */ psVpost->dev.type = RT_Device_Class_Graphic; diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c index 31cb6c6d02..5f87e038c1 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c @@ -27,6 +27,7 @@ static struct rt_device_graphic_info g_Ili9341Info = .pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565, .framebuffer = RT_NULL, .width = XSIZE_PHYS, + .pitch = XSIZE_PHYS * 2, .height = YSIZE_PHYS }; @@ -324,7 +325,7 @@ int rt_hw_lcd_ili9341_init(void) lcd_device.user_data = &ili9341_ops; #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) - g_Ili9341Info.framebuffer = rt_malloc_align((DEF_VRAM_BUFFER_NUMBER * g_Ili9341Info.width * g_Ili9341Info.height * (g_Ili9341Info.bits_per_pixel / 8)) + 32, 32); + g_Ili9341Info.framebuffer = rt_malloc_align((DEF_VRAM_BUFFER_NUMBER * g_Ili9341Info.pitch * g_Ili9341Info.height) + 32, 32); RT_ASSERT(g_Ili9341Info.framebuffer != RT_NULL); #endif diff --git a/bsp/nuvoton/libraries/nu_packages/Kconfig b/bsp/nuvoton/libraries/nu_packages/Kconfig index ab3bba4331..b27797f36a 100644 --- a/bsp/nuvoton/libraries/nu_packages/Kconfig +++ b/bsp/nuvoton/libraries/nu_packages/Kconfig @@ -38,7 +38,7 @@ menu "Nuvoton Packages Config" bool "ILI9341 LCD Panel" select BSP_USING_GPIO default n - + if NU_PKG_USING_ILI9341 choice @@ -62,8 +62,20 @@ menu "Nuvoton Packages Config" default n config NU_PKG_ILI9341_HORIZONTAL - bool "Set horizontal view. (320x240)" - default n + bool + default y + + config BSP_LCD_BPP + int + default 16 if NU_PKG_USING_ILI9341 + + config BSP_LCD_WIDTH + int + default 320 if NU_PKG_ILI9341_HORIZONTAL + + config BSP_LCD_HEIGHT + int + default 240 if NU_PKG_ILI9341_HORIZONTAL endif diff --git a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h index 341e2606f0..6e814049ff 100644 --- a/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h +++ b/bsp/nuvoton/libraries/nuc980/Driver/Include/nu_adc.h @@ -35,51 +35,142 @@ extern "C" #define ADC_ERR_CMD 2 /*!< The command is wrong */ /// @cond HIDDEN_SYMBOLS -typedef INT32(*ADC_CALLBACK)(UINT32 status, UINT32 userData); +typedef int32_t(*ADC_CALLBACK)(uint32_t status, uint32_t userData); /// @endcond HIDDEN_SYMBOLS /*---------------------------------------------------------------------------------------------------------*/ /* ADC_CTL constant definitions */ /*---------------------------------------------------------------------------------------------------------*/ #define ADC_CTL_ADEN 0x00000001 /*!< ADC Power Control */ -#define ADC_CTL_VBGEN 0x00000002 /*!< ADC Internal Bandgap Power Control */ +#define ADC_CTL_VBGEN 0x00000002 /*!< ADC Internal Bandgap Power Control */ +#define ADC_CTL_PWKPEN 0x00000004 /*!< ADC Keypad Power Enable Control */ #define ADC_CTL_MST 0x00000100 /*!< Menu Start Conversion */ +#define ADC_CTL_PEDEEN 0x00000200 /*!< Pen Down Event Enable */ +#define ADC_CTL_WKPEN 0x00000400 /*!< Keypad Press Wake Up Enable */ +#define ADC_CTL_WKTEN 0x00000800 /*!< Touch Wake Up Enable */ +#define ADC_CTL_WMSWCH 0x00010000 /*!< Wire Mode Switch For 5-Wire/4-Wire Configuration */ /*---------------------------------------------------------------------------------------------------------*/ /* ADC_CONF constant definitions */ /*---------------------------------------------------------------------------------------------------------*/ +#define ADC_CONF_TEN 0x00000001 /*!< Touch Enable */ +#define ADC_CONF_ZEN 0x00000002 /*!< Press Enable */ #define ADC_CONF_NACEN 0x00000004 /*!< Normal AD Conversion Enable */ +#define ADC_CONF_VBATEN 0x00000100 /*!< Voltage Battery Enable */ +#define ADC_CONF_KPCEN 0x00000200 /*!< Keypad Press Conversion Enable */ #define ADC_CONF_SELFTEN 0x00000400 /*!< Selft Test Enable */ +#define ADC_CONF_DISTMAVEN (1<<20) /*!< Display T Mean Average Enable */ +#define ADC_CONF_DISZMAVEN (1<<21) /*!< Display Z Mean Average Enable */ #define ADC_CONF_HSPEED (1<<22) /*!< High Speed Enable */ -#define ADC_CONF_CHSEL_Pos 12 /*!< Channel Selection Position */ -#define ADC_CONF_CHSEL_Msk (0xF<psCurrentRxDesc; @@ -1151,7 +1151,7 @@ EMAC_DESCRIPTOR_T * EMAC_RecvPktDoneWoRxTrigger(EMAC_MEMMGR_T *psMemMgr) return ret; } -void EMAC_RxTrigger(EMAC_MEMMGR_T *psMemMgr, EMAC_DESCRIPTOR_T * rx_desc) +void EMAC_RxTrigger(EMAC_MEMMGR_T *psMemMgr, EMAC_DESCRIPTOR_T *rx_desc) { EMAC_T *EMAC = psMemMgr->psEmac; diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig index 08ea27c97a..ffa3e55cc4 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig @@ -70,6 +70,13 @@ config SOC_SERIES_NUC980 bool "Enable Analog-to-Digital Converter(ADC)" select RT_USING_ADC + if BSP_USING_ADC + config BSP_USING_ADC_TOUCH + bool "Enable ADC Touching function" + select RT_USING_TOUCH + default n + endif + menuconfig BSP_USING_TMR bool "Enable Timer Controller(TIMER)" diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c index 721bd5d6c1..66d93845ab 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.c @@ -15,9 +15,12 @@ #include #include "NuMicro.h" -#include +#include "drv_sys.h" +#include "nu_bitutil.h" +#include "drv_adc.h" /* Private define ---------------------------------------------------------------*/ +#define DEF_ADC_TOUCH_SMPL_TICK 40 /* Private Typedef --------------------------------------------------------------*/ struct nu_adc @@ -31,12 +34,33 @@ struct nu_adc int chn_num; uint32_t chn_mask; rt_sem_t m_psSem; + +#if defined(BSP_USING_ADC_TOUCH) + rt_touch_t psRtTouch; + rt_timer_t psRtTouchMenuTimer; + rt_mq_t m_pmqTouchXYZ; +#endif + + nu_adc_cb m_isr[eAdc_ISR_CNT]; + nu_adc_cb m_wkisr[eAdc_WKISR_CNT]; }; typedef struct nu_adc *nu_adc_t; +#if defined(BSP_USING_ADC_TOUCH) +struct nu_adc_touch_data +{ + uint32_t u32X; + uint32_t u32Y; + uint32_t u32Z0; + uint32_t u32Z1; +}; +typedef struct nu_adc_touch_data *nu_adc_touch_data_t; +#endif + /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled); static rt_err_t nu_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value); +static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args); /* Public functions ------------------------------------------------------------*/ int rt_hw_adc_init(void); @@ -56,24 +80,41 @@ static struct nu_adc g_sNuADC = static void nu_adc_isr(int vector, void *param) { - uint32_t isr, conf; + rt_int32_t isr, wkisr; nu_adc_t psNuAdc = (nu_adc_t)param; + rt_int32_t irqidx; - conf = inpw(REG_ADC_CONF); isr = inpw(REG_ADC_ISR); + wkisr = inpw(REG_ADC_WKISR); - if ((isr & ADC_ISR_NACF) && (conf & ADC_CONF_NACEN)) + while ((irqidx = nu_ctz(isr)) < eAdc_ISR_CNT) { - outpw(REG_ADC_ISR, ADC_ISR_NACF); - } + uint32_t u32IsrBitMask = 1 << irqidx ; - if (isr & ADC_ISR_MF) + if (psNuAdc->m_isr[irqidx].cbfunc != RT_NULL) + { + //rt_kprintf("[%s] %d %x\n", __func__, irqidx, psNuAdc->m_isr[irqidx].cbfunc); + psNuAdc->m_isr[irqidx].cbfunc(isr, psNuAdc->m_isr[irqidx].private_data); + } + + /* Clear sent bit */ + outpw(REG_ADC_ISR, u32IsrBitMask); + isr &= ~(u32IsrBitMask); + } //while + + while ((irqidx = nu_ctz(wkisr)) < eAdc_WKISR_CNT) { - rt_err_t result; - outpw(REG_ADC_ISR, ADC_ISR_MF); - result = rt_sem_release(psNuAdc->m_psSem); - RT_ASSERT(result == RT_EOK); - } + uint32_t u32IsrBitMask = 1 << irqidx ; + + if (psNuAdc->m_wkisr[irqidx].cbfunc != RT_NULL) + { + psNuAdc->m_wkisr[irqidx].cbfunc(wkisr, psNuAdc->m_wkisr[irqidx].private_data); + } + + /* Clear sent bit */ + outpw(REG_ADC_WKISR, u32IsrBitMask); + wkisr &= ~(u32IsrBitMask); + } //while } static rt_err_t _nu_adc_init(rt_device_t dev) @@ -96,11 +137,171 @@ static rt_err_t _nu_adc_init(rt_device_t dev) return RT_EOK; } +static int32_t AdcMenuStartCallback(uint32_t status, uint32_t userData) +{ + nu_adc_t psNuAdc = (nu_adc_t)userData; + +#if defined(BSP_USING_ADC_TOUCH) + + static struct nu_adc_touch_data point; + static rt_bool_t bDrop = RT_FALSE; + static uint32_t u32LastZ0 = 0xffffu; + + if (psNuAdc->psRtTouch != RT_NULL) + { + uint32_t value; + + value = inpw(REG_ADC_XYDATA); + point.u32X = (value & 0x0ffful); + point.u32Y = ((value >> 16) & 0x0ffful); + + value = inpw(REG_ADC_ZDATA); + point.u32Z0 = (value & 0x0ffful); + point.u32Z1 = ((value >> 16) & 0x0ffful); + + /* Trigger next or not. */ + if (point.u32Z0 == 0) + { + /* Stop sampling procedure. */ + rt_timer_stop(g_sNuADC.psRtTouchMenuTimer); + + /* Re-start pendown detection */ + nu_adc_touch_detect(RT_TRUE); + + bDrop = RT_TRUE; + } + else + { + bDrop = RT_FALSE; + } + + /* Notify upper layer. */ + if ((!bDrop || (u32LastZ0 != 0)) && rt_mq_send(psNuAdc->m_pmqTouchXYZ, (const void *)&point, sizeof(struct nu_adc_touch_data)) == RT_EOK) + { + rt_hw_touch_isr(psNuAdc->psRtTouch); + } + + u32LastZ0 = point.u32Z0; + } + else +#endif + { + rt_err_t result = rt_sem_release(psNuAdc->m_psSem); + RT_ASSERT(result == RT_EOK); + } + + return 0; +} + +#if defined(BSP_USING_ADC_TOUCH) + +void nu_adc_touch_detect(rt_bool_t bStartDetect) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + if (bStartDetect) + { + /* Start detect PenDown */ + _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_ON, RT_NULL); + } + else + { + /* Stop detect PenDown */ + _nu_adc_control((rt_device_t)psNuAdc, PEPOWER_OFF, RT_NULL); + } +} + +static int32_t PenDownCallback(uint32_t status, uint32_t userData) +{ + nu_adc_touch_detect(RT_FALSE); + + rt_timer_start(g_sNuADC.psRtTouchMenuTimer); + + return 0; +} + +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt) +{ + int i; + struct nu_adc_touch_data value; + + for (i = 0 ; i < dataCnt; i++) + { + if (rt_mq_recv(g_sNuADC.m_pmqTouchXYZ, (void *)&value, sizeof(struct nu_adc_touch_data), 0) == -RT_ETIMEOUT) + break; + + bufX[i] = value.u32X; + bufY[i] = value.u32Y; + bufZ0[i] = value.u32Z0; + bufZ1[i] = value.u32Z1; + } + return i; +} + +void nu_adc_touch_start_conv(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + _nu_adc_control((rt_device_t)psNuAdc, START_MST, RT_NULL); +} + +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + nu_adc_cb sNuAdcCb; + + rt_adc_enable((rt_adc_device_t)psNuAdc, 4); + rt_adc_enable((rt_adc_device_t)psNuAdc, 5); + rt_adc_enable((rt_adc_device_t)psNuAdc, 6); + rt_adc_enable((rt_adc_device_t)psNuAdc, 7); + + outpw(REG_ADC_CONF, (inpw(REG_ADC_CONF) & ~(0xfful << 24)) | 0xfful << 24); + + /* Register touch device. */ + psNuAdc->psRtTouch = psRtTouch; + + /* Enable TouchXY. */ + _nu_adc_control((rt_device_t)psNuAdc, T_ON, RT_NULL); + + /* Enable TouchZZ. */ + _nu_adc_control((rt_device_t)psNuAdc, Z_ON, RT_NULL); + + /* Register PenDown callback. */ + sNuAdcCb.cbfunc = PenDownCallback; + sNuAdcCb.private_data = (rt_uint32_t)psRtTouch; + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_ON, (void *)&sNuAdcCb); + + nu_adc_touch_detect(RT_TRUE); + + return RT_EOK; +} + +rt_err_t nu_adc_touch_disable(void) +{ + nu_adc_t psNuAdc = (nu_adc_t)&g_sNuADC; + + nu_adc_touch_detect(RT_FALSE); + + _nu_adc_control((rt_device_t)psNuAdc, T_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, Z_OFF, RT_NULL); + _nu_adc_control((rt_device_t)psNuAdc, PEDEF_OFF, RT_NULL); + + rt_adc_disable((rt_adc_device_t)psNuAdc, 4); + rt_adc_disable((rt_adc_device_t)psNuAdc, 5); + rt_adc_disable((rt_adc_device_t)psNuAdc, 6); + rt_adc_disable((rt_adc_device_t)psNuAdc, 7); + + return RT_EOK; +} + +#endif + static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) { rt_err_t ret = RT_EINVAL ; nu_adc_t psNuAdc = (nu_adc_t)dev; + nu_adc_cb_t psAdcCb = (nu_adc_cb_t)args; + switch (cmd) { case START_MST: /* Menu Start Conversion */ @@ -116,29 +317,259 @@ static rt_err_t _nu_adc_control(rt_device_t dev, int cmd, void *args) RT_ASSERT(ret == RT_EOK); /* Get data: valid data is 12-bit */ - *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF; + if (args != RT_NULL) + *((uint32_t *)args) = inpw(REG_ADC_DATA) & 0x00000FFF; } break; + + /* case START_MST_POLLING: Not supported. */ + case VBPOWER_ON: /* Enable ADC Internal Bandgap Power */ { outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_VBGEN); } break; + case VBPOWER_OFF: /* Disable ADC Internal Bandgap Power */ { outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_VBGEN); } break; + + case KPPOWER_ON: /* Enable ADC Keypad Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PWKPEN); + } + break; + + case KPPOWER_OFF: /* Disable ADC Keypad Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PWKPEN); + } + break; + + case PEPOWER_ON: /* Enable Pen Power */ + { + int retry = 100; + uint32_t treg = inpw(REG_ADC_IER); + outpw(REG_ADC_IER, treg & ~(ADC_IER_PEDEIEN | ADC_IER_PEUEIEN)); + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_PEDEEN); + do + { + outpw(REG_ADC_ISR, ADC_ISR_PEDEF | ADC_ISR_PEUEF); + rt_thread_mdelay(1); + if (retry-- == 0) + break; + } + while (inpw(REG_ADC_ISR) & (ADC_ISR_PEDEF | ADC_ISR_PEUEF)); + outpw(REG_ADC_IER, treg); + } + break; + + case PEPOWER_OFF: /* Disable Pen Power */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_PEDEEN); + } + break; + + case KPPRESS_ON: /* Enable Keypad press event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN); + } + break; + + case KPPRESS_OFF: /* Disable Keypad press event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER & ~ADC_IER_KPEIEN)); + } + break; + + case KPUP_ON: /* Enable Keypad up event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPUEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPUEIEN); + } + break; + + case KPUP_OFF: /* Disable Keypad up event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_KPUEIEN); + } + break; + + case PEDEF_ON: /* Enable Pen Down Event */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_PEDEF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_PEDEIEN); + } + break; + + case PEDEF_OFF: /* Disable Pen Down Event */ + { + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_PEDEIEN); + } + break; + + case WKP_ON: /* Enable Keypad Press Wake Up */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_wkisr[eAdc_WKPEF], psAdcCb, sizeof(nu_adc_cb)); + } + + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKPEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKPIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26)); + } + break; + + case WKP_OFF: /* Disable Keypad Press Wake Up */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKPEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKPIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26)); + } + break; + + case WKT_ON: /* Enable Touch Wake Up */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_wkisr[eAdc_WPEDEF], psAdcCb, sizeof(nu_adc_cb)); + } + + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WKTEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_WKTIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) | (1 << 26)); + } + break; + + case WKT_OFF: /* Disable Touch Wake Up */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WKTEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) & ~ADC_IER_WKTIEN); + //outpw(REG_SYS_WKUPSER, inpw(REG_SYS_WKUPSER) & ~(1 << 26)); + } + break; + + case SWITCH_5WIRE_ON: /* Wire Mode Switch to 5-Wire */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_WMSWCH); + } + break; + + case SWITCH_5WIRE_OFF: /* Wire Mode Switch to 4-Wire */ + { + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) & ~ADC_CTL_WMSWCH); + } + break; + + case T_ON: /* Enable Touch detection function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_TEN); + } + break; + + case T_OFF: /* Disable Touch detection function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_TEN); + } + break; + + case TAVG_ON: /* Enable Touch Mean average for X and Y function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISTMAVEN); + } + break; + + case TAVG_OFF: /* Disable Touch Mean average for X and Y function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISTMAVEN); + } + break; + + case Z_ON: /* Enable Press measure function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_ZEN); + } + break; + + case Z_OFF: /* Disable Press measure function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_ZEN); +#if defined(BSP_USING_ADC_TOUCH) + rt_mq_control(psNuAdc->m_pmqTouchXYZ, RT_IPC_CMD_RESET, RT_NULL); +#endif + } + break; + + case TZAVG_ON: /* Enable Pressure Mean average for Z1 and Z2 function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_DISZMAVEN); + } + break; + + case TZAVG_OFF: /* Disable Pressure Mean average for Z1 and Z2 function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_DISZMAVEN); + } + break; + case NAC_ON: /* Enable Normal AD Conversion */ { outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_NACEN | ADC_CONF_REFSEL_AVDD33); } break; + case NAC_OFF: /* Disable Normal AD Conversion */ { outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_NACEN); } break; + + case VBAT_ON: /* Enable Voltage Battery Conversion */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_VBF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_VBATEN); + } + break; + + case VBAT_OFF: /* Disable Voltage Battery */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_VBATEN); + } + break; + + case KPCONV_ON: /* Enable Keypad conversion function */ + { + if (psAdcCb) + { + rt_memcpy(&psNuAdc->m_isr[eAdc_KPCF], psAdcCb, sizeof(nu_adc_cb)); + } + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) | ADC_CONF_KPCEN); + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_KPEIEN); + } + break; + + case KPCONV_OFF: /* Disable Keypad conversion function */ + { + outpw(REG_ADC_CONF, inpw(REG_ADC_CONF) & ~ADC_CONF_KPCEN); + } + break; + case SWITCH_CH: { int chn = (int)args; @@ -265,6 +696,16 @@ exit_nu_adc_convert: return (-ret) ; } +static void nu_adc_touch_smpl(void *p) +{ + /* Enable interrupt */ + outpw(REG_ADC_IER, inpw(REG_ADC_IER) | ADC_IER_MIEN); + + /* Start conversion */ + outpw(REG_ADC_CTL, inpw(REG_ADC_CTL) | ADC_CTL_MST); +} + + int rt_hw_adc_init(void) { rt_err_t result = RT_ERROR; @@ -279,8 +720,22 @@ int rt_hw_adc_init(void) g_sNuADC.m_psSem = rt_sem_create("adc_mst_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(g_sNuADC.m_psSem != RT_NULL); +#if defined(BSP_USING_ADC_TOUCH) + g_sNuADC.m_pmqTouchXYZ = rt_mq_create("ADC_TOUCH_XYZ", sizeof(struct nu_adc_touch_data), TOUCH_MQ_LENGTH, RT_IPC_FLAG_FIFO); + RT_ASSERT(g_sNuADC.m_pmqTouchXYZ != RT_NULL); + + g_sNuADC.psRtTouchMenuTimer = rt_timer_create("TOUCH_SMPL_TIMER", nu_adc_touch_smpl, (void *)&g_sNuADC, DEF_ADC_TOUCH_SMPL_TICK, RT_TIMER_FLAG_PERIODIC); + RT_ASSERT(g_sNuADC.psRtTouchMenuTimer != RT_NULL); +#endif + + rt_memset(&g_sNuADC.m_isr, 0, sizeof(g_sNuADC.m_isr)); + rt_memset(&g_sNuADC.m_wkisr, 0, sizeof(g_sNuADC.m_wkisr)); + + g_sNuADC.m_isr[eAdc_MF].cbfunc = AdcMenuStartCallback; + g_sNuADC.m_isr[eAdc_MF].private_data = (UINT32)&g_sNuADC; + return (int)result; } INIT_BOARD_EXPORT(rt_hw_adc_init); -#endif //#if defined(BSP_USING_EADC) +#endif //#if defined(BSP_USING_ADC) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h new file mode 100644 index 0000000000..ead185e0c1 --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc.h @@ -0,0 +1,84 @@ +/**************************************************************************//** +* +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-4-7 Wayne First version +* +******************************************************************************/ + +#ifndef __DRV_ADC_H__ +#define __DRV_ADC_H__ + +#include +#include "nu_adc.h" +#if defined(BSP_USING_ADC_TOUCH) + #include "touch.h" +#endif + +#define TOUCH_MQ_LENGTH 64 + +#define DEF_CAL_POINT_NUM 5 + +typedef enum +{ + eAdc_MF, //0 + eAdc_KPEF, //1 + eAdc_PEDEF, //2 + eAdc_KPUEF, //3 + eAdc_PEUEF, //4 + eAdc_TF = 8, //8 + eAdc_ZF, //9 + eAdc_NACF, //10 + eAdc_VBF, //11 + eAdc_KPCF, //12 + eAdc_SELFTF, //13 + eAdc_INTKP = 16, //16 + eAdc_INTTC, //17 + eAdc_ISR_CNT //18 +} E_ADC_ISR_EVENT; + +typedef enum +{ + eAdc_WKPEF, + eAdc_WPEDEF, + eAdc_WKISR_CNT +} E_ADC_WKISR_EVENT; + +typedef struct +{ + ADC_CALLBACK cbfunc; + uint32_t private_data; +} nu_adc_cb; + +typedef nu_adc_cb *nu_adc_cb_t; + +#if defined(BSP_USING_ADC_TOUCH) +typedef struct +{ + int32_t x; + int32_t y; +} S_COORDINATE_POINT; + +typedef struct +{ + int32_t a; + int32_t b; + int32_t c; + int32_t d; + int32_t e; + int32_t f; + int32_t div; +} S_CALIBRATION_MATRIX; + +int32_t nu_adc_touch_read_xyz(uint32_t *bufX, uint32_t *bufY, uint32_t *bufZ0, uint32_t *bufZ1, int32_t dataCnt); +rt_err_t nu_adc_touch_enable(rt_touch_t psRtTouch); +rt_err_t nu_adc_touch_disable(void); +void nu_adc_touch_detect(rt_bool_t bStartDetect); +void nu_adc_touch_start_conv(void); +#endif + +#endif /* __DRV_ADC_H__ */ diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c new file mode 100644 index 0000000000..e995f249af --- /dev/null +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c @@ -0,0 +1,681 @@ +/**************************************************************************//** +* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Change Logs: +* Date Author Notes +* 2021-04-20 Wayne First version +* +******************************************************************************/ + +#include + +#if defined(BSP_USING_ADC_TOUCH) + +#include "NuMicro.h" +#include +#include +#include "drv_adc.h" +#include "touch.h" + +#if !defined(PATH_CALIBRATION_FILE) + #define PATH_CALIBRATION_FILE "/mnt/filesystem/ts_calibration" +#endif + + +typedef struct +{ + struct rt_touch_device dev; + rt_uint32_t x_range; + rt_uint32_t y_range; +} nu_adc_touch; +typedef nu_adc_touch *nu_adc_touch_t; + +static nu_adc_touch s_NuAdcTouch = {0}; + +#if (BSP_LCD_WIDTH==320) && (BSP_LCD_HEIGHT==240) +static S_CALIBRATION_MATRIX g_sCalMat = { 43, -5839, 21672848, 4193, -11, -747882, 65536 }; +static volatile uint32_t g_u32Calibrated = 1; +#else +static S_CALIBRATION_MATRIX g_sCalMat = { 1, 0, 0, 0, 1, 0, 1 }; +static volatile uint32_t g_u32Calibrated = 0; +#endif + +static int nu_adc_touch_readfile(void); + +static const S_CALIBRATION_MATRIX g_sCalZero = { 1, 0, 0, 0, 1, 0, 1 }; + +static int nu_adc_cal_mat_get(const S_COORDINATE_POINT *psDispCP, S_COORDINATE_POINT *psADCCP, S_CALIBRATION_MATRIX *psCM) +{ +#if (DEF_CAL_POINT_NUM==3) + + psCM->div = ((psADCCP[0].x - psADCCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psADCCP[1].x - psADCCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + if (psCM->div == 0) + { + return -1; + } + else + { + psCM->a = ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].x - psDispCP[2].x) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->b = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].x - psDispCP[2].x)) - + ((psDispCP[0].x - psDispCP[2].x) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->c = (psADCCP[2].x * psDispCP[1].x - psADCCP[1].x * psDispCP[2].x) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].x - psADCCP[2].x * psDispCP[0].x) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].x - psADCCP[0].x * psDispCP[1].x) * psADCCP[2].y ; + + psCM->d = ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].y - psADCCP[2].y)) - + ((psDispCP[1].y - psDispCP[2].y) * (psADCCP[0].y - psADCCP[2].y)) ; + + psCM->e = ((psADCCP[0].x - psADCCP[2].x) * (psDispCP[1].y - psDispCP[2].y)) - + ((psDispCP[0].y - psDispCP[2].y) * (psADCCP[1].x - psADCCP[2].x)) ; + + psCM->f = (psADCCP[2].x * psDispCP[1].y - psADCCP[1].x * psDispCP[2].y) * psADCCP[0].y + + (psADCCP[0].x * psDispCP[2].y - psADCCP[2].x * psDispCP[0].y) * psADCCP[1].y + + (psADCCP[1].x * psDispCP[0].y - psADCCP[0].x * psDispCP[1].y) * psADCCP[2].y ; + } + +#elif (DEF_CAL_POINT_NUM==5) + + int i; + float n, x, y, xx, yy, xy, z, zx, zy; + float a, b, c, d, e, f, g; + float scaling = 65536.0f; + + n = x = y = xx = yy = xy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + n += 1.0; + x += (float)psADCCP[i].x; + y += (float)psADCCP[i].y; + xx += (float)psADCCP[i].x * psADCCP[i].x; + yy += (float)psADCCP[i].y * psADCCP[i].y; + xy += (float)psADCCP[i].x * psADCCP[i].y; + } + + d = n * (xx * yy - xy * xy) + x * (xy * y - x * yy) + y * (x * xy - y * xx); + if (d < 0.1 && d > -0.1) + { + return -1; + } + + a = (xx * yy - xy * xy) / d; + b = (xy * y - x * yy) / d; + c = (x * xy - y * xx) / d; + e = (n * yy - y * y) / d; + f = (x * y - n * xy) / d; + g = (n * xx - x * x) / d; + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].x; + zx += (float)psDispCP[i].x * psADCCP[i].x; + zy += (float)psDispCP[i].x * psADCCP[i].y; + } + + psCM->c = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->a = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->b = (int32_t)((c * z + f * zx + g * zy) * scaling); + + z = zx = zy = 0; + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + z += (float)psDispCP[i].y; + zx += (float)psDispCP[i].y * psADCCP[i].x; + zy += (float)psDispCP[i].y * psADCCP[i].y; + } + + psCM->f = (int32_t)((a * z + b * zx + c * zy) * scaling); + psCM->d = (int32_t)((b * z + e * zx + f * zy) * scaling); + psCM->e = (int32_t)((c * z + f * zx + g * zy) * scaling); + + psCM->div = (int32_t)scaling; + +#else +#error "Not supported calibration method" +#endif + return 0; +} + +static void nu_adc_touch_cal(int32_t *sumx, int32_t *sumy) +{ + int32_t xtemp, ytemp; + + xtemp = *sumx; + ytemp = *sumy; + *sumx = (g_sCalMat.c + + g_sCalMat.a * xtemp + + g_sCalMat.b * ytemp) / g_sCalMat.div; + *sumy = (g_sCalMat.f + + g_sCalMat.d * xtemp + + g_sCalMat.e * ytemp) / g_sCalMat.div; +} + +static rt_size_t nu_adc_touch_readpoint(struct rt_touch_device *device, void *buf, rt_size_t read_num) +{ + static uint32_t last_report_x = 0, last_report_y = 0; + struct rt_touch_data *pPoint = (struct rt_touch_data *)buf; + nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(buf != RT_NULL); + + int i; + + for (i = 0; i < read_num; i++) + { + uint32_t bufZ0 = 0, bufZ1 = 0; + int32_t sumx = 0, sumy = 0; + pPoint[i].timestamp = rt_touch_get_ts(); + pPoint[i].track_id = 0; + + if (nu_adc_touch_read_xyz((uint32_t *)&sumx, (uint32_t *)&sumy, &bufZ0, &bufZ1, 1) != 1) + break; + + if (bufZ0 == 0) + { + /* Workaround: In this case, x, y values are unstable. so, report last point's coordinate.*/ + pPoint[i].event = RT_TOUCH_EVENT_UP; + pPoint[i].x_coordinate = (uint16_t)last_report_x; + pPoint[i].y_coordinate = (uint16_t)last_report_y; + } + else + { + if (g_u32Calibrated) + { + nu_adc_touch_cal(&sumx, &sumy); + } + last_report_x = sumx; + last_report_y = sumy; + + pPoint[i].event = RT_TOUCH_EVENT_DOWN; + pPoint[i].x_coordinate = (uint16_t)sumx; + pPoint[i].y_coordinate = (uint16_t)sumy; + } + + if (g_u32Calibrated) + { + bufZ0 = bufZ0 >> 3; + pPoint[i].width = (bufZ0 > 255) ? 255 : bufZ0; + + //Limit max x, y coordinate if value is over its range. + pPoint[i].x_coordinate = (pPoint[i].x_coordinate > psNuAdcTouch->x_range) ? psNuAdcTouch->x_range : pPoint[i].x_coordinate; + pPoint[i].y_coordinate = (pPoint[i].y_coordinate > psNuAdcTouch->y_range) ? psNuAdcTouch->y_range : pPoint[i].y_coordinate; + } + } + return (rt_size_t)i; +} + +static rt_err_t nu_adc_touch_control(struct rt_touch_device *device, int cmd, void *data) +{ + nu_adc_touch_t psNuAdcTouch = (nu_adc_touch_t)device; + RT_ASSERT(psNuAdcTouch != RT_NULL); + + switch (cmd) + { + case RT_TOUCH_CTRL_SET_X_RANGE: /* set x range */ + psNuAdcTouch->x_range = *((rt_int32_t *)data); + break; + + case RT_TOUCH_CTRL_SET_Y_RANGE: /* set y range */ + psNuAdcTouch->y_range = *((rt_int32_t *)data); + break; + + case RT_TOUCH_CTRL_ENABLE_INT: /* enable pen_down interrupt */ + nu_adc_touch_detect(RT_TRUE); + break; + + case RT_TOUCH_CTRL_DISABLE_INT: /* disable pen_down interrupt */ + nu_adc_touch_detect(RT_FALSE); + break; + + case RT_TOUCH_CTRL_POWER_ON: /* Touch Power On */ + return nu_adc_touch_enable(device); + + case RT_TOUCH_CTRL_POWER_OFF: /* Touch Power Off */ + return nu_adc_touch_disable(); + + default: + return -RT_ERROR; + } + return RT_EOK; +} + +static struct rt_touch_ops touch_ops = +{ + .touch_readpoint = nu_adc_touch_readpoint, + .touch_control = nu_adc_touch_control, +}; + +static void nu_adc_touch_update_calmat(S_CALIBRATION_MATRIX *psNewCalMat) +{ + if (psNewCalMat && + psNewCalMat->div != 0) + { + rt_memcpy(&g_sCalMat, psNewCalMat, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 1; + rt_kprintf("Applied calibration data: %d, %d, %d, %d, %d, %d, %d\n", + g_sCalMat.a, + g_sCalMat.b, + g_sCalMat.c, + g_sCalMat.d, + g_sCalMat.e, + g_sCalMat.f, + g_sCalMat.div); + + } +} + +static void nu_adc_touch_reset_calmat(void) +{ + rt_memcpy(&g_sCalMat, &g_sCalZero, sizeof(S_CALIBRATION_MATRIX)); + g_u32Calibrated = 0; +} + +int rt_hw_adc_touch_init(void) +{ + /* Register touch device */ + s_NuAdcTouch.dev.info.type = RT_TOUCH_TYPE_RESISTANCE; + s_NuAdcTouch.dev.info.vendor = RT_TOUCH_VENDOR_UNKNOWN; + s_NuAdcTouch.dev.info.point_num = 1; + s_NuAdcTouch.dev.info.range_x = BSP_LCD_WIDTH; + s_NuAdcTouch.dev.info.range_y = BSP_LCD_HEIGHT; + + s_NuAdcTouch.dev.ops = &touch_ops; + + return (int)rt_hw_touch_register(&s_NuAdcTouch.dev, "adc_touch", RT_DEVICE_FLAG_INT_RX, RT_NULL); +} +INIT_DEVICE_EXPORT(rt_hw_adc_touch_init); + + +static rt_thread_t adc_touch_thread = RT_NULL; +static rt_sem_t adc_touch_sem = RT_NULL; +static int adc_touch_worker_run = 0; + +static rt_err_t adc_touch_rx_callback(rt_device_t dev, rt_size_t size) +{ + //rt_kprintf("[%s %d] %d\n", __func__, __LINE__, size); + return rt_sem_release(adc_touch_sem); +} + +static rt_err_t adc_request_point(rt_device_t pdev, struct rt_touch_data *psTouchPoint) +{ + rt_err_t ret = -RT_ERROR; + + if ((ret = rt_sem_take(adc_touch_sem, rt_tick_from_millisecond(500))) == RT_EOK) + { + rt_memset(psTouchPoint, 0, sizeof(struct rt_touch_data)); + + if (rt_device_read(pdev, 0, psTouchPoint, s_NuAdcTouch.dev.info.point_num) == s_NuAdcTouch.dev.info.point_num) + { + ret = RT_EOK; + } + + } + + return ret; +} + +RT_WEAK void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t event) +{ +} + +static rt_device_t lcd_device = 0; +static struct rt_device_graphic_info info; + +static void lcd_cleanscreen(void) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + + rt_memset(info.framebuffer, 0, (info.pitch * info.height)); + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#define DEF_DOT_NUMBER 9 +#define DOTS_NUMBER (DEF_DOT_NUMBER*DEF_DOT_NUMBER) +static void nu_draw_bots(int x, int y) +{ + if (info.framebuffer != RT_NULL) + { + /* Rendering */ + struct rt_device_rect_info rect; + int i, j; + int start_x = x - (DEF_DOT_NUMBER / 2); + int start_y = y - (DEF_DOT_NUMBER / 2); + + if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565) + { + uint16_t *pu16Start = (uint16_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 2)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu16Start[i] = 0x07E0; //Green, RGB + pu16Start += info.width; + } + } + else if (info.pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888) + { + uint32_t *pu32Start = (uint32_t *)((uint32_t)info.framebuffer + (start_y) * info.pitch + (start_x * 4)); + for (j = 0; j < DEF_DOT_NUMBER; j++) + { + for (i = 0; i < DEF_DOT_NUMBER; i++) + pu32Start[i] = 0xff00ff00; //Green, ARGB + pu32Start += info.width; + } + } + else + { + //Not supported + } + + rect.x = 0; + rect.y = 0; + rect.width = info.width; + rect.height = info.height; + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + } + else + { + // TODO + } +} + +#if (DEF_CAL_POINT_NUM==3) +const S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ + {BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 2}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / 4, BSP_LCD_HEIGHT / 4}, + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / 4} +}; +#elif (DEF_CAL_POINT_NUM==5) +const static S_COORDINATE_POINT sDispPoints[DEF_CAL_POINT_NUM] = +{ +#define DEF_CUT_PIECES 8 + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH - BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + {BSP_LCD_WIDTH / DEF_CUT_PIECES, BSP_LCD_HEIGHT - BSP_LCD_HEIGHT / DEF_CUT_PIECES}, + + {BSP_LCD_WIDTH / 2, BSP_LCD_HEIGHT / 2} +}; +#endif + +static int nu_adc_touch_readfile(void) +{ + int fd; + + S_CALIBRATION_MATRIX sCalMat; + + if ((fd = open(PATH_CALIBRATION_FILE, O_RDONLY, 0)) < 0) + { + goto exit_nu_adc_touch_readfile; + } + else if (read(fd, &sCalMat, sizeof(S_CALIBRATION_MATRIX)) == sizeof(S_CALIBRATION_MATRIX)) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + nu_adc_touch_update_calmat(&sCalMat); + + return 0; + +exit_nu_adc_touch_readfile: + + return -1; +} + +static int nu_adc_touch_writefile(void *buf, int buf_len) +{ + int fd; + + if ((fd = open(PATH_CALIBRATION_FILE, O_WRONLY | O_CREAT, 0)) < 0) + { + goto exit_nu_adc_touch_writefile; + } + else if (write(fd, buf, buf_len) == buf_len) + { + rt_kprintf("[%s] %s\n", __func__, PATH_CALIBRATION_FILE); + } + + close(fd); + + return 0; + +exit_nu_adc_touch_writefile: + + return -1; +} + +static void nu_touch_do_calibration(rt_device_t pdev) +{ + int i; + rt_err_t result; + + S_CALIBRATION_MATRIX sCalMat; + S_COORDINATE_POINT sADCPoints[DEF_CAL_POINT_NUM]; + + lcd_device = rt_device_find("lcd"); + if (!lcd_device) + { + rt_kprintf("Not supported graphics ops\n"); + return; + } + + result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK) + { + rt_kprintf("error!"); + return; + } + + result = rt_device_open(lcd_device, 0); + if (result != RT_EOK) + { + rt_kprintf("opened?"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, info.framebuffer); + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + struct rt_touch_data sTouchPoint; + int count = 0; + + lcd_cleanscreen(); + + /* Drain RX queue before doing calibrate. */ + while (adc_request_point(pdev, &sTouchPoint) == RT_EOK); + + rt_thread_mdelay(100); + + /* Ready to calibrate */ + nu_draw_bots(sDispPoints[i].x, sDispPoints[i].y); + +#define DEF_MAX_GET_POINT_NUM 5 + + sADCPoints[i].x = 0; + sADCPoints[i].y = 0; + + while (count < DEF_MAX_GET_POINT_NUM) + { + if (adc_request_point(pdev, &sTouchPoint) == RT_EOK) + { + sADCPoints[i].x += (int32_t)sTouchPoint.x_coordinate; + sADCPoints[i].y += (int32_t)sTouchPoint.y_coordinate; + rt_kprintf("[%d %d] - Disp:[%d, %d] -> ADC:[%d, %d]\n", i, count, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + count++; + } + } + + sADCPoints[i].x = (int32_t)((float)sADCPoints[i].x / DEF_MAX_GET_POINT_NUM); + sADCPoints[i].y = (int32_t)((float)sADCPoints[i].y / DEF_MAX_GET_POINT_NUM); + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + + rt_thread_mdelay(300); + } + + lcd_cleanscreen(); + + /* Get calibration matrix. */ + if (nu_adc_cal_mat_get(&sDispPoints[0], &sADCPoints[0], &sCalMat) == 0) + { + /* Finally, update calibration matrix to drivers. */ + nu_adc_touch_update_calmat(&sCalMat); + + nu_adc_touch_writefile(&sCalMat, sizeof(sCalMat)); + + for (i = 0; i < DEF_CAL_POINT_NUM; i++) + { + rt_kprintf("[%d] - Disp:[%d, %d], ADC:[%d, %d]\n", i, sDispPoints[i].x, sDispPoints[i].y, sADCPoints[i].x, sADCPoints[i].y); + } + } + else + { + rt_kprintf("Failed to calibrate.\n"); + } + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWEROFF, RT_NULL); + rt_device_close(lcd_device); + + return; +} + +static void adc_touch_entry(void *parameter) +{ + struct rt_touch_data touch_point; + + rt_err_t result; + rt_device_t pdev; + + int max_range; + + adc_touch_sem = rt_sem_create("adc_touch_sem", 0, RT_IPC_FLAG_FIFO); + RT_ASSERT(adc_touch_sem != RT_NULL); + + pdev = rt_device_find("adc_touch"); + if (!pdev) + { + rt_kprintf("Not found\n"); + return ; + } + + nu_adc_touch_readfile(); + + result = rt_device_open(pdev, RT_DEVICE_FLAG_INT_RX); + RT_ASSERT(result == RT_EOK); + + result = rt_device_set_rx_indicate(pdev, adc_touch_rx_callback); + RT_ASSERT(result == RT_EOK); + + max_range = BSP_LCD_WIDTH; + result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_X_RANGE, (void *)&max_range); + RT_ASSERT(result == RT_EOK); + + max_range = BSP_LCD_HEIGHT; + result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); + RT_ASSERT(result == RT_EOK); + + result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_ON, RT_NULL); + RT_ASSERT(result == RT_EOK); + + while (adc_touch_worker_run) + { + if (!g_u32Calibrated) + { + rt_kprintf("Start ADC touching calibration.\n"); + nu_touch_do_calibration(pdev); + rt_kprintf("Stop ADC touching calibration.\n"); + continue; + } + + if (adc_request_point(pdev, &touch_point) == RT_EOK) + { + if (touch_point.event == RT_TOUCH_EVENT_DOWN + || touch_point.event == RT_TOUCH_EVENT_UP + || touch_point.event == RT_TOUCH_EVENT_MOVE) + { + nu_touch_inputevent_cb(touch_point.x_coordinate, touch_point.y_coordinate, touch_point.event); + + rt_kprintf("x=%d y=%d event=%s%s%s\n", + touch_point.x_coordinate, + touch_point.y_coordinate, + (touch_point.event == RT_TOUCH_EVENT_DOWN) ? "DOWN" : "", + (touch_point.event == RT_TOUCH_EVENT_UP) ? "UP" : "", + (touch_point.event == RT_TOUCH_EVENT_MOVE) ? "MOVE" : ""); + } + } + } + + result = rt_device_control(pdev, RT_TOUCH_CTRL_POWER_OFF, RT_NULL); + RT_ASSERT(result == RT_EOK); + + result = rt_device_close(pdev); + RT_ASSERT(result == RT_EOK); +} + + +/* Support "nu_touch_start" command line in msh mode */ +static rt_err_t nu_touch_start(int argc, char **argv) +{ + if (adc_touch_thread == RT_NULL) + { + adc_touch_thread = rt_thread_create("adc_touch_thread", + adc_touch_entry, + RT_NULL, + 4096, + 25, + 5); + adc_touch_worker_run = 1; + if (adc_touch_thread != RT_NULL) + rt_thread_startup(adc_touch_thread); + } + return 0; +} +MSH_CMD_EXPORT(nu_touch_start, e.g: start adc touch); + +/* Support "nu_touch_stop" command line in msh mode */ +static rt_err_t nu_touch_stop(int argc, char **argv) +{ + adc_touch_worker_run = 0; + adc_touch_thread = RT_NULL; + return 0; +} +MSH_CMD_EXPORT(nu_touch_stop, e.g: stop adc touch); + +static int nu_touch_autostart(void) +{ + return nu_touch_start(0, RT_NULL); +} +INIT_APP_EXPORT(nu_touch_autostart); + +static rt_err_t nu_touch_calibration(int argc, char **argv) +{ + /* Clean calibration matrix data for getting raw adc value. */ + nu_adc_touch_reset_calmat(); + + return 0; +} +MSH_CMD_EXPORT(nu_touch_calibration, for adc touch); + +#endif //#if defined(BSP_USING_ADC_TOUCH) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c index 3b48867bb2..fcdbbe8d74 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_can.c @@ -64,6 +64,7 @@ struct nu_can IRQn_Type irqn; E_SYS_IPRST rstidx; E_SYS_IPCLK clkidx; + uint32_t int_flag; }; typedef struct nu_can *nu_can_t; @@ -130,16 +131,16 @@ static const struct can_configure nu_can_default_config = NU_CAN_CONFIG_DEFAULT; /* Interrupt Handle Function ----------------------------------------------------*/ static void nu_can_isr(int vector, void *param) { - uint32_t u32IIDRstatus; nu_can_t psNuCAN = (nu_can_t)param; /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; /* Get interrupt event */ - u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base); + uint32_t u32IIDRstatus = CAN_GET_INT_PENDING_STATUS(base) & CAN_IIDR_INTID_Msk; - if (u32IIDRstatus == 0x00008000) /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + /* Check Status Interrupt Flag (Error status Int and Status change Int) */ + if (u32IIDRstatus == 0x00008000) { /**************************/ /* Status Change interrupt*/ @@ -147,20 +148,24 @@ static void nu_can_isr(int vector, void *param) if (base->STATUS & CAN_STATUS_TXOK_Msk) { base->STATUS &= ~CAN_STATUS_TXOK_Msk; /* Clear Tx Ok status*/ - //rt_kprintf("%s: TX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); + } #endif } if (base->STATUS & CAN_STATUS_RXOK_Msk) { base->STATUS &= ~CAN_STATUS_RXOK_Msk; /* Clear Rx Ok status*/ - //rt_kprintf("%s: RX\n", psNuCAN->name) ; #ifndef RT_CAN_USING_HDR - /* Using as Lisen,Loopback,Loopback+Lisen mode*/ - rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) + { + /*Using as Lisen,Loopback,Loopback+Lisen mode*/ + rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_RX_IND); + } #endif } @@ -169,17 +174,16 @@ static void nu_can_isr(int vector, void *param) /**************************/ if (base->STATUS & CAN_STATUS_EWARN_Msk) { - rt_kprintf("%s: EWARN\n", psNuCAN->name) ; + rt_kprintf("[%s]EWARN INT\n", psNuCAN->name) ; } if (base->STATUS & CAN_STATUS_BOFF_Msk) { - rt_kprintf("%s: BUSOFF\n", psNuCAN->name) ; + rt_kprintf("[%s]BUSOFF INT\n", psNuCAN->name) ; - /* Do Init to release busoff pin */ - base->CON = (CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); - base->CON &= (~(CAN_CON_INIT_Msk | CAN_CON_CCE_Msk)); - while (base->CON & CAN_CON_INIT_Msk); + /* To release busoff pin */ + CAN_EnterInitMode(base, CAN_CON_INIT_Msk | CAN_CON_CCE_Msk); + CAN_LeaveInitMode(base); } if (base->STATUS & CAN_STATUS_LEC_Msk) @@ -192,66 +196,83 @@ static void nu_can_isr(int vector, void *param) /*IntId: 0x0001-0x0020, Number of Message Object which caused the interrupt.*/ else if (u32IIDRstatus > 0 && u32IIDRstatus <= 32) { - /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ - if (u32IIDRstatus <= RX_MSG_ID_INDEX) + if ((psNuCAN->int_flag & RT_DEVICE_FLAG_INT_TX) && + (u32IIDRstatus <= RX_MSG_ID_INDEX)) { - //rt_kprintf("[%s-Tx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM 0~RX_MSG_ID_INDEX for CAN Tx using*/ rt_hw_can_isr(&psNuCAN->dev, RT_CAN_EVENT_TX_DONE); } - else /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ + else if (psNuCAN->int_flag & RT_DEVICE_FLAG_INT_RX) { - //rt_kprintf("[%s-Rx]IntId = %d\n", psNuCAN->name, u32IIDRstatus); + /*Message RAM RX_MSG_ID_INDEX~31 for CAN Rx using*/ rt_hw_can_isr(&psNuCAN->dev, (RT_CAN_EVENT_RX_IND | ((u32IIDRstatus - 1) << 8))); } CAN_CLR_INT_PENDING_BIT(base, (u32IIDRstatus - 1)); /* Clear Interrupt Pending */ } #endif - } +static void nu_can_ie(nu_can_t psNuCAN) +{ + uint32_t u32CanIE = CAN_CON_IE_Msk; + + if (psNuCAN->int_flag & (RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX)) + { + u32CanIE |= CAN_CON_SIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_SIE_Msk; + } + + if (psNuCAN->int_flag & RT_DEVICE_CAN_INT_ERR) + { + u32CanIE |= CAN_CON_EIE_Msk; + } + else + { + u32CanIE &= ~CAN_CON_EIE_Msk; + } + + if (u32CanIE & (CAN_CON_SIE_Msk | CAN_CON_EIE_Msk)) + { + CAN_EnableInt(psNuCAN->base, u32CanIE); + + /* Enable interrupt. */ + rt_hw_interrupt_umask(psNuCAN->irqn); + } + else + { + u32CanIE |= (CAN_CON_IE_Msk | CAN_CON_SIE_Msk); + CAN_DisableInt(psNuCAN->base, u32CanIE); + + /* Disable interrupt. */ + rt_hw_interrupt_mask(psNuCAN->irqn); + } +} static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure *cfg) { nu_can_t psNuCAN = (nu_can_t)can; + uint32_t u32CANMode; - RT_ASSERT(can != RT_NULL); - RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(cfg); /* Get base address of CAN register */ CAN_T *base = psNuCAN->base; - RT_ASSERT(base != RT_NULL); - - switch (cfg->mode) - { - /* CAN default Normal mode */ - case RT_CAN_MODE_NORMAL: - can->config.mode = CAN_NORMAL_MODE; - break; - case RT_CAN_MODE_LISEN: - can->config.mode = RT_CAN_MODE_LISEN; - break; - case RT_CAN_MODE_LOOPBACK: - can->config.mode = RT_CAN_MODE_LOOPBACK; - break; - case RT_CAN_MODE_LOOPBACKANLISEN: - can->config.mode = RT_CAN_MODE_LOOPBACKANLISEN; - break; - default: - rt_kprintf("Unsupported Operating mode"); - goto exit_nu_can_configure; - } - + /* Reset this module */ nu_sys_ip_reset(psNuCAN->rstidx); - /*Set the CAN Bit Rate and Operating mode*/ - if (CAN_Open(base, can->config.baud_rate, can->config.mode) < 1) - return -(RT_ERROR); + u32CANMode = (cfg->mode == RT_CAN_MODE_NORMAL) ? CAN_NORMAL_MODE : CAN_BASIC_MODE; + /*Set the CAN Bit Rate and Operating mode*/ + if (CAN_Open(base, cfg->baud_rate, u32CANMode) != cfg->baud_rate) + goto exit_nu_can_configure; switch (cfg->mode) { - /* CAN default Normal mode */ case RT_CAN_MODE_NORMAL: #ifdef RT_CAN_USING_HDR CAN_LeaveTestMode(base); @@ -273,6 +294,7 @@ static rt_err_t nu_can_configure(struct rt_can_device *can, struct can_configure goto exit_nu_can_configure; } + nu_can_ie(psNuCAN); return RT_EOK; @@ -285,73 +307,33 @@ exit_nu_can_configure: static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) { - rt_uint32_t argval; - nu_can_t psNuCAN = (nu_can_t)can; + rt_uint32_t argval = (rt_uint32_t)arg; + nu_can_t psNuCAN = (nu_can_t)can; -#ifdef RT_CAN_USING_HDR - struct rt_can_filter_config *filter_cfg; -#endif - /* Get base address of CAN register */ - CAN_T *base = psNuCAN->base; - - RT_ASSERT(base != RT_NULL); - /* Check baud rate */ - RT_ASSERT(can->config.baud_rate != 0); + RT_ASSERT(can); switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - argval = (rt_uint32_t) arg; - if ((argval == RT_DEVICE_FLAG_INT_RX) || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Disable NVIC interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Status Change Interrupt */ - CAN_DisableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Disable interrupt. */ - rt_hw_interrupt_mask(psNuCAN->irqn); - - /* Disable Error Interrupt */ - CAN_DisableInt(base, CAN_CON_EIE_Msk); - } - break; - case RT_DEVICE_CTRL_SET_INT: - argval = (rt_uint32_t) arg; - if (argval == RT_DEVICE_FLAG_INT_RX || (argval == RT_DEVICE_FLAG_INT_TX)) - { - /* Enable Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } - else if (argval == RT_DEVICE_CAN_INT_ERR) - { - /* Enable Error Status and Status Change Interrupt */ - CAN_EnableInt(base, CAN_CON_IE_Msk | CAN_CON_SIE_Msk | CAN_CON_EIE_Msk); - - /* Enable interrupt. */ - rt_hw_interrupt_umask(psNuCAN->irqn); - } + psNuCAN->int_flag |= argval; + nu_can_ie(psNuCAN); + break; + + case RT_DEVICE_CTRL_CLR_INT: + psNuCAN->int_flag &= ~argval; + nu_can_ie(psNuCAN); break; -#ifdef RT_CAN_USING_HDR case RT_CAN_CMD_SET_FILTER: - filter_cfg = (struct rt_can_filter_config *)arg; + { + struct rt_can_filter_config *filter_cfg = (struct rt_can_filter_config *)arg; for (int i = 0; i < filter_cfg->count; i++) { - /*set the filter message object*/ if (filter_cfg->items[i].mode == 1) { - if (CAN_SetRxMsgObjAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) + if (CAN_SetRxMsgObjAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask, FALSE) == FALSE) { return -(RT_ERROR); } @@ -359,46 +341,61 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) else { /*set the filter message object*/ - if (CAN_SetRxMsgAndMsk(base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) + if (CAN_SetRxMsgAndMsk(psNuCAN->base, MSG(filter_cfg->items[i].hdr + RX_MSG_ID_INDEX), filter_cfg->items[i].ide, filter_cfg->items[i].id, filter_cfg->items[i].mask) == FALSE) { return -(RT_ERROR); } } } - break; -#endif + } + break; case RT_CAN_CMD_SET_MODE: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_NORMAL && argval != RT_CAN_MODE_LISEN && - argval != RT_CAN_MODE_LOOPBACK && argval != RT_CAN_MODE_LOOPBACKANLISEN) + if ((argval == RT_CAN_MODE_NORMAL) || + (argval == RT_CAN_MODE_LISEN) || + (argval == RT_CAN_MODE_LOOPBACK) || + (argval == RT_CAN_MODE_LOOPBACKANLISEN)) + { + if (argval != can->config.mode) + { + can->config.mode = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.mode) - { - can->config.mode = argval; - return nu_can_configure(can, &can->config); - } break; case RT_CAN_CMD_SET_BAUD: - argval = (rt_uint32_t) arg; - if (argval != CAN1MBaud && argval != CAN800kBaud && argval != CAN500kBaud && argval != CAN250kBaud && - argval != CAN125kBaud && argval != CAN100kBaud && argval != CAN50kBaud && argval != CAN20kBaud && argval != CAN10kBaud) + { + if ((argval == CAN1MBaud) || + (argval == CAN800kBaud) || + (argval == CAN500kBaud) || + (argval == CAN250kBaud) || + (argval == CAN125kBaud) || + (argval == CAN100kBaud) || + (argval == CAN50kBaud) || + (argval == CAN20kBaud) || + (argval == CAN10kBaud)) + { + if (argval != can->config.baud_rate) + { + can->config.baud_rate = argval; + return nu_can_configure(can, &can->config); + } + } + else { return -(RT_ERROR); } - if (argval != can->config.baud_rate) - { - can->config.baud_rate = argval; - return nu_can_configure(can, &can->config); - } - break; + } + break; case RT_CAN_CMD_SET_PRIV: - argval = (rt_uint32_t) arg; - if (argval != RT_CAN_MODE_PRIV && argval != RT_CAN_MODE_NOPRIV) + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) { return -(RT_ERROR); } @@ -411,16 +408,23 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) case RT_CAN_CMD_GET_STATUS: { - rt_uint32_t errtype; - errtype = base->ERR; - /*Receive Error Counter*/ + rt_uint32_t errtype = psNuCAN->base->ERR; + + RT_ASSERT(arg); + + /*Receive Error Counter, return value is with Receive Error Passive.*/ can->status.rcverrcnt = (errtype >> 8); + /*Transmit Error Counter*/ - can->status.snderrcnt = ((errtype >> 24) & 0xFF); - can->status.lasterrtype = CAN_GET_INT_STATUS(base) & 0x8000; - /*status error code*/ - can->status.errcode = CAN_GET_INT_STATUS(base) & 0x07; - rt_memcpy(arg, &can->status, sizeof(can->status)); + can->status.snderrcnt = (errtype & 0xFF); + + /*Last Error Type*/ + can->status.lasterrtype = CAN_GET_INT_STATUS(psNuCAN->base) & 0x8000; + + /*Status error code*/ + can->status.errcode = CAN_GET_INT_STATUS(psNuCAN->base) & 0x07; + + rt_memcpy(arg, &can->status, sizeof(struct rt_can_status)); } break; @@ -435,64 +439,91 @@ static rt_err_t nu_can_control(struct rt_can_device *can, int cmd, void *arg) static int nu_can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + RT_ASSERT(can); + RT_ASSERT(buf); - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + pmsg = (struct rt_can_msg *) buf; - /* Check the parameters */ - RT_ASSERT(IS_CAN_DLC(pmsg->len)); - - /* Standard ID (11 bits)*/ - if (pmsg->ide == RT_CAN_STDID) + if (pmsg->ide == RT_CAN_STDID && IS_CAN_STDID(pmsg->id)) { + /* Standard ID (11 bits)*/ tMsg.IdType = CAN_STD_ID; - RT_ASSERT(IS_CAN_STDID(pmsg->id)) tMsg.Id = pmsg->id ; } - else + else if (pmsg->ide == RT_CAN_EXTID && IS_CAN_EXTID(pmsg->id)) { /* Extended ID (29 bits)*/ tMsg.IdType = CAN_EXT_ID; - RT_ASSERT(IS_CAN_EXTID(pmsg->id)); tMsg.Id = pmsg->id ; } + else + { + goto exit_nu_can_sendmsg; + } if (pmsg->rtr == RT_CAN_DTR) { /* Data frame */ tMsg.FrameType = CAN_DATA_FRAME; } - else + else if (pmsg->rtr == RT_CAN_RTR) { /* Remote frame */ tMsg.FrameType = CAN_REMOTE_FRAME; } - tMsg.DLC = pmsg->len; - rt_memcpy(tMsg.Data, pmsg->data, pmsg->len); - - if (CAN_Transmit(base, MSG(boxno), &tMsg) == FALSE) // Configure Msg RAM and send the Msg in the RAM + else { - return -(RT_ERROR); + goto exit_nu_can_sendmsg; + } + + /* Check the parameters */ + if (IS_CAN_DLC(pmsg->len)) + { + tMsg.DLC = pmsg->len; + } + else + { + goto exit_nu_can_sendmsg; + } + + if (pmsg->data && pmsg->len) + { + rt_memcpy(&tMsg.Data[0], pmsg->data, pmsg->len); + } + else + { + goto exit_nu_can_sendmsg; + } + + /* Configure Msg RAM and send the Msg in the RAM. */ + if (CAN_Transmit(psNuCAN->base, MSG(boxno), &tMsg) == FALSE) + { + goto exit_nu_can_sendmsg; } return RT_EOK; + +exit_nu_can_sendmsg: + + return -(RT_ERROR); } + static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxno) { STR_CANMSG_T tMsg; - struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; - /* Get base address of CAN register */ - CAN_T *base = ((nu_can_t)can)->base; + struct rt_can_msg *pmsg; + nu_can_t psNuCAN = (nu_can_t)can; - RT_ASSERT(base != RT_NULL); - RT_ASSERT(buf != RT_NULL); + RT_ASSERT(can); + RT_ASSERT(buf); + + pmsg = (struct rt_can_msg *) buf; /* get data */ - if (CAN_Receive(base, boxno, &tMsg) == FALSE) + if (CAN_Receive(psNuCAN->base, boxno, &tMsg) == FALSE) { rt_kprintf("No available RX Msg.\n"); return -(RT_ERROR); @@ -504,32 +535,13 @@ static int nu_can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t boxn can->hdr[pmsg->hdr].connected = 1; #endif - /* Standard ID (11 bits)*/ - if (tMsg.IdType == CAN_STD_ID) - { - pmsg->ide = RT_CAN_STDID; - pmsg->id = tMsg.Id; - } - else /* Extended ID (29 bits)*/ - { - pmsg->ide = RT_CAN_EXTID; - pmsg->id = tMsg.Id; - } - - if (tMsg.FrameType == CAN_DATA_FRAME) - { - /* Data frame */ - pmsg->rtr = RT_CAN_DTR; - } - else - { - /* Remote frame */ - pmsg->rtr = RT_CAN_RTR; - } - + pmsg->ide = (tMsg.IdType == CAN_STD_ID) ? RT_CAN_STDID : RT_CAN_EXTID; + pmsg->rtr = (tMsg.FrameType == CAN_DATA_FRAME) ? RT_CAN_DTR : RT_CAN_RTR; + pmsg->id = tMsg.Id; pmsg->len = tMsg.DLC ; - rt_memcpy(pmsg->data, tMsg.Data, pmsg->len); + if (pmsg->data && pmsg->len) + rt_memcpy(pmsg->data, &tMsg.Data[0], pmsg->len); return RT_EOK; } @@ -564,5 +576,4 @@ static int rt_hw_can_init(void) return (int)ret; } INIT_DEVICE_EXPORT(rt_hw_can_init); - #endif //#if defined(BSP_USING_CAN) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c index 252ca1e1ae..9e94e347ca 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_emac.c @@ -682,7 +682,7 @@ lwiperf_report(void *arg, enum lwiperf_report_type report_type, (int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec); } -void lwiperf_example_init(void) +void lwiperf_example_init(int argc, char **argv) { lwiperf_start_tcp_server_default(lwiperf_report, NULL); } diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c index 423740dfc0..89e80b662f 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_i2c.c @@ -118,7 +118,7 @@ static rt_err_t nu_i2c_bus_control(struct rt_i2c_bus_device *bus, rt_uint32_t u3 RT_ASSERT(bus != RT_NULL); nu_i2c = (nu_i2c_bus_t *) bus; - switch (RT_I2C_DEV_CTRL_CLK) + switch (u32Cmd) { case RT_I2C_DEV_CTRL_CLK: I2C_SetBusClockFreq(nu_i2c->I2C, u32Value); diff --git a/bsp/nuvoton/nk-980iot/.config b/bsp/nuvoton/nk-980iot/.config index fa6f45f046..1339d389e1 100644 --- a/bsp/nuvoton/nk-980iot/.config +++ b/bsp/nuvoton/nk-980iot/.config @@ -203,8 +203,7 @@ CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096 CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2 CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048 # CONFIG_RT_USING_SENSOR is not set -CONFIG_RT_USING_TOUCH=y -# CONFIG_RT_TOUCH_PIN_IRQ is not set +# CONFIG_RT_USING_TOUCH is not set CONFIG_RT_USING_HWCRYPTO=y CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto" CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16 @@ -550,17 +549,11 @@ CONFIG_PKG_NETUTILS_VER_NUM=0x10301 # # LVGL: powerful and easy-to-use embedded GUI library # -CONFIG_PKG_USING_LVGL=y -CONFIG_PKG_LVGL_PATH="/packages/multimedia/LVGL/LVGL" -# CONFIG_PKG_USING_LVGL_EXAMPLES is not set -CONFIG_PKG_USING_LVGL_V810=y +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LVGL_V810 is not set # CONFIG_PKG_USING_LVGL_LATEST_VERSION is not set -CONFIG_PKG_LVGL_VER="v8.1.0" -CONFIG_PKG_LVGL_VER_NUM=0x08010 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set -CONFIG_PKG_USING_LV_MUSIC_DEMO=y -CONFIG_PKG_LV_MUSIC_DEMO_PATH="/packages/multimedia/LVGL/lv_music_demo" -CONFIG_PKG_LV_MUSIC_DEMO_VER="v0.1.1" +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set # # u8g2: a monochrome graphic library @@ -597,6 +590,7 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -607,7 +601,6 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -658,6 +651,7 @@ CONFIG_PKG_WAVPLAYER_VER="latest" # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -783,6 +777,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -874,23 +869,8 @@ CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -CONFIG_NU_PKG_USING_NAU8822=y -# CONFIG_NU_PKG_USING_DA9062 is not set -CONFIG_NU_PKG_USING_ILI9341=y -CONFIG_NU_PKG_USING_ILI9341_SPI=y -# CONFIG_NU_PKG_USING_ILI9341_EBI is not set -CONFIG_NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER=y -CONFIG_NU_PKG_ILI9341_HORIZONTAL=y -CONFIG_NU_PKG_USING_SPINAND=y +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -913,6 +893,7 @@ CONFIG_BSP_USING_RTC=y CONFIG_NU_RTC_SUPPORT_IO_RW=y CONFIG_NU_RTC_SUPPORT_MSH_CMD=y CONFIG_BSP_USING_ADC=y +# CONFIG_BSP_USING_ADC_TOUCH is not set CONFIG_BSP_USING_TMR=y CONFIG_BSP_USING_TIMER=y CONFIG_BSP_USING_TMR0=y @@ -998,8 +979,20 @@ CONFIG_BOARD_USING_USB1_HOST=y # Board extended module drivers # # CONFIG_BOARD_USING_MAX31875 is not set -CONFIG_BOARD_USING_LCD_ILI9341=y -CONFIG_BOARD_USING_ILI9341_PIN_BACKLIGHT=103 -CONFIG_BOARD_USING_ILI9341_PIN_RESET=90 -CONFIG_BOARD_USING_ILI9341_PIN_DC=89 +# CONFIG_BOARD_USING_LCD_ILI9341 is not set # CONFIG_BOARD_USING_ESP8266 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +CONFIG_NU_PKG_USING_SPINAND=y +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." diff --git a/bsp/nuvoton/nk-980iot/Kconfig b/bsp/nuvoton/nk-980iot/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/nk-980iot/Kconfig +++ b/bsp/nuvoton/nk-980iot/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-980iot/board/Kconfig b/bsp/nuvoton/nk-980iot/board/Kconfig index 06547f567b..e623161d9e 100644 --- a/bsp/nuvoton/nk-980iot/board/Kconfig +++ b/bsp/nuvoton/nk-980iot/board/Kconfig @@ -72,6 +72,7 @@ menu "Hardware Drivers Config" config BOARD_USING_LCD_ILI9341 bool "LCD ILI9341 (over spi0)" select RT_USING_TOUCH + select BSP_USING_ADC_TOUCH select NU_PKG_USING_ILI9341 select NU_PKG_USING_ILI9341_SPI select NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER @@ -113,5 +114,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c index 97ab099cfa..0ab0bb1f71 100644 --- a/bsp/nuvoton/nk-980iot/board/nu_pin_init.c +++ b/bsp/nuvoton/nk-980iot/board/nu_pin_init.c @@ -57,8 +57,10 @@ static void nu_pin_i2c_init(void) /* I2C0: PA[0, 1] */ outpw(REG_SYS_GPA_MFPL, (inpw(REG_SYS_GPA_MFPL) & ~0x000000FF) | 0x00000033); +#if !defined(BSP_USING_ADC_TOUCH) /* I2C2: PB5, PB7 */ outpw(REG_SYS_GPB_MFPL, (inpw(REG_SYS_GPB_MFPL) & ~0xF0F00000) | 0x20200000); +#endif } diff --git a/bsp/nuvoton/nk-980iot/project.uvproj b/bsp/nuvoton/nk-980iot/project.uvproj deleted file mode 100644 index edb52cb8a3..0000000000 --- a/bsp/nuvoton/nk-980iot/project.uvproj +++ /dev/null @@ -1,1877 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\Objects\ - rtthread - 1 - 0 - 0 - 1 - 1 - .\Listings\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARM.DLL - -cAT91SAM9 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 0 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 6 - - - - - - - - - - - - - ..\libraries\nuc980\Script\NUC980xx61.ini - Segger\JLTAgdi.dll - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nu_packages\ILI9341;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\SPINAND;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - mtd_nand.c - 1 - ..\..\..\components\drivers\mtd\mtd_nand.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - - - - - - - - - - - Drivers - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - Libraries - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - LVGL-port - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_ili9341 - - - lcd_ili9341.c - 1 - ..\libraries\nu_packages\ILI9341\lcd_ili9341.c - - - - - ili9341_spi.c - 1 - ..\libraries\nu_packages\ILI9341\ili9341_spi.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - nu_pkgs_spinand - - - spinand.c - 1 - ..\libraries\nu_packages\SPINAND\spinand.c - - - - - drv_spinand.c - 1 - ..\libraries\nu_packages\SPINAND\drv_spinand.c - - - - - nuc980_usbhostlib - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/nk-980iot/project.uvprojx b/bsp/nuvoton/nk-980iot/project.uvprojx deleted file mode 100644 index 7d23d354b5..0000000000 --- a/bsp/nuvoton/nk-980iot/project.uvprojx +++ /dev/null @@ -1,1869 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - 0 - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARM.DLL - -cAT91SAM9260 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - ARM926EJ-S - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x20000000 - 0x800000 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x100000 - 0x8000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x20800000 - 0x1800000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 0 - 0x300000 - 0x1000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nu_packages\ILI9341;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\SPINAND;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - board - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - mtd_nand.c - 1 - ..\..\..\components\drivers\mtd\mtd_nand.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - - - - - - - - - - - Drivers - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - Libraries - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - LVGL-port - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_ili9341 - - - lcd_ili9341.c - 1 - ..\libraries\nu_packages\ILI9341\lcd_ili9341.c - - - - - ili9341_spi.c - 1 - ..\libraries\nu_packages\ILI9341\ili9341_spi.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - nu_pkgs_spinand - - - spinand.c - 1 - ..\libraries\nu_packages\SPINAND\spinand.c - - - - - drv_spinand.c - 1 - ..\libraries\nu_packages\SPINAND\drv_spinand.c - - - - - nuc980_usbhostlib - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/nk-980iot/rtconfig.h b/bsp/nuvoton/nk-980iot/rtconfig.h deleted file mode 100644 index b77df08b3f..0000000000 --- a/bsp/nuvoton/nk-980iot/rtconfig.h +++ /dev/null @@ -1,459 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 16 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_MEMHEAP -#define RT_MEMHEAP_FAST_MODE -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_ARM9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 16 -#define DFS_FILESYSTEM_TYPES_MAX 16 -#define DFS_FD_MAX 64 -#define RT_USING_DFS_MNTTABLE -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_CAN_USING_HDR -#define RT_USING_HWTIMER -#define RT_USING_CPUTIME -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_MTD_NAND -#define RT_MTD_NAND_DEBUG -#define RT_USING_RTC -#define RT_USING_ALARM -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_TOUCH -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_CDC -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_MSTORAGE -#define RT_VCOM_TASK_STK_SIZE 2048 -#define RT_CDC_RX_BUFSIZE 128 -#define RT_VCOM_SERNO "32021919830108" -#define RT_VCOM_SER_LEN 14 -#define RT_VCOM_TX_TIMEOUT 1000 -#define RT_USB_MSTORAGE_DISK_NAME "ramdisk1" - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP212 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.31.55" -#define RT_LWIP_GWADDR "192.168.31.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 16 -#define RT_LWIP_PBUF_NUM 256 -#define RT_LWIP_RAW_PCB_NUM 16 -#define RT_LWIP_UDP_PCB_NUM 16 -#define RT_LWIP_TCP_PCB_NUM 16 -#define RT_LWIP_TCP_SEG_NUM 64 -#define RT_LWIP_TCP_SND_BUF 16384 -#define RT_LWIP_TCP_WND 65535 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 256 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 256 -#define RT_LWIP_REASSEMBLY_FRAG -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define RT_LWIP_NETIF_LOOPBACK -#define LWIP_NETIF_LOOPBACK 1 -#define RT_LWIP_STATS -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_NETUTILS -#define PKG_NETUTILS_TFTP -#define PKG_NETUTILS_IPERF -#define PKG_NETUTILS_NTP -#define NTP_USING_AUTO_SYNC -#define NTP_AUTO_SYNC_FIRST_DELAY 30 -#define NTP_AUTO_SYNC_PERIOD 3600 -#define NETUTILS_NTP_HOSTNAME "0.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME2 "1.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME3 "2.tw.pool.ntp.org" -#define PKG_USING_NETUTILS_V131 -#define PKG_NETUTILS_VER_NUM 0x10301 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - -#define PKG_USING_LVGL -#define PKG_USING_LVGL_V810 -#define PKG_LVGL_VER_NUM 0x08010 -#define PKG_USING_LV_MUSIC_DEMO - -/* u8g2: a monochrome graphic library */ - -#define PKG_USING_WAVPLAYER -#define PKG_WP_USING_PLAY -#define PKG_WP_PLAY_DEVICE "sound0" -#define PKG_WP_USING_RECORD -#define PKG_WP_RECORD_DEVICE "sound0" -#define PKG_USING_WAVPLAYER_LATEST_VERSION - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_DFS_UFFS -#define RT_USING_DFS_UFFS -#define RT_UFFS_ECC_MODE_3 -#define RT_UFFS_ECC_MODE 3 -#define PKG_USING_DFS_UFFS_LATEST_VERSION -#define PKG_USING_RAMDISK -#define PKG_USING_RAMDISK_LATEST_VERSION - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define PKG_USING_OPTPARSE -#define PKG_USING_OPTPARSE_LATEST_VERSION - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO -#define NU_PKG_USING_NAU8822 -#define NU_PKG_USING_ILI9341 -#define NU_PKG_USING_ILI9341_SPI -#define NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER -#define NU_PKG_ILI9341_HORIZONTAL -#define NU_PKG_USING_SPINAND - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_NUC980 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_MMU -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define BSP_USING_GPIO -#define BSP_USING_EMAC -#define BSP_USING_EMAC0 -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_IO_RW -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_ADC -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TIMER0 -#define BSP_USING_TMR1 -#define BSP_USING_TIMER1 -#define BSP_USING_TMR2 -#define BSP_USING_TIMER2 -#define BSP_USING_TMR3 -#define BSP_USING_TIMER3 -#define BSP_USING_TMR4 -#define BSP_USING_TIMER4 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART1_TX_DMA -#define BSP_USING_UART1_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C0 -#define BSP_USING_I2C2 -#define BSP_USING_SDH -#define BSP_USING_SDH1 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define BSP_USING_PWM -#define BSP_USING_PWM0 -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0 -#define BSP_USING_SPI0_PDMA -#define BSP_USING_SPI1_NONE -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 4096 -#define BSP_USING_QSPI -#define BSP_USING_QSPI_PDMA -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI0_PDMA -#define BSP_USING_CRYPTO -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_USBH - -/* On-board Peripheral Drivers */ - -#define BSP_USING_CONSOLE -#define BOARD_USING_IP101GR -#define BOARD_USING_NAU8822 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPINAND -#define BOARD_USING_USB0_DEVICE_HOST -#define BOARD_USING_USB1_HOST - -/* Board extended module drivers */ - -#define BOARD_USING_LCD_ILI9341 -#define BOARD_USING_ILI9341_PIN_BACKLIGHT 103 -#define BOARD_USING_ILI9341_PIN_RESET 90 -#define BOARD_USING_ILI9341_PIN_DC 89 - -#endif diff --git a/bsp/nuvoton/nk-980iot/rtconfig.py b/bsp/nuvoton/nk-980iot/rtconfig.py index 1f8263adae..7412b89abf 100644 --- a/bsp/nuvoton/nk-980iot/rtconfig.py +++ b/bsp/nuvoton/nk-980iot/rtconfig.py @@ -85,4 +85,10 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' - POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file + POST_ACTION += 'fromelf -z $TARGET\n' +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuvoton/nk-980iot/spinor.config b/bsp/nuvoton/nk-980iot/spinor.config index d93d276436..689099bb5b 100644 --- a/bsp/nuvoton/nk-980iot/spinor.config +++ b/bsp/nuvoton/nk-980iot/spinor.config @@ -7,6 +7,7 @@ # RT-Thread Kernel # CONFIG_RT_NAME_MAX=16 +# CONFIG_RT_USING_BIG_ENDIAN is not set # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_ALIGN_SIZE=4 @@ -17,10 +18,19 @@ CONFIG_RT_THREAD_PRIORITY_MAX=32 CONFIG_RT_TICK_PER_SECOND=1000 CONFIG_RT_USING_OVERFLOW_CHECK=y CONFIG_RT_USING_HOOK=y +CONFIG_RT_HOOK_USING_FUNC_PTR=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=2048 # CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set +# CONFIG_RT_USING_TINY_FFS is not set +# CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -48,13 +58,18 @@ CONFIG_RT_USING_SIGNALS=y # Memory Management # CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_MEMHEAP=y -# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_MEMHEAP=y +CONFIG_RT_MEMHEAP_FAST_MODE=y +# CONFIG_RT_MEMHEAP_BSET_MODE is not set +CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +# CONFIG_RT_USING_SLAB_AS_HEAP is not set # CONFIG_RT_USING_USERHEAP is not set +# CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_MEMTRACE=y +# CONFIG_RT_USING_HEAP_ISR is not set CONFIG_RT_USING_HEAP=y # @@ -66,7 +81,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40003 +CONFIG_RT_VER_NUM=0x40100 CONFIG_ARCH_ARM=y # CONFIG_RT_USING_CPU_FFS is not set CONFIG_ARCH_ARM_ARM9=y @@ -79,6 +94,7 @@ CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 +# CONFIG_RT_USING_LEGACY is not set # # C++ features @@ -89,25 +105,26 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # Command shell # CONFIG_RT_USING_FINSH=y +CONFIG_RT_USING_MSH=y +CONFIG_FINSH_USING_MSH=y CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=5 CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set -CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 -CONFIG_FINSH_CMD_SIZE=80 # CONFIG_FINSH_USING_AUTH is not set -CONFIG_FINSH_USING_MSH=y -CONFIG_FINSH_USING_MSH_DEFAULT=y -# CONFIG_FINSH_USING_MSH_ONLY is not set CONFIG_FINSH_ARG_MAX=10 # # Device virtual file system # CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FILESYSTEMS_MAX=16 CONFIG_DFS_FILESYSTEM_TYPES_MAX=16 @@ -125,27 +142,32 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y # CONFIG_RT_DFS_ELM_USE_LFN_2 is not set CONFIG_RT_DFS_ELM_USE_LFN_3=y CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y +# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set +CONFIG_RT_DFS_ELM_LFN_UNICODE=0 CONFIG_RT_DFS_ELM_MAX_LFN=255 CONFIG_RT_DFS_ELM_DRIVES=8 CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=4096 # CONFIG_RT_DFS_ELM_USE_ERASE is not set CONFIG_RT_DFS_ELM_REENTRANT=y +CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000 CONFIG_RT_USING_DFS_DEVFS=y # CONFIG_RT_USING_DFS_ROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set -# CONFIG_RT_USING_DFS_UFFS is not set -# CONFIG_RT_USING_DFS_JFFS2 is not set # CONFIG_RT_USING_DFS_NFS is not set # # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -CONFIG_RT_PIPE_BUFSZ=512 CONFIG_RT_USING_SYSTEM_WORKQUEUE=y CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y +CONFIG_RT_USING_SERIAL_V1=y +# CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=2048 CONFIG_RT_USING_CAN=y @@ -167,9 +189,6 @@ CONFIG_RT_USING_PWM=y CONFIG_RT_USING_RTC=y CONFIG_RT_USING_ALARM=y # CONFIG_RT_USING_SOFT_RTC is not set -CONFIG_RTC_SYNC_USING_NTP=y -CONFIG_RTC_NTP_FIRST_SYNC_DELAY=30 -CONFIG_RTC_NTP_SYNC_PERIOD=3600 # CONFIG_RT_USING_SDIO is not set CONFIG_RT_USING_SPI=y CONFIG_RT_USING_QSPI=y @@ -220,9 +239,11 @@ CONFIG_RT_HWCRYPTO_USING_RNG=y # # Using USB # +CONFIG_RT_USING_USB=y CONFIG_RT_USING_USB_HOST=y CONFIG_RT_USBH_MSTORAGE=y CONFIG_UDISK_MOUNTPOINT="/mnt/udisk" +# CONFIG_RT_USBH_HID is not set CONFIG_RT_USING_USB_DEVICE=y CONFIG_RT_USBD_THREAD_STACK_SZ=4096 CONFIG_USB_VENDOR_ID=0x0FFE @@ -247,14 +268,34 @@ CONFIG_RT_USB_MSTORAGE_DISK_NAME="ramdisk1" # # POSIX layer and C standard library # -CONFIG_RT_USING_LIBC=y -# CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_USING_POSIX=y -# CONFIG_RT_USING_POSIX_MMAP is not set -# CONFIG_RT_USING_POSIX_TERMIOS is not set -# CONFIG_RT_USING_POSIX_GETLINE is not set -# CONFIG_RT_USING_POSIX_AIO is not set # CONFIG_RT_USING_MODULE is not set +CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 + +# +# POSIX (Portable Operating System Interface) layer +# +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_STDIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y +# CONFIG_RT_USING_POSIX_TERMIOS is not set +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +# CONFIG_RT_USING_POSIX_DELAY is not set +# CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_PTHREADS is not set + +# +# Interprocess Communication (IPC) +# +# CONFIG_RT_USING_POSIX_PIPE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set +# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set + +# +# Socket is in the 'Network' category +# # # Network @@ -264,7 +305,7 @@ CONFIG_RT_USING_POSIX=y # Socket abstraction layer # CONFIG_RT_USING_SAL=y -CONFIG_SAL_INTERNET_CHECK=y +# CONFIG_SAL_INTERNET_CHECK is not set # # protocol stack implement @@ -290,8 +331,9 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP212 is not set +# CONFIG_RT_USING_LWIP202 is not set +# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP212=y # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 CONFIG_RT_LWIP_IGMP=y @@ -305,30 +347,30 @@ CONFIG_IP_SOF_BROADCAST_RECV=1 # # Static IPv4 Address # -CONFIG_RT_LWIP_IPADDR="192.168.1.30" -CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_IPADDR="192.168.31.55" +CONFIG_RT_LWIP_GWADDR="192.168.31.1" CONFIG_RT_LWIP_MSKADDR="255.255.255.0" CONFIG_RT_LWIP_UDP=y CONFIG_RT_LWIP_TCP=y CONFIG_RT_LWIP_RAW=y # CONFIG_RT_LWIP_PPP is not set -CONFIG_RT_MEMP_NUM_NETCONN=32 +CONFIG_RT_MEMP_NUM_NETCONN=16 CONFIG_RT_LWIP_PBUF_NUM=256 -CONFIG_RT_LWIP_RAW_PCB_NUM=32 -CONFIG_RT_LWIP_UDP_PCB_NUM=32 -CONFIG_RT_LWIP_TCP_PCB_NUM=32 -CONFIG_RT_LWIP_TCP_SEG_NUM=256 -CONFIG_RT_LWIP_TCP_SND_BUF=32768 -CONFIG_RT_LWIP_TCP_WND=10240 +CONFIG_RT_LWIP_RAW_PCB_NUM=16 +CONFIG_RT_LWIP_UDP_PCB_NUM=16 +CONFIG_RT_LWIP_TCP_PCB_NUM=16 +CONFIG_RT_LWIP_TCP_SEG_NUM=64 +CONFIG_RT_LWIP_TCP_SND_BUF=16384 +CONFIG_RT_LWIP_TCP_WND=65535 CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 -CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=32 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=256 CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=4096 # CONFIG_LWIP_NO_RX_THREAD is not set # CONFIG_LWIP_NO_TX_THREAD is not set CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 -CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024 -CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=32 -# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=4096 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=256 +CONFIG_RT_LWIP_REASSEMBLY_FRAG=y CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 CONFIG_LWIP_NETIF_LINK_CALLBACK=1 CONFIG_SO_REUSE=1 @@ -362,8 +404,15 @@ CONFIG_RT_LWIP_USING_PING=y CONFIG_RT_USING_UTEST=y CONFIG_UTEST_THR_STACK_SIZE=4096 CONFIG_UTEST_THR_PRIORITY=20 +# CONFIG_RT_USING_VAR_EXPORT is not set +# CONFIG_RT_USING_RT_LINK is not set # CONFIG_RT_USING_LWP is not set +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + # # RT-Thread online packages # @@ -411,22 +460,25 @@ CONFIG_PKG_NETUTILS_TFTP=y CONFIG_PKG_NETUTILS_IPERF=y # CONFIG_PKG_NETUTILS_NETIO is not set CONFIG_PKG_NETUTILS_NTP=y -CONFIG_NETUTILS_NTP_TIMEZONE=8 +CONFIG_NTP_USING_AUTO_SYNC=y +CONFIG_NTP_AUTO_SYNC_FIRST_DELAY=30 +CONFIG_NTP_AUTO_SYNC_PERIOD=3600 CONFIG_NETUTILS_NTP_HOSTNAME="0.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME2="1.tw.pool.ntp.org" CONFIG_NETUTILS_NTP_HOSTNAME3="2.tw.pool.ntp.org" # CONFIG_PKG_NETUTILS_TELNET is not set # CONFIG_PKG_NETUTILS_TCPDUMP is not set -CONFIG_PKG_USING_NETUTILS_V120=y -# CONFIG_PKG_USING_NETUTILS_V110 is not set -# CONFIG_PKG_USING_NETUTILS_V100 is not set # CONFIG_PKG_USING_NETUTILS_LATEST_VERSION is not set -CONFIG_PKG_NETUTILS_VER="v1.2.0" +CONFIG_PKG_USING_NETUTILS_V131=y +# CONFIG_PKG_USING_NETUTILS_V130 is not set +CONFIG_PKG_NETUTILS_VER="v1.3.1" +CONFIG_PKG_NETUTILS_VER_NUM=0x10301 # CONFIG_PKG_USING_CMUX is not set # CONFIG_PKG_USING_PPP_DEVICE is not set # CONFIG_PKG_USING_AT_DEVICE is not set # CONFIG_PKG_USING_ATSRV_SOCKET is not set # CONFIG_PKG_USING_WIZNET is not set +# CONFIG_PKG_USING_ZB_COORDINATOR is not set # # IoT Cloud @@ -439,6 +491,7 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_JIOT-C-SDK is not set # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set # CONFIG_PKG_USING_JOYLINK is not set +# CONFIG_PKG_USING_EZ_IOT_OS is not set # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set @@ -447,8 +500,6 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set # CONFIG_PKG_USING_DLT645 is not set # CONFIG_PKG_USING_QXWZ is not set # CONFIG_PKG_USING_SMTP_CLIENT is not set @@ -462,12 +513,26 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_PDULIB is not set # CONFIG_PKG_USING_BTSTACK is not set # CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set +# CONFIG_PKG_USING_AGILE_MODBUS is not set +# CONFIG_PKG_USING_AGILE_FTP is not set +# CONFIG_PKG_USING_EMBEDDEDPROTO is not set +# CONFIG_PKG_USING_RT_LINK_HW is not set +# CONFIG_PKG_USING_LORA_PKT_FWD is not set +# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set +# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set +# CONFIG_PKG_USING_HM is not set +# CONFIG_PKG_USING_SMALL_MODBUS is not set +# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_LIBSODIUM is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -475,21 +540,51 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # # language packages # +# CONFIG_PKG_USING_LUATOS_SOC is not set # CONFIG_PKG_USING_LUA is not set # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set +# CONFIG_PKG_USING_PIKASCRIPT is not set # # multimedia packages # + +# +# LVGL: powerful and easy-to-use embedded GUI library +# +# CONFIG_PKG_USING_LVGL is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set + +# +# u8g2: a monochrome graphic library +# +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set # CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_PDFGEN is not set # CONFIG_PKG_USING_HELIX is not set # CONFIG_PKG_USING_AZUREGUIX is not set # CONFIG_PKG_USING_TOUCHGFX2RTT is not set +# CONFIG_PKG_USING_NUEMWIN is not set +# CONFIG_PKG_USING_MP3PLAYER is not set +# CONFIG_PKG_USING_TINYJPEG is not set +# CONFIG_PKG_USING_UGUI is not set + +# +# PainterEngine: A cross-platform graphics application framework written in C language +# +# CONFIG_PKG_USING_PAINTERENGINE is not set +# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_TERMBOX is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -498,9 +593,11 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_EASYFLASH is not set # CONFIG_PKG_USING_EASYLOGGER is not set # CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set # CONFIG_PKG_USING_ADBD is not set # CONFIG_PKG_USING_COREMARK is not set # CONFIG_PKG_USING_DHRYSTONE is not set @@ -514,15 +611,72 @@ CONFIG_PKG_NETUTILS_VER="v1.2.0" # CONFIG_PKG_USING_UMCN is not set # CONFIG_PKG_USING_LWRB2RTT is not set # CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set +# CONFIG_PKG_USING_DEVMEM is not set +# CONFIG_PKG_USING_REGEX is not set +CONFIG_PKG_USING_MEM_SANDBOX=y +CONFIG_PKG_MEM_SANDBOX_PATH="/packages/tools/mem_sandbox" +CONFIG_PKG_USING_MEM_SANDBOX_LATEST_VERSION=y +CONFIG_PKG_MEM_SANDBOX_VER="latest" +# CONFIG_PKG_USING_SOLAR_TERMS is not set +# CONFIG_PKG_USING_GAN_ZHI is not set +# CONFIG_PKG_USING_FDT is not set # # system packages # + +# +# enhanced kernel services +# +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set + +# +# POSIX extension functions +# +# CONFIG_PKG_USING_POSIX_GETLINE is not set +# CONFIG_PKG_USING_POSIX_WCWIDTH is not set +# CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set + +# +# acceleration: Assembly language or algorithmic acceleration packages +# +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set + +# +# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard +# +# CONFIG_PKG_USING_CMSIS_5 is not set +# CONFIG_PKG_USING_CMSIS_RTOS2 is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_PERSIMMON is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set CONFIG_PKG_USING_FAL=y CONFIG_PKG_FAL_PATH="/packages/system/fal" @@ -542,10 +696,11 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set -# CONFIG_PKG_USING_LITTLEVGL2RTT is not set -# CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set +# CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_THREAD_POOL is not set # CONFIG_PKG_USING_ROBOTS is not set # CONFIG_PKG_USING_EV is not set @@ -559,17 +714,15 @@ CONFIG_PKG_USING_RAMDISK_LATEST_VERSION=y CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_MININI is not set # CONFIG_PKG_USING_QBOOT is not set - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UCOSII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set -# CONFIG_PKG_USING_UC_MODBUS is not set # CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set +# CONFIG_PKG_USING_EVENT_RECORDER is not set +# CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_MCUBOOT is not set +# CONFIG_PKG_USING_TINYUSB is not set +# CONFIG_PKG_USING_USB_STACK is not set # # peripheral libraries and drivers @@ -578,9 +731,9 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_U8G2 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set # CONFIG_PKG_USING_SX12XX is not set @@ -593,7 +746,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set -# CONFIG_PKG_USING_ROSSERIAL is not set # CONFIG_PKG_USING_AGILE_BUTTON is not set # CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set @@ -627,16 +779,73 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_STM32WB55_SDK is not set +# CONFIG_PKG_USING_RDA58XX is not set +# CONFIG_PKG_USING_LIBNFC is not set +# CONFIG_PKG_USING_MFOC is not set +# CONFIG_PKG_USING_TMC51XX is not set +# CONFIG_PKG_USING_TCA9534 is not set +# CONFIG_PKG_USING_KOBUKI is not set +# CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_MICRO_ROS is not set +# CONFIG_PKG_USING_MCP23008 is not set +# CONFIG_PKG_USING_BLUETRUM_SDK is not set +# CONFIG_PKG_USING_MISAKA_AT24CXX is not set +# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set +# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set +# CONFIG_PKG_USING_BL_MCU_SDK is not set +# CONFIG_PKG_USING_SOFT_SERIAL is not set +# CONFIG_PKG_USING_MB85RS16 is not set +# CONFIG_PKG_USING_CW2015 is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set +# CONFIG_PKG_USING_NAXOS is not set # # miscellaneous packages # + +# +# samples: kernel and components samples +# +# CONFIG_PKG_USING_KERNEL_SAMPLES is not set +# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set +# CONFIG_PKG_USING_NETWORK_SAMPLES is not set +# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set + +# +# entertainment: terminal games and other interesting software packages +# +# CONFIG_PKG_USING_CMATRIX is not set +# CONFIG_PKG_USING_SL is not set +# CONFIG_PKG_USING_CAL is not set +# CONFIG_PKG_USING_ACLOCK is not set +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_DONUT is not set +# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set CONFIG_PKG_USING_OPTPARSE=y CONFIG_PKG_OPTPARSE_PATH="/packages/misc/optparse" -CONFIG_PKG_USING_OPTPARSE_V100=y -# CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION is not set -CONFIG_PKG_OPTPARSE_VER="v1.0.0" +CONFIG_PKG_USING_OPTPARSE_LATEST_VERSION=y +CONFIG_PKG_OPTPARSE_VER="latest" # CONFIG_OPTPARSE_USING_DEMO is not set # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set @@ -646,69 +855,44 @@ CONFIG_PKG_OPTPARSE_VER="v1.0.0" # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_CANFESTIVAL is not set # CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_MINIZIP is not set # CONFIG_PKG_USING_DSTR is not set # CONFIG_PKG_USING_TINYFRAME is not set # CONFIG_PKG_USING_KENDRYTE_DEMO is not set # CONFIG_PKG_USING_DIGITALCTRL is not set # CONFIG_PKG_USING_UPACKER is not set # CONFIG_PKG_USING_UPARAM is not set - -# -# samples: kernel and components samples -# -# CONFIG_PKG_USING_KERNEL_SAMPLES is not set -# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set -# CONFIG_PKG_USING_NETWORK_SAMPLES is not set -# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set CONFIG_PKG_USING_VI=y CONFIG_PKG_VI_PATH="/packages/misc/vi" +CONFIG_VI_SANDBOX_SIZE_KB=20 CONFIG_VI_MAX_LEN=4096 # CONFIG_VI_ENABLE_8BIT is not set CONFIG_VI_ENABLE_COLON=y +CONFIG_VI_ENABLE_COLON_EXPAND=y CONFIG_VI_ENABLE_YANKMARK=y CONFIG_VI_ENABLE_SEARCH=y CONFIG_VI_ENABLE_DOT_CMD=y CONFIG_VI_ENABLE_READONLY=y CONFIG_VI_ENABLE_SETOPTS=y CONFIG_VI_ENABLE_SET=y +# CONFIG_VI_ENABLE_WIN_RESIZE is not set CONFIG_VI_ENABLE_VI_ASK_TERMINAL=y CONFIG_VI_ENABLE_UNDO=y CONFIG_VI_ENABLE_UNDO_QUEUE=y CONFIG_VI_UNDO_QUEUE_MAX=256 +CONFIG_VI_ENABLE_VERBOSE_STATUS=y CONFIG_PKG_USING_VI_LATEST_VERSION=y CONFIG_PKG_VI_VER="latest" # CONFIG_PKG_USING_KI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_VT100 is not set -# CONFIG_PKG_USING_ULAPACK is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set - -# -# games: games run on RT-Thread console -# -# CONFIG_PKG_USING_THREES is not set -# CONFIG_PKG_USING_2048 is not set -# CONFIG_PKG_USING_SNAKE is not set -# CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_LWGPS is not set -# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -CONFIG_NU_PKG_USING_NAU8822=y -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -718,12 +902,11 @@ CONFIG_NU_PKG_USING_NAU8822=y # On-chip Peripheral Drivers # CONFIG_SOC_SERIES_NUC980=y -# CONFIG_BSP_USE_STDDRIVER_SOURCE is not set +CONFIG_BSP_USE_STDDRIVER_SOURCE=y CONFIG_BSP_USING_MMU=y CONFIG_BSP_USING_PDMA=y CONFIG_NU_PDMA_MEMFUN_ACTOR_MAX=2 CONFIG_BSP_USING_GPIO=y -# CONFIG_BSP_USING_CLK is not set CONFIG_BSP_USING_EMAC=y CONFIG_BSP_USING_EMAC0=y # CONFIG_BSP_USING_EMAC1 is not set @@ -732,27 +915,23 @@ CONFIG_BSP_USING_RTC=y CONFIG_NU_RTC_SUPPORT_IO_RW=y CONFIG_NU_RTC_SUPPORT_MSH_CMD=y CONFIG_BSP_USING_ADC=y +# CONFIG_BSP_USING_ADC_TOUCH is not set CONFIG_BSP_USING_TMR=y CONFIG_BSP_USING_TIMER=y CONFIG_BSP_USING_TMR0=y CONFIG_BSP_USING_TIMER0=y -# CONFIG_BSP_USING_TPWM0 is not set # CONFIG_BSP_USING_TIMER0_CAPTURE is not set CONFIG_BSP_USING_TMR1=y CONFIG_BSP_USING_TIMER1=y -# CONFIG_BSP_USING_TPWM1 is not set # CONFIG_BSP_USING_TIMER1_CAPTURE is not set CONFIG_BSP_USING_TMR2=y CONFIG_BSP_USING_TIMER2=y -# CONFIG_BSP_USING_TPWM2 is not set # CONFIG_BSP_USING_TIMER2_CAPTURE is not set CONFIG_BSP_USING_TMR3=y CONFIG_BSP_USING_TIMER3=y -# CONFIG_BSP_USING_TPWM3 is not set # CONFIG_BSP_USING_TIMER3_CAPTURE is not set CONFIG_BSP_USING_TMR4=y CONFIG_BSP_USING_TIMER4=y -# CONFIG_BSP_USING_TPWM4 is not set # CONFIG_BSP_USING_TIMER4_CAPTURE is not set CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART0=y @@ -794,8 +973,9 @@ CONFIG_BSP_USING_SPI1_NONE=y CONFIG_BSP_USING_I2S=y CONFIG_NU_I2S_DMA_FIFO_SIZE=4096 CONFIG_BSP_USING_QSPI=y +# CONFIG_BSP_USING_QSPI_PDMA is not set CONFIG_BSP_USING_QSPI0=y -CONFIG_BSP_USING_QSPI0_PDMA=y +# CONFIG_BSP_USING_QSPI0_PDMA is not set # CONFIG_BSP_USING_SCUART is not set CONFIG_BSP_USING_CRYPTO=y # CONFIG_NU_PRNG_USE_SEED is not set @@ -823,5 +1003,18 @@ CONFIG_BOARD_USING_USB1_HOST=y # CONFIG_BOARD_USING_MAX31875 is not set # CONFIG_BOARD_USING_LCD_ILI9341 is not set # CONFIG_BOARD_USING_ESP8266 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk980-iot.test.utest." diff --git a/bsp/nuvoton/nk-n9h30/.config b/bsp/nuvoton/nk-n9h30/.config index d235edc087..5fc517cbdb 100644 --- a/bsp/nuvoton/nk-n9h30/.config +++ b/bsp/nuvoton/nk-n9h30/.config @@ -744,6 +744,7 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -832,19 +833,6 @@ CONFIG_PKG_RAMDISK_VER="latest" # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -# CONFIG_NU_PKG_USING_DEMO is not set -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -CONFIG_NU_PKG_USING_NAU8822=y -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set - # # Hardware Drivers Config # @@ -929,6 +917,7 @@ CONFIG_BSP_USING_VPOST=y # CONFIG_LCM_USING_LSA40AT9001 is not set CONFIG_LCM_USING_FW070TFT=y # CONFIG_LCM_USING_FW043TFT is not set +# CONFIG_LCM_USING_FW070TFT_WSVGA is not set CONFIG_VPOST_USING_LCD_IDX=3 CONFIG_BSP_LCD_BPP=32 CONFIG_BSP_LCD_WIDTH=800 @@ -946,10 +935,30 @@ CONFIG_BOARD_USING_NAU8822=y CONFIG_BOARD_USING_STORAGE_SDCARD=y CONFIG_BOARD_USING_STORAGE_SPIFLASH=y CONFIG_BOARD_USING_BUZZER=y -CONFIG_BOARD_USING_LCM=y CONFIG_BOARD_USING_USB0_DEVICE_HOST=y CONFIG_BOARD_USING_USB1_HOST=y # # Board extended module drivers # +CONFIG_BOARD_USING_LCM=y +CONFIG_BOARD_USING_LCM_FW070TFT_WVGA=y +# CONFIG_BOARD_USING_LCM_FW043TFT_HVGA is not set +# CONFIG_BOARD_USING_LCM_FW070TFT_WSVGA is not set +CONFIG_BOARD_USING_ADCTOUCH=y +# CONFIG_BOARD_USING_GT911 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +# CONFIG_NU_PKG_USING_DEMO is not set +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +CONFIG_NU_PKG_USING_NAU8822=y +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk-n9h30.test.utest." diff --git a/bsp/nuvoton/nk-n9h30/Kconfig b/bsp/nuvoton/nk-n9h30/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/nk-n9h30/Kconfig +++ b/bsp/nuvoton/nk-n9h30/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c index 266be12a31..3162bf8d2b 100644 --- a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c +++ b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c @@ -26,9 +26,30 @@ static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ static void *buf3_next = RT_NULL; +static uint32_t u32FirstFlush = 0; + +static void nu_antitearing(lv_disp_draw_buf_t *draw_buf, lv_color_t *color_p) +{ + if (buf3_next) + { + /* vsync-none: Use triple screen-sized buffers. */ + if (draw_buf->buf1 == color_p) + draw_buf->buf1 = buf3_next; + else + draw_buf->buf2 = buf3_next; + + draw_buf->buf_act = buf3_next; + buf3_next = color_p; + } + else + { + /* vsync-after: Use ping-pong screen-sized buffers only.*/ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + } +} + static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - lv_disp_t *psDisp = _lv_refr_get_disp_refreshing(); void *pvDstReDraw; #if (LV_USE_GPU_N9H30_GE2D==0) @@ -55,8 +76,14 @@ static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_c mmu_invalidate_dcache((uint32_t)pvDstReDraw, disp_drv->draw_buf->size * sizeof(lv_color_t)); #endif - /* WAIT_VSYNC */ - rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + nu_antitearing(disp_drv->draw_buf, color_p); + + if (!u32FirstFlush) + { + /* Enable backlight at first flushing. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + u32FirstFlush = 1; + } lv_disp_flush_ready(disp_drv); } @@ -70,21 +97,13 @@ static void nu_flush_full_refresh(lv_disp_drv_t *disp_drv, const lv_area_t *area /* Use PANDISPLAY without H/W copying */ rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, color_p); - if (buf3_next) - { - /* vsync-none: Use triple screen-sized buffers. */ - if (disp_drv->draw_buf->buf1 == color_p) - disp_drv->draw_buf->buf1 = buf3_next; - else - disp_drv->draw_buf->buf2 = buf3_next; + nu_antitearing(disp_drv->draw_buf, color_p); - disp_drv->draw_buf->buf_act = buf3_next; - buf3_next = color_p; - } - else + if (!u32FirstFlush) { - /* vsync-after: Use ping-pong screen-sized buffers only.*/ - rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); + /* Enable backlight at first flushing. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + u32FirstFlush = 1; } lv_disp_flush_ready(disp_drv); @@ -106,6 +125,13 @@ static void nu_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t ge2dSpriteBlt_Screen(area->x1, area->y1, flush_area_w, flush_area_h, (void *)color_p); // -> Leave GE2D + if (!u32FirstFlush) + { + /* Enable backlight at first flushing. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWERON, RT_NULL); + u32FirstFlush = 1; + } + lv_disp_flush_ready(disp_drv); } @@ -188,6 +214,9 @@ void lv_port_disp_init(void) return; } + /* Disable backlight at startup. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_POWEROFF, RT_NULL); + RT_ASSERT(info.bits_per_pixel == 8 || info.bits_per_pixel == 16 || info.bits_per_pixel == 24 || info.bits_per_pixel == 32); diff --git a/bsp/nuvoton/nk-n9h30/board/Kconfig b/bsp/nuvoton/nk-n9h30/board/Kconfig index c26e25fb65..379add6d0b 100644 --- a/bsp/nuvoton/nk-n9h30/board/Kconfig +++ b/bsp/nuvoton/nk-n9h30/board/Kconfig @@ -45,12 +45,6 @@ menu "Hardware Drivers Config" select BSP_USING_PWM0 default n - config BOARD_USING_LCM - bool "NuDesign TFT-LCD7(over vpost)" - select BSP_USING_VPOST - select LCM_USING_FW070TFT - default y - config BOARD_USING_USB0_DEVICE_HOST select BSP_USING_USBH select BSP_USING_USBD @@ -69,7 +63,61 @@ menu "Hardware Drivers Config" menu "Board extended module drivers" + config BOARD_USING_LCM + bool "Use LCD panel." + default y + + if BOARD_USING_LCM + + choice + prompt "Select LCD panel devices.(Over VPOST)" + default BOARD_USING_LCM_FW070TFT_WVGA + + config BOARD_USING_LCM_FW070TFT_WVGA + bool "NuDesign TFT-LCD7-WVGA" + select BSP_USING_VPOST + select LCM_USING_FW070TFT + help + Choose this option if you use 7" 800x480x32b LCD panel. + + config BOARD_USING_LCM_FW043TFT_HVGA + bool "NuDesign TFT-LCD43-HVGA" + select BSP_USING_VPOST + select LCM_USING_FW043TFT + help + Choose this option if you use 4.3" 480x272x32b LCD panel. + + config BOARD_USING_LCM_FW070TFT_WSVGA + bool "NuDesign TFT-LCD7-WSVGA" + select BSP_USING_VPOST + select LCM_USING_FW070TFT_WSVGA + help + Choose this option if you use 7" 1024x600x32b LCD panel. + endchoice + + choice + prompt "Select Touch devices." + default BOARD_USING_ADCTOUCH + + config BOARD_USING_ADCTOUCH + bool "ADC touching" + select BSP_USING_ADC_TOUCH + help + Choose this option if you use internal ADC touching function. + + config BOARD_USING_GT911 + bool "GT911 TSC" + select BSP_USING_I2C + select BSP_USING_I2C0 + select PKG_USING_GT911 + help + Choose this option if you use GT911 external TSC touching function. + endchoice + + endif + endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/nk-n9h30/board/board_dev.c b/bsp/nuvoton/nk-n9h30/board/board_dev.c index 42d1bdac94..ba21df17dd 100644 --- a/bsp/nuvoton/nk-n9h30/board/board_dev.c +++ b/bsp/nuvoton/nk-n9h30/board/board_dev.c @@ -173,6 +173,34 @@ int rt_hw_nau8822_port(void) INIT_COMPONENT_EXPORT(rt_hw_nau8822_port); #endif /* BOARD_USING_NAU8822 */ +//#if defined(BOARD_USING_GT911) && defined(PKG_USING_GT911) +#if defined(PKG_USING_GT911) +#include "drv_gpio.h" +#include "gt911.h" + +#define GT911_RST_PIN NU_GET_PININDEX(NU_PG, 4) +#define GT911_IRQ_PIN NU_GET_PININDEX(NU_PG, 5) + +extern int gt911_sample(const char *name, rt_uint16_t x, rt_uint16_t y); +int rt_hw_gt911_port(void) +{ + struct rt_touch_config cfg; + rt_uint8_t rst_pin; + + rst_pin = GT911_RST_PIN; + cfg.dev_name = "i2c0"; + cfg.irq_pin.pin = GT911_IRQ_PIN; + cfg.irq_pin.mode = PIN_MODE_INPUT_PULLDOWN; + cfg.user_data = &rst_pin; + + rt_hw_gt911_init("gt911", &cfg); + gt911_sample("gt911", BSP_LCD_WIDTH, BSP_LCD_HEIGHT); + + return 0; +} +INIT_ENV_EXPORT(rt_hw_gt911_port); +#endif /* if defined(BOARD_USING_GT911) && defined(PKG_USING_GT911) */ + #if defined(BOARD_USING_BUZZER) #define PWM_DEV_NAME "pwm0" @@ -224,13 +252,13 @@ static void PlayRingTone(void) #include /* defined the LCM_BLEN pin: PH3 */ - #define LCM_BLEN NU_GET_PININDEX(NU_PH, 3) + #define LCM_BACKLIGHT_CTRL NU_GET_PININDEX(NU_PH, 3) #endif -#define PWM_DEV_NAME "pwm0" -#define LCM_PWM_CHANNEL (0) +#define PWM_DEV_NAME "pwm0" +#define LCM_PWM_CHANNEL (0) -static void LCMLightOn(void) +void nu_lcd_backlight_on(void) { struct rt_device_pwm *pwm_dev; @@ -243,10 +271,27 @@ static void LCMLightOn(void) { rt_kprintf("Can't find %s\n", PWM_DEV_NAME); } + + rt_pin_mode(LCM_BACKLIGHT_CTRL, PIN_MODE_OUTPUT); + rt_pin_write(LCM_BACKLIGHT_CTRL, PIN_HIGH); +} + +void nu_lcd_backlight_off(void) +{ + struct rt_device_pwm *pwm_dev; + + if ((pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME)) != RT_NULL) + { + rt_pwm_disable(pwm_dev, LCM_PWM_CHANNEL); + } + else + { + rt_kprintf("Can't find %s\n", PWM_DEV_NAME); + } + + rt_pin_mode(LCM_BACKLIGHT_CTRL, PIN_MODE_OUTPUT); + rt_pin_write(LCM_BACKLIGHT_CTRL, PIN_LOW); } -#ifdef FINSH_USING_MSH - MSH_CMD_EXPORT(LCMLightOn, LCM - light on panel); -#endif int rt_hw_lcm_port(void) { @@ -259,9 +304,6 @@ int rt_hw_lcm_port(void) } #endif - /* Use PWM to control backlight. */ - LCMLightOn(); - return 0; } INIT_COMPONENT_EXPORT(rt_hw_lcm_port); diff --git a/bsp/nuvoton/nk-n9h30/project.uvproj b/bsp/nuvoton/nk-n9h30/project.uvproj deleted file mode 100644 index f3ff2ed8d7..0000000000 --- a/bsp/nuvoton/nk-n9h30/project.uvproj +++ /dev/null @@ -1,1791 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\Objects\ - rtthread - 1 - 0 - 0 - 1 - 1 - .\Listings\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARM.DLL - -cAT91SAM9 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 6 - - - - - - - - - - - - - ..\libraries\nuc980\Script\NUC980xx61.ini - Segger\JLTAgdi.dll - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\n9h30\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\n9h30\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\n9h30\UsbHostLib\inc;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - .\linking_scripts\n9h30.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - board_dev.c - 1 - board\board_dev.c - - - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - rt_inputcapture.c - 1 - ..\..\..\components\drivers\misc\rt_inputcapture.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_usbd.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbd.c - - - - - drv_timer.c - 1 - ..\libraries\n9h30\rtt_port\drv_timer.c - - - - - drv_vpost.c - 1 - ..\libraries\n9h30\rtt_port\drv_vpost.c - - - - - drv_adc.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc.c - - - - - drv_can.c - 1 - ..\libraries\n9h30\rtt_port\drv_can.c - - - - - drv_pwm.c - 1 - ..\libraries\n9h30\rtt_port\drv_pwm.c - - - - - drv_systick.c - 1 - ..\libraries\n9h30\rtt_port\drv_systick.c - - - - - drv_common.c - 1 - ..\libraries\n9h30\rtt_port\drv_common.c - - - - - drv_jpegcodec.c - 1 - ..\libraries\n9h30\rtt_port\drv_jpegcodec.c - - - - - drv_usbhost.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbhost.c - - - - - drv_emac.c - 1 - ..\libraries\n9h30\rtt_port\drv_emac.c - - - - - drv_scuart.c - 1 - ..\libraries\n9h30\rtt_port\drv_scuart.c - - - - - drv_adc_touch.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc_touch.c - - - - - drv_qspi.c - 1 - ..\libraries\n9h30\rtt_port\drv_qspi.c - - - - - drv_sys.c - 1 - ..\libraries\n9h30\rtt_port\drv_sys.c - - - - - drv_gpio.c - 1 - ..\libraries\n9h30\rtt_port\drv_gpio.c - - - - - drv_etimer.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\n9h30\rtt_port\drv_wdt.c - - - - - drv_ge2d.c - 1 - ..\libraries\n9h30\rtt_port\drv_ge2d.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer_capture.c - - - - - drv_uart.c - 1 - ..\libraries\n9h30\rtt_port\drv_uart.c - - - - - drv_i2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2c.c - - - - - drv_sdh.c - 1 - ..\libraries\n9h30\rtt_port\drv_sdh.c - - - - - drv_rtc.c - 1 - ..\libraries\n9h30\rtt_port\drv_rtc.c - - - - - drv_crypto.c - 1 - ..\libraries\n9h30\rtt_port\drv_crypto.c - - - - - drv_softi2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_softi2c.c - - - - - drv_i2s.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2s.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - Libraries - - - nu_timer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_timer.c - - - - - nu_emac.c - 1 - ..\libraries\n9h30\Driver\Source\nu_emac.c - - - - - nu_sys.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sys.c - - - - - nu_gpio.c - 1 - ..\libraries\n9h30\Driver\Source\nu_gpio.c - - - - - nu_wwdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wwdt.c - - - - - nu_etimer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_etimer.c - - - - - nu_spi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_spi.c - - - - - nu_can.c - 1 - ..\libraries\n9h30\Driver\Source\nu_can.c - - - - - nu_wdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wdt.c - - - - - nu_fmi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_fmi.c - - - - - nu_lcd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_lcd.c - - - - - nu_sdh.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sdh.c - - - - - nu_usbd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_usbd.c - - - - - nu_cap.c - 1 - ..\libraries\n9h30\Driver\Source\nu_cap.c - - - - - nu_scuart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_scuart.c - - - - - nu_i2s.c - 1 - ..\libraries\n9h30\Driver\Source\nu_i2s.c - - - - - nu_rtc.c - 1 - ..\libraries\n9h30\Driver\Source\nu_rtc.c - - - - - nu_pwm.c - 1 - ..\libraries\n9h30\Driver\Source\nu_pwm.c - - - - - nu_crypto.c - 1 - ..\libraries\n9h30\Driver\Source\nu_crypto.c - - - - - nu_uart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_uart.c - - - - - LVGL-port - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - n9h30_usbhostlib - - - ehci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci.c - - - - - ohci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ohci.c - - - - - mem_alloc.c - 1 - ..\libraries\n9h30\UsbHostLib\src\mem_alloc.c - - - - - ehci_iso.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci_iso.c - - - - - support.c - 1 - ..\libraries\n9h30\UsbHostLib\src\support.c - - - - - usb_core.c - 1 - ..\libraries\n9h30\UsbHostLib\src\usb_core.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - SAL - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/nk-n9h30/project.uvprojx b/bsp/nuvoton/nk-n9h30/project.uvprojx deleted file mode 100644 index 6dc5488c5c..0000000000 --- a/bsp/nuvoton/nk-n9h30/project.uvprojx +++ /dev/null @@ -1,1783 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - 0 - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARM.DLL - -cAT91SAM9260 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - ARM926EJ-S - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x20000000 - 0x800000 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x100000 - 0x8000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x20800000 - 0x1800000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 0 - 0x300000 - 0x1000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\touch;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\n9h30\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\n9h30\Driver\Include;applications\lvgl;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\n9h30\UsbHostLib\inc;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - - .\linking_scripts\n9h30.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - board - - - board_dev.c - 1 - board\board_dev.c - - - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - rt_inputcapture.c - 1 - ..\..\..\components\drivers\misc\rt_inputcapture.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - alarm.c - 1 - ..\..\..\components\drivers\rtc\alarm.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - touch.c - 1 - ..\..\..\components\drivers\touch\touch.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_common.c - 1 - ..\libraries\n9h30\rtt_port\drv_common.c - - - - - drv_can.c - 1 - ..\libraries\n9h30\rtt_port\drv_can.c - - - - - drv_emac.c - 1 - ..\libraries\n9h30\rtt_port\drv_emac.c - - - - - drv_timer.c - 1 - ..\libraries\n9h30\rtt_port\drv_timer.c - - - - - drv_pwm.c - 1 - ..\libraries\n9h30\rtt_port\drv_pwm.c - - - - - drv_usbd.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbd.c - - - - - drv_usbhost.c - 1 - ..\libraries\n9h30\rtt_port\drv_usbhost.c - - - - - drv_crypto.c - 1 - ..\libraries\n9h30\rtt_port\drv_crypto.c - - - - - drv_systick.c - 1 - ..\libraries\n9h30\rtt_port\drv_systick.c - - - - - drv_gpio.c - 1 - ..\libraries\n9h30\rtt_port\drv_gpio.c - - - - - drv_scuart.c - 1 - ..\libraries\n9h30\rtt_port\drv_scuart.c - - - - - drv_etimer.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\n9h30\rtt_port\drv_wdt.c - - - - - drv_adc.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc.c - - - - - drv_qspi.c - 1 - ..\libraries\n9h30\rtt_port\drv_qspi.c - - - - - drv_i2s.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2s.c - - - - - drv_sdh.c - 1 - ..\libraries\n9h30\rtt_port\drv_sdh.c - - - - - drv_i2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_i2c.c - - - - - drv_softi2c.c - 1 - ..\libraries\n9h30\rtt_port\drv_softi2c.c - - - - - drv_uart.c - 1 - ..\libraries\n9h30\rtt_port\drv_uart.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\n9h30\rtt_port\drv_etimer_capture.c - - - - - drv_vpost.c - 1 - ..\libraries\n9h30\rtt_port\drv_vpost.c - - - - - drv_adc_touch.c - 1 - ..\libraries\n9h30\rtt_port\drv_adc_touch.c - - - - - drv_rtc.c - 1 - ..\libraries\n9h30\rtt_port\drv_rtc.c - - - - - drv_sys.c - 1 - ..\libraries\n9h30\rtt_port\drv_sys.c - - - - - drv_jpegcodec.c - 1 - ..\libraries\n9h30\rtt_port\drv_jpegcodec.c - - - - - drv_ge2d.c - 1 - ..\libraries\n9h30\rtt_port\drv_ge2d.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - Libraries - - - nu_wwdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wwdt.c - - - - - nu_lcd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_lcd.c - - - - - nu_usbd.c - 1 - ..\libraries\n9h30\Driver\Source\nu_usbd.c - - - - - nu_i2s.c - 1 - ..\libraries\n9h30\Driver\Source\nu_i2s.c - - - - - nu_rtc.c - 1 - ..\libraries\n9h30\Driver\Source\nu_rtc.c - - - - - nu_pwm.c - 1 - ..\libraries\n9h30\Driver\Source\nu_pwm.c - - - - - nu_emac.c - 1 - ..\libraries\n9h30\Driver\Source\nu_emac.c - - - - - nu_sys.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sys.c - - - - - nu_spi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_spi.c - - - - - nu_etimer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_etimer.c - - - - - nu_timer.c - 1 - ..\libraries\n9h30\Driver\Source\nu_timer.c - - - - - nu_can.c - 1 - ..\libraries\n9h30\Driver\Source\nu_can.c - - - - - nu_fmi.c - 1 - ..\libraries\n9h30\Driver\Source\nu_fmi.c - - - - - nu_gpio.c - 1 - ..\libraries\n9h30\Driver\Source\nu_gpio.c - - - - - nu_wdt.c - 1 - ..\libraries\n9h30\Driver\Source\nu_wdt.c - - - - - nu_scuart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_scuart.c - - - - - nu_crypto.c - 1 - ..\libraries\n9h30\Driver\Source\nu_crypto.c - - - - - nu_uart.c - 1 - ..\libraries\n9h30\Driver\Source\nu_uart.c - - - - - nu_sdh.c - 1 - ..\libraries\n9h30\Driver\Source\nu_sdh.c - - - - - nu_cap.c - 1 - ..\libraries\n9h30\Driver\Source\nu_cap.c - - - - - LVGL-port - - - lv_port_disp.c - 1 - applications\lvgl\lv_port_disp.c - - - - - lv_port_indev.c - 1 - applications\lvgl\lv_port_indev.c - - - - - lv_demo.c - 1 - applications\lvgl\lv_demo.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - n9h30_usbhostlib - - - ohci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ohci.c - - - - - usb_core.c - 1 - ..\libraries\n9h30\UsbHostLib\src\usb_core.c - - - - - mem_alloc.c - 1 - ..\libraries\n9h30\UsbHostLib\src\mem_alloc.c - - - - - support.c - 1 - ..\libraries\n9h30\UsbHostLib\src\support.c - - - - - ehci.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\n9h30\UsbHostLib\src\ehci_iso.c - - - - - nu_pkgs_nau8822 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau8822.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau8822.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/nk-n9h30/rtconfig.h b/bsp/nuvoton/nk-n9h30/rtconfig.h deleted file mode 100644 index 1138f94322..0000000000 --- a/bsp/nuvoton/nk-n9h30/rtconfig.h +++ /dev/null @@ -1,422 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 16 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_MEMHEAP -#define RT_MEMHEAP_FAST_MODE -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_INTERRUPT_INFO -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_ARM9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 16 -#define DFS_FILESYSTEM_TYPES_MAX 16 -#define DFS_FD_MAX 64 -#define RT_USING_DFS_MNTTABLE -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_RTC -#define RT_USING_ALARM -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_USING_QSPI -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_TOUCH -#define RT_USING_INPUT_CAPTURE -#define RT_INPUT_CAPTURE_RB_SIZE 100 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_CDC -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_MSTORAGE -#define RT_VCOM_TASK_STK_SIZE 512 -#define RT_CDC_RX_BUFSIZE 128 -#define RT_VCOM_SERNO "32021919830108" -#define RT_VCOM_SER_LEN 14 -#define RT_VCOM_TX_TIMEOUT 1000 -#define RT_USB_MSTORAGE_DISK_NAME "ramdisk1" - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP202 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 32 -#define RT_LWIP_PBUF_NUM 256 -#define RT_LWIP_RAW_PCB_NUM 32 -#define RT_LWIP_UDP_PCB_NUM 32 -#define RT_LWIP_TCP_PCB_NUM 32 -#define RT_LWIP_TCP_SEG_NUM 256 -#define RT_LWIP_TCP_SND_BUF 32768 -#define RT_LWIP_TCP_WND 10240 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 32 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 32 -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define RT_LWIP_NETIF_LOOPBACK -#define LWIP_NETIF_LOOPBACK 1 -#define RT_LWIP_STATS -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - -#define PKG_USING_LVGL -#define PKG_USING_LVGL_V810 -#define PKG_LVGL_VER_NUM 0x08010 -#define PKG_USING_LV_MUSIC_DEMO - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define FAL_USING_SFUD_PORT -#define FAL_USING_NOR_FLASH_DEV_NAME "norflash0" -#define PKG_USING_FAL_LATEST_VERSION -#define PKG_FAL_VER_NUM 0x99999 -#define PKG_USING_RAMDISK -#define PKG_USING_RAMDISK_LATEST_VERSION - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_NAU8822 - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_N9H30 -#define BSP_USING_MMU -#define BSP_USING_GPIO -#define BSP_USING_EMAC -#define BSP_USING_EMAC0 -#define BSP_USING_EMAC1 -#define BSP_USING_RTC -#define BSP_USING_ADC -#define BSP_USING_ADC_TOUCH -#define BSP_USING_ETMR -#define BSP_USING_ETIMER -#define BSP_USING_ETIMER_CAPTURE -#define BSP_USING_ETMR0 -#define BSP_USING_ETIMER0 -#define BSP_USING_ETMR1 -#define BSP_USING_ETIMER1 -#define BSP_USING_ETMR2 -#define BSP_USING_ETIMER2_CAPTURE -#define BSP_USING_ETMR3 -#define BSP_USING_ETIMER3_CAPTURE -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TIMER0 -#define BSP_USING_TIMER1 -#define BSP_USING_TIMER2 -#define BSP_USING_TIMER3 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_I2C -#define BSP_USING_I2C0 -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define BSP_USING_SDH1 -#define NU_SDH_HOTPLUG -#define BSP_USING_CAN -#define BSP_USING_CAN0 -#define BSP_USING_PWM -#define BSP_USING_PWM0 -#define BSP_USING_QSPI -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI1_NONE -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 2048 -#define BSP_USING_WDT -#define BSP_USING_EBI -#define BSP_USING_VPOST -#define LCM_USING_FW070TFT -#define VPOST_USING_LCD_IDX 3 -#define BSP_LCD_BPP 32 -#define BSP_LCD_WIDTH 800 -#define BSP_LCD_HEIGHT 480 -#define BSP_USING_VPOST_OSD -#define BSP_USING_USBD -#define BSP_USING_USBH - -/* On-board Peripheral Drivers */ - -#define BSP_USING_CONSOLE -#define BOARD_USING_IP101GR -#define BOARD_USING_NAU8822 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_BUZZER -#define BOARD_USING_LCM -#define BOARD_USING_USB0_DEVICE_HOST -#define BOARD_USING_USB1_HOST - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/nk-n9h30/rtconfig.py b/bsp/nuvoton/nk-n9h30/rtconfig.py index 79a4da1d49..cdca30ea1a 100644 --- a/bsp/nuvoton/nk-n9h30/rtconfig.py +++ b/bsp/nuvoton/nk-n9h30/rtconfig.py @@ -85,4 +85,10 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' - POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file + POST_ACTION += 'fromelf -z $TARGET\n' +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuvoton/nk-rtu980/.config b/bsp/nuvoton/nk-rtu980/.config index 853e905aed..566468f589 100644 --- a/bsp/nuvoton/nk-rtu980/.config +++ b/bsp/nuvoton/nk-rtu980/.config @@ -974,3 +974,5 @@ CONFIG_BOARD_USING_USB0_DEVICE_HOST=y # Board extended module drivers # CONFIG_BOARD_USING_IP101GR=y +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.nk-rtu980.test.utest." diff --git a/bsp/nuvoton/nk-rtu980/Kconfig b/bsp/nuvoton/nk-rtu980/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/nk-rtu980/Kconfig +++ b/bsp/nuvoton/nk-rtu980/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/nk-rtu980/board/Kconfig b/bsp/nuvoton/nk-rtu980/board/Kconfig index 2682f8b89f..04cc595e7a 100644 --- a/bsp/nuvoton/nk-rtu980/board/Kconfig +++ b/bsp/nuvoton/nk-rtu980/board/Kconfig @@ -44,5 +44,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/nk-rtu980/project.uvproj b/bsp/nuvoton/nk-rtu980/project.uvproj deleted file mode 100644 index 9c0d498aed..0000000000 --- a/bsp/nuvoton/nk-rtu980/project.uvproj +++ /dev/null @@ -1,1774 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\Objects\ - rtthread - 1 - 0 - 0 - 1 - 1 - .\Listings\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARM.DLL - -cAT91SAM9 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 0 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 6 - - - - - - - - - - - - - ..\libraries\nuc980\Script\NUC980xx61.ini - Segger\JLTAgdi.dll - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - board - - - board_dev.c - 1 - board\board_dev.c - - - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - DeviceDrivers - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - Libraries - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nuc980_usbhostlib - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/nk-rtu980/project.uvprojx b/bsp/nuvoton/nk-rtu980/project.uvprojx deleted file mode 100644 index bc477201f8..0000000000 --- a/bsp/nuvoton/nk-rtu980/project.uvprojx +++ /dev/null @@ -1,1766 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread - 0x4 - ARM-ADS - 0 - - - Nuvoton_ARM9_Series - Nuvoton - - - - - 0 - - - - - - - - - - - - 0 - 0 - - - - Atmel\SAM9260\ - Atmel\SAM9260\ - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARM.DLL - -cAT91SAM9260 - DARMATS9.DLL - -p91SAM9260 - SARM.DLL - - TARMATS9.DLL - -p91SAM9260 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 0 - 1 - 4098 - - 0 - Segger\JLTAgdi.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - ARM926EJ-S - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 1 - 0x100000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x20000000 - 0x800000 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x100000 - 0x8000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x20800000 - 0x1800000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x200000 - 0x1000 - - - 0 - 0x300000 - 0x1000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\arm926;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\nuc980\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\nuc980\Driver\Include;..\..\..\components\net\lwip-2.1.2\src;..\..\..\components\net\lwip-2.1.2\src\include;..\..\..\components\net\lwip-2.1.2\src\arch\include;..\..\..\components\net\lwip-2.1.2\src\include\netif;..\libraries\nu_packages\Demo;..\libraries\nuc980\UsbHostLib\inc;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x20000000 - 0x20800000 - - .\linking_scripts\nuc980.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - nu_pin_init.c - 1 - board\nu_pin_init.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - start_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\start_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\arm926\cpuport.c - - - - - stack.c - 1 - ..\..\..\libcpu\arm\arm926\stack.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\arm926\context_rvds.S - - - - - trap.c - 1 - ..\..\..\libcpu\arm\arm926\trap.c - - - - - machine.c - 1 - ..\..\..\libcpu\arm\arm926\machine.c - - - - - mmu.c - 1 - ..\..\..\libcpu\arm\arm926\mmu.c - - - - - DeviceDrivers - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - cputime.c - 1 - ..\..\..\components\drivers\cputime\cputime.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - drv_usbd.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbd.c - - - - - drv_etimer.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer.c - - - - - drv_gpio.c - 1 - ..\libraries\nuc980\rtt_port\drv_gpio.c - - - - - drv_adc.c - 1 - ..\libraries\nuc980\rtt_port\drv_adc.c - - - - - drv_spi.c - 1 - ..\libraries\nuc980\rtt_port\drv_spi.c - - - - - drv_sdh.c - 1 - ..\libraries\nuc980\rtt_port\drv_sdh.c - - - - - drv_crypto.c - 1 - ..\libraries\nuc980\rtt_port\drv_crypto.c - - - - - drv_can.c - 1 - ..\libraries\nuc980\rtt_port\drv_can.c - - - - - drv_ebi.c - 1 - ..\libraries\nuc980\rtt_port\drv_ebi.c - - - - - drv_sys.c - 1 - ..\libraries\nuc980\rtt_port\drv_sys.c - - - - - drv_qspi.c - 1 - ..\libraries\nuc980\rtt_port\drv_qspi.c - - - - - drv_scuart.c - 1 - ..\libraries\nuc980\rtt_port\drv_scuart.c - - - - - drv_uart.c - 1 - ..\libraries\nuc980\rtt_port\drv_uart.c - - - - - drv_common.c - 1 - ..\libraries\nuc980\rtt_port\drv_common.c - - - - - drv_emac.c - 1 - ..\libraries\nuc980\rtt_port\drv_emac.c - - - - - drv_softi2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_softi2c.c - - - - - drv_i2c.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2c.c - - - - - drv_usbhost.c - 1 - ..\libraries\nuc980\rtt_port\drv_usbhost.c - - - - - drv_etimer_capture.c - 1 - ..\libraries\nuc980\rtt_port\drv_etimer_capture.c - - - - - drv_wdt.c - 1 - ..\libraries\nuc980\rtt_port\drv_wdt.c - - - - - drv_pdma.c - 1 - ..\libraries\nuc980\rtt_port\drv_pdma.c - - - - - drv_systick.c - 1 - ..\libraries\nuc980\rtt_port\drv_systick.c - - - - - drv_i2s.c - 1 - ..\libraries\nuc980\rtt_port\drv_i2s.c - - - - - drv_rtc.c - 1 - ..\libraries\nuc980\rtt_port\drv_rtc.c - - - - - drv_pwm.c - 1 - ..\libraries\nuc980\rtt_port\drv_pwm.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - memheap.c - 1 - ..\..\..\src\memheap.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - Libraries - - - nu_wdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wdt.c - - - - - nu_rtc.c - 1 - ..\libraries\nuc980\Driver\Source\nu_rtc.c - - - - - nu_crypto.c - 1 - ..\libraries\nuc980\Driver\Source\nu_crypto.c - - - - - nu_pdma.c - 1 - ..\libraries\nuc980\Driver\Source\nu_pdma.c - - - - - nu_uart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_uart.c - - - - - nu_qspi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_qspi.c - - - - - nu_sdh.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sdh.c - - - - - nu_scuart.c - 1 - ..\libraries\nuc980\Driver\Source\nu_scuart.c - - - - - nu_sys.c - 1 - ..\libraries\nuc980\Driver\Source\nu_sys.c - - - - - nu_can.c - 1 - ..\libraries\nuc980\Driver\Source\nu_can.c - - - - - nu_usbd.c - 1 - ..\libraries\nuc980\Driver\Source\nu_usbd.c - - - - - nu_cap.c - 1 - ..\libraries\nuc980\Driver\Source\nu_cap.c - - - - - nu_i2s.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2s.c - - - - - nu_ebi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_ebi.c - - - - - nu_gpio.c - 1 - ..\libraries\nuc980\Driver\Source\nu_gpio.c - - - - - nu_wwdt.c - 1 - ..\libraries\nuc980\Driver\Source\nu_wwdt.c - - - - - nu_i2c.c - 1 - ..\libraries\nuc980\Driver\Source\nu_i2c.c - - - - - nu_spi.c - 1 - ..\libraries\nuc980\Driver\Source\nu_spi.c - - - - - nu_emac.c - 1 - ..\libraries\nuc980\Driver\Source\nu_emac.c - - - - - nu_etimer.c - 1 - ..\libraries\nuc980\Driver\Source\nu_etimer.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\sockets.c - - - - - altcp_alloc.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_alloc.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\err.c - - - - - altcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\udp.c - - - - - altcp_tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\altcp_tcp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\api_msg.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\apps\ping\ping.c - - - - - if_api.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\api\if_api.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.1.2\src\core\tcp.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nuc980_usbhostlib - - - ehci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ehci_iso.c - - - - - mem_alloc.c - 1 - ..\libraries\nuc980\UsbHostLib\src\mem_alloc.c - - - - - ohci.c - 1 - ..\libraries\nuc980\UsbHostLib\src\ohci.c - - - - - support.c - 1 - ..\libraries\nuc980\UsbHostLib\src\support.c - - - - - usb_core.c - 1 - ..\libraries\nuc980\UsbHostLib\src\usb_core.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - mstorage.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\mstorage.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - cdc_vcom.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\cdc_vcom.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/nk-rtu980/rtconfig.h b/bsp/nuvoton/nk-rtu980/rtconfig.h deleted file mode 100644 index 6da5ab3233..0000000000 --- a/bsp/nuvoton/nk-rtu980/rtconfig.h +++ /dev/null @@ -1,431 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 16 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_MEMHEAP -#define RT_MEMHEAP_FAST_MODE -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_MEMTRACE -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_ARM9 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 16 -#define DFS_FILESYSTEM_TYPES_MAX 16 -#define DFS_FD_MAX 64 -#define RT_USING_DFS_MNTTABLE -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_CAN_USING_HDR -#define RT_USING_HWTIMER -#define RT_USING_CPUTIME -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_USING_QSPI -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_CDC -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_MSTORAGE -#define RT_VCOM_TASK_STK_SIZE 2048 -#define RT_CDC_RX_BUFSIZE 128 -#define RT_VCOM_SERNO "32021919830108" -#define RT_VCOM_SER_LEN 14 -#define RT_VCOM_TX_TIMEOUT 1000 -#define RT_USB_MSTORAGE_DISK_NAME "ramdisk1" - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP212 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.31.55" -#define RT_LWIP_GWADDR "192.168.31.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 16 -#define RT_LWIP_PBUF_NUM 256 -#define RT_LWIP_RAW_PCB_NUM 16 -#define RT_LWIP_UDP_PCB_NUM 16 -#define RT_LWIP_TCP_PCB_NUM 16 -#define RT_LWIP_TCP_SEG_NUM 64 -#define RT_LWIP_TCP_SND_BUF 16384 -#define RT_LWIP_TCP_WND 65535 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 256 -#define RT_LWIP_TCPTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 4096 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 256 -#define RT_LWIP_REASSEMBLY_FRAG -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define RT_LWIP_NETIF_LOOPBACK -#define LWIP_NETIF_LOOPBACK 1 -#define RT_LWIP_STATS -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_NETUTILS -#define PKG_NETUTILS_TFTP -#define PKG_NETUTILS_IPERF -#define PKG_NETUTILS_NTP -#define NTP_USING_AUTO_SYNC -#define NTP_AUTO_SYNC_FIRST_DELAY 30 -#define NTP_AUTO_SYNC_PERIOD 3600 -#define NETUTILS_NTP_HOSTNAME "0.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME2 "1.tw.pool.ntp.org" -#define NETUTILS_NTP_HOSTNAME3 "2.tw.pool.ntp.org" -#define PKG_USING_NETUTILS_V131 -#define PKG_NETUTILS_VER_NUM 0x10301 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define FAL_USING_SFUD_PORT -#define FAL_USING_NOR_FLASH_DEV_NAME "norflash0" -#define PKG_USING_FAL_LATEST_VERSION -#define PKG_FAL_VER_NUM 0x99999 -#define PKG_USING_RAMDISK -#define PKG_USING_RAMDISK_LATEST_VERSION - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define PKG_USING_OPTPARSE -#define PKG_USING_OPTPARSE_LATEST_VERSION - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_NUC980 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_MMU -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define BSP_USING_GPIO -#define BSP_USING_EMAC -#define BSP_USING_EMAC1 -#define NU_EMAC_PDMA_MEMCOPY -#define NU_EMAC_PDMA_MEMCOPY_THRESHOLD 128 -#define BSP_USING_ADC -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TIMER0 -#define BSP_USING_TMR1 -#define BSP_USING_TIMER1 -#define BSP_USING_TMR2 -#define BSP_USING_TIMER2 -#define BSP_USING_TMR3 -#define BSP_USING_TIMER3 -#define BSP_USING_TMR4 -#define BSP_USING_TIMER4 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART4 -#define BSP_USING_UART4_TX_DMA -#define BSP_USING_UART4_RX_DMA -#define BSP_USING_UART8 -#define BSP_USING_UART8_TX_DMA -#define BSP_USING_UART8_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C1 -#define BSP_USING_CAN -#define BSP_USING_CAN3 -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0 -#define BSP_USING_SPI0_PDMA -#define BSP_USING_SPI1_NONE -#define BSP_USING_QSPI -#define BSP_USING_QSPI_PDMA -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI0_PDMA -#define BSP_USING_CRYPTO -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_USBH - -/* On-board Peripheral Drivers */ - -#define BSP_USING_CONSOLE -#define BOARD_USING_UART8_RS485 -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_USB0_DEVICE_HOST - -/* Board extended module drivers */ - -#define BOARD_USING_IP101GR - -#endif diff --git a/bsp/nuvoton/nk-rtu980/rtconfig.py b/bsp/nuvoton/nk-rtu980/rtconfig.py index c246b656ad..07f75ed3e0 100644 --- a/bsp/nuvoton/nk-rtu980/rtconfig.py +++ b/bsp/nuvoton/nk-rtu980/rtconfig.py @@ -85,4 +85,10 @@ elif PLATFORM == 'armcc': CFLAGS += ' -O2' POST_ACTION = 'fromelf --bin $TARGET --output ' + TARGET_NAME + ' \n' - POST_ACTION += 'fromelf -z $TARGET\n' \ No newline at end of file + POST_ACTION += 'fromelf -z $TARGET\n' +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) diff --git a/bsp/nuvoton/numaker-iot-m487/.config b/bsp/nuvoton/numaker-iot-m487/.config index c10d9235f9..58d95746ed 100644 --- a/bsp/nuvoton/numaker-iot-m487/.config +++ b/bsp/nuvoton/numaker-iot-m487/.config @@ -973,3 +973,5 @@ CONFIG_BOARD_USING_HSUSBH_USBD=y # # CONFIG_BOARD_USING_MAX31875 is not set # CONFIG_BOARD_USING_LCD_ILI9341 is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-iot-m487.test.utest." diff --git a/bsp/nuvoton/numaker-iot-m487/Kconfig b/bsp/nuvoton/numaker-iot-m487/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/numaker-iot-m487/Kconfig +++ b/bsp/nuvoton/numaker-iot-m487/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-iot-m487/board/Kconfig b/bsp/nuvoton/numaker-iot-m487/board/Kconfig index 7b2fb2683a..0e81a45529 100644 --- a/bsp/nuvoton/numaker-iot-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-iot-m487/board/Kconfig @@ -129,5 +129,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/numaker-iot-m487/project.uvproj b/bsp/nuvoton/numaker-iot-m487/project.uvproj deleted file mode 100644 index b26994de86..0000000000 --- a/bsp/nuvoton/numaker-iot-m487/project.uvproj +++ /dev/null @@ -1,1814 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - - - M487JIDAE - Nuvoton - IRAM(0x20000000-0x20027FFF) IROM(0-0x7FFFF) CLOCK(192000000) CPUTYPE("Cortex-M4") FPU2 - - undefined - - 0 - - - - - - - - - - - SFD\Nuvoton\M481_v1.SFR - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil4\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil4\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 10 - - - - - - - - - - - - - - NULink\Nu_Link.dll - - - - - 1 - 0 - 0 - 1 - 1 - 4101 - - 0 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 8 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\components\net\at\include;..\..\..\components\net\at\at_socket;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\BMX055;..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver;..\libraries\nu_packages\BMX055\libraries\BMG160_driver;..\libraries\nu_packages\BMX055\libraries\BMM050_driver;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\drivers\sensors;..\..\..\components\drivers\include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - AT - - - at_socket.c - 1 - ..\..\..\components\net\at\at_socket\at_socket.c - - - - - at_utils.c - 1 - ..\..\..\components\net\at\src\at_utils.c - - - - - at_client.c - 1 - ..\..\..\components\net\at\src\at_client.c - - - - - at_cli.c - 1 - ..\..\..\components\net\at\src\at_cli.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - Libraries - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - m480_usbhostlib - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - nu_pkgs_bmx055 - - - bmg160.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMG160_driver\bmg160.c - - - - - bma2x2.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver\bma2x2.c - - - - - sensor_bmx055.c - 1 - ..\libraries\nu_packages\BMX055\sensor_bmx055.c - - - - - bmm050.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMM050_driver\bmm050.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - af_inet_at.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_at.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - Sensors - - - sensor_cmd.c - 1 - ..\..\..\components\drivers\sensors\sensor_cmd.c - - - - - sensor.c - 1 - ..\..\..\components\drivers\sensors\sensor.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/numaker-iot-m487/project.uvprojx b/bsp/nuvoton/numaker-iot-m487/project.uvprojx deleted file mode 100644 index bf9144d3c4..0000000000 --- a/bsp/nuvoton/numaker-iot-m487/project.uvprojx +++ /dev/null @@ -1,1809 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - 0 - - - M487JIDAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.5 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x28000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M481_AP_512 -FS00 -FL080000 -FP0($$Device:M487JIDAE$Flash\M481_AP_512.FLM)) - 0 - $$Device:M487JIDAE$Device\M480\Include\M480.h - - - - - - - - - - $$Device:M487JIDAE$SVD\Nuvoton\M481_v1.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4103 - - 1 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\components\net\at\include;..\..\..\components\net\at\at_socket;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\BMX055;..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver;..\libraries\nu_packages\BMX055\libraries\BMG160_driver;..\libraries\nu_packages\BMX055\libraries\BMM050_driver;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\drivers\sensors;..\..\..\components\drivers\include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - AT - - - at_client.c - 1 - ..\..\..\components\net\at\src\at_client.c - - - - - at_cli.c - 1 - ..\..\..\components\net\at\src\at_cli.c - - - - - at_utils.c - 1 - ..\..\..\components\net\at\src\at_utils.c - - - - - at_socket.c - 1 - ..\..\..\components\net\at\at_socket\at_socket.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - device.c - 1 - ..\..\..\src\device.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - Libraries - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - m480_usbhostlib - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - nu_pkgs_bmx055 - - - bmg160.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMG160_driver\bmg160.c - - - - - bma2x2.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMA2x2_driver\bma2x2.c - - - - - sensor_bmx055.c - 1 - ..\libraries\nu_packages\BMX055\sensor_bmx055.c - - - - - bmm050.c - 1 - ..\libraries\nu_packages\BMX055\libraries\BMM050_driver\bmm050.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_at.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_at.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - Sensors - - - sensor_cmd.c - 1 - ..\..\..\components\drivers\sensors\sensor_cmd.c - - - - - sensor.c - 1 - ..\..\..\components\drivers\sensors\sensor.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-iot-m487/rtconfig.h b/bsp/nuvoton/numaker-iot-m487/rtconfig.h deleted file mode 100644 index 670d11e494..0000000000 --- a/bsp/nuvoton/numaker-iot-m487/rtconfig.h +++ /dev/null @@ -1,400 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 1024 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M4 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 2048 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 8 -#define DFS_FILESYSTEM_TYPES_MAX 4 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_SENSOR -#define RT_USING_SENSOR_CMD -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_DES -#define RT_HWCRYPTO_USING_DES_ECB -#define RT_HWCRYPTO_USING_DES_CBC -#define RT_HWCRYPTO_USING_3DES -#define RT_HWCRYPTO_USING_3DES_ECB -#define RT_HWCRYPTO_USING_3DES_CBC -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG -#define RT_HWCRYPTO_USING_CRC -#define RT_HWCRYPTO_USING_CRC_07 -#define RT_HWCRYPTO_USING_CRC_8005 -#define RT_HWCRYPTO_USING_CRC_1021 -#define RT_HWCRYPTO_USING_CRC_04C11DB7 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk/" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define _RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_AT -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - - -/* AT commands */ - -#define RT_USING_AT -#define AT_USING_CLIENT -#define AT_CLIENT_NUM_MAX 1 -#define AT_USING_SOCKET -#define AT_USING_CLI -#define AT_CMD_MAX_LEN 512 -#define AT_SW_VERSION_NUM 0x10301 - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_AT_DEVICE -#define AT_DEVICE_USING_ESP8266 -#define AT_DEVICE_ESP8266_INIT_ASYN -#define PKG_USING_AT_DEVICE_LATEST_VERSION -#define PKG_AT_DEVICE_VER_NUM 0x99999 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define PKG_USING_FAL_LATEST_VERSION -#define PKG_FAL_VER_NUM 0x99999 - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO -#define NU_PKG_USING_BMX055 -#define NU_PKG_USING_NAU88L25 - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M480 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_FMC -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_TMR -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART1_TX_DMA -#define BSP_USING_UART1_RX_DMA -#define BSP_USING_UART2 -#define BSP_USING_UART2_TX_DMA -#define BSP_USING_UART2_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C0 -#define BSP_USING_I2C1 -#define BSP_USING_I2C2 -#define BSP_USING_USCI -#define BSP_USING_UUART -#define BSP_USING_USCI0 -#define BSP_USING_UUART0 -#define BSP_USING_UUART0_TX_DMA -#define BSP_USING_UUART0_RX_DMA -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0_NONE -#define BSP_USING_SPI1 -#define BSP_USING_SPI1_PDMA -#define BSP_USING_SPI2 -#define BSP_USING_SPI3_NONE -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 2048 -#define BSP_USING_QSPI -#define BSP_USING_QSPI0 -#define BSP_USING_CRYPTO -#define BSP_USING_TRNG -#define BSP_USING_CRC -#define NU_CRC_USE_PDMA -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_HSUSBH -#define NU_USBHOST_HUB_POLLING_INTERVAL 100 - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME -#define BOARD_USING_ESP8266 -#define BOARD_USING_BMX055 -#define BOARD_USING_NAU88L25 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_HSUSBH_USBD - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/numaker-iot-m487/rtconfig.py b/bsp/nuvoton/numaker-iot-m487/rtconfig.py index 902a2bdce9..7beeafe88a 100644 --- a/bsp/nuvoton/numaker-iot-m487/rtconfig.py +++ b/bsp/nuvoton/numaker-iot-m487/rtconfig.py @@ -130,3 +130,11 @@ elif PLATFORM == 'iar': EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/numaker-m032ki/.config b/bsp/nuvoton/numaker-m032ki/.config index acdfc2eb88..13bed80dd6 100644 --- a/bsp/nuvoton/numaker-m032ki/.config +++ b/bsp/nuvoton/numaker-m032ki/.config @@ -797,3 +797,5 @@ CONFIG_BSP_USING_NULINKME=y # Board extended module drivers # # CONFIG_BOARD_USING_STORAGE_SPIFLASH is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-m032ki.test.utest." diff --git a/bsp/nuvoton/numaker-m032ki/Kconfig b/bsp/nuvoton/numaker-m032ki/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/numaker-m032ki/Kconfig +++ b/bsp/nuvoton/numaker-m032ki/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-m032ki/board/Kconfig b/bsp/nuvoton/numaker-m032ki/board/Kconfig index a3f0437b7b..bc112e0583 100644 --- a/bsp/nuvoton/numaker-m032ki/board/Kconfig +++ b/bsp/nuvoton/numaker-m032ki/board/Kconfig @@ -24,4 +24,5 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" endmenu diff --git a/bsp/nuvoton/numaker-m032ki/project.uvprojx b/bsp/nuvoton/numaker-m032ki/project.uvprojx deleted file mode 100644 index dbefa40af7..0000000000 --- a/bsp/nuvoton/numaker-m032ki/project.uvprojx +++ /dev/null @@ -1,1228 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m031 - 0x4 - ARM-ADS - 5060750::V5.06 update 6 (build 750)::ARMCC - 5060750::V5.06 update 6 (build 750)::ARMCC - 0 - - - M032KIAAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.10 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x18000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M0") CLOCK(12000000) - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M031_AP_512 -FS00 -FL080000 -FP0($$Device:M032KIAAE$Flash\M031_AP_512.FLM)) - 0 - $$Device:M032KIAAE$Device\M031\Include\M031Series.h - - - - - - - - - - $$Device:M032KIAAE$SVD\Nuvoton\M031AE_v1.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 1 - fromelf --bin ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.bin" - fromelf --text -c ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.txt" - 0 - 0 - 0 - 0 - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - -pCM0 - SARMCM3.DLL - - TARMCM1.DLL - -pCM0 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4103 - - 1 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M0" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x18000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x18000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 5 - 3 - 0 - 0 - 0 - 1 - 0 - - - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m031\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m0;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\m031\Device\Nuvoton\M031\Include;..\libraries\m031\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m031\StdDriver\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel;..\..\..\examples\utest\testcases\utest - - - - 1 - 0 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m031_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - board - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m0\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m0\cpuport.c - - - - - DeviceDrivers - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - Drivers - - - system_M031Series.c - 1 - ..\libraries\m031\Device\Nuvoton\M031\Source\system_M031Series.c - - - - - startup_M031Series.s - 2 - ..\libraries\m031\Device\Nuvoton\M031\Source\ARM\startup_M031Series.s - - - - - drv_timer.c - 1 - ..\libraries\m031\rtt_port\drv_timer.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m031\rtt_port\drv_bpwm_capture.c - - - - - drv_pwm_capture.c - 1 - ..\libraries\m031\rtt_port\drv_pwm_capture.c - - - - - drv_ebi.c - 1 - ..\libraries\m031\rtt_port\drv_ebi.c - - - - - drv_adc.c - 1 - ..\libraries\m031\rtt_port\drv_adc.c - - - - - drv_common.c - 1 - ..\libraries\m031\rtt_port\drv_common.c - - - - - drv_uuart.c - 1 - ..\libraries\m031\rtt_port\drv_uuart.c - - - - - drv_wdt.c - 1 - ..\libraries\m031\rtt_port\drv_wdt.c - - - - - drv_uspi.c - 1 - ..\libraries\m031\rtt_port\drv_uspi.c - - - - - drv_qspi.c - 1 - ..\libraries\m031\rtt_port\drv_qspi.c - - - - - drv_spi.c - 1 - ..\libraries\m031\rtt_port\drv_spi.c - - - - - drv_fmc.c - 1 - ..\libraries\m031\rtt_port\drv_fmc.c - - - - - drv_crc.c - 1 - ..\libraries\m031\rtt_port\drv_crc.c - - - - - drv_i2c.c - 1 - ..\libraries\m031\rtt_port\drv_i2c.c - - - - - drv_gpio.c - 1 - ..\libraries\m031\rtt_port\drv_gpio.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m031\rtt_port\drv_timer_capture.c - - - - - drv_crypto.c - 1 - ..\libraries\m031\rtt_port\drv_crypto.c - - - - - drv_rtc.c - 1 - ..\libraries\m031\rtt_port\drv_rtc.c - - - - - drv_bpwm.c - 1 - ..\libraries\m031\rtt_port\drv_bpwm.c - - - - - drv_uart.c - 1 - ..\libraries\m031\rtt_port\drv_uart.c - - - - - drv_spii2s.c - 1 - ..\libraries\m031\rtt_port\drv_spii2s.c - - - - - drv_pdma.c - 1 - ..\libraries\m031\rtt_port\drv_pdma.c - - - - - drv_pwm.c - 1 - ..\libraries\m031\rtt_port\drv_pwm.c - - - - - drv_softi2c.c - 1 - ..\libraries\m031\rtt_port\drv_softi2c.c - - - - - drv_clk.c - 1 - ..\libraries\m031\rtt_port\drv_clk.c - - - - - drv_ui2c.c - 1 - ..\libraries\m031\rtt_port\drv_ui2c.c - - - - - drv_usbd.c - 1 - ..\libraries\m031\rtt_port\drv_usbd.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - Libraries - - - nu_ebi.c - 1 - ..\libraries\m031\StdDriver\src\nu_ebi.c - - - - - nu_adc.c - 1 - ..\libraries\m031\StdDriver\src\nu_adc.c - - - - - nu_clk.c - 1 - ..\libraries\m031\StdDriver\src\nu_clk.c - - - - - nu_uart.c - 1 - ..\libraries\m031\StdDriver\src\nu_uart.c - - - - - nu_usbd.c - 1 - ..\libraries\m031\StdDriver\src\nu_usbd.c - - - - - nu_pdma.c - 1 - ..\libraries\m031\StdDriver\src\nu_pdma.c - - - - - nu_i2c.c - 1 - ..\libraries\m031\StdDriver\src\nu_i2c.c - - - - - nu_spi.c - 1 - ..\libraries\m031\StdDriver\src\nu_spi.c - - - - - nu_wwdt.c - 1 - ..\libraries\m031\StdDriver\src\nu_wwdt.c - - - - - nu_pwm.c - 1 - ..\libraries\m031\StdDriver\src\nu_pwm.c - - - - - nu_rtc.c - 1 - ..\libraries\m031\StdDriver\src\nu_rtc.c - - - - - nu_bpwm.c - 1 - ..\libraries\m031\StdDriver\src\nu_bpwm.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m031\StdDriver\src\nu_usci_i2c.c - - - - - nu_gpio.c - 1 - ..\libraries\m031\StdDriver\src\nu_gpio.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m031\StdDriver\src\nu_usci_spi.c - - - - - nu_wdt.c - 1 - ..\libraries\m031\StdDriver\src\nu_wdt.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m031\StdDriver\src\nu_usci_uart.c - - - - - nu_sys.c - 1 - ..\libraries\m031\StdDriver\src\nu_sys.c - - - - - nu_qspi.c - 1 - ..\libraries\m031\StdDriver\src\nu_qspi.c - - - - - nu_timer.c - 1 - ..\libraries\m031\StdDriver\src\nu_timer.c - - - - - nu_acmp.c - 1 - ..\libraries\m031\StdDriver\src\nu_acmp.c - - - - - nu_fmc.c - 1 - ..\libraries\m031\StdDriver\src\nu_fmc.c - - - - - nu_crc.c - 1 - ..\libraries\m031\StdDriver\src\nu_crc.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - utestcases - - - mem_tc.c - 1 - ..\..\..\examples\utest\testcases\kernel\mem_tc.c - - - - - pass_tc.c - 1 - ..\..\..\examples\utest\testcases\utest\pass_tc.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-m032ki/rtconfig.h b/bsp/nuvoton/numaker-m032ki/rtconfig.h deleted file mode 100644 index f2184d36fa..0000000000 --- a/bsp/nuvoton/numaker-m032ki/rtconfig.h +++ /dev/null @@ -1,286 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 512 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 512 - -/* kservice optimization */ - -#define RT_DEBUG - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M0 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 -#define DFS_FD_MAX 16 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_HWTIMER -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_WDT - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define RT_USB_DEVICE_COMPOSITE -#define RT_USB_DEVICE_NONE -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - - -/* Network interface device */ - - -/* light weight TCP/IP stack */ - - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - -#define RT_USING_UTESTCASES - -/* Utest Self Testcase */ - -#define UTEST_SELF_PASS_TC - -/* Kernel Testcase */ - -#define UTEST_SMALL_MEM_TC - -/* Utest Serial Testcase */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M032 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 4 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_IO_RW -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_ADC -#define BSP_USING_ADC0 -#define BSP_USING_TMR -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TIMER0 -#define BSP_USING_TMR1 -#define BSP_USING_TIMER1 -#define BSP_USING_TMR2 -#define BSP_USING_TIMER2 -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART1_TX_DMA -#define BSP_USING_UART1_RX_DMA -#define BSP_USING_UART2 -#define BSP_USING_UART3 -#define BSP_USING_UART4 -#define BSP_USING_UART5 -#define BSP_USING_UART6 -#define BSP_USING_UART7 -#define BSP_USING_WDT -#define BSP_USING_USBD - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/numaker-m032ki/rtconfig.py b/bsp/nuvoton/numaker-m032ki/rtconfig.py index bc7ec5b5c1..1061a7f5fd 100644 --- a/bsp/nuvoton/numaker-m032ki/rtconfig.py +++ b/bsp/nuvoton/numaker-m032ki/rtconfig.py @@ -122,3 +122,11 @@ elif PLATFORM == 'iar': EXEC_PATH += '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/numaker-m2354/.config b/bsp/nuvoton/numaker-m2354/.config index 0ff7f7a969..12f8e22bcc 100644 --- a/bsp/nuvoton/numaker-m2354/.config +++ b/bsp/nuvoton/numaker-m2354/.config @@ -557,6 +557,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -567,7 +568,6 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -618,6 +618,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -652,14 +653,14 @@ CONFIG_FAL_DEBUG_CONFIG=y CONFIG_FAL_DEBUG=1 CONFIG_FAL_PART_HAS_TABLE_CFG=y # CONFIG_FAL_USING_SFUD_PORT is not set -CONFIG_PKG_USING_FAL_V00500=y +# CONFIG_PKG_USING_FAL_V00500 is not set # CONFIG_PKG_USING_FAL_V00400 is not set # CONFIG_PKG_USING_FAL_V00300 is not set # CONFIG_PKG_USING_FAL_V00200 is not set # CONFIG_PKG_USING_FAL_V00100 is not set -# CONFIG_PKG_USING_FAL_LATEST_VERSION is not set -CONFIG_PKG_FAL_VER="v0.5.0" -CONFIG_PKG_FAL_VER_NUM=0x00500 +CONFIG_PKG_USING_FAL_LATEST_VERSION=y +CONFIG_PKG_FAL_VER="latest" +CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set @@ -742,6 +743,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -829,19 +831,8 @@ CONFIG_PKG_FAL_VER_NUM=0x00500 # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -# CONFIG_NU_PKG_USING_NAU88L25 is not set -# CONFIG_NU_PKG_USING_NAU8822 is not set -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -947,3 +938,18 @@ CONFIG_BOARD_USING_OTG=y # Board extended module drivers # CONFIG_BOARD_USING_SEGMENT_LCD=y + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +# CONFIG_NU_PKG_USING_NAU88L25 is not set +# CONFIG_NU_PKG_USING_NAU8822 is not set +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-m2354.test.utest." diff --git a/bsp/nuvoton/numaker-m2354/Kconfig b/bsp/nuvoton/numaker-m2354/Kconfig index 90354447b3..b396340d12 100644 --- a/bsp/nuvoton/numaker-m2354/Kconfig +++ b/bsp/nuvoton/numaker-m2354/Kconfig @@ -9,7 +9,7 @@ config RTT_DIR string option env="RTT_ROOT" default "../../.." - + # you can change the RTT_ROOT default "../../.." to your rtthread_root, # example : default "F:/git_repositories/rt-thread" @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-m2354/board/Kconfig b/bsp/nuvoton/numaker-m2354/board/Kconfig index a3e751aa42..3c71934493 100644 --- a/bsp/nuvoton/numaker-m2354/board/Kconfig +++ b/bsp/nuvoton/numaker-m2354/board/Kconfig @@ -68,4 +68,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" + endmenu diff --git a/bsp/nuvoton/numaker-m2354/project.uvprojx b/bsp/nuvoton/numaker-m2354/project.uvprojx deleted file mode 100644 index c15ccbb19a..0000000000 --- a/bsp/nuvoton/numaker-m2354/project.uvprojx +++ /dev/null @@ -1,1768 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m2354 - 0x4 - ARM-ADS - 6100001::V6.10.1::.\ARMCLANG - 1 - - - M2354KJFAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.10 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x40000) IROM(0x00000000,0x100000) CPUTYPE("Cortex-M23") TZ CLOCK(12000000) ESEL ELITTLE - - - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M2354_AP_1M -FS00 -FL0100000 -FP0($$Device:M2354KJFAE$Flash\M2354_AP_1M.FLM)) - 0 - $$Device:M2354KJFAE$Device\M2354\Include\M2354.h - - - - - - - - - - $$Device:M2354KJFAE$SVD\Nuvoton\M2354.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 1 - fromelf --bin ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.bin" - fromelf --text -c ".\build\keil5\\@L.axf" --output ".\build\keil5\\@L.txt" - 0 - 0 - 0 - 0 - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - - - - - SARMV8M.DLL - -MPU - TCM.DLL - -pCM23 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4101 - - 1 - BIN\UL2V8M.DLL - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M23" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 8 - 0 - 1 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x40000 - - - 1 - 0x0 - 0x100000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x100000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x40000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 5 - 3 - 0 - 0 - 0 - 1 - 0 - - - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\..\..\components\net\at\include;..\..\..\components\net\at\at_socket;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m2354\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m23;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\libraries\m2354\Device\Nuvoton\M2354\Include;..\libraries\m2354\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m2354\StdDriver\inc;..\libraries\m2354\USBHostLib\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\SLCD;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\dfs_net;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\drivers\sensors;..\..\..\components\drivers\include;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m2354_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - AT - - - at_socket.c - 1 - ..\..\..\components\net\at\at_socket\at_socket.c - - - - - at_cli.c - 1 - ..\..\..\components\net\at\src\at_cli.c - - - - - at_utils.c - 1 - ..\..\..\components\net\at\src\at_utils.c - - - - - at_client.c - 1 - ..\..\..\components\net\at\src\at_client.c - - - - - board - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - Compiler - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m23\context_rvds.S - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m23\cpuport.c - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - -std=c99 - - - - - - - - - - Drivers - - - startup_M2354.s - 2 - ..\libraries\m2354\Device\Nuvoton\M2354\Source\ARM\startup_M2354.s - - - - - system_M2354.c - 1 - ..\libraries\m2354\Device\Nuvoton\M2354\Source\system_M2354.c - - - - - drv_crc.c - 1 - ..\libraries\m2354\rtt_port\drv_crc.c - - - - - drv_usbd.c - 1 - ..\libraries\m2354\rtt_port\drv_usbd.c - - - - - drv_ecap.c - 1 - ..\libraries\m2354\rtt_port\drv_ecap.c - - - - - drv_common.c - 1 - ..\libraries\m2354\rtt_port\drv_common.c - - - - - drv_eadc.c - 1 - ..\libraries\m2354\rtt_port\drv_eadc.c - - - - - drv_pdma.c - 1 - ..\libraries\m2354\rtt_port\drv_pdma.c - - - - - drv_qspi.c - 1 - ..\libraries\m2354\rtt_port\drv_qspi.c - - - - - drv_gpio.c - 1 - ..\libraries\m2354\rtt_port\drv_gpio.c - - - - - drv_tpwm.c - 1 - ..\libraries\m2354\rtt_port\drv_tpwm.c - - - - - drv_spi.c - 1 - ..\libraries\m2354\rtt_port\drv_spi.c - - - - - drv_wdt.c - 1 - ..\libraries\m2354\rtt_port\drv_wdt.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m2354\rtt_port\drv_bpwm_capture.c - - - - - drv_spii2s.c - 1 - ..\libraries\m2354\rtt_port\drv_spii2s.c - - - - - drv_bpwm.c - 1 - ..\libraries\m2354\rtt_port\drv_bpwm.c - - - - - drv_usbhost.c - 1 - ..\libraries\m2354\rtt_port\drv_usbhost.c - - - - - drv_epwm.c - 1 - ..\libraries\m2354\rtt_port\drv_epwm.c - - - - - drv_can.c - 1 - ..\libraries\m2354\rtt_port\drv_can.c - - - - - drv_sdh.c - 1 - ..\libraries\m2354\rtt_port\drv_sdh.c - - - - - drv_trng.c - 1 - ..\libraries\m2354\rtt_port\drv_trng.c - - - - - drv_timer.c - 1 - ..\libraries\m2354\rtt_port\drv_timer.c - - - - - drv_fmc.c - 1 - ..\libraries\m2354\rtt_port\drv_fmc.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m2354\rtt_port\drv_timer_capture.c - - - - - drv_softi2c.c - 1 - ..\libraries\m2354\rtt_port\drv_softi2c.c - - - - - drv_uspi.c - 1 - ..\libraries\m2354\rtt_port\drv_uspi.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m2354\rtt_port\drv_epwm_capture.c - - - - - drv_i2s.c - 1 - ..\libraries\m2354\rtt_port\drv_i2s.c - - - - - drv_uart.c - 1 - ..\libraries\m2354\rtt_port\drv_uart.c - - - - - drv_ebi.c - 1 - ..\libraries\m2354\rtt_port\drv_ebi.c - - - - - drv_clk.c - 1 - ..\libraries\m2354\rtt_port\drv_clk.c - - - - - drv_otg.c - 1 - ..\libraries\m2354\rtt_port\drv_otg.c - - - - - drv_i2c.c - 1 - ..\libraries\m2354\rtt_port\drv_i2c.c - - - - - drv_rtc.c - 1 - ..\libraries\m2354\rtt_port\drv_rtc.c - - - - - drv_scuart.c - 1 - ..\libraries\m2354\rtt_port\drv_scuart.c - - - - - drv_uuart.c - 1 - ..\libraries\m2354\rtt_port\drv_uuart.c - - - - - drv_crypto.c - 1 - ..\libraries\m2354\rtt_port\drv_crypto.c - - - - - drv_qei.c - 1 - ..\libraries\m2354\rtt_port\drv_qei.c - - - - - drv_slcd.c - 1 - ..\libraries\m2354\rtt_port\drv_slcd.c - - - - - drv_ui2c.c - 1 - ..\libraries\m2354\rtt_port\drv_ui2c.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - Libraries - - - nu_ewwdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ewwdt.c - - - - - nu_wwdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_wwdt.c - - - - - nu_usbd.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usbd.c - - - - - nu_crypto.c - 1 - ..\libraries\m2354\StdDriver\src\nu_crypto.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usci_i2c.c - - - - - nu_qspi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_qspi.c - - - - - nu_clk.c - 1 - ..\libraries\m2354\StdDriver\src\nu_clk.c - - - - - nu_lcd.c - 1 - ..\libraries\m2354\StdDriver\src\nu_lcd.c - - - - - nu_scuart.c - 1 - ..\libraries\m2354\StdDriver\src\nu_scuart.c - - - - - nu_sys.c - 1 - ..\libraries\m2354\StdDriver\src\nu_sys.c - - - - - nu_sc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_sc.c - - - - - nu_sdh.c - 1 - ..\libraries\m2354\StdDriver\src\nu_sdh.c - - - - - nu_spi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_spi.c - - - - - nu_ewdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ewdt.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usci_uart.c - - - - - nu_acmp.c - 1 - ..\libraries\m2354\StdDriver\src\nu_acmp.c - - - - - nu_wdt.c - 1 - ..\libraries\m2354\StdDriver\src\nu_wdt.c - - - - - nu_i2c.c - 1 - ..\libraries\m2354\StdDriver\src\nu_i2c.c - - - - - nu_fmc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_fmc.c - - - - - nu_dac.c - 1 - ..\libraries\m2354\StdDriver\src\nu_dac.c - - - - - nu_rtc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_rtc.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_timer_pwm.c - - - - - nu_uart.c - 1 - ..\libraries\m2354\StdDriver\src\nu_uart.c - - - - - nu_ecap.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ecap.c - - - - - nu_eadc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_eadc.c - - - - - nu_can.c - 1 - ..\libraries\m2354\StdDriver\src\nu_can.c - - - - - nu_epwm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_epwm.c - - - - - nu_bpwm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_bpwm.c - - - - - nu_dpm.c - 1 - ..\libraries\m2354\StdDriver\src\nu_dpm.c - - - - - nu_pdma.c - 1 - ..\libraries\m2354\StdDriver\src\nu_pdma.c - - - - - nu_qei.c - 1 - ..\libraries\m2354\StdDriver\src\nu_qei.c - - - - - nu_timer.c - 1 - ..\libraries\m2354\StdDriver\src\nu_timer.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_usci_spi.c - - - - - nu_ebi.c - 1 - ..\libraries\m2354\StdDriver\src\nu_ebi.c - - - - - nu_crc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_crc.c - - - - - nu_fvc.c - 1 - ..\libraries\m2354\StdDriver\src\nu_fvc.c - - - - - nu_i2s.c - 1 - ..\libraries\m2354\StdDriver\src\nu_i2s.c - - - - - nu_rng.c - 1 - ..\libraries\m2354\StdDriver\src\nu_rng.c - - - - - nu_gpio.c - 1 - ..\libraries\m2354\StdDriver\src\nu_gpio.c - - - - - nu_keystore.c - 1 - ..\libraries\m2354\StdDriver\src\nu_keystore.c - - - - - nu_tamper.c - 1 - ..\libraries\m2354\StdDriver\src\nu_tamper.c - - - - - m2354_usbhostlib - - - mem_alloc.c - 1 - ..\libraries\m2354\USBHostLib\src\mem_alloc.c - - - - - ohci.c - 1 - ..\libraries\m2354\USBHostLib\src\ohci.c - - - - - usb_core.c - 1 - ..\libraries\m2354\USBHostLib\src\usb_core.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_slcd - - - slcd_rhe6616tp01.c - 1 - ..\libraries\nu_packages\SLCD\slcd_rhe6616tp01.c - - - - - POSIX - - - select.c - 1 - ..\..\..\components\libc\posix\io\select.c - - - - - poll.c - 1 - ..\..\..\components\libc\posix\io\poll\poll.c - - - - - rt_usbd - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - rt_usbh - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - dfs_net.c - 1 - ..\..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_sockets.c - 1 - ..\..\..\components\net\sal_socket\socket\net_sockets.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - af_inet_at.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_at.c - - - - - Sensors - - - sensor_cmd.c - 1 - ..\..\..\components\drivers\sensors\sensor_cmd.c - - - - - sensor.c - 1 - ..\..\..\components\drivers\sensors\sensor.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-m2354/rtconfig.h b/bsp/nuvoton/numaker-m2354/rtconfig.h deleted file mode 100644 index 81c3909d82..0000000000 --- a/bsp/nuvoton/numaker-m2354/rtconfig.h +++ /dev/null @@ -1,383 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 2048 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 4 -#define DFS_FILESYSTEM_TYPES_MAX 4 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 2 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 2048 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_USING_QSPI -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_DEBUG_SFUD -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_SENSOR -#define RT_USING_SENSOR_CMD -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_DES -#define RT_HWCRYPTO_USING_DES_ECB -#define RT_HWCRYPTO_USING_DES_CBC -#define RT_HWCRYPTO_USING_3DES -#define RT_HWCRYPTO_USING_3DES_ECB -#define RT_HWCRYPTO_USING_3DES_CBC -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG -#define RT_HWCRYPTO_USING_CRC -#define RT_HWCRYPTO_USING_CRC_07 -#define RT_HWCRYPTO_USING_CRC_8005 -#define RT_HWCRYPTO_USING_CRC_1021 -#define RT_HWCRYPTO_USING_CRC_04C11DB7 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define _RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO -#define RT_USING_POSIX_POLL -#define RT_USING_POSIX_SELECT - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_AT -#define SAL_USING_POSIX - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - - -/* AT commands */ - -#define RT_USING_AT -#define AT_USING_CLIENT -#define AT_CLIENT_NUM_MAX 1 -#define AT_USING_SOCKET -#define AT_USING_CLI -#define AT_CMD_MAX_LEN 2048 -#define AT_SW_VERSION_NUM 0x10301 - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - -#define PKG_USING_AT_DEVICE -#define AT_DEVICE_USING_ESP8266 -#define AT_DEVICE_ESP8266_INIT_ASYN -#define PKG_USING_AT_DEVICE_LATEST_VERSION -#define PKG_AT_DEVICE_VER_NUM 0x99999 - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define PKG_USING_FAL_V00500 -#define PKG_FAL_VER_NUM 0x00500 - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M2354 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_FMC -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_EADC -#define BSP_USING_EADC0 -#define BSP_USING_TMR -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_UART1 -#define BSP_USING_UART4 -#define BSP_USING_UART4_TX_DMA -#define BSP_USING_UART4_RX_DMA -#define BSP_USING_I2C -#define BSP_USING_I2C1 -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define NU_SDH_MOUNT_ON_ROOT -#define BSP_USING_SPI -#define BSP_USING_SPI0 -#define BSP_USING_SPI1 -#define BSP_USING_SPI2_NONE -#define BSP_USING_SPI3_NONE -#define BSP_USING_CRYPTO -#define BSP_USING_TRNG -#define BSP_USING_CRC -#define NU_CRC_USE_PDMA -#define BSP_USING_WDT -#define BSP_USING_SLCD -#define BSP_USING_USBD -#define BSP_USING_USBH -#define NU_USBHOST_HUB_POLLING_INTERVAL 100 -#define BSP_USING_OTG - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME -#define BOARD_USING_ESP8266 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_OTG - -/* Board extended module drivers */ - -#define BOARD_USING_SEGMENT_LCD - -#endif diff --git a/bsp/nuvoton/numaker-m2354/rtconfig.py b/bsp/nuvoton/numaker-m2354/rtconfig.py index 2a59f1a4f0..2b2d5c86f7 100644 --- a/bsp/nuvoton/numaker-m2354/rtconfig.py +++ b/bsp/nuvoton/numaker-m2354/rtconfig.py @@ -122,3 +122,11 @@ elif PLATFORM == 'iar': EXEC_PATH += '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index d0bd4b04bf..84c9359e02 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -578,6 +578,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -588,7 +589,6 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -639,6 +639,7 @@ CONFIG_UTEST_THR_PRIORITY=20 # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -675,13 +676,13 @@ CONFIG_FAL_DEBUG=1 CONFIG_FAL_PART_HAS_TABLE_CFG=y # CONFIG_FAL_USING_SFUD_PORT is not set # CONFIG_PKG_USING_FAL_V00500 is not set -CONFIG_PKG_USING_FAL_V00400=y +# CONFIG_PKG_USING_FAL_V00400 is not set # CONFIG_PKG_USING_FAL_V00300 is not set # CONFIG_PKG_USING_FAL_V00200 is not set # CONFIG_PKG_USING_FAL_V00100 is not set -# CONFIG_PKG_USING_FAL_LATEST_VERSION is not set -CONFIG_PKG_FAL_VER="v0.4.0" -CONFIG_PKG_FAL_VER_NUM=0x00400 +CONFIG_PKG_USING_FAL_LATEST_VERSION=y +CONFIG_PKG_FAL_VER="latest" +CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set @@ -764,6 +765,7 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -851,19 +853,8 @@ CONFIG_PKG_FAL_VER_NUM=0x00400 # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -# CONFIG_NU_PKG_USING_BMX055 is not set -# CONFIG_NU_PKG_USING_MAX31875 is not set -CONFIG_NU_PKG_USING_NAU88L25=y -# CONFIG_NU_PKG_USING_NAU8822 is not set -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -975,3 +966,18 @@ CONFIG_BOARD_USING_HSUSBH_USBD=y # Board extended module drivers # # CONFIG_BOARD_USING_ADVANCE_V4 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +# CONFIG_NU_PKG_USING_BMX055 is not set +# CONFIG_NU_PKG_USING_MAX31875 is not set +CONFIG_NU_PKG_USING_NAU88L25=y +# CONFIG_NU_PKG_USING_NAU8822 is not set +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set +CONFIG_BOARD_USE_UTEST=y +CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-pfm-m487.test.utest." diff --git a/bsp/nuvoton/numaker-pfm-m487/Kconfig b/bsp/nuvoton/numaker-pfm-m487/Kconfig index 5c55e87c61..b396340d12 100644 --- a/bsp/nuvoton/numaker-pfm-m487/Kconfig +++ b/bsp/nuvoton/numaker-pfm-m487/Kconfig @@ -18,12 +18,6 @@ config PKGS_DIR option env="PKGS_ROOT" default "packages" -config NU_PKGS_DIR - string - option env="NU_PKGS_ROOT" - default "../libraries/nu_packages" - source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" -source "$NU_PKGS_DIR/Kconfig" source "$BSP_DIR/board/Kconfig" diff --git a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig index fc56305c9d..a4f4e0c69a 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig @@ -162,4 +162,6 @@ menu "Hardware Drivers Config" endmenu + source "$BSP_DIR/../libraries/nu_packages/Kconfig" + endmenu diff --git a/bsp/nuvoton/numaker-pfm-m487/project.uvproj b/bsp/nuvoton/numaker-pfm-m487/project.uvproj deleted file mode 100644 index 9e8d850de2..0000000000 --- a/bsp/nuvoton/numaker-pfm-m487/project.uvproj +++ /dev/null @@ -1,1966 +0,0 @@ - - - 1.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - - - M487JIDAE - Nuvoton - IRAM(0x20000000-0x20027FFF) IROM(0-0x7FFFF) CLOCK(192000000) CPUTYPE("Cortex-M4") FPU2 - - undefined - - 0 - - - - - - - - - - - SFD\Nuvoton\M481_v1.SFR - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil4\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil4\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - - 0 - 10 - - - - - - - - - - - - - - NULink\Nu_Link.dll - - - - - 1 - 0 - 0 - 1 - 1 - 4101 - - 0 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 8 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - mnt.c - 1 - applications\mnt.c - - - - - main.c - 1 - applications\main.c - - - - - Compiler - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - DeviceDrivers - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - Libraries - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - m480_usbhostlib - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - -
diff --git a/bsp/nuvoton/numaker-pfm-m487/project.uvprojx b/bsp/nuvoton/numaker-pfm-m487/project.uvprojx deleted file mode 100644 index 0050c2f13a..0000000000 --- a/bsp/nuvoton/numaker-pfm-m487/project.uvprojx +++ /dev/null @@ -1,1961 +0,0 @@ - - - 2.1 -
### uVision Project, (C) Keil Software
- - - rtthread-m480 - 0x4 - ARM-ADS - 0 - - - M487JIDAE - Nuvoton - Nuvoton.NuMicro_DFP.1.3.5 - http://www.nuvoton.com/hq/enu/Documents/KEILSoftwarePack - IRAM(0x20000000,0x28000) IROM(0x00000000,0x80000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0M481_AP_512 -FS00 -FL080000 -FP0($$Device:M487JIDAE$Flash\M481_AP_512.FLM)) - 0 - $$Device:M487JIDAE$Device\M480\Include\M480.h - - - - - - - - - - $$Device:M487JIDAE$SVD\Nuvoton\M481_v1.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\build\keil5\ - rtthread - 1 - 0 - 1 - 1 - 1 - .\build\keil5\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf.exe --bin --output "$L@L.bin" "$L@L.axf" - - 0 - 0 - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - - DARMCM1.DLL - - SARMCM3.DLL - - TARMCM1.DLL - - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4103 - - 1 - NULink\Nu_Link.dll - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 1 - 0x0 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x80000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x28000 - - - 0 - 0x0 - 0x0 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - - --c99 - __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - - applications;.;..\libraries\m480\CMSIS\Include;..\..\..\components\libc\compilers\common;..\..\..\components\libc\compilers\common\nogcc;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\audio;..\..\..\components\drivers\include;..\..\..\components\drivers\hwcrypto;.;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\spi;..\..\..\components\drivers\include;..\..\..\components\drivers\spi\sfud\inc;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;board\NuClockConfig;board\NuPinConfig;..\libraries\m480\Device\Nuvoton\M480\Include;..\libraries\m480\rtt_port;..\..\..\components\dfs\include;..\..\..\components\dfs\filesystems\devfs;..\..\..\components\dfs\filesystems\elmfat;..\..\..\components\finsh;.;..\..\..\include;..\libraries\m480\StdDriver\inc;..\..\..\components\net\lwip-2.0.2\src;..\..\..\components\net\lwip-2.0.2\src\include;..\..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\..\components\net\lwip-2.0.2\src\arch\include;..\..\..\components\net\lwip-2.0.2\src\include\netif;..\libraries\m480\USBHostLib\inc;..\libraries\nu_packages\Demo;..\libraries\nu_packages\AudioCodec;..\libraries\nu_packages\NuUtils\inc;..\..\..\components\libc\posix\io\poll;..\..\..\components\libc\posix\ipc;..\..\..\components\drivers\usb\usbdevice;..\..\..\components\drivers\usb\usbhost;..\..\..\components\drivers\usb\usbhost\class;..\..\..\components\drivers\usb\usbhost\core;..\..\..\components\drivers\usb\usbhost\include;..\..\..\components\drivers\include;..\..\..\components\net\netdev\include;..\..\..\components\net\sal_socket\include;..\..\..\components\net\sal_socket\include\socket;..\..\..\components\net\sal_socket\impl;..\..\..\components\net\sal_socket\include\socket\sys_socket;..\..\..\components\utilities\utest;..\..\..\examples\utest\testcases\kernel - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - .\linking_scripts\m480_flash.sct - - - - - - - - - - - Applications - - - main.c - 1 - applications\main.c - - - - - mnt.c - 1 - applications\mnt.c - - - - - Compiler - - - libc_syms.c - 1 - ..\..\..\components\libc\compilers\armlibc\libc_syms.c - - - - - syscalls.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscalls.c - - - - - syscall_mem.c - 1 - ..\..\..\components\libc\compilers\armlibc\syscall_mem.c - - - - - stdlib.c - 1 - ..\..\..\components\libc\compilers\common\stdlib.c - - - - - time.c - 1 - ..\..\..\components\libc\compilers\common\time.c - - - - - CPU - - - div0.c - 1 - ..\..\..\libcpu\arm\common\div0.c - - - - - showmem.c - 1 - ..\..\..\libcpu\arm\common\showmem.c - - - - - backtrace.c - 1 - ..\..\..\libcpu\arm\common\backtrace.c - - - - - cpuport.c - 1 - ..\..\..\libcpu\arm\cortex-m4\cpuport.c - - - - - context_rvds.S - 2 - ..\..\..\libcpu\arm\cortex-m4\context_rvds.S - - - - - DeviceDrivers - - - audio_pipe.c - 1 - ..\..\..\components\drivers\audio\audio_pipe.c - - - - - audio.c - 1 - ..\..\..\components\drivers\audio\audio.c - - - - - can.c - 1 - ..\..\..\components\drivers\can\can.c - - - - - hw_symmetric.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_symmetric.c - - - - - hwcrypto.c - 1 - ..\..\..\components\drivers\hwcrypto\hwcrypto.c - - - - - hw_rng.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_rng.c - - - - - hw_crc.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_crc.c - - - - - hw_hash.c - 1 - ..\..\..\components\drivers\hwcrypto\hw_hash.c - - - - - hwtimer.c - 1 - ..\..\..\components\drivers\hwtimer\hwtimer.c - - - - - i2c_core.c - 1 - ..\..\..\components\drivers\i2c\i2c_core.c - - - - - i2c_dev.c - 1 - ..\..\..\components\drivers\i2c\i2c_dev.c - - - - - i2c-bit-ops.c - 1 - ..\..\..\components\drivers\i2c\i2c-bit-ops.c - - - - - adc.c - 1 - ..\..\..\components\drivers\misc\adc.c - - - - - rt_drv_pwm.c - 1 - ..\..\..\components\drivers\misc\rt_drv_pwm.c - - - - - pin.c - 1 - ..\..\..\components\drivers\misc\pin.c - - - - - lptimer.c - 1 - ..\..\..\components\drivers\pm\lptimer.c - - - - - pm.c - 1 - ..\..\..\components\drivers\pm\pm.c - - - - - rtc.c - 1 - ..\..\..\components\drivers\rtc\rtc.c - - - - - serial.c - 1 - ..\..\..\components\drivers\serial\serial.c - - - - - sfud.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud.c - - - - - spi_core.c - 1 - ..\..\..\components\drivers\spi\spi_core.c - - - - - sfud_sfdp.c - 1 - ..\..\..\components\drivers\spi\sfud\src\sfud_sfdp.c - - - - - spi_dev.c - 1 - ..\..\..\components\drivers\spi\spi_dev.c - - - - - qspi_core.c - 1 - ..\..\..\components\drivers\spi\qspi_core.c - - - - - spi_flash_sfud.c - 1 - ..\..\..\components\drivers\spi\spi_flash_sfud.c - - - - - ringbuffer.c - 1 - ..\..\..\components\drivers\src\ringbuffer.c - - - - - dataqueue.c - 1 - ..\..\..\components\drivers\src\dataqueue.c - - - - - workqueue.c - 1 - ..\..\..\components\drivers\src\workqueue.c - - - - - completion.c - 1 - ..\..\..\components\drivers\src\completion.c - - - - - ringblk_buf.c - 1 - ..\..\..\components\drivers\src\ringblk_buf.c - - - - - pipe.c - 1 - ..\..\..\components\drivers\src\pipe.c - - - - - waitqueue.c - 1 - ..\..\..\components\drivers\src\waitqueue.c - - - - - watchdog.c - 1 - ..\..\..\components\drivers\watchdog\watchdog.c - - - - - - - --c99 - - - - - - - - - - Drivers - - - nutool_pincfg.c - 1 - board\NuPinConfig\nutool_pincfg.c - - - - - board_dev.c - 1 - board\board_dev.c - - - - - nutool_modclkcfg.c - 1 - board\NuClockConfig\nutool_modclkcfg.c - - - - - system_M480.c - 1 - ..\libraries\m480\Device\Nuvoton\M480\Source\system_M480.c - - - - - startup_M480.s - 2 - ..\libraries\m480\Device\Nuvoton\M480\Source\ARM\startup_M480.s - - - - - drv_fmc.c - 1 - ..\libraries\m480\rtt_port\drv_fmc.c - - - - - drv_bpwm.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm.c - - - - - drv_eadc.c - 1 - ..\libraries\m480\rtt_port\drv_eadc.c - - - - - drv_common.c - 1 - ..\libraries\m480\rtt_port\drv_common.c - - - - - drv_bpwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_bpwm_capture.c - - - - - drv_timer.c - 1 - ..\libraries\m480\rtt_port\drv_timer.c - - - - - drv_pdma.c - 1 - ..\libraries\m480\rtt_port\drv_pdma.c - - - - - drv_emac.c - 1 - ..\libraries\m480\rtt_port\drv_emac.c - - - - - drv_usbd.c - 1 - ..\libraries\m480\rtt_port\drv_usbd.c - - - - - drv_clk.c - 1 - ..\libraries\m480\rtt_port\drv_clk.c - - - - - drv_trng.c - 1 - ..\libraries\m480\rtt_port\drv_trng.c - - - - - drv_uspi.c - 1 - ..\libraries\m480\rtt_port\drv_uspi.c - - - - - drv_tpwm.c - 1 - ..\libraries\m480\rtt_port\drv_tpwm.c - - - - - drv_crypto.c - 1 - ..\libraries\m480\rtt_port\drv_crypto.c - - - - - drv_qei.c - 1 - ..\libraries\m480\rtt_port\drv_qei.c - - - - - drv_hsusbd.c - 1 - ..\libraries\m480\rtt_port\drv_hsusbd.c - - - - - drv_spi.c - 1 - ..\libraries\m480\rtt_port\drv_spi.c - - - - - drv_uuart.c - 1 - ..\libraries\m480\rtt_port\drv_uuart.c - - - - - drv_qspi.c - 1 - ..\libraries\m480\rtt_port\drv_qspi.c - - - - - drv_scuart.c - 1 - ..\libraries\m480\rtt_port\drv_scuart.c - - - - - drv_rtc.c - 1 - ..\libraries\m480\rtt_port\drv_rtc.c - - - - - drv_gpio.c - 1 - ..\libraries\m480\rtt_port\drv_gpio.c - - - - - drv_spii2s.c - 1 - ..\libraries\m480\rtt_port\drv_spii2s.c - - - - - drv_uart.c - 1 - ..\libraries\m480\rtt_port\drv_uart.c - - - - - drv_hsotg.c - 1 - ..\libraries\m480\rtt_port\drv_hsotg.c - - - - - drv_timer_capture.c - 1 - ..\libraries\m480\rtt_port\drv_timer_capture.c - - - - - drv_ebi.c - 1 - ..\libraries\m480\rtt_port\drv_ebi.c - - - - - drv_sdh.c - 1 - ..\libraries\m480\rtt_port\drv_sdh.c - - - - - drv_wdt.c - 1 - ..\libraries\m480\rtt_port\drv_wdt.c - - - - - drv_i2c.c - 1 - ..\libraries\m480\rtt_port\drv_i2c.c - - - - - drv_epwm.c - 1 - ..\libraries\m480\rtt_port\drv_epwm.c - - - - - drv_usbhost.c - 1 - ..\libraries\m480\rtt_port\drv_usbhost.c - - - - - drv_crc.c - 1 - ..\libraries\m480\rtt_port\drv_crc.c - - - - - drv_ecap.c - 1 - ..\libraries\m480\rtt_port\drv_ecap.c - - - - - drv_i2s.c - 1 - ..\libraries\m480\rtt_port\drv_i2s.c - - - - - drv_ui2c.c - 1 - ..\libraries\m480\rtt_port\drv_ui2c.c - - - - - drv_softi2c.c - 1 - ..\libraries\m480\rtt_port\drv_softi2c.c - - - - - drv_can.c - 1 - ..\libraries\m480\rtt_port\drv_can.c - - - - - drv_epwm_capture.c - 1 - ..\libraries\m480\rtt_port\drv_epwm_capture.c - - - - - Filesystem - - - dfs_posix.c - 1 - ..\..\..\components\dfs\src\dfs_posix.c - - - - - dfs_fs.c - 1 - ..\..\..\components\dfs\src\dfs_fs.c - - - - - dfs.c - 1 - ..\..\..\components\dfs\src\dfs.c - - - - - dfs_file.c - 1 - ..\..\..\components\dfs\src\dfs_file.c - - - - - devfs.c - 1 - ..\..\..\components\dfs\filesystems\devfs\devfs.c - - - - - dfs_elm.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\dfs_elm.c - - - - - ffunicode.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ffunicode.c - - - - - ff.c - 1 - ..\..\..\components\dfs\filesystems\elmfat\ff.c - - - - - Finsh - - - shell.c - 1 - ..\..\..\components\finsh\shell.c - - - - - msh.c - 1 - ..\..\..\components\finsh\msh.c - - - - - msh_file.c - 1 - ..\..\..\components\finsh\msh_file.c - - - - - cmd.c - 1 - ..\..\..\components\finsh\cmd.c - - - - - Kernel - - - mempool.c - 1 - ..\..\..\src\mempool.c - - - - - irq.c - 1 - ..\..\..\src\irq.c - - - - - mem.c - 1 - ..\..\..\src\mem.c - - - - - object.c - 1 - ..\..\..\src\object.c - - - - - thread.c - 1 - ..\..\..\src\thread.c - - - - - kservice.c - 1 - ..\..\..\src\kservice.c - - - - - device.c - 1 - ..\..\..\src\device.c - - - - - scheduler.c - 1 - ..\..\..\src\scheduler.c - - - - - timer.c - 1 - ..\..\..\src\timer.c - - - - - clock.c - 1 - ..\..\..\src\clock.c - - - - - signal.c - 1 - ..\..\..\src\signal.c - - - - - idle.c - 1 - ..\..\..\src\idle.c - - - - - components.c - 1 - ..\..\..\src\components.c - - - - - ipc.c - 1 - ..\..\..\src\ipc.c - - - - - Libraries - - - nu_hsusbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_hsusbd.c - - - - - nu_epwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_epwm.c - - - - - nu_qspi.c - 1 - ..\libraries\m480\StdDriver\src\nu_qspi.c - - - - - nu_clk.c - 1 - ..\libraries\m480\StdDriver\src\nu_clk.c - - - - - nu_crc.c - 1 - ..\libraries\m480\StdDriver\src\nu_crc.c - - - - - nu_i2s.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2s.c - - - - - nu_trng.c - 1 - ..\libraries\m480\StdDriver\src\nu_trng.c - - - - - nu_ebi.c - 1 - ..\libraries\m480\StdDriver\src\nu_ebi.c - - - - - nu_sys.c - 1 - ..\libraries\m480\StdDriver\src\nu_sys.c - - - - - nu_ccap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ccap.c - - - - - nu_wwdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wwdt.c - - - - - nu_acmp.c - 1 - ..\libraries\m480\StdDriver\src\nu_acmp.c - - - - - nu_qei.c - 1 - ..\libraries\m480\StdDriver\src\nu_qei.c - - - - - nu_fmc.c - 1 - ..\libraries\m480\StdDriver\src\nu_fmc.c - - - - - nu_sdh.c - 1 - ..\libraries\m480\StdDriver\src\nu_sdh.c - - - - - nu_timer_pwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer_pwm.c - - - - - nu_pdma.c - 1 - ..\libraries\m480\StdDriver\src\nu_pdma.c - - - - - nu_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_i2c.c - - - - - nu_emac.c - 1 - ..\libraries\m480\StdDriver\src\nu_emac.c - - - - - nu_bpwm.c - 1 - ..\libraries\m480\StdDriver\src\nu_bpwm.c - - - - - nu_usci_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_spi.c - - - - - nu_dac.c - 1 - ..\libraries\m480\StdDriver\src\nu_dac.c - - - - - nu_wdt.c - 1 - ..\libraries\m480\StdDriver\src\nu_wdt.c - - - - - nu_can.c - 1 - ..\libraries\m480\StdDriver\src\nu_can.c - - - - - nu_spi.c - 1 - ..\libraries\m480\StdDriver\src\nu_spi.c - - - - - nu_usbd.c - 1 - ..\libraries\m480\StdDriver\src\nu_usbd.c - - - - - nu_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_uart.c - - - - - nu_crypto.c - 1 - ..\libraries\m480\StdDriver\src\nu_crypto.c - - - - - nu_eadc.c - 1 - ..\libraries\m480\StdDriver\src\nu_eadc.c - - - - - nu_sc.c - 1 - ..\libraries\m480\StdDriver\src\nu_sc.c - - - - - nu_gpio.c - 1 - ..\libraries\m480\StdDriver\src\nu_gpio.c - - - - - nu_ecap.c - 1 - ..\libraries\m480\StdDriver\src\nu_ecap.c - - - - - nu_rtc.c - 1 - ..\libraries\m480\StdDriver\src\nu_rtc.c - - - - - nu_spim.c - 1 - ..\libraries\m480\StdDriver\src\nu_spim.c - - - - - nu_usci_i2c.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_i2c.c - - - - - nu_timer.c - 1 - ..\libraries\m480\StdDriver\src\nu_timer.c - - - - - nu_usci_uart.c - 1 - ..\libraries\m480\StdDriver\src\nu_usci_uart.c - - - - - nu_scuart.c - 1 - ..\libraries\m480\StdDriver\src\nu_scuart.c - - - - - lwIP - - - netdb.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netdb.c - - - - - ip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ip.c - - - - - autoip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c - - - - - ethernet.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernet.c - - - - - netif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\netif.c - - - - - sys.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\sys.c - - - - - sockets.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\sockets.c - - - - - netifapi.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netifapi.c - - - - - tcpip.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\tcpip.c - - - - - ip4_addr.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c - - - - - dhcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c - - - - - init.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\init.c - - - - - ethernetif.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c - - - - - etharp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c - - - - - memp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\memp.c - - - - - ip4.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c - - - - - netbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\netbuf.c - - - - - raw.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\raw.c - - - - - ping.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - - - - ip4_frag.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c - - - - - tcp_out.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_out.c - - - - - lowpan6.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c - - - - - icmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c - - - - - api_lib.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_lib.c - - - - - inet_chksum.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c - - - - - stats.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\stats.c - - - - - err.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\err.c - - - - - tcp_in.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp_in.c - - - - - dns.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\dns.c - - - - - sys_arch.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c - - - - - timeouts.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\timeouts.c - - - - - igmp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c - - - - - udp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\udp.c - - - - - pbuf.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\pbuf.c - - - - - def.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\def.c - - - - - api_msg.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\api\api_msg.c - - - - - tcp.c - 1 - ..\..\..\components\net\lwip-2.0.2\src\core\tcp.c - - - - - m480_usbhostlib - - - mem_alloc.c - 1 - ..\libraries\m480\USBHostLib\src\mem_alloc.c - - - - - ehci.c - 1 - ..\libraries\m480\USBHostLib\src\ehci.c - - - - - usb_core.c - 1 - ..\libraries\m480\USBHostLib\src\usb_core.c - - - - - ohci.c - 1 - ..\libraries\m480\USBHostLib\src\ohci.c - - - - - ehci_iso.c - 1 - ..\libraries\m480\USBHostLib\src\ehci_iso.c - - - - - nu_pkgs_demo - - - usbd_cdc_vcom_echo.c - 1 - ..\libraries\nu_packages\Demo\usbd_cdc_vcom_echo.c - - - - - slcd_show_tick.c - 1 - ..\libraries\nu_packages\Demo\slcd_show_tick.c - - - - - usbd_hid_dance_mouse.c - 1 - ..\libraries\nu_packages\Demo\usbd_hid_dance_mouse.c - - - - - nu_pkgs_nau88l25 - - - audio_test.c - 1 - ..\libraries\nu_packages\AudioCodec\audio_test.c - - - - - acodec_nau88l25.c - 1 - ..\libraries\nu_packages\AudioCodec\acodec_nau88l25.c - - - - - rt_usbd - - - usbdevice_core.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice_core.c - - - - - usbdevice.c - 1 - ..\..\..\components\drivers\usb\usbdevice\core\usbdevice.c - - - - - hid.c - 1 - ..\..\..\components\drivers\usb\usbdevice\class\hid.c - - - - - rt_usbh - - - mass.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\mass.c - - - - - hub.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\hub.c - - - - - usbhost.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost.c - - - - - udisk.c - 1 - ..\..\..\components\drivers\usb\usbhost\class\udisk.c - - - - - usbhost_core.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\usbhost_core.c - - - - - driver.c - 1 - ..\..\..\components\drivers\usb\usbhost\core\driver.c - - - - - SAL - - - netdev_ipaddr.c - 1 - ..\..\..\components\net\netdev\src\netdev_ipaddr.c - - - - - netdev.c - 1 - ..\..\..\components\net\netdev\src\netdev.c - - - - - net_netdb.c - 1 - ..\..\..\components\net\sal_socket\socket\net_netdb.c - - - - - sal_socket.c - 1 - ..\..\..\components\net\sal_socket\src\sal_socket.c - - - - - af_inet_lwip.c - 1 - ..\..\..\components\net\sal_socket\impl\af_inet_lwip.c - - - - - UTest - - - utest.c - 1 - ..\..\..\components\utilities\utest\utest.c - - - - - - - - - - - - - - - - - - -
diff --git a/bsp/nuvoton/numaker-pfm-m487/rtconfig.h b/bsp/nuvoton/numaker-pfm-m487/rtconfig.h deleted file mode 100644 index 4f9e169ee4..0000000000 --- a/bsp/nuvoton/numaker-pfm-m487/rtconfig.h +++ /dev/null @@ -1,413 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 1024 - -/* kservice optimization */ - -#define RT_DEBUG -#define RT_DEBUG_COLOR - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 256 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 -#define ARCH_ARM -#define RT_USING_CPU_FFS -#define ARCH_ARM_CORTEX_M -#define ARCH_ARM_CORTEX_M4 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 2048 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 8 -#define DFS_FILESYSTEM_TYPES_MAX 4 -#define DFS_FD_MAX 32 -#define RT_USING_DFS_ELMFAT - -/* elm-chan's FatFs, Generic FAT Filesystem Module */ - -#define RT_DFS_ELM_CODE_PAGE 437 -#define RT_DFS_ELM_WORD_ACCESS -#define RT_DFS_ELM_USE_LFN_3 -#define RT_DFS_ELM_USE_LFN 3 -#define RT_DFS_ELM_LFN_UNICODE_0 -#define RT_DFS_ELM_LFN_UNICODE 0 -#define RT_DFS_ELM_MAX_LFN 255 -#define RT_DFS_ELM_DRIVES 8 -#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096 -#define RT_DFS_ELM_REENTRANT -#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SYSTEM_WORKQUEUE -#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 -#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 128 -#define RT_USING_CAN -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS -#define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_PM -#define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_RTC -#define RT_USING_SPI -#define RT_USING_QSPI -#define RT_USING_SFUD -#define RT_SFUD_USING_SFDP -#define RT_SFUD_USING_FLASH_INFO_TABLE -#define RT_SFUD_SPI_MAX_HZ 50000000 -#define RT_USING_WDT -#define RT_USING_AUDIO -#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 -#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 -#define RT_AUDIO_RECORD_PIPE_SIZE 2048 -#define RT_USING_HWCRYPTO -#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" -#define RT_HWCRYPTO_IV_MAX_SIZE 16 -#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 -#define RT_HWCRYPTO_USING_AES -#define RT_HWCRYPTO_USING_AES_ECB -#define RT_HWCRYPTO_USING_AES_CBC -#define RT_HWCRYPTO_USING_AES_CFB -#define RT_HWCRYPTO_USING_AES_CTR -#define RT_HWCRYPTO_USING_AES_OFB -#define RT_HWCRYPTO_USING_DES -#define RT_HWCRYPTO_USING_DES_ECB -#define RT_HWCRYPTO_USING_DES_CBC -#define RT_HWCRYPTO_USING_3DES -#define RT_HWCRYPTO_USING_3DES_ECB -#define RT_HWCRYPTO_USING_3DES_CBC -#define RT_HWCRYPTO_USING_SHA1 -#define RT_HWCRYPTO_USING_SHA2 -#define RT_HWCRYPTO_USING_SHA2_224 -#define RT_HWCRYPTO_USING_SHA2_256 -#define RT_HWCRYPTO_USING_SHA2_384 -#define RT_HWCRYPTO_USING_SHA2_512 -#define RT_HWCRYPTO_USING_RNG -#define RT_HWCRYPTO_USING_CRC -#define RT_HWCRYPTO_USING_CRC_07 -#define RT_HWCRYPTO_USING_CRC_8005 -#define RT_HWCRYPTO_USING_CRC_1021 -#define RT_HWCRYPTO_USING_CRC_04C11DB7 - -/* Using USB */ - -#define RT_USING_USB -#define RT_USING_USB_HOST -#define RT_USBH_MSTORAGE -#define UDISK_MOUNTPOINT "/mnt/udisk/" -#define RT_USING_USB_DEVICE -#define RT_USBD_THREAD_STACK_SZ 4096 -#define USB_VENDOR_ID 0x0FFE -#define USB_PRODUCT_ID 0x0001 -#define _RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID -#define RT_USB_DEVICE_HID_MOUSE - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - -#define RT_USING_POSIX_FS -#define RT_USING_POSIX_DEVIO - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - -#define RT_USING_SAL -#define SAL_INTERNET_CHECK - -/* protocol stack implement */ - -#define SAL_USING_LWIP -#define SAL_SOCKETS_NUM 16 - -/* Network interface device */ - -#define RT_USING_NETDEV -#define NETDEV_USING_IFCONFIG -#define NETDEV_USING_PING -#define NETDEV_USING_NETSTAT -#define NETDEV_USING_AUTO_DEFAULT -#define NETDEV_IPV4 1 -#define NETDEV_IPV6 0 - -/* light weight TCP/IP stack */ - -#define RT_USING_LWIP -#define RT_USING_LWIP202 -#define RT_LWIP_MEM_ALIGNMENT 4 -#define RT_LWIP_IGMP -#define RT_LWIP_ICMP -#define RT_LWIP_DNS -#define RT_LWIP_DHCP -#define IP_SOF_BROADCAST 1 -#define IP_SOF_BROADCAST_RECV 1 - -/* Static IPv4 Address */ - -#define RT_LWIP_IPADDR "192.168.1.30" -#define RT_LWIP_GWADDR "192.168.1.1" -#define RT_LWIP_MSKADDR "255.255.255.0" -#define RT_LWIP_UDP -#define RT_LWIP_TCP -#define RT_LWIP_RAW -#define RT_MEMP_NUM_NETCONN 8 -#define RT_LWIP_PBUF_NUM 16 -#define RT_LWIP_RAW_PCB_NUM 4 -#define RT_LWIP_UDP_PCB_NUM 4 -#define RT_LWIP_TCP_PCB_NUM 4 -#define RT_LWIP_TCP_SEG_NUM 40 -#define RT_LWIP_TCP_SND_BUF 8196 -#define RT_LWIP_TCP_WND 8196 -#define RT_LWIP_TCPTHREAD_PRIORITY 10 -#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 -#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_PRIORITY 12 -#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 -#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 -#define LWIP_NETIF_STATUS_CALLBACK 1 -#define LWIP_NETIF_LINK_CALLBACK 1 -#define SO_REUSE 1 -#define LWIP_SO_RCVTIMEO 1 -#define LWIP_SO_SNDTIMEO 1 -#define LWIP_SO_RCVBUF 1 -#define LWIP_SO_LINGER 0 -#define LWIP_NETIF_LOOPBACK 0 -#define RT_LWIP_USING_PING - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - -#define PKG_USING_FAL -#define FAL_DEBUG_CONFIG -#define FAL_DEBUG 1 -#define FAL_PART_HAS_TABLE_CFG -#define PKG_USING_FAL_V00400 -#define PKG_FAL_VER_NUM 0x00400 - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - - -/* Nuvoton Packages Config */ - -#define NU_PKG_USING_UTILS -#define NU_PKG_USING_DEMO -#define NU_PKG_USING_NAU88L25 - -/* Hardware Drivers Config */ - -/* On-chip Peripheral Drivers */ - -#define SOC_SERIES_M480 -#define BSP_USE_STDDRIVER_SOURCE -#define BSP_USING_PDMA -#define NU_PDMA_MEMFUN_ACTOR_MAX 2 -#define NU_PDMA_SGTBL_POOL_SIZE 16 -#define BSP_USING_FMC -#define BSP_USING_GPIO -#define BSP_USING_CLK -#define NU_CLK_INVOKE_WKTMR -#define BSP_USING_EMAC -#define NU_EMAC_PDMA_MEMCOPY -#define NU_EMAC_PDMA_MEMCOPY_THRESHOLD 128 -#define BSP_USING_RTC -#define NU_RTC_SUPPORT_MSH_CMD -#define BSP_USING_TMR -#define BSP_USING_UART -#define BSP_USING_UART0 -#define BSP_USING_I2C -#define BSP_USING_I2C1 -#define BSP_USING_I2C2 -#define BSP_USING_SDH -#define BSP_USING_SDH0 -#define NU_SDH_USING_PDMA -#define NU_SDH_HOTPLUG -#define BSP_USING_SPI -#define BSP_USING_SPI_PDMA -#define BSP_USING_SPI0_NONE -#define BSP_USING_SPI1_NONE -#define BSP_USING_SPI2_NONE -#define BSP_USING_SPI3 -#define BSP_USING_I2S -#define NU_I2S_DMA_FIFO_SIZE 2048 -#define BSP_USING_QSPI -#define BSP_USING_QSPI0 -#define BSP_USING_QSPI0_PDMA -#define BSP_USING_CRYPTO -#define BSP_USING_TRNG -#define BSP_USING_CRC -#define NU_CRC_USE_PDMA -#define BSP_USING_WDT -#define BSP_USING_USBD -#define BSP_USING_HSUSBH -#define NU_USBHOST_HUB_POLLING_INTERVAL 100 - -/* On-board Peripheral Drivers */ - -#define BSP_USING_NULINKME -#define BOARD_USING_IP101GR -#define BOARD_USING_NAU88L25 -#define BOARD_USING_STORAGE_SDCARD -#define BOARD_USING_STORAGE_SPIFLASH -#define BOARD_USING_HSUSBH_USBD - -/* Board extended module drivers */ - - -#endif diff --git a/bsp/nuvoton/numaker-pfm-m487/rtconfig.py b/bsp/nuvoton/numaker-pfm-m487/rtconfig.py index 902a2bdce9..7beeafe88a 100644 --- a/bsp/nuvoton/numaker-pfm-m487/rtconfig.py +++ b/bsp/nuvoton/numaker-pfm-m487/rtconfig.py @@ -130,3 +130,11 @@ elif PLATFORM == 'iar': EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = '' + +def dist_handle(BSP_ROOT, dist_dir): + import sys + cwd_path = os.getcwd() + sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools')) + from sdk_dist import dist_do_building + dist_do_building(BSP_ROOT, dist_dir) + diff --git a/bsp/nuvoton/tools/sdk_dist.py b/bsp/nuvoton/tools/sdk_dist.py new file mode 100644 index 0000000000..d76f7fcfc8 --- /dev/null +++ b/bsp/nuvoton/tools/sdk_dist.py @@ -0,0 +1,39 @@ +import os +import sys +import shutil +cwd_path = os.getcwd() +sys.path.append(os.path.join(os.path.dirname(cwd_path), 'rt-thread', 'tools')) + +def dist_modify_relative_path(board_kconfig_path): + # Read in the file + with open(board_kconfig_path, 'r') as file : + filedata = file.read() + + # Replace the target string + filedata = filedata.replace('$BSP_DIR/../libraries', './libraries') + + # Write the file out again + with open(board_kconfig_path, 'w') as file: + file.write(filedata) + +# BSP dist function +def dist_do_building(BSP_ROOT, dist_dir): + from mkdist import bsp_copy_files + import rtconfig + + library_path = os.path.join(os.path.dirname(BSP_ROOT), 'libraries') + library_dir = os.path.join(dist_dir, 'libraries') + + print('=> copy nuvoton bsp drivers') + bsp_copy_files(os.path.join(library_path, rtconfig.BSP_LIBRARY_TYPE), + os.path.join(library_dir, rtconfig.BSP_LIBRARY_TYPE)) + + print('=> copy nu_packages') + bsp_copy_files(os.path.join(library_path, 'nu_packages'), + os.path.join(library_dir, 'nu_packages')) + + print('=> copy Kconfig') + shutil.copyfile(os.path.join(library_path, 'Kconfig'), os.path.join(library_dir, 'Kconfig')) + + print('=> Modify libraries relative path in board/Kconfig ') + dist_modify_relative_path(os.path.join(dist_dir, 'board', 'Kconfig')) \ No newline at end of file From eef0a2d810447c50ac06b6c63de2169ade05d0d4 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 29 Dec 2021 02:33:40 -0500 Subject: [PATCH 18/65] [qmeu] chore --- bsp/qemu-vexpress-a9/applications/main.c | 2 +- bsp/qemu-vexpress-a9/drivers/drv_clcd.c | 6 ++++-- bsp/stm32/libraries/HAL_Drivers/drv_lcd.c | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bsp/qemu-vexpress-a9/applications/main.c b/bsp/qemu-vexpress-a9/applications/main.c index e8ef51657e..b9364eee2f 100644 --- a/bsp/qemu-vexpress-a9/applications/main.c +++ b/bsp/qemu-vexpress-a9/applications/main.c @@ -14,7 +14,7 @@ int main(void) { - printf("hello rt-thread\n"); + printf("Hello RT-Thread!\n"); return 0; } diff --git a/bsp/qemu-vexpress-a9/drivers/drv_clcd.c b/bsp/qemu-vexpress-a9/drivers/drv_clcd.c index 2d012dca84..3fe2bd58d3 100644 --- a/bsp/qemu-vexpress-a9/drivers/drv_clcd.c +++ b/bsp/qemu-vexpress-a9/drivers/drv_clcd.c @@ -75,13 +75,15 @@ static rt_err_t drv_clcd_control(struct rt_device *device, int cmd, void *args) RT_ASSERT(info != RT_NULL); info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; - // info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_ARGB888; info->bits_per_pixel= 16; info->width = lcd->width; info->height = lcd->height; info->framebuffer = lcd->fb; } break; + + default: + return -RT_EINVAL; } return RT_EOK; @@ -109,7 +111,7 @@ int drv_clcd_hw_init(void) _lcd.width = CLCD_WIDTH; _lcd.height = CLCD_HEIGHT; - _lcd.fb = rt_malloc(_lcd.width * _lcd.height * 2); + _lcd.fb = rt_malloc(_lcd.width * _lcd.height * 2 /*RGB565 2 Bytes*/); if (_lcd.fb == NULL) { rt_kprintf("initialize frame buffer failed!\n"); diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c b/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c index 96c61835e6..a0db14fc1a 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_lcd.c @@ -90,6 +90,9 @@ static rt_err_t drv_lcd_control(struct rt_device *device, int cmd, void *args) info->framebuffer = lcd->lcd_info.framebuffer; } break; + + default: + return -RT_EINVAL; } return RT_EOK; From 76cab376adf0cf52a17d11e633be711ba6149c4a Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 14 Jan 2022 23:31:59 -0500 Subject: [PATCH 19/65] =?UTF-8?q?[libc]=20=E8=B0=83=E6=95=B4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/{nogcc => extension}/SConscript | 0 .../compilers/common/{nogcc => extension}/fcntl.h | 0 .../libc/compilers/common/extension/readme.md | 4 ++++ .../common/{nogcc => extension}/sys/errno.h | 0 .../common/{nogcc => extension}/sys/select.h | 0 .../common/{nogcc => extension}/sys/stat.h | 0 .../common/{nogcc => extension}/sys/types.h | 0 .../common/{nogcc => extension}/sys/unistd.h | 0 .../common/{nogcc => extension}/unistd.h | 0 components/libc/compilers/common/nogcc/readme.md | 3 --- .../libc/compilers/gcc/newlib/legacy/SConscript | 15 --------------- .../libc/compilers/{gcc => }/newlib/README.md | 0 .../libc/compilers/{gcc => }/newlib/SConscript | 0 .../libc/compilers/{gcc => }/newlib/fcntl.h | 0 .../compilers/{gcc => newlib/legacy}/SConscript | 0 .../{gcc => }/newlib/legacy/_select/SConscript | 0 .../{gcc => }/newlib/legacy/_select/readme.md | 0 .../{gcc => }/newlib/legacy/_select/sys/select.h | 0 .../libc/compilers/{gcc => }/newlib/libc_syms.c | 0 .../compilers/{gcc => }/newlib/machine/time.h | 0 .../libc/compilers/{gcc => }/newlib/syscalls.c | 0 21 files changed, 4 insertions(+), 18 deletions(-) rename components/libc/compilers/common/{nogcc => extension}/SConscript (100%) rename components/libc/compilers/common/{nogcc => extension}/fcntl.h (100%) create mode 100644 components/libc/compilers/common/extension/readme.md rename components/libc/compilers/common/{nogcc => extension}/sys/errno.h (100%) rename components/libc/compilers/common/{nogcc => extension}/sys/select.h (100%) rename components/libc/compilers/common/{nogcc => extension}/sys/stat.h (100%) rename components/libc/compilers/common/{nogcc => extension}/sys/types.h (100%) rename components/libc/compilers/common/{nogcc => extension}/sys/unistd.h (100%) rename components/libc/compilers/common/{nogcc => extension}/unistd.h (100%) delete mode 100644 components/libc/compilers/common/nogcc/readme.md delete mode 100644 components/libc/compilers/gcc/newlib/legacy/SConscript rename components/libc/compilers/{gcc => }/newlib/README.md (100%) rename components/libc/compilers/{gcc => }/newlib/SConscript (100%) rename components/libc/compilers/{gcc => }/newlib/fcntl.h (100%) rename components/libc/compilers/{gcc => newlib/legacy}/SConscript (100%) rename components/libc/compilers/{gcc => }/newlib/legacy/_select/SConscript (100%) rename components/libc/compilers/{gcc => }/newlib/legacy/_select/readme.md (100%) rename components/libc/compilers/{gcc => }/newlib/legacy/_select/sys/select.h (100%) rename components/libc/compilers/{gcc => }/newlib/libc_syms.c (100%) rename components/libc/compilers/{gcc => }/newlib/machine/time.h (100%) rename components/libc/compilers/{gcc => }/newlib/syscalls.c (100%) diff --git a/components/libc/compilers/common/nogcc/SConscript b/components/libc/compilers/common/extension/SConscript similarity index 100% rename from components/libc/compilers/common/nogcc/SConscript rename to components/libc/compilers/common/extension/SConscript diff --git a/components/libc/compilers/common/nogcc/fcntl.h b/components/libc/compilers/common/extension/fcntl.h similarity index 100% rename from components/libc/compilers/common/nogcc/fcntl.h rename to components/libc/compilers/common/extension/fcntl.h diff --git a/components/libc/compilers/common/extension/readme.md b/components/libc/compilers/common/extension/readme.md new file mode 100644 index 0000000000..ca0df69246 --- /dev/null +++ b/components/libc/compilers/common/extension/readme.md @@ -0,0 +1,4 @@ +## Attentions + +This folder is "common" for toolchains, which only support ISO C, as an extension part, such as Keil-MDK and IAR. + diff --git a/components/libc/compilers/common/nogcc/sys/errno.h b/components/libc/compilers/common/extension/sys/errno.h similarity index 100% rename from components/libc/compilers/common/nogcc/sys/errno.h rename to components/libc/compilers/common/extension/sys/errno.h diff --git a/components/libc/compilers/common/nogcc/sys/select.h b/components/libc/compilers/common/extension/sys/select.h similarity index 100% rename from components/libc/compilers/common/nogcc/sys/select.h rename to components/libc/compilers/common/extension/sys/select.h diff --git a/components/libc/compilers/common/nogcc/sys/stat.h b/components/libc/compilers/common/extension/sys/stat.h similarity index 100% rename from components/libc/compilers/common/nogcc/sys/stat.h rename to components/libc/compilers/common/extension/sys/stat.h diff --git a/components/libc/compilers/common/nogcc/sys/types.h b/components/libc/compilers/common/extension/sys/types.h similarity index 100% rename from components/libc/compilers/common/nogcc/sys/types.h rename to components/libc/compilers/common/extension/sys/types.h diff --git a/components/libc/compilers/common/nogcc/sys/unistd.h b/components/libc/compilers/common/extension/sys/unistd.h similarity index 100% rename from components/libc/compilers/common/nogcc/sys/unistd.h rename to components/libc/compilers/common/extension/sys/unistd.h diff --git a/components/libc/compilers/common/nogcc/unistd.h b/components/libc/compilers/common/extension/unistd.h similarity index 100% rename from components/libc/compilers/common/nogcc/unistd.h rename to components/libc/compilers/common/extension/unistd.h diff --git a/components/libc/compilers/common/nogcc/readme.md b/components/libc/compilers/common/nogcc/readme.md deleted file mode 100644 index b10940d003..0000000000 --- a/components/libc/compilers/common/nogcc/readme.md +++ /dev/null @@ -1,3 +0,0 @@ -## Attentions - -This folder is "common" for toolchains excluding gcc. \ No newline at end of file diff --git a/components/libc/compilers/gcc/newlib/legacy/SConscript b/components/libc/compilers/gcc/newlib/legacy/SConscript deleted file mode 100644 index 4c815c49b8..0000000000 --- a/components/libc/compilers/gcc/newlib/legacy/SConscript +++ /dev/null @@ -1,15 +0,0 @@ -# RT-Thread building script for bridge - -import os -from building import * - -cwd = GetCurrentDir() -objs = [] -list = os.listdir(cwd) - -for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) - -Return('objs') diff --git a/components/libc/compilers/gcc/newlib/README.md b/components/libc/compilers/newlib/README.md similarity index 100% rename from components/libc/compilers/gcc/newlib/README.md rename to components/libc/compilers/newlib/README.md diff --git a/components/libc/compilers/gcc/newlib/SConscript b/components/libc/compilers/newlib/SConscript similarity index 100% rename from components/libc/compilers/gcc/newlib/SConscript rename to components/libc/compilers/newlib/SConscript diff --git a/components/libc/compilers/gcc/newlib/fcntl.h b/components/libc/compilers/newlib/fcntl.h similarity index 100% rename from components/libc/compilers/gcc/newlib/fcntl.h rename to components/libc/compilers/newlib/fcntl.h diff --git a/components/libc/compilers/gcc/SConscript b/components/libc/compilers/newlib/legacy/SConscript similarity index 100% rename from components/libc/compilers/gcc/SConscript rename to components/libc/compilers/newlib/legacy/SConscript diff --git a/components/libc/compilers/gcc/newlib/legacy/_select/SConscript b/components/libc/compilers/newlib/legacy/_select/SConscript similarity index 100% rename from components/libc/compilers/gcc/newlib/legacy/_select/SConscript rename to components/libc/compilers/newlib/legacy/_select/SConscript diff --git a/components/libc/compilers/gcc/newlib/legacy/_select/readme.md b/components/libc/compilers/newlib/legacy/_select/readme.md similarity index 100% rename from components/libc/compilers/gcc/newlib/legacy/_select/readme.md rename to components/libc/compilers/newlib/legacy/_select/readme.md diff --git a/components/libc/compilers/gcc/newlib/legacy/_select/sys/select.h b/components/libc/compilers/newlib/legacy/_select/sys/select.h similarity index 100% rename from components/libc/compilers/gcc/newlib/legacy/_select/sys/select.h rename to components/libc/compilers/newlib/legacy/_select/sys/select.h diff --git a/components/libc/compilers/gcc/newlib/libc_syms.c b/components/libc/compilers/newlib/libc_syms.c similarity index 100% rename from components/libc/compilers/gcc/newlib/libc_syms.c rename to components/libc/compilers/newlib/libc_syms.c diff --git a/components/libc/compilers/gcc/newlib/machine/time.h b/components/libc/compilers/newlib/machine/time.h similarity index 100% rename from components/libc/compilers/gcc/newlib/machine/time.h rename to components/libc/compilers/newlib/machine/time.h diff --git a/components/libc/compilers/gcc/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c similarity index 100% rename from components/libc/compilers/gcc/newlib/syscalls.c rename to components/libc/compilers/newlib/syscalls.c From c3162f373fbd6bacae946f717f41e271ffbe0835 Mon Sep 17 00:00:00 2001 From: "Man, Jianting (Meco)" <920369182@qq.com> Date: Sun, 16 Jan 2022 22:21:39 -0500 Subject: [PATCH 20/65] =?UTF-8?q?[libc][lwip]=20=E4=BF=AE=E5=A4=8Dioctl?= =?UTF-8?q?=E4=B8=8Elwip=20socket=E5=AE=9A=E4=B9=89=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=20(#5504)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [lwip] 修复ioctl与lwip socket定义冲突的问题 * format sys/ioctl.h --- components/libc/compilers/common/sys/ioctl.h | 76 ++++++++++++++------ components/net/lwip-1.4.1/src/lwipopts.h | 1 + components/net/lwip-2.0.2/src/lwipopts.h | 1 + components/net/lwip-2.0.3/src/lwipopts.h | 1 + components/net/lwip-2.1.2/src/lwipopts.h | 1 + 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/components/libc/compilers/common/sys/ioctl.h b/components/libc/compilers/common/sys/ioctl.h index c663025c1f..0b1edca699 100644 --- a/components/libc/compilers/common/sys/ioctl.h +++ b/components/libc/compilers/common/sys/ioctl.h @@ -11,34 +11,79 @@ #ifndef __SYS_IOCTL_H__ #define __SYS_IOCTL_H__ -#include - #ifdef _WIN32 #include #endif -struct winsize { +struct winsize +{ unsigned short ws_row; unsigned short ws_col; unsigned short ws_xpixel; unsigned short ws_ypixel; }; -#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) ) +/* + * Direction bits, which any architecture can choose to override + * before including this file. + */ + +#ifndef _IOC_NONE #define _IOC_NONE 0U +#endif + +#ifndef _IOC_WRITE #define _IOC_WRITE 1U +#endif + +#ifndef _IOC_READ #define _IOC_READ 2U +#endif -#if !defined (_WIN32) && !defined (__TASKING__) -#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0) -#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c)) -#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c)) -#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c)) +#ifndef _IOC +#define _IOC(a,b,c,d) (((a)<<30) | ((b)<<8) | (c) | ((d)<<16)) +#endif +#ifndef _IO +#define _IO(a,b) _IOC(_IOC_NONE, (a), (b), 0) +#endif + +#ifndef _IOW +#define _IOW(a,b,c) _IOC(_IOC_WRITE, (a), (b), sizeof(c)) +#endif + +#ifndef _IOR +#define _IOR(a,b,c) _IOC(_IOC_READ, (a), (b), sizeof(c)) +#endif + +#ifndef _IOWR +#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE, (a), (b), sizeof(c)) +#endif + +#ifndef FIONREAD #define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ +#endif + +#ifndef FIONBIO #define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ #endif + +#ifndef FIOASYNC +#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */ +#endif + +#ifndef FIONWRITE #define FIONWRITE _IOR('f', 121, int) /* get # bytes outstanding in send queue */ +#endif + +/* Socket I/O Controls */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */ +#endif #define TCGETS 0x5401 #define TCSETS 0x5402 @@ -66,18 +111,12 @@ struct winsize { #define TIOCMSET 0x5418 #define TIOCGSOFTCAR 0x5419 #define TIOCSSOFTCAR 0x541A -#ifndef FIONREAD -#define FIONREAD 0x541B -#endif #define TIOCINQ FIONREAD #define TIOCLINUX 0x541C #define TIOCCONS 0x541D #define TIOCGSERIAL 0x541E #define TIOCSSERIAL 0x541F #define TIOCPKT 0x5420 -#ifndef FIONBIO -#define FIONBIO 0x5421 -#endif #define TIOCNOTTY 0x5422 #define TIOCSETD 0x5423 #define TIOCGETD 0x5424 @@ -103,10 +142,6 @@ struct winsize { #define FIONCLEX 0x5450 #define FIOCLEX 0x5451 -#ifndef _WIN32 -#define FIOASYNC 0x5452 -#endif - #define TIOCSERCONFIG 0x5453 #define TIOCSERGWILD 0x5454 #define TIOCSERSWILD 0x5455 @@ -168,9 +203,6 @@ struct winsize { #define SIOCSPGRP 0x8902 #define FIOGETOWN 0x8903 #define SIOCGPGRP 0x8904 -#ifndef SIOCATMARK -#define SIOCATMARK 0x8905 -#endif #define SIOCGSTAMP 0x8906 #define SIOCGSTAMPNS 0x8907 diff --git a/components/net/lwip-1.4.1/src/lwipopts.h b/components/net/lwip-1.4.1/src/lwipopts.h index d7a6807cbd..03930c8741 100644 --- a/components/net/lwip-1.4.1/src/lwipopts.h +++ b/components/net/lwip-1.4.1/src/lwipopts.h @@ -526,6 +526,7 @@ #define LWIP_SOCKET 1 #endif #include +#include /* * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h index 5c99013d2e..2de6aa1052 100644 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ b/components/net/lwip-2.0.2/src/lwipopts.h @@ -565,6 +565,7 @@ #define LWIP_SOCKET 1 #endif #include +#include /* * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. diff --git a/components/net/lwip-2.0.3/src/lwipopts.h b/components/net/lwip-2.0.3/src/lwipopts.h index 5c99013d2e..2de6aa1052 100644 --- a/components/net/lwip-2.0.3/src/lwipopts.h +++ b/components/net/lwip-2.0.3/src/lwipopts.h @@ -565,6 +565,7 @@ #define LWIP_SOCKET 1 #endif #include +#include /* * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. diff --git a/components/net/lwip-2.1.2/src/lwipopts.h b/components/net/lwip-2.1.2/src/lwipopts.h index ca70de012a..701449c108 100644 --- a/components/net/lwip-2.1.2/src/lwipopts.h +++ b/components/net/lwip-2.1.2/src/lwipopts.h @@ -568,6 +568,7 @@ #define LWIP_SOCKET 1 #endif #include +#include /* * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. From 169fca84f7799bb3fa2475978f4f97ca9dd35bb4 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sat, 15 Jan 2022 23:20:45 -0500 Subject: [PATCH 21/65] [ymodem] silent warnings --- components/utilities/ymodem/ry_sy.c | 7 ++----- components/utilities/ymodem/ymodem.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/components/utilities/ymodem/ry_sy.c b/components/utilities/ymodem/ry_sy.c index b77bd7abc2..d61b0cde58 100644 --- a/components/utilities/ymodem/ry_sy.c +++ b/components/utilities/ymodem/ry_sy.c @@ -15,8 +15,6 @@ #include #include #include - -#include #include #include @@ -115,7 +113,7 @@ static enum rym_code _rym_send_begin( rt_kprintf("error open file.\n"); return RYM_ERR_FILE; } - sprintf((char *)buf, "%s%c%ld", (char *) & (cctx->fpath[1]), insert_0, file_buf.st_size); + rt_sprintf((char *)buf, "%s%c%d", (char *) & (cctx->fpath[1]), insert_0, file_buf.st_size); return RYM_CODE_SOH; } @@ -140,8 +138,7 @@ static enum rym_code _rym_send_data( if (read_size < len) { rt_memset(buf + read_size, 0x1A, len - read_size); - /* stage = RYM_STAGE_FINISHING */ - ctx->stage = 4; + ctx->stage = RYM_STAGE_FINISHING; } return RYM_CODE_SOH; diff --git a/components/utilities/ymodem/ymodem.h b/components/utilities/ymodem/ymodem.h index 7006cf268d..2f05e4f2f2 100644 --- a/components/utilities/ymodem/ymodem.h +++ b/components/utilities/ymodem/ymodem.h @@ -72,7 +72,7 @@ enum rym_code enum rym_stage { - RYM_STAGE_NONE, + RYM_STAGE_NONE = 0, /* set when C is send */ RYM_STAGE_ESTABLISHING, /* set when we've got the packet 0 and sent ACK and second C */ From 77a5ddf9aef1e784023ce5e12732ca26081de271 Mon Sep 17 00:00:00 2001 From: Siwei Xu Date: Sat, 8 Jan 2022 19:26:29 +0800 Subject: [PATCH 22/65] [bsp/n32g452xx] add rt_pin_get support --- bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c | 23 +++++++++++++++++-- .../n32g452xx-mini-system/applications/main.c | 13 +++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c b/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c index 56cdfadf6c..f41d4dcae0 100644 --- a/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c +++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c @@ -20,9 +20,9 @@ #define __N32_PIN(index, rcc, gpio, gpio_index) \ { \ 0, RCC_##rcc##_PERIPH_GPIO##gpio, GPIO##gpio, GPIO_PIN_##gpio_index \ -, GPIO##gpio##_PORT_SOURCE, GPIO_PIN_SOURCE##gpio_index \ +, GPIO##gpio##_PORT_SOURCE, GPIO_PIN_SOURCE##gpio_index, "P" #gpio "." #gpio_index \ } -#define __N32_PIN_DEFAULT {-1, 0, 0, 0, 0, 0} +#define __N32_PIN_DEFAULT {-1, 0, 0, 0, 0, 0, ""} /* N32 GPIO driver */ struct pin_index @@ -33,6 +33,7 @@ struct pin_index uint32_t pin; uint8_t port_source; uint8_t pin_source; + const char* name; }; static const struct pin_index pins[] = @@ -473,6 +474,23 @@ const struct pin_index *get_pin(uint8_t pin) return index; }; +rt_base_t n32_pin_get(const char *name) +{ + rt_base_t i; + + for (i = 0; i < ITEM_NUM(pins); i++) + { + if (rt_strcmp(pins[i].name, name) == 0) + { + /* in get_pin function, use pin parameter as index of pins array */ + return i; + } + } + + /* refers content of pins array, map to __N32_PIN_DEFAULT */ + return 0; +} + void n32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) { const struct pin_index *index; @@ -754,6 +772,7 @@ const static struct rt_pin_ops _n32_pin_ops = n32_pin_attach_irq, n32_pin_dettach_irq, n32_pin_irq_enable, + n32_pin_get }; int n32_hw_pin_init(void) diff --git a/bsp/n32g452xx/n32g452xx-mini-system/applications/main.c b/bsp/n32g452xx/n32g452xx-mini-system/applications/main.c index 11fdf6f84b..fcb0110413 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/applications/main.c +++ b/bsp/n32g452xx/n32g452xx-mini-system/applications/main.c @@ -12,19 +12,24 @@ #include /* defined the LED1 pin: PB5 */ -#define LED1_PIN 57 +#define LED1_NAME "PB.5" +rt_base_t led1_pin; int main(void) { uint32_t Speed = 200; + + /* get LED1 pin id by name */ + led1_pin = rt_pin_get(LED1_NAME); + /* set LED1 pin mode to output */ - rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + rt_pin_mode(led1_pin, PIN_MODE_OUTPUT); while (1) { - rt_pin_write(LED1_PIN, PIN_LOW); + rt_pin_write(led1_pin, PIN_LOW); rt_thread_mdelay(Speed); - rt_pin_write(LED1_PIN, PIN_HIGH); + rt_pin_write(led1_pin, PIN_HIGH); rt_thread_mdelay(Speed); } } From 94116501fe4ed00d0e676ac4f7a1f08c0230a083 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 17 Jan 2022 13:16:14 -0500 Subject: [PATCH 23/65] =?UTF-8?q?[stm32][at=20esp8266][kconfig]=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0esp8266=E9=85=8D=E7=BD=AE=E9=80=89=E9=A1=B9?= =?UTF-8?q?=E6=8E=A5=E7=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32/stm32f407-atk-explorer/board/Kconfig | 3 +++ bsp/stm32/stm32l475-atk-pandora/board/Kconfig | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig index 2684672d54..7fcdba54c8 100644 --- a/bsp/stm32/stm32f407-atk-explorer/board/Kconfig +++ b/bsp/stm32/stm32f407-atk-explorer/board/Kconfig @@ -438,6 +438,7 @@ menu "Board extended module Drivers" select PKG_USING_AT_DEVICE select AT_DEVICE_USING_ESP8266 select AT_DEVICE_ESP8266_SAMPLE + select AT_DEVICE_ESP8266_SAMPLE_BSP_TAKEOVER if BSP_USING_AT_ESP8266 @@ -457,6 +458,8 @@ menu "Board extended module Drivers" int "The maximum length of receive line buffer" default 512 + comment "May adjust RT_SERIAL_RB_BUFSZ up to 512 if using the Serial V1 device driver" + endif endmenu diff --git a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig index 767c446a13..d17a1f542b 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig +++ b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig @@ -473,8 +473,10 @@ menu "Board extended module Drivers" select PKG_USING_AT_DEVICE select AT_DEVICE_USING_ESP8266 select AT_DEVICE_ESP8266_SAMPLE + select AT_DEVICE_ESP8266_SAMPLE_BSP_TAKEOVER if BSP_USING_AT_ESP8266 + config ESP8266_SAMPLE_WIFI_SSID string "WIFI ssid" default "rtthread" @@ -490,6 +492,9 @@ menu "Board extended module Drivers" config ESP8266_SAMPLE_RECV_BUFF_LEN int "The maximum length of receive line buffer" default 512 + + comment "May adjust RT_SERIAL_RB_BUFSZ up to 512 if using the Serial V1 device driver" + endif config BSP_USING_NRF24L01 From d6d84ed05593184ea82d9e888917e6397f58b1f6 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 17 Jan 2022 18:58:18 -0500 Subject: [PATCH 24/65] [kernel][pm] beautify code --- src/idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idle.c b/src/idle.c index e3b16c856c..7ea0cd15de 100644 --- a/src/idle.c +++ b/src/idle.c @@ -241,7 +241,6 @@ static void rt_defunct_execute(void) } } -extern void rt_system_power_manager(void); static void rt_thread_idle_entry(void *parameter) { #ifdef RT_USING_SMP @@ -275,6 +274,7 @@ static void rt_thread_idle_entry(void *parameter) #endif /* RT_USING_SMP */ #ifdef RT_USING_PM + void rt_system_power_manager(void); rt_system_power_manager(); #endif /* RT_USING_PM */ } From a095de14c2691fb6e272974a2a76b9587bf60242 Mon Sep 17 00:00:00 2001 From: Blues-Jiang Date: Tue, 18 Jan 2022 16:51:46 +0800 Subject: [PATCH 25/65] Init update. --- bsp/n32g452xx/Libraries/rt_drivers/drv_adc.c | 6 +- bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c | 283 +++++++++------ bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.c | 7 +- .../Libraries/rt_drivers/drv_usart.c | 104 +++++- bsp/n32g452xx/n32g452xx-mini-system/.config | 139 +++++--- .../n32g452xx-mini-system/board/Kconfig | 153 +++++++- .../n32g452xx-mini-system/board/board.c | 1 + .../n32g452xx-mini-system/board/board.h | 2 +- .../n32g452xx-mini-system/board/msp/n32_msp.c | 330 ++++++++++++++++-- .../n32g452xx-mini-system/board/msp/n32_msp.h | 1 + .../n32g452xx-mini-system/rtconfig.h | 43 ++- 11 files changed, 847 insertions(+), 222 deletions(-) diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_adc.c b/bsp/n32g452xx/Libraries/rt_drivers/drv_adc.c index 8223a54e6a..992af05e52 100644 --- a/bsp/n32g452xx/Libraries/rt_drivers/drv_adc.c +++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_adc.c @@ -124,9 +124,9 @@ static rt_err_t n32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channe ADC_InitStructure.ChsNumber = 1; ADC_Init(n32_adc_handler, &ADC_InitStructure); - if (((n32_adc_handler == ADC2) || (n32_adc_handler == ADC2)) - && ((n32_adc_get_channel(channel) == ADC_CH_16) - || (n32_adc_get_channel(channel) == ADC_CH_18))) + if (((n32_adc_handler == ADC1) || (n32_adc_handler == ADC2)) + && ((n32_adc_get_channel(channel) == ADC_CH_16) + || (n32_adc_get_channel(channel) == ADC_CH_18))) { ADC_EnableTempSensorVrefint(ENABLE); } diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c b/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c index f41d4dcae0..eece7aa780 100644 --- a/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c +++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_gpio.c @@ -15,7 +15,9 @@ #ifdef RT_USING_PIN -#define N32G45X_PIN_NUMBERS 64 //[48, 64, 100, 144 ] +#ifndef N32G45X_PIN_NUMBERS + #define N32G45X_PIN_NUMBERS 64//[48, 64, 80, 100, 128 ] +#endif #define __N32_PIN(index, rcc, gpio, gpio_index) \ { \ @@ -88,16 +90,15 @@ static const struct pin_index pins[] = __N32_PIN(46, APB2, B, 9), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - -#endif -#if (N32G45X_PIN_NUMBERS == 64) + #endif + #if (N32G45X_PIN_NUMBERS == 64) __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(2, APB2, C, 13), __N32_PIN(3, APB2, C, 14), __N32_PIN(4, APB2, C, 15), - __N32_PIN(5, APB2, D, 0), - __N32_PIN(6, APB2, D, 1), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(8, APB2, C, 0), __N32_PIN(9, APB2, C, 1), @@ -156,6 +157,89 @@ static const struct pin_index pins[] = __N32_PIN(62, APB2, B, 9), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, + #endif + #if (N32G45X_PIN_NUMBERS == 80) + __N32_PIN_DEFAULT, + __N32_PIN(1, APB2, E, 2), + __N32_PIN(2, APB2, E, 3), + __N32_PIN_DEFAULT, + __N32_PIN(4, APB2, C, 13), + __N32_PIN(5, APB2, C, 14), + __N32_PIN(6, APB2, C, 15), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, + __N32_PIN(10, APB2, C, 0), + __N32_PIN(11, APB2, C, 1), + __N32_PIN(12, APB2, C, 2), + __N32_PIN(13, APB2, C, 3), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, + __N32_PIN(16, APB2, A, 0), + __N32_PIN(17, APB2, A, 1), + __N32_PIN(18, APB2, A, 2), + __N32_PIN(19, APB2, A, 3), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, + __N32_PIN(22, APB2, A, 4), + __N32_PIN(23, APB2, A, 5), + __N32_PIN(24, APB2, A, 6), + __N32_PIN(25, APB2, A, 7), + __N32_PIN(26, APB2, C, 4), + __N32_PIN(27, APB2, C, 5), + __N32_PIN(28, APB2, B, 0), + __N32_PIN(29, APB2, B, 1), + __N32_PIN(30, APB2, B, 2), + __N32_PIN(31, APB2, E, 7), + __N32_PIN(32, APB2, E, 8), + __N32_PIN(33, APB2, E, 9), + __N32_PIN(34, APB2, E, 10), + __N32_PIN(35, APB2, E, 11), + __N32_PIN(36, APB2, E, 12), + __N32_PIN(37, APB2, E, 13), + __N32_PIN(38, APB2, B, 10), + __N32_PIN(39, APB2, B, 11), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, + __N32_PIN(42, APB2, B, 12), + __N32_PIN(43, APB2, B, 13), + __N32_PIN(44, APB2, B, 14), + __N32_PIN(45, APB2, B, 15), + __N32_PIN(46, APB2, D, 8), + __N32_PIN(47, APB2, D, 9), + __N32_PIN(48, APB2, D, 10), + __N32_PIN(49, APB2, D, 14), + __N32_PIN(50, APB2, D, 15), + __N32_PIN(51, APB2, C, 6), + __N32_PIN(52, APB2, C, 7), + __N32_PIN(53, APB2, C, 8), + __N32_PIN(54, APB2, C, 9), + __N32_PIN(55, APB2, A, 8), + __N32_PIN(56, APB2, A, 9), + __N32_PIN(57, APB2, A, 10), + __N32_PIN(58, APB2, A, 11), + __N32_PIN(59, APB2, A, 12), + __N32_PIN(60, APB2, A, 13), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, + __N32_PIN(63, APB2, A, 14), + __N32_PIN(64, APB2, A, 15), + __N32_PIN(65, APB2, C, 10), + __N32_PIN(66, APB2, C, 11), + __N32_PIN(67, APB2, C, 12), + __N32_PIN(68, APB2, D, 0), + __N32_PIN(69, APB2, D, 1), + __N32_PIN(70, APB2, D, 2), + __N32_PIN(71, APB2, B, 3), + __N32_PIN(72, APB2, B, 4), + __N32_PIN(73, APB2, B, 5), + __N32_PIN(74, APB2, B, 6), + __N32_PIN(75, APB2, B, 7), + __N32_PIN_DEFAULT, + __N32_PIN(77, APB2, B, 8), + __N32_PIN(78, APB2, B, 9), + __N32_PIN_DEFAULT, + __N32_PIN_DEFAULT, #endif #if (N32G45X_PIN_NUMBERS == 100) __N32_PIN_DEFAULT, @@ -259,8 +343,8 @@ static const struct pin_index pins[] = __N32_PIN(98, APB2, E, 1), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, -#endif -#if (N32G45X_PIN_NUMBERS == 144) + #endif + #if (N32G45X_PIN_NUMBERS == 128) __N32_PIN_DEFAULT, __N32_PIN(1, APB2, E, 2), __N32_PIN(2, APB2, E, 3), @@ -271,7 +355,6 @@ static const struct pin_index pins[] = __N32_PIN(7, APB2, C, 13), __N32_PIN(8, APB2, C, 14), __N32_PIN(9, APB2, C, 15), - __N32_PIN(10, APB2, F, 0), __N32_PIN(11, APB2, F, 1), __N32_PIN(12, APB2, F, 2), @@ -280,131 +363,115 @@ static const struct pin_index pins[] = __N32_PIN(15, APB2, F, 5), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(18, APB2, F, 6), - __N32_PIN(19, APB2, F, 7), - __N32_PIN(20, APB2, F, 8), - __N32_PIN(21, APB2, F, 9), - __N32_PIN(22, APB2, F, 10), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(26, APB2, C, 0), - __N32_PIN(27, APB2, C, 1), - __N32_PIN(28, APB2, C, 2), - __N32_PIN(29, APB2, C, 3), + __N32_PIN(21, APB2, C, 0), + __N32_PIN(22, APB2, C, 1), + __N32_PIN(23, APB2, C, 2), + __N32_PIN(24, APB2, C, 3), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(34, APB2, A, 0), - __N32_PIN(35, APB2, A, 1), - __N32_PIN(36, APB2, A, 2), - __N32_PIN(37, APB2, A, 3), + __N32_PIN(29, APB2, A, 0), + __N32_PIN(30, APB2, A, 1), + __N32_PIN(31, APB2, A, 2), + __N32_PIN(32, APB2, A, 3), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(40, APB2, A, 4), - __N32_PIN(41, APB2, A, 5), - __N32_PIN(42, APB2, A, 6), - __N32_PIN(43, APB2, A, 7), - __N32_PIN(44, APB2, C, 4), - __N32_PIN(45, APB2, C, 5), - __N32_PIN(46, APB2, B, 0), - __N32_PIN(47, APB2, B, 1), - __N32_PIN(48, APB2, B, 2), - __N32_PIN(49, APB2, F, 11), - __N32_PIN(50, APB2, F, 12), + __N32_PIN(35, APB2, A, 4), + __N32_PIN(36, APB2, A, 5), + __N32_PIN(37, APB2, A, 6), + __N32_PIN(38, APB2, A, 7), + __N32_PIN(39, APB2, C, 4), + __N32_PIN(40, APB2, C, 5), + __N32_PIN(41, APB2, B, 0), + __N32_PIN(42, APB2, B, 1), + __N32_PIN(43, APB2, B, 2), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(53, APB2, F, 13), - __N32_PIN(54, APB2, F, 14), - __N32_PIN(55, APB2, F, 15), - __N32_PIN(56, APB2, G, 0), - __N32_PIN(57, APB2, G, 1), - __N32_PIN(58, APB2, E, 7), - __N32_PIN(59, APB2, E, 8), - __N32_PIN(60, APB2, E, 9), + __N32_PIN(46, APB2, F, 12), + __N32_PIN(47, APB2, F, 13), + __N32_PIN(48, APB2, F, 14), + __N32_PIN(49, APB2, F, 15), + __N32_PIN(50, APB2, E, 7), + __N32_PIN(51, APB2, E, 8), + __N32_PIN(52, APB2, E, 9), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(63, APB2, E, 10), - __N32_PIN(64, APB2, E, 11), - __N32_PIN(65, APB2, E, 12), - __N32_PIN(66, APB2, E, 13), - __N32_PIN(67, APB2, E, 14), - __N32_PIN(68, APB2, E, 15), - __N32_PIN(69, APB2, B, 10), - __N32_PIN(70, APB2, B, 11), + __N32_PIN(55, APB2, E, 10), + __N32_PIN(56, APB2, E, 11), + __N32_PIN(57, APB2, E, 12), + __N32_PIN(58, APB2, E, 13), + __N32_PIN(59, APB2, E, 14), + __N32_PIN(60, APB2, E, 15), + __N32_PIN(61, APB2, B, 10), + __N32_PIN(62, APB2, B, 11), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(73, APB2, B, 12), - __N32_PIN(74, APB2, B, 13), - __N32_PIN(75, APB2, B, 14), - __N32_PIN(76, APB2, B, 15), - __N32_PIN(77, APB2, D, 8), - __N32_PIN(78, APB2, D, 9), - __N32_PIN(79, APB2, D, 10), - __N32_PIN(80, APB2, D, 11), - __N32_PIN(81, APB2, D, 12), - __N32_PIN(82, APB2, D, 13), + __N32_PIN(65, APB2, B, 12), + __N32_PIN(66, APB2, B, 13), + __N32_PIN(67, APB2, B, 14), + __N32_PIN(68, APB2, B, 15), + __N32_PIN(69, APB2, D, 8), + __N32_PIN(70, APB2, D, 9), + __N32_PIN(71, APB2, D, 10), + __N32_PIN(72, APB2, D, 11), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(85, APB2, D, 14), - __N32_PIN(86, APB2, D, 15), - __N32_PIN(87, APB2, G, 2), - __N32_PIN(88, APB2, G, 3), - __N32_PIN(89, APB2, G, 4), - __N32_PIN(90, APB2, G, 5), - __N32_PIN(91, APB2, G, 6), - __N32_PIN(92, APB2, G, 7), - __N32_PIN(93, APB2, G, 8), + __N32_PIN(75, APB2, D, 12), + __N32_PIN(76, APB2, D, 13), + __N32_PIN(77, APB2, D, 14), + __N32_PIN(78, APB2, D, 15), + __N32_PIN(79, APB2, G, 0), + __N32_PIN(80, APB2, G, 1), + __N32_PIN(81, APB2, G, 2), + __N32_PIN(82, APB2, G, 3), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(96, APB2, C, 6), - __N32_PIN(97, APB2, C, 7), - __N32_PIN(98, APB2, C, 8), - __N32_PIN(99, APB2, C, 9), - __N32_PIN(100, APB2, A, 8), - __N32_PIN(101, APB2, A, 9), - __N32_PIN(102, APB2, A, 10), - __N32_PIN(103, APB2, A, 11), - __N32_PIN(104, APB2, A, 12), - __N32_PIN(105, APB2, A, 13), + __N32_PIN(85, APB2, C, 6), + __N32_PIN(86, APB2, C, 7), + __N32_PIN(87, APB2, C, 8), + __N32_PIN(88, APB2, C, 9), + __N32_PIN(89, APB2, A, 8), + __N32_PIN(90, APB2, A, 9), + __N32_PIN(91, APB2, A, 10), + __N32_PIN(92, APB2, A, 11), + __N32_PIN(93, APB2, A, 12), + __N32_PIN(94, APB2, A, 13), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN_DEFAULT, - __N32_PIN(109, APB2, A, 14), - __N32_PIN(110, APB2, A, 15), - __N32_PIN(111, APB2, C, 10), - __N32_PIN(112, APB2, C, 11), - __N32_PIN(113, APB2, C, 12), - __N32_PIN(114, APB2, D, 0), - __N32_PIN(115, APB2, D, 1), - __N32_PIN(116, APB2, D, 2), - __N32_PIN(117, APB2, D, 3), - __N32_PIN(118, APB2, D, 4), - __N32_PIN(119, APB2, D, 5), + __N32_PIN(97, APB2, A, 14), + __N32_PIN(98, APB2, A, 15), + __N32_PIN(99, APB2, C, 10), + __N32_PIN(100, APB2, C, 11), + __N32_PIN(101, APB2, C, 12), + __N32_PIN(102, APB2, D, 0), + __N32_PIN(103, APB2, D, 1), + __N32_PIN(104, APB2, D, 2), + __N32_PIN(105, APB2, D, 3), + __N32_PIN(106, APB2, D, 4), + __N32_PIN(107, APB2, D, 5), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(122, APB2, D, 6), - __N32_PIN(123, APB2, D, 7), - __N32_PIN(124, APB2, G, 9), - __N32_PIN(125, APB2, G, 10), - __N32_PIN(126, APB2, G, 11), - __N32_PIN(127, APB2, G, 12), - __N32_PIN(128, APB2, G, 13), - __N32_PIN(129, APB2, G, 14), + __N32_PIN(110, APB2, D, 6), + __N32_PIN(111, APB2, D, 7), + __N32_PIN(112, APB2, G, 4), + __N32_PIN(113, APB2, G, 5), + __N32_PIN(114, APB2, G, 9), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, - __N32_PIN(132, APB2, G, 15), - __N32_PIN(133, APB2, B, 3), - __N32_PIN(134, APB2, B, 4), - __N32_PIN(135, APB2, B, 5), - __N32_PIN(136, APB2, B, 6), - __N32_PIN(137, APB2, B, 7), + __N32_PIN(117, APB2, B, 3), + __N32_PIN(118, APB2, B, 4), + __N32_PIN(119, APB2, B, 5), + __N32_PIN(120, APB2, B, 6), + __N32_PIN(121, APB2, B, 7), __N32_PIN_DEFAULT, - __N32_PIN(139, APB2, B, 8), - __N32_PIN(140, APB2, B, 9), - __N32_PIN(141, APB2, E, 0), - __N32_PIN(142, APB2, E, 1), + __N32_PIN(123, APB2, B, 8), + __N32_PIN(124, APB2, B, 9), + __N32_PIN(125, APB2, E, 0), + __N32_PIN(126, APB2, E, 1), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, #endif diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.c b/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.c index 99fd087498..a5dadf573d 100644 --- a/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.c +++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_pwm.c @@ -212,10 +212,6 @@ static rt_err_t drv_pwm_set(struct n32_pwm *pwm_dev, struct rt_pwm_configuration rt_uint64_t psc; rt_uint32_t pulse; - /* Init timer pin and enable clock */ - void n32_msp_tim_init(void *Instance); - n32_msp_tim_init(TIMx); - RCC_ClocksType RCC_Clock; RCC_GetClocksFreqValue(&RCC_Clock); rt_uint64_t input_clock; @@ -332,6 +328,9 @@ static int rt_hw_pwm_init(void) if (rt_device_pwm_register(&n32_pwm_obj[i].pwm_device, n32_pwm_obj[i].name, &drv_ops, &(n32_pwm_obj[i])) == RT_EOK) { + /* Init timer pin and enable clock */ + void n32_msp_tim_init(void *Instance); + n32_msp_tim_init(n32_pwm_obj[i].tim_handle); } else { diff --git a/bsp/n32g452xx/Libraries/rt_drivers/drv_usart.c b/bsp/n32g452xx/Libraries/rt_drivers/drv_usart.c index 98e0193a77..2f15585970 100644 --- a/bsp/n32g452xx/Libraries/rt_drivers/drv_usart.c +++ b/bsp/n32g452xx/Libraries/rt_drivers/drv_usart.c @@ -477,6 +477,76 @@ void DMA1_Channel8_IRQHandler(void) } #endif /* BSP_USING_UART5 */ +#if defined(BSP_USING_UART6) +/* UART6 device driver structure */ +struct n32_uart uart6 = +{ + UART6, + UART6_IRQn, + { + DMA2_CH1, + DMA2, + DMA2_FLAG_GL1, + DMA2_Channel1_IRQn, + 0, + }, +}; +struct rt_serial_device serial6; + +void UART6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + uart_isr(&serial6); + /* leave interrupt */ + rt_interrupt_leave(); +} + +void DMA2_Channel1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + dma_rx_done_isr(&serial6); + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART6 */ + +#if defined(BSP_USING_UART7) +/* UART7 device driver structure */ +struct n32_uart uart7 = +{ + UART7, + UART7_IRQn, + { + DMA2_CH6, + DMA2, + DMA2_FLAG_GL6, + DMA2_Channel6_IRQn, + 0, + }, +}; +struct rt_serial_device serial7; + +void UART7_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + uart_isr(&serial7); + /* leave interrupt */ + rt_interrupt_leave(); +} + +void DMA2_Channel6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + dma_rx_done_isr(&serial7); + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* BSP_USING_UART7 */ + static void NVIC_Configuration(struct n32_uart *uart) { NVIC_InitType NVIC_InitStructure; @@ -582,7 +652,7 @@ int rt_hw_usart_init(void) /* register UART3 device */ rt_hw_serial_register(&serial3, "uart3", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | - RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, + RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* BSP_USING_UART3 */ @@ -592,7 +662,7 @@ int rt_hw_usart_init(void) serial4.ops = &n32_uart_ops; serial4.config = config; NVIC_Configuration(uart); - /* register UART3 device */ + /* register UART4 device */ rt_hw_serial_register(&serial4, "uart4", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, @@ -605,12 +675,40 @@ int rt_hw_usart_init(void) serial5.ops = &n32_uart_ops; serial5.config = config; NVIC_Configuration(uart); - /* register UART3 device */ + /* register UART5 device */ rt_hw_serial_register(&serial5, "uart5", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, uart); #endif /* BSP_USING_UART5 */ + + #if defined(BSP_USING_UART6) + uart = &uart6; + config.baud_rate = BAUD_RATE_115200; + serial6.ops = &n32_uart_ops; + serial6.config = config; + NVIC_Configuration(uart); + /* register UART6 device */ + rt_hw_serial_register(&serial6, "uart6", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | + RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, + uart); + #endif /* BSP_USING_UART6 */ + + #if defined(BSP_USING_UART7) + uart = &uart7; + config.baud_rate = BAUD_RATE_115200; + serial7.ops = &n32_uart_ops; + serial7.config = config; + NVIC_Configuration(uart); + /* register UART7 device */ + rt_hw_serial_register(&serial7, "uart7", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | + RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX, + uart); + #endif /* BSP_USING_UART7 */ + + return RT_EOK; } diff --git a/bsp/n32g452xx/n32g452xx-mini-system/.config b/bsp/n32g452xx/n32g452xx-mini-system/.config index 9921e8b35d..2a79b2d35e 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/.config +++ b/bsp/n32g452xx/n32g452xx-mini-system/.config @@ -34,7 +34,7 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 # CONFIG_RT_USING_TINY_FFS is not set # CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y -# CONFIG_RT_DEBUG_COLOR is not set +CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set # CONFIG_RT_DEBUG_THREAD_CONFIG is not set # CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set @@ -54,7 +54,7 @@ CONFIG_RT_USING_MUTEX=y CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MAILBOX=y CONFIG_RT_USING_MESSAGEQUEUE=y -# CONFIG_RT_USING_SIGNALS is not set +CONFIG_RT_USING_SIGNALS=y # # Memory Management @@ -134,9 +134,12 @@ CONFIG_RT_USING_SERIAL_V1=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set -# CONFIG_RT_USING_HWTIMER is not set +CONFIG_RT_USING_HWTIMER=y # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +CONFIG_RT_USING_I2C_BITOPS=y +# CONFIG_RT_I2C_BITOPS_DEBUG is not set # CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y CONFIG_RT_USING_ADC=y @@ -292,7 +295,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_JIOT-C-SDK is not set # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set # CONFIG_PKG_USING_JOYLINK is not set -# CONFIG_PKG_USING_EZ_IOT_OS is not set # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set @@ -326,14 +328,12 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set # CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set # CONFIG_PKG_USING_HM is not set -# CONFIG_PKG_USING_SMALL_MODBUS is not set -# CONFIG_PKG_USING_NET_SERVER is not set # # security packages # # CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_LIBSODIUM is not set +# CONFIG_PKG_USING_libsodium is not set # CONFIG_PKG_USING_TINYCRYPT is not set # CONFIG_PKG_USING_TFM is not set # CONFIG_PKG_USING_YD_CRYPTO is not set @@ -341,7 +341,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # language packages # -# CONFIG_PKG_USING_LUATOS_SOC is not set # CONFIG_PKG_USING_LUA is not set # CONFIG_PKG_USING_JERRYSCRIPT is not set # CONFIG_PKG_USING_MICROPYTHON is not set @@ -354,15 +353,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # LVGL: powerful and easy-to-use embedded GUI library # -# CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set -# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set - -# -# u8g2: a monochrome graphic library -# -# CONFIG_PKG_USING_U8G2_OFFICIAL is not set -# CONFIG_PKG_USING_U8G2 is not set +# CONFIG_PKG_USING_LVGL is not set # CONFIG_PKG_USING_OPENMV is not set # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set @@ -378,13 +370,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_UGUI is not set # -# PainterEngine: A cross-platform graphics application framework written in C language +# u8g2: a monochrome graphic library # -# CONFIG_PKG_USING_PAINTERENGINE is not set -# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_TERMBOX is not set -# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_U8G2_OFFICIAL is not set +# CONFIG_PKG_USING_U8G2 is not set # # tools packages @@ -427,39 +416,19 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_MEM_SANDBOX is not set # CONFIG_PKG_USING_SOLAR_TERMS is not set # CONFIG_PKG_USING_GAN_ZHI is not set -# CONFIG_PKG_USING_FDT is not set # # system packages # -# -# enhanced kernel services -# -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set -# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set - -# -# POSIX extension functions -# -# CONFIG_PKG_USING_POSIX_GETLINE is not set -# CONFIG_PKG_USING_POSIX_WCWIDTH is not set -# CONFIG_PKG_USING_POSIX_ITOA is not set - # # acceleration: Assembly language or algorithmic acceleration packages # +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_QFPLIB_M0_FULL is not set # CONFIG_PKG_USING_QFPLIB_M0_TINY is not set # CONFIG_PKG_USING_QFPLIB_M3 is not set -# -# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard -# -# CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_RTOS2 is not set - # # Micrium: Micrium software products porting for RT-Thread # @@ -469,7 +438,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set -# CONFIG_RT_USING_ARDUINO is not set # CONFIG_PKG_USING_GUIENGINE is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set @@ -478,6 +446,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set # CONFIG_PKG_USING_DFS_JFFS2 is not set @@ -494,13 +463,14 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_QBOOT is not set # CONFIG_PKG_USING_PPOOL is not set # CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set # CONFIG_PKG_USING_LPM is not set # CONFIG_PKG_USING_TLSF is not set # CONFIG_PKG_USING_EVENT_RECORDER is not set # CONFIG_PKG_USING_ARM_2D is not set +# CONFIG_PKG_USING_WCWIDTH is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set -# CONFIG_PKG_USING_USB_STACK is not set # # peripheral libraries and drivers @@ -574,11 +544,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_BLUETRUM_SDK is not set # CONFIG_PKG_USING_MISAKA_AT24CXX is not set # CONFIG_PKG_USING_MISAKA_RGB_BLING is not set -# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set # CONFIG_PKG_USING_BL_MCU_SDK is not set # CONFIG_PKG_USING_SOFT_SERIAL is not set -# CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_CW2015 is not set # # AI packages @@ -617,7 +584,6 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_SNAKE is not set # CONFIG_PKG_USING_TETRIS is not set # CONFIG_PKG_USING_DONUT is not set -# CONFIG_PKG_USING_COWSAY is not set # CONFIG_PKG_USING_LIBCSV is not set # CONFIG_PKG_USING_OPTPARSE is not set # CONFIG_PKG_USING_FASTLZ is not set @@ -639,11 +605,14 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_VI is not set # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set # CONFIG_PKG_USING_UKAL is not set # CONFIG_PKG_USING_CRCLIB is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set +# CONFIG_PKG_USING_TERMBOX is not set # # Hardware Drivers Config @@ -658,18 +627,78 @@ CONFIG_BSP_USING_UART=y # # On-chip Peripheral Drivers # +# CONFIG_N32G45X_PIN_NUMBERS_48 is not set +CONFIG_N32G45X_PIN_NUMBERS_64=y +# CONFIG_N32G45X_PIN_NUMBERS_100 is not set +# CONFIG_N32G45X_PIN_NUMBERS_128 is not set +CONFIG_N32G45X_PIN_NUMBERS=64 CONFIG_BSP_USING_GPIO=y + +# +# Remap JTAG Port +# +# CONFIG_BSP_RMP_SW_JTAG_FULL_ENABLE is not set +# CONFIG_BSP_RMP_SW_JTAG_NO_NJTRST is not set +CONFIG_BSP_RMP_SW_JTAG_SW_ENABLE=y +# CONFIG_BSP_RMP_SW_JTAG_DISABLE is not set # CONFIG_BSP_USING_ON_CHIP_FLASH is not set # CONFIG_BSP_USING_WDT is not set CONFIG_BSP_USING_UART1=y +# CONFIG_BSP_USING_UART1_PIN_RMP is not set +CONFIG_BSP_USING_UART1_NO_RMP=y # CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_USING_UART2_NO_RMP is not set +# CONFIG_BSP_USING_UART2_PIN_RMP1 is not set +# CONFIG_BSP_USING_UART2_PIN_RMP2 is not set +# CONFIG_BSP_USING_UART2_PIN_RMP3 is not set # CONFIG_BSP_USING_UART3 is not set # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_UART5 is not set -# CONFIG_BSP_USING_PWM is not set -# CONFIG_BSP_USING_HWTIMER is not set +# CONFIG_BSP_USING_UART6 is not set +# CONFIG_BSP_USING_UART7 is not set +CONFIG_BSP_USING_PWM=y +CONFIG_BSP_USING_TIM1PWM=y +# CONFIG_BSP_USING_TIM1_CH1 is not set +# CONFIG_BSP_USING_TIM1_CH2 is not set +# CONFIG_BSP_USING_TIM1_CH3 is not set +# CONFIG_BSP_USING_TIM1_CH4 is not set +CONFIG_BSP_USING_TIM2PWM=y +# CONFIG_BSP_USING_TIM2_CH1 is not set +# CONFIG_BSP_USING_TIM2_CH2 is not set +# CONFIG_BSP_USING_TIM2_CH3 is not set +CONFIG_BSP_USING_TIM2_CH4=y +CONFIG_BSP_USING_TIM3PWM=y +# CONFIG_BSP_USING_TIM3_CH1 is not set +CONFIG_BSP_USING_TIM3_CH2=y +# CONFIG_BSP_USING_TIM3_CH3 is not set +# CONFIG_BSP_USING_TIM3_CH4 is not set +CONFIG_BSP_USING_TIM4PWM=y +# CONFIG_BSP_USING_TIM4_CH1 is not set +# CONFIG_BSP_USING_TIM4_CH2 is not set +CONFIG_BSP_USING_TIM4_CH3=y +# CONFIG_BSP_USING_TIM4_CH4 is not set +CONFIG_BSP_USING_TIM5PWM=y +# CONFIG_BSP_USING_TIM5_CH1 is not set +# CONFIG_BSP_USING_TIM5_CH2 is not set +CONFIG_BSP_USING_TIM5_CH3=y +# CONFIG_BSP_USING_TIM5_CH4 is not set +CONFIG_BSP_USING_TIM8PWM=y +# CONFIG_BSP_USING_TIM8_CH1 is not set +# CONFIG_BSP_USING_TIM8_CH2 is not set +# CONFIG_BSP_USING_TIM8_CH3 is not set +CONFIG_BSP_USING_TIM8_CH4=y +CONFIG_BSP_USING_HWTIMER=y +# CONFIG_BSP_USING_HWTIM3 is not set +# CONFIG_BSP_USING_HWTIM4 is not set +# CONFIG_BSP_USING_HWTIM5 is not set +CONFIG_BSP_USING_HWTIM6=y +# CONFIG_BSP_USING_HWTIM7 is not set # CONFIG_BSP_USING_SPI is not set -# CONFIG_BSP_USING_I2C1 is not set -# CONFIG_BSP_USING_ADC is not set +CONFIG_BSP_USING_I2C1=y +CONFIG_BSP_I2C1_SCL_PIN=29 +CONFIG_BSP_I2C1_SDA_PIN=30 +CONFIG_BSP_USING_ADC=y +CONFIG_BSP_USING_ADC1=y +# CONFIG_BSP_USING_ADC2 is not set # CONFIG_BSP_USING_CAN is not set # CONFIG_BSP_USING_SDIO is not set diff --git a/bsp/n32g452xx/n32g452xx-mini-system/board/Kconfig b/bsp/n32g452xx/n32g452xx-mini-system/board/Kconfig index 0b77f8ca90..59a042bf99 100755 --- a/bsp/n32g452xx/n32g452xx-mini-system/board/Kconfig +++ b/bsp/n32g452xx/n32g452xx-mini-system/board/Kconfig @@ -19,10 +19,49 @@ endmenu menu "On-chip Peripheral Drivers" + choice + prompt "Package of N32G45NXX chip:" + default N32G45X_PIN_NUMBERS_64 + config N32G45X_PIN_NUMBERS_48 + bool "LQFP48/TQFP48(QFN48 is not supported.)" + config N32G45X_PIN_NUMBERS_64 + bool "LQFP64" + config N32G45X_PIN_NUMBERS_100 + bool "LQFP100" + config N32G45X_PIN_NUMBERS_128 + bool "LQFP128" + endchoice + + config N32G45X_PIN_NUMBERS + int + range 0 128 + default 48 if N32G45X_PIN_NUMBERS_48 + default 64 if N32G45X_PIN_NUMBERS_64 + default 100 if N32G45X_PIN_NUMBERS_100 + default 128 if N32G45X_PIN_NUMBERS_128 + + config BSP_USING_GPIO bool "Enable GPIO" select RT_USING_PIN default y + if BSP_USING_GPIO + + menu "Remap JTAG Port" + choice + prompt "Remap JTAG Port" + default BSP_RMP_SW_JTAG_SW_ENABLE + config BSP_RMP_SW_JTAG_FULL_ENABLE + bool "Full SWJ Enabled (JTAG-DP+SW-DP). No GPIO available." + config BSP_RMP_SW_JTAG_NO_NJTRST + bool "Full SWJ Enabled (JTAG-DP+SW-DP) without JTRST. PB4 available." + config BSP_RMP_SW_JTAG_SW_ENABLE + bool "JTAG-DP Disabled and SW-DP Enabled. PA15,PB3,PB4 available." + config BSP_RMP_SW_JTAG_DISABLE + bool "Full SWJ Disabled (JTAG-DP+SW-DP). PA13,PA14,PA15,PB3,PB4 available." + endchoice + endmenu + endif config BSP_USING_ON_CHIP_FLASH bool "Enable on-chip FLASH" @@ -39,25 +78,121 @@ menu "On-chip Peripheral Drivers" select RT_USING_SERIAL if BSP_USING_UART config BSP_USING_UART1 - bool "Enable UART1" + bool "Enable USART1" default y + if BSP_USING_UART1 + choice + prompt "Select TX/RX Pin of USART1" + default BSP_USING_UART1_NO_RMP + config BSP_USING_UART1_PIN_RMP + bool "USART1(Remap):(TX:PB6,RX:PB7)" + config BSP_USING_UART1_NO_RMP + bool "USART1(Default):(TX:PA9,RX:PA10)" + endchoice + endif config BSP_USING_UART2 - bool "Enable UART2" + bool "Enable USART2" default n + if BSP_USING_UART2 + choice + prompt "Select TX/RX Pin of USART2" + default BSP_USING_UART2_NO_RMP + config BSP_USING_UART2_NO_RMP + bool "USART2(Default):(TX:PA2, RX:PA3)" + config BSP_USING_UART2_PIN_RMP1 + bool "USART2:(TX:PD5, RX:PD6)" + config BSP_USING_UART2_PIN_RMP2 + bool "USART2:(TX:PC8, RX:PC9)" + config BSP_USING_UART2_PIN_RMP3 + bool "USART2:(TX:PB4, RX:PB5)" + endchoice + endif + config BSP_USING_UART3 - bool "Enable UART3" + bool "Enable USART3" default n + if BSP_USING_UART3 + choice + prompt "Select TX/RX Pin of USART3" + default BSP_USING_UART3_PIN_NO_RMP + config BSP_USING_UART3_PIN_NO_RMP + bool "USART3:Default (TX:PB10, RX:PB11)" + config BSP_USING_UART3_PIN_PART_RMP + bool "USART3:Partial remap (TX:PC10, RX:PC11)" + config BSP_USING_UART3_PIN_ALL_RMP + bool "USART3:Full remap (TX:PD8, RX:PD9)" + endchoice + endif config BSP_USING_UART4 bool "Enable UART4" default n + if BSP_USING_UART4 + choice + prompt "Select TX/RX Pin of UART4" + default BSP_USING_UART4_PIN_NORMP + config BSP_USING_UART4_PIN_NORMP + bool "UART4(Default):TX:PC10, RX:PC11" + config BSP_USING_UART4_PIN_RMP1 + bool "UART4:TX:PB2, RX:PE7" + config BSP_USING_UART4_PIN_RMP2 + bool "UART4:TX:PA13, RX:PA14" + config BSP_USING_UART4_PIN_RMP3 + bool "UART4:TX:PD0, RX:PD1" + endchoice + endif config BSP_USING_UART5 bool "Enable UART5" default n - + if BSP_USING_UART5 + choice + prompt "Select TX/RX Pin of UART5" + default BSP_USING_UART5_PIN_NORMP + config BSP_USING_UART5_PIN_NORMP + bool "UART5(Default):TX:PC12, RX:PD2" + config BSP_USING_UART5_PIN_RMP1 + bool "UART5:TX:PB13, RX:PB14" + config BSP_USING_UART5_PIN_RMP2 + bool "UART5:TX:PE8, RX:PE9" + config BSP_USING_UART5_PIN_RMP3 + bool "UART5:TX:PB8, RX:PB9" + endchoice + endif + + config BSP_USING_UART6 + bool "Enable UART6" + default n + if BSP_USING_UART6 + choice + prompt "Select TX/RX Pin of UART6" + default BSP_USING_UART6_PIN_NORMP + config BSP_USING_UART6_PIN_NORMP + bool "UART6(Default):TX:PE2, RX:PE3" + config BSP_USING_UART6_PIN_RMP2 + bool "UART6:TX:PC0, RX:PC1" + config BSP_USING_UART6_PIN_RMP3 + bool "UART6:TX:PB0, RX:PB1" + endchoice + endif + + config BSP_USING_UART7 + bool "Enable UART7" + default n + if BSP_USING_UART7 + choice + prompt "Select TX/RX Pin of UART7" + default BSP_USING_UART7_PIN_NORMP + config BSP_USING_UART7_PIN_NORMP + bool "UART7(Default):TX:PC4, RX:PC5" + config BSP_USING_UART7_PIN_RMP1 + bool "UART7:TX:PC2, RX:PC3" + config BSP_USING_UART7_PIN_RMP3 + bool "UART7:TX:PG0, RX:PG1" + endchoice + endif endif menuconfig BSP_USING_PWM @@ -213,13 +348,13 @@ menu "On-chip Peripheral Drivers" select RT_USING_PIN if BSP_USING_I2C1 config BSP_I2C1_SCL_PIN - int "i2c1 scl pin number" - range 0 63 - default 22 + int "I2C1 scl pin number" + range 1 N32G45X_PIN_NUMBERS + default 29 config BSP_I2C1_SDA_PIN int "I2C1 sda pin number" - range 0 63 - default 23 + range 1 N32G45X_PIN_NUMBERS + default 30 endif menuconfig BSP_USING_ADC diff --git a/bsp/n32g452xx/n32g452xx-mini-system/board/board.c b/bsp/n32g452xx/n32g452xx-mini-system/board/board.c index ca6e55fb4e..9048415752 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/board/board.c +++ b/bsp/n32g452xx/n32g452xx-mini-system/board/board.c @@ -76,6 +76,7 @@ void rt_hw_board_init() #ifdef RT_USING_PIN int n32_hw_pin_init(void); n32_hw_pin_init(); + n32_msp_jtag_init(RT_NULL); #endif #ifdef RT_USING_SERIAL diff --git a/bsp/n32g452xx/n32g452xx-mini-system/board/board.h b/bsp/n32g452xx/n32g452xx-mini-system/board/board.h index 0a3b0fa661..fd5fa543f4 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/board/board.h +++ b/bsp/n32g452xx/n32g452xx-mini-system/board/board.h @@ -25,7 +25,7 @@ extern "C" { #define N32_FLASH_END_ADDRESS ((uint32_t)(N32_FLASH_START_ADRESS + N32_FLASH_SIZE)) /* Internal SRAM memory size[Kbytes] <80>, Default: 80*/ -#define N32_SRAM_SIZE (80) +#define N32_SRAM_SIZE (144) #define N32_SRAM_END (0x20000000 + N32_SRAM_SIZE * 1024) #if defined(__ARMCC_VERSION) diff --git a/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c b/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c index bd79fbd756..259a0d88e0 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c +++ b/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c @@ -27,58 +27,283 @@ void n32_msp_usart_init(void *Instance) if (USART1 == USARTx) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE); + #ifdef BSP_USING_UART1_PIN_RMP + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_USART1, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_6; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_7; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + #else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_9; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_10; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + #endif } -#endif -#ifdef BSP_USING_UART2 - if (USART2 == USARTx) + + #endif /* BSP_USING_UART1 */ + #ifdef BSP_USING_UART2 + + if(USART2 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE); + #ifdef BSP_USING_UART2_PIN_RMP1 + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP1_USART2, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_5; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_6; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + + #elif defined (BSP_USING_UART2_PIN_RMP2) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMCP2_USART2, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_8; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_9; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + + #elif defined (BSP_USING_UART2_PIN_RMP3) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_USART2, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_4; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_5; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + + #else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_2; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_3; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + #endif } -#endif -#ifdef BSP_USING_UART3 - if (USART3 == USARTx) + + #endif /* BSP_USING_UART2 */ + #ifdef BSP_USING_UART3 + + if(USART3 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3, ENABLE); + #if defined(BSP_USING_UART3_PIN_PART_RMP) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_PART_RMP_USART3, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_10; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_11; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART3_PIN_ALL_RMP) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_ALL_RMP_USART3, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_8; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_9; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + #else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_10; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_11; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + #endif } -#endif -#ifdef BSP_USING_UART4 - if (UART4 == USARTx) + + #endif /* BSP_USING_UART3 */ + #ifdef BSP_USING_UART4 + + if(UART4 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_UART4, ENABLE); - RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + #if defined(BSP_USING_UART4_PIN_RMP1) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP1_UART4, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_GPIOE, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_2; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_7; + GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART4_PIN_RMP2) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP2_UART4, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_13; + GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_14; + GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART4_PIN_RMP3) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_UART4, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_0; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_1; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + #else + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_10; - GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_11; - GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + #endif } -#endif + + #endif /* BSP_USING_UART4 */ + #ifdef BSP_USING_UART5 + + if(UART5 == USARTx) + { + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_UART5, ENABLE); + #if defined(BSP_USING_UART5_PIN_RMP1) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP1_UART5, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_13; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_14; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART5_PIN_RMP2) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP2_UART5, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_8; + GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_9; + GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART5_PIN_RMP3) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_UART5, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_8; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_9; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + #else + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_GPIOD, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_12; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_2; + GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); + #endif + } + + #endif /* BSP_USING_UART5 */ + #ifdef BSP_USING_UART6 + + if(UART6 == USARTx) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART6, ENABLE); + #if defined(BSP_USING_UART6_PIN_RMP2) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP2_UART6, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_0; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_1; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART6_PIN_RMP3) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_UART6, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_0; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_1; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + #else /* BSP_USING_UART6_PIN_NORMP */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_2; + GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_3; + GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); + #endif + } + + #endif /* BSP_USING_UART6 */ + #ifdef BSP_USING_UART7 + + if(UART7 == USARTx) + { + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART7, ENABLE); + #if defined(BSP_USING_UART7_PIN_RMP1) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP1_UART7, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_2; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_3; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + #elif defined(BSP_USING_UART7_PIN_RMP3) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_UART7, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOG, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_0; + GPIO_InitPeripheral(GPIOG, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_1; + GPIO_InitPeripheral(GPIOG, &GPIO_InitCtlStruct); + #else /* BSP_USING_UART7_PIN_NORMP */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitCtlStruct.Pin = GPIO_PIN_4; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitCtlStruct.Pin = GPIO_PIN_5; + GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); + #endif + } + + #endif /* BSP_USING_UART7 */ /* Add others */ } #endif /* BSP_USING_SERIAL */ @@ -113,7 +338,6 @@ void n32_msp_spi_init(void *Instance) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI2, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); - GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_12; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); @@ -167,7 +391,7 @@ void n32_msp_tim_init(void *Instance) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); - GPIO_InitCtlStructure.Pin = GPIO_PIN_8 | GPIO_PIN_11; + GPIO_InitCtlStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; GPIO_InitCtlStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStructure); @@ -244,7 +468,7 @@ void n32_msp_adc_init(void *Instance) /* Configure ADC Channel as analog input */ GPIO_InitCtlStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3; - GPIO_InitCtlStruct.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitCtlStruct.GPIO_Speed = GPIO_INPUT; GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); } @@ -260,7 +484,7 @@ void n32_msp_adc_init(void *Instance) /* Configure ADC Channel as analog input */ GPIO_InitCtlStruct.Pin = GPIO_PIN_1; - GPIO_InitCtlStruct.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitCtlStruct.GPIO_Speed = GPIO_INPUT; GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); } @@ -341,21 +565,73 @@ void n32_msp_can_init(void *Instance) if (CAN2 == CANx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN2, ENABLE); - RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); - // GPIO_PinsRemapConfig(AFIO_MAP6_CAN2_0001, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_InitCtlStruct.Pin = GPIO_PIN_6; + GPIO_InitCtlStruct.Pin = GPIO_PIN_13; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; - GPIO_InitCtlStruct.Pin = GPIO_PIN_5; + GPIO_InitCtlStruct.Pin = GPIO_PIN_12; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); } #endif } #endif /* BSP_USING_CAN */ +void n32_msp_jtag_init(void* Instance) +{ + GPIO_InitType GPIO_InitCtlStruct; + GPIO_InitStruct(&GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Speed = GPIO_Speed_50MHz; + #if defined(BSP_RMP_SW_JTAG_NO_NJTRST) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST, ENABLE); + /* Available pin: PB4 */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitCtlStruct.Pin = GPIO_PIN_4; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + #elif defined(BSP_RMP_SW_JTAG_SW_ENABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE); + /* Available pin: PB3, PB4, PA15 */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_Out_OD; + GPIO_InitCtlStruct.Pin = GPIO_PIN_3; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitCtlStruct.Pin = GPIO_PIN_4; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitCtlStruct.Pin = GPIO_PIN_15; + GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + #elif defined(BSP_RMP_SW_JTAG_DISABLE) + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_DISABLE, ENABLE); + /* Available pin: PB3, PB4, PA13, PA14, PA15 */ + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_Out_OD; + GPIO_InitCtlStruct.Pin = GPIO_PIN_3; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; + GDPIO_InitCtlStruct.Pin = GPIO_PIN_4; + GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitCtlStruct.Pin = GPIO_PIN_13; + GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPD; + GPIO_InitCtlStruct.Pin = GPIO_PIN_14; + GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitCtlStruct.Pin = GPIO_PIN_15; + GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); + #else + return; + #endif +} + + #ifdef RT_USING_FINSH #include #if defined(BSP_USING_UART2) || defined(BSP_USING_UART3) @@ -413,7 +689,7 @@ static int adc_vol_sample(int argc, char *argv[]) return RT_ERROR; } - for (int i = 6; i <= 9; ++i) + for(int i = 1; i <= 18; ++i) { ret = rt_adc_enable(adc_dev, i); value = rt_adc_read(adc_dev, i); diff --git a/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.h b/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.h index b92c62a69f..5d911a9ca4 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.h +++ b/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.h @@ -18,6 +18,7 @@ void n32_msp_sdio_init(void *Instance); void n32_msp_adc_init(void *Instance); void n32_msp_hwtim_init(void *Instance); void n32_msp_can_init(void *Instance); +void n32_msp_jtag_init(void *Instance); #endif /* __N32_MSP_H__ */ diff --git a/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h b/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h index 14a3c468b7..4ebccc41b1 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h +++ b/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h @@ -24,6 +24,7 @@ /* kservice optimization */ #define RT_DEBUG +#define RT_DEBUG_COLOR /* Inter-Thread communication */ @@ -32,6 +33,7 @@ #define RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE +#define RT_USING_SIGNALS /* Memory Management */ @@ -84,6 +86,9 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_HWTIMER +#define RT_USING_I2C +#define RT_USING_I2C_BITOPS #define RT_USING_PIN #define RT_USING_ADC #define RT_USING_PWM @@ -157,26 +162,14 @@ /* u8g2: a monochrome graphic library */ -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - /* tools packages */ /* system packages */ -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - /* acceleration: Assembly language or algorithmic acceleration packages */ -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - /* Micrium: Micrium software products porting for RT-Thread */ @@ -204,7 +197,33 @@ /* On-chip Peripheral Drivers */ +#define N32G45X_PIN_NUMBERS_64 +#define N32G45X_PIN_NUMBERS 64 #define BSP_USING_GPIO + +/* Remap JTAG Port */ + +#define BSP_RMP_SW_JTAG_SW_ENABLE #define BSP_USING_UART1 +#define BSP_USING_UART1_NO_RMP +#define BSP_USING_PWM +#define BSP_USING_TIM1PWM +#define BSP_USING_TIM2PWM +#define BSP_USING_TIM2_CH4 +#define BSP_USING_TIM3PWM +#define BSP_USING_TIM3_CH2 +#define BSP_USING_TIM4PWM +#define BSP_USING_TIM4_CH3 +#define BSP_USING_TIM5PWM +#define BSP_USING_TIM5_CH3 +#define BSP_USING_TIM8PWM +#define BSP_USING_TIM8_CH4 +#define BSP_USING_HWTIMER +#define BSP_USING_HWTIM6 +#define BSP_USING_I2C1 +#define BSP_I2C1_SCL_PIN 29 +#define BSP_I2C1_SDA_PIN 30 +#define BSP_USING_ADC +#define BSP_USING_ADC1 #endif From 7c54f5eca7ec8b68567ced4a63505be1cb849765 Mon Sep 17 00:00:00 2001 From: Blues-Jiang Date: Tue, 18 Jan 2022 17:20:02 +0800 Subject: [PATCH 26/65] reformat code. --- .../n32g452xx-mini-system/board/msp/n32_msp.c | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c b/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c index 259a0d88e0..84ff210461 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c +++ b/bsp/n32g452xx/n32g452xx-mini-system/board/msp/n32_msp.c @@ -27,7 +27,7 @@ void n32_msp_usart_init(void *Instance) if (USART1 == USARTx) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE); - #ifdef BSP_USING_UART1_PIN_RMP +#ifdef BSP_USING_UART1_PIN_RMP RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP_USART1, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); @@ -37,7 +37,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_7; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - #else +#else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_9; @@ -45,16 +45,16 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_10; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART1 */ - #ifdef BSP_USING_UART2 +#endif /* BSP_USING_UART1 */ +#ifdef BSP_USING_UART2 - if(USART2 == USARTx) + if (USART2 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE); - #ifdef BSP_USING_UART2_PIN_RMP1 +#ifdef BSP_USING_UART2_PIN_RMP1 RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP1_USART2, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); @@ -65,7 +65,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.Pin = GPIO_PIN_6; GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); - #elif defined (BSP_USING_UART2_PIN_RMP2) +#elif defined (BSP_USING_UART2_PIN_RMP2) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMCP2_USART2, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); @@ -76,7 +76,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.Pin = GPIO_PIN_9; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); - #elif defined (BSP_USING_UART2_PIN_RMP3) +#elif defined (BSP_USING_UART2_PIN_RMP3) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_USART2, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); @@ -86,8 +86,8 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_5; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - - #else + +#else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_2; @@ -95,16 +95,16 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_3; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART2 */ - #ifdef BSP_USING_UART3 +#endif /* BSP_USING_UART2 */ +#ifdef BSP_USING_UART3 - if(USART3 == USARTx) + if (USART3 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART3, ENABLE); - #if defined(BSP_USING_UART3_PIN_PART_RMP) +#if defined(BSP_USING_UART3_PIN_PART_RMP) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_PART_RMP_USART3, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); @@ -114,7 +114,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_11; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART3_PIN_ALL_RMP) +#elif defined(BSP_USING_UART3_PIN_ALL_RMP) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_ALL_RMP_USART3, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); @@ -124,7 +124,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_9; GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); - #else +#else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_10; @@ -132,16 +132,16 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_11; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART3 */ - #ifdef BSP_USING_UART4 +#endif /* BSP_USING_UART3 */ +#ifdef BSP_USING_UART4 - if(UART4 == USARTx) + if (UART4 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_UART4, ENABLE); - #if defined(BSP_USING_UART4_PIN_RMP1) +#if defined(BSP_USING_UART4_PIN_RMP1) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP1_UART4, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_GPIOE, ENABLE); @@ -151,7 +151,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_7; GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART4_PIN_RMP2) +#elif defined(BSP_USING_UART4_PIN_RMP2) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP2_UART4, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); @@ -161,7 +161,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_14; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART4_PIN_RMP3) +#elif defined(BSP_USING_UART4_PIN_RMP3) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_UART4, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); @@ -171,7 +171,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_1; GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); - #else +#else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_10; @@ -179,16 +179,16 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_11; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART4 */ - #ifdef BSP_USING_UART5 +#endif /* BSP_USING_UART4 */ +#ifdef BSP_USING_UART5 - if(UART5 == USARTx) + if (UART5 == USARTx) { RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_UART5, ENABLE); - #if defined(BSP_USING_UART5_PIN_RMP1) +#if defined(BSP_USING_UART5_PIN_RMP1) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP1_UART5, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); @@ -198,7 +198,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_14; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART5_PIN_RMP2) +#elif defined(BSP_USING_UART5_PIN_RMP2) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP2_UART5, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); @@ -208,7 +208,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_9; GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART5_PIN_RMP3) +#elif defined(BSP_USING_UART5_PIN_RMP3) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_UART5, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); @@ -218,7 +218,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_9; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - #else +#else RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_GPIOD, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_12; @@ -226,16 +226,16 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_2; GPIO_InitPeripheral(GPIOD, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART5 */ - #ifdef BSP_USING_UART6 +#endif /* BSP_USING_UART5 */ +#ifdef BSP_USING_UART6 - if(UART6 == USARTx) + if (UART6 == USARTx) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART6, ENABLE); - #if defined(BSP_USING_UART6_PIN_RMP2) +#if defined(BSP_USING_UART6_PIN_RMP2) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP2_UART6, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); @@ -245,7 +245,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_1; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART6_PIN_RMP3) +#elif defined(BSP_USING_UART6_PIN_RMP3) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_UART6, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); @@ -255,7 +255,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_1; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - #else /* BSP_USING_UART6_PIN_NORMP */ +#else /* BSP_USING_UART6_PIN_NORMP */ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOE, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_2; @@ -263,16 +263,16 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_3; GPIO_InitPeripheral(GPIOE, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART6 */ - #ifdef BSP_USING_UART7 +#endif /* BSP_USING_UART6 */ +#ifdef BSP_USING_UART7 - if(UART7 == USARTx) + if (UART7 == USARTx) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART7, ENABLE); - #if defined(BSP_USING_UART7_PIN_RMP1) +#if defined(BSP_USING_UART7_PIN_RMP1) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP1_UART7, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); @@ -282,7 +282,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_3; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); - #elif defined(BSP_USING_UART7_PIN_RMP3) +#elif defined(BSP_USING_UART7_PIN_RMP3) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP3_UART7, ENABLE); RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOG, ENABLE); @@ -292,7 +292,7 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_1; GPIO_InitPeripheral(GPIOG, &GPIO_InitCtlStruct); - #else /* BSP_USING_UART7_PIN_NORMP */ +#else /* BSP_USING_UART7_PIN_NORMP */ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitCtlStruct.Pin = GPIO_PIN_4; @@ -300,10 +300,10 @@ void n32_msp_usart_init(void *Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitCtlStruct.Pin = GPIO_PIN_5; GPIO_InitPeripheral(GPIOC, &GPIO_InitCtlStruct); - #endif +#endif } - #endif /* BSP_USING_UART7 */ +#endif /* BSP_USING_UART7 */ /* Add others */ } #endif /* BSP_USING_SERIAL */ @@ -577,12 +577,12 @@ void n32_msp_can_init(void *Instance) } #endif /* BSP_USING_CAN */ -void n32_msp_jtag_init(void* Instance) +void n32_msp_jtag_init(void *Instance) { GPIO_InitType GPIO_InitCtlStruct; GPIO_InitStruct(&GPIO_InitCtlStruct); GPIO_InitCtlStruct.GPIO_Speed = GPIO_Speed_50MHz; - #if defined(BSP_RMP_SW_JTAG_NO_NJTRST) +#if defined(BSP_RMP_SW_JTAG_NO_NJTRST) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_NO_NJTRST, ENABLE); /* Available pin: PB4 */ @@ -590,7 +590,7 @@ void n32_msp_jtag_init(void* Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitCtlStruct.Pin = GPIO_PIN_4; GPIO_InitPeripheral(GPIOB, &GPIO_InitCtlStruct); - #elif defined(BSP_RMP_SW_JTAG_SW_ENABLE) +#elif defined(BSP_RMP_SW_JTAG_SW_ENABLE) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE); /* Available pin: PB3, PB4, PA15 */ @@ -605,7 +605,7 @@ void n32_msp_jtag_init(void* Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitCtlStruct.Pin = GPIO_PIN_15; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - #elif defined(BSP_RMP_SW_JTAG_DISABLE) +#elif defined(BSP_RMP_SW_JTAG_DISABLE) RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE); GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_DISABLE, ENABLE); /* Available pin: PB3, PB4, PA13, PA14, PA15 */ @@ -626,9 +626,9 @@ void n32_msp_jtag_init(void* Instance) GPIO_InitCtlStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitCtlStruct.Pin = GPIO_PIN_15; GPIO_InitPeripheral(GPIOA, &GPIO_InitCtlStruct); - #else +#else return; - #endif +#endif } @@ -689,7 +689,7 @@ static int adc_vol_sample(int argc, char *argv[]) return RT_ERROR; } - for(int i = 1; i <= 18; ++i) + for (int i = 1; i <= 18; ++i) { ret = rt_adc_enable(adc_dev, i); value = rt_adc_read(adc_dev, i); From 711465b1372c199c723336eb2efb7972e063a3f6 Mon Sep 17 00:00:00 2001 From: Blues-Jiang Date: Wed, 19 Jan 2022 17:49:37 +0800 Subject: [PATCH 27/65] Regenerate rtconfig.h based on default configuration. --- bsp/n32g452xx/n32g452xx-mini-system/.config | 63 +++---------------- .../n32g452xx-mini-system/rtconfig.h | 25 -------- 2 files changed, 10 insertions(+), 78 deletions(-) diff --git a/bsp/n32g452xx/n32g452xx-mini-system/.config b/bsp/n32g452xx/n32g452xx-mini-system/.config index 2a79b2d35e..b96ae26740 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/.config +++ b/bsp/n32g452xx/n32g452xx-mini-system/.config @@ -49,12 +49,12 @@ CONFIG_RT_DEBUG_COLOR=y # # Inter-Thread communication # -CONFIG_RT_USING_SEMAPHORE=y -CONFIG_RT_USING_MUTEX=y -CONFIG_RT_USING_EVENT=y -CONFIG_RT_USING_MAILBOX=y -CONFIG_RT_USING_MESSAGEQUEUE=y -CONFIG_RT_USING_SIGNALS=y +# CONFIG_RT_USING_SEMAPHORE is not set +# CONFIG_RT_USING_MUTEX is not set +# CONFIG_RT_USING_EVENT is not set +# CONFIG_RT_USING_MAILBOX is not set +# CONFIG_RT_USING_MESSAGEQUEUE is not set +# CONFIG_RT_USING_SIGNALS is not set # # Memory Management @@ -647,58 +647,15 @@ CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_UART1_PIN_RMP is not set CONFIG_BSP_USING_UART1_NO_RMP=y # CONFIG_BSP_USING_UART2 is not set -# CONFIG_BSP_USING_UART2_NO_RMP is not set -# CONFIG_BSP_USING_UART2_PIN_RMP1 is not set -# CONFIG_BSP_USING_UART2_PIN_RMP2 is not set -# CONFIG_BSP_USING_UART2_PIN_RMP3 is not set # CONFIG_BSP_USING_UART3 is not set # CONFIG_BSP_USING_UART4 is not set # CONFIG_BSP_USING_UART5 is not set # CONFIG_BSP_USING_UART6 is not set # CONFIG_BSP_USING_UART7 is not set -CONFIG_BSP_USING_PWM=y -CONFIG_BSP_USING_TIM1PWM=y -# CONFIG_BSP_USING_TIM1_CH1 is not set -# CONFIG_BSP_USING_TIM1_CH2 is not set -# CONFIG_BSP_USING_TIM1_CH3 is not set -# CONFIG_BSP_USING_TIM1_CH4 is not set -CONFIG_BSP_USING_TIM2PWM=y -# CONFIG_BSP_USING_TIM2_CH1 is not set -# CONFIG_BSP_USING_TIM2_CH2 is not set -# CONFIG_BSP_USING_TIM2_CH3 is not set -CONFIG_BSP_USING_TIM2_CH4=y -CONFIG_BSP_USING_TIM3PWM=y -# CONFIG_BSP_USING_TIM3_CH1 is not set -CONFIG_BSP_USING_TIM3_CH2=y -# CONFIG_BSP_USING_TIM3_CH3 is not set -# CONFIG_BSP_USING_TIM3_CH4 is not set -CONFIG_BSP_USING_TIM4PWM=y -# CONFIG_BSP_USING_TIM4_CH1 is not set -# CONFIG_BSP_USING_TIM4_CH2 is not set -CONFIG_BSP_USING_TIM4_CH3=y -# CONFIG_BSP_USING_TIM4_CH4 is not set -CONFIG_BSP_USING_TIM5PWM=y -# CONFIG_BSP_USING_TIM5_CH1 is not set -# CONFIG_BSP_USING_TIM5_CH2 is not set -CONFIG_BSP_USING_TIM5_CH3=y -# CONFIG_BSP_USING_TIM5_CH4 is not set -CONFIG_BSP_USING_TIM8PWM=y -# CONFIG_BSP_USING_TIM8_CH1 is not set -# CONFIG_BSP_USING_TIM8_CH2 is not set -# CONFIG_BSP_USING_TIM8_CH3 is not set -CONFIG_BSP_USING_TIM8_CH4=y -CONFIG_BSP_USING_HWTIMER=y -# CONFIG_BSP_USING_HWTIM3 is not set -# CONFIG_BSP_USING_HWTIM4 is not set -# CONFIG_BSP_USING_HWTIM5 is not set -CONFIG_BSP_USING_HWTIM6=y -# CONFIG_BSP_USING_HWTIM7 is not set +# CONFIG_BSP_USING_PWM is not set +# CONFIG_BSP_USING_HWTIMER is not set # CONFIG_BSP_USING_SPI is not set -CONFIG_BSP_USING_I2C1=y -CONFIG_BSP_I2C1_SCL_PIN=29 -CONFIG_BSP_I2C1_SDA_PIN=30 -CONFIG_BSP_USING_ADC=y -CONFIG_BSP_USING_ADC1=y -# CONFIG_BSP_USING_ADC2 is not set +# CONFIG_BSP_USING_I2C1 is not set +# CONFIG_BSP_USING_ADC is not set # CONFIG_BSP_USING_CAN is not set # CONFIG_BSP_USING_SDIO is not set diff --git a/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h b/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h index 4ebccc41b1..82deef48ad 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h +++ b/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h @@ -28,12 +28,6 @@ /* Inter-Thread communication */ -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE -#define RT_USING_SIGNALS /* Memory Management */ @@ -206,24 +200,5 @@ #define BSP_RMP_SW_JTAG_SW_ENABLE #define BSP_USING_UART1 #define BSP_USING_UART1_NO_RMP -#define BSP_USING_PWM -#define BSP_USING_TIM1PWM -#define BSP_USING_TIM2PWM -#define BSP_USING_TIM2_CH4 -#define BSP_USING_TIM3PWM -#define BSP_USING_TIM3_CH2 -#define BSP_USING_TIM4PWM -#define BSP_USING_TIM4_CH3 -#define BSP_USING_TIM5PWM -#define BSP_USING_TIM5_CH3 -#define BSP_USING_TIM8PWM -#define BSP_USING_TIM8_CH4 -#define BSP_USING_HWTIMER -#define BSP_USING_HWTIM6 -#define BSP_USING_I2C1 -#define BSP_I2C1_SCL_PIN 29 -#define BSP_I2C1_SDA_PIN 30 -#define BSP_USING_ADC -#define BSP_USING_ADC1 #endif From d62368cc758117ead219ff5d6328524adec9c699 Mon Sep 17 00:00:00 2001 From: Blues-Jiang Date: Thu, 20 Jan 2022 10:01:34 +0800 Subject: [PATCH 28/65] Reinit .config based on default setting. --- bsp/n32g452xx/n32g452xx-mini-system/.config | 25 ++++++++----------- .../n32g452xx-mini-system/rtconfig.h | 18 +++++++------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/bsp/n32g452xx/n32g452xx-mini-system/.config b/bsp/n32g452xx/n32g452xx-mini-system/.config index b96ae26740..d987bd9b79 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/.config +++ b/bsp/n32g452xx/n32g452xx-mini-system/.config @@ -34,7 +34,7 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 # CONFIG_RT_USING_TINY_FFS is not set # CONFIG_RT_PRINTF_LONGLONG is not set CONFIG_RT_DEBUG=y -CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_COLOR is not set # CONFIG_RT_DEBUG_INIT_CONFIG is not set # CONFIG_RT_DEBUG_THREAD_CONFIG is not set # CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set @@ -49,11 +49,11 @@ CONFIG_RT_DEBUG_COLOR=y # # Inter-Thread communication # -# CONFIG_RT_USING_SEMAPHORE is not set -# CONFIG_RT_USING_MUTEX is not set -# CONFIG_RT_USING_EVENT is not set -# CONFIG_RT_USING_MAILBOX is not set -# CONFIG_RT_USING_MESSAGEQUEUE is not set +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y # CONFIG_RT_USING_SIGNALS is not set # @@ -134,24 +134,21 @@ CONFIG_RT_USING_SERIAL_V1=y CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set -CONFIG_RT_USING_HWTIMER=y +# CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set -CONFIG_RT_USING_I2C=y -# CONFIG_RT_I2C_DEBUG is not set -CONFIG_RT_USING_I2C_BITOPS=y -# CONFIG_RT_I2C_BITOPS_DEBUG is not set +# CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y -CONFIG_RT_USING_ADC=y +# CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set -CONFIG_RT_USING_PWM=y +# CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set # CONFIG_RT_USING_PM is not set # CONFIG_RT_USING_RTC is not set # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set -CONFIG_RT_USING_WDT=y +# CONFIG_RT_USING_WDT is not set # CONFIG_RT_USING_AUDIO is not set # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set diff --git a/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h b/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h index 82deef48ad..e191c2d43d 100644 --- a/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h +++ b/bsp/n32g452xx/n32g452xx-mini-system/rtconfig.h @@ -24,10 +24,14 @@ /* kservice optimization */ #define RT_DEBUG -#define RT_DEBUG_COLOR /* Inter-Thread communication */ +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE /* Memory Management */ @@ -72,6 +76,12 @@ /* Device virtual file system */ +#define RT_USING_DFS +#define DFS_USING_POSIX +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 4 +#define DFS_FILESYSTEM_TYPES_MAX 4 +#define DFS_FD_MAX 16 /* Device Drivers */ @@ -80,13 +90,7 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_HWTIMER -#define RT_USING_I2C -#define RT_USING_I2C_BITOPS #define RT_USING_PIN -#define RT_USING_ADC -#define RT_USING_PWM -#define RT_USING_WDT /* Using USB */ From 27511885f34d074258c7d5d9a152f1c604351e33 Mon Sep 17 00:00:00 2001 From: liukangcc Date: Wed, 22 Dec 2021 11:03:03 +0800 Subject: [PATCH 29/65] [update] change ccflags to cflags --- .../hal_libraries/ab32vg1_hal/SConscript | 20 ++++++--- .../libraries/hal_libraries/bmsis/SConscript | 24 +++++++--- bsp/ck802/applications/SConscript | 4 +- bsp/gd32/docs/GD32系列BSP制作教程.md | 4 +- bsp/ra6m4-cpk/ports/fal/SConscript | 10 ++--- bsp/ra6m4-cpk/ports/rw007/SConscript | 10 ++--- bsp/stm32/stm32h743-openmv-h7plus/SConstruct | 4 +- .../board/ports/fal/SConscript | 10 ++--- bsp/thead-smart/applications/SConscript | 4 +- bsp/tm4c129x/libraries/SConscript | 6 +-- components/drivers/spi/SConscript | 10 ++--- tools/building.py | 45 +++++++++++++++++-- tools/codelite.py | 4 +- tools/iar.py | 2 +- tools/keil.py | 10 ++--- tools/ses.py | 10 ++--- 16 files changed, 117 insertions(+), 60 deletions(-) diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/SConscript b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/SConscript index 3321a76d91..625f186203 100644 --- a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/SConscript +++ b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/SConscript @@ -18,12 +18,14 @@ DEPENDS = [""] # SOURCES: Need to compile c and c++ source, auto search when SOURCES is empty # # LOCAL_CPPPATH: Local file path (.h/.c/.cpp) -# LOCAL_CCFLAGS: Local compilation parameter +# LOCAL_CFLAGS: Local c compilation parameter +# LOCAL_CCFLAGS: Local c/c++ compilation parameter +# LOCAL_CXXFLAGS: Local c++ compilation parameter # LOCAL_ASFLAGS: Local assembly parameters # # CPPPATH: Global file path (.h/.c/.cpp), auto search when LOCAL_CPPPATH/CPPPATH # is empty # no pass!!! -# CCFLAGS: Global compilation parameter +# CFLAGS : Global compilation parameter # ASFLAGS: Global assembly parameters # # CPPDEFINES: Global macro definition @@ -37,12 +39,16 @@ DEPENDS = [""] CWD = GetCurrentDir() SOURCES = Glob("./source/*.c") -LOCAL_CPPPATH = [] -LOCAL_CCFLAGS = "" +LOCAL_CPPPATH = [] +LOCAL_CFLAGS = "" +LOCAL_CCFLAGS = "" +LOCAL_CXXFLAGS = "" LOCAL_ASFLAGS = "" CPPPATH = [GetCurrentDir(), os.path.join(GetCurrentDir(), 'include')] -CCFLAGS = "" +CFLAGS = "" +CCFLAGS = "" +CXXFLAGS = "" ASFLAGS = "" CPPDEFINES = [] @@ -61,10 +67,14 @@ CPPPATH_IGNORE = [] #--------------------------------------------------------------------------------- objs = DefineGroup(name = PKGNAME, src = SOURCES, depend = DEPENDS, CPPPATH = CPPPATH, + CFLAGS = CFLAGS, CCFLAGS = CCFLAGS, + CXXFLAGS = CXXFLAGS, ASFLAGS = ASFLAGS, LOCAL_CPPPATH = LOCAL_CPPPATH, + LOCAL_CFLAGS = LOCAL_CFLAGS, LOCAL_CCFLAGS = LOCAL_CCFLAGS, + LOCAL_CXXFLAGS = LOCAL_CXXFLAGS, LOCAL_ASFLAGS = LOCAL_ASFLAGS, CPPDEFINES = CPPDEFINES, LOCAL_CPPDEFINES = LOCAL_CPPDEFINES, diff --git a/bsp/bluetrum/libraries/hal_libraries/bmsis/SConscript b/bsp/bluetrum/libraries/hal_libraries/bmsis/SConscript index 9a82897032..a395e0acf8 100644 --- a/bsp/bluetrum/libraries/hal_libraries/bmsis/SConscript +++ b/bsp/bluetrum/libraries/hal_libraries/bmsis/SConscript @@ -19,12 +19,14 @@ DEPENDS = [""] # SOURCES: Need to compile c and c++ source, auto search when SOURCES is empty # # LOCAL_CPPPATH: Local file path (.h/.c/.cpp) -# LOCAL_CCFLAGS: Local compilation parameter +# LOCAL_CFLAGS: Local c compilation parameter +# LOCAL_CCFLAGS: Local c/c++ compilation parameter +# LOCAL_CXXFLAGS: Local c++ compilation parameter # LOCAL_ASFLAGS: Local assembly parameters # # CPPPATH: Global file path (.h/.c/.cpp), auto search when LOCAL_CPPPATH/CPPPATH # is empty # no pass!!! -# CCFLAGS: Global compilation parameter +# CFLAGS : Global compilation parameter # ASFLAGS: Global assembly parameters # # CPPDEFINES: Global macro definition @@ -35,22 +37,26 @@ DEPENDS = [""] # # LINKFLAGS: Link options #--------------------------------------------------------------------------------- +CWD = GetCurrentDir() SOURCES = Glob("./source/*.c") -SOURCES += Glob("./source/*.S") -LOCAL_CPPPATH = [] -LOCAL_CCFLAGS = "" +LOCAL_CPPPATH = [] +LOCAL_CFLAGS = "" +LOCAL_CCFLAGS = "" +LOCAL_CXXFLAGS = "" LOCAL_ASFLAGS = "" CPPPATH = [GetCurrentDir(), os.path.join(GetCurrentDir(), 'include')] -CCFLAGS = "" +CFLAGS = "" +CCFLAGS = "" +CXXFLAGS = "" ASFLAGS = "" CPPDEFINES = [] LOCAL_CPPDEFINES = [] LIBS = [] -LIBPATH = [] +LIBPATH = [] LINKFLAGS = "" @@ -62,10 +68,14 @@ CPPPATH_IGNORE = [] #--------------------------------------------------------------------------------- objs = DefineGroup(name = PKGNAME, src = SOURCES, depend = DEPENDS, CPPPATH = CPPPATH, + CFLAGS = CFLAGS, CCFLAGS = CCFLAGS, + CXXFLAGS = CXXFLAGS, ASFLAGS = ASFLAGS, LOCAL_CPPPATH = LOCAL_CPPPATH, + LOCAL_CFLAGS = LOCAL_CFLAGS, LOCAL_CCFLAGS = LOCAL_CCFLAGS, + LOCAL_CXXFLAGS = LOCAL_CXXFLAGS, LOCAL_ASFLAGS = LOCAL_ASFLAGS, CPPDEFINES = CPPDEFINES, LOCAL_CPPDEFINES = LOCAL_CPPDEFINES, diff --git a/bsp/ck802/applications/SConscript b/bsp/ck802/applications/SConscript index 78698e4ad3..8cffec4949 100644 --- a/bsp/ck802/applications/SConscript +++ b/bsp/ck802/applications/SConscript @@ -6,8 +6,8 @@ cwd = os.path.join(str(Dir('#')), 'applications') src = Glob('*.c') CPPPATH = [cwd, str(Dir('#'))] -CCFLAGS = ' -c -mistack -ffunction-sections' +CFLAGS = ' -c -mistack -ffunction-sections' -group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, CCFLAGS=CCFLAGS) +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, CFLAGS=CFLAGS) Return('group') diff --git a/bsp/gd32/docs/GD32系列BSP制作教程.md b/bsp/gd32/docs/GD32系列BSP制作教程.md index 6f0a4427f7..4e517348b5 100644 --- a/bsp/gd32/docs/GD32系列BSP制作教程.md +++ b/bsp/gd32/docs/GD32系列BSP制作教程.md @@ -145,14 +145,14 @@ TARGET = 'rtthread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, AR = rtconfig.AR, ARFLAGS = '-rc', CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) if rtconfig.PLATFORM == 'iar': - env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) env.Replace(ARFLAGS = ['']) env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map') diff --git a/bsp/ra6m4-cpk/ports/fal/SConscript b/bsp/ra6m4-cpk/ports/fal/SConscript index 2b71fcc93c..c8931044c5 100644 --- a/bsp/ra6m4-cpk/ports/fal/SConscript +++ b/bsp/ra6m4-cpk/ports/fal/SConscript @@ -8,15 +8,15 @@ src = [] src += Glob('*.c') CPPPATH = [cwd] -LOCAL_CCFLAGS = '' +LOCAL_CFLAGS = '' if rtconfig.PLATFORM == 'gcc': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' elif rtconfig.PLATFORM == 'armcc': - LOCAL_CCFLAGS += ' --c99' + LOCAL_CFLAGS += ' --c99' elif rtconfig.PLATFORM == 'armclang': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' -group = DefineGroup('FAL', src, depend = ['PKG_USING_FAL'], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS) +group = DefineGroup('FAL', src, depend = ['PKG_USING_FAL'], CPPPATH = CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS) Return('group') diff --git a/bsp/ra6m4-cpk/ports/rw007/SConscript b/bsp/ra6m4-cpk/ports/rw007/SConscript index 7ce64a6c3c..99b97f1a80 100644 --- a/bsp/ra6m4-cpk/ports/rw007/SConscript +++ b/bsp/ra6m4-cpk/ports/rw007/SConscript @@ -8,15 +8,15 @@ src = [] src += Glob('*.c') CPPPATH = [cwd] -LOCAL_CCFLAGS = '' +LOCAL_CFLAGS = '' if rtconfig.PLATFORM == 'gcc': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' elif rtconfig.PLATFORM == 'armcc': - LOCAL_CCFLAGS += ' --c99' + LOCAL_CFLAGS += ' --c99' elif rtconfig.PLATFORM == 'armclang': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' -group = DefineGroup('rw007', src, depend = ['BSP_USING_RW007'], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS) +group = DefineGroup('rw007', src, depend = ['BSP_USING_RW007'], CPPPATH = CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS) Return('group') diff --git a/bsp/stm32/stm32h743-openmv-h7plus/SConstruct b/bsp/stm32/stm32h743-openmv-h7plus/SConstruct index a7cc0cb251..7adb1878ab 100644 --- a/bsp/stm32/stm32h743-openmv-h7plus/SConstruct +++ b/bsp/stm32/stm32h743-openmv-h7plus/SConstruct @@ -20,14 +20,14 @@ TARGET = 'rt-thread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, AR = rtconfig.AR, ARFLAGS = '-rc', CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) if rtconfig.PLATFORM == 'iar': - env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) + env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) env.Replace(ARFLAGS = ['']) env.Replace(LINKCOM = env["LINKCOM"] + ' --map rt-thread.map') diff --git a/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript b/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript index 4a53bd1c97..045b8d91df 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript +++ b/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript @@ -8,16 +8,16 @@ src = [] src += Glob('*.c') CPPPATH = [cwd] -LOCAL_CCFLAGS = '' +LOCAL_CFLAGS = '' if rtconfig.CROSS_TOOL == 'gcc': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' elif rtconfig.CROSS_TOOL == 'keil': if rtconfig.PLATFORM == 'armcc': - LOCAL_CCFLAGS += ' --c99' + LOCAL_CFLAGS += ' --c99' elif rtconfig.PLATFORM == 'armclang': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' -group = DefineGroup('FAL', src, depend = ['PKG_USING_FAL'], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS) +group = DefineGroup('FAL', src, depend = ['PKG_USING_FAL'], CPPPATH = CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS) Return('group') diff --git a/bsp/thead-smart/applications/SConscript b/bsp/thead-smart/applications/SConscript index b95023ca41..873f10c6e5 100644 --- a/bsp/thead-smart/applications/SConscript +++ b/bsp/thead-smart/applications/SConscript @@ -6,8 +6,8 @@ cwd = GetCurrentDir() src = Glob('*.c') CPPPATH = GetCurrentDir() -CCFLAGS = ' -c -ffunction-sections' +CFLAGS = ' -c -ffunction-sections' -group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, CCFLAGS=CCFLAGS) +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH, CFLAGS=CFLAGS) Return('group') diff --git a/bsp/tm4c129x/libraries/SConscript b/bsp/tm4c129x/libraries/SConscript index 56c7b84ab3..9262cbfe87 100644 --- a/bsp/tm4c129x/libraries/SConscript +++ b/bsp/tm4c129x/libraries/SConscript @@ -6,7 +6,7 @@ from building import * cwd = GetCurrentDir() src = Glob('driverlib/*.c') SrcRemove(src, 'onewire.c') -CCFLAGS = '' +CFLAGS = '' # add for startup script if rtconfig.CROSS_TOOL == 'gcc': @@ -15,12 +15,12 @@ elif rtconfig.CROSS_TOOL == 'keil': src += ['startup/startup_rvmdk.S'] elif rtconfig.CROSS_TOOL == 'iar': src += ['startup/startup_ewarm.c'] - CCFLAGS += ' --diag_suppress=pe177' + CFLAGS += ' --diag_suppress=pe177' CPPPATH = [cwd, cwd + '/inc', cwd + '/driverlib'] CPPDEFINES = [rtconfig.PART_TYPE] -group = DefineGroup('Libraries', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, CCFLAGS = CCFLAGS) +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, CFLAGS = CFLAGS) Return('group') diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index d6cb93f7f1..fab1298f8a 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -4,7 +4,7 @@ import rtconfig cwd = GetCurrentDir() src = ['spi_core.c', 'spi_dev.c'] CPPPATH = [cwd, cwd + '/../include'] -LOCAL_CCFLAGS = '' +LOCAL_CFLAGS = '' if GetDepend('RT_USING_QSPI'): src += ['qspi_core.c'] @@ -26,15 +26,15 @@ if GetDepend('RT_USING_SFUD'): if GetDepend('RT_SFUD_USING_SFDP'): src_device += ['sfud/src/sfud_sfdp.c'] if rtconfig.CROSS_TOOL == 'gcc': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' elif rtconfig.CROSS_TOOL == 'keil': if rtconfig.PLATFORM == 'armcc': - LOCAL_CCFLAGS += ' --c99' + LOCAL_CFLAGS += ' --c99' elif rtconfig.PLATFORM == 'armclang': - LOCAL_CCFLAGS += ' -std=c99' + LOCAL_CFLAGS += ' -std=c99' src += src_device -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SPI'], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS) +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SPI'], CPPPATH = CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS) Return('group') diff --git a/tools/building.py b/tools/building.py index 10641c11a9..23fe64e2f6 100644 --- a/tools/building.py +++ b/tools/building.py @@ -557,11 +557,21 @@ def AddDepend(option): def MergeGroup(src_group, group): src_group['src'] = src_group['src'] + group['src'] + if 'CFLAGS' in group: + if 'CFLAGS' in src_group: + src_group['CFLAGS'] = src_group['CFLAGS'] + group['CFLAGS'] + else: + src_group['CFLAGS'] = group['CFLAGS'] if 'CCFLAGS' in group: if 'CCFLAGS' in src_group: src_group['CCFLAGS'] = src_group['CCFLAGS'] + group['CCFLAGS'] else: src_group['CCFLAGS'] = group['CCFLAGS'] + if 'CXXFLAGS' in group: + if 'CXXFLAGS' in src_group: + src_group['CXXFLAGS'] = src_group['CXXFLAGS'] + group['CXXFLAGS'] + else: + src_group['CXXFLAGS'] = group['CXXFLAGS'] if 'CPPPATH' in group: if 'CPPPATH' in src_group: src_group['CPPPATH'] = src_group['CPPPATH'] + group['CPPPATH'] @@ -579,11 +589,21 @@ def MergeGroup(src_group, group): src_group['ASFLAGS'] = group['ASFLAGS'] # for local CCFLAGS/CPPPATH/CPPDEFINES + if 'LOCAL_CFLAGS' in group: + if 'LOCAL_CFLAGS' in src_group: + src_group['LOCAL_CFLAGS'] = src_group['LOCAL_CFLAGS'] + group['LOCAL_CFLAGS'] + else: + src_group['LOCAL_CFLAGS'] = group['LOCAL_CFLAGS'] if 'LOCAL_CCFLAGS' in group: if 'LOCAL_CCFLAGS' in src_group: src_group['LOCAL_CCFLAGS'] = src_group['LOCAL_CCFLAGS'] + group['LOCAL_CCFLAGS'] else: src_group['LOCAL_CCFLAGS'] = group['LOCAL_CCFLAGS'] + if 'LOCAL_CXXFLAGS' in group: + if 'LOCAL_CXXFLAGS' in src_group: + src_group['LOCAL_CXXFLAGS'] = src_group['LOCAL_CXXFLAGS'] + group['LOCAL_CXXFLAGS'] + else: + src_group['LOCAL_CXXFLAGS'] = group['LOCAL_CXXFLAGS'] if 'LOCAL_CPPPATH' in group: if 'LOCAL_CPPPATH' in src_group: src_group['LOCAL_CPPPATH'] = src_group['LOCAL_CPPPATH'] + group['LOCAL_CPPPATH'] @@ -650,10 +670,18 @@ def DefineGroup(name, src, depend, **parameters): else: group['src'] = src + if 'CFLAGS' in group: + target = group['CFLAGS'] + if len(target) > 0: + Env.AppendUnique(CFLAGS = target) if 'CCFLAGS' in group: target = group['CCFLAGS'] if len(target) > 0: Env.AppendUnique(CCFLAGS = target) + if 'CXXFLAGS' in group: + target = group['CXXFLAGS'] + if len(target) > 0: + Env.AppendUnique(CXXFLAGS = target) if 'CPPPATH' in group: target = group['CPPPATH'] if _PretreatListParameters(target) == True: @@ -682,11 +710,18 @@ def DefineGroup(name, src, depend, **parameters): import rtconfig if rtconfig.PLATFORM == 'gcc': + if 'CFLAGS' in group: + group['CFLAGS'] = utils.GCCC99Patch(group['CFLAGS']) if 'CCFLAGS' in group: group['CCFLAGS'] = utils.GCCC99Patch(group['CCFLAGS']) + if 'CXXFLAGS' in group: + group['CXXFLAGS'] = utils.GCCC99Patch(group['CXXFLAGS']) if 'LOCAL_CCFLAGS' in group: group['LOCAL_CCFLAGS'] = utils.GCCC99Patch(group['LOCAL_CCFLAGS']) - + if 'LOCAL_CXXFLAGS' in group: + group['LOCAL_CXXFLAGS'] = utils.GCCC99Patch(group['LOCAL_CXXFLAGS']) + if 'LOCAL_CFLAGS' in group: + group['LOCAL_CFLAGS'] = utils.GCCC99Patch(group['LOCAL_CFLAGS']) # check whether to clean up library if GetOption('cleanlib') and os.path.exists(os.path.join(group['path'], GroupLibFullName(name, Env))): if group['src'] != []: @@ -785,14 +820,16 @@ def DoBuilding(target, objects): # handle local group def local_group(group, objects): - if 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group or 'LOCAL_ASFLAGS' in group: + if 'LOCAL_CFLAGS' in group or 'LOCAL_CXXFLAGS' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group or 'LOCAL_ASFLAGS' in group: + CFLAGS = Env.get('CFLAGS', '') + group.get('LOCAL_CFLAGS', '') CCFLAGS = Env.get('CCFLAGS', '') + group.get('LOCAL_CCFLAGS', '') + CXXFLAGS = Env.get('CXXFLAGS', '') + group.get('LOCAL_CXXFLAGS', '') CPPPATH = Env.get('CPPPATH', ['']) + group.get('LOCAL_CPPPATH', ['']) CPPDEFINES = Env.get('CPPDEFINES', ['']) + group.get('LOCAL_CPPDEFINES', ['']) ASFLAGS = Env.get('ASFLAGS', '') + group.get('LOCAL_ASFLAGS', '') for source in group['src']: - objects.append(Env.Object(source, CCFLAGS = CCFLAGS, ASFLAGS = ASFLAGS, + objects.append(Env.Object(source, CFLAGS = CFLAGS, CCFLAGS = CCFLAGS, CXXFLAGS = CXXFLAGS, ASFLAGS = ASFLAGS, CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)) return True @@ -822,7 +859,7 @@ def DoBuilding(target, objects): else: # remove source files with local flags setting for group in Projects: - if 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group: + if 'LOCAL_CFLAGS' in group or 'LOCAL_CXXFLAGS' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPPATH' in group or 'LOCAL_CPPDEFINES' in group: for source in group['src']: for obj in objects: if source.abspath == obj.abspath or (len(obj.sources) > 0 and source.abspath == obj.sources[0].abspath): diff --git a/tools/codelite.py b/tools/codelite.py index 9b2060dfa5..f4e612be61 100644 --- a/tools/codelite.py +++ b/tools/codelite.py @@ -194,8 +194,8 @@ def TargetCodelite(script, program): #print building.Env.get('LIBPATH', []) #print building.Env.get('LIBS', []) - CLSetCFlags(root, building.Env.get('CCFLAGS', [])) - CLSetCxxFlags(root, building.Env.get('CCFLAGS', [])) + CLSetCFlags(root, building.Env.get('CFLAGS', [])) + CLSetCxxFlags(root, building.Env.get('CFLAGS', [])) asflags = building.Env.get('ASFLAGS', []) asflags = asflags.replace('-ffunction-sections', '') diff --git a/tools/iar.py b/tools/iar.py index a0028128e3..6b31976d05 100644 --- a/tools/iar.py +++ b/tools/iar.py @@ -88,7 +88,7 @@ def IARProject(target, script): CPPPATH = [] CPPDEFINES = [] LINKFLAGS = '' - CCFLAGS = '' + CFLAGS = '' Libs = [] lib_prefix = ['lib', ''] lib_suffix = ['.a', '.o', ''] diff --git a/tools/keil.py b/tools/keil.py index b3643fbe74..b1ce0610c4 100644 --- a/tools/keil.py +++ b/tools/keil.py @@ -192,7 +192,7 @@ def MDK45Project(tree, target, script): CPPPATH = [] CPPDEFINES = [] LINKFLAGS = '' - CCFLAGS = '' + CFLAGS = '' ProjectFiles = [] # add group @@ -204,14 +204,14 @@ def MDK45Project(tree, target, script): group_tree = MDK4AddGroup(ProjectFiles, groups, group['name'], group['src'], project_path) # for local CPPPATH/CPPDEFINES - if (group_tree != None) and ('LOCAL_CPPPATH' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPDEFINES' in group): + if (group_tree != None) and ('LOCAL_CPPPATH' in group or 'LOCAL_CFLAGS' in group or 'LOCAL_CPPDEFINES' in group): GroupOption = SubElement(group_tree, 'GroupOption') GroupArmAds = SubElement(GroupOption, 'GroupArmAds') Cads = SubElement(GroupArmAds, 'Cads') VariousControls = SubElement(Cads, 'VariousControls') MiscControls = SubElement(VariousControls, 'MiscControls') - if 'LOCAL_CCFLAGS' in group: - MiscControls.text = group['LOCAL_CCFLAGS'] + if 'LOCAL_CFLAGS' in group: + MiscControls.text = group['LOCAL_CFLAGS'] else: MiscControls.text = ' ' Define = SubElement(VariousControls, 'Define') @@ -329,7 +329,7 @@ def MDKProject(target, script): CPPPATH = [] CPPDEFINES = [] LINKFLAGS = '' - CCFLAGS = '' + CFLAGS = '' # number of groups group_index = 1 diff --git a/tools/ses.py b/tools/ses.py index cc513f0baa..67ea8b0cbe 100644 --- a/tools/ses.py +++ b/tools/ses.py @@ -49,7 +49,7 @@ def SESProject(env) : CPPPATH = [] CPPDEFINES = [] LINKFLAGS = '' - CCFLAGS = '' + CFLAGS = '' project_node = tree.find('project') @@ -59,11 +59,11 @@ def SESProject(env) : group_tree = SDKAddGroup(project_node, group['name'], group['src'], project_path) # get each group's cc flags - if 'CCFLAGS' in group and group['CCFLAGS']: - if CCFLAGS: - CCFLAGS += ' ' + group['CCFLAGS'] + if 'CFLAGS' in group and group['CFLAGS']: + if CFLAGS: + CFLAGS += ' ' + group['CFLAGS'] else: - CCFLAGS += group['CCFLAGS'] + CFLAGS += group['CFLAGS'] # get each group's link flags if 'LINKFLAGS' in group and group['LINKFLAGS']: From 884218588ae6a68ed923e4a9774f2ea4d76b90db Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 19 Jan 2022 23:24:47 -0500 Subject: [PATCH 30/65] =?UTF-8?q?[sconscript.platform]=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=92=88=E5=AF=B9=E7=BC=96=E8=AF=91=E5=99=A8=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E7=9A=84=E8=84=9A=E6=9C=AC=20-=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=95=B0=E5=97=A6=E7=9A=84=E4=BB=A3=E7=A0=81=20related:=20http?= =?UTF-8?q?s://github.com/RT-Thread/rt-thread/issues/3046?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stm32l475-atk-pandora/board/ports/fal/SConscript | 11 +++++------ components/drivers/spi/SConscript | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript b/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript index 4a53bd1c97..2b71fcc93c 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript +++ b/bsp/stm32/stm32l475-atk-pandora/board/ports/fal/SConscript @@ -10,13 +10,12 @@ src += Glob('*.c') CPPPATH = [cwd] LOCAL_CCFLAGS = '' -if rtconfig.CROSS_TOOL == 'gcc': +if rtconfig.PLATFORM == 'gcc': + LOCAL_CCFLAGS += ' -std=c99' +elif rtconfig.PLATFORM == 'armcc': + LOCAL_CCFLAGS += ' --c99' +elif rtconfig.PLATFORM == 'armclang': LOCAL_CCFLAGS += ' -std=c99' -elif rtconfig.CROSS_TOOL == 'keil': - if rtconfig.PLATFORM == 'armcc': - LOCAL_CCFLAGS += ' --c99' - elif rtconfig.PLATFORM == 'armclang': - LOCAL_CCFLAGS += ' -std=c99' group = DefineGroup('FAL', src, depend = ['PKG_USING_FAL'], CPPPATH = CPPPATH, LOCAL_CCFLAGS = LOCAL_CCFLAGS) diff --git a/components/drivers/spi/SConscript b/components/drivers/spi/SConscript index d6cb93f7f1..f1c2bd343d 100644 --- a/components/drivers/spi/SConscript +++ b/components/drivers/spi/SConscript @@ -25,13 +25,12 @@ if GetDepend('RT_USING_SFUD'): CPPPATH += [cwd + '/sfud/inc'] if GetDepend('RT_SFUD_USING_SFDP'): src_device += ['sfud/src/sfud_sfdp.c'] - if rtconfig.CROSS_TOOL == 'gcc': + if rtconfig.PLATFORM == 'gcc': + LOCAL_CCFLAGS += ' -std=c99' + elif rtconfig.PLATFORM == 'armcc': + LOCAL_CCFLAGS += ' --c99' + elif rtconfig.PLATFORM == 'armclang': LOCAL_CCFLAGS += ' -std=c99' - elif rtconfig.CROSS_TOOL == 'keil': - if rtconfig.PLATFORM == 'armcc': - LOCAL_CCFLAGS += ' --c99' - elif rtconfig.PLATFORM == 'armclang': - LOCAL_CCFLAGS += ' -std=c99' src += src_device From add72f1d7cc32a8d302f6e5549b82b4ce06a5a9a Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Wed, 19 Jan 2022 16:13:23 -0500 Subject: [PATCH 31/65] [dfs][posix] add creat() --- components/dfs/src/dfs_posix.c | 16 ++++++++++++++++ .../libc/compilers/common/extension/fcntl.h | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c index 5b26f190ce..3008a06da5 100644 --- a/components/dfs/src/dfs_posix.c +++ b/components/dfs/src/dfs_posix.c @@ -7,6 +7,7 @@ * Date Author Notes * 2009-05-27 Yi.qiu The first version * 2018-02-07 Bernard Change the 3rd parameter of open/fcntl/ioctl to '...' + * 2022-01-19 Meco Man add creat() */ #include @@ -56,6 +57,21 @@ int open(const char *file, int flags, ...) } RTM_EXPORT(open); +/** + * this function is a POSIX compliant version, + * which will create a new file or rewrite an existing one + * + * @param path the path name of file. + * @param mode the file permission bits to be used in creating the file (not used, can be 0) + * + * @return the non-negative integer on successful open, others for failed. + */ +int creat(const char *path, mode_t mode) +{ + return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); +} +RTM_EXPORT(creat); + /** * this function is a POSIX compliant version, which will close the open * file descriptor. diff --git a/components/libc/compilers/common/extension/fcntl.h b/components/libc/compilers/common/extension/fcntl.h index 83c3ec0b6b..ac642abcbb 100644 --- a/components/libc/compilers/common/extension/fcntl.h +++ b/components/libc/compilers/common/extension/fcntl.h @@ -11,7 +11,7 @@ #ifndef __FCNTL_H__ #define __FCNTL_H__ -#include +#include "sys/types.h" #define O_RDONLY 00 #define O_WRONLY 01 @@ -66,6 +66,6 @@ int open(const char *file, int flags, ...); int fcntl(int fildes, int cmd, ...); -int creat(const char *, mode_t); +int creat(const char *path, mode_t mode); #endif From c811ecf998771dc5919d376610382aa11447a751 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 20 Jan 2022 14:29:38 +0800 Subject: [PATCH 32/65] [tool] Fix bug with missing brackets in eclipse.py --- tools/eclipse.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/eclipse.py b/tools/eclipse.py index 410952ce20..736fcbc66d 100644 --- a/tools/eclipse.py +++ b/tools/eclipse.py @@ -365,7 +365,7 @@ def UpdateProjectStructure(env, prj_name): out = open('.project', 'w') out.write('\n') xml_indent(root) - out.write(etree.tostring(root, encoding='utf-8').decode('utf-8') + out.write(etree.tostring(root, encoding='utf-8').decode('utf-8')) out.close() return @@ -504,7 +504,7 @@ def UpdateCproject(env, project, excluding, reset, prj_name): out.write('\n') out.write('') xml_indent(root) - out.write(etree.tostring(root, encoding='utf-8').decode('utf-8') + out.write(etree.tostring(root, encoding='utf-8').decode('utf-8')) out.close() From 5820cc27b8b106ac79f0a7cfbe2d0763a97b0bdf Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 20 Jan 2022 15:24:36 +0800 Subject: [PATCH 33/65] [ci] add scons tools test --- .github/workflows/action_tools.yml | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/workflows/action_tools.yml diff --git a/.github/workflows/action_tools.yml b/.github/workflows/action_tools.yml new file mode 100644 index 0000000000..7c59ae7b37 --- /dev/null +++ b/.github/workflows/action_tools.yml @@ -0,0 +1,82 @@ +name: ToolsCI + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + # Runs at 16:00 UTC (BeiJing 00:00) on the 1st of every month + schedule: + - cron: '0 16 1 * *' + push: + branches: + - master + paths-ignore: + - documentation/** + - '**/README.md' + - '**/README_zh.md' + - '**/*.c' + - '**/*.h' + - '**/*.cpp' + pull_request: + branches: + - master + paths-ignore: + - documentation/** + - '**/README.md' + - '**/README_zh.md' + - '**/*.c' + - '**/*.h' + - '**/*.cpp' + +jobs: + test: + runs-on: ubuntu-latest + name: Tools + strategy: + fail-fast: false + env: + TEST_BSP_ROOT: bsp/stm32/stm32f407-atk-explorer + steps: + - uses: actions/checkout@v1 + + - name: Install Tools + shell: bash + run: | + sudo apt-get update + sudo apt-get -yqq install scons + + - name: Install Arm ToolChains + if: ${{ success() }} + shell: bash + run: | + wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/v1.3/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 + sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt + /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version + echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin" >> $GITHUB_ENV + + - name: Build Tools + run: | + scons --pyconfig-silent -C $TEST_BSP_ROOT + scons -j$(nproc) -C $TEST_BSP_ROOT + + - name: Project generate Tools + if: ${{ success() }} + run: | + echo "Test to generate mdk project" + scons --target=mdk -s -C $TEST_BSP_ROOT + scons --target=mdk4 -s -C $TEST_BSP_ROOT + scons --target=mdk5 -s -C $TEST_BSP_ROOT + echo "Test to generate iar project" + scons --target=iar -s -C $TEST_BSP_ROOT + echo "Test to generate eclipse project" + scons --target=eclipse -s -C $TEST_BSP_ROOT + echo "Test to generate cmake project" + scons --target=cmake -s -C $TEST_BSP_ROOT + echo "Test to generate makefile project" + scons --target=makefile -s -C $TEST_BSP_ROOT + + - name: Project dist Tools + if: ${{ success() }} + run: | + echo "Test to dist project" + scons --dist -C $TEST_BSP_ROOT + scons --dist-ide -C $TEST_BSP_ROOT From 4dab5e0e59680ca77c5c3beab0d08ac15d1a1af9 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Thu, 20 Jan 2022 15:25:40 +0800 Subject: [PATCH 34/65] [ci] Optimize AutoTestCI trigger timing. --- .github/workflows/action_utest.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/action_utest.yml b/.github/workflows/action_utest.yml index b83fd21bdd..cb7707059b 100644 --- a/.github/workflows/action_utest.yml +++ b/.github/workflows/action_utest.yml @@ -1,7 +1,25 @@ name: AutoTestCI # Controls when the action will run. Triggers the workflow on push or pull request -on: [push, pull_request] +# events but only for the master branch +on: + # Runs at 16:00 UTC (BeiJing 00:00) on the 1st of every month + schedule: + - cron: '0 16 1 * *' + push: + branches: + - master + paths-ignore: + - documentation/** + - '**/README.md' + - '**/README_zh.md' + pull_request: + branches: + - master + paths-ignore: + - documentation/** + - '**/README.md' + - '**/README_zh.md' jobs: test: From 075e04e344f0cea8d62504c244861f473921c495 Mon Sep 17 00:00:00 2001 From: xiangxistu <52819708+xiangxistu@users.noreply.github.com> Date: Thu, 20 Jan 2022 20:53:47 +0800 Subject: [PATCH 35/65] the support for PSE51 (#5534) * [add] the function realization of signal for posix. * [update] the posix support for armclang. * [add] the new macro "RT_USING_POSIX_TIMER". * [modify] select "RT_USING_SOFT_TIMER" when use posix'timer. * [bug] optimize the logic for the "time_xxx" functions. * [modify] use "RT_USING_POSIX_TIMER" to protect the macro definition. * [modify] error code when except happened. * [delete] the "environ" is useless at this time. --- .../compilers/common/extension/sys/types.h | 2 + .../compilers/common/extension/sys/unistd.h | 3 + components/libc/compilers/common/sys/signal.h | 38 ++ components/libc/compilers/common/sys/time.h | 29 +- components/libc/compilers/common/time.c | 263 ++++++++++++++ components/libc/posix-info.txt | 327 ++++++++++++++++++ components/libc/posix/Kconfig | 5 + components/libc/posix/delay/delay.h | 1 + components/libc/posix/pthreads/pthread.h | 4 + components/libc/posix/signal/posix_signal.c | 40 ++- include/rtdef.h | 1 + src/timer.c | 2 + 12 files changed, 711 insertions(+), 4 deletions(-) create mode 100644 components/libc/posix-info.txt diff --git a/components/libc/compilers/common/extension/sys/types.h b/components/libc/compilers/common/extension/sys/types.h index 32b2493c95..85cd4fea21 100644 --- a/components/libc/compilers/common/extension/sys/types.h +++ b/components/libc/compilers/common/extension/sys/types.h @@ -28,6 +28,8 @@ typedef signed int ssize_t; /* Used for a count of bytes or an error #else typedef long signed int ssize_t; /* Used for a count of bytes or an error indication. */ #endif +typedef unsigned long __timer_t; +typedef __timer_t timer_t; typedef long suseconds_t; /* microseconds. */ typedef unsigned long useconds_t; /* microseconds (unsigned) */ diff --git a/components/libc/compilers/common/extension/sys/unistd.h b/components/libc/compilers/common/extension/sys/unistd.h index 650c87dc18..29ec3f70c4 100644 --- a/components/libc/compilers/common/extension/sys/unistd.h +++ b/components/libc/compilers/common/extension/sys/unistd.h @@ -19,10 +19,13 @@ #define STDOUT_FILENO 1 /* standard output file descriptor */ #define STDERR_FILENO 2 /* standard error file descriptor */ +unsigned alarm(unsigned __secs); ssize_t read(int fd, void *buf, size_t len); ssize_t write(int fd, const void *buf, size_t len); off_t lseek(int fd, off_t offset, int whence); +int pause(void); int fsync(int fildes); +long sysconf(int __name); int unlink(const char *pathname); int close(int d); int ftruncate(int fd, off_t length); diff --git a/components/libc/compilers/common/sys/signal.h b/components/libc/compilers/common/sys/signal.h index 9787958a37..041dd765b7 100644 --- a/components/libc/compilers/common/sys/signal.h +++ b/components/libc/compilers/common/sys/signal.h @@ -17,6 +17,19 @@ extern "C" { #endif #include +#include + + +/* sigev_notify values + NOTE: P1003.1c/D10, p. 34 adds SIGEV_THREAD. */ + +#define SIGEV_NONE 1 /* No asynchronous notification shall be delivered */ + /* when the event of interest occurs. */ +#define SIGEV_SIGNAL 2 /* A queued signal, with an application defined */ + /* value, shall be delivered when the event of */ + /* interest occurs. */ +#define SIGEV_THREAD 3 /* A notification function shall be called to */ + /* perform notification. */ /* Signal Generation and Delivery, P1003.1b-1993, p. 63 NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and @@ -62,6 +75,16 @@ struct sigaction int sa_flags; }; +/* + * Structure used in sigaltstack call. + */ +typedef struct sigaltstack +{ + void *ss_sp; /* Stack base or pointer. */ + int ss_flags; /* Flags. */ + size_t ss_size; /* Stack size. */ +} stack_t; + #define SIG_SETMASK 0 /* set mask with sigprocmask() */ #define SIG_BLOCK 1 /* set of signals to block */ #define SIG_UNBLOCK 2 /* set of signals to, well, unblock */ @@ -73,6 +96,15 @@ struct sigaction #define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0) int sigprocmask (int how, const sigset_t *set, sigset_t *oset); +int sigpending (sigset_t *set); +int sigsuspend (const sigset_t *set); + +#include "time.h" +int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout); +int sigwait(const sigset_t *set, int *sig); +int sigwaitinfo(const sigset_t *set, siginfo_t *info); +int raise(int sig); +int sigqueue(pid_t pid, int signo, const union sigval value); int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); #ifdef __ARMCC_VERSION @@ -100,6 +132,9 @@ int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) #define SIGTTOU 22 #define SIGPOLL 23 #define SIGWINCH 24 +#define SIGXCPU 24 /* exceeded CPU time limit */ +#define SIGXFSZ 25 /* exceeded file size limit */ +#define SIGVTALRM 26 /* virtual time alarm */ /* #define SIGUSR1 25 */ /* #define SIGUSR2 26 */ #define SIGRTMIN 27 @@ -133,6 +168,9 @@ int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) #define SIGTTOU 22 #define SIGPOLL 23 #define SIGWINCH 24 +#define SIGXCPU 24 /* exceeded CPU time limit */ +#define SIGXFSZ 25 /* exceeded file size limit */ +#define SIGVTALRM 26 /* virtual time alarm */ #define SIGUSR1 25 #define SIGUSR2 26 #define SIGRTMIN 27 diff --git a/components/libc/compilers/common/sys/time.h b/components/libc/compilers/common/sys/time.h index 758333796d..a3af31b20b 100644 --- a/components/libc/compilers/common/sys/time.h +++ b/components/libc/compilers/common/sys/time.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -60,6 +60,16 @@ struct timespec time_t tv_sec; /* seconds */ long tv_nsec; /* and nanoseconds */ }; + +/* + * Structure defined by POSIX.1b to be like a itimerval, but with + * timespecs. Used in the timer_*() system calls. + */ +struct itimerspec +{ + struct timespec it_interval; + struct timespec it_value; +}; #endif int stime(const time_t *t); @@ -68,6 +78,9 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv, const struct timezone *tz); #if defined(__ARMCC_VERSION) || defined (__ICCARM__) struct tm *gmtime_r(const time_t *timep, struct tm *r); +struct tm* localtime_r(const time_t* t, struct tm* r); +char* asctime_r(const struct tm *t, char *buf); +char *ctime_r(const time_t * tim_p, char * result); #elif defined(_WIN32) struct tm* gmtime_r(const time_t* timep, struct tm* r); struct tm* gmtime(const time_t* t); @@ -84,7 +97,7 @@ time_t time(time_t* t); int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); #endif /* RT_USING_POSIX_DELAY */ -#ifdef RT_USING_POSIX_CLOCK +#if defined(RT_USING_POSIX_CLOCK) || defined (RT_USING_POSIX_TIMER) /* POSIX clock and timer */ #define MILLISECOND_PER_SECOND 1000UL #define MICROSECOND_PER_SECOND 1000000UL @@ -110,7 +123,9 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 4 #endif +#endif /* defined(RT_USING_POSIX_CLOCK) || defined (RT_USING_POSIX_TIMER) */ +#ifdef RT_USING_POSIX_CLOCK int clock_getres (clockid_t clockid, struct timespec *res); int clock_gettime (clockid_t clockid, struct timespec *tp); int clock_settime (clockid_t clockid, const struct timespec *tp); @@ -118,6 +133,16 @@ int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, s int rt_timespec_to_tick(const struct timespec *time); #endif /* RT_USING_POSIX_CLOCK */ +#ifdef RT_USING_POSIX_TIMER +#include "signal.h" +int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid); +int timer_delete(timer_t timerid); +int timer_getoverrun(timer_t timerid); +int timer_gettime(timer_t timerid, struct itimerspec *its); +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, + struct itimerspec *ovalue); +#endif /* RT_USING_POSIX_TIMER */ + /* timezone */ void tz_set(int8_t tz); int8_t tz_get(void); diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index 0b34236952..a963b25f1a 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -718,6 +718,269 @@ RTM_EXPORT(rt_timespec_to_tick); #endif /* RT_USING_POSIX_CLOCK */ +#ifdef RT_USING_POSIX_TIMER + +#define ACTIVE 1 +#define NOT_ACTIVE 0 + +struct timer_obj +{ + struct rt_timer timer; + void (*sigev_notify_function)(union sigval val); + union sigval val; + struct timespec interval; /* Reload value */ + rt_uint32_t reload; /* Reload value in ms */ + rt_uint32_t status; +}; + +static void rtthread_timer_wrapper(void *timerobj) +{ + struct timer_obj *timer; + + timer = (struct timer_obj *)timerobj; + + if (timer->reload == 0U) + { + timer->status = NOT_ACTIVE; + } + + if(timer->sigev_notify_function != RT_NULL) + { + (timer->sigev_notify_function)(timer->val); + } +} + +/** + * @brief Create a per-process timer. + * + * This API does not accept SIGEV_THREAD as valid signal event notification + * type. + * + * See IEEE 1003.1 + */ +int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid) +{ + static int num = 0; + struct timer_obj *timer; + char timername[RT_NAME_MAX] = {0}; + + if (clockid != CLOCK_MONOTONIC || evp == NULL || + (evp->sigev_notify != SIGEV_NONE && + evp->sigev_notify != SIGEV_SIGNAL)) + { + rt_set_errno(EINVAL); + return -RT_ERROR; + } + + timer = rt_malloc(sizeof(struct timer_obj)); + if(timer == RT_NULL) + { + rt_set_errno(ENOMEM); + return -RT_ENOMEM; + } + + RT_ASSERT(evp->sigev_notify_function != RT_NULL); + rt_snprintf(timername, RT_NAME_MAX, "psx_tm%02d", num++); + num %= 100; + timer->sigev_notify_function = evp->sigev_notify_function; + timer->val = evp->sigev_value; + timer->interval.tv_sec = 0; + timer->interval.tv_nsec = 0; + timer->reload = 0U; + timer->status = NOT_ACTIVE; + + if (evp->sigev_notify == SIGEV_NONE) + { + rt_timer_init(&timer->timer, timername, RT_NULL, RT_NULL, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); + } + else + { + rt_timer_init(&timer->timer, timername, rtthread_timer_wrapper, timer, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); + } + + *timerid = (timer_t)timer; + + return RT_EOK; +} +RTM_EXPORT(timer_create); + +/** + * @brief Delete a per-process timer. + * + * See IEEE 1003.1 + */ +int timer_delete(timer_t timerid) +{ + struct timer_obj *timer = (struct timer_obj *)timerid; + + if (timer == RT_NULL) + { + rt_set_errno(EINVAL); + return -RT_ERROR; + } + + if (timer->status == ACTIVE) + { + timer->status = NOT_ACTIVE; + rt_timer_stop(&timer->timer); + } + + rt_free(timer); + + return RT_EOK; +} +RTM_EXPORT(timer_delete); + +/** + * + * Return the overrun count for the last timer expiration. + * It is subefficient to create a new structure to get overrun count. + **/ +int timer_getoverrun(timer_t timerid) +{ + rt_set_errno(ENOSYS); + return -RT_ERROR; +} + +/** + * @brief Get amount of time left for expiration on a per-process timer. + * + * See IEEE 1003.1 + */ +int timer_gettime(timer_t timerid, struct itimerspec *its) +{ + struct timer_obj *timer = (struct timer_obj *)timerid; + rt_tick_t remaining; + rt_uint32_t seconds, nanoseconds; + rt_int64_t nsecs, secs; + + if (timer == NULL) + { + rt_set_errno(EINVAL); + return -RT_ERROR; + } + + if (its == NULL) + { + rt_set_errno(EFAULT); + return -RT_ERROR; + } + + if (timer->status == ACTIVE) + { + rt_tick_t remain_tick; + + rt_timer_control(&timer->timer, RT_TIMER_CTRL_GET_REMAIN_TIME, &remain_tick); + + /* 'remain_tick' is minimum-unit in the RT-Thread' timer, + * so the seconds, nanoseconds will be calculated by 'remain_tick'. + */ + remaining = remain_tick - rt_tick_get(); + + /* calculate 'second' */ + seconds = remaining / RT_TICK_PER_SECOND; + + /* calculate 'nanosecond'; To avoid lost of accuracy, because "RT_TICK_PER_SECOND" maybe 100, 1000, 1024 and so on. + * + * remain_tick millisecond remain_tick * MILLISECOND_PER_SECOND + * ------------------------- = -------------------------- ---> millisecond = ------------------------------------------- + * RT_TICK_PER_SECOND MILLISECOND_PER_SECOND RT_TICK_PER_SECOND + * + * remain_tick * MILLISECOND_PER_SECOND remain_tick * MILLISECOND_PER_SECOND * MICROSECOND_PER_SECOND + * millisecond = ---------------------------------------- ---> nanosecond = ------------------------------------------------------------------- + * RT_TICK_PER_SECOND RT_TICK_PER_SECOND + * + */ + nanoseconds = (((remaining % RT_TICK_PER_SECOND) * MILLISECOND_PER_SECOND) * MICROSECOND_PER_SECOND) / RT_TICK_PER_SECOND ; + + its->it_value.tv_sec = (rt_int32_t)seconds; + its->it_value.tv_nsec = (rt_int32_t)nanoseconds; + } + else + { + /* Timer is disarmed */ + its->it_value.tv_sec = 0; + its->it_value.tv_nsec = 0; + } + + /* The interval last set by timer_settime() */ + its->it_interval = timer->interval; + return RT_EOK; +} +RTM_EXPORT(timer_gettime); + +/** + * @brief Sets expiration time of per-process timer. + * + * See IEEE 1003.1 + */ +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, + struct itimerspec *ovalue) +{ + struct timer_obj *timer = (struct timer_obj *)timerid; + rt_uint32_t duration, current; + + if (timer == NULL || + value->it_interval.tv_nsec < 0 || + value->it_interval.tv_nsec >= NANOSECOND_PER_SECOND || + value->it_value.tv_nsec < 0 || + value->it_value.tv_nsec >= NANOSECOND_PER_SECOND) + { + rt_set_errno(EINVAL); + return -RT_ERROR; + } + + if (value == NULL || ovalue == NULL) + { + rt_set_errno(EFAULT); + return -RT_ERROR; + } + + /* Save time to expire and old reload value. */ + if (ovalue != NULL) + { + timer_gettime(timerid, ovalue); + } + + /* Stop the timer if the value is 0 */ + if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) + { + if (timer->status == ACTIVE) + { + rt_timer_stop(&timer->timer); + } + + timer->status = NOT_ACTIVE; + return RT_EOK; + } + + /* calculate timer period(tick); To avoid lost of accuracy, because "RT_TICK_PER_SECOND" maybe 100, 1000, 1024 and so on. + * + * tick nanosecond nanosecond * RT_TICK_PER_SECOND + * ------------------------- = -------------------------- ---> tick = ------------------------------------- + * RT_TICK_PER_SECOND NANOSECOND_PER_SECOND NANOSECOND_PER_SECOND + * + */ + timer->reload = (value->it_interval.tv_sec * RT_TICK_PER_SECOND) + (value->it_interval.tv_nsec * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND; + timer->interval.tv_sec = value->it_interval.tv_sec; + timer->interval.tv_nsec = value->it_interval.tv_nsec; + + if (timer->status == ACTIVE) + { + rt_timer_stop(&timer->timer); + } + + timer->status = ACTIVE; + rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, (void *)timer->reload); + rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL); + rt_timer_start(&timer->timer); + + return RT_EOK; +} +RTM_EXPORT(timer_settime); +#endif /* RT_USING_POSIX_TIMER */ + + /* timezone */ #ifndef RT_LIBC_DEFAULT_TIMEZONE #define RT_LIBC_DEFAULT_TIMEZONE 8 diff --git a/components/libc/posix-info.txt b/components/libc/posix-info.txt new file mode 100644 index 0000000000..e5cccbc89b --- /dev/null +++ b/components/libc/posix-info.txt @@ -0,0 +1,327 @@ +### The list of function support for POSIX 51 standard in the RT-Thread + + ++ isalnum() ++ isalpha() ++ isblank() ++ iscntrl() ++ isdigit() ++ isgraph() ++ islower() ++ isprint() ++ ispunct() ++ isspace() ++ isupper() ++ isxdigit() ++ tolower() ++ toupper() + + -> for gcc, keil, iar platform at the same time; + Suggest to choose ++ errno + + ++ open() + + ;the 'env' should combined with non-volatile devices ++ feclearexcept() ++ fegetenv() ++ fegetexceptflag() ++ fegetround() ++ feholdexcept() ++ feraiseexcept() ++ fesetenv() ++ fesetexceptflag() ++ fesetround() ++ fetestexcept() ++ feupdateenv() + + ++ imaxabs() ++ imaxdiv() ++ strtoimax() ++ strtoumax() + + ++ localeconv() ++ setlocale() + + ++ pthread_atfork() ++ pthread_attr_destroy() ++ pthread_attr_getdetachstate() ++ pthread_attr_getguardsize() ++ pthread_attr_getinheritsched() ++ pthread_attr_getschedparam() ++ pthread_attr_getschedpolicy() ++ pthread_attr_getscope() ++ pthread_attr_getstack() ++ pthread_attr_getstackaddr() ++ pthread_attr_getstacksize() ++ pthread_attr_init() ++ pthread_attr_setdetachstate() ++ pthread_attr_setguardsize() ++ pthread_attr_setinheritsched() ++ pthread_attr_setschedparam() ++ pthread_attr_setschedpolicy() ++ pthread_attr_setscope() ++ pthread_attr_setstack() ++ pthread_attr_setstackaddr() ++ pthread_attr_setstacksize() ++ pthread_cancel() ++ pthread_cleanup_pop() ++ pthread_cleanup_push() ++ pthread_cond_broadcast() ++ pthread_cond_destroy() ++ pthread_cond_init() ++ pthread_cond_signal() ++ pthread_cond_timedwait() ++ pthread_cond_wait() ++ pthread_condattr_destroy() ++ pthread_condattr_getclock() ++ pthread_condattr_init() ++ pthread_condattr_setclock() ++ pthread_create() ++ pthread_detach() ++ pthread_equal() ++ pthread_exit() ++ pthread_getcpuclockid() ++ pthread_getconcurrency() ++ pthread_getschedparam() ++ pthread_getspecific() ++ pthread_join() ++ pthread_key_create() ++ pthread_key_delete() ++ pthread_mutex_destroy() ++ pthread_mutex_getprioceiling() ++ pthread_mutex_init() ++ pthread_mutex_lock() ++ pthread_mutex_setprioceiling() ++ pthread_mutex_trylock() ++ pthread_mutex_unlock() ++ pthread_mutexattr_destroy() ++ pthread_mutexattr_getprioceiling() ++ pthread_mutexattr_getprotocol() ++ pthread_mutexattr_gettype() ++ pthread_mutexattr_init() ++ pthread_mutexattr_setprioceiling() ++ pthread_mutexattr_setprotocol() ++ pthread_mutexattr_settype() ++ pthread_once() ++ pthread_self() ++ pthread_setcancelstate() ++ pthread_setcanceltype() ++ pthread_setconcurrency() ++ pthread_setschedparam() ++ pthread_setschedprio() ++ pthread_setspecific() ++ pthread_testcancel() + + ++ sched_get_priority_max() ++ sched_get_priority_min() ++ sched_rr_get_interval() + + ++ sem_close() ++ sem_destroy() ++ sem_getvalue() ++ sem_init() ++ sem_open() ++ sem_post() ++ sem_timedwait() ++ sem_trywait() ++ sem_unlink() ++ sem_wait() + + ++ longjmp() ++ setjmp() + + -> for gcc, keil, iar platform at the same time; + Suggest to choose ++ kill() ++ pthread_kill() ++ pthread_sigmask() ++ raise() ++ sigaction() ++ sigaddset() ++ sigdelset() ++ sigemptyset() ++ sigfillset() ++ sigismember() ++ signal() ++ sigpending() ++ sigprocmask() +- sigqueue() ++ sigsuspend() ++ sigtimedwait() ++ sigwait() ++ sigwaitinfo() + + ++ va_arg() ++ va_copy() ++ va_end() ++ va_start() + + ++ clearerr() ++ fclose() +- fdopen() ++ feof() ++ ferror() ++ fflush() ++ fgetc() ++ fgets() +- fileno() +- flockfile() ++ fopen() ++ fprintf() ++ fputc() ++ fputs() ++ fread() ++ freopen() ++ fscanf() +- ftrylockfile() +- funlockfile() ++ fwrite() ++ getc() +% getc_unlocked() ; thread safe in the default ++ getchar() ++ getchar_unlocked() ++ gets() ++ perror() ++ printf() ++ putc() +% putc_unlocked() ; thread safe in the default ++ putchar() +% putchar_unlocked() ; thread safe in the default ++ puts() ++ scanf() ++ setbuf() ++ setvbuf() ++ snprintf() ++ sprintf() ++ sscanf() ++ stderr ++ stdin ++ stdout ++ ungetc() ++ vfprintf() ++ vfscanf() ++ vprintf() ++ vscanf() ++ vsnprintf() ++ vsprintf() ++ vsscanf() + + ++ abort() ++ abs() ++ atof() ++ atoi() ++ atol() ++ atoll() ++ bsearch() ++ calloc() ++ div() ++ free() ++ getenv() ++ labs() ++ ldiv() ++ llabs() ++ lldiv() ++ malloc() ++ qsort() ++ rand() +% rand_r() ; thread safe in the default ++ realloc() +- setenv() ;the 'env' should combined with non-volatile devices ++ srand() ++ strtod() ++ strtof() ++ strtol() ++ strtold() ++ strtoll() ++ strtoul() ++ strtoull() +- unsetenv() ;the 'env' should combined with non-volatile devices + + ++ memchr() ++ memcmp() ++ memcpy() ++ memmove() ++ memset() ++ strcat() ++ strchr() ++ strcmp() ++ strcoll() ++ strcpy() ++ strcspn() ++ strerror() +% strerror_r() ; thread safe in the default ++ strlen() ++ strncat() ++ strncmp() ++ strncpy() ++ strpbrk() ++ strrchr() ++ strspn() ++ strstr() ++ strtok() +% strtok_r() ; thread safe in the default ++ strxfrm() + + +- mlockall() ++ mmap() +- munlock() ++ munmap() +- shm_open() +- shm_unlink() + + ++ uname() + + -> for gcc, keil, iar platform at the same time; + Suggest to choose ++ asctime() ++ asctime_r() ++ clock_getres() ++ clock_gettime() ++ clock_nanosleep() ++ clock_settime() ++ ctime() ++ ctime_r() ++ difftime() ++ gmtime() ++ gmtime_r() ++ localtime() ++ localtime_r() ++ mktime() ++ nanosleep() ++ strftime() ++ time() ++ timer_create() ++ timer_delete() ++ timer_getoverrun() ++ timer_gettime() ++ timer_settime() +% tzname ; you should better use 'tz_xxx' in the rt-thread. +% tzset() ; you should better use 'tz_xxx' in the rt-thread. + + ++ alarm() ++ close() ++ environ +% fdatasync() ;smaller ranther than , in the rt-thread, it is universal ++ fsync() ++ pause() ++ read() ++ sysconf() ++ write() +- confstr() + + diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index 76dabc2734..8f527fa46d 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -49,6 +49,11 @@ config RT_USING_POSIX_CLOCK select RT_USING_POSIX_DELAY default n +config RT_USING_POSIX_TIMER + select RT_USING_TIMER_SOFT + bool "Enable posix time functions, timer_create()/timer_gettime()/timer_settime() etc" + default n + config RT_USING_PTHREADS bool "Enable pthreads APIs" select RT_USING_POSIX_CLOCK diff --git a/components/libc/posix/delay/delay.h b/components/libc/posix/delay/delay.h index 19492bdb45..eb0332e0cd 100644 --- a/components/libc/posix/delay/delay.h +++ b/components/libc/posix/delay/delay.h @@ -11,6 +11,7 @@ #ifndef __DELAY_H__ #define __DELAY_H__ +unsigned int sleep(unsigned int seconds); void msleep(unsigned int msecs); void ssleep(unsigned int seconds); void mdelay(unsigned long msecs); diff --git a/components/libc/posix/pthreads/pthread.h b/components/libc/posix/pthreads/pthread.h index ad3259d2dc..c170ec49fd 100644 --- a/components/libc/posix/pthreads/pthread.h +++ b/components/libc/posix/pthreads/pthread.h @@ -185,6 +185,10 @@ int pthread_setschedprio(pthread_t thread, int prio); void pthread_exit (void *value_ptr); int pthread_once(pthread_once_t * once_control, void (*init_routine) (void)); +#ifdef RT_USING_SIGNALS +int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); +#endif + /* pthread cleanup */ void pthread_cleanup_pop(int execute); void pthread_cleanup_push(void (*routine)(void*), void *arg); diff --git a/components/libc/posix/signal/posix_signal.c b/components/libc/posix/signal/posix_signal.c index ac8d2b1eef..c87bc6104f 100644 --- a/components/libc/posix/signal/posix_signal.c +++ b/components/libc/posix/signal/posix_signal.c @@ -55,6 +55,35 @@ int sigprocmask (int how, const sigset_t *set, sigset_t *oset) return 0; } +int sigpending (sigset_t *set) +{ + sigprocmask(SIG_SETMASK, RT_NULL, set); + return 0; +} + +int sigsuspend (const sigset_t *set) +{ + int ret = 0; + sigset_t origin_set; + sigset_t suspend_set; + siginfo_t info; /* unless paremeter */ + + /* get the origin signal information */ + sigpending(&origin_set); + + /* set the new signal information */ + sigprocmask(SIG_BLOCK, set, RT_NULL); + sigpending(&suspend_set); + + ret = rt_signal_wait(&suspend_set, &info, RT_WAITING_FOREVER); + + /* restore the original sigprocmask */ + sigprocmask(SIG_UNBLOCK, (sigset_t *)0xffffUL, RT_NULL); + sigprocmask(SIG_BLOCK, &origin_set, RT_NULL); + + return ret; +} + int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { rt_sighandler_t old = RT_NULL; @@ -75,8 +104,7 @@ int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) return 0; } -int sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec *timeout) +int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) { int ret = 0; int tick = RT_WAITING_FOREVER; @@ -114,3 +142,11 @@ int raise(int sig) return 0; } +#include +int sigqueue (pid_t pid, int signo, const union sigval value) +{ + /* no support, signal queue */ + + return -1; +} + diff --git a/include/rtdef.h b/include/rtdef.h index e9f8cb8068..66d30001a0 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -487,6 +487,7 @@ struct rt_object_information #define RT_TIMER_CTRL_SET_ONESHOT 0x2 /**< change timer to one shot */ #define RT_TIMER_CTRL_SET_PERIODIC 0x3 /**< change timer to periodic */ #define RT_TIMER_CTRL_GET_STATE 0x4 /**< get timer run state active or deactive*/ +#define RT_TIMER_CTRL_GET_REMAIN_TIME 0x5 /**< get the remaining hang time */ #ifndef RT_TIMER_SKIP_LIST_LEVEL #define RT_TIMER_SKIP_LIST_LEVEL 1 diff --git a/src/timer.c b/src/timer.c index da113298da..6ef9a4ed3f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -581,6 +581,8 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) /*timer is stop*/ *(rt_uint32_t *)arg = RT_TIMER_FLAG_DEACTIVATED; } + case RT_TIMER_CTRL_GET_REMAIN_TIME: + *(rt_tick_t *)arg = timer->timeout_tick; break; default: From 3606065803205b03f0e3f07f3791297799639dba Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 18 Jan 2022 15:10:06 -0500 Subject: [PATCH 36/65] =?UTF-8?q?[lwip]=20remove=20lwip=202.0.2=20-=20?= =?UTF-8?q?=E7=A7=BB=E9=99=A42.0.2=EF=BC=8C=E8=AF=A5=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E5=87=A0=E4=B8=AA=E9=87=8D=E8=A6=81=E7=9A=84?= =?UTF-8?q?bug=EF=BC=8C=E5=B7=B2=E7=BB=8F=E5=9C=A82.0.3=E4=B8=AD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=EF=BC=8C=E4=BD=9C=E8=80=85=E5=BC=BA=E7=83=88=E5=BB=BA?= =?UTF-8?q?=E8=AE=AE=E6=9B=B4=E6=96=B0=20-=20=E5=B0=86=E9=83=A8=E5=88=86bs?= =?UTF-8?q?p=E7=94=B12.0.2=E8=B0=83=E6=95=B4=E4=B8=BA2.0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/gd32450z-eval/.config | 9 +- bsp/gd32450z-eval/project.uvprojx | 460 +- bsp/gd32450z-eval/rtconfig.h | 2 +- bsp/imx6sx/cortex-a9/.config | 9 +- bsp/imx6sx/cortex-a9/rtconfig.h | 2 +- bsp/ls2kdev/.config | 9 +- bsp/ls2kdev/rtconfig.h | 2 +- bsp/qemu-vexpress-a9/.config | 11 +- bsp/qemu-vexpress-a9/rtconfig.h | 2 +- bsp/raspberry-pi/raspi4-32/.config | 9 +- bsp/raspberry-pi/raspi4-32/rtconfig.h | 2 +- bsp/zynqmp-r5-axu4ev/.config | 9 +- bsp/zynqmp-r5-axu4ev/rtconfig.h | 2 +- components/net/Kconfig | 5 +- components/net/lwip-2.0.2/CHANGELOG | 4276 ----------------- components/net/lwip-2.0.2/COPYING | 33 - components/net/lwip-2.0.2/FILES | 5 - components/net/lwip-2.0.2/README | 100 - components/net/lwip-2.0.2/READTEST.md | 22 - components/net/lwip-2.0.2/SConscript | 89 - components/net/lwip-2.0.2/UPGRADING | 235 - components/net/lwip-2.0.2/doc/FILES | 9 - .../net/lwip-2.0.2/doc/NO_SYS_SampleCode.c | 117 - components/net/lwip-2.0.2/doc/contrib.txt | 58 - .../net/lwip-2.0.2/doc/doxygen/generate.bat | 1 - .../net/lwip-2.0.2/doc/doxygen/generate.sh | 3 - .../net/lwip-2.0.2/doc/doxygen/lwip.Doxyfile | 2505 ---------- .../net/lwip-2.0.2/doc/doxygen/main_page.h | 132 - .../lwip-2.0.2/doc/doxygen/output/index.html | 10 - .../net/lwip-2.0.2/doc/doxygen_docs.zip | Bin 2106820 -> 0 bytes components/net/lwip-2.0.2/doc/mdns.txt | 113 - components/net/lwip-2.0.2/doc/mqtt_client.txt | 162 - components/net/lwip-2.0.2/doc/ppp.txt | 529 -- components/net/lwip-2.0.2/doc/rawapi.txt | 499 -- components/net/lwip-2.0.2/doc/savannah.txt | 120 - components/net/lwip-2.0.2/doc/sys_arch.txt | 303 -- components/net/lwip-2.0.2/src/FILES | 15 - components/net/lwip-2.0.2/src/Filelists.mk | 181 - components/net/lwip-2.0.2/src/api/api_lib.c | 1010 ---- components/net/lwip-2.0.2/src/api/api_msg.c | 1947 -------- components/net/lwip-2.0.2/src/api/err.c | 115 - components/net/lwip-2.0.2/src/api/netbuf.c | 246 - components/net/lwip-2.0.2/src/api/netdb.c | 413 -- components/net/lwip-2.0.2/src/api/netifapi.c | 221 - components/net/lwip-2.0.2/src/api/sockets.c | 2852 ----------- components/net/lwip-2.0.2/src/api/tcpip.c | 518 -- components/net/lwip-2.0.2/src/apps/README.md | 6 - components/net/lwip-2.0.2/src/apps/httpd/fs.c | 179 - .../net/lwip-2.0.2/src/apps/httpd/fs/404.html | 21 - .../lwip-2.0.2/src/apps/httpd/fs/img/sics.gif | Bin 724 -> 0 bytes .../lwip-2.0.2/src/apps/httpd/fs/index.html | 47 - .../net/lwip-2.0.2/src/apps/httpd/fsdata.c | 298 -- .../net/lwip-2.0.2/src/apps/httpd/fsdata.h | 50 - .../net/lwip-2.0.2/src/apps/httpd/httpd.c | 2629 ---------- .../lwip-2.0.2/src/apps/httpd/httpd_structs.h | 114 - .../src/apps/httpd/makefsdata/makefsdata | 97 - .../src/apps/httpd/makefsdata/makefsdata.c | 1033 ---- .../src/apps/httpd/makefsdata/readme.txt | 13 - .../net/lwip-2.0.2/src/apps/lwiperf/lwiperf.c | 661 --- .../net/lwip-2.0.2/src/apps/mdns/mdns.c | 2028 -------- .../net/lwip-2.0.2/src/apps/mqtt/mqtt.c | 1341 ------ .../lwip-2.0.2/src/apps/netbiosns/netbiosns.c | 367 -- .../net/lwip-2.0.2/src/apps/ping/ping.c | 245 - .../net/lwip-2.0.2/src/apps/snmp/snmp_asn1.c | 749 --- .../net/lwip-2.0.2/src/apps/snmp/snmp_asn1.h | 108 - .../net/lwip-2.0.2/src/apps/snmp/snmp_core.c | 1349 ------ .../lwip-2.0.2/src/apps/snmp/snmp_core_priv.h | 76 - .../net/lwip-2.0.2/src/apps/snmp/snmp_mib2.c | 116 - .../lwip-2.0.2/src/apps/snmp/snmp_mib2_icmp.c | 182 - .../src/apps/snmp/snmp_mib2_interfaces.c | 375 -- .../lwip-2.0.2/src/apps/snmp/snmp_mib2_ip.c | 743 --- .../lwip-2.0.2/src/apps/snmp/snmp_mib2_snmp.c | 227 - .../src/apps/snmp/snmp_mib2_system.c | 377 -- .../lwip-2.0.2/src/apps/snmp/snmp_mib2_tcp.c | 594 --- .../lwip-2.0.2/src/apps/snmp/snmp_mib2_udp.c | 357 -- .../net/lwip-2.0.2/src/apps/snmp/snmp_msg.c | 1668 ------- .../net/lwip-2.0.2/src/apps/snmp/snmp_msg.h | 194 - .../lwip-2.0.2/src/apps/snmp/snmp_netconn.c | 121 - .../src/apps/snmp/snmp_pbuf_stream.c | 156 - .../src/apps/snmp/snmp_pbuf_stream.h | 73 - .../net/lwip-2.0.2/src/apps/snmp/snmp_raw.c | 100 - .../lwip-2.0.2/src/apps/snmp/snmp_scalar.c | 220 - .../net/lwip-2.0.2/src/apps/snmp/snmp_table.c | 343 -- .../src/apps/snmp/snmp_threadsync.c | 219 - .../net/lwip-2.0.2/src/apps/snmp/snmp_traps.c | 445 -- .../net/lwip-2.0.2/src/apps/snmp/snmpv3.c | 136 - .../lwip-2.0.2/src/apps/snmp/snmpv3_dummy.c | 145 - .../lwip-2.0.2/src/apps/snmp/snmpv3_mbedtls.c | 331 -- .../lwip-2.0.2/src/apps/snmp/snmpv3_priv.h | 66 - .../net/lwip-2.0.2/src/apps/sntp/sntp.c | 727 --- .../net/lwip-2.0.2/src/apps/tftp/tftp_port.c | 73 - .../lwip-2.0.2/src/apps/tftp/tftp_server.c | 417 -- .../src/arch/include/arch/bpstruct.h | 35 - .../net/lwip-2.0.2/src/arch/include/arch/cc.h | 106 - .../src/arch/include/arch/epstruct.h | 35 - .../lwip-2.0.2/src/arch/include/arch/perf.h | 52 - .../src/arch/include/arch/sys_arch.h | 57 - components/net/lwip-2.0.2/src/arch/sys_arch.c | 773 --- components/net/lwip-2.0.2/src/core/def.c | 222 - components/net/lwip-2.0.2/src/core/dns.c | 1587 ------ .../net/lwip-2.0.2/src/core/inet_chksum.c | 609 --- components/net/lwip-2.0.2/src/core/init.c | 385 -- components/net/lwip-2.0.2/src/core/ip.c | 124 - .../net/lwip-2.0.2/src/core/ipv4/autoip.c | 527 -- .../net/lwip-2.0.2/src/core/ipv4/dhcp.c | 1950 -------- .../net/lwip-2.0.2/src/core/ipv4/etharp.c | 1206 ----- .../net/lwip-2.0.2/src/core/ipv4/icmp.c | 397 -- .../net/lwip-2.0.2/src/core/ipv4/igmp.c | 800 --- components/net/lwip-2.0.2/src/core/ipv4/ip4.c | 1086 ----- .../net/lwip-2.0.2/src/core/ipv4/ip4_addr.c | 331 -- .../net/lwip-2.0.2/src/core/ipv4/ip4_frag.c | 831 ---- .../net/lwip-2.0.2/src/core/ipv6/dhcp6.c | 50 - .../net/lwip-2.0.2/src/core/ipv6/ethip6.c | 118 - .../net/lwip-2.0.2/src/core/ipv6/icmp6.c | 350 -- .../net/lwip-2.0.2/src/core/ipv6/inet6.c | 53 - components/net/lwip-2.0.2/src/core/ipv6/ip6.c | 1122 ----- .../net/lwip-2.0.2/src/core/ipv6/ip6_addr.c | 292 -- .../net/lwip-2.0.2/src/core/ipv6/ip6_frag.c | 805 ---- .../net/lwip-2.0.2/src/core/ipv6/mld6.c | 588 --- components/net/lwip-2.0.2/src/core/ipv6/nd6.c | 2102 -------- components/net/lwip-2.0.2/src/core/mem.c | 777 --- components/net/lwip-2.0.2/src/core/memp.c | 496 -- components/net/lwip-2.0.2/src/core/netif.c | 1316 ----- components/net/lwip-2.0.2/src/core/pbuf.c | 1442 ------ components/net/lwip-2.0.2/src/core/raw.c | 521 -- components/net/lwip-2.0.2/src/core/stats.c | 169 - components/net/lwip-2.0.2/src/core/sys.c | 106 - components/net/lwip-2.0.2/src/core/tcp.c | 2164 --------- components/net/lwip-2.0.2/src/core/tcp_in.c | 1818 ------- components/net/lwip-2.0.2/src/core/tcp_out.c | 1671 ------- components/net/lwip-2.0.2/src/core/timeouts.c | 433 -- components/net/lwip-2.0.2/src/core/udp.c | 1191 ----- .../net/lwip-2.0.2/src/include/lwip/api.h | 400 -- .../lwip-2.0.2/src/include/lwip/apps/FILES | 2 - .../net/lwip-2.0.2/src/include/lwip/apps/fs.h | 103 - .../lwip-2.0.2/src/include/lwip/apps/httpd.h | 236 - .../src/include/lwip/apps/httpd_opts.h | 323 -- .../src/include/lwip/apps/lwiperf.h | 84 - .../lwip-2.0.2/src/include/lwip/apps/mdns.h | 69 - .../src/include/lwip/apps/mdns_opts.h | 74 - .../src/include/lwip/apps/mdns_priv.h | 66 - .../lwip-2.0.2/src/include/lwip/apps/mqtt.h | 244 - .../src/include/lwip/apps/mqtt_opts.h | 103 - .../src/include/lwip/apps/netbiosns.h | 43 - .../src/include/lwip/apps/netbiosns_opts.h | 59 - .../lwip-2.0.2/src/include/lwip/apps/snmp.h | 128 - .../src/include/lwip/apps/snmp_core.h | 364 -- .../src/include/lwip/apps/snmp_mib2.h | 78 - .../src/include/lwip/apps/snmp_opts.h | 293 -- .../src/include/lwip/apps/snmp_scalar.h | 113 - .../src/include/lwip/apps/snmp_table.h | 134 - .../src/include/lwip/apps/snmp_threadsync.h | 114 - .../lwip-2.0.2/src/include/lwip/apps/snmpv3.h | 90 - .../lwip-2.0.2/src/include/lwip/apps/sntp.h | 76 - .../src/include/lwip/apps/sntp_opts.h | 173 - .../src/include/lwip/apps/tftp_opts.h | 105 - .../src/include/lwip/apps/tftp_server.h | 94 - .../net/lwip-2.0.2/src/include/lwip/arch.h | 320 -- .../net/lwip-2.0.2/src/include/lwip/autoip.h | 99 - .../net/lwip-2.0.2/src/include/lwip/debug.h | 167 - .../net/lwip-2.0.2/src/include/lwip/def.h | 142 - .../net/lwip-2.0.2/src/include/lwip/dhcp.h | 143 - .../net/lwip-2.0.2/src/include/lwip/dhcp6.h | 58 - .../net/lwip-2.0.2/src/include/lwip/dns.h | 130 - .../net/lwip-2.0.2/src/include/lwip/err.h | 119 - .../net/lwip-2.0.2/src/include/lwip/errno.h | 193 - .../net/lwip-2.0.2/src/include/lwip/etharp.h | 106 - .../net/lwip-2.0.2/src/include/lwip/ethip6.h | 68 - .../net/lwip-2.0.2/src/include/lwip/icmp.h | 110 - .../net/lwip-2.0.2/src/include/lwip/icmp6.h | 70 - .../net/lwip-2.0.2/src/include/lwip/igmp.h | 115 - .../net/lwip-2.0.2/src/include/lwip/inet.h | 172 - .../lwip-2.0.2/src/include/lwip/inet_chksum.h | 105 - .../net/lwip-2.0.2/src/include/lwip/init.h | 100 - .../net/lwip-2.0.2/src/include/lwip/ip.h | 319 -- .../net/lwip-2.0.2/src/include/lwip/ip4.h | 111 - .../lwip-2.0.2/src/include/lwip/ip4_addr.h | 227 - .../lwip-2.0.2/src/include/lwip/ip4_frag.h | 100 - .../net/lwip-2.0.2/src/include/lwip/ip6.h | 93 - .../lwip-2.0.2/src/include/lwip/ip6_addr.h | 285 -- .../lwip-2.0.2/src/include/lwip/ip6_frag.h | 120 - .../net/lwip-2.0.2/src/include/lwip/ip_addr.h | 407 -- .../net/lwip-2.0.2/src/include/lwip/mem.h | 82 - .../net/lwip-2.0.2/src/include/lwip/memp.h | 153 - .../net/lwip-2.0.2/src/include/lwip/mld6.h | 99 - .../net/lwip-2.0.2/src/include/lwip/nd6.h | 84 - .../net/lwip-2.0.2/src/include/lwip/netbuf.h | 118 - .../net/lwip-2.0.2/src/include/lwip/netdb.h | 150 - .../net/lwip-2.0.2/src/include/lwip/netif.h | 474 -- .../lwip-2.0.2/src/include/lwip/netifapi.h | 140 - .../net/lwip-2.0.2/src/include/lwip/opt.h | 2876 ----------- .../net/lwip-2.0.2/src/include/lwip/pbuf.h | 263 - .../src/include/lwip/priv/api_msg.h | 216 - .../src/include/lwip/priv/memp_priv.h | 183 - .../src/include/lwip/priv/memp_std.h | 146 - .../src/include/lwip/priv/nd6_priv.h | 144 - .../src/include/lwip/priv/tcp_priv.h | 507 -- .../src/include/lwip/priv/tcpip_priv.h | 160 - .../lwip-2.0.2/src/include/lwip/prot/autoip.h | 78 - .../lwip-2.0.2/src/include/lwip/prot/dhcp.h | 183 - .../lwip-2.0.2/src/include/lwip/prot/dns.h | 140 - .../lwip-2.0.2/src/include/lwip/prot/etharp.h | 91 - .../src/include/lwip/prot/ethernet.h | 172 - .../lwip-2.0.2/src/include/lwip/prot/icmp.h | 91 - .../lwip-2.0.2/src/include/lwip/prot/icmp6.h | 170 - .../lwip-2.0.2/src/include/lwip/prot/igmp.h | 90 - .../net/lwip-2.0.2/src/include/lwip/prot/ip.h | 51 - .../lwip-2.0.2/src/include/lwip/prot/ip4.h | 127 - .../lwip-2.0.2/src/include/lwip/prot/ip6.h | 169 - .../lwip-2.0.2/src/include/lwip/prot/mld6.h | 70 - .../lwip-2.0.2/src/include/lwip/prot/nd6.h | 277 -- .../lwip-2.0.2/src/include/lwip/prot/tcp.h | 97 - .../lwip-2.0.2/src/include/lwip/prot/udp.h | 68 - .../net/lwip-2.0.2/src/include/lwip/raw.h | 118 - .../net/lwip-2.0.2/src/include/lwip/sio.h | 142 - .../net/lwip-2.0.2/src/include/lwip/snmp.h | 213 - .../net/lwip-2.0.2/src/include/lwip/sockets.h | 593 --- .../net/lwip-2.0.2/src/include/lwip/stats.h | 491 -- .../net/lwip-2.0.2/src/include/lwip/sys.h | 455 -- .../net/lwip-2.0.2/src/include/lwip/tcp.h | 433 -- .../net/lwip-2.0.2/src/include/lwip/tcpip.h | 106 - .../lwip-2.0.2/src/include/lwip/timeouts.h | 121 - .../net/lwip-2.0.2/src/include/lwip/udp.h | 182 - .../net/lwip-2.0.2/src/include/netif/etharp.h | 3 - .../lwip-2.0.2/src/include/netif/ethernet.h | 77 - .../lwip-2.0.2/src/include/netif/ethernetif.h | 53 - .../lwip-2.0.2/src/include/netif/lowpan6.h | 86 - .../src/include/netif/lowpan6_opts.h | 70 - .../lwip-2.0.2/src/include/netif/ppp/ccp.h | 156 - .../src/include/netif/ppp/chap-md5.h | 36 - .../src/include/netif/ppp/chap-new.h | 192 - .../src/include/netif/ppp/chap_ms.h | 44 - .../lwip-2.0.2/src/include/netif/ppp/eap.h | 169 - .../lwip-2.0.2/src/include/netif/ppp/ecp.h | 50 - .../lwip-2.0.2/src/include/netif/ppp/eui64.h | 94 - .../lwip-2.0.2/src/include/netif/ppp/fsm.h | 175 - .../lwip-2.0.2/src/include/netif/ppp/ipcp.h | 126 - .../lwip-2.0.2/src/include/netif/ppp/ipv6cp.h | 183 - .../lwip-2.0.2/src/include/netif/ppp/lcp.h | 171 - .../lwip-2.0.2/src/include/netif/ppp/magic.h | 122 - .../lwip-2.0.2/src/include/netif/ppp/mppe.h | 173 - .../src/include/netif/ppp/polarssl/arc4.h | 81 - .../src/include/netif/ppp/polarssl/des.h | 92 - .../src/include/netif/ppp/polarssl/md4.h | 97 - .../src/include/netif/ppp/polarssl/md5.h | 96 - .../src/include/netif/ppp/polarssl/sha1.h | 96 - .../lwip-2.0.2/src/include/netif/ppp/ppp.h | 690 --- .../src/include/netif/ppp/ppp_impl.h | 629 --- .../src/include/netif/ppp/ppp_opts.h | 593 --- .../lwip-2.0.2/src/include/netif/ppp/pppapi.h | 137 - .../src/include/netif/ppp/pppcrypt.h | 136 - .../src/include/netif/ppp/pppdebug.h | 80 - .../lwip-2.0.2/src/include/netif/ppp/pppoe.h | 179 - .../src/include/netif/ppp/pppol2tp.h | 201 - .../lwip-2.0.2/src/include/netif/ppp/pppos.h | 118 - .../lwip-2.0.2/src/include/netif/ppp/upap.h | 123 - .../net/lwip-2.0.2/src/include/netif/ppp/vj.h | 161 - .../net/lwip-2.0.2/src/include/netif/slipif.h | 87 - .../net/lwip-2.0.2/src/include/posix/netdb.h | 33 - .../lwip-2.0.2/src/include/posix/sys/socket.h | 33 - components/net/lwip-2.0.2/src/lwipopts.h | 637 --- components/net/lwip-2.0.2/src/lwippools.h | 10 - components/net/lwip-2.0.2/src/netif/FILES | 24 - .../net/lwip-2.0.2/src/netif/ethernet.c | 314 -- .../net/lwip-2.0.2/src/netif/ethernetif.c | 1022 ---- components/net/lwip-2.0.2/src/netif/lowpan6.c | 1193 ----- .../lwip-2.0.2/src/netif/ppp/PPPD_FOLLOWUP | 473 -- .../net/lwip-2.0.2/src/netif/ppp/auth.c | 2510 ---------- components/net/lwip-2.0.2/src/netif/ppp/ccp.c | 1740 ------- .../net/lwip-2.0.2/src/netif/ppp/chap-md5.c | 126 - .../net/lwip-2.0.2/src/netif/ppp/chap-new.c | 677 --- .../net/lwip-2.0.2/src/netif/ppp/chap_ms.c | 962 ---- .../net/lwip-2.0.2/src/netif/ppp/demand.c | 465 -- components/net/lwip-2.0.2/src/netif/ppp/eap.c | 2423 ---------- components/net/lwip-2.0.2/src/netif/ppp/ecp.c | 191 - .../net/lwip-2.0.2/src/netif/ppp/eui64.c | 56 - components/net/lwip-2.0.2/src/netif/ppp/fsm.c | 799 --- .../net/lwip-2.0.2/src/netif/ppp/ipcp.c | 2418 ---------- .../net/lwip-2.0.2/src/netif/ppp/ipv6cp.c | 1533 ------ components/net/lwip-2.0.2/src/netif/ppp/lcp.c | 2790 ----------- .../net/lwip-2.0.2/src/netif/ppp/magic.c | 294 -- .../net/lwip-2.0.2/src/netif/ppp/mppe.c | 412 -- .../net/lwip-2.0.2/src/netif/ppp/multilink.c | 609 --- .../lwip-2.0.2/src/netif/ppp/polarssl/README | 22 - .../lwip-2.0.2/src/netif/ppp/polarssl/arc4.c | 101 - .../lwip-2.0.2/src/netif/ppp/polarssl/des.c | 422 -- .../lwip-2.0.2/src/netif/ppp/polarssl/md4.c | 281 -- .../lwip-2.0.2/src/netif/ppp/polarssl/md5.c | 300 -- .../lwip-2.0.2/src/netif/ppp/polarssl/sha1.c | 335 -- components/net/lwip-2.0.2/src/netif/ppp/ppp.c | 1647 ------- .../net/lwip-2.0.2/src/netif/ppp/pppapi.c | 427 -- .../net/lwip-2.0.2/src/netif/ppp/pppcrypt.c | 66 - .../net/lwip-2.0.2/src/netif/ppp/pppoe.c | 1191 ----- .../net/lwip-2.0.2/src/netif/ppp/pppol2tp.c | 1131 ----- .../net/lwip-2.0.2/src/netif/ppp/pppos.c | 875 ---- .../net/lwip-2.0.2/src/netif/ppp/upap.c | 677 --- .../net/lwip-2.0.2/src/netif/ppp/utils.c | 959 ---- components/net/lwip-2.0.2/src/netif/ppp/vj.c | 695 --- components/net/lwip-2.0.2/src/netif/slipif.c | 555 --- components/net/lwip-2.0.2/test/fuzz/Makefile | 53 - components/net/lwip-2.0.2/test/fuzz/README | 34 - components/net/lwip-2.0.2/test/fuzz/config.h | 0 components/net/lwip-2.0.2/test/fuzz/fuzz.c | 136 - .../net/lwip-2.0.2/test/fuzz/lwipopts.h | 68 - .../lwip-2.0.2/test/fuzz/output_to_pcap.sh | 31 - .../net/lwip-2.0.2/test/unit/core/test_mem.c | 121 - .../net/lwip-2.0.2/test/unit/core/test_mem.h | 8 - .../net/lwip-2.0.2/test/unit/core/test_pbuf.c | 239 - .../net/lwip-2.0.2/test/unit/core/test_pbuf.h | 8 - .../net/lwip-2.0.2/test/unit/dhcp/test_dhcp.c | 1024 ---- .../net/lwip-2.0.2/test/unit/dhcp/test_dhcp.h | 8 - .../lwip-2.0.2/test/unit/etharp/test_etharp.c | 269 -- .../lwip-2.0.2/test/unit/etharp/test_etharp.h | 8 - .../net/lwip-2.0.2/test/unit/lwip_check.h | 37 - .../net/lwip-2.0.2/test/unit/lwip_unittests.c | 70 - .../net/lwip-2.0.2/test/unit/lwipopts.h | 62 - .../net/lwip-2.0.2/test/unit/mdns/test_mdns.c | 915 ---- .../net/lwip-2.0.2/test/unit/mdns/test_mdns.h | 8 - .../net/lwip-2.0.2/test/unit/tcp/tcp_helper.c | 314 -- .../net/lwip-2.0.2/test/unit/tcp/tcp_helper.h | 52 - .../net/lwip-2.0.2/test/unit/tcp/test_tcp.c | 744 --- .../net/lwip-2.0.2/test/unit/tcp/test_tcp.h | 8 - .../lwip-2.0.2/test/unit/tcp/test_tcp_oos.c | 1049 ---- .../lwip-2.0.2/test/unit/tcp/test_tcp_oos.h | 8 - .../net/lwip-2.0.2/test/unit/udp/test_udp.c | 68 - .../net/lwip-2.0.2/test/unit/udp/test_udp.h | 8 - 326 files changed, 274 insertions(+), 125935 deletions(-) delete mode 100644 components/net/lwip-2.0.2/CHANGELOG delete mode 100644 components/net/lwip-2.0.2/COPYING delete mode 100644 components/net/lwip-2.0.2/FILES delete mode 100644 components/net/lwip-2.0.2/README delete mode 100644 components/net/lwip-2.0.2/READTEST.md delete mode 100644 components/net/lwip-2.0.2/SConscript delete mode 100644 components/net/lwip-2.0.2/UPGRADING delete mode 100644 components/net/lwip-2.0.2/doc/FILES delete mode 100644 components/net/lwip-2.0.2/doc/NO_SYS_SampleCode.c delete mode 100644 components/net/lwip-2.0.2/doc/contrib.txt delete mode 100644 components/net/lwip-2.0.2/doc/doxygen/generate.bat delete mode 100644 components/net/lwip-2.0.2/doc/doxygen/generate.sh delete mode 100644 components/net/lwip-2.0.2/doc/doxygen/lwip.Doxyfile delete mode 100644 components/net/lwip-2.0.2/doc/doxygen/main_page.h delete mode 100644 components/net/lwip-2.0.2/doc/doxygen/output/index.html delete mode 100644 components/net/lwip-2.0.2/doc/doxygen_docs.zip delete mode 100644 components/net/lwip-2.0.2/doc/mdns.txt delete mode 100644 components/net/lwip-2.0.2/doc/mqtt_client.txt delete mode 100644 components/net/lwip-2.0.2/doc/ppp.txt delete mode 100644 components/net/lwip-2.0.2/doc/rawapi.txt delete mode 100644 components/net/lwip-2.0.2/doc/savannah.txt delete mode 100644 components/net/lwip-2.0.2/doc/sys_arch.txt delete mode 100644 components/net/lwip-2.0.2/src/FILES delete mode 100644 components/net/lwip-2.0.2/src/Filelists.mk delete mode 100644 components/net/lwip-2.0.2/src/api/api_lib.c delete mode 100644 components/net/lwip-2.0.2/src/api/api_msg.c delete mode 100644 components/net/lwip-2.0.2/src/api/err.c delete mode 100644 components/net/lwip-2.0.2/src/api/netbuf.c delete mode 100644 components/net/lwip-2.0.2/src/api/netdb.c delete mode 100644 components/net/lwip-2.0.2/src/api/netifapi.c delete mode 100644 components/net/lwip-2.0.2/src/api/sockets.c delete mode 100644 components/net/lwip-2.0.2/src/api/tcpip.c delete mode 100644 components/net/lwip-2.0.2/src/apps/README.md delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/fs.c delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/fs/404.html delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/fs/img/sics.gif delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/fs/index.html delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/fsdata.c delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/fsdata.h delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/httpd.c delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/httpd_structs.h delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata.c delete mode 100644 components/net/lwip-2.0.2/src/apps/httpd/makefsdata/readme.txt delete mode 100644 components/net/lwip-2.0.2/src/apps/lwiperf/lwiperf.c delete mode 100644 components/net/lwip-2.0.2/src/apps/mdns/mdns.c delete mode 100644 components/net/lwip-2.0.2/src/apps/mqtt/mqtt.c delete mode 100644 components/net/lwip-2.0.2/src/apps/netbiosns/netbiosns.c delete mode 100644 components/net/lwip-2.0.2/src/apps/ping/ping.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.h delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_core.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_core_priv.h delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_icmp.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_interfaces.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_ip.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_snmp.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_system.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_tcp.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_udp.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.h delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_netconn.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.h delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_raw.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_scalar.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_table.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_threadsync.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmp_traps.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmpv3.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmpv3_dummy.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmpv3_mbedtls.c delete mode 100644 components/net/lwip-2.0.2/src/apps/snmp/snmpv3_priv.h delete mode 100644 components/net/lwip-2.0.2/src/apps/sntp/sntp.c delete mode 100644 components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c delete mode 100644 components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c delete mode 100644 components/net/lwip-2.0.2/src/arch/include/arch/bpstruct.h delete mode 100644 components/net/lwip-2.0.2/src/arch/include/arch/cc.h delete mode 100644 components/net/lwip-2.0.2/src/arch/include/arch/epstruct.h delete mode 100644 components/net/lwip-2.0.2/src/arch/include/arch/perf.h delete mode 100644 components/net/lwip-2.0.2/src/arch/include/arch/sys_arch.h delete mode 100644 components/net/lwip-2.0.2/src/arch/sys_arch.c delete mode 100644 components/net/lwip-2.0.2/src/core/def.c delete mode 100644 components/net/lwip-2.0.2/src/core/dns.c delete mode 100644 components/net/lwip-2.0.2/src/core/inet_chksum.c delete mode 100644 components/net/lwip-2.0.2/src/core/init.c delete mode 100644 components/net/lwip-2.0.2/src/core/ip.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/autoip.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/dhcp.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/etharp.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/icmp.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/igmp.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/ip4.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/ip4_addr.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv4/ip4_frag.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/dhcp6.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/ethip6.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/icmp6.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/inet6.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/ip6.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/ip6_addr.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/ip6_frag.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/mld6.c delete mode 100644 components/net/lwip-2.0.2/src/core/ipv6/nd6.c delete mode 100644 components/net/lwip-2.0.2/src/core/mem.c delete mode 100644 components/net/lwip-2.0.2/src/core/memp.c delete mode 100644 components/net/lwip-2.0.2/src/core/netif.c delete mode 100644 components/net/lwip-2.0.2/src/core/pbuf.c delete mode 100644 components/net/lwip-2.0.2/src/core/raw.c delete mode 100644 components/net/lwip-2.0.2/src/core/stats.c delete mode 100644 components/net/lwip-2.0.2/src/core/sys.c delete mode 100644 components/net/lwip-2.0.2/src/core/tcp.c delete mode 100644 components/net/lwip-2.0.2/src/core/tcp_in.c delete mode 100644 components/net/lwip-2.0.2/src/core/tcp_out.c delete mode 100644 components/net/lwip-2.0.2/src/core/timeouts.c delete mode 100644 components/net/lwip-2.0.2/src/core/udp.c delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/api.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/FILES delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/fs.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/httpd.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/httpd_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/lwiperf.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/mdns.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/mdns_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/mdns_priv.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/mqtt.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/mqtt_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp_core.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp_mib2.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp_scalar.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp_table.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmp_threadsync.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/snmpv3.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/sntp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/sntp_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/tftp_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/apps/tftp_server.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/arch.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/autoip.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/debug.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/def.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/dhcp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/dhcp6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/dns.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/err.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/errno.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/etharp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ethip6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/icmp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/icmp6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/igmp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/inet.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/inet_chksum.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/init.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip4.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip4_addr.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip4_frag.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip6_addr.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip6_frag.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/ip_addr.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/mem.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/memp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/mld6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/nd6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/netbuf.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/netdb.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/netif.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/netifapi.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/opt.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/pbuf.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/priv/api_msg.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/priv/memp_priv.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/priv/memp_std.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/priv/nd6_priv.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/priv/tcp_priv.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/priv/tcpip_priv.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/autoip.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/dhcp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/dns.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/etharp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/ethernet.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/icmp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/icmp6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/igmp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/ip.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/ip4.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/ip6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/mld6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/nd6.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/tcp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/prot/udp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/raw.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/sio.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/snmp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/sockets.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/stats.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/sys.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/tcp.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/tcpip.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/timeouts.h delete mode 100644 components/net/lwip-2.0.2/src/include/lwip/udp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/etharp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ethernet.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ethernetif.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/lowpan6.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/lowpan6_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ccp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/chap-md5.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/chap-new.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/chap_ms.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/eap.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ecp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/eui64.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/fsm.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ipcp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ipv6cp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/lcp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/magic.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/mppe.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/arc4.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/des.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md4.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md5.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/sha1.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ppp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ppp_impl.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/ppp_opts.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/pppapi.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/pppcrypt.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/pppdebug.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/pppoe.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/pppol2tp.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/pppos.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/upap.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/ppp/vj.h delete mode 100644 components/net/lwip-2.0.2/src/include/netif/slipif.h delete mode 100644 components/net/lwip-2.0.2/src/include/posix/netdb.h delete mode 100644 components/net/lwip-2.0.2/src/include/posix/sys/socket.h delete mode 100644 components/net/lwip-2.0.2/src/lwipopts.h delete mode 100644 components/net/lwip-2.0.2/src/lwippools.h delete mode 100644 components/net/lwip-2.0.2/src/netif/FILES delete mode 100644 components/net/lwip-2.0.2/src/netif/ethernet.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ethernetif.c delete mode 100644 components/net/lwip-2.0.2/src/netif/lowpan6.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/PPPD_FOLLOWUP delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/auth.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/ccp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/chap-md5.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/chap-new.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/chap_ms.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/demand.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/eap.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/ecp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/eui64.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/fsm.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/ipcp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/ipv6cp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/lcp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/magic.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/mppe.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/multilink.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/polarssl/README delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/polarssl/arc4.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/polarssl/des.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/polarssl/md4.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/polarssl/md5.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/polarssl/sha1.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/ppp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/pppapi.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/pppcrypt.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/pppoe.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/pppol2tp.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/pppos.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/upap.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/utils.c delete mode 100644 components/net/lwip-2.0.2/src/netif/ppp/vj.c delete mode 100644 components/net/lwip-2.0.2/src/netif/slipif.c delete mode 100644 components/net/lwip-2.0.2/test/fuzz/Makefile delete mode 100644 components/net/lwip-2.0.2/test/fuzz/README delete mode 100644 components/net/lwip-2.0.2/test/fuzz/config.h delete mode 100644 components/net/lwip-2.0.2/test/fuzz/fuzz.c delete mode 100644 components/net/lwip-2.0.2/test/fuzz/lwipopts.h delete mode 100644 components/net/lwip-2.0.2/test/fuzz/output_to_pcap.sh delete mode 100644 components/net/lwip-2.0.2/test/unit/core/test_mem.c delete mode 100644 components/net/lwip-2.0.2/test/unit/core/test_mem.h delete mode 100644 components/net/lwip-2.0.2/test/unit/core/test_pbuf.c delete mode 100644 components/net/lwip-2.0.2/test/unit/core/test_pbuf.h delete mode 100644 components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.c delete mode 100644 components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.h delete mode 100644 components/net/lwip-2.0.2/test/unit/etharp/test_etharp.c delete mode 100644 components/net/lwip-2.0.2/test/unit/etharp/test_etharp.h delete mode 100644 components/net/lwip-2.0.2/test/unit/lwip_check.h delete mode 100644 components/net/lwip-2.0.2/test/unit/lwip_unittests.c delete mode 100644 components/net/lwip-2.0.2/test/unit/lwipopts.h delete mode 100644 components/net/lwip-2.0.2/test/unit/mdns/test_mdns.c delete mode 100644 components/net/lwip-2.0.2/test/unit/mdns/test_mdns.h delete mode 100644 components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.c delete mode 100644 components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.h delete mode 100644 components/net/lwip-2.0.2/test/unit/tcp/test_tcp.c delete mode 100644 components/net/lwip-2.0.2/test/unit/tcp/test_tcp.h delete mode 100644 components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.c delete mode 100644 components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.h delete mode 100644 components/net/lwip-2.0.2/test/unit/udp/test_udp.c delete mode 100644 components/net/lwip-2.0.2/test/unit/udp/test_udp.h diff --git a/bsp/gd32450z-eval/.config b/bsp/gd32450z-eval/.config index 5102985dc4..1869a867eb 100644 --- a/bsp/gd32450z-eval/.config +++ b/bsp/gd32450z-eval/.config @@ -263,8 +263,7 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 @@ -495,6 +494,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -505,7 +505,6 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -556,6 +555,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -667,6 +667,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -754,6 +755,8 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set CONFIG_SOC_GD32450Z=y CONFIG_BSP_USING_SDRAM=y CONFIG_BSP_USING_UART0=y diff --git a/bsp/gd32450z-eval/project.uvprojx b/bsp/gd32450z-eval/project.uvprojx index 1fb3e8e5f0..592fc6bd8d 100644 --- a/bsp/gd32450z-eval/project.uvprojx +++ b/bsp/gd32450z-eval/project.uvprojx @@ -333,7 +333,7 @@ USE_STDPERIPH_DRIVER, __RTTHREAD__, RT_USING_ARM_LIBC, __CLK_TCK=RT_TICK_PER_SECOND - applications;.;..\..\components\libc\compilers\common;..\..\components\libc\compilers\common\nogcc;..\..\libcpu\arm\common;..\..\libcpu\arm\cortex-m4;..\..\components\drivers\include;..\..\components\drivers\include;..\..\components\drivers\include;drivers;..\..\components\dfs\include;..\..\components\dfs\filesystems\devfs;..\..\components\dfs\filesystems\elmfat;..\..\components\finsh;.;..\..\include;Libraries\CMSIS\GD\GD32F4xx\Include;Libraries\CMSIS;Libraries\GD32F4xx_standard_peripheral\Include;..\..\components\net\lwip-2.0.2\src;..\..\components\net\lwip-2.0.2\src\include;..\..\components\net\lwip-2.0.2\src\include\ipv4;..\..\components\net\lwip-2.0.2\src\arch\include;..\..\components\net\lwip-2.0.2\src\include\netif;..\..\components\libc\posix\io;..\..\components\libc\posix\io\poll;..\..\components\libc\posix\ipc;..\..\components\net\netdev\include;..\..\components\net\sal_socket\include;..\..\components\net\sal_socket\include\socket;..\..\components\net\sal_socket\impl;..\..\components\net\sal_socket\include\dfs_net;..\..\components\net\sal_socket\include\socket\sys_socket;..\..\examples\utest\testcases\kernel + applications;.;..\..\components\libc\compilers\common;..\..\components\libc\compilers\common\extension;..\..\libcpu\arm\common;..\..\libcpu\arm\cortex-m4;..\..\components\drivers\include;..\..\components\drivers\include;..\..\components\drivers\include;drivers;..\..\components\dfs\include;..\..\components\dfs\filesystems\devfs;..\..\components\dfs\filesystems\elmfat;..\..\components\finsh;.;..\..\include;Libraries\CMSIS\GD\GD32F4xx\Include;Libraries\CMSIS;Libraries\GD32F4xx_standard_peripheral\Include;..\..\components\net\lwip-2.0.3\src;..\..\components\net\lwip-2.0.3\src\include;..\..\components\net\lwip-2.0.3\src\include\ipv4;..\..\components\net\lwip-2.0.3\src\arch\include;..\..\components\net\lwip-2.0.3\src\include\netif;..\..\components\libc\posix\io;..\..\components\libc\posix\io\poll;..\..\components\libc\posix\ipc;..\..\components\net\netdev\include;..\..\components\net\sal_socket\include;..\..\components\net\sal_socket\include\socket;..\..\components\net\sal_socket\impl;..\..\components\net\sal_socket\include\dfs_net;..\..\components\net\sal_socket\include\socket\sys_socket;..\..\examples\utest\testcases\kernel @@ -386,13 +386,6 @@ Compiler - - - libc_syms.c - 1 - ..\..\components\libc\compilers\armlibc\libc_syms.c - - syscalls.c @@ -407,6 +400,13 @@ ..\..\components\libc\compilers\armlibc\syscall_mem.c + + + libc_syms.c + 1 + ..\..\components\libc\compilers\armlibc\libc_syms.c + + stdlib.c @@ -478,9 +478,9 @@ - dataqueue.c + completion.c 1 - ..\..\components\drivers\src\dataqueue.c + ..\..\components\drivers\src\completion.c @@ -492,9 +492,16 @@ - workqueue.c + ringbuffer.c 1 - ..\..\components\drivers\src\workqueue.c + ..\..\components\drivers\src\ringbuffer.c + + + + + dataqueue.c + 1 + ..\..\components\drivers\src\dataqueue.c @@ -504,13 +511,6 @@ ..\..\components\drivers\src\ringblk_buf.c - - - completion.c - 1 - ..\..\components\drivers\src\completion.c - - waitqueue.c @@ -520,9 +520,9 @@ - ringbuffer.c + workqueue.c 1 - ..\..\components\drivers\src\ringbuffer.c + ..\..\components\drivers\src\workqueue.c @@ -601,6 +601,13 @@ ..\..\components\dfs\filesystems\devfs\devfs.c + + + ffunicode.c + 1 + ..\..\components\dfs\filesystems\elmfat\ffunicode.c + + dfs_elm.c @@ -615,13 +622,6 @@ ..\..\components\dfs\filesystems\elmfat\ff.c - - - ffunicode.c - 1 - ..\..\components\dfs\filesystems\elmfat\ffunicode.c - - Finsh @@ -656,6 +656,13 @@ Kernel + + + idle.c + 1 + ..\..\src\idle.c + + ipc.c @@ -663,6 +670,55 @@ ..\..\src\ipc.c + + + components.c + 1 + ..\..\src\components.c + + + + + timer.c + 1 + ..\..\src\timer.c + + + + + mem.c + 1 + ..\..\src\mem.c + + + + + irq.c + 1 + ..\..\src\irq.c + + + + + scheduler.c + 1 + ..\..\src\scheduler.c + + + + + object.c + 1 + ..\..\src\object.c + + + + + mempool.c + 1 + ..\..\src\mempool.c + + thread.c @@ -677,20 +733,6 @@ ..\..\src\kservice.c - - - clock.c - 1 - ..\..\src\clock.c - - - - - object.c - 1 - ..\..\src\object.c - - device.c @@ -700,51 +742,9 @@ - timer.c + clock.c 1 - ..\..\src\timer.c - - - - - scheduler.c - 1 - ..\..\src\scheduler.c - - - - - mempool.c - 1 - ..\..\src\mempool.c - - - - - mem.c - 1 - ..\..\src\mem.c - - - - - components.c - 1 - ..\..\src\components.c - - - - - idle.c - 1 - ..\..\src\idle.c - - - - - irq.c - 1 - ..\..\src\irq.c + ..\..\src\clock.c @@ -752,37 +752,37 @@ Libraries - gd32f4xx_dma.c + gd32f4xx_adc.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dma.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_adc.c - gd32f4xx_spi.c + gd32f4xx_wwdgt.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_spi.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_wwdgt.c - gd32f4xx_exti.c + gd32f4xx_usart.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c - gd32f4xx_rcu.c + gd32f4xx_dac.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dac.c - gd32f4xx_enet.c + gd32f4xx_i2c.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_enet.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c @@ -801,23 +801,23 @@ - gd32f4xx_i2c.c + gd32f4xx_timer.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_i2c.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_timer.c - gd32f4xx_gpio.c + gd32f4xx_sdio.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_sdio.c - gd32f4xx_dac.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dac.c + startup_gd32f4xx.s + 2 + Libraries\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s @@ -836,86 +836,23 @@ - gd32f4xx_sdio.c + gd32f4xx_gpio.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_sdio.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_gpio.c - gd32f4xx_dci.c + gd32f4xx_exti.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dci.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_exti.c - gd32f4xx_iref.c + gd32f4xx_rcu.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_iref.c - - - - - system_gd32f4xx.c - 1 - Libraries\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c - - - - - gd32f4xx_usart.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_usart.c - - - - - gd32f4xx_dbg.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dbg.c - - - - - gd32f4xx_syscfg.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c - - - - - startup_gd32f4xx.s - 2 - Libraries\CMSIS\GD\GD32F4xx\Source\ARM\startup_gd32f4xx.s - - - - - gd32f4xx_fmc.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_fmc.c - - - - - gd32f4xx_pmu.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_pmu.c - - - - - gd32f4xx_wwdgt.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_wwdgt.c - - - - - gd32f4xx_ctc.c - 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_ctc.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_rcu.c @@ -927,16 +864,16 @@ - gd32f4xx_ipa.c + gd32f4xx_spi.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_ipa.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_spi.c - gd32f4xx_adc.c + gd32f4xx_ctc.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_adc.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_ctc.c @@ -948,9 +885,44 @@ - gd32f4xx_timer.c + gd32f4xx_enet.c 1 - Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_timer.c + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_enet.c + + + + + system_gd32f4xx.c + 1 + Libraries\CMSIS\GD\GD32F4xx\Source\system_gd32f4xx.c + + + + + gd32f4xx_fmc.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_fmc.c + + + + + gd32f4xx_iref.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_iref.c + + + + + gd32f4xx_dbg.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dbg.c + + + + + gd32f4xx_pmu.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_pmu.c @@ -960,6 +932,34 @@ Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_can.c + + + gd32f4xx_ipa.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_ipa.c + + + + + gd32f4xx_syscfg.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_syscfg.c + + + + + gd32f4xx_dci.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dci.c + + + + + gd32f4xx_dma.c + 1 + Libraries\GD32F4xx_standard_peripheral\Source\gd32f4xx_dma.c + + gd32f4xx_fwdgt.c @@ -970,263 +970,263 @@ lwIP - - - ping.c - 1 - ..\..\components\net\lwip-2.0.2\src\apps\ping\ping.c - - netdb.c 1 - ..\..\components\net\lwip-2.0.2\src\api\netdb.c + ..\..\components\net\lwip-2.0.3\src\api\netdb.c ip.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ip.c + ..\..\components\net\lwip-2.0.3\src\core\ip.c autoip.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\autoip.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\autoip.c ethernet.c 1 - ..\..\components\net\lwip-2.0.2\src\netif\ethernet.c + ..\..\components\net\lwip-2.0.3\src\netif\ethernet.c netif.c 1 - ..\..\components\net\lwip-2.0.2\src\core\netif.c + ..\..\components\net\lwip-2.0.3\src\core\netif.c sys.c 1 - ..\..\components\net\lwip-2.0.2\src\core\sys.c + ..\..\components\net\lwip-2.0.3\src\core\sys.c sockets.c 1 - ..\..\components\net\lwip-2.0.2\src\api\sockets.c + ..\..\components\net\lwip-2.0.3\src\api\sockets.c netifapi.c 1 - ..\..\components\net\lwip-2.0.2\src\api\netifapi.c + ..\..\components\net\lwip-2.0.3\src\api\netifapi.c tcpip.c 1 - ..\..\components\net\lwip-2.0.2\src\api\tcpip.c + ..\..\components\net\lwip-2.0.3\src\api\tcpip.c ip4_addr.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_addr.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\ip4_addr.c dhcp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\dhcp.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\dhcp.c init.c 1 - ..\..\components\net\lwip-2.0.2\src\core\init.c + ..\..\components\net\lwip-2.0.3\src\core\init.c ethernetif.c 1 - ..\..\components\net\lwip-2.0.2\src\netif\ethernetif.c + ..\..\components\net\lwip-2.0.3\src\netif\ethernetif.c etharp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\etharp.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\etharp.c memp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\memp.c + ..\..\components\net\lwip-2.0.3\src\core\memp.c ip4.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\ip4.c netbuf.c 1 - ..\..\components\net\lwip-2.0.2\src\api\netbuf.c + ..\..\components\net\lwip-2.0.3\src\api\netbuf.c raw.c 1 - ..\..\components\net\lwip-2.0.2\src\core\raw.c + ..\..\components\net\lwip-2.0.3\src\core\raw.c ip4_frag.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\ip4_frag.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\ip4_frag.c tcp_out.c 1 - ..\..\components\net\lwip-2.0.2\src\core\tcp_out.c + ..\..\components\net\lwip-2.0.3\src\core\tcp_out.c lowpan6.c 1 - ..\..\components\net\lwip-2.0.2\src\netif\lowpan6.c + ..\..\components\net\lwip-2.0.3\src\netif\lowpan6.c icmp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\icmp.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\icmp.c api_lib.c 1 - ..\..\components\net\lwip-2.0.2\src\api\api_lib.c + ..\..\components\net\lwip-2.0.3\src\api\api_lib.c inet_chksum.c 1 - ..\..\components\net\lwip-2.0.2\src\core\inet_chksum.c + ..\..\components\net\lwip-2.0.3\src\core\inet_chksum.c stats.c 1 - ..\..\components\net\lwip-2.0.2\src\core\stats.c + ..\..\components\net\lwip-2.0.3\src\core\stats.c err.c 1 - ..\..\components\net\lwip-2.0.2\src\api\err.c + ..\..\components\net\lwip-2.0.3\src\api\err.c tcp_in.c 1 - ..\..\components\net\lwip-2.0.2\src\core\tcp_in.c + ..\..\components\net\lwip-2.0.3\src\core\tcp_in.c dns.c 1 - ..\..\components\net\lwip-2.0.2\src\core\dns.c + ..\..\components\net\lwip-2.0.3\src\core\dns.c sys_arch.c 1 - ..\..\components\net\lwip-2.0.2\src\arch\sys_arch.c + ..\..\components\net\lwip-2.0.3\src\arch\sys_arch.c timeouts.c 1 - ..\..\components\net\lwip-2.0.2\src\core\timeouts.c + ..\..\components\net\lwip-2.0.3\src\core\timeouts.c igmp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\ipv4\igmp.c + ..\..\components\net\lwip-2.0.3\src\core\ipv4\igmp.c udp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\udp.c + ..\..\components\net\lwip-2.0.3\src\core\udp.c pbuf.c 1 - ..\..\components\net\lwip-2.0.2\src\core\pbuf.c + ..\..\components\net\lwip-2.0.3\src\core\pbuf.c def.c 1 - ..\..\components\net\lwip-2.0.2\src\core\def.c + ..\..\components\net\lwip-2.0.3\src\core\def.c api_msg.c 1 - ..\..\components\net\lwip-2.0.2\src\api\api_msg.c + ..\..\components\net\lwip-2.0.3\src\api\api_msg.c + + + + + ping.c + 1 + ..\..\components\net\lwip-2.0.3\src\apps\ping\ping.c tcp.c 1 - ..\..\components\net\lwip-2.0.2\src\core\tcp.c + ..\..\components\net\lwip-2.0.3\src\core\tcp.c @@ -1249,6 +1249,13 @@ SAL + + + netdev.c + 1 + ..\..\components\net\netdev\src\netdev.c + + netdev_ipaddr.c @@ -1258,9 +1265,9 @@ - netdev.c + sal_socket.c 1 - ..\..\components\net\netdev\src\netdev.c + ..\..\components\net\sal_socket\src\sal_socket.c @@ -1284,13 +1291,6 @@ ..\..\components\net\sal_socket\dfs_net\dfs_net.c - - - sal_socket.c - 1 - ..\..\components\net\sal_socket\src\sal_socket.c - - af_inet_lwip.c diff --git a/bsp/gd32450z-eval/rtconfig.h b/bsp/gd32450z-eval/rtconfig.h index 24e31e0e72..f77bbc63ca 100644 --- a/bsp/gd32450z-eval/rtconfig.h +++ b/bsp/gd32450z-eval/rtconfig.h @@ -152,7 +152,7 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP202 +#define RT_USING_LWIP203 #define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_IGMP #define RT_LWIP_ICMP diff --git a/bsp/imx6sx/cortex-a9/.config b/bsp/imx6sx/cortex-a9/.config index 6cf3583151..4b42f0268a 100644 --- a/bsp/imx6sx/cortex-a9/.config +++ b/bsp/imx6sx/cortex-a9/.config @@ -235,8 +235,7 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 @@ -467,6 +466,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -477,7 +477,6 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -528,6 +527,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -639,6 +639,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -726,5 +727,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set CONFIG_SOC_MCIMX6X4=y CONFIG_RT_USING_UART1=y diff --git a/bsp/imx6sx/cortex-a9/rtconfig.h b/bsp/imx6sx/cortex-a9/rtconfig.h index 4990f78084..ee4491554a 100644 --- a/bsp/imx6sx/cortex-a9/rtconfig.h +++ b/bsp/imx6sx/cortex-a9/rtconfig.h @@ -134,7 +134,7 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP202 +#define RT_USING_LWIP203 #define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_IGMP #define RT_LWIP_ICMP diff --git a/bsp/ls2kdev/.config b/bsp/ls2kdev/.config index 2e2dcca70b..a273e07a43 100644 --- a/bsp/ls2kdev/.config +++ b/bsp/ls2kdev/.config @@ -264,8 +264,7 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=8 @@ -501,6 +500,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -511,7 +511,6 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -562,6 +561,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -673,6 +673,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -760,6 +761,8 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set CONFIG_SOC_LS2K1000=y CONFIG_RT_USING_UART0=y # CONFIG_RT_USING_UART4 is not set diff --git a/bsp/ls2kdev/rtconfig.h b/bsp/ls2kdev/rtconfig.h index dceb19ed54..27fd9b0766 100644 --- a/bsp/ls2kdev/rtconfig.h +++ b/bsp/ls2kdev/rtconfig.h @@ -151,7 +151,7 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP202 +#define RT_USING_LWIP203 #define RT_LWIP_MEM_ALIGNMENT 8 #define RT_LWIP_IGMP #define RT_LWIP_ICMP diff --git a/bsp/qemu-vexpress-a9/.config b/bsp/qemu-vexpress-a9/.config index 1823424c79..f20d37057e 100644 --- a/bsp/qemu-vexpress-a9/.config +++ b/bsp/qemu-vexpress-a9/.config @@ -299,9 +299,8 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -# CONFIG_RT_USING_LWIP202 is not set -# CONFIG_RT_USING_LWIP203 is not set -CONFIG_RT_USING_LWIP212=y +CONFIG_RT_USING_LWIP203=y +# CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 # CONFIG_RT_LWIP_IGMP is not set @@ -532,6 +531,7 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -542,7 +542,6 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -593,6 +592,7 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -705,6 +705,7 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -792,6 +793,8 @@ CONFIG_RT_USING_LWP=y # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config diff --git a/bsp/qemu-vexpress-a9/rtconfig.h b/bsp/qemu-vexpress-a9/rtconfig.h index 5957f7c565..35238f926c 100644 --- a/bsp/qemu-vexpress-a9/rtconfig.h +++ b/bsp/qemu-vexpress-a9/rtconfig.h @@ -203,7 +203,7 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP212 +#define RT_USING_LWIP203 #define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_ICMP #define RT_LWIP_DNS diff --git a/bsp/raspberry-pi/raspi4-32/.config b/bsp/raspberry-pi/raspi4-32/.config index 82e6d9493e..133327fe51 100644 --- a/bsp/raspberry-pi/raspi4-32/.config +++ b/bsp/raspberry-pi/raspi4-32/.config @@ -282,8 +282,7 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 @@ -514,6 +513,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -524,7 +524,6 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -575,6 +574,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -686,6 +686,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -773,6 +774,8 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set CONFIG_BCM2711_SOC=y # CONFIG_BSP_SUPPORT_FPU is not set diff --git a/bsp/raspberry-pi/raspi4-32/rtconfig.h b/bsp/raspberry-pi/raspi4-32/rtconfig.h index aeeb1f12f8..ed2adcbb38 100644 --- a/bsp/raspberry-pi/raspi4-32/rtconfig.h +++ b/bsp/raspberry-pi/raspi4-32/rtconfig.h @@ -168,7 +168,7 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP202 +#define RT_USING_LWIP203 #define RT_LWIP_MEM_ALIGNMENT 4 #define RT_LWIP_IGMP #define RT_LWIP_ICMP diff --git a/bsp/zynqmp-r5-axu4ev/.config b/bsp/zynqmp-r5-axu4ev/.config index e72504bec4..9c68105bb2 100644 --- a/bsp/zynqmp-r5-axu4ev/.config +++ b/bsp/zynqmp-r5-axu4ev/.config @@ -265,8 +265,7 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=32 @@ -497,6 +496,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -507,7 +507,6 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -558,6 +557,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -669,6 +669,7 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -756,6 +757,8 @@ CONFIG_RT_LWIP_USING_PING=y # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set CONFIG_SOC_ZYNQMP_R5=y # diff --git a/bsp/zynqmp-r5-axu4ev/rtconfig.h b/bsp/zynqmp-r5-axu4ev/rtconfig.h index 2dad29e3c4..8fd898cad6 100644 --- a/bsp/zynqmp-r5-axu4ev/rtconfig.h +++ b/bsp/zynqmp-r5-axu4ev/rtconfig.h @@ -154,7 +154,7 @@ /* light weight TCP/IP stack */ #define RT_USING_LWIP -#define RT_USING_LWIP202 +#define RT_USING_LWIP203 #define RT_LWIP_MEM_ALIGNMENT 32 #define RT_LWIP_IGMP #define RT_LWIP_ICMP diff --git a/components/net/Kconfig b/components/net/Kconfig index d9ed7d9542..f4531375c0 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -120,9 +120,6 @@ config RT_USING_LWIP config RT_USING_LWIP141 bool "lwIP v1.4.1" - config RT_USING_LWIP202 - bool "lwIP v2.0.2" - config RT_USING_LWIP203 bool "lwIP v2.0.3" @@ -131,7 +128,7 @@ config RT_USING_LWIP endchoice - if (RT_USING_LWIP202 || RT_USING_LWIP212 || RT_USING_LWIP203) + if (RT_USING_LWIP203 || RT_USING_LWIP212) config RT_USING_LWIP_IPV6 bool "IPV6 protocol" default n diff --git a/components/net/lwip-2.0.2/CHANGELOG b/components/net/lwip-2.0.2/CHANGELOG deleted file mode 100644 index 3a277195ce..0000000000 --- a/components/net/lwip-2.0.2/CHANGELOG +++ /dev/null @@ -1,4276 +0,0 @@ -HISTORY - -(git master) - - * [Enter new changes just after this line - do not remove this line] - -(STABLE-2.0.2) - - ++ New features: - - 2017-02-10: Dirk Ziegelmeier - * Implement task #14367: Hooks need a better place to be defined: - We now have a #define for a header file name that is #included in every .c - file that provides hooks. - - ++ Bugfixes: - - 2017-03-08 - * tcp: do not keep sending SYNs when getting ACKs - - 2017-03-08: Joel Cunningham - * tcp: Initialize ssthresh to TCP_SND_BUF (bug #50476) - - 2017-03-01: Simon Goldschmidt - * httpd: LWIP_HTTPD_POST_MANUAL_WND: fixed double-free when httpd_post_data_recved - is called nested from httpd_post_receive_data() (bug #50424) - - 2017-02-28: David van Moolenbroek/Simon Goldschmidt - * tcp: fixed bug #50418: LWIP_EVENT_API: fix invalid calbacks for SYN_RCVD pcb - - 2017-02-17: Simon Goldschmidt - * dns: Improved DNS_LOCAL_HOSTLIST interface (bug #50325) - - 2017-02-16: Simon Goldschmidt - * LWIP_NETCONN_FULLDUPLEX: fixed shutdown during write (bug #50274) - - 2017-02-13: Simon Goldschmidt/Dirk Ziegelmeier - * For tiny targtes, LWIP_RAND is optional (fix compile time checks) - - 2017-02-10: Simon Goldschmidt - * tcp: Fixed bug #47485 (tcp_close() should not fail on memory error) by retrying - to send FIN from tcp_fasttmr - - 2017-02-09: Simon Goldschmidt - * sockets: Fixed bug #44032 (LWIP_NETCONN_FULLDUPLEX: select might work on - invalid/reused socket) by not allowing to reallocate a socket that has - "select_waiting != 0" - - 2017-02-09: Simon Goldschmidt - * httpd: Fixed bug #50059 (httpd LWIP_HTTPD_SUPPORT_11_KEEPALIVE vs. - LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED) - - 2017-02-08: Dirk Ziegelmeier - * Rename "IPv6 mapped IPv4 addresses" to their correct name from RFC4191: - "IPv4-mapped IPv6 address" - - 2017-02-08: Luc Revardel - * mld6.c: Fix bug #50220 (mld6_leavegroup does not send ICMP6_TYPE_MLD, even - if last reporter) - - 2017-02-08: David van Moolenbroek - * ip6.c: Patch #9250: fix source substitution in ip6_output_if() - - 2017-02-08: Simon Goldschmidt - * tcp_out.c: Fixed bug #50090 (last_unsent->oversize_left can become wrong value - in tcp_write error path) - - 2017-02-02: Dirk Ziegelmeier - * Fix bug #50206: UDP Netconn bind to IP6_ADDR_ANY fails - - 2017-01-18: Dirk Ziegelmeier - * Fix zero-copy RX, see bug bug #50064. PBUF_REFs were not supported as ARP requests. - - 2017-01-15: Axel Lin, Dirk Ziegelmeier - * minor bug fixes in mqtt - - 2017-01-11: Knut Andre Tidemann - * sockets/netconn: fix broken default ICMPv6 handling of checksums - -(STABLE-2.0.1) - - ++ New features: - - 2016-12-31: Simon Goldschmidt - * tcp.h/.c: added function tcp_listen_with_backlog_and_err() to get the error - reason when listening fails (bug #49861) - - 2016-12-20: Erik Andersen - * Add MQTT client - - 2016-12-14: Jan Breuer: - * opt.h, ndc.h/.c: add support for RDNSS option (as per RFC 6106) - - 2016-12-14: David van Moolenbroek - * opt.h, nd6.c: Added LWIP_HOOK_ND6_GET_GW() - - 2016-12-09: Dirk Ziegelmeier - * ip6_frag.c: Implemented support for LWIP_NETIF_TX_SINGLE_PBUF - - 2016-12-09: Simon Goldschmidt - * dns.c: added one-shot multicast DNS queries - - 2016-11-24: Ambroz Bizjak, David van Moolenbroek - * tcp_out.c: Optimize passing contiguous nocopy buffers to tcp_write (bug #46290) - - 2016-11-16: Dirk Ziegelmeier - * sockets.c: added support for IPv6 mapped IPv4 addresses - - ++ Bugfixes: - - 2016-12-16: Thomas Mueller - * api_lib.c: fixed race condition in return value of netconn_gethostbyname() - (and thus also lwip_gethostbyname/_r() and lwip_getaddrinfo()) - - 2016-12-15: David van Moolenbroek - * opt.h, tcp: added LWIP_HOOK_TCP_ISN() to implement less predictable initial - sequence numbers (see contrib/addons/tcp_isn for an example implementation) - - 2016-12-05: Dirk Ziegelmeier - * fixed compiling with IPv4 disabled (IPv6 only case) - - 2016-11-28: Simon Goldschmidt - * api_lib.c: fixed bug #49725 (send-timeout: netconn_write() can return - ERR_OK without all bytes being written) - - 2016-11-28: Ambroz Bizjak - * tcpi_in.c: fixed bug #49717 (window size in received SYN and SYN-ACK - assumed scaled) - - 2016-11-25: Simon Goldschmidt - * dhcp.c: fixed bug #49676 (Possible endless loop when parsing dhcp options) - - 2016-11-23: Dirk Ziegelmeier - * udp.c: fixed bug #49662: multicast traffic is now only received on a UDP PCB - (and therefore on a UDP socket/netconn) when the PCB is bound to IP_ADDR_ANY - - 2016-11-16: Dirk Ziegelmeier - * *: Fixed dual-stack behaviour, IPv6 mapped IPv4 support in socket API - - 2016-11-14: Joel Cunningham - * tcp_out.c: fixed bug #49533 (start persist timer when unsent seg can't fit - in window) - - 2016-11-16: Roberto Barbieri Carrera - * autoip.c: fixed bug #49610 (sometimes AutoIP fails to reuse the same address) - - 2016-11-11: Dirk Ziegelmeier - * sockets.c: fixed bug #49578 (dropping multicast membership does not work - with LWIP_SOCKET_OFFSET) - -(STABLE-2.0.0) - - ++ New features: - - 2016-07-27: Simon Goldschmidt - * opt.h, timeouts.h/.c: added LWIP_TIMERS_CUSTOM to override the default - implementation of timeouts - - 2016-07-xx: Dirk Ziegelmeier - * Large overhaul of doxygen documentation - - 2016-04-05: Simon Goldschmidt - * timers.h/.c: prepare for overriding current timeout implementation: all - stack-internal caclic timers are avaliable in the lwip_cyclic_timers array - - 2016-03-23: Simon Goldschmidt - * tcp: call accept-callback with ERR_MEM when allocating a pcb fails on - passive open to inform the application about this error - ATTENTION: applications have to handle NULL pcb in accept callback! - - 2016-02-22: Ivan Delamer - * Initial 6LoWPAN support - - 2016-02-XX to 2016-03-XX: Dirk Ziegelmeier - * Cleanup TCPIP thread sync methods in a way that it is possibe to use them - in arbitrary code that needs things to be done in TCPIP thread. Used to - decouple netconn, netif, ppp and 6LoWPAN from LWIP core. - - 2016-02-XX: Dirk Ziegelmeier - * Implement dual-stack support in RAW, UDP and TCP. Add new IP address - type IPADDR_ANY_TYPE for this. Netconn/Socket API: Dual-stack is - automatically supported when an IPv6 netconn/socket is created. - - 2015-12-26: Martin Hentschel and Dirk Ziegelmeier - * Rewrite SNMP agent. SNMPv2c + MIB compiler. - - 2015-11-12: Dirk Ziegelmeier - * Decouple SNMP stack from lwIP core and move stack to apps/ directory. - Breaking change: Users have to call snmp_init() now! - - 2015-11-12: Dirk Ziegelmeier - * Implement possibility to declare private memory pools. This is useful to - decouple some apps from the core (SNMP stack) or make contrib app usage - simpler (httpserver_raw) - - 2015-10-09: Simon Goldschmidt - * started to move "private" header files containing implementation details to - "lwip/priv/" include directory to seperate the API from the implementation. - - 2015-10-07: Simon Goldschmidt - * added sntp client as first "supported" application layer protocol implementation - added 'apps' folder - - 2015-09-30: Dirk Ziegelmeier - * snmp_structs.h, mib_structs.c, mib2.c: snmp: fixed ugly inheritance - implementation by aggregating the "base class" (struct mib_node) in all - derived node classes to get more type-safe code - - 2015-09-23: Simon Goldschmidt - * netif.h/.c, nd6.c: task #13729: Convert netif addresses (IPv4 & IPv6) to - ip_addr_t (so they can be used without conversion/temporary storage) - - 2015-09-08: Dirk Ziegelmeier - * snmp: Separate mib2 counter/table callbacks from snmp agent. This both cleans - up the code and should allow integration of a 3rd party agent/mib2. Simple - counters are kept in MIB2_STATS, tree/table change function prototypes moved to - snmp_mib2.h. - - 2015-09-03: Simon Goldschmidt - * opt.h, dns.h/.c: DNS/IPv6: added support for AAAA records - - 2015-09-01: Simon Goldschmidt - * task #12178: hardware checksum capabilities can be configured per netif - (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function) - - 2015-08-30: Simon Goldschmidt - * PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in - contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required) - - 2015-08-30: Simon Goldschmidt - * support IPv4 source based routing: define LWIP_HOOK_IP4_ROUTE_SRC to point - to a routing function - - 2015-08-05: Simon Goldschmidt - * many files: allow multicast socket options IP_MULTICAST_TTL, IP_MULTICAST_IF - and IP_MULTICAST_LOOP to be used without IGMP - - 2015-04-24: Simon Goldschmidt - * dhcp.h/c, autoip.h/.c: added functions dhcp/autoip_supplied_address() to - check for the source of address assignment (replacement for NETIF_FLAG_DHCP) - - 2015-04-10: Simon Goldschmidt - * many files: task #13480: added LWIP_IPV4 define - IPv4 can be disabled, - leaving an IPv6-only stack - - 2015-04-09: Simon Goldschmidt - * nearly all files: task #12722 (improve IPv4/v6 address handling): renamed - ip_addr_t to ip4_addr_t, renamed ipX_addr_t to ip_addr_t and added IP - version; ip_addr_t is used for all generic IP addresses for the API, - ip(4/6)_addr_t are only used internally or when initializing netifs or when - calling version-related functions - - 2015-03-24: Simon Goldschmidt - * opt.h, ip4_addr.h, ip4.c, ip6.c: loopif is not required for loopback traffic - any more but passed through any netif (ENABLE_LOOPBACK has to be enabled) - - 2015-03-23: Simon Goldschmidt - * opt.h, etharp.c: with ETHARP_TABLE_MATCH_NETIF== 1, duplicate (Auto)-IP - addresses on multiple netifs should now be working correctly (if correctly - addressed by routing, that is) - - 2015-03-23: Simon Goldschmidt - * etharp.c: Stable etharp entries that are about to expire are now refreshed - using unicast to prevent unnecessary broadcast. Only if no answer is received - after 15 seconds, broadcast is used. - - 2015-03-06: Philip Gladstone - * netif.h/.c: patch #8359 (Provide utility function to add an IPv6 address to - an interface) - - 2015-03-05: Simon Goldschmidt - * netif.c, ip4.c, dhcp.c, autoip.c: fixed bug #37068 (netif up/down handling - is unclear): correclty separated administrative status of a netif (up/down) - from 'valid address' status - ATTENTION: netif_set_up() now always has to be called, even when dhcp/autoip - is used! - - 2015-02-26: patch by TabascoEye - * netif.c, udp.h/.c: fixed bug #40753 (re-bind UDP pcbs on change of IP address) - - 2015-02-22: chrysn, Simon Goldschmidt - * *.*: Changed nearly all functions taking 'ip(X)_addr_t' pointer to take - const pointers (changed user callbacks: raw_recv_fn, udp_recv_fn; changed - port callbacks: netif_output_fn, netif_igmp_mac_filter_fn) - - 2015-02-19: Ivan Delamer - * netif.h, dhcp.c: Removed unused netif flag for DHCP. The preferred way to evaluate - if DHCP is active is through netif->dhcp field. - - 2015-02-19: Ivan Delamer - * netif.h, slipif.c, ppp.c: Removed unused netif flag for point to point connections - - 2015-02-18: Simon Goldschmidt - * api_lib.c: fixed bug #37958 "netconn API doesn't handle correctly - connections half-closed by peer" - - 2015-02-18: Simon Goldschmidt - * tcp.c: tcp_alloc() prefers killing CLOSING/LAST_ACK over active connections - (see bug #39565) - - 2015-02-16: Claudius Zingerli, Sergio Caprile - * opt.h, dhcp.h/.c: patch #8361 "Add support for NTP option in DHCP" - - 2015-02-14: Simon Goldschmidt - * opt.h, snmp*: added support for write-access community and dedicated - community for sending traps - - 2015-02-13: Simon Goldschmidt - * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when - a memp pool was empty and an item is now available - - 2015-02-13: Simon Goldschmidt - * opt.h, pbuf.h/.c, etharp.c: Added the option PBUF_LINK_ENCAPSULATION_HLEN to - allocate additional header space for TX on netifs requiring additional headers - - 2015-02-12: chrysn - * timers.h/.c: introduce sys_timeouts_sleeptime (returns the time left before - the next timeout is due, for NO_SYS==1) - - 2015-02-11: Nick van Ijzendoorn - * opt.h, sockets.h/c: patch #7702 "Include ability to increase the socket number - with defined offset" - - 2015-02-11: Frederick Baksik - * opt.h, def.h, others: patch #8423 "arch/perf.h" should be made an optional item - - 2015-02-11: Simon Goldschmidt - * api_msg.c, opt.h: started to implement fullduplex sockets/netconns - (note that this is highly unstable yet!) - - 2015-01-17: Simon Goldschmidt - * api: allow enabling socket API without (public) netconn API - netconn API is - still used by sockets, but keeping it private (static) should allow better - compiler optimizations - - 2015-01-16: Simon Goldschmidt - * tcp_in.c: fixed bug #20506 "Initial congestion window is very small" again - by implementing the calculation formula from RFC3390 - - 2014-12-10: Simon Goldschmidt - * api: added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread - instead of using one per netconn and per select call - - 2014-12-08: Simon Goldschmidt - * ip6.h: fixed bug #43778: IPv6 header version not set on 16-bit platform - (macro IP6H_VTCFL_SET()) - - 2014-12-08: Simon Goldschmidt - * icmp.c, ip4.c, pbuf.c, udp.c, pbuf.h: task #11472 Support PBUF_REF for RX - (IPv6 and IPv4/v6 reassembly might not work yet) - - 2014-11-06: Simon Goldschmidt - * sockets.c/.h, init.c: lwip_socket_init() is not needed any more - -> compatibility define - - 2014-09-16: Simon Goldschmidt - * dns.c, opt.h: reduced ram usage by parsing DNS responses in place - - 2014-09-16: Simon Goldschmidt - * pbuf.h/.c: added pbuf_take_at() and pbuf_put_at() - - 2014-09-15: Simon Goldschmidt - * dns.c: added source port randomization to make the DNS client more robust - (see bug #43144) - - 2013-09-02: Simon Goldschmidt - * arch.h and many other files: added optional macros PACK_STRUCT_FLD_8() and - PACK_STRUCT_FLD_S() to prevent gcc 4 from warning about struct members that - do not need packing - - 2013-08-19: Simon Goldschmidt - * netif.h: bug #42998: made NETIF_MAX_HWADDR_LEN overridable for some special - networks - - 2013-03-17: Simon Goldschmidt (patch by Ghobad Emadi) - * opt.h, etharp.c: Added LWIP_HOOK_ETHARP_GET_GW to implement IPv4 routing with - multiple gateways - - 2013-04-20: Fatih Asici - * opt.h, etharp.h/.c: patch #7993: Added support for transmitting packets - with VLAN headers via hook function LWIP_HOOK_VLAN_SET and to check them - via hook function LWIP_HOOK_VLAN_CHECK - - 2014-02-20: Simon Goldschmidt (based on patch by Artem Pisarenko) - * patch #7885: modification of api modules to support FreeRTOS-MPU - (don't pass stack-pointers to other threads) - - 2014-02-05: Simon Goldschmidt (patch by "xtian" and "alex_ab") - * patch #6537/#7858: TCP window scaling support - - 2014-01-17: Jiri Engelthaler - * icmp, icmp6, opt.h: patch #8027: Completed HW checksuming for IPv4 and - IPv6 ICMP's - - 2012-08-22: Sylvain Rochet - * New PPP stack for lwIP, developed in ppp-new branch. - Based from pppd 2.4.5, released 2009-11-17, with huge changes to match - code size and memory requirements for embedded devices, including: - - Gluing together the previous low-level PPP code in lwIP to pppd 2.4.5, which - is more or less what pppd sys-* files are, so that we get something working - using the unix port. - - Merged some patchs from lwIP Git repository which add interesting features - or fix bugs. - - Merged some patchs from Debian pppd package which add interesting features - or fix bugs. - - Ported PPP timeout handling to the lwIP timers system - - Disabled all the PPP code using filesystem access, replaced in necessary cases - to configuration variables. - - Disabled all the PPP code forking processes. - - Removed IPX support, lwIP does not support IPX. - - Ported and improved random module from the previous PPP port. - - Removed samba TDB (file-driven database) usage, because it needs a filesystem. - - MS-CHAP required a DES implementation, we added the latest PolarSSL DES - implementation which is under a BSD-ish license. - - Also switched to PolarSSL MD4,MD5,SHA1 implementations, which are meant to be - used in embedded devices with reduced memory footprint. - - Removed PPP configuration file parsing support. - - Added macro definition EAP_SUPPORT to make EAP support optional. - - Added macro definition CHAP_SUPPORT to make CHAP support optional. - - Added macro definition MSCHAP_SUPPORT to make MSCHAP support optional. - - Added macro definition PAP_SUPPORT to make PAP support optional. - - Cleared all Linux syscall calls. - - Disabled demand support using a macro, so that it can be ported later. - - Disabled ECP support using a macro, so that it can be ported later. - - Disabled CCP support using a macro, so that it can be ported later. - - Disabled CBCP support using a macro, so that it can be ported later. - - Disabled LQR support using a macro, so that it can be ported later. - - Print packet debug feature optional, through PRINTPKT_SUPPORT - - Removed POSIX signal usage. - - Fully ported PPPoS code from the previous port. - - Fully ported PPPoE code from the previous port. - - Fully ported VJ compression protocol code from the previous port. - - Removed all malloc()/free() use from PPP, replaced by stack usage or PBUF. - - Disabled PPP server support using a macro, so that it can be ported later. - - Switched all PPP debug to lwIP debug system. - - Created PPP Control Block (PPP PCB), removed PPP unit integer everywhere, - removed all global variables everywhere, did everything necessary for - the PPP stack to support more than one PPP session (pppd only support - one session per process). - - Removed the statically allocated output buffer, now using PBUF. - - Improved structure size of all PPP modules, deep analyze of code to reduce - variables size to the bare minimum. Switched all boolean type (char type in - most architecture) to compiler generated bitfields. - - Added PPP IPv6 support, glued lwIP IPv6 support to PPP. - - Now using a persistent netif interface which can then be used in lwIP - functions requiring a netif. - - Now initializing PPP in lwip_init() function. - - Reworked completely the PPP state machine, so that we don't end up in - anymore in inconsistent state, especially with PPPoE. - - Improved the way we handle PPP reconnection after disconnect, cleaning - everything required so that we start the PPP connection again from a - clean state. - - Added PPP holdoff support, allow the lwIP user to wait a little bit before - reconnecting, prevents connection flood, especially when using PPPoL2TP. - - Added PPPoL2TP LAC support (a.k.a. UDP tunnels), adding a VPN client - feature to lwIP, L2TP being a widely used tunnel protocol. - - Switched all used PPP types to lwIP types (u8t, u16t, u32t, ...) - - Added PPP API "sequential" thread-safe API, based from NETIFAPI. - - 2011-07-21: Simon Goldschmidt - * sockets.c, opt.h: (bug #30185): added LWIP_FIONREAD_LINUXMODE that makes - ioctl/FIONREAD return the size of the next pending datagram. - - 2011-05-25: Simon Goldschmidt - * again nearly the whole stack, renamed ip.c to ip4.c, ip_addr.c to ip4_addr.c, - combined ipv4/ipv6 inet_chksum.c, added ip.h, ip_addr.h: Combined IPv4 - and IPv6 code where possible, added defines to access IPv4/IPv6 in non-IP - code so that the code is more readable. - - 2011-05-17: Patch by Ivan Delamer (only checked in by Simon Goldschmidt) - * nearly the whole stack: Finally, we got decent IPv6 support, big thanks to - Ivan! (this is work in progress: we're just post release anyway :-) - - - ++ Bugfixes: - - 2016-08-23: Simon Goldschmidt - * etharp: removed ETHARP_TRUST_IP_MAC since it is insecure and we don't need - it any more after implementing unicast ARP renewal towards arp entry timeout - - 2016-07-20: Simon Goldschmidt - * memp.h/.c: fixed bug #48442 (memp stats don't work for MEMP_MEM_MALLOC) - - 2016-07-21: Simon Goldschmidt (patch by Ambroz Bizjak) - * tcp_in.c, tcp_out.c: fixed bug #48543 (TCP sent callback may prematurely - report sent data when only part of a segment is acked) and don't include - SYN/FIN in snd_buf counter - - 2016-07-19: Simon Goldschmidt - * etharp.c: fixed bug #48477 (ARP input packet might update static entry) - - 2016-07-11: Simon Goldschmidt - * tcp_in.c: fixed bug #48476 (TCP sent callback called wrongly due to picking - up old pcb->acked - - 2016-06-30: Simon Goldschmidt (original patch by Fabian Koch) - * tcp_in.c: fixed bug #48170 (Vulnerable to TCP RST spoofing) - - 2016-05-20: Dirk Ziegelmeier - * sntp.h/.c: Fix return value of sntp_getserver() call to return a pointer - - 2016-04-05: Simon Goldschmidt (patch by Philip Gladstone) - * udp.c: patch #8358: allow more combinations of listening PCB for IPv6 - - 2016-04-05: Simon Goldschmidt - * netconn/socket API: fixed bug# 43739 (Accept not reporting errors about - aborted connections): netconn_accept() returns ERR_ABRT (sockets: ECONNABORTED) - for aborted connections, ERR_CLSD (sockets: EINVAL) if the listening netconn - is closed, which better seems to follow the standard. - - 2016-03-23: Florent Matignon - * dhcp.c: fixed bug #38203: DHCP options are not recorded in all DHCP ack messages - - 2016-03-22: Simon Goldschmidt - * tcp: changed accept handling to be done internally: the application does not - have to call tcp_accepted() any more. Instead, when delaying accept (e.g. sockets - do), call tcp_backlog_delayed()/tcp_backlog_accepted() (fixes bug #46696) - - 2016-03-22: Simon Goldschmidt - * dns.c: ignore dns response parsing errors, only abort resolving for correct - responses or error responses from correct server (bug #47459) - - 2016-03-17: Simon Goldschmidt - * api_msg.c: fixed bug #47448 (netconn/socket leak if RST is received during close) - - 2016-03-17: Joel Cunningham - * api_msg.c: don't fail closing a socket/netconn when failing to allocate the - FIN segment; blocking the calling thread for a while is better than risking - leaking a netconn/socket (see bug #46701) - - 2016-03-16: Joel Cunningham - * tcp_out.c: reset rto timer on fast retransmission - - 2016-03-16: Deomid Ryabkov - * tcp_out.c: fixed bug #46384 Segment size calculation bug with MSS != TCP_MSS - - 2016-03-05: Simon Goldschmidt - * err.h/.c, sockets.c: ERR_IF is not necessarily a fatal error - - 2015-11-19: fix by Kerem Hadimli - * sockets.c: fixed bug #46471: lwip_accept() leaks socket descriptors if new - netconn was already closed because of peer behavior - - 2015-11-12: fix by Valery Ushakov - * tcp_in.c: fixed bug #46365 tcp_accept_null() should call tcp_abort() - - 2015-10-02: Dirk Ziegelmeier/Simon Goldschmidt - * snmp: cleaned up snmp structs API (fixed race conditions from bug #46089, - reduce ram/rom usage of tables): incompatible change for private MIBs - - 2015-09-30: Simon Goldschmidt - * ip4_addr.c: fixed bug #46072: ip4addr_aton() does not check the number range - of all address parts - - 2015-08-28: Simon Goldschmidt - * tcp.c, tcp_in.c: fixed bug #44023: TCP ssthresh value is unclear: ssthresh - is set to the full send window for active open, too, and is updated once - after SYN to ensure the correct send window is used - - 2015-08-28: Simon Goldschmidt - * tcp: fixed bug #45559: Window scaling casts u32_t to u16_t without checks - - 2015-08-26: Simon Goldschmidt - * ip6_frag.h/.c: fixed bug bug #41009: IPv6 reassembly broken on 64-bit platforms: - define IPV6_FRAG_COPYHEADER==1 on these platforms to copy the IPv6 header - instead of referencing it, which gives more room for struct ip6_reass_helper - - 2015-08-25: Simon Goldschmidt - * sockets.c: fixed bug #45827: recvfrom: TCP window is updated with MSG_PEEK - - 2015-08-20: Manoj Kumar - * snmp_msg.h, msg_in.c: fixed bug #43790: Sending octet string of Length >255 - from SNMP agent - - 2015-08-19: Jens Nielsen - * icmp.c, ip4.c, tcp_in.c, udp.c, raw.c: fixed bug #45120: Broadcast & multiple - interfaces handling - - 2015-08-19: Simon Goldschmidt (patch by "Sandra") - * dns.c: fixed bug #45004: dns response without answer might be discarded - - 2015-08-18: Chrysn - * timers.c: patch #8704 fix sys_timeouts_sleeptime function - - 2015-07-01: Erik Ekman - * puf.c: fixed bug #45454 (pbuf_take_at() skips write and returns OK if offset - is at start of pbuf in chain) - - 2015-05-19: Simon Goldschmidt - * dhcp.h/.c: fixed bugs #45140 and #45141 (dhcp was not stopped correctly after - fixing bug #38204) - - 2015-03-21: Simon Goldschmidt (patch by Homyak) - * tcp_in.c: fixed bug #44766 (LWIP_WND_SCALE: tcphdr->wnd was not scaled in - two places) - - 2015-03-21: Simon Goldschmidt - * tcp_impl.h, tcp.c, tcp_in.c: fixed bug #41318 (Bad memory ref in tcp_input() - after tcp_close()) - - 2015-03-21: Simon Goldschmidt - * tcp_in.c: fixed bug #38468 (tcp_sent() not called on half-open connection for - data ACKed with the same ack as FIN) - - 2015-03-21: Simon Goldschmidt (patch by Christoffer Lind) - * dhcp.h/.c: fixed bug #38204 (DHCP lease time not handled correctly) - - 2015-03-20: Simon Goldschmidt - * dhcp.c: fixed bug #38714 (Missing option and client address in DHCPRELEASE message) - - 2015-03-19: Simon Goldschmidt - * api.h, tcpip.h, api_lib.c, api_msg.c: fixed race conditions in assigning - netconn->last_err (fixed bugs #38121 and #37676) - - 2015-03-09: Simon Goldschmidt - * ip4.c: fixed the IPv4 part of bug #43904 (ip_route() must detect linkup status) - - 2015-03-04: Simon Goldschmidt - * nd6.c: fixed bug #43784 (a host should send at least one Router Solicitation) - - 2015-03-04: Valery Ushakov - * ip6.c: fixed bug #41094 (Byte-order bug in IPv6 fragmentation header test) - - 2015-03-04: Zach Smith - * nd6.c: fixed bug #38153 (nd6_input() byte order issues) - - 2015-02-26: Simon Goldschmidt - * netif.c, tcp.h/.c: fixed bug #44378 (TCP connections are not aborted on netif - remove) - - 2015-02-25: Simon Goldschmidt - * ip4.c, etharp.c: fixed bug #40177 (System hangs when dealing with corrupted - packets), implemented task #12357 (Ensure that malicious packets don't - assert-fail): improved some pbuf_header calls to not assert-fail. - - 2015-02-25: patch by Joel Cunningham - * udp.h/.c, sockets.c: fixed bug #43028 (IP_MULTICAST_TTL affects unicast - datagrams) - - 2015-02-25: patch by Greg Renda - * ip4_frag.c: fixed bug #38210 (ip reassembly while remove oldest datagram) - - 2015-02-25: Simon Goldschmidt - * sockets.c: fixed bug #38165 (socket with mulicast): ensure igmp membership - are dropped when socket (not netconn!) is closed. - - 2015-02-25: Simon Goldschmidt - * ip4.h/.c, udp.c: fixed bug #38061 (wrong multicast routing in IPv4) by - adding an optional default netif for multicast routing - - 2015-02-25: Simon Goldschmidt - * netconn API: fixed that netconn_connect still used message passing for - LWIP_TCPIP_CORE_LOCKING==1 - - 2015-02-22: patch by Jens Nielsen - * icmp.c: fixed bug #38803 (Source address in broadcast ping reply) - - 2015-02-22: Simon Goldschmidt - * udp.h, sockets.c: added proper accessor functions for pcb->multicast_ip - (previously used by get/setsockopt only) - - 2015-02-18: Simon Goldschmidt - * sockets.c: Fixed select not reporting received FIN as 'readable' in certain - rare cases (bug #43779: select(), close(), and TCP retransmission error) - - 2015-02-17: Simon Goldschmidt - * err.h, sockets.c, api_msg.c: fixed bug #38853 "connect() use a wrong errno": - return ERR_ALREADY/EALRADY during connect, ERR_ISCONN/EISCONN when already - connected - - 2015-02-17: Simon Goldschmidt - * tcp_impl.h, tcp_out.c, tcp.c, api_msg.c: fixed bug #37614 "Errors from - ipX_output are not processed". Now tcp_output(_segment) checks for the return - value of ipX_output and does not try to send more on error. A netif driver - can call tcp_txnow() (from tcpip_thread!) to try to send again if TX buffers - are available again. - - 2015-02-14: patches by Freddie Chopin - * snmp*: made community writable, fixed some const pointers - - 2015-02-13: Simon Goldschmidt - * msg_in.c: fixed bug #22070 "MIB_OBJECT_WRITE_ONLY not implemented in SNMP" - - 2015-02-12: Simon Goldschmidt - * ip.h, ip4.c, ip6.c: fixed bug #36403 "ip4_input() and ip6_input() always pass - inp to higher layers": now the accepting netif is passed up, but the input - netif is available through ip_current_input_netif() if required. - - 2015-02-11: patch by hichard - * tcpip.c: fixed bug #43094 "The function tcpip_input() forget to handle IPv6" - - 2015-02-10: Simon Goldschmidt - * netconn API: fixed that netconn_close/netconn_delete still used message passing - for LWIP_TCPIP_CORE_LOCKING==1 - - 2015-02-10: Simon Goldschmidt - * netconn/socket api: fixed bug #44225 "closing TCP socket should time out - eventually", implemented task #6930 "Implement SO_LINGER": closing TCP sockets - times out after 20 seconds or after the configured SND_TIMEOUT or depending - on the linger settings. - - 2015-01-27: Simon Goldschmidt - * api_msg.c: fixed that SHUT_RD followed by SHUT_WR was different to SHUT_RDWR, - fixed return value of lwip_netconn_do_close on unconnected netconns - - 2015-01-17: Simon Goldschmidt - * sockets.c: fixed bug #43361 select() crashes with stale FDs - - 2015-01-17: Simon Goldschmidt - * sockets.c/.h, memp_std.h: fixed bug #40788 "lwip_setsockopt_internal() crashes" - by rewriting set/getsockopt functions to combine checks with the actual code - and add more NULL checks; this also fixes that CORE_LOCKING used message - passing for set/getsockopt. - - 2014-12-19: Simon Goldschmidt - * opt.h, dhcp.h/.c: prevent dhcp from starting when netif link is down (only - when LWIP_DHCP_CHECK_LINK_UP==1, which is disabled by default for - compatibility reasons) - - 2014-12-17: Simon Goldschmidt - * tcp_out.c: fixed bug #43840 Checksum error for TCP_CHECKSUM_ON_COPY==1 for - no-copy data with odd length - - 2014-12-10: Simon Goldschmidt - * sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO - take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can - be used to revert to the old 'winsock' style behaviour) - Fixed implementation of SO_ACCEPTCONN to just look at the pcb state - - 2014-12-09: Simon Goldschmidt - * ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded - - 2014-10-21: Simon Goldschmidt (patch by Joel Cunningham and Albert Huitsing) - * sockts.c: fixed bugs #41495 Possible threading issue in select() and #43278 - event_callback() handle context switch when calling sys_sem_signal() - - 2014-10-21: Simon Goldschmidt - * api_msg.c: fixed bug #38219 Assert on TCP netconn_write with sndtimeout set - - 2014-09-16: Kevin Cernekee - * dns.c: patch #8480 Fix handling of dns_seqno wraparound - - 2014-09-16: Simon Goldschmidt - * tcp_out.c: fixed bug #43192 tcp_enqueue_flags() should not check TCP_SND_QUEUELEN - when sending FIN - - 2014-09-03: Simon Goldschmidt - * msg_in.c: fixed bug #39355 SNMP Memory Leak in case of error - - 2014-09-02: Simon Goldschmidt - * err.h/.c, sockets.c, api_msg.c: fixed bug #43110 call getpeername() before - listen() will cause a error - - 2014-09-02: Simon Goldschmidt - * sockets.c: fixed bug #42117 lwip_fcntl does not set errno - - 2014-09-02: Simon Goldschmidt - * tcp.c: fixed bug #42299 tcp_abort() leaves freed pcb on tcp_bound_pcbs list - - 2014-08-20: Simon Goldschmidt - * dns.c: fixed bug #42987 lwIP is vulnerable to DNS cache poisoning due to - non-randomized TXIDs - - 2014-06-03: Simon Goldschmidt - * tcp_impl.h, tcp_in.c: fixed bug #37969 SYN packet dropped as short packet in - tcp_input function - - 2014-05-20: Simon Goldschmidt - * tcp_out.c: fixed bug #37184 tcp_write problem for pcbs in the SYN_SENT state - - 2014-05-19: Simon Goldschmidt - * *.h: Fixed bug #35874 reserved identifier violation (removed leading underscores - from header include guards) - - 2014-04-08: Simon Goldschmidt - * tcp.c: Fixed bug #36167 tcp server crash when client closes (maximum window) - - 2014-04-06: Simon Goldschmidt - * tcp_in.c: Fixed bug #36210 lwIP does not elicit an empty ACK when received - unacceptable ACK - - 2014-04-06: Simon Goldschmidt - * dhcp.c, ip4.c/.h, ip6.c/.h, udp.c/.h, ip.h: Fixed bug #41787 DHCP Discovery - is invalid when an IP is set to thet netif. - - 2014-03-14: Simon Goldschmidt - * tcp_out.c: Fixed bug #36153 TCP Cheksum error if LWIP_CHECKSUM_ON_COPY=1 - - 2014-03-11: Simon Goldschmidt (patch by Mason) - * opt.h, sockets.c: fixed bug #35928 BSD sockets functions must set errno for - POSIX-compliance - - 2014-02-27: Simon Goldschmidt - * dhcp.c: fixed bug #40303 DHCP xid renewed when sending a DHCPREQUEST - - 2014-02-27: Simon Goldschmidt - * raw.c: fixed bug #41680 raw socket can not receive IPv6 packet when - IP_SOF_BROADCAST_RECV==1 - - 2014-02-27: Simon Goldschmidt - * api_msg.c, sockets.c: fixed bug #38404 getpeeraddr returns success on - unconnected/listening TCP sockets - - 2014-02-27: Simon Goldschmidt - * sockets.c: fixed bug #41729 Some socket functions return Exyz instead of -1 - - 2014-02-25: Simon Goldschmidt - * ip4.c: fixed bug #39514 ip_route() may return an IPv6-only interface - - 2014-02-25: Simon Goldschmidt, patch by Fatih Asici - * pbuf.c: fixed bug #39356 Wrong increment in pbuf_memfind() - - 2014-02-25: Simon Goldschmidt - * netif.c/.h, udp.c: fixed bug #39225 udp.c uses netif_matches_ip6_addr() incorrectly; - renamed function netif_matches_ip6_addr() to netif_get_ip6_addr_match() - - 2014-02-25: Simon Goldschmidt - * igmp.c: fixed bug #39145 IGMP membership report for 224.0.0.1 - - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) - * etharp.c, opt.h: fixed bug #34681 Limit ARP queue length by ARP_QUEUE_LEN (=3) - - 2014-02-22: Simon Goldschmidt (patch by Amir Shalem) - * etharp.h/.c: fixed bug #34682 Limit ARP request flood for unresolved entry - - 2014-02-20: Simon Goldschmidt - * tcp_out.c: fixed bug #39683 Assertion "seg->tcphdr not aligned" failed with - MEM_ALIGNMENT = 8 - - 2014-02-20: Simon Goldschmidt - * sockets.c: fixed bug #39882 No function shall set errno to 0 - - 2014-02-20: Simon Goldschmidt - * mib_structs.c: fixed bug #40050 SNMP problem with MIB arrays > 255 - - 2014-02-20: Simon Goldschmidt - * api.h, sockets.c: fixed bug #41499 netconn::recv_avail can overflow - - 2014-01-08: Stathis Voukelatos - * memp_std.h: patch #7928 Fixed size calculation in MALLOC memory pool - creation macro - - 2014-01-18: Brian Fahs - * tcp_out.c: patch #8237: tcp_rexmit_rto fails to update pcb->unsent_oversize - when necessary - - 2014-01-17: Grant Erickson, Jay Logue, Simon Goldschmidt - * ipv6.c, netif.c: patch #7913 Enable Support for IPv6 Loopback - - 2014-01-16: Stathis Voukelatos - * netif.c: patch #7902 Fixed netif_poll() operation when LWIP_LOOPBACK_MAX_PBUFS > 0 - - 2014-01-14: "Freddie Chopin" - * snmp.h, mib2.c: fixed constness and spelling of sysdescr - - 2014-01-14: Simon Goldschmidt (patch by Thomas Faber) - * tcpip.c: patch #8241: Fix implicit declaration of ip_input with - LWIP_TCPIP_CORE_LOCKING_INPUT disabled - - 2014-01-14: chrysn - * timers.c: patch #8244 make timeouts usable reliably from outside of the - timeout routine - - 2014-01-10: Simon Goldschmidt - * ip_frag.c, ip6_frag.c: fixed bug #41041 Potential use-after-free in IPv6 reassembly - - 2014-01-10: Simon Goldschmidt - * memp.c: fixed bug #41188 Alignment error in memp_init() when MEMP_SEPARATE_POOLS==1 - - 2014-01-10: Simon Goldschmidt - * tcp.c: fixed bug #39898 tcp_fasttmr() possible lock due to infinte queue process loop - - 2013-06-29: Simon Goldschmidt - * inet.h, sockets.h: partially fixed bug #37585: IPv6 compatibility (in socket structs) - - 2013-06-29: Simon Goldschmidt - * inet6.h: bug #37585/task #12600: fixed struct in6_addr.s6_addr to conform to spec - - 2013-04-24: patch by Liam - * api_msg.c: patch #8008 Fix a potential null pointer dereference in assert - - 2013-04-24: Simon Goldschmidt - * igmp.c: fixed possible division by zero - - 2013-04-24: Simon Goldschmidt - * ip6.h, some ipv6 C files: fixed bug #38526 Coverity: Recursive Header Inclusion in ip6.h - - 2013-04-24: Simon Goldschmidt (patch by Emil Ljungdahl): - * netif.c: fixed bug #38586 netif_loop_output() "deadlocks" - - 2013-01-15: Simon Goldschmidt - * ip4.c: fixed bug #37665 ip_canforward operates on address in wrong byte order - - 2013-01-15: Simon Goldschmidt - * pbuf.h: fixed bug #38097 pbuf_free_ooseq() warning - - 2013-01-14: Simon Goldschmidt - * dns.c: fixed bug #37705 Possible memory corruption in DNS query - - 2013-01-11: Simon Goldschmidt - * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it - - 2012-08-22: Simon Goldschmidt - * memp.c: fixed bug #37166: memp_sanity check loops itself - - 2012-08-13: Simon Goldschmidt - * dhcp.c: fixed bug #36645: Calling dhcp_release before dhcp_start - dereferences NULL - - 2012-08-13: Simon Goldschmidt - * msg_out.c: fixed bug #36840 snmp_send_trap() NULL de-reference if traps - configured but no interfaces available - - 2012-08-13: Simon Goldschmidt - * dns.c: fixed bug #36899 DNS TTL 0 is cached for a long time - - 2012-05-11: Simon Goldschmidt (patch by Marty) - * memp.c: fixed bug #36412: memp.c does not compile when - MEMP_OVERFLOW_CHECK > zero and MEMP_SEPARATE_POOLS == 1 - - 2012-05-03: Simon Goldschmidt (patch by Sylvain Rochet) - * ppp.c: fixed bug #36283 (PPP struct used on header size computation and - not packed) - - 2012-05-03: Simon Goldschmidt (patch by David Empson) - * ppp.c: fixed bug #36388 (PPP: checksum-only in last pbuf leads to pbuf with - zero length) - - 2012-03-25: Simon Goldschmidt - * api_msg.c: Fixed bug #35817: do_connect() invalidly signals op_completed - for UDP/RAW with LWIP_TCPIP_CORE_LOCKING==1 - - 2012-03-25: Simon Goldschmidt - * api_msg.h, api_lib.c, api_msg.c, netifapi.c: fixed bug #35931: Name space - pollution in api_msg.c and netifapi.c - - 2011-08-24: Simon Goldschmidt - * inet6.h: fixed bug #34124 struct in6_addr does not conform to the standard - - - -(STABLE-1.4.1) - - ++ New features: - - 2012-03-25: Simon Goldschmidt (idea by Mason) - * posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h - which are a simple wrapper to the correct lwIP include files. - - 2012-01-16: Simon Goldschmidt - * opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP - - 2011-12-17: Simon Goldschmidt - * ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW) - (fixes bug #35061) - - 2011-09-27: Simon Goldschmidt - * opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989) - (define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h) - - 2011-09-21: Simon Goldschmidt - * opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on - send (TCP only, bug #33820) - - 2011-09-21: Simon Goldschmidt - * init.c: Converted runtime-sanity-checks into compile-time checks that can - be disabled (since runtime checks can often not be seen on embedded targets) - - 2011-09-11: Simon Goldschmidt - * ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file - to get a clear separation of which functions an application or port may use - (task #11281) - - 2011-09-11: Simon Goldschmidt - * opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize - initial local TCP/UDP ports (so that different port ranges are used after - a reboot; bug #33818; this one added tcp_init/udp_init functions again) - - 2011-09-03: Simon Goldschmidt - * dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302) - - 2011-08-24: Simon Goldschmidt - * opt.h, netif.h/.c: added netif remove callback (bug #32397) - - 2011-07-26: Simon Goldschmidt - * etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter - function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN) - - 2011-07-21: Simon Goldschmidt (patch by hanhui) - * ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour: - Added pbuf flags to mark incoming packets as link-layer broadcast/multicast. - Also added code to allow ip_forward() to forward non-broadcast packets to - the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1). - - 2011-06-26: Simon Goldschmidt (patch by Cameron Gutman) - * tcp.c, tcp_out.c: bug #33604: added some more asserts to check that - pcb->state != LISTEN - - 2011-05-14: Simon Goldschmidt (patch by Stéphane Lesage) - * tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static - memory message - - - ++ Bugfixes: - - 2012-09-26: Simon Goldschmidt - * api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object - - 2012-09-26: patch by Henrik Persson - * dhcp.c: patch #7843 Fix corner case with dhcp timeouts - - 2012-09-26: patch by Henrik Persson - * dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet - - 2012-08-22: Simon Goldschmidt - * memp.c: fixed bug #37166: memp_sanity check loops itself - - 2012-05-08: Simon Goldschmidt - * tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was - a debug-check issue only) - - 2012-03-27: Simon Goldschmidt - * vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c - - 2012-03-27: Simon Goldschmidt (patch by Mason) - * tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the - send MSS - - 2012-03-22: Simon Goldschmidt - * ip4.c: fixed bug #35927: missing refragmentaion in ip_forward - - 2012-03-20: Simon Goldschmidt (patch by Mason) - * netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list - - 2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic) - * ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian, - possible bug on little endian system - - 2012-02-23: Simon Goldschmidt - * etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway - (introduced when fixing bug# 33551) - - 2012-02-16: Simon Goldschmidt - * ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP() - (bug #35541: PPP Memory Leak) - - 2012-02-16: Simon Goldschmidt - * etharp.c: fixed bug #35531: Impossible to send multicast without a gateway - (introduced when fixing bug# 33551) - - 2012-02-16: Simon Goldschmidt (patch by Stéphane Lesage) - * msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed - - 2012-02-15: Simon Goldschmidt - * init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with - MEMP_MEM_MALLOC==1 - - 2012-02-12: Simon Goldschmidt - * tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on - MSS > pcb->snd_wnd (by not creating segments bigger than half the window) - - 2012-02-11: Simon Goldschmidt - * tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait - queue while closing - - 2012-01-22: Simon Goldschmidt - * tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR) - - 2012-01-21: Simon Goldschmidt - * tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb - - 2012-01-20: Simon Goldschmidt - * dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths - - 2012-01-20: Simon Goldschmidt - * pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy - - 2011-11-25: Simon Goldschmidt - * tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt - tcp_active_pcbs in some cases - - 2011-11-23: Simon Goldschmidt - * sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with - '#ifndef sys_msleep' - - 2011-11-22: Simon Goldschmidt - * netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when - netif is brought down - - 2011-10-28: Simon Goldschmidt - * tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks - - 2011-10-23: Simon Goldschmidt - * mem.c: fixed bug #34429: possible memory corruption with - LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1 - - 2011-10-18: Simon Goldschmidt - * arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard - error value - - 2011-10-18: Simon Goldschmidt - * opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small - windows (bug #34176 select after non-blocking send times out) - - 2011-10-18: Simon Goldschmidt - * tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't - consider netif->mtu, causes slow network - - 2011-10-18: Simon Goldschmidt - * sockets.c: fixed bug #34581 missing parentheses in udplite sockets code - - 2011-10-18: Simon Goldschmidt - * sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS - - 2011-10-17: Simon Goldschmidt - * api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api - - 2011-10-13: Simon Goldschmidt - * tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no - zero window is received) by starting the persist timer when a zero window is - received, not when we have more data queued for sending than fits into the - window - - 2011-10-13: Simon Goldschmidt - * def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex - - 2011-10-13: Simon Goldschmidt - * sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is - used and not all protocols are enabled - - 2011-10-12: Simon Goldschmidt - * pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4 - - 2011-10-09: Simon Goldschmidt - * tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect - byte value when pcb->unacked != NULL - - 2011-10-09: Simon Goldschmidt - * ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong - - 2011-09-27: Simon Goldschmidt - * tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places... - - 2011-09-27: Simon Goldschmidt - * tcp_in.c: fixed bug #28288: Data after FIN in oos queue - - 2011-09-27: Simon Goldschmidt - * dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf - - 2011-09-24: Simon Goldschmidt - * mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1 - - 2011-09-23: Simon Goldschmidt - * pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for - the last packet including FIN can lose data - - 2011-09-22: Simon Goldschmidt - * tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into - account - - 2011-09-21: Simon Goldschmidt - * opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks - in init.c - - 2011-09-20: Simon Goldschmidt - * timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts) - - 2011-09-11: Simon Goldschmidt - * tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs - (bug #34019) - - 2011-09-09: Simon Goldschmidt - * udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if - udp port matches - - 2011-09-03: Simon Goldschmidt - * tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet - is aggregated and sent to application - - 2011-09-01: Simon Goldschmidt - * opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared - to other options - - 2011-09-01: Simon Goldschmidt - * tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno - - 2011-08-24: Simon Goldschmidt - * api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling - accept() on UDP connections - - 2011-08-24: Simon Goldschmidt - * sockets.h: fixed bug #34057 socklen_t should be a typedef - - 2011-08-24: Simon Goldschmidt - * pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo) - - 2011-08-24: Simon Goldschmidt - * dhcp.c: fixed bug #34122 dhcp: hostname can overflow - - 2011-08-24: Simon Goldschmidt - * netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr - - 2011-08-22: Simon Goldschmidt - * tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This - merely prevents nagle from not transmitting fast after closing.) - - 2011-07-22: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns - always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now - lwip_send() sends as much as possible for non-blocking sockets - - 2011-07-22: Simon Goldschmidt - * pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented - for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() - at regular intervals from main level. - - 2011-07-21: Simon Goldschmidt - * etharp.c: fixed bug #33551 (ARP entries may time out although in use) by - sending an ARP request when an ARP entry is used in the last minute before - it would time out. - - 2011-07-04: Simon Goldschmidt - * sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0. - - 2011-06-26: Simon Goldschmidt - * tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by - updating its documentation only. - - 2011-06-26: Simon Goldschmidt - * mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an - unaligned pointer. - - 2011-06-26: Simon Goldschmidt - * mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1" - - 2011-05-25: Simon Goldschmidt - * tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range) - - - -(STABLE-1.4.0) - - ++ New features: - - 2011-03-27: Simon Goldschmidt - * tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and - calculate it in tcp_zero_window_probe (the only place where it was used). - - 2010-11-21: Simon Goldschmidt - * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif - (fixes bug #31525). - - 2010-07-12: Simon Goldschmidt (patch by Stephane Lesage) - * ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for - IP_MULTICAST_LOOP at socket- and raw-API level. - - 2010-06-16: Simon Goldschmidt - * ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow - link-layer-addressed UDP traffic to be received while a netif is down (just - like DHCP during configuration) - - 2010-05-22: Simon Goldschmidt - * many many files: bug #27352: removed packing from ip_addr_t, the packed - version is now only used in protocol headers. Added global storage for - current src/dest IP address while in input functions. - - 2010-05-16: Simon Goldschmidt - * def.h: task #10391: Add preprocessor-macros for compile-time htonl - calculation (and use them throughout the stack where applicable) - - 2010-05-16: Simon Goldschmidt - * opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool - instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h) - - 2010-05-16: Simon Goldschmidt - * opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own - MEMP pool instead of the heap - - 2010-05-13: Simon Goldschmidt - * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added - new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast - packets to more than one pcb. - - 2010-05-02: Simon Goldschmidt - * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending - UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1 - - 2010-04-30: Simon Goldschmidt - * udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that - take a precalculated checksum, added pbuf_fill_chksum() to copy data - into a pbuf and at the same time calculating the checksum for that data - - 2010-04-29: Simon Goldschmidt - * ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying - 2-byte-aligned IP addresses and MAC addresses - - 2010-04-28: Patch by Bill Auerbach - * ip.c: Inline generating IP checksum to save a function call - - 2010-04-14: Simon Goldschmidt - * tcpip.h/.c, timers.c: Added an overridable define to get informed when the - tcpip_thread processes messages or timeouts to implement a watchdog. - - 2010-03-28: Simon Goldschmidt - * ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing - fragment if LWIP_NETIF_TX_SINGLE_PBUF==1 - - 2010-03-27: Simon Goldschmidt - * etharp.c: Speedup TX by moving code from find_entry to etharp_output/ - etharp_query to prevent unnecessary function calls (inspired by - patch #7135). - - 2010-03-20: Simon Goldschmidt - * opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code - since the linker cannot do this automatically to save space. - - 2010-03-20: Simon Goldschmidt - * opt.h, etharp.c/.h: Added support for static ARP table entries - - 2010-03-14: Simon Goldschmidt - * tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum - when creating TCP segments, not when (re-)transmitting them. - - 2010-03-07: Simon Goldschmidt - * sockets.c: bug #28775 (select/event_callback: only check select_cb_list - on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code. - This should speed up receiving data on sockets as the select code in - event_callback is only executed when select is waiting. - - 2010-03-06: Simon Goldschmidt - * tcp_out.c: task #7013 (Create option to have all packets delivered to - netif->output in one piece): Always copy to try to create single pbufs - in tcp_write. - - 2010-03-06: Simon Goldschmidt - * api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv - by not allocating a netbuf): added function netconn_recv_tcp_pbuf() - for tcp netconns to receive pbufs, not netbufs; use that function - for tcp sockets. - - 2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt - * opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040: - Work on tcp_enqueue: Don't waste memory when chaining segments, - added option TCP_OVERSIZE to prevent creating many small pbufs when - calling tcp_write with many small blocks of data. Instead, pbufs are - allocated larger than needed and the space is used for later calls to - tcp_write. - - 2010-02-21: Simon Goldschmidt - * stats.c/.h: Added const char* name to mem- and memp-stats for easier - debugging. - - 2010-02-21: Simon Goldschmidt - * tcp.h (and usages), added tcp_impl.h: Splitted API and internal - implementation of tcp to make API usage cleare to application programmers - - 2010-02-14: Simon Goldschmidt/Stephane Lesage - * ip_addr.h: Improved some defines working on ip addresses, added faster - macro to copy addresses that cannot be NULL - - 2010-02-13: Simon Goldschmidt - * api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non- - blocking send operation) - - 2010-02-12: Simon Goldschmidt - * sockets.c/.h: Added a minimal version of posix fctl() to have a - standardised way to set O_NONBLOCK for nonblocking sockets. - - 2010-02-12: Simon Goldschmidt - * dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated - memory): added autoip_set_struct() and dhcp_set_struct() to let autoip - and dhcp work with user-allocated structs instead of callin mem_malloc - - 2010-02-12: Simon Goldschmidt/Jeff Barber - * tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has - SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT - - 2010-02-12: Simon Goldschmidt - * sys layer: task #10139 (Prefer statically allocated memory): converted - mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; - converted sys_mbox_new/sys_sem_new to take pointers and return err_t; - task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX - to let sys.h use binary semaphores instead of mutexes - as before) - - 2010-02-09: Simon Goldschmidt (Simon Kallweit) - * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 - (Restart system timeout handling) - - 2010-02-09: Simon Goldschmidt - * netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into - netif.c) - loopif does not have to be created by the port any more, - just define LWIP_HAVE_LOOPIF to 1. - - 2010-02-08: Simon Goldschmidt - * inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa - inet_ntoa_r/ipaddr_ntoa_r - - 2010-02-08: Simon Goldschmidt - * netif.h: Added netif_s/get_igmp_mac_filter() macros - - 2010-02-05: Simon Goldschmidt - * netif.h: Added function-like macros to get/set the hostname on a netif - - 2010-02-04: Simon Goldschmidt - * nearly every file: Replaced struct ip_addr by typedef ip_addr_t to - make changing the actual implementation behind the typedef easier. - - 2010-02-01: Simon Goldschmidt - * opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool - for allocating memory when getaddrinfo() is called. - - 2010-01-31: Simon Goldschmidt - * dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse - them once instead of parsing for every option. This also removes - the need for mem_malloc from dhcp_recv and makes it possible to - correctly retrieve the BOOTP file. - - 2010-01-30: simon Goldschmidt - * sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect - the sockets array. - - 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) - * api.h, api_msg.c, sockets.c: Added except set support in select - (patch #6860) - - 2010-01-29: Simon Goldschmidt (patch by Laura Garrett) - * api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c: - Add non-blocking support for connect (partly from patch #6860), - plus many cleanups in socket & netconn API. - - 2010-01-27: Simon Goldschmidt - * opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding - to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605 - - 2010-01-26: Simon Goldschmidt - * snmp: Use memp pools for snmp instead of the heap; added 4 new pools. - - 2010-01-14: Simon Goldschmidt - * ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback - by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback() - - 2010-01-13: Simon Goldschmidt - * mem.c: The heap now may be moved to user-defined memory by defining - LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address - (patch #6966 and bug #26133) - - 2010-01-10: Simon Goldschmidt (Bill Auerbach) - * opt.h, memp.c: patch #6822 (Add option to place memory pools in - separate arrays) - - 2010-01-10: Simon Goldschmidt - * init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define - LWIP_RAND() for lwip-wide randomization (to be defined in cc.h) - - 2009-12-31: Simon Goldschmidt - * tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h - added timers.c/.h: Separated timer implementation from semaphore/mbox - implementation, moved timer implementation to timers.c/.h, timers are - now only called from tcpip_thread or by explicitly checking them. - (TASK#7235) - - 2009-12-27: Simon Goldschmidt - * opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option - LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE) - - - ++ Bugfixes: - - 2011-04-20: Simon Goldschmidt - * sys_arch.txt: sys_arch_timeouts() is not needed any more. - - 2011-04-13: Simon Goldschmidt - * tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by - using ports in the IANA private/dynamic range (49152 through 65535). - - 2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl: - * etharp.h/.c: Fixed broken VLAN support. - - 2011-03-27: Simon Goldschmidt - * tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp - pcbs) by checking if the pcb was bound (local_port != 0). - - 2011-03-27: Simon Goldschmidt - * ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice) - - 2011-03-27: Simon Goldschmidt - * sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and - raw pcbs with LWIP_TCPIP_CORE_LOCKING==1. - - 2011-03-27: Simon Goldschmidt - * tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route - is present never times out) by starting retransmission timer before checking - route. - - 2011-03-22: Simon Goldschmidt - * ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only - calling sio_read_abort() if the file descriptor is valid. - - 2011-03-14: Simon Goldschmidt - * err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect - more than once can render a socket useless) since it mainly involves changing - "FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal. - - 2011-03-13: Simon Goldschmidt - * sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing - err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN: - use EALRADY instead of -1 - - 2011-03-13: Simon Goldschmidt - * api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the - connection has been aborted by err_tcp (since this is not a normal closing - procedure). - - 2011-03-13: Simon Goldschmidt - * tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind - with pcb->state != CLOSED - - 2011-02-17: Simon Goldschmidt - * rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in - documentation - - 2011-02-17: Simon Goldschmidt - * many files: Added missing U/UL modifiers to fix 16-bit-arch portability. - - 2011-01-24: Simon Goldschmidt - * sockets.c: Fixed bug #31741: lwip_select seems to have threading problems - - 2010-12-02: Simon Goldschmidt - * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. - - 2010-11-23: Simon Goldschmidt - * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for - LWIP_SO_RCVBUF and ioctl/FIONREAD. - - 2010-11-23: Simon Goldschmidt - * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at - least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. - - 2010-11-23: Simon Goldschmidt - * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after - refusing 'refused_data' again. - - 2010-11-22: Simon Goldschmidt - * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS - after a successful nonblocking connection. - - 2010-11-22: Simon Goldschmidt - * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr - must be sent link-local - - 2010-11-22: Simon Goldschmidt - * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for - LWIP_TIMERS==0 - - 2010-11-20: Simon Goldschmidt - * sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number - - 2010-11-20: Simon Goldschmidt - * sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to - resemble other stacks. - - 2010-11-20: Simon Goldschmidt - * dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else - no-copy TCP writes will never succeed. - - 2010-11-20: Simon Goldschmidt - * dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does - not match documentation: return ERR_ARG instead of ERR_VAL if not - initialized or wrong argument. - - 2010-10-20: Simon Goldschmidt - * sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16 - - 2010-10-05: Simon Goldschmidt - * dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when - replugging the network cable after an AutoIP address was assigned. - - 2010-08-10: Simon Goldschmidt - * tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs - - 2010-08-03: Simon Goldschmidt - * udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625) - - 2010-08-01: Simon Goldschmidt (patch by Greg Renda) - * ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big - endian architectures) - - 2010-07-28: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP - disabled. - - 2010-07-27: Simon Goldschmidt - * tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no - harm but never did anything - - 2010-07-21: Simon Goldschmidt - * ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not - add IP options) - - 2010-07-16: Kieran Mansley - * msg_in.c: Fixed SNMP ASN constant defines to not use ! operator - - 2010-07-10: Simon Goldschmidt - * ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options - - 2010-06-30: Simon Goldschmidt - * api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in - netconn_delete) - - 2010-06-28: Kieran Mansley - * timers.c remove unportable printing of C function pointers - - 2010-06-24: Simon Goldschmidt - * init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag - NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading - - 2010-06-24: Simon Goldschmidt - * api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly - implemented shutdown at socket level. - - 2010-06-21: Simon Goldschmidt - * pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has - problems with zero-copy DMA MACs) by adding custom pbufs and implementing - custom pbufs that reference other (original) pbufs. Additionally set - IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side. - - 2010-06-15: Simon Goldschmidt - * dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses - - 2010-06-14: Simon Goldschmidt - * autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses - - 2010-06-12: Simon Goldschmidt - * dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop - state - - 2010-05-17: Simon Goldschmidt - * netdb.c: Correctly NULL-terminate h_addr_list - - 2010-05-16: Simon Goldschmidt - * def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent - "symbol already defined" i.e. when linking to winsock - - 2010-05-05: Simon Goldschmidt - * def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may - overflow) - - 2010-04-21: Simon Goldschmidt - * api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening - connection) - - 2010-03-28: Luca Ceresoli - * ip_addr.c/.h: patch #7143: Add a few missing const qualifiers - - 2010-03-27: Luca Ceresoli - * mib2.c: patch #7130: remove meaningless const qualifiers - - 2010-03-26: Simon Goldschmidt - * tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too - - 2010-03-26: Simon Goldschmidt - * various files: Fixed compiling with different options disabled (TCP/UDP), - triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled - - 2010-03-25: Simon Goldschmidt - * sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly - - 2010-03-25: Simon Goldschmidt - * tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side - overrunning our rcv_wnd in ooseq case. - - 2010-03-22: Simon Goldschmidt - * tcp.c: tcp_listen() did not copy the pcb's prio. - - 2010-03-19: Simon Goldschmidt - * snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set - - 2010-03-14: Simon Goldschmidt - * opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports - where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h - and basing PBUF_LINK_HLEN on it. - - 2010-03-08: Simon Goldschmidt - * netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections - when assiging routable address): when checking incoming packets and - aborting existing connection on address change, filter out link-local - addresses. - - 2010-03-06: Simon Goldschmidt - * sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING - - 2010-03-06: Simon Goldschmidt - * ipv4/ip.c: Don't try to forward link-local addresses - - 2010-03-06: Simon Goldschmidt - * etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal- - addresses to gw - - 2010-03-05: Simon Goldschmidt - * dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type - and state. - - 2010-03-05: Simon Goldschmidt - * api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split - into multiple calls to tcp_write. - - 2010-02-21: Simon Goldschmidt - * opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep - the implementation of DNS_USES_STATIC_BUF==1) - - 2010-02-20: Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement - close() vs. shutdown(). Now the application does not get any more - recv callbacks after calling tcp_close(). Added tcp_shutdown(). - - 2010-02-19: Simon Goldschmidt - * mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent - confusion with realloc() - - 2010-02-15: Simon Goldschmidt/Stephane Lesage - * netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK - (fixes bug #28899) - - 2010-02-14: Simon Goldschmidt - * netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with - LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and - admin-status of a netif are up - - 2010-02-14: Simon Goldschmidt - * opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet - reception and is not really necessary - - 2010-02-14: Simon Goldschmidt - * etharp.c/.h: Fixed ARP input processing: only add a new entry if a - request was directed as us (RFC 826, Packet Reception), otherwise - only update existing entries; internalized some functions - - 2010-02-14: Simon Goldschmidt - * netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be - disabled on netif used for PPPoE) by adding a new netif flag - (NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet - device but prevents usage of ARP (so that ethernet_input can be used - for PPPoE). - - 2010-02-12: Simon Goldschmidt - * netif.c: netif_set_link_up/down: only do something if the link state - actually changes - - 2010-02-12: Simon Goldschmidt/Stephane Lesage - * api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking - connect) - - 2010-02-12: Simon Goldschmidt - * mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h) - - 2010-02-09: Simon Goldschmidt - * api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110 - (recv() makes receive window update for data that wasn't received by - application) - - 2010-02-09: Simon Goldschmidt/Stephane Lesage - * sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out - or any netconn_recv() error) - - 2010-02-09: Simon Goldschmidt - * ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets) - - 2010-02-09: Simon Goldschmidt - * netif.c: For loopback packets, adjust the stats- and snmp-counters - for the loopback netif. - - 2010-02-08: Simon Goldschmidt - * igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity - since they are not used anywhere else. - - 2010-02-08: Simon Goldschmidt (Stéphane Lesage) - * igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats - (patch from bug #28798) - - 2010-02-08: Simon Goldschmidt (Stéphane Lesage) - * igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and - another bug when LWIP_RAND() returns zero. - - 2010-02-04: Simon Goldschmidt - * nearly every file: Use macros defined in ip_addr.h (some of them new) - to work with IP addresses (preparation for bug #27352 - Change ip_addr - from struct to typedef (u32_t) - and better code). - - 2010-01-31: Simon Goldschmidt - * netif.c: Don't call the link-callback from netif_set_up/down() since - this invalidly retriggers DHCP. - - 2010-01-29: Simon Goldschmidt - * ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the - portability file inet.h and its contents from the stack: moved htonX- - functions to def.h (and the new def.c - they are not ipv4 dependent), - let inet.h depend on ip_addr.h and not the other way round. - This fixes bug #28732. - - 2010-01-28: Kieran Mansley - * tcp.c: Ensure ssthresh >= 2*MSS - - 2010-01-27: Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv - callback can lead to accessing unallocated memory. As a consequence, - ERR_ABRT means the application has called tcp_abort()! - - 2010-01-25: Simon Goldschmidt - * snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY - not implemented in SNMP): write-only or not-accessible are still - returned by getnext (though not by get) - - 2010-01-24: Simon Goldschmidt - * snmp: Renamed the private mib node from 'private' to 'mib_private' to - not use reserved C/C++ keywords - - 2010-01-23: Simon Goldschmidt - * sockets.c: Fixed bug #28716: select() returns 0 after waiting for less - than 1 ms - - 2010-01-21: Simon Goldschmidt - * tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called - if tcp_enqueue fails) both in raw- and netconn-API - - 2010-01-19: Simon Goldschmidt - * api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp - - 2010-01-18: Iordan Neshev/Simon Goldschmidt - * src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some - bugfix backports from 2.4.x. - - 2010-01-18: Simon Goldschmidt - * mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong - - 2010-01-17: Simon Goldschmidt - * api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c): - task #10102: "netconn: clean up conn->err threading issues" by adding - error return value to struct api_msg_msg - - 2010-01-17: Simon Goldschmidt - * api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept() - to return err_t (bugs #27709 and #28087) - - 2010-01-14: Simon Goldschmidt - * ...: Use typedef for function prototypes throughout the stack. - - 2010-01-13: Simon Goldschmidt - * api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive - window = 0) by correctly draining recvmbox/acceptmbox - - 2010-01-11: Simon Goldschmidt - * pap.c: Fixed bug #13315 (PPP PAP authentication can result in - erroneous callbacks) by copying the code from recent pppd - - 2010-01-10: Simon Goldschmidt - * raw.c: Fixed bug #28506 (raw_bind should filter received packets) - - 2010-01-10: Simon Goldschmidt - * tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)()) - - 2010-01-08: Simon Goldschmidt - * sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535) - - 2010-01-08: Simon Goldschmidt - * dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string - passed to dns_local_addhost() might be volatile - - 2010-01-07: Simon Goldschmidt - * timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too - - 2010-01-06: Simon Goldschmidt - * netdb.h: Fixed bug #28496: missing include guards in netdb.h - - 2009-12-31: Simon Goldschmidt - * many ppp files: Reorganised PPP source code from ucip structure to pppd - structure to easily compare our code against the pppd code (around v2.3.1) - - 2009-12-27: Simon Goldschmidt - * tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted - unit test - - -(STABLE-1.3.2) - - ++ New features: - - 2009-10-27 Simon Goldschmidt/Stephan Lesage - * netifapi.c/.h: Added netifapi_netif_set_addr() - - 2009-10-07 Simon Goldschmidt/Fabian Koch - * api_msg.c, netbuf.c/.h, opt.h: patch #6888: Patch for UDP Netbufs to - support dest-addr and dest-port (optional: LWIP_NETBUF_RECVINFO) - - 2009-08-26 Simon Goldschmidt/Simon Kallweit - * slipif.c/.h: bug #26397: SLIP polling support - - 2009-08-25 Simon Goldschmidt - * opt.h, etharp.h/.c: task #9033: Support IEEE 802.1q tagged frame (VLAN), - New configuration options ETHARP_SUPPORT_VLAN and ETHARP_VLAN_CHECK. - - 2009-08-25 Simon Goldschmidt - * ip_addr.h, netdb.c: patch #6900: added define ip_ntoa(struct ip_addr*) - - 2009-08-24 Jakob Stoklund Olesen - * autoip.c, dhcp.c, netif.c: patch #6725: Teach AutoIP and DHCP to respond - to netif_set_link_up(). - - 2009-08-23 Simon Goldschmidt - * tcp.h/.c: Added function tcp_debug_state_str() to convert a tcp state - to a human-readable string. - - ++ Bugfixes: - - 2009-12-24: Kieran Mansley - * tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing - (BUG#28241) - - 2009-12-06: Simon Goldschmidt - * ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can - be statically allocated (like in ucip) - - 2009-12-04: Simon Goldschmidt (patch by Ioardan Neshev) - * pap.c: patch #6969: PPP: missing PAP authentication UNTIMEOUT - - 2009-12-03: Simon Goldschmidt - * tcp.h, tcp_in.c, tcp_out.c: Fixed bug #28106: dup ack for fast retransmit - could have non-zero length - - 2009-12-02: Simon Goldschmidt - * tcp_in.c: Fixed bug #27904: TCP sends too many ACKs: delay resetting - tcp_input_pcb until after calling the pcb's callbacks - - 2009-11-29: Simon Goldschmidt - * tcp_in.c: Fixed bug #28054: Two segments with FIN flag on the out-of- - sequence queue, also fixed PBUF_POOL leak in the out-of-sequence code - - 2009-11-29: Simon Goldschmidt - * pbuf.c: Fixed bug #28064: pbuf_alloc(PBUF_POOL) is not thread-safe by - queueing a call into tcpip_thread to free ooseq-bufs if the pool is empty - - 2009-11-26: Simon Goldschmidt - * tcp.h: Fixed bug #28098: Nagle can prevent fast retransmit from sending - segment - - 2009-11-26: Simon Goldschmidt - * tcp.h, sockets.c: Fixed bug #28099: API required to disable Nagle - algorithm at PCB level - - 2009-11-22: Simon Goldschmidt - * tcp_out.c: Fixed bug #27905: FIN isn't combined with data on unsent - - 2009-11-22: Simon Goldschmidt (suggested by Bill Auerbach) - * tcp.c: tcp_alloc: prevent increasing stats.err for MEMP_TCP_PCB when - reusing time-wait pcb - - 2009-11-20: Simon Goldschmidt (patch by Albert Bartel) - * sockets.c: Fixed bug #28062: Data received directly after accepting - does not wake up select - - 2009-11-11: Simon Goldschmidt - * netdb.h: Fixed bug #27994: incorrect define for freeaddrinfo(addrinfo) - - 2009-10-30: Simon Goldschmidt - * opt.h: Increased default value for TCP_MSS to 536, updated default - value for TCP_WND to 4*TCP_MSS to keep delayed ACK working. - - 2009-10-28: Kieran Mansley - * tcp_in.c, tcp_out.c, tcp.h: re-work the fast retransmission code - to follow algorithm from TCP/IP Illustrated - - 2009-10-27: Kieran Mansley - * tcp_in.c: fix BUG#27445: grow cwnd with every duplicate ACK - - 2009-10-25: Simon Goldschmidt - * tcp.h: bug-fix in the TCP_EVENT_RECV macro (has to call tcp_recved if - pcb->recv is NULL to keep rcv_wnd correct) - - 2009-10-25: Simon Goldschmidt - * tcp_in.c: Fixed bug #26251: RST process in TIME_WAIT TCP state - - 2009-10-23: Simon Goldschmidt (David Empson) - * tcp.c: Fixed bug #27783: Silly window avoidance for small window sizes - - 2009-10-21: Simon Goldschmidt - * tcp_in.c: Fixed bug #27215: TCP sent() callback gives leading and - trailing 1 byte len (SYN/FIN) - - 2009-10-21: Simon Goldschmidt - * tcp_out.c: Fixed bug #27315: zero window probe and FIN - - 2009-10-19: Simon Goldschmidt - * dhcp.c/.h: Minor code simplification (don't store received pbuf, change - conditional code to assert where applicable), check pbuf length before - testing for valid reply - - 2009-10-19: Simon Goldschmidt - * dhcp.c: Removed most calls to udp_connect since they aren't necessary - when using udp_sendto_if() - always stay connected to IP_ADDR_ANY. - - 2009-10-16: Simon Goldschmidt - * ip.c: Fixed bug #27390: Source IP check in ip_input() causes it to drop - valid DHCP packets -> allow 0.0.0.0 as source address when LWIP_DHCP is - enabled - - 2009-10-15: Simon Goldschmidt (Oleg Tyshev) - * tcp_in.c: Fixed bug #27329: dupacks by unidirectional data transmit - - 2009-10-15: Simon Goldschmidt - * api_lib.c: Fixed bug #27709: conn->err race condition on netconn_recv() - timeout - - 2009-10-15: Simon Goldschmidt - * autoip.c: Fixed bug #27704: autoip starts with wrong address - LWIP_AUTOIP_CREATE_SEED_ADDR() returned address in host byte order instead - of network byte order - - 2009-10-11 Simon Goldschmidt (Jörg Kesten) - * tcp_out.c: Fixed bug #27504: tcp_enqueue wrongly concatenates segments - which are not consecutive when retransmitting unacked segments - - 2009-10-09 Simon Goldschmidt - * opt.h: Fixed default values of some stats to only be enabled if used - Fixes bug #27338: sys_stats is defined when NO_SYS = 1 - - 2009-08-30 Simon Goldschmidt - * ip.c: Fixed bug bug #27345: "ip_frag() does not use the LWIP_NETIF_LOOPBACK - function" by checking for loopback before calling ip_frag - - 2009-08-25 Simon Goldschmidt - * dhcp.c: fixed invalid dependency to etharp_query if DHCP_DOES_ARP_CHECK==0 - - 2009-08-23 Simon Goldschmidt - * ppp.c: bug #27078: Possible memory leak in pppInit() - - 2009-08-23 Simon Goldschmidt - * netdb.c, dns.c: bug #26657: DNS, if host name is "localhost", result - is error. - - 2009-08-23 Simon Goldschmidt - * opt.h, init.c: bug #26649: TCP fails when TCP_MSS > TCP_SND_BUF - Fixed wrong parenthesis, added check in init.c - - 2009-08-23 Simon Goldschmidt - * ppp.c: bug #27266: wait-state debug message in pppMain occurs every ms - - 2009-08-23 Simon Goldschmidt - * many ppp files: bug #27267: Added include to string.h where needed - - 2009-08-23 Simon Goldschmidt - * tcp.h: patch #6843: tcp.h macro optimization patch (for little endian) - - -(STABLE-1.3.1) - - ++ New features: - - 2009-05-10 Simon Goldschmidt - * opt.h, sockets.c, pbuf.c, netbuf.h, pbuf.h: task #7013: Added option - LWIP_NETIF_TX_SINGLE_PBUF to try to create transmit packets from only - one pbuf to help MACs that don't support scatter-gather DMA. - - 2009-05-09 Simon Goldschmidt - * icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming - ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - - 2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen - * ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive - extended info about the currently received packet. - - 2009-04-27 Simon Goldschmidt - * sys.h: Made SYS_LIGHTWEIGHT_PROT and sys_now() work with NO_SYS=1 - - 2009-04-25 Simon Goldschmidt - * mem.c, opt.h: Added option MEM_USE_POOLS_TRY_BIGGER_POOL to try the next - bigger malloc pool if one is empty (only usable with MEM_USE_POOLS). - - 2009-04-21 Simon Goldschmidt - * dns.c, init.c, dns.h, opt.h: task #7507, patch #6786: DNS supports static - hosts table. New configuration options DNS_LOCAL_HOSTLIST and - DNS_LOCAL_HOSTLIST_IS_DYNAMIC. Also, DNS_LOOKUP_LOCAL_EXTERN() can be defined - as an external function for lookup. - - 2009-04-15 Simon Goldschmidt - * dhcp.c: patch #6763: Global DHCP XID can be redefined to something more unique - - 2009-03-31 Kieran Mansley - * tcp.c, tcp_out.c, tcp_in.c, sys.h, tcp.h, opts.h: add support for - TCP timestamp options, off by default. Rework tcp_enqueue() to - take option flags rather than specified option data - - 2009-02-18 Simon Goldschmidt - * cc.h: Added printf formatter for size_t: SZT_F - - 2009-02-16 Simon Goldschmidt (patch by Rishi Khan) - * icmp.c, opt.h: patch #6539: (configurable) response to broadcast- and multicast - pings - - 2009-02-12 Simon Goldschmidt - * init.h: Added LWIP_VERSION to get the current version of the stack - - 2009-02-11 Simon Goldschmidt (suggested by Gottfried Spitaler) - * opt.h, memp.h/.c: added MEMP_MEM_MALLOC to use mem_malloc/mem_free instead - of the pool allocator (can save code size with MEM_LIBC_MALLOC if libc-malloc - is otherwise used) - - 2009-01-28 Jonathan Larmour (suggested by Bill Bauerbach) - * ipv4/inet_chksum.c, ipv4/lwip/inet_chksum.h: inet_chksum_pseudo_partial() - is only used by UDPLITE at present, so conditionalise it. - - 2008-12-03 Simon Goldschmidt (base on patch from Luca Ceresoli) - * autoip.c: checked in (slightly modified) patch #6683: Customizable AUTOIP - "seed" address. This should reduce AUTOIP conflicts if - LWIP_AUTOIP_CREATE_SEED_ADDR is overridden. - - 2008-10-02 Jonathan Larmour and Rishi Khan - * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking - socket. - - 2008-06-30 Simon Goldschmidt - * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from - interrupt context isn't safe: LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT allows - mem_free to run between mem_malloc iterations. Added illegal counter for - mem stats. - - 2008-06-27 Simon Goldschmidt - * stats.h/.c, some other files: patch #6483: stats module improvement: - Added defines to display each module's statistic individually, added stats - defines for MEM, MEMP and SYS modules, removed (unused) rexmit counter. - - 2008-06-17 Simon Goldschmidt - * err.h: patch #6459: Made err_t overridable to use a more efficient type - (define LWIP_ERR_T in cc.h) - - 2008-06-17 Simon Goldschmidt - * slipif.c: patch #6480: Added a configuration option for slipif for symmetry - to loopif - - 2008-06-17 Simon Goldschmidt (patch by Luca Ceresoli) - * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly - modified version of patch # 6370: Moved loopif code to netif.c so that - loopback traffic is supported on all netifs (all local IPs). - Added option to limit loopback packets for each netifs. - - - ++ Bugfixes: - 2009-08-12 Kieran Mansley - * tcp_in.c, tcp.c: Fix bug #27209: handle trimming of segments when - out of window or out of order properly - - 2009-08-12 Kieran Mansley - * tcp_in.c: Fix bug #27199: use snd_wl2 instead of snd_wl1 - - 2009-07-28 Simon Goldschmidt - * mem.h: Fixed bug #27105: "realloc() cannot replace mem_realloc()"s - - 2009-07-27 Kieran Mansley - * api.h api_msg.h netdb.h sockets.h: add missing #include directives - - 2009-07-09 Kieran Mansley - * api_msg.c, sockets.c, api.h: BUG23240 use signed counters for - recv_avail and don't increment counters until message successfully - sent to mbox - - 2009-06-25 Kieran Mansley - * api_msg.c api.h: BUG26722: initialise netconn write variables - in netconn_alloc - - 2009-06-25 Kieran Mansley - * tcp.h: BUG26879: set ret value in TCP_EVENT macros when function is not set - - 2009-06-25 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: BUG26301 and BUG26267: correct - simultaneous close behaviour, and make snd_nxt have the same meaning - as in the RFCs. - - 2009-05-12 Simon Goldschmidt - * etharp.h, etharp.c, netif.c: fixed bug #26507: "Gratuitous ARP depends on - arp_table / uses etharp_query" by adding etharp_gratuitous() - - 2009-05-12 Simon Goldschmidt - * ip.h, ip.c, igmp.c: bug #26487: Added ip_output_if_opt that can add IP options - to the IP header (used by igmp_ip_output_if) - - 2009-05-06 Simon Goldschmidt - * inet_chksum.c: On little endian architectures, use LWIP_PLATFORM_HTONS (if - defined) for SWAP_BYTES_IN_WORD to speed up checksumming. - - 2009-05-05 Simon Goldschmidt - * sockets.c: bug #26405: Prematurely released semaphore causes lwip_select() - to crash - - 2009-05-04 Simon Goldschmidt - * init.c: snmp was not initialized in lwip_init() - - 2009-05-04 Frédéric Bernon - * dhcp.c, netbios.c: Changes if IP_SOF_BROADCAST is enabled. - - 2009-05-03 Simon Goldschmidt - * tcp.h: bug #26349: Nagle algorithm doesn't send although segment is full - (and unsent->next == NULL) - - 2009-05-02 Simon Goldschmidt - * tcpip.h, tcpip.c: fixed tcpip_untimeout (does not need the time, broken after - 1.3.0 in CVS only) - fixes compilation of ppp_oe.c - - 2009-05-02 Simon Goldschmidt - * msg_in.c: fixed bug #25636: SNMPSET value is ignored for integer fields - - 2009-05-01 Simon Goldschmidt - * pap.c: bug #21680: PPP upap_rauthnak() drops legal NAK packets - - 2009-05-01 Simon Goldschmidt - * ppp.c: bug #24228: Memory corruption with PPP and DHCP - - 2009-04-29 Frédéric Bernon - * raw.c, udp.c, init.c, opt.h, ip.h, sockets.h: bug #26309: Implement the - SO(F)_BROADCAST filter for all API layers. Avoid the unindented reception - of broadcast packets even when this option wasn't set. Port maintainers - which want to enable this filter have to set IP_SOF_BROADCAST=1 in opt.h. - If you want this option also filter broadcast on recv operations, you also - have to set IP_SOF_BROADCAST_RECV=1 in opt.h. - - 2009-04-28 Simon Goldschmidt, Jakob Stoklund Olesen - * dhcp.c: patch #6721, bugs #25575, #25576: Some small fixes to DHCP and - DHCP/AUTOIP cooperation - - 2009-04-25 Simon Goldschmidt, Oleg Tyshev - * tcp_out.c: bug #24212: Deadlocked tcp_retransmit due to exceeded pcb->cwnd - Fixed by sorting the unsent and unacked queues (segments are inserted at the - right place in tcp_output and tcp_rexmit). - - 2009-04-25 Simon Goldschmidt - * memp.c, mem.c, memp.h, mem_std.h: bug #26213 "Problem with memory allocation - when debugging": memp_sizes contained the wrong sizes (including sanity - regions); memp pools for MEM_USE_POOLS were too small - - 2009-04-24 Simon Goldschmidt, Frédéric Bernon - * inet.c: patch #6765: Fix a small problem with the last changes (incorrect - behavior, with with ip address string not ended by a '\0', a space or a - end of line) - - 2009-04-19 Simon Goldschmidt - * rawapi.txt: Fixed bug #26069: Corrected documentation: if tcp_connect fails, - pcb->err is called, not pcb->connected (with an error code). - - 2009-04-19 Simon Goldschmidt - * tcp_out.c: Fixed bug #26236: "TCP options (timestamp) don't work with - no-copy-tcpwrite": deallocate option data, only concat segments with same flags - - 2009-04-19 Simon Goldschmidt - * tcp_out.c: Fixed bug #25094: "Zero-length pbuf" (options are now allocated - in the header pbuf, not the data pbuf) - - 2009-04-18 Simon Goldschmidt - * api_msg.c: fixed bug #25695: Segmentation fault in do_writemore() - - 2009-04-15 Simon Goldschmidt - * sockets.c: tried to fix bug #23559: lwip_recvfrom problem with tcp - - 2009-04-15 Simon Goldschmidt - * dhcp.c: task #9192: mem_free of dhcp->options_in and dhcp->msg_in - - 2009-04-15 Simon Goldschmidt - * ip.c, ip6.c, tcp_out.c, ip.h: patch #6808: Add a utility function - ip_hinted_output() (for smaller code mainly) - - 2009-04-15 Simon Goldschmidt - * inet.c: patch #6765: Supporting new line characters in inet_aton() - - 2009-04-15 Simon Goldschmidt - * dhcp.c: patch #6764: DHCP rebind and renew did not send hostnam option; - Converted constant OPTION_MAX_MSG_SIZE to netif->mtu, check if netif->mtu - is big enough in dhcp_start - - 2009-04-15 Simon Goldschmidt - * netbuf.c: bug #26027: netbuf_chain resulted in pbuf memory leak - - 2009-04-15 Simon Goldschmidt - * sockets.c, ppp.c: bug #25763: corrected 4 occurrences of SMEMCPY to MEMCPY - - 2009-04-15 Simon Goldschmidt - * sockets.c: bug #26121: set_errno can be overridden - - 2009-04-09 Kieran Mansley (patch from Luca Ceresoli ) - * init.c, opt.h: Patch#6774 TCP_QUEUE_OOSEQ breaks compilation when - LWIP_TCP==0 - - 2009-04-09 Kieran Mansley (patch from Roy Lee ) - * tcp.h: Patch#6802 Add do-while-clauses to those function like - macros in tcp.h - - 2009-03-31 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h, opt.h: Rework the way window - updates are calculated and sent (BUG20515) - - * tcp_in.c: cope with SYN packets received during established states, - and retransmission of initial SYN. - - * tcp_out.c: set push bit correctly when tcp segments are merged - - 2009-03-27 Kieran Mansley - * tcp_out.c set window correctly on probes (correcting change made - yesterday) - - 2009-03-26 Kieran Mansley - * tcp.c, tcp_in.c, tcp.h: add tcp_abandon() to cope with dropping - connections where no reset required (bug #25622) - - * tcp_out.c: set TCP_ACK flag on keepalive and zero window probes - (bug #20779) - - 2009-02-18 Simon Goldschmidt (Jonathan Larmour and Bill Auerbach) - * ip_frag.c: patch #6528: the buffer used for IP_FRAG_USES_STATIC_BUF could be - too small depending on MEM_ALIGNMENT - - 2009-02-16 Simon Goldschmidt - * sockets.h/.c, api_*.h/.c: fixed arguments of socket functions to match the standard; - converted size argument of netconn_write to 'size_t' - - 2009-02-16 Simon Goldschmidt - * tcp.h, tcp.c: fixed bug #24440: TCP connection close problem on 64-bit host - by moving accept callback function pointer to TCP_PCB_COMMON - - 2009-02-12 Simon Goldschmidt - * dhcp.c: fixed bug #25345 (DHCPDECLINE is sent with "Maximum message size" - option) - - 2009-02-11 Simon Goldschmidt - * dhcp.c: fixed bug #24480 (releasing old udp_pdb and pbuf in dhcp_start) - - 2009-02-11 Simon Goldschmidt - * opt.h, api_msg.c: added configurable default valud for netconn->recv_bufsize: - RECV_BUFSIZE_DEFAULT (fixes bug #23726: pbuf pool exhaustion on slow recv()) - - 2009-02-10 Simon Goldschmidt - * tcp.c: fixed bug #25467: Listen backlog is not reset on timeout in SYN_RCVD: - Accepts_pending is decrease on a corresponding listen pcb when a connection - in state SYN_RCVD is close. - - 2009-01-28 Jonathan Larmour - * pbuf.c: reclaim pbufs from TCP out-of-sequence segments if we run - out of pool pbufs. - - 2008-12-19 Simon Goldschmidt - * many files: patch #6699: fixed some warnings on platform where sizeof(int) == 2 - - 2008-12-10 Tamas Somogyi, Frédéric Bernon - * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and - port uses deleted netbuf. - - 2008-10-18 Simon Goldschmidt - * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length - in tcp_parseopt - - 2008-10-15 Simon Goldschmidt - * ip_frag.c: fixed bug #24517: IP reassembly crashes on unaligned IP headers - by packing the struct ip_reass_helper. - - 2008-10-03 David Woodhouse, Jonathan Larmour - * etharp.c (etharp_arp_input): Fix type aliasing problem copying ip address. - - 2008-10-02 Jonathan Larmour - * dns.c: Hard-code structure sizes, to avoid issues on some compilers where - padding is included. - - 2008-09-30 Jonathan Larmour - * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an - assertion check that addrlen isn't NULL. - - 2008-09-30 Jonathan Larmour - * tcp.c: Fix bug #24227, wrong error message in tcp_bind. - - 2008-08-26 Simon Goldschmidt - * inet.h, ip_addr.h: fixed bug #24132: Cross-dependency between ip_addr.h and - inet.h -> moved declaration of struct in_addr from ip_addr.h to inet.h - - 2008-08-14 Simon Goldschmidt - * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when - tcp_close returns != ERR_OK) - - 2008-07-08 Frédéric Bernon - * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters - in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). - - 2008-06-24 Jonathan Larmour - * tcp_in.c: Fix for bug #23693 as suggested by Art R. Ensure cseg is unused - if tcp_seg_copy fails. - - 2008-06-17 Simon Goldschmidt - * inet_chksum.c: Checked in some ideas of patch #6460 (loop optimizations) - and created defines for swapping bytes and folding u32 to u16. - - 2008-05-30 Kieran Mansley - * tcp_in.c Remove redundant "if" statement, and use real rcv_wnd - rather than rcv_ann_wnd when deciding if packets are in-window. - Contributed by - - 2008-05-30 Kieran Mansley - * mem.h: Fix BUG#23254. Change macro definition of mem_* to allow - passing as function pointers when MEM_LIBC_MALLOC is defined. - - 2008-05-09 Jonathan Larmour - * err.h, err.c, sockets.c: Fix bug #23119: Reorder timeout error code to - stop it being treated as a fatal error. - - 2008-04-15 Simon Goldschmidt - * dhcp.c: fixed bug #22804: dhcp_stop doesn't clear NETIF_FLAG_DHCP - (flag now cleared) - - 2008-03-27 Simon Goldschmidt - * mem.c, tcpip.c, tcpip.h, opt.h: fixed bug #21433 (Calling mem_free/pbuf_free - from interrupt context isn't safe): set LWIP_USE_HEAP_FROM_INTERRUPT to 1 - in lwipopts.h or use pbuf_free_callback(p)/mem_free_callback(m) to free pbufs - or heap memory from interrupt context - - 2008-03-26 Simon Goldschmidt - * tcp_in.c, tcp.c: fixed bug #22249: division by zero could occur if a remote - host sent a zero mss as TCP option. - - -(STABLE-1.3.0) - - ++ New features: - - 2008-03-10 Jonathan Larmour - * inet_chksum.c: Allow choice of one of the sample algorithms to be - made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM. - - 2008-01-22 Frédéric Bernon - * tcp.c, tcp_in.c, tcp.h, opt.h: Rename LWIP_CALCULATE_EFF_SEND_MSS in - TCP_CALCULATE_EFF_SEND_MSS to have coherent TCP options names. - - 2008-01-14 Frédéric Bernon - * rawapi.txt, api_msg.c, tcp.c, tcp_in.c, tcp.h: changes for task #7675 "Enable - to refuse data on a TCP_EVENT_RECV call". Important, behavior changes for the - tcp_recv callback (see rawapi.txt). - - 2008-01-14 Frédéric Bernon, Marc Chaland - * ip.c: Integrate patch #6369" ip_input : checking before realloc". - - 2008-01-12 Frédéric Bernon - * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field - netconn::sem per netconn::op_completed like suggested for the task #7490 - "Add return value to sys_mbox_post". - - 2008-01-12 Frédéric Bernon - * api_msg.c, opt.h: replace DEFAULT_RECVMBOX_SIZE per DEFAULT_TCP_RECVMBOX_SIZE, - DEFAULT_UDP_RECVMBOX_SIZE and DEFAULT_RAW_RECVMBOX_SIZE (to optimize queues - sizes), like suggested for the task #7490 "Add return value to sys_mbox_post". - - 2008-01-10 Frédéric Bernon - * tcpip.h, tcpip.c: add tcpip_callback_with_block function for the task #7490 - "Add return value to sys_mbox_post". tcpip_callback is always defined as - "blocking" ("block" parameter = 1). - - 2008-01-10 Frédéric Bernon - * tcpip.h, tcpip.c, api.h, api_lib.c, api_msg.c, sockets.c: replace the field - netconn::mbox (sys_mbox_t) per netconn::sem (sys_sem_t) for the task #7490 - "Add return value to sys_mbox_post". - - 2008-01-05 Frédéric Bernon - * sys_arch.txt, api.h, api_lib.c, api_msg.h, api_msg.c, tcpip.c, sys.h, opt.h: - Introduce changes for task #7490 "Add return value to sys_mbox_post" with some - modifications in the sys_mbox api: sys_mbox_new take a "size" parameters which - indicate the number of pointers query by the mailbox. There is three defines - in opt.h to indicate sizes for tcpip::mbox, netconn::recvmbox, and for the - netconn::acceptmbox. Port maintainers, you can decide to just add this new - parameter in your implementation, but to ignore it to keep the previous behavior. - The new sys_mbox_trypost function return a value to know if the mailbox is - full or if the message is posted. Take a look to sys_arch.txt for more details. - This new function is used in tcpip_input (so, can be called in an interrupt - context since the function is not blocking), and in recv_udp and recv_raw. - - 2008-01-04 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour - * rawapi.txt, api.h, api_lib.c, api_msg.h, api_msg.c, sockets.c, tcp.h, tcp.c, - tcp_in.c, init.c, opt.h: rename backlog options with TCP_ prefix, limit the - "backlog" parameter in an u8_t, 0 is interpreted as "smallest queue", add - documentation in the rawapi.txt file. - - 2007-12-31 Kieran Mansley (based on patch from Per-Henrik Lundbolm) - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Add TCP persist timer - - 2007-12-31 Frédéric Bernon, Luca Ceresoli - * autoip.c, etharp.c: ip_addr.h: Integrate patch #6348: "Broadcast ARP packets - in autoip". The change in etharp_raw could be removed, since all calls to - etharp_raw use ethbroadcast for the "ethdst_addr" parameter. But it could be - wrong in the future. - - 2007-12-30 Frédéric Bernon, Tom Evans - * ip.c: Fix bug #21846 "LwIP doesn't appear to perform any IP Source Address - Filtering" reported by Tom Evans. - - 2007-12-21 Frédéric Bernon, Simon Goldschmidt, Jonathan Larmour - * tcp.h, opt.h, api.h, api_msg.h, tcp.c, tcp_in.c, api_lib.c, api_msg.c, - sockets.c, init.c: task #7252: Implement TCP listen backlog: Warning: raw API - applications have to call 'tcp_accepted(pcb)' in their accept callback to - keep accepting new connections. - - 2007-12-13 Frédéric Bernon - * api_msg.c, err.h, err.c, sockets.c, dns.c, dns.h: replace "enum dns_result" - by err_t type. Add a new err_t code "ERR_INPROGRESS". - - 2007-12-12 Frédéric Bernon - * dns.h, dns.c, opt.h: move DNS options to the "right" place. Most visibles - are the one which have ram usage. - - 2007-12-05 Frédéric Bernon - * netdb.c: add a LWIP_DNS_API_HOSTENT_STORAGE option to decide to use a static - set of variables (=0) or a local one (=1). In this last case, your port should - provide a function "struct hostent* sys_thread_hostent( struct hostent* h)" - which have to do a copy of "h" and return a pointer ont the "per-thread" copy. - - 2007-12-03 Simon Goldschmidt - * ip.c: ip_input: check if a packet is for inp first before checking all other - netifs on netif_list (speeds up packet receiving in most cases) - - 2007-11-30 Simon Goldschmidt - * udp.c, raw.c: task #7497: Sort lists (pcb, netif, ...) for faster access - UDP: move a (connected) pcb selected for input to the front of the list of - pcbs so that it is found faster next time. Same for RAW pcbs that have eaten - a packet. - - 2007-11-28 Simon Goldschmidt - * etharp.c, stats.c, stats.h, opt.h: Introduced ETHARP_STATS - - 2007-11-25 Simon Goldschmidt - * dhcp.c: dhcp_unfold_reply() uses pbuf_copy_partial instead of its own copy - algorithm. - - 2007-11-24 Simon Goldschmidt - * netdb.h, netdb.c, sockets.h/.c: Moved lwip_gethostbyname from sockets.c - to the new file netdb.c; included lwip_getaddrinfo. - - 2007-11-21 Simon Goldschmidt - * tcp.h, opt.h, tcp.c, tcp_in.c: implemented calculating the effective send-mss - based on the MTU of the netif used to send. Enabled by default. Disable by - setting LWIP_CALCULATE_EFF_SEND_MSS to 0. This fixes bug #21492. - - 2007-11-19 Frédéric Bernon - * api_msg.c, dns.h, dns.c: Implement DNS_DOES_NAME_CHECK option (check if name - received match the name query), implement DNS_USES_STATIC_BUF (the place where - copy dns payload to parse the response), return an error if there is no place - for a new query, and fix some minor problems. - - 2007-11-16 Simon Goldschmidt - * new files: ipv4/inet.c, ipv4/inet_chksum.c, ipv6/inet6.c - removed files: core/inet.c, core/inet6.c - Moved inet files into ipv4/ipv6 directory; splitted inet.c/inet.h into - inet and chksum part; changed includes in all lwIP files as appropriate - - 2007-11-16 Simon Goldschmidt - * api.h, api_msg.h, api_lib.c, api_msg.c, socket.h, socket.c: Added sequential - dns resolver function for netconn api (netconn_gethostbyname) and socket api - (gethostbyname/gethostbyname_r). - - 2007-11-15 Jim Pettinato, Frédéric Bernon - * opt.h, init.c, tcpip.c, dhcp.c, dns.h, dns.c: add DNS client for simple name - requests with RAW api interface. Initialization is done in lwip_init() with - build time options. DNS timer is added in tcpip_thread context. DHCP can set - DNS server ip addresses when options are received. You need to set LWIP_DNS=1 - in your lwipopts.h file (LWIP_DNS=0 in opt.h). DNS_DEBUG can be set to get - some traces with LWIP_DEBUGF. Sanity check have been added. There is a "todo" - list with points to improve. - - 2007-11-06 Simon Goldschmidt - * opt.h, mib2.c: Patch #6215: added ifAdminStatus write support (if explicitly - enabled by defining SNMP_SAFE_REQUESTS to 0); added code to check link status - for ifOperStatus if LWIP_NETIF_LINK_CALLBACK is defined. - - 2007-11-06 Simon Goldschmidt - * api.h, api_msg.h and dependent files: Task #7410: Removed the need to include - core header files in api.h (ip/tcp/udp/raw.h) to hide the internal - implementation from netconn api applications. - - 2007-11-03 Frédéric Bernon - * api.h, api_lib.c, api_msg.c, sockets.c, opt.h: add SO_RCVBUF option for UDP & - RAW netconn. You need to set LWIP_SO_RCVBUF=1 in your lwipopts.h (it's disabled - by default). Netconn API users can use the netconn_recv_bufsize macro to access - it. This is a first release which have to be improve for TCP. Note it used the - netconn::recv_avail which need to be more "thread-safe" (note there is already - the problem for FIONREAD with lwip_ioctl/ioctlsocket). - - 2007-11-01 Frédéric Bernon, Marc Chaland - * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, tcp.h, tcp_out.c: - Integrate "patch #6250 : MSG_MORE flag for send". MSG_MORE is used at socket api - layer, NETCONN_MORE at netconn api layer, and TCP_WRITE_FLAG_MORE at raw api - layer. This option enable to delayed TCP PUSH flag on multiple "write" calls. - Note that previous "copy" parameter for "write" APIs is now called "apiflags". - - 2007-10-24 Frédéric Bernon - * api.h, api_lib.c, api_msg.c: Add macro API_EVENT in the same spirit than - TCP_EVENT_xxx macros to get a code more readable. It could also help to remove - some code (like we have talk in "patch #5919 : Create compile switch to remove - select code"), but it could be done later. - - 2007-10-08 Simon Goldschmidt - * many files: Changed initialization: many init functions are not needed any - more since we now rely on the compiler initializing global and static - variables to zero! - - 2007-10-06 Simon Goldschmidt - * ip_frag.c, memp.c, mib2.c, ip_frag.h, memp_std.h, opt.h: Changed IP_REASSEMBLY - to enqueue the received pbufs so that multiple packets can be reassembled - simultaneously and no static reassembly buffer is needed. - - 2007-10-05 Simon Goldschmidt - * tcpip.c, etharp.h, etharp.c: moved ethernet_input from tcpip.c to etharp.c so - all netifs (or ports) can use it. - - 2007-10-05 Frédéric Bernon - * netifapi.h, netifapi.c: add function netifapi_netif_set_default. Change the - common function to reduce a little bit the footprint (for all functions using - only the "netif" parameter). - - 2007-10-03 Frédéric Bernon - * netifapi.h, netifapi.c: add functions netifapi_netif_set_up, netifapi_netif_set_down, - netifapi_autoip_start and netifapi_autoip_stop. Use a common function to reduce - a little bit the footprint (for all functions using only the "netif" parameter). - - 2007-09-15 Frédéric Bernon - * udp.h, udp.c, sockets.c: Changes for "#20503 IGMP Improvement". Add IP_MULTICAST_IF - option in socket API, and a new field "multicast_ip" in "struct udp_pcb" (for - netconn and raw API users), only if LWIP_IGMP=1. Add getsockopt processing for - IP_MULTICAST_TTL and IP_MULTICAST_IF. - - 2007-09-10 Frédéric Bernon - * snmp.h, mib2.c: enable to remove SNMP timer (which consumne several cycles - even when it's not necessary). snmp_agent.txt tell to call snmp_inc_sysuptime() - each 10ms (but, it's intrusive if you use sys_timeout feature). Now, you can - decide to call snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but - call to a lower frequency). Or, you can decide to not call snmp_inc_sysuptime() - or snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro. - This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside - snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only - when it's queried (any direct call to "sysuptime" is changed by a call to - snmp_get_sysuptime). - - 2007-09-09 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, netif.h, netif.c, ip.c: To enable to have interfaces with IGMP, - and others without it, there is a new NETIF_FLAG_IGMP flag to set in netif->flags - if you want IGMP on an interface. igmp_stop() is now called inside netif_remove(). - igmp_report_groups() is now called inside netif_set_link_up() (need to have - LWIP_NETIF_LINK_CALLBACK=1) to resend reports once the link is up (avoid to wait - the next query message to receive the matching multicast streams). - - 2007-09-08 Frédéric Bernon - * sockets.c, ip.h, api.h, tcp.h: declare a "struct ip_pcb" which only contains - IP_PCB. Add in the netconn's "pcb" union a "struct ip_pcb *ip;" (no size change). - Use this new field to access to common pcb fields (ttl, tos, so_options, etc...). - Enable to access to these fields with LWIP_TCP=0. - - 2007-09-05 Frédéric Bernon - * udp.c, ipv4/icmp.c, ipv4/ip.c, ipv6/icmp.c, ipv6/ip6.c, ipv4/icmp.h, - ipv6/icmp.h, opt.h: Integrate "task #7272 : LWIP_ICMP option". The new option - LWIP_ICMP enable/disable ICMP module inside the IP stack (enable per default). - Be careful, disabling ICMP make your product non-compliant to RFC1122, but - help to reduce footprint, and to reduce "visibility" on the Internet. - - 2007-09-05 Frédéric Bernon, Bill Florac - * opt.h, sys.h, tcpip.c, slipif.c, ppp.c, sys_arch.txt: Change parameters list - for sys_thread_new (see "task #7252 : Create sys_thread_new_ex()"). Two new - parameters have to be provided: a task name, and a task stack size. For this - one, since it's platform dependant, you could define the best one for you in - your lwipopts.h. For port maintainers, you can just add these new parameters - in your sys_arch.c file, and but it's not mandatory, use them in your OS - specific functions. - - 2007-09-05 Frédéric Bernon - * inet.c, autoip.c, msg_in.c, msg_out.c, init.c: Move some build time checkings - inside init.c for task #7142 "Sanity check user-configurable values". - - 2007-09-04 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, memp_std.h, memp.c, init.c, opt.h: Replace mem_malloc call by - memp_malloc, and use a new MEMP_NUM_IGMP_GROUP option (see opt.h to define the - value). It will avoid potential fragmentation problems, use a counter to know - how many times a group is used on an netif, and free it when all applications - leave it. MEMP_NUM_IGMP_GROUP got 8 as default value (and init.c got a sanity - check if LWIP_IGMP!=0). - - 2007-09-03 Frédéric Bernon - * igmp.h, igmp.c, sockets.c, api_msg.c: Changes for "#20503 IGMP Improvement". - Initialize igmp_mac_filter to NULL in netif_add (this field should be set in - the netif's "init" function). Use the "imr_interface" field (for socket layer) - and/or the "interface" field (for netconn layer), for join/leave operations. - The igmp_join/leavegroup first parameter change from a netif to an ipaddr. - This field could be a netif's ipaddr, or "any" (same meaning than ip_addr_isany). - - 2007-08-30 Frédéric Bernon - * Add netbuf.h, netbuf.c, Change api.h, api_lib.c: #7249 "Split netbuf functions - from api/api_lib". Now netbuf API is independant of netconn, and can be used - with other API (application based on raw API, or future "socket2" API). Ports - maintainers just have to add src/api/netbuf.c in their makefile/projects. - - 2007-08-30 Frédéric Bernon, Jonathan Larmour - * init.c: Add first version of lwip_sanity_check for task #7142 "Sanity check - user-configurable values". - - 2007-08-29 Frédéric Bernon - * igmp.h, igmp.c, tcpip.c, init.c, netif.c: change igmp_init and add igmp_start. - igmp_start is call inside netif_add. Now, igmp initialization is in the same - spirit than the others modules. Modify some IGMP debug traces. - - 2007-08-29 Frédéric Bernon - * Add init.h, init.c, Change opt.h, tcpip.c: Task #7213 "Add a lwip_init function" - Add lwip_init function to regroup all modules initializations, and to provide - a place to add code for task #7142 "Sanity check user-configurable values". - Ports maintainers should remove direct initializations calls from their code, - and add init.c in their makefiles. Note that lwip_init() function is called - inside tcpip_init, but can also be used by raw api users since all calls are - disabled when matching options are disabled. Also note that their is new options - in opt.h, you should configure in your lwipopts.h (they are enabled per default). - - 2007-08-26 Marc Boucher - * api_msg.c: do_close_internal(): Reset the callbacks and arg (conn) to NULL - since they can under certain circumstances be called with an invalid conn - pointer after the connection has been closed (and conn has been freed). - - 2007-08-25 Frédéric Bernon (Artem Migaev's Patch) - * netif.h, netif.c: Integrate "patch #6163 : Function to check if link layer is up". - Add a netif_is_link_up() function if LWIP_NETIF_LINK_CALLBACK option is set. - - 2007-08-22 Frédéric Bernon - * netif.h, netif.c, opt.h: Rename LWIP_NETIF_CALLBACK in LWIP_NETIF_STATUS_CALLBACK - to be coherent with new LWIP_NETIF_LINK_CALLBACK option before next release. - - 2007-08-22 Frédéric Bernon - * tcpip.h, tcpip.c, ethernetif.c, opt.h: remove options ETHARP_TCPIP_INPUT & - ETHARP_TCPIP_ETHINPUT, now, only "ethinput" code is supported, even if the - name is tcpip_input (we keep the name of 1.2.0 function). - - 2007-08-17 Jared Grubb - * memp_std.h, memp.h, memp.c, mem.c, stats.c: (Task #7136) Centralize mempool - settings into new memp_std.h and optional user file lwippools.h. This adds - more dynamic mempools, and allows the user to create an arbitrary number of - mempools for mem_malloc. - - 2007-08-16 Marc Boucher - * api_msg.c: Initialize newconn->state to NETCONN_NONE in accept_function; - otherwise it was left to NETCONN_CLOSE and sent_tcp() could prematurely - close the connection. - - 2007-08-16 Marc Boucher - * sockets.c: lwip_accept(): check netconn_peer() error return. - - 2007-08-16 Marc Boucher - * mem.c, mem.h: Added mem_calloc(). - - 2007-08-16 Marc Boucher - * tcpip.c, tcpip.h memp.c, memp.h: Added distinct memp (MEMP_TCPIP_MSG_INPKT) - for input packets to prevent floods from consuming all of MEMP_TCPIP_MSG - and starving other message types. - Renamed MEMP_TCPIP_MSG to MEMP_TCPIP_MSG_API - - 2007-08-16 Marc Boucher - * pbuf.c, pbuf.h, etharp.c, tcp_in.c, sockets.c: Split pbuf flags in pbuf - type and flgs (later renamed to flags). - Use enum pbuf_flag as pbuf_type. Renumber PBUF_FLAG_*. - Improved lwip_recvfrom(). TCP push now propagated. - - 2007-08-16 Marc Boucher - * ethernetif.c, contrib/ports/various: ethbroadcast now a shared global - provided by etharp. - - 2007-08-16 Marc Boucher - * ppp_oe.c ppp_oe.h, auth.c chap.c fsm.c lcp.c ppp.c ppp.h, - etharp.c ethernetif.c, etharp.h, opt.h tcpip.h, tcpip.c: - Added PPPoE support and various PPP improvements. - - 2007-07-25 Simon Goldschmidt - * api_lib.c, ip_frag.c, pbuf.c, api.h, pbuf.h: Introduced pbuf_copy_partial, - making netbuf_copy_partial use this function. - - 2007-07-25 Simon Goldschmidt - * tcp_in.c: Fix bug #20506: Slow start / initial congestion window starts with - 2 * mss (instead of 1 * mss previously) to comply with some newer RFCs and - other stacks. - - 2007-07-13 Jared Grubb (integrated by Frédéric Bernon) - * opt.h, netif.h, netif.c, ethernetif.c: Add new configuration option to add - a link callback in the netif struct, and functions to handle it. Be carefull - for port maintainers to add the NETIF_FLAG_LINK_UP flag (like in ethernetif.c) - if you want to be sure to be compatible with future changes... - - 2007-06-30 Frédéric Bernon - * sockets.h, sockets.c: Implement MSG_PEEK flag for recv/recvfrom functions. - - 2007-06-21 Simon Goldschmidt - * etharp.h, etharp.c: Combined etharp_request with etharp_raw for both - LWIP_AUTOIP =0 and =1 to remove redundant code. - - 2007-06-21 Simon Goldschmidt - * mem.c, memp.c, mem.h, memp.h, opt.h: task #6863: Introduced the option - MEM_USE_POOLS to use 4 pools with different sized elements instead of a - heap. This both prevents memory fragmentation and gives a higher speed - at the cost of more memory consumption. Turned off by default. - - 2007-06-21 Simon Goldschmidt - * api_lib.c, api_msg.c, api.h, api_msg.h: Converted the length argument of - netconn_write (and therefore also api_msg_msg.msg.w.len) from u16_t into - int to be able to send a bigger buffer than 64K with one time (mainly - used from lwip_send). - - 2007-06-21 Simon Goldschmidt - * tcp.h, api_msg.c: Moved the nagle algorithm from netconn_write/do_write - into a define (tcp_output_nagle) in tcp.h to provide it to raw api users, too. - - 2007-06-21 Simon Goldschmidt - * api.h, api_lib.c, api_msg.c: Fixed bug #20021: Moved sendbuf-processing in - netconn_write from api_lib.c to api_msg.c to also prevent multiple context- - changes on low memory or empty send-buffer. - - 2007-06-18 Simon Goldschmidt - * etharp.c, etharp.h: Changed etharp to use a defined hardware address length - of 6 to avoid loading netif->hwaddr_len every time (since this file is only - used for ethernet and struct eth_addr already had a defined length of 6). - - 2007-06-17 Simon Goldschmidt - * sockets.c, sockets.h: Implemented socket options SO_NO_CHECK for UDP sockets - to disable UDP checksum generation on transmit. - - 2007-06-13 Frédéric Bernon, Simon Goldschmidt - * debug.h, api_msg.c: change LWIP_ERROR to use it to check errors like invalid - pointers or parameters, and let the possibility to redefined it in cc.h. Use - this macro to check "conn" parameter in api_msg.c functions. - - 2007-06-11 Simon Goldschmidt - * sockets.c, sockets.h: Added UDP lite support for sockets - - 2007-06-10 Simon Goldschmidt - * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled - by default) to switch off UDP-Lite support if not needed (reduces udp.c code - size) - - 2007-06-09 Dominik Spies (integrated by Frédéric Bernon) - * autoip.h, autoip.c, dhcp.h, dhcp.c, netif.h, netif.c, etharp.h, etharp.c, opt.h: - AutoIP implementation available for IPv4, with new options LWIP_AUTOIP and - LWIP_DHCP_AUTOIP_COOP if you want to cooperate with DHCP. Some tips to adapt - (see TODO mark in the source code). - - 2007-06-09 Simon Goldschmidt - * etharp.h, etharp.c, ethernetif.c: Modified order of parameters for - etharp_output() to match netif->output so etharp_output() can be used - directly as netif->output to save one function call. - - 2007-06-08 Simon Goldschmidt - * netif.h, ethernetif.c, slipif.c, loopif.c: Added define - NETIF_INIT_SNMP(netif, type, speed) to initialize per-netif snmp variables, - added initialization of those to ethernetif, slipif and loopif. - - 2007-05-18 Simon Goldschmidt - * opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF - (defaulting to off for now) that can be set to 0 to send fragmented - packets by passing PBUF_REFs down the stack. - - 2007-05-23 Frédéric Bernon - * api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP - connections, such present in patch #5959. - - 2007-05-23 Frédéric Bernon - * api.h, api_lib.c, api_msg.c, sockets.c: group the different NETCONN_UDPxxx - code in only one part... - - 2007-05-18 Simon Goldschmidt - * opt.h, memp.h, memp.c: Added option MEMP_OVERFLOW_CHECK to check for memp - elements to overflow. This is achieved by adding some bytes before and after - each pool element (increasing their size, of course), filling them with a - prominent value and checking them on freeing the element. - Set it to 2 to also check every element in every pool each time memp_malloc() - or memp_free() is called (slower but more helpful). - - 2007-05-10 Simon Goldschmidt - * opt.h, memp.h, memp.c, pbuf.c (see task #6831): use a new memp pool for - PBUF_POOL pbufs instead of the old pool implementation in pbuf.c to reduce - code size. - - 2007-05-11 Frédéric Bernon - * sockets.c, api_lib.c, api_msg.h, api_msg.c, netifapi.h, netifapi.c, tcpip.c: - Include a function pointer instead of a table index in the message to reduce - footprint. Disable some part of lwip_send and lwip_sendto if some options are - not set (LWIP_TCP, LWIP_UDP, LWIP_RAW). - - 2007-05-10 Simon Goldschmidt - * *.h (except netif/ppp/*.h): Included patch #5448: include '#ifdef __cplusplus - \ extern "C" {' in all header files. Now you can write your application using - the lwIP stack in C++ and simply #include the core files. Note I have left - out the netif/ppp/*h header files for now, since I don't know which files are - included by applications and which are for internal use only. - - 2007-05-09 Simon Goldschmidt - * opt.h, *.c/*.h: Included patch #5920: Create define to override C-library - memcpy. 2 Defines are created: MEMCPY() for normal memcpy, SMEMCPY() for - situations where some compilers might inline the copy and save a function - call. Also replaced all calls to memcpy() with calls to (S)MEMCPY(). - - 2007-05-08 Simon Goldschmidt - * mem.h: If MEM_LIBC_MALLOC==1, allow the defines (e.g. mem_malloc() -> malloc()) - to be overriden in case the C-library malloc implementation is not protected - against concurrent access. - - 2007-05-04 Simon Goldschmidt (Atte Kojo) - * etharp.c: Introduced fast one-entry-cache to speed up ARP lookup when sending - multiple packets to the same host. - - 2007-05-04 Frédéric Bernon, Jonathan Larmour - * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible - to corrupt remote addr/port connection state". Reduce problems "not enought memory" with - netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between - sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. - Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct, - these fields are now renamed "addr" & "port". - - 2007-04-11 Jonathan Larmour - * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new - sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return - with SYS_MBOX_EMPTY. sys_arch_mbox_tryfetch can be implemented as a function-like macro - by the port in sys_arch.h if desired. - - 2007-04-06 Frédéric Bernon, Simon Goldschmidt - * opt.h, tcpip.h, tcpip.c, netifapi.h, netifapi.c: New configuration option LWIP_NETIF_API - allow to use thread-safe functions to add/remove netif in list, and to start/stop dhcp - clients, using new functions from netifapi.h. Disable as default (no port change to do). - - 2007-04-05 Frédéric Bernon - * sockets.c: remplace ENOBUFS errors on alloc_socket by ENFILE to be more BSD compliant. - - 2007-04-04 Simon Goldschmidt - * arch.h, api_msg.c, dhcp.c, msg_in.c, sockets.c: Introduced #define LWIP_UNUSED_ARG(x) - use this for and architecture-independent form to tell the compiler you intentionally - are not using this variable. Can be overriden in cc.h. - - 2007-03-28 Frédéric Bernon - * opt.h, netif.h, dhcp.h, dhcp.c: New configuration option LWIP_NETIF_HOSTNAME allow to - define a hostname in netif struct (this is just a pointer, so, you can use a hardcoded - string, point on one of your's ethernetif field, or alloc a string you will free yourself). - It will be used by DHCP to register a client hostname, but can also be use when you call - snmp_set_sysname. - - 2007-03-28 Frédéric Bernon - * netif.h, netif.c: A new NETIF_FLAG_ETHARP flag is defined in netif.h, to allow to - initialize a network interface's flag with. It tell this interface is an ethernet - device, and we can use ARP with it to do a "gratuitous ARP" (RFC 3220 "IP Mobility - Support for IPv4" section 4.6) when interface is "up" with netif_set_up(). - - 2007-03-26 Frédéric Bernon, Jonathan Larmour - * opt.h, tcpip.c: New configuration option LWIP_ARP allow to disable ARP init at build - time if you only use PPP or SLIP. The default is enable. Note we don't have to call - etharp_init in your port's initilization sequence if you use tcpip.c, because this call - is done in tcpip_init function. - - 2007-03-22 Frédéric Bernon - * stats.h, stats.c, msg_in.c: Stats counters can be change to u32_t if necessary with the - new option LWIP_STATS_LARGE. If you need this option, define LWIP_STATS_LARGE to 1 in - your lwipopts.h. More, unused counters are not defined in the stats structs, and not - display by stats_display(). Note that some options (SYS_STATS and RAW_STATS) are defined - but never used. Fix msg_in.c with the correct #if test for a stat display. - - 2007-03-21 Kieran Mansley - * netif.c, netif.h: Apply patch#4197 with some changes (originator: rireland@hmgsl.com). - Provides callback on netif up/down state change. - - 2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds - * sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c, - ip.c, netif.h, tcpip.c, opt.h: - New configuration option LWIP_IGMP to enable IGMP processing. Based on only one - filter per all network interfaces. Declare a new function in netif to enable to - control the MAC filter (to reduce lwIP traffic processing). - - 2007-03-11 Frédéric Bernon - * tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can - be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this - unless you know what you're doing (default are RFC1122 compliant). Note - that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set in seconds. - - 2007-03-08 Frédéric Bernon - * tcp.h: Keepalive values can be configured at compile time, but don't change - this unless you know what you're doing (default are RFC1122 compliant). - - 2007-03-08 Frédéric Bernon - * sockets.c, api.h, api_lib.c, tcpip.c, sys.h, sys.c, err.c, opt.h: - Implement LWIP_SO_RCVTIMEO configuration option to enable/disable SO_RCVTIMEO - on UDP sockets/netconn. - - 2007-03-08 Simon Goldschmidt - * snmp_msg.h, msg_in.c: SNMP UDP ports can be configured at compile time. - - 2007-03-06 Frédéric Bernon - * api.h, api_lib.c, sockets.h, sockets.c, tcpip.c, sys.h, sys.c, err.h: - Implement SO_RCVTIMEO on UDP sockets/netconn. - - 2007-02-28 Kieran Mansley (based on patch from Simon Goldschmidt) - * api_lib.c, tcpip.c, memp.c, memp.h: make API msg structs allocated - on the stack and remove the API msg type from memp - - 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) - * sockets.h, sockets.c: Move socket initialization to new - lwip_socket_init() function. - NOTE: this changes the API with ports. Ports will have to be - updated to call lwip_socket_init() now. - - 2007-02-26 Jonathan Larmour (based on patch from Simon Goldschmidt) - * api_lib.c: Use memcpy in netbuf_copy_partial. - - - ++ Bug fixes: - - 2008-03-17 Frédéric Bernon, Ed Kerekes - * igmp.h, igmp.c: Fix bug #22613 "IGMP iphdr problem" (could have - some problems to fill the IP header on some targets, use now the - ip.h macros to do it). - - 2008-03-13 Frédéric Bernon - * sockets.c: Fix bug #22435 "lwip_recvfrom with TCP break;". Using - (lwip_)recvfrom with valid "from" and "fromlen" parameters, on a - TCP connection caused a crash. Note that using (lwip_)recvfrom - like this is a bit slow and that using (lwip)getpeername is the - good lwip way to do it (so, using recv is faster on tcp sockets). - - 2008-03-12 Frédéric Bernon, Jonathan Larmour - * api_msg.c, contrib/apps/ping.c: Fix bug #22530 "api_msg.c's - recv_raw() does not consume data", and the ping sample (with - LWIP_SOCKET=1, the code did the wrong supposition that lwip_recvfrom - returned the IP payload, without the IP header). - - 2008-03-04 Jonathan Larmour - * mem.c, stats.c, mem.h: apply patch #6414 to avoid compiler errors - and/or warnings on some systems where mem_size_t and size_t differ. - * pbuf.c, ppp.c: Fix warnings on some systems with mem_malloc. - - 2008-03-04 Kieran Mansley (contributions by others) - * Numerous small compiler error/warning fixes from contributions to - mailing list after 1.3.0 release candidate made. - - 2008-01-25 Cui hengbin (integrated by Frédéric Bernon) - * dns.c: Fix bug #22108 "DNS problem" caused by unaligned structures. - - 2008-01-15 Kieran Mansley - * tcp_out.c: BUG20511. Modify persist timer to start when we are - prevented from sending by a small send window, not just a zero - send window. - - 2008-01-09 Jonathan Larmour - * opt.h, ip.c: Rename IP_OPTIONS define to IP_OPTIONS_ALLOWED to avoid - conflict with Linux system headers. - - 2008-01-06 Jonathan Larmour - * dhcp.c: fix bug #19927: "DHCP NACK problem" by clearing any existing set IP - address entirely on receiving a DHCPNAK, and restarting discovery. - - 2007-12-21 Simon Goldschmidt - * sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail - is not protected" by using new macros for interlocked access to modify/test - netconn->recv_avail. - - 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) - * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state) - - 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling - of silly window avoidance and prevent lwIP from shrinking the window) - - 2007-12-04 Simon Goldschmidt - * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last - data packet was lost): add assert that all segment lists are empty in - tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED - state from LAST_ACK in tcp_process - - 2007-12-02 Simon Goldschmidt - * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET - If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now - has to be set to 0 in lwipopts.h - - 2007-12-02 Simon Goldschmidt - * api_msg.c, api_lib.c: fix bug #21656 (recvmbox problem in netconn API): always - allocate a recvmbox in netconn_new_with_proto_and_callback. For a tcp-listen - netconn, this recvmbox is later freed and a new mbox is allocated for acceptmbox. - This is a fix for thread-safety and allocates all items needed for a netconn - when the netconn is created. - - 2007-11-30 Simon Goldschmidt - * udp.c: first attempt to fix bug #21655 (DHCP doesn't work reliably with multiple - netifs): if LWIP_DHCP is enabled, UDP packets to DHCP_CLIENT_PORT are passed - to netif->dhcp->pcb only (if that exists) and not to any other pcb for the same - port (only solution to let UDP pcbs 'bind' to a netif instead of an IP address) - - 2007-11-27 Simon Goldschmidt - * ip.c: fixed bug #21643 (udp_send/raw_send don't fail if netif is down) by - letting ip_route only use netifs that are up. - - 2007-11-27 Simon Goldschmidt - * err.h, api_lib.c, api_msg.c, sockets.c: Changed error handling: ERR_MEM, ERR_BUF - and ERR_RTE are seen as non-fatal, all other errors are fatal. netconns and - sockets block most operations once they have seen a fatal error. - - 2007-11-27 Simon Goldschmidt - * udp.h, udp.c, dhcp.c: Implemented new function udp_sendto_if which takes the - netif to send as an argument (to be able to send on netifs that are down). - - 2007-11-26 Simon Goldschmidt - * tcp_in.c: Fixed bug #21582: pcb->acked accounting can be wrong when ACKs - arrive out-of-order - - 2007-11-21 Simon Goldschmidt - * tcp.h, tcp_out.c, api_msg.c: Fixed bug #20287: tcp_output_nagle sends too early - Fixed the nagle algorithm; nagle now also works for all raw API applications - and has to be explicitly disabled with 'tcp_pcb->flags |= TF_NODELAY' - - 2007-11-12 Frédéric Bernon - * sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fixed bug #20900. Now, most - of the netconn_peer and netconn_addr processing is done inside tcpip_thread - context in do_getaddr. - - 2007-11-10 Simon Goldschmidt - * etharp.c: Fixed bug: assert fired when MEMP_ARP_QUEUE was empty (which can - happen any time). Now the packet simply isn't enqueued when out of memory. - - 2007-11-01 Simon Goldschmidt - * tcp.c, tcp_in.c: Fixed bug #21494: The send mss (pcb->mss) is set to 536 (or - TCP_MSS if that is smaller) as long as no MSS option is received from the - remote host. - - 2007-11-01 Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c: Fixed bug #21491: The MSS option sent (with SYN) - is now based on TCP_MSS instead of pcb->mss (on passive open now effectively - sending our configured TCP_MSS instead of the one received). - - 2007-11-01 Simon Goldschmidt - * tcp_in.c: Fixed bug #21181: On active open, the initial congestion window was - calculated based on the configured TCP_MSS, not on the MSS option received - with SYN+ACK. - - 2007-10-09 Simon Goldschmidt - * udp.c, inet.c, inet.h: Fixed UDPLite: send: Checksum was always generated too - short and also was generated wrong if checksum coverage != tot_len; - receive: checksum was calculated wrong if checksum coverage != tot_len - - 2007-10-08 Simon Goldschmidt - * mem.c: lfree was not updated in mem_realloc! - - 2007-10-07 Frédéric Bernon - * sockets.c, api.h, api_lib.c: First step to fix "bug #20900 : Potential - crash error problem with netconn_peer & netconn_addr". VERY IMPORTANT: - this change cause an API breakage for netconn_addr, since a parameter - type change. Any compiler should cause an error without any changes in - yours netconn_peer calls (so, it can't be a "silent change"). It also - reduce a little bit the footprint for socket layer (lwip_getpeername & - lwip_getsockname use now a common lwip_getaddrname function since - netconn_peer & netconn_addr have the same parameters). - - 2007-09-20 Simon Goldschmidt - * tcp.c: Fixed bug #21080 (tcp_bind without check pcbs in TIME_WAIT state) - by checking tcp_tw_pcbs also - - 2007-09-19 Simon Goldschmidt - * icmp.c: Fixed bug #21107 (didn't reset IP TTL in ICMP echo replies) - - 2007-09-15 Mike Kleshov - * mem.c: Fixed bug #21077 (inaccuracy in calculation of lwip_stat.mem.used) - - 2007-09-06 Frédéric Bernon - * several-files: replace some #include "arch/cc.h" by "lwip/arch.h", or simply remove - it as long as "lwip/opt.h" is included before (this one include "lwip/debug.h" which - already include "lwip/arch.h"). Like that, default defines are provided by "lwip/arch.h" - if they are not defined in cc.h, in the same spirit than "lwip/opt.h" for lwipopts.h. - - 2007-08-30 Frédéric Bernon - * igmp.h, igmp.c: Some changes to remove some redundant code, add some traces, - and fix some coding style. - - 2007-08-28 Frédéric Bernon - * tcpip.c: Fix TCPIP_MSG_INPKT processing: now, tcpip_input can be used for any - kind of packets. These packets are considered like Ethernet packets (payload - pointing to ethhdr) if the netif got the NETIF_FLAG_ETHARP flag. Else, packets - are considered like IP packets (payload pointing to iphdr). - - 2007-08-27 Frédéric Bernon - * api.h, api_lib.c, api_msg.c: First fix for "bug #20900 : Potential crash error - problem with netconn_peer & netconn_addr". Introduce NETCONN_LISTEN netconn_state - and remove obsolete ones (NETCONN_RECV & NETCONN_ACCEPT). - - 2007-08-24 Kieran Mansley - * inet.c Modify (acc >> 16) test to ((acc >> 16) != 0) to help buggy - compiler (Paradigm C++) - - 2007-08-09 Frédéric Bernon, Bill Florac - * stats.h, stats.c, igmp.h, igmp.c, opt.h: Fix for bug #20503 : IGMP Improvement. - Introduce IGMP_STATS to centralize statistics management. - - 2007-08-09 Frédéric Bernon, Bill Florac - * udp.c: Fix for bug #20503 : IGMP Improvement. Enable to receive a multicast - packet on a udp pcb binded on an netif's IP address, and not on "any". - - 2007-08-09 Frédéric Bernon, Bill Florac - * igmp.h, igmp.c, ip.c: Fix minor changes from bug #20503 : IGMP Improvement. - This is mainly on using lookup/lookfor, and some coding styles... - - 2007-07-26 Frédéric Bernon (and "thedoctor") - * igmp.c: Fix bug #20595 to accept IGMPv3 "Query" messages. - - 2007-07-25 Simon Goldschmidt - * api_msg.c, tcp.c: Another fix for bug #20021: by not returning an error if - tcp_output fails in tcp_close, the code in do_close_internal gets simpler - (tcp_output is called again later from tcp timers). - - 2007-07-25 Simon Goldschmidt - * ip_frag.c: Fixed bug #20429: use the new pbuf_copy_partial instead of the old - copy_from_pbuf, which illegally modified the given pbuf. - - 2007-07-25 Simon Goldschmidt - * tcp_out.c: tcp_enqueue: pcb->snd_queuelen didn't work for chaine PBUF_RAMs: - changed snd_queuelen++ to snd_queuelen += pbuf_clen(p). - - 2007-07-24 Simon Goldschmidt - * api_msg.c, tcp.c: Fix bug #20480: Check the pcb passed to tcp_listen() for the - correct state (must be CLOSED). - - 2007-07-13 Thomas Taranowski (commited by Jared Grubb) - * memp.c: Fix bug #20478: memp_malloc returned NULL+MEMP_SIZE on failed - allocation. It now returns NULL. - - 2007-07-13 Frédéric Bernon - * api_msg.c: Fix bug #20318: api_msg "recv" callbacks don't call pbuf_free in - all error cases. - - 2007-07-13 Frédéric Bernon - * api_msg.c: Fix bug #20315: possible memory leak problem if tcp_listen failed, - because current code doesn't follow rawapi.txt documentation. - - 2007-07-13 Kieran Mansley - * src/core/tcp_in.c Apply patch#5741 from Oleg Tyshev to fix bug in - out of sequence processing of received packets - - 2007-07-03 Simon Goldschmidt - * nearly-all-files: Added assertions where PBUF_RAM pbufs are used and an - assumption is made that this pbuf is in one piece (i.e. not chained). These - assumptions clash with the possibility of converting to fully pool-based - pbuf implementations, where PBUF_RAM pbufs might be chained. - - 2007-07-03 Simon Goldschmidt - * api.h, api_lib.c, api_msg.c: Final fix for bug #20021 and some other problems - when closing tcp netconns: removed conn->sem, less context switches when - closing, both netconn_close and netconn_delete should safely close tcp - connections. - - 2007-07-02 Simon Goldschmidt - * ipv4/ip.h, ipv6/ip.h, opt.h, netif.h, etharp.h, ipv4/ip.c, netif.c, raw.c, - tcp_out.c, udp.c, etharp.c: Added option LWIP_NETIF_HWADDRHINT (default=off) - to cache ARP table indices with each pcb instead of single-entry cache for - the complete stack. - - 2007-07-02 Simon Goldschmidt - * tcp.h, tcp.c, tcp_in.c, tcp_out.c: Added some ASSERTS and casts to prevent - warnings when assigning to smaller types. - - 2007-06-28 Simon Goldschmidt - * tcp_out.c: Added check to prevent tcp_pcb->snd_queuelen from overflowing. - - 2007-06-28 Simon Goldschmidt - * tcp.h: Fixed bug #20287: Fixed nagle algorithm (sending was done too early if - a segment contained chained pbufs) - - 2007-06-28 Frédéric Bernon - * autoip.c: replace most of rand() calls by a macro LWIP_AUTOIP_RAND which compute - a "pseudo-random" value based on netif's MAC and some autoip fields. It's always - possible to define this macro in your own lwipopts.h to always use C library's - rand(). Note that autoip_create_rand_addr doesn't use this macro. - - 2007-06-28 Frédéric Bernon - * netifapi.h, netifapi.c, tcpip.h, tcpip.c: Update code to handle the option - LWIP_TCPIP_CORE_LOCKING, and do some changes to be coherent with last modifications - in api_lib/api_msg (use pointers and not type with table, etc...) - - 2007-06-26 Simon Goldschmidt - * udp.h: Fixed bug #20259: struct udp_hdr was lacking the packin defines. - - 2007-06-25 Simon Goldschmidt - * udp.c: Fixed bug #20253: icmp_dest_unreach was called with a wrong p->payload - for udp packets with no matching pcb. - - 2007-06-25 Simon Goldschmidt - * udp.c: Fixed bug #20220: UDP PCB search in udp_input(): a non-local match - could get udp input packets if the remote side matched. - - 2007-06-13 Simon Goldschmidt - * netif.c: Fixed bug #20180 (TCP pcbs listening on IP_ADDR_ANY could get - changed in netif_set_ipaddr if previous netif->ip_addr.addr was 0. - - 2007-06-13 Simon Goldschmidt - * api_msg.c: pcb_new sets conn->err if protocol is not implemented - -> netconn_new_..() does not allocate a new connection for unsupported - protocols. - - 2007-06-13 Frédéric Bernon, Simon Goldschmidt - * api_lib.c: change return expression in netconn_addr and netconn_peer, because - conn->err was reset to ERR_OK without any reasons (and error was lost)... - - 2007-06-13 Frédéric Bernon, Matthias Weisser - * opt.h, mem.h, mem.c, memp.c, pbuf.c, ip_frag.c, vj.c: Fix bug #20162. Rename - MEM_ALIGN in LWIP_MEM_ALIGN and MEM_ALIGN_SIZE in LWIP_MEM_ALIGN_SIZE to avoid - some macro names collision with some OS macros. - - 2007-06-11 Simon Goldschmidt - * udp.c: UDP Lite: corrected the use of chksum_len (based on RFC3828: if it's 0, - create checksum over the complete packet. On RX, if it's < 8 (and not 0), - discard the packet. Also removed the duplicate 'udphdr->chksum = 0' for both - UDP & UDP Lite. - - 2007-06-11 Srinivas Gollakota & Oleg Tyshev - * tcp_out.c: Fix for bug #20075 : "A problem with keep-alive timer and TCP flags" - where TCP flags wasn't initialized in tcp_keepalive. - - 2007-06-03 Simon Goldschmidt - * udp.c: udp_input(): Input pbuf was not freed if pcb had no recv function - registered, p->payload was modified without modifying p->len if sending - icmp_dest_unreach() (had no negative effect but was definitively wrong). - - 2007-06-03 Simon Goldschmidt - * icmp.c: Corrected bug #19937: For responding to an icmp echo request, icmp - re-used the input pbuf even if that didn't have enough space to include the - link headers. Now the space is tested and a new pbuf is allocated for the - echo response packet if the echo request pbuf isn't big enough. - - 2007-06-01 Simon Goldschmidt - * sockets.c: Checked in patch #5914: Moved sockopt processing into tcpip_thread. - - 2007-05-23 Frédéric Bernon - * api_lib.c, sockets.c: Fixed bug #5958 for netconn_listen (acceptmbox only - allocated by do_listen if success) and netconn_accept errors handling. In - most of api_lib functions, we replace some errors checkings like "if (conn==NULL)" - by ASSERT, except for netconn_delete. - - 2007-05-23 Frédéric Bernon - * api_lib.c: Fixed bug #5957 "Safe-thread problem inside netconn_recv" to return - an error code if it's impossible to fetch a pbuf on a TCP connection (and not - directly close the recvmbox). - - 2007-05-22 Simon Goldschmidt - * tcp.c: Fixed bug #1895 (tcp_bind not correct) by introducing a list of - bound but unconnected (and non-listening) tcp_pcbs. - - 2007-05-22 Frédéric Bernon - * sys.h, sys.c, api_lib.c, tcpip.c: remove sys_mbox_fetch_timeout() (was only - used for LWIP_SO_RCVTIMEO option) and use sys_arch_mbox_fetch() instead of - sys_mbox_fetch() in api files. Now, users SHOULD NOT use internal lwIP features - like "sys_timeout" in their application threads. - - 2007-05-22 Frédéric Bernon - * api.h, api_lib.c, api_msg.h, api_msg.c: change the struct api_msg_msg to see - which parameters are used by which do_xxx function, and to avoid "misusing" - parameters (patch #5938). - - 2007-05-22 Simon Goldschmidt - * api_lib.c, api_msg.c, raw.c, api.h, api_msg.h, raw.h: Included patch #5938: - changed raw_pcb.protocol from u16_t to u8_t since for IPv4 and IPv6, proto - is only 8 bits wide. This affects the api, as there, the protocol was - u16_t, too. - - 2007-05-18 Simon Goldschmidt - * memp.c: addition to patch #5913: smaller pointer was returned but - memp_memory was the same size -> did not save memory. - - 2007-05-16 Simon Goldschmidt - * loopif.c, slipif.c: Fix bug #19729: free pbuf if netif->input() returns - != ERR_OK. - - 2007-05-16 Simon Goldschmidt - * api_msg.c, udp.c: If a udp_pcb has a local_ip set, check if it is the same - as the one of the netif used for sending to prevent sending from old - addresses after a netif address gets changed (partly fixes bug #3168). - - 2007-05-16 Frédéric Bernon - * tcpip.c, igmp.h, igmp.c: Fixed bug "#19800 : IGMP: igmp_tick() will not work - with NO_SYS=1". Note that igmp_init is always in tcpip_thread (and not in - tcpip_init) because we have to be sure that network interfaces are already - added (mac filter is updated only in igmp_init for the moment). - - 2007-05-16 Simon Goldschmidt - * mem.c, memp.c: Removed semaphores from memp, changed sys_sem_wait calls - into sys_arch_sem_wait calls to prevent timers from running while waiting - for the heap. This fixes bug #19167. - - 2007-05-13 Simon Goldschmidt - * tcp.h, sockets.h, sockets.c: Fixed bug from patch #5865 by moving the defines - for socket options (lwip_set/-getsockopt) used with level IPPROTO_TCP from - tcp.h to sockets.h. - - 2007-05-07 Simon Goldschmidt - * mem.c: Another attempt to fix bug #17922. - - 2007-05-04 Simon Goldschmidt - * pbuf.c, pbuf.h, etharp.c: Further update to ARP queueing: Changed pbuf_copy() - implementation so that it can be reused (don't allocate the target - pbuf inside pbuf_copy()). - - 2007-05-04 Simon Goldschmidt - * memp.c: checked in patch #5913: in memp_malloc() we can return memp as mem - to save a little RAM (next pointer of memp is not used while not in pool). - - 2007-05-03 "maq" - * sockets.c: Fix ioctl FIONREAD when some data remains from last recv. - (patch #3574). - - 2007-04-23 Simon Goldschmidt - * loopif.c, loopif.h, opt.h, src/netif/FILES: fix bug #2595: "loopif results - in NULL reference for incoming TCP packets". Loopif has to be configured - (using LWIP_LOOPIF_MULTITHREADING) to directly call netif->input() - (multithreading environments, e.g. netif->input() = tcpip_input()) or - putting packets on a list that is fed to the stack by calling loopif_poll() - (single-thread / NO_SYS / polling environment where e.g. - netif->input() = ip_input). - - 2007-04-17 Jonathan Larmour - * pbuf.c: Use s32_t in pbuf_realloc(), as an s16_t can't reliably hold - the difference between two u16_t's. - * sockets.h: FD_SETSIZE needs to match number of sockets, which is - MEMP_NUM_NETCONN in sockets.c right now. - - 2007-04-12 Jonathan Larmour - * icmp.c: Reset IP header TTL in ICMP ECHO responses (bug #19580). - - 2007-04-12 Kieran Mansley - * tcp.c, tcp_in.c, tcp_out.c, tcp.h: Modify way the retransmission - timer is reset to fix bug#19434, with help from Oleg Tyshev. - - 2007-04-11 Simon Goldschmidt - * etharp.c, pbuf.c, pbuf.h: 3rd fix for bug #11400 (arp-queuing): More pbufs than - previously thought need to be copied (everything but PBUF_ROM!). Cleaned up - pbuf.c: removed functions no needed any more (by etharp). - - 2007-04-11 Kieran Mansley - * inet.c, ip_addr.h, sockets.h, sys.h, tcp.h: Apply patch #5745: Fix - "Constant is long" warnings with 16bit compilers. Contributed by - avatar@mmlab.cse.yzu.edu.tw - - 2007-04-05 Frédéric Bernon, Jonathan Larmour - * api_msg.c: Fix bug #16830: "err_tcp() posts to connection mailbox when no pend on - the mailbox is active". Now, the post is only done during a connect, and do_send, - do_write and do_join_leave_group don't do anything if a previous error was signaled. - - 2007-04-03 Frédéric Bernon - * ip.c: Don't set the IP_DF ("Don't fragment") flag in the IP header in IP output - packets. See patch #5834. - - 2007-03-30 Frédéric Bernon - * api_msg.c: add a "pcb_new" helper function to avoid redundant code, and to add - missing pcb allocations checking (in do_bind, and for each raw_new). Fix style. - - 2007-03-30 Frédéric Bernon - * most of files: prefix all debug.h define with "LWIP_" to avoid any conflict with - others environment defines (these were too "generic"). - - 2007-03-28 Frédéric Bernon - * api.h, api_lib.c, sockets.c: netbuf_ref doesn't check its internal pbuf_alloc call - result and can cause a crash. lwip_send now check netbuf_ref result. - - 2007-03-28 Simon Goldschmidt - * sockets.c Remove "#include " from sockets.c to avoid multiple - definition of macros (in errno.h and lwip/arch.h) if LWIP_PROVIDE_ERRNO is - defined. This is the way it should have been already (looking at - doc/sys_arch.txt) - - 2007-03-28 Kieran Mansley - * opt.h Change default PBUF_POOL_BUFSIZE (again) to accomodate default MSS + - IP and TCP headers *and* physical link headers - - 2007-03-26 Frédéric Bernon (based on patch from Dmitry Potapov) - * api_lib.c: patch for netconn_write(), fixes a possible race condition which cause - to send some garbage. It is not a definitive solution, but the patch does solve - the problem for most cases. - - 2007-03-22 Frédéric Bernon - * api_msg.h, api_msg.c: Remove obsolete API_MSG_ACCEPT and do_accept (never used). - - 2007-03-22 Frédéric Bernon - * api_lib.c: somes resources couldn't be freed if there was errors during - netconn_new_with_proto_and_callback. - - 2007-03-22 Frédéric Bernon - * ethernetif.c: update netif->input calls to check return value. In older ports, - it's a good idea to upgrade them, even if before, there could be another problem - (access to an uninitialized mailbox). - - 2007-03-21 Simon Goldschmidt - * sockets.c: fixed bug #5067 (essentialy a signed/unsigned warning fixed - by casting to unsigned). - - 2007-03-21 Frédéric Bernon - * api_lib.c, api_msg.c, tcpip.c: integrate sys_mbox_fetch(conn->mbox, NULL) calls from - api_lib.c to tcpip.c's tcpip_apimsg(). Now, use a local variable and not a - dynamic one from memp to send tcpip_msg to tcpip_thread in a synchrone call. - Free tcpip_msg from tcpip_apimsg is not done in tcpip_thread. This give a - faster and more reliable communication between api_lib and tcpip. - - 2007-03-21 Frédéric Bernon - * opt.h: Add LWIP_NETIF_CALLBACK (to avoid compiler warning) and set it to 0. - - 2007-03-21 Frédéric Bernon - * api_msg.c, igmp.c, igmp.h: Fix C++ style comments - - 2007-03-21 Kieran Mansley - * opt.h Change default PBUF_POOL_BUFSIZE to accomodate default MSS + - IP and TCP headers - - 2007-03-21 Kieran Mansley - * Fix all uses of pbuf_header to check the return value. In some - cases just assert if it fails as I'm not sure how to fix them, but - this is no worse than before when they would carry on regardless - of the failure. - - 2007-03-21 Kieran Mansley - * sockets.c, igmp.c, igmp.h, memp.h: Fix C++ style comments and - comment out missing header include in icmp.c - - 2007-03-20 Frédéric Bernon - * memp.h, stats.c: Fix stats_display function where memp_names table wasn't - synchronized with memp.h. - - 2007-03-20 Frédéric Bernon - * tcpip.c: Initialize tcpip's mbox, and verify if initialized in tcpip_input, - tcpip_ethinput, tcpip_callback, tcpip_apimsg, to fix a init problem with - network interfaces. Also fix a compiler warning. - - 2007-03-20 Kieran Mansley - * udp.c: Only try and use pbuf_header() to make space for headers if - not a ROM or REF pbuf. - - 2007-03-19 Frédéric Bernon - * api_msg.h, api_msg.c, tcpip.h, tcpip.c: Add return types to tcpip_apimsg() - and api_msg_post(). - - 2007-03-19 Frédéric Bernon - * Remove unimplemented "memp_realloc" function from memp.h. - - 2007-03-11 Simon Goldschmidt - * pbuf.c: checked in patch #5796: pbuf_alloc: len field claculation caused - memory corruption. - - 2007-03-11 Simon Goldschmidt (based on patch from Dmitry Potapov) - * api_lib.c, sockets.c, api.h, api_msg.h, sockets.h: Fixed bug #19251 - (missing `const' qualifier in socket functions), to get more compatible to - standard POSIX sockets. - - 2007-03-11 Frédéric Bernon (based on patch from Dmitry Potapov) - * sockets.c: Add asserts inside bind, connect and sendto to check input - parameters. Remove excessive set_errno() calls after get_socket(), because - errno is set inside of get_socket(). Move last sock_set_errno() inside - lwip_close. - - 2007-03-09 Simon Goldschmidt - * memp.c: Fixed bug #11400: New etharp queueing introduced bug: memp_memory - was allocated too small. - - 2007-03-06 Simon Goldschmidt - * tcpip.c: Initialize dhcp timers in tcpip_thread (if LWIP_DHCP) to protect - the stack from concurrent access. - - 2007-03-06 Frédéric Bernon, Dmitry Potapov - * tcpip.c, ip_frag.c, ethernetif.c: Fix some build problems, and a redundancy - call to "lwip_stats.link.recv++;" in low_level_input() & ethernetif_input(). - - 2007-03-06 Simon Goldschmidt - * ip_frag.c, ip_frag.h: Reduce code size: don't include code in those files - if IP_FRAG == 0 and IP_REASSEMBLY == 0 - - 2007-03-06 Frédéric Bernon, Simon Goldschmidt - * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration - option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. - Allow to do ARP processing for incoming packets inside tcpip_thread - (protecting ARP layer against concurrent access). You can also disable - old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. - Older ports have to use tcpip_ethinput. - - 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) - * err.h, err.c: fixed compiler warning "initialization dircards qualifiers - from pointer target type" - - 2007-03-05 Frédéric Bernon - * opt.h, sockets.h: add new configuration options (LWIP_POSIX_SOCKETS_IO_NAMES, - ETHARP_TRUST_IP_MAC, review SO_REUSE) - - 2007-03-04 Frédéric Bernon - * api_msg.c: Remove some compiler warnings : parameter "pcb" was never - referenced. - - 2007-03-04 Frédéric Bernon - * api_lib.c: Fix "[patch #5764] api_lib.c cleanup: after patch #5687" (from - Dmitry Potapov). - The api_msg struct stay on the stack (not moved to netconn struct). - - 2007-03-04 Simon Goldschmidt (based on patch from Dmitry Potapov) - * pbuf.c: Fix BUG#19168 - pbuf_free can cause deadlock (if - SYS_LIGHTWEIGHT_PROT=1 & freeing PBUF_RAM when mem_sem is not available) - Also fixed cast warning in pbuf_alloc() - - 2007-03-04 Simon Goldschmidt - * etharp.c, etharp.h, memp.c, memp.h, opt.h: Fix BUG#11400 - don't corrupt - existing pbuf chain when enqueuing multiple pbufs to a pending ARP request - - 2007-03-03 Frédéric Bernon - * udp.c: remove obsolete line "static struct udp_pcb *pcb_cache = NULL;" - It is static, and never used in udp.c except udp_init(). - - 2007-03-02 Simon Goldschmidt - * tcpip.c: Moved call to ip_init(), udp_init() and tcp_init() from - tcpip_thread() to tcpip_init(). This way, raw API connections can be - initialized before tcpip_thread is running (e.g. before OS is started) - - 2007-03-02 Frédéric Bernon - * rawapi.txt: Fix documentation mismatch with etharp.h about etharp_tmr's call - interval. - - 2007-02-28 Kieran Mansley - * pbuf.c: Fix BUG#17645 - ensure pbuf payload pointer is not moved - outside the region of the pbuf by pbuf_header() - - 2007-02-28 Kieran Mansley - * sockets.c: Fix BUG#19161 - ensure milliseconds timeout is non-zero - when supplied timeout is also non-zero - -(STABLE-1.2.0) - - 2006-12-05 Leon Woestenberg - * CHANGELOG: Mention STABLE-1.2.0 release. - - ++ New features: - - 2006-12-01 Christiaan Simons - * mem.h, opt.h: Added MEM_LIBC_MALLOC option. - Note this is a workaround. Currently I have no other options left. - - 2006-10-26 Christiaan Simons (accepted patch by Jonathan Larmour) - * ipv4/ip_frag.c: rename MAX_MTU to IP_FRAG_MAX_MTU and move define - to include/lwip/opt.h. - * ipv4/lwip/ip_frag.h: Remove unused IP_REASS_INTERVAL. - Move IP_REASS_MAXAGE and IP_REASS_BUFSIZE to include/lwip/opt.h. - * opt.h: Add above new options. - - 2006-08-18 Christiaan Simons - * tcp_{in,out}.c: added SNMP counters. - * ipv4/ip.c: added SNMP counters. - * ipv4/ip_frag.c: added SNMP counters. - - 2006-08-08 Christiaan Simons - * etharp.{c,h}: added etharp_find_addr() to read - (stable) ethernet/IP address pair from ARP table - - 2006-07-14 Christiaan Simons - * mib_structs.c: added - * include/lwip/snmp_structs.h: added - * netif.{c,h}, netif/ethernetif.c: added SNMP statistics to netif struct - - 2006-07-06 Christiaan Simons - * snmp/asn1_{enc,dec}.c added - * snmp/mib2.c added - * snmp/msg_{in,out}.c added - * include/lwip/snmp_asn1.h added - * include/lwip/snmp_msg.h added - * doc/snmp_agent.txt added - - 2006-03-29 Christiaan Simons - * inet.c, inet.h: Added platform byteswap support. - Added LWIP_PLATFORM_BYTESWAP define (defaults to 0) and - optional LWIP_PLATFORM_HTONS(), LWIP_PLATFORM_HTONL() macros. - - ++ Bug fixes: - - 2006-11-30 Christiaan Simons - * dhcp.c: Fixed false triggers of request_timeout. - - 2006-11-28 Christiaan Simons - * netif.c: In netif_add() fixed missing clear of ip_addr, netmask, gw and flags. - - 2006-10-11 Christiaan Simons - * api_lib.c etharp.c, ip.c, memp.c, stats.c, sys.{c,h} tcp.h: - Partially accepted patch #5449 for ANSI C compatibility / build fixes. - * ipv4/lwip/ip.h ipv6/lwip/ip.h: Corrected UDP-Lite protocol - identifier from 170 to 136 (bug #17574). - - 2006-10-10 Christiaan Simons - * api_msg.c: Fixed Nagle algorithm as reported by Bob Grice. - - 2006-08-17 Christiaan Simons - * udp.c: Fixed bug #17200, added check for broadcast - destinations for PCBs bound to a unicast address. - - 2006-08-07 Christiaan Simons - * api_msg.c: Flushing TCP output in do_close() (bug #15926). - - 2006-06-27 Christiaan Simons - * api_msg.c: Applied patch for cold case (bug #11135). - In accept_function() ensure newconn->callback is always initialized. - - 2006-06-15 Christiaan Simons - * mem.h: added MEM_SIZE_F alias to fix an ancient cold case (bug #1748), - facilitate printing of mem_size_t and u16_t statistics. - - 2006-06-14 Christiaan Simons - * api_msg.c: Applied patch #5146 to handle allocation failures - in accept() by Kevin Lawson. - - 2006-05-26 Christiaan Simons - * api_lib.c: Removed conn->sem creation and destruction - from netconn_write() and added sys_sem_new to netconn_new_*. - -(STABLE-1_1_1) - - 2006-03-03 Christiaan Simons - * ipv4/ip_frag.c: Added bound-checking assertions on ip_reassbitmap - access and added pbuf_alloc() return value checks. - - 2006-01-01 Leon Woestenberg - * tcp_{in,out}.c, tcp_out.c: Removed 'even sndbuf' fix in TCP, which is - now handled by the checksum routine properly. - - 2006-02-27 Leon Woestenberg - * pbuf.c: Fix alignment; pbuf_init() would not work unless - pbuf_pool_memory[] was properly aligned. (Patch by Curt McDowell.) - - 2005-12-20 Leon Woestenberg - * tcp.c: Remove PCBs which stay in LAST_ACK state too long. Patch - submitted by Mitrani Hiroshi. - - 2005-12-15 Christiaan Simons - * inet.c: Disabled the added summing routine to preserve code space. - - 2005-12-14 Leon Woestenberg - * tcp_in.c: Duplicate FIN ACK race condition fix by Kelvin Lawson. - Added Curt McDowell's optimized checksumming routine for future - inclusion. Need to create test case for unaliged, aligned, odd, - even length combination of cases on various endianess machines. - - 2005-12-09 Christiaan Simons - * inet.c: Rewrote standard checksum routine in proper portable C. - - 2005-11-25 Christiaan Simons - * udp.c tcp.c: Removed SO_REUSE hack. Should reside in socket code only. - * *.c: introduced cc.h LWIP_DEBUG formatters matching the u16_t, s16_t, - u32_t, s32_t typedefs. This solves most debug word-length assumes. - - 2005-07-17 Leon Woestenberg - * inet.c: Fixed unaligned 16-bit access in the standard checksum - routine by Peter Jolasson. - * slipif.c: Fixed implementation assumption of single-pbuf datagrams. - - 2005-02-04 Leon Woestenberg - * tcp_out.c: Fixed uninitialized 'queue' referenced in memerr branch. - * tcp_{out|in}.c: Applied patch fixing unaligned access. - - 2005-01-04 Leon Woestenberg - * pbuf.c: Fixed missing semicolon after LWIP_DEBUG statement. - - 2005-01-03 Leon Woestenberg - * udp.c: UDP pcb->recv() was called even when it was NULL. - -(STABLE-1_1_0) - - 2004-12-28 Leon Woestenberg - * etharp.*: Disabled multiple packets on the ARP queue. - This clashes with TCP queueing. - - 2004-11-28 Leon Woestenberg - * etharp.*: Fixed race condition from ARP request to ARP timeout. - Halved the ARP period, doubled the period counts. - ETHARP_MAX_PENDING now should be at least 2. This prevents - the counter from reaching 0 right away (which would allow - too little time for ARP responses to be received). - - 2004-11-25 Leon Woestenberg - * dhcp.c: Decline messages were not multicast but unicast. - * etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD. - Do not try hard to insert arbitrary packet's source address, - etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD. - etharp_query() now always DOES call ETHARP_TRY_HARD so that users - querying an address will see it appear in the cache (DHCP could - suffer from this when a server invalidly gave an in-use address.) - * ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are - comparing network addresses (identifiers), not the network masks - themselves. - * ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given - IP address actually belongs to the network of the given interface. - - 2004-11-24 Kieran Mansley - * tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state. - -(STABLE-1_1_0-RC1) - - 2004-10-16 Kieran Mansley - * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, - even if one is already pending, if the rcv_wnd is above a threshold - (currently TCP_WND/2). This avoids waiting for a timer to expire to send a - delayed ACK in order to open the window if the stack is only receiving data. - - 2004-09-12 Kieran Mansley - * tcp*.*: Retransmit time-out handling improvement by Sam Jansen. - - 2004-08-20 Tony Mountifield - * etharp.c: Make sure the first pbuf queued on an ARP entry - is properly ref counted. - - 2004-07-27 Tony Mountifield - * debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler - warnings about comparison. - * pbuf.c: Stopped compiler complaining of empty if statement - when LWIP_DEBUGF() empty. Closed an unclosed comment. - * tcp.c: Stopped compiler complaining of empty if statement - when LWIP_DEBUGF() empty. - * ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons(). - * inet.c: Added a couple of casts to quiet the compiler. - No need to test isascii(c) before isdigit(c) or isxdigit(c). - - 2004-07-22 Tony Mountifield - * inet.c: Made data types consistent in inet_ntoa(). - Added casts for return values of checksum routines, to pacify compiler. - * ip_frag.c, tcp_out.c, sockets.c, pbuf.c - Small corrections to some debugging statements, to pacify compiler. - - 2004-07-21 Tony Mountifield - * etharp.c: Removed spurious semicolon and added missing end-of-comment. - * ethernetif.c Updated low_level_output() to match prototype for - netif->linkoutput and changed low_level_input() similarly for consistency. - * api_msg.c: Changed recv_raw() from int to u8_t, to match prototype - of raw_recv() in raw.h and so avoid compiler error. - * sockets.c: Added trivial (int) cast to keep compiler happier. - * ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros. - -(STABLE-1_0_0) - - ++ Changes: - - 2004-07-05 Leon Woestenberg - * sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure - your cc.h file defines this either 1 or 0. If non-defined, - defaults to 1. - * .c: Added and includes where used. - * etharp.c: Made some array indices unsigned. - - 2004-06-27 Leon Woestenberg - * netif.*: Added netif_set_up()/down(). - * dhcp.c: Changes to restart program flow. - - 2004-05-07 Leon Woestenberg - * etharp.c: In find_entry(), instead of a list traversal per candidate, do a - single-pass lookup for different candidates. Should exploit locality. - - 2004-04-29 Leon Woestenberg - * tcp*.c: Cleaned up source comment documentation for Doxygen processing. - * opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC. - * etharp.c: update_arp_entry() only adds new ARP entries when adviced to by - the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option. - - ++ Bug fixes: - - 2004-04-27 Leon Woestenberg - * etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution - suggested by Timmy Brolin. Fix for 32-bit processors that cannot access - non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix - is to prefix the 14-bit Ethernet headers with two padding bytes. - - 2004-04-23 Leon Woestenberg - * ip_addr.c: Fix in the ip_addr_isbroadcast() check. - * etharp.c: Fixed the case where the packet that initiates the ARP request - is not queued, and gets lost. Fixed the case where the packets destination - address is already known; we now always queue the packet and perform an ARP - request. - -(STABLE-0_7_0) - - ++ Bug fixes: - - * Fixed TCP bug for SYN_SENT to ESTABLISHED state transition. - * Fixed TCP bug in dequeueing of FIN from out of order segment queue. - * Fixed two possible NULL references in rare cases. - -(STABLE-0_6_6) - - ++ Bug fixes: - - * Fixed DHCP which did not include the IP address in DECLINE messages. - - ++ Changes: - - * etharp.c has been hauled over a bit. - -(STABLE-0_6_5) - - ++ Bug fixes: - - * Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic. - * Packets sent from ARP queue had invalid source hardware address. - - ++ Changes: - - * Pass-by ARP requests do now update the cache. - - ++ New features: - - * No longer dependent on ctype.h. - * New socket options. - * Raw IP pcb support. - -(STABLE-0_6_4) - - ++ Bug fixes: - - * Some debug formatters and casts fixed. - * Numereous fixes in PPP. - - ++ Changes: - - * DEBUGF now is LWIP_DEBUGF - * pbuf_dechain() has been re-enabled. - * Mentioned the changed use of CVS branches in README. - -(STABLE-0_6_3) - - ++ Bug fixes: - - * Fixed pool pbuf memory leak in pbuf_alloc(). - Occured if not enough PBUF_POOL pbufs for a packet pbuf chain. - Reported by Savin Zlobec. - - * PBUF_POOL chains had their tot_len field not set for non-first - pbufs. Fixed in pbuf_alloc(). - - ++ New features: - - * Added PPP stack contributed by Marc Boucher - - ++ Changes: - - * Now drops short packets for ICMP/UDP/TCP protocols. More robust. - - * ARP queueuing now queues the latest packet instead of the first. - This is the RFC recommended behaviour, but can be overridden in - lwipopts.h. - -(0.6.2) - - ++ Bugfixes: - - * TCP has been fixed to deal with the new use of the pbuf->ref - counter. - - * DHCP dhcp_inform() crash bug fixed. - - ++ Changes: - - * Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed - pbuf_refresh(). This has sped up pbuf pool operations considerably. - Implemented by David Haas. - -(0.6.1) - - ++ New features: - - * The packet buffer implementation has been enhanced to support - zero-copy and copy-on-demand for packet buffers which have their - payloads in application-managed memory. - Implemented by David Haas. - - Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy - if an outgoing packet can be directly sent on the link, or perform - a copy-on-demand when necessary. - - The application can safely assume the packet is sent, and the RAM - is available to the application directly after calling udp_send() - or similar function. - - ++ Bugfixes: - - * ARP_QUEUEING should now correctly work for all cases, including - PBUF_REF. - Implemented by Leon Woestenberg. - - ++ Changes: - - * IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer - to a '0.0.0.0' IP address. - - * The packet buffer implementation is changed. The pbuf->ref counter - meaning has changed, and several pbuf functions have been - adapted accordingly. - - * netif drivers have to be changed to set the hardware address length field - that must be initialized correctly by the driver (hint: 6 for Ethernet MAC). - See the contrib/ports/c16x cs8900 driver as a driver example. - - * netif's have a dhcp field that must be initialized to NULL by the driver. - See the contrib/ports/c16x cs8900 driver as a driver example. - -(0.5.x) This file has been unmaintained up to 0.6.1. All changes are - logged in CVS but have not been explained here. - -(0.5.3) Changes since version 0.5.2 - - ++ Bugfixes: - - * memp_malloc(MEMP_API_MSG) could fail with multiple application - threads because it wasn't protected by semaphores. - - ++ Other changes: - - * struct ip_addr now packed. - - * The name of the time variable in arp.c has been changed to ctime - to avoid conflicts with the time() function. - -(0.5.2) Changes since version 0.5.1 - - ++ New features: - - * A new TCP function, tcp_tmr(), now handles both TCP timers. - - ++ Bugfixes: - - * A bug in tcp_parseopt() could cause the stack to hang because of a - malformed TCP option. - - * The address of new connections in the accept() function in the BSD - socket library was not handled correctly. - - * pbuf_dechain() did not update the ->tot_len field of the tail. - - * Aborted TCP connections were not handled correctly in all - situations. - - ++ Other changes: - - * All protocol header structs are now packed. - - * The ->len field in the tcp_seg structure now counts the actual - amount of data, and does not add one for SYN and FIN segments. - -(0.5.1) Changes since version 0.5.0 - - ++ New features: - - * Possible to run as a user process under Linux. - - * Preliminary support for cross platform packed structs. - - * ARP timer now implemented. - - ++ Bugfixes: - - * TCP output queue length was badly initialized when opening - connections. - - * TCP delayed ACKs were not sent correctly. - - * Explicit initialization of BSS segment variables. - - * read() in BSD socket library could drop data. - - * Problems with memory alignment. - - * Situations when all TCP buffers were used could lead to - starvation. - - * TCP MSS option wasn't parsed correctly. - - * Problems with UDP checksum calculation. - - * IP multicast address tests had endianess problems. - - * ARP requests had wrong destination hardware address. - - ++ Other changes: - - * struct eth_addr changed from u16_t[3] array to u8_t[6]. - - * A ->linkoutput() member was added to struct netif. - - * TCP and UDP ->dest_* struct members where changed to ->remote_*. - - * ntoh* macros are now null definitions for big endian CPUs. - -(0.5.0) Changes since version 0.4.2 - - ++ New features: - - * Redesigned operating system emulation layer to make porting easier. - - * Better control over TCP output buffers. - - * Documenation added. - - ++ Bugfixes: - - * Locking issues in buffer management. - - * Bugfixes in the sequential API. - - * IP forwarding could cause memory leakage. This has been fixed. - - ++ Other changes: - - * Directory structure somewhat changed; the core/ tree has been - collapsed. - -(0.4.2) Changes since version 0.4.1 - - ++ New features: - - * Experimental ARP implementation added. - - * Skeleton Ethernet driver added. - - * Experimental BSD socket API library added. - - ++ Bugfixes: - - * In very intense situations, memory leakage could occur. This has - been fixed. - - ++ Other changes: - - * Variables named "data" and "code" have been renamed in order to - avoid name conflicts in certain compilers. - - * Variable++ have in appliciable cases been translated to ++variable - since some compilers generate better code in the latter case. - -(0.4.1) Changes since version 0.4 - - ++ New features: - - * TCP: Connection attempts time out earlier than data - transmissions. Nagle algorithm implemented. Push flag set on the - last segment in a burst. - - * UDP: experimental support for UDP-Lite extensions. - - ++ Bugfixes: - - * TCP: out of order segments were in some cases handled incorrectly, - and this has now been fixed. Delayed acknowledgements was broken - in 0.4, has now been fixed. Binding to an address that is in use - now results in an error. Reset connections sometimes hung an - application; this has been fixed. - - * Checksum calculation sometimes failed for chained pbufs with odd - lengths. This has been fixed. - - * API: a lot of bug fixes in the API. The UDP API has been improved - and tested. Error reporting and handling has been - improved. Logical flaws and race conditions for incoming TCP - connections has been found and removed. - - * Memory manager: alignment issues. Reallocating memory sometimes - failed, this has been fixed. - - * Generic library: bcopy was flawed and has been fixed. - - ++ Other changes: - - * API: all datatypes has been changed from generic ones such as - ints, to specified ones such as u16_t. Functions that return - errors now have the correct type (err_t). - - * General: A lot of code cleaned up and debugging code removed. Many - portability issues have been fixed. - - * The license was changed; the advertising clause was removed. - - * C64 port added. - - * Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri - Kosunen, Mikael Caleres, and Frits Wilmink for reporting and - fixing bugs! - -(0.4) Changes since version 0.3.1 - - * Memory management has been radically changed; instead of - allocating memory from a shared heap, memory for objects that are - rapidly allocated and deallocated is now kept in pools. Allocation - and deallocation from those memory pools is very fast. The shared - heap is still present but is used less frequently. - - * The memory, memory pool, and packet buffer subsystems now support - 4-, 2-, or 1-byte alignment. - - * "Out of memory" situations are handled in a more robust way. - - * Stack usage has been reduced. - - * Easier configuration of lwIP parameters such as memory usage, - TTLs, statistics gathering, etc. All configuration parameters are - now kept in a single header file "lwipopts.h". - - * The directory structure has been changed slightly so that all - architecture specific files are kept under the src/arch - hierarchy. - - * Error propagation has been improved, both in the protocol modules - and in the API. - - * The code for the RTXC architecture has been implemented, tested - and put to use. - - * Bugs have been found and corrected in the TCP, UDP, IP, API, and - the Internet checksum modules. - - * Bugs related to porting between a 32-bit and a 16-bit architecture - have been found and corrected. - - * The license has been changed slightly to conform more with the - original BSD license, including the advertisement clause. - -(0.3.1) Changes since version 0.3 - - * Fix of a fatal bug in the buffer management. Pbufs with allocated - RAM never returned the RAM when the pbuf was deallocated. - - * TCP congestion control, window updates and retransmissions did not - work correctly. This has now been fixed. - - * Bugfixes in the API. - -(0.3) Changes since version 0.2 - - * New and improved directory structure. All include files are now - kept in a dedicated include/ directory. - - * The API now has proper error handling. A new function, - netconn_err(), now returns an error code for the connection in - case of errors. - - * Improvements in the memory management subsystem. The system now - keeps a pointer to the lowest free memory block. A new function, - mem_malloc2() tries to allocate memory once, and if it fails tries - to free some memory and retry the allocation. - - * Much testing has been done with limited memory - configurations. lwIP now does a better job when overloaded. - - * Some bugfixes and improvements to the buffer (pbuf) subsystem. - - * Many bugfixes in the TCP code: - - - Fixed a bug in tcp_close(). - - - The TCP receive window was incorrectly closed when out of - sequence segments was received. This has been fixed. - - - Connections are now timed-out of the FIN-WAIT-2 state. - - - The initial congestion window could in some cases be too - large. This has been fixed. - - - The retransmission queue could in some cases be screwed up. This - has been fixed. - - - TCP RST flag now handled correctly. - - - Out of sequence data was in some cases never delivered to the - application. This has been fixed. - - - Retransmitted segments now contain the correct acknowledgment - number and advertised window. - - - TCP retransmission timeout backoffs are not correctly computed - (ala BSD). After a number of retransmissions, TCP now gives up - the connection. - - * TCP connections now are kept on three lists, one for active - connections, one for listening connections, and one for - connections that are in TIME-WAIT. This greatly speeds up the fast - timeout processing for sending delayed ACKs. - - * TCP now provides proper feedback to the application when a - connection has been successfully set up. - - * More comments have been added to the code. The code has also been - somewhat cleaned up. - -(0.2) Initial public release. diff --git a/components/net/lwip-2.0.2/COPYING b/components/net/lwip-2.0.2/COPYING deleted file mode 100644 index e23898b5e8..0000000000 --- a/components/net/lwip-2.0.2/COPYING +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - - diff --git a/components/net/lwip-2.0.2/FILES b/components/net/lwip-2.0.2/FILES deleted file mode 100644 index e6e09989d9..0000000000 --- a/components/net/lwip-2.0.2/FILES +++ /dev/null @@ -1,5 +0,0 @@ -src/ - The source code for the lwIP TCP/IP stack. -doc/ - The documentation for lwIP. -test/ - Some code to test whether the sources do what they should. - -See also the FILES file in each subdirectory. diff --git a/components/net/lwip-2.0.2/README b/components/net/lwip-2.0.2/README deleted file mode 100644 index 0884d27bea..0000000000 --- a/components/net/lwip-2.0.2/README +++ /dev/null @@ -1,100 +0,0 @@ -INTRODUCTION - -lwIP is a small independent implementation of the TCP/IP protocol -suite that has been developed by Adam Dunkels at the Computer and -Networks Architectures (CNA) lab at the Swedish Institute of Computer -Science (SICS). - -The focus of the lwIP TCP/IP implementation is to reduce the RAM usage -while still having a full scale TCP. This making lwIP suitable for use -in embedded systems with tens of kilobytes of free RAM and room for -around 40 kilobytes of code ROM. - - -FEATURES - - * IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over - multiple network interfaces - * ICMP (Internet Control Message Protocol) for network maintenance and debugging - * IGMP (Internet Group Management Protocol) for multicast traffic management - * MLD (Multicast listener discovery for IPv6). Aims to be compliant with - RFC 2710. No support for MLDv2 - * ND (Neighbor discovery and stateless address autoconfiguration for IPv6). - Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - (Address autoconfiguration) - * UDP (User Datagram Protocol) including experimental UDP-lite extensions - * TCP (Transmission Control Protocol) with congestion control, RTT estimation - and fast recovery/fast retransmit - * raw/native API for enhanced performance - * Optional Berkeley-like socket API - * DNS (Domain names resolver) - - -APPLICATIONS - - * HTTP server with SSI and CGI - * SNMPv2c agent with MIB compiler (Simple Network Management Protocol) - * SNTP (Simple network time protocol) - * NetBIOS name service responder - * MDNS (Multicast DNS) responder - * iPerf server implementation - - -LICENSE - -lwIP is freely available under a BSD license. - - -DEVELOPMENT - -lwIP has grown into an excellent TCP/IP stack for embedded devices, -and developers using the stack often submit bug fixes, improvements, -and additions to the stack to further increase its usefulness. - -Development of lwIP is hosted on Savannah, a central point for -software development, maintenance and distribution. Everyone can -help improve lwIP by use of Savannah's interface, Git and the -mailing list. A core team of developers will commit changes to the -Git source tree. - -The lwIP TCP/IP stack is maintained in the 'lwip' Git module and -contributions (such as platform ports) are in the 'contrib' Git module. - -See doc/savannah.txt for details on Git server access for users and -developers. - -The current Git trees are web-browsable: - http://git.savannah.gnu.org/cgit/lwip.git - http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git - -Submit patches and bugs via the lwIP project page: - http://savannah.nongnu.org/projects/lwip/ - -Continuous integration builds (GCC, clang): - https://travis-ci.org/yarrick/lwip-merged - - -DOCUMENTATION - -Self documentation of the source code is regularly extracted from the current -Git sources and is available from this web page: - http://www.nongnu.org/lwip/ - -There is now a constantly growing wiki about lwIP at - http://lwip.wikia.com/wiki/LwIP_Wiki - -Also, there are mailing lists you can subscribe at - http://savannah.nongnu.org/mail/?group=lwip -plus searchable archives: - http://lists.nongnu.org/archive/html/lwip-users/ - http://lists.nongnu.org/archive/html/lwip-devel/ - -lwIP was originally written by Adam Dunkels: - http://dunkels.com/adam/ - -Reading Adam's papers, the files in docs/, browsing the source code -documentation and browsing the mailing list archives is a good way to -become familiar with the design of lwIP. - -Adam Dunkels -Leon Woestenberg diff --git a/components/net/lwip-2.0.2/READTEST.md b/components/net/lwip-2.0.2/READTEST.md deleted file mode 100644 index dbc2a2bf4d..0000000000 --- a/components/net/lwip-2.0.2/READTEST.md +++ /dev/null @@ -1,22 +0,0 @@ -Porting network interface device for RT-Thread in lwIP. -The major jobs following RT-Thread Team. The RT-Thread network interface device need to synchronize some network status and address information in lwIP, so it need to make some changes in the lwIP netwrok status and address operations function. -The specific changes are as follows: - - - netif.c: add RT-Thread netdev header file , status synchronize(UP, LINK_UP), address synchronize(IP, netmask, gateway); - - - dns.c: add RT-Thread header file, dns servers synchronize; - - - sockets.c: custom 'select' function implementation in RT-Thread by the wait queue mode. - -by ChenYong 2019/3/26 10:00 AM -chenyong@rt-thread.com - - -Porting lwip 2.0.2 running on RT-Thread. -The major jobs following RT-Thread Team. The RT-Thread team already port the lwip 2.0.0, so I only do some move code and test jobs. -I use the memory pools to test lwip 2.0.2, I use the iperf tool to test it about more than 20 hours, It is running normal. -I don't test it working on memory heap. -... -Good Luck. -by Hans.Huang 2017/3/27 10:52 AM -huangxi_hans@163.com diff --git a/components/net/lwip-2.0.2/SConscript b/components/net/lwip-2.0.2/SConscript deleted file mode 100644 index df04b42324..0000000000 --- a/components/net/lwip-2.0.2/SConscript +++ /dev/null @@ -1,89 +0,0 @@ -from building import * - -src = Split(""" -src/arch/sys_arch.c -src/api/api_lib.c -src/api/api_msg.c -src/api/err.c -src/api/netbuf.c -src/api/netdb.c -src/api/netifapi.c -src/api/sockets.c -src/api/tcpip.c -src/core/def.c -src/core/dns.c -src/core/inet_chksum.c -src/core/init.c -src/core/ip.c -src/core/memp.c -src/core/netif.c -src/core/pbuf.c -src/core/raw.c -src/core/stats.c -src/core/sys.c -src/core/tcp.c -src/core/tcp_in.c -src/core/tcp_out.c -src/core/timeouts.c -src/core/udp.c -src/netif/ethernet.c -src/netif/ethernetif.c -src/netif/lowpan6.c -""") - -ipv4_src = Split(""" -src/core/ipv4/autoip.c -src/core/ipv4/dhcp.c -src/core/ipv4/etharp.c -src/core/ipv4/icmp.c -src/core/ipv4/igmp.c -src/core/ipv4/ip4.c -src/core/ipv4/ip4_addr.c -src/core/ipv4/ip4_frag.c -""") - -ipv6_src = Split(""" -src/core/ipv6/dhcp6.c -src/core/ipv6/ethip6.c -src/core/ipv6/icmp6.c -src/core/ipv6/inet6.c -src/core/ipv6/ip6.c -src/core/ipv6/ip6_addr.c -src/core/ipv6/ip6_frag.c -src/core/ipv6/mld6.c -src/core/ipv6/nd6.c -""") - -snmp_src = Glob("src/apps/snmp/*.c") - -ppp_src = Glob("src/netif/ppp/*.c") + Glob("src/netif/ppp/polarssl/*c") - -src = src + ipv4_src - -# The set of source files associated with this SConscript file. -path = [GetCurrentDir() + '/src', - GetCurrentDir() + '/src/include', - GetCurrentDir() + '/src/include/ipv4', - GetCurrentDir() + '/src/arch/include', - GetCurrentDir() + '/src/include/netif'] - -if not GetDepend('RT_USING_SAL'): - path += [GetCurrentDir() + '/src/include/posix'] - -if GetDepend(['RT_LWIP_SNMP']): - src += snmp_src - path += [GetCurrentDir() + '/src/apps/snmp'] - -if GetDepend(['RT_LWIP_PPP']): - src += ppp_src - path += [GetCurrentDir() + '/src/netif/ppp'] - -if GetDepend(['RT_USING_LWIP_IPV6']): - src += ipv6_src - -if GetDepend(['RT_LWIP_USING_PING']): - src += Glob('src/apps/ping/ping.c') - -group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP202'], CPPPATH = path) - -Return('group') diff --git a/components/net/lwip-2.0.2/UPGRADING b/components/net/lwip-2.0.2/UPGRADING deleted file mode 100644 index 3a984c9270..0000000000 --- a/components/net/lwip-2.0.2/UPGRADING +++ /dev/null @@ -1,235 +0,0 @@ -This file lists major changes between release versions that require -ports or applications to be changed. Use it to update a port or an -application written for an older version of lwIP to correctly work -with newer versions. - - -(git master) - - * [Enter new changes just after this line - do not remove this line] - -(2.0.1) - - ++ Application changes: - - * UDP does NOT receive multicast traffic from ALL netifs on an UDP PCB bound to a specific - netif any more. Users need to bind to IP_ADDR_ANY to receive multicast traffic and compare - ip_current_netif() to the desired netif for every packet. - See bug #49662 for an explanation. - -(2.0.0) - - ++ Application changes: - - * Changed netif "up" flag handling to be an administrative flag (as opposed to the previous meaning of - "ip4-address-valid", a netif will now not be used for transmission if not up) -> even a DHCP netif - has to be set "up" before starting the DHCP client - * Added IPv6 support (dual-stack or IPv4/IPv6 only) - * Changed ip_addr_t to be a union in dual-stack mode (use ip4_addr_t where referring to IPv4 only). - * Major rewrite of SNMP (added MIB parser that creates code stubs for custom MIBs); - supports SNMPv2c (experimental v3 support) - * Moved some core applications from contrib repository to src/apps (and include/lwip/apps) - - +++ Raw API: - * Changed TCP listen backlog: removed tcp_accepted(), added the function pair tcp_backlog_delayed()/ - tcp_backlog_accepted() to explicitly delay backlog handling on a connection pcb - - +++ Socket API: - * Added an implementation for posix sendmsg() - * Added LWIP_FIONREAD_LINUXMODE that makes ioctl/FIONREAD return the size of the next pending datagram - - ++ Port changes - - +++ new files: - * MANY new and moved files! - * Added src/Filelists.mk for use in Makefile projects - * Continued moving stack-internal parts from abc.h to abc_priv.h in sub-folder "priv" - to let abc.h only contain the actual application programmer's API - - +++ sys layer: - * Made LWIP_TCPIP_CORE_LOCKING==1 the default as it usually performs better than - the traditional message passing (although with LWIP_COMPAT_MUTEX you are still - open to priority inversion, so this is not recommended any more) - * Added LWIP_NETCONN_SEM_PER_THREAD to use one "op_completed" semaphore per thread - instead of using one per netconn (these semaphores are used even with core locking - enabled as some longer lasting functions like big writes still need to delay) - * Added generalized abstraction for itoa(), strnicmp(), stricmp() and strnstr() - in def.h (to be overridden in cc.h) instead of config - options for netbiosns, httpd, dns, etc. ... - * New abstraction for hton* and ntoh* functions in def.h. - To override them, use the following in cc.h: - #define lwip_htons(x) - #define lwip_htonl(x) - - +++ new options: - * TODO - - +++ new pools: - * Added LWIP_MEMPOOL_* (declare/init/alloc/free) to declare private memp pools - that share memp.c code but do not have to be made global via lwippools.h - * Added pools for IPv6, MPU_COMPATIBLE, dns-api, netif-api, etc. - * added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item - is now available - - * Signature of LWIP_HOOK_VLAN_SET macro was changed - - * LWIP_DECLARE_MEMORY_ALIGNED() may be used to declare aligned memory buffers (mem/memp) - or to move buffers to dedicated memory using compiler attributes - - * Standard C headers are used to define sized types and printf formatters - (disable by setting LWIP_NO_STDINT_H=1 or LWIP_NO_INTTYPES_H=1 if your compiler - does not support these) - - - ++ Major bugfixes/improvements - - * Added IPv6 support (dual-stack or IPv4/IPv6 only) - * Major rewrite of PPP (incl. keep-up with apache pppd) - see doc/ppp.txt for an upgrading how-to - * Major rewrite of SNMP (incl. MIB parser) - * Fixed timing issues that might have lead to losing a DHCP lease - * Made rx processing path more robust against crafted errors - * TCP window scaling support - * modification of api modules to support FreeRTOS-MPU (don't pass stack-pointers to other threads) - * made DNS client more robust - * support PBUF_REF for RX packets - * LWIP_NETCONN_FULLDUPLEX allows netconn/sockets to be used for reading/writing from separate - threads each (needs LWIP_NETCONN_SEM_PER_THREAD) - * Moved and reordered stats (mainly memp/mib2) - -(1.4.0) - - ++ Application changes: - - * Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for - compatibility to old applications, but will be removed in the future). - - * Renamed mem_realloc() to mem_trim() to prevent confusion with realloc() - - +++ Raw API: - * Changed the semantics of tcp_close() (since it was rather a - shutdown before): Now the application does *NOT* get any calls to the recv - callback (aside from NULL/closed) after calling tcp_close() - - * When calling tcp_abort() from a raw API TCP callback function, - make sure you return ERR_ABRT to prevent accessing unallocated memory. - (ERR_ABRT now means the applicaiton has called tcp_abort!) - - +++ Netconn API: - * Changed netconn_receive() and netconn_accept() to return - err_t, not a pointer to new data/netconn. - - +++ Socket API: - * LWIP_SO_RCVTIMEO: when accept() or recv() time out, they - now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT. - - * Added a minimal version of posix fctl() to have a - standardised way to set O_NONBLOCK for nonblocking sockets. - - +++ all APIs: - * correctly implemented SO(F)_REUSEADDR - - ++ Port changes - - +++ new files: - - * Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h: - - * Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains - the actual application programmer's API - - * Separated timer implementation from sys.h/.c, moved to timers.h/.c; - Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you - still want to use your own timer implementation for NO_SYS==0 (as before). - - +++ sys layer: - - * Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/ - sys_sem_t; - - * Converted sys_mbox_new/sys_sem_new to take pointers and return err_t; - - * Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use - binary semaphores instead of mutexes - as before) - - +++ new options: - - * Don't waste memory when chaining segments, added option TCP_OVERSIZE to - prevent creating many small pbufs when calling tcp_write with many small - blocks of data. Instead, pbufs are allocated larger than needed and the - space is used for later calls to tcp_write. - - * Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs - in tcp_write/udp_send. - - * Added an additional option LWIP_ETHERNET to support ethernet without ARP - (necessary for pure PPPoE) - - * Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may - be used to place these pools into user-defined memory by using external - declaration. - - * Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT - - +++ new pools: - - * Netdb uses a memp pool for allocating memory when getaddrinfo() is called, - so MEMP_NUM_NETDB has to be set accordingly. - - * DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so - MEMP_NUM_LOCALHOSTLIST has to be set accordingly. - - * Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have - to be set accordingly. - - * PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES - has to be set accordingly - - * Integrated loopif into netif.c - loopif does not have to be created by the - port any more, just define LWIP_HAVE_LOOPIF to 1. - - * Added define LWIP_RAND() for lwip-wide randomization (needs to be defined - in cc.h, e.g. used by igmp) - - * Added printf-formatter X8_F to printf u8_t as hex - - * The heap now may be moved to user-defined memory by defining - LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address - - * added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work - with user-allocated structs instead of calling mem_malloc - - * Added const char* name to mem- and memp-stats for easier debugging. - - * Calculate the TCP/UDP checksum while copying to only fetch data once: - Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum - - * Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to - more than one pcb. - - * Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned - off any more, if this is set to 0, only one packet (the most recent one) is - queued (like demanded by RFC 1122). - - - ++ Major bugfixes/improvements - - * Implemented tcp_shutdown() to only shut down one end of a connection - * Implemented shutdown() at socket- and netconn-level - * Added errorset support to select() + improved select speed overhead - * Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x) - * Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1 - * Use macros defined in ip_addr.h to work with IP addresses - * Implemented many nonblocking socket/netconn functions - * Fixed ARP input processing: only add a new entry if a request was directed as us - * mem_realloc() to mem_trim() to prevent confusion with realloc() - * Some improvements for AutoIP (don't route/forward link-local addresses, don't break - existing connections when assigning a routable address) - * Correctly handle remote side overrunning our rcv_wnd in ooseq case - * Removed packing from ip_addr_t, the packed version is now only used in protocol headers - * Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0 - * Added support for static ARP table entries - -(STABLE-1.3.2) - - * initial version of this file diff --git a/components/net/lwip-2.0.2/doc/FILES b/components/net/lwip-2.0.2/doc/FILES deleted file mode 100644 index e588575085..0000000000 --- a/components/net/lwip-2.0.2/doc/FILES +++ /dev/null @@ -1,9 +0,0 @@ -doxygen/ - Configuration files and scripts to create the lwIP doxygen source - documentation (found at http://www.nongnu.org/lwip/) - -savannah.txt - How to obtain the current development source code. -contrib.txt - How to contribute to lwIP as a developer. -rawapi.txt - The documentation for the core API of lwIP. - Also provides an overview about the other APIs and multithreading. -sys_arch.txt - The documentation for a system abstraction layer of lwIP. -ppp.txt - Documentation of the PPP interface for lwIP. diff --git a/components/net/lwip-2.0.2/doc/NO_SYS_SampleCode.c b/components/net/lwip-2.0.2/doc/NO_SYS_SampleCode.c deleted file mode 100644 index f5c6c10b61..0000000000 --- a/components/net/lwip-2.0.2/doc/NO_SYS_SampleCode.c +++ /dev/null @@ -1,117 +0,0 @@ -void eth_mac_irq() -{ - /* Service MAC IRQ here */ - - /* Allocate pbuf from pool (avoid using heap in interrupts) */ - struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL); - - if(p != NULL) { - /* Copy ethernet frame into pbuf */ - pbuf_take(p, eth_data, eth_data_count); - - /* Put in a queue which is processed in main loop */ - if(!queue_try_put(&queue, p)) { - /* queue is full -> packet loss */ - pbuf_free(p); - } - } -} - -static err_t netif_output(struct netif *netif, struct pbuf *p) -{ - LINK_STATS_INC(link.xmit); - - /* Update SNMP stats (only if you use SNMP) */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len); - int unicast = ((p->payload[0] & 0x01) == 0); - if (unicast) { - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - } else { - MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); - } - - lock_interrupts(); - pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0); - /* Start MAC transmit here */ - unlock_interrupts(); - - return ERR_OK; -} - -static void netif_status_callback(struct netif *netif) -{ - printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif))); -} - -static err_t netif_init(struct netif *netif) -{ - netif->linkoutput = netif_output; - netif->output = etharp_output; - netif->output_ip6 = ethip6_output; - netif->mtu = ETHERNET_MTU; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; - MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000); - - SMEMCPY(netif->hwaddr, your_mac_address_goes_here, sizeof(netif->hwaddr)); - netif->hwaddr_len = sizeof(netif->hwaddr); - - return ERR_OK; -} - -void main(void) -{ - struct netif netif; - - lwip_init(); - - netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input); - netif.name[0] = 'e'; - netif.name[1] = '0'; - netif_create_ip6_linklocal_address(&netif, 1); - netif.ip6_autoconfig_enabled = 1; - netif_set_status_callback(&netif, netif_status_callback); - netif_set_default(&netif); - netif_set_up(&netif); - - /* Start DHCP and HTTPD */ - dhcp_init(); - httpd_init(); - - while(1) { - /* Check link state, e.g. via MDIO communication with PHY */ - if(link_state_changed()) { - if(link_is_up()) { - netif_set_link_up(&netif); - } else { - netif_set_link_down(&netif); - } - } - - /* Check for received frames, feed them to lwIP */ - lock_interrupts(); - struct pbuf* p = queue_try_get(&queue); - unlock_interrupts(); - - if(p != NULL) { - LINK_STATS_INC(link.recv); - - /* Update SNMP stats (only if you use SNMP) */ - MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - int unicast = ((p->payload[0] & 0x01) == 0); - if (unicast) { - MIB2_STATS_NETIF_INC(netif, ifinucastpkts); - } else { - MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); - } - - if(netif.input(p, &netif) != ERR_OK) { - pbuf_free(p); - } - } - - /* Cyclic lwIP timers check */ - sys_check_timeouts(); - - /* your application goes here */ - } -} diff --git a/components/net/lwip-2.0.2/doc/contrib.txt b/components/net/lwip-2.0.2/doc/contrib.txt deleted file mode 100644 index 6f0d7bc516..0000000000 --- a/components/net/lwip-2.0.2/doc/contrib.txt +++ /dev/null @@ -1,58 +0,0 @@ -1 Introduction - -This document describes some guidelines for people participating -in lwIP development. - -2 How to contribute to lwIP - -Here is a short list of suggestions to anybody working with lwIP and -trying to contribute bug reports, fixes, enhancements, platform ports etc. -First of all as you may already know lwIP is a volunteer project so feedback -to fixes or questions might often come late. Hopefully the bug and patch tracking -features of Savannah help us not lose users' input. - -2.1 Source code style: - -1. do not use tabs. -2. indentation is two spaces per level (i.e. per tab). -3. end debug messages with a trailing newline (\n). -4. one space between keyword and opening bracket. -5. no space between function and opening bracket. -6. one space and no newline before opening curly braces of a block. -7. closing curly brace on a single line. -8. spaces surrounding assignment and comparisons. -9. don't initialize static and/or global variables to zero, the compiler takes care of that. -10. use current source code style as further reference. - -2.2 Source code documentation style: - -1. JavaDoc compliant and Doxygen compatible. -2. Function documentation above functions in .c files, not .h files. - (This forces you to synchronize documentation and implementation.) -3. Use current documentation style as further reference. - -2.3 Bug reports and patches: - -1. Make sure you are reporting bugs or send patches against the latest - sources. (From the latest release and/or the current Git sources.) -2. If you think you found a bug make sure it's not already filed in the - bugtracker at Savannah. -3. If you have a fix put the patch on Savannah. If it is a patch that affects - both core and arch specific stuff please separate them so that the core can - be applied separately while leaving the other patch 'open'. The preferred way - is to NOT touch archs you can't test and let maintainers take care of them. - This is a good way to see if they are used at all - the same goes for unix - netifs except tapif. -4. Do not file a bug and post a fix to it to the patch area. Either a bug report - or a patch will be enough. - If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area. -5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other - trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you - change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than - if it's not to the point and long :) so the chances for it to be applied are greater. - -2.4 Platform porters: - -1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and - you think it could benefit others[1] you might want discuss this on the mailing list. You - can also ask for Git access to submit and maintain your port in the contrib Git module. diff --git a/components/net/lwip-2.0.2/doc/doxygen/generate.bat b/components/net/lwip-2.0.2/doc/doxygen/generate.bat deleted file mode 100644 index 4eab18c7f4..0000000000 --- a/components/net/lwip-2.0.2/doc/doxygen/generate.bat +++ /dev/null @@ -1 +0,0 @@ -doxygen lwip.Doxyfile diff --git a/components/net/lwip-2.0.2/doc/doxygen/generate.sh b/components/net/lwip-2.0.2/doc/doxygen/generate.sh deleted file mode 100644 index 89344b0e81..0000000000 --- a/components/net/lwip-2.0.2/doc/doxygen/generate.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -doxygen lwip.Doxyfile diff --git a/components/net/lwip-2.0.2/doc/doxygen/lwip.Doxyfile b/components/net/lwip-2.0.2/doc/doxygen/lwip.Doxyfile deleted file mode 100644 index 0e3349a79a..0000000000 --- a/components/net/lwip-2.0.2/doc/doxygen/lwip.Doxyfile +++ /dev/null @@ -1,2505 +0,0 @@ -# Doxyfile 1.8.11 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. -# The default value is: UTF-8. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by -# double-quotes, unless you are using Doxywizard) that should identify the -# project for which the documentation is generated. This name is used in the -# title of most generated pages and in a few other places. -# The default value is: My Project. - -PROJECT_NAME = "lwIP" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. This -# could be handy for archiving the generated documentation or if some version -# control system is used. - -PROJECT_NUMBER = "2.0.2" - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a -# quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "Lightweight IP stack" - -# With the PROJECT_LOGO tag one can specify a logo or an icon that is included -# in the documentation. The maximum height of the logo should not exceed 55 -# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy -# the logo to the output directory. - -PROJECT_LOGO = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path -# into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If -# left blank the current directory will be used. - -OUTPUT_DIRECTORY = output - -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. -# The default value is: NO. - -CREATE_SUBDIRS = NO - -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII -# characters to appear in the names of generated files. If set to NO, non-ASCII -# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode -# U+3044. -# The default value is: NO. - -ALLOW_UNICODE_NAMES = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. -# The default value is: English. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member -# descriptions after the members that are listed in the file and class -# documentation (similar to Javadoc). Set to NO to disable this. -# The default value is: YES. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief -# description of a member or function before the detailed description -# -# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. -# The default value is: YES. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator that is -# used to form the text in various listings. Each string in this list, if found -# as the leading text of the brief description, will be stripped from the text -# and the result, after processing the whole list, is used as the annotated -# text. Otherwise, the brief description is used as-is. If left blank, the -# following values are used ($name is automatically replaced with the name of -# the entity):The $name class, The $name widget, The $name file, is, provides, -# specifies, contains, represents, a, an and the. - -ABBREVIATE_BRIEF = "The $name class " \ - "The $name widget " \ - "The $name file " \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief -# description. -# The default value is: NO. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. -# The default value is: NO. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path -# before files name in the file list and in the header files. If set to NO the -# shortest path that makes the file name unique will be used -# The default value is: YES. - -FULL_PATH_NAMES = YES - -# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. -# Stripping is only done if one of the specified strings matches the left-hand -# part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to -# strip. -# -# Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. -# This tag requires that the tag FULL_PATH_NAMES is set to YES. - -STRIP_FROM_PATH = ../../ - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the -# path mentioned in the documentation of a class, which tells the reader which -# header file to include in order to use a class. If left blank only the name of -# the header file containing the class definition is used. Otherwise one should -# specify the list of include paths that are normally passed to the compiler -# using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't -# support long names like on DOS, Mac, or CD-ROM. -# The default value is: NO. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) -# The default value is: NO. - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) -# The default value is: NO. - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a -# multi-line C++ special comment block (i.e. a block of //! or /// comments) as -# a brief description. This used to be the default behavior. The new default is -# to treat a multi-line C++ comment block as a detailed description. Set this -# tag to YES if you prefer the old behavior instead. -# -# Note that setting this tag to YES also means that rational rose comments are -# not recognized any more. -# The default value is: NO. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the -# documentation from any documented member that it re-implements. -# The default value is: YES. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new -# page for each member. If set to NO, the documentation of a member will be part -# of the file/class/namespace that contains it. -# The default value is: NO. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen -# uses this value to replace tabs by spaces in code fragments. -# Minimum value: 1, maximum value: 16, default value: 4. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that act as commands in -# the documentation. An alias has the form: -# name=value -# For example adding -# "sideeffect=@par Side Effects:\n" -# will allow you to put the command \sideeffect (or @sideeffect) in the -# documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. - -ALIASES = - -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. For -# instance, some of the names that are used will be different. The list of all -# members will be omitted, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or -# Python sources only. Doxygen will then generate output that is more tailored -# for that language. For instance, namespaces will be presented as packages, -# qualified scopes will look different, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources. Doxygen will then generate output that is tailored for Fortran. -# The default value is: NO. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for VHDL. -# The default value is: NO. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given -# extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. -# -# Note: For files without extension you can use no_extension as a placeholder. -# -# Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments -# according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in -# case of backward compatibilities issues. -# The default value is: YES. - -MARKDOWN_SUPPORT = YES - -# When enabled doxygen tries to link words that correspond to documented -# classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. -# The default value is: YES. - -AUTOLINK_SUPPORT = YES - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. -# The default value is: NO. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. -# The default value is: NO. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. -# The default value is: NO. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. -# This will only work if the methods are indeed getting or setting a simple -# type. If this is not the case, or you want to show the methods anyway, you -# should set this option to NO. -# The default value is: YES. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. -# The default value is: NO. - -DISTRIBUTE_GROUP_DOC = NO - -# If one adds a struct or class to a group and this option is enabled, then also -# any nested class or struct is added to the same group. By default this option -# is disabled and one has to add nested compounds explicitly via \ingroup. -# The default value is: NO. - -GROUP_NESTED_COMPOUNDS = NO - -# Set the SUBGROUPING tag to YES to allow class member groups of the same type -# (for instance a group of public functions) to be put as a subgroup of that -# type (e.g. under the Public Functions section). Set it to NO to prevent -# subgrouping. Alternatively, this can be done per class using the -# \nosubgrouping command. -# The default value is: YES. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions -# are shown inside the group in which they are included (e.g. using \ingroup) -# instead of on a separate page (for HTML and Man pages) or section (for LaTeX -# and RTF). -# -# Note that this feature does not work in combination with -# SEPARATE_MEMBER_PAGES. -# The default value is: NO. - -INLINE_GROUPED_CLASSES = NO - -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions -# with only public data fields or simple typedef fields will be shown inline in -# the documentation of the scope in which they are defined (i.e. file, -# namespace, or group documentation), provided this scope is documented. If set -# to NO, structs, classes, and unions are shown on a separate page (for HTML and -# Man pages) or section (for LaTeX and RTF). -# The default value is: NO. - -INLINE_SIMPLE_STRUCTS = NO - -# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or -# enum is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically be -# useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. -# The default value is: NO. - -TYPEDEF_HIDES_STRUCT = NO - -# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This -# cache is used to resolve symbols given their name and scope. Since this can be -# an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The -# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range -# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest -# the optimal cache size from a speed point of view. -# Minimum value: 0, maximum value: 9, default value: 0. - -LOOKUP_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in -# documentation are documented, even if no documentation was available. Private -# class members and static file members will be hidden unless the -# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. -# Note: This will also disable the warnings about undocumented members that are -# normally produced when WARNINGS is set to YES. -# The default value is: NO. - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will -# be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal -# scope will be included in the documentation. -# The default value is: NO. - -EXTRACT_PACKAGE = NO - -# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be -# included in the documentation. -# The default value is: NO. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO, -# only classes defined in header files are included. Does not have any effect -# for Java sources. -# The default value is: YES. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. If set to YES, local methods, -# which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO, only methods in the interface are -# included. -# The default value is: NO. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base name of -# the file that contains the anonymous namespace. By default anonymous namespace -# are hidden. -# The default value is: NO. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all -# undocumented members inside documented classes or files. If set to NO these -# members will be included in the various overviews, but no documentation -# section is generated. This option has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_MEMBERS = YES - -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. If set -# to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. -# The default value is: NO. - -HIDE_UNDOC_CLASSES = YES - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. -# The default value is: NO. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO, these -# blocks will be appended to the function's detailed documentation block. -# The default value is: NO. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation that is typed after a -# \internal command is included. If the tag is set to NO then the documentation -# will be excluded. Set it to YES to include the internal documentation. -# The default value is: NO. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES, the -# scope will be hidden. -# The default value is: NO. - -HIDE_SCOPE_NAMES = NO - -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will -# append additional text to a page's title, such as Class Reference. If set to -# YES the compound reference will be hidden. -# The default value is: NO. - -HIDE_COMPOUND_REFERENCE= NO - -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of -# the files that are included by a file in the documentation of that file. -# The default value is: YES. - -SHOW_INCLUDE_FILES = YES - -# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each -# grouped member an include statement to the documentation, telling the reader -# which file to include in order to use the member. -# The default value is: NO. - -SHOW_GROUPED_MEMB_INC = NO - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include -# files with double quotes in the documentation rather than with sharp brackets. -# The default value is: NO. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the -# documentation for inline members. -# The default value is: YES. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the -# (detailed) documentation of file and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. -# The default value is: YES. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief -# descriptions of file, namespace and class members alphabetically by member -# name. If set to NO, the members will appear in declaration order. Note that -# this will also influence the order of the classes in the class list. -# The default value is: NO. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the -# (brief and detailed) documentation of class members so that constructors and -# destructors are listed first. If set to NO the constructors will appear in the -# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. -# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief -# member documentation. -# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting -# detailed member documentation. -# The default value is: NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy -# of group names into alphabetical order. If set to NO the group names will -# appear in their defined order. -# The default value is: NO. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by -# fully-qualified names, including namespaces. If set to NO, the class list will -# be sorted only by class name, not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the alphabetical -# list. -# The default value is: NO. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper -# type resolution of all parameters of a function it will reject a match between -# the prototype and the implementation of a member function even if there is -# only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still -# accept a match between prototype and implementation in such cases. -# The default value is: NO. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo -# list. This list is created by putting \todo commands in the documentation. -# The default value is: YES. - -GENERATE_TODOLIST = NO - -# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test -# list. This list is created by putting \test commands in the documentation. -# The default value is: YES. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug -# list. This list is created by putting \bug commands in the documentation. -# The default value is: YES. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) -# the deprecated list. This list is created by putting \deprecated commands in -# the documentation. -# The default value is: YES. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional documentation -# sections, marked by \if ... \endif and \cond -# ... \endcond blocks. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the -# initial value of a variable or macro / define can have for it to appear in the -# documentation. If the initializer consists of more lines than specified here -# it will be hidden. Use a value of 0 to hide initializers completely. The -# appearance of the value of individual variables and macros / defines can be -# controlled using \showinitializer or \hideinitializer command in the -# documentation regardless of this setting. -# Minimum value: 0, maximum value: 10000, default value: 30. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES, the -# list will mention the files that were used to generate the documentation. -# The default value is: YES. - -SHOW_USED_FILES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This -# will remove the Files entry from the Quick Index and from the Folder Tree View -# (if specified). -# The default value is: YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces -# page. This will remove the Namespaces entry from the Quick Index and from the -# Folder Tree View (if specified). -# The default value is: YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command command input-file, where command is the value of the -# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file -# version. For an example see the documentation. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can -# optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. -# -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE -# tag is left empty. - -LAYOUT_FILE = - -# The CITE_BIB_FILES tag can be used to specify one or more bib files containing -# the reference definitions. This must be a list of .bib files. The .bib -# extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. -# For LaTeX the style of the bibliography can be controlled using -# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. See also \cite for info how to create references. - -CITE_BIB_FILES = - -#--------------------------------------------------------------------------- -# Configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the -# messages are off. -# The default value is: NO. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES -# this implies that the warnings are on. -# -# Tip: Turn warnings on while writing the documentation. -# The default value is: YES. - -WARNINGS = YES - -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate -# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: YES. - -WARN_IF_UNDOCUMENTED = YES - -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. -# The default value is: YES. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that -# are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. -# The default value is: NO. - -WARN_NO_PARAMDOC = NO - -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. -# The default value is: NO. - -WARN_AS_ERROR = NO - -# The WARN_FORMAT tag determines the format of the warning messages that doxygen -# can produce. The string should contain the $file, $line, and $text tags, which -# will be replaced by the file and line number from which the warning originated -# and the warning text. Optionally the format may contain $version, which will -# be replaced by the version of the file (if it could be obtained via -# FILE_VERSION_FILTER) -# The default value is: $file:$line: $text. - -WARN_FORMAT = "$file:$line: $text " - -# The WARN_LOGFILE tag can be used to specify a file to which warning and error -# messages should be written. If left blank the output is written to standard -# error (stderr). - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# Configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag is used to specify the files and/or directories that contain -# documented source files. You may enter file names like myfile.cpp or -# directories like /usr/src/myproject. Separate the files or directories with -# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING -# Note: If this tag is empty the current directory is searched. - -INPUT = main_page.h ../../src - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses -# libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of -# possible encodings. -# The default value is: UTF-8. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. -# -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, -# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.inc \ - *.m \ - *.mm \ - *.dox - -# The RECURSIVE tag can be used to specify whether or not subdirectories should -# be searched for input files as well. -# The default value is: NO. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should be -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. -# -# Note that relative paths are relative to the directory from which doxygen is -# run. - -EXCLUDE = ../../src/include/netif/ppp/polarssl - -# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. -# The default value is: NO. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or directories -# that contain example code fragments that are included (see the \include -# command). - -EXAMPLE_PATH = ../ ../../ - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank all -# files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude commands -# irrespective of the value of the RECURSIVE tag. -# The default value is: NO. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or directories -# that contain images that are to be included in the documentation (see the -# \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command: -# -# -# -# where is the value of the INPUT_FILTER tag, and is the -# name of an input file. Doxygen will then use the output that the filter -# program writes to standard output. If FILTER_PATTERNS is specified, this tag -# will be ignored. -# -# Note that the filter must not add or remove lines; it is applied before the -# code is scanned, but not when the output code is generated. If lines are added -# or removed, the anchors will not be placed correctly. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: pattern=filter -# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how -# filters are used. If the FILTER_PATTERNS tag is empty or if none of the -# patterns match the file name, INPUT_FILTER is applied. -# -# Note that for custom extensions or not directly supported extensions you also -# need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will also be used to filter the input files that are used for -# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). -# The default value is: NO. - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and -# it is also possible to disable source filtering for a specific pattern using -# *.ext= (so without naming a filter). -# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. - -FILTER_SOURCE_PATTERNS = - -# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page -# (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. - -USE_MDFILE_AS_MAINPAGE = main_page.h - -#--------------------------------------------------------------------------- -# Configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will be -# generated. Documented entities will be cross-referenced with these sources. -# -# Note: To get rid of all source code in the generated output, make sure that -# also VERBATIM_HEADERS is set to NO. -# The default value is: NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. -# The default value is: NO. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any -# special comment blocks from generated source code fragments. Normal C, C++ and -# Fortran comments will always remain visible. -# The default value is: YES. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. -# The default value is: NO. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES then for each documented function -# all documented entities called/used by that function will be listed. -# The default value is: NO. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES then the hyperlinks from functions in REFERENCES_RELATION and -# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will -# link to the documentation. -# The default value is: YES. - -REFERENCES_LINK_SOURCE = YES - -# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the -# source code will show a tooltip with additional information such as prototype, -# brief description and links to the definition and documentation. Since this -# will make the HTML file larger and loading of large files a bit slower, you -# can opt to disable this feature. -# The default value is: YES. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -SOURCE_TOOLTIPS = YES - -# If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in -# source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version -# 4.8.6 or higher. -# -# To use it do the following: -# - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file -# - Make sure the INPUT points to the root of the source tree -# - Run doxygen as normal -# -# Doxygen will invoke htags (and that will in turn invoke gtags), so these -# tools must be available from the command line (i.e. in the search path). -# -# The result: instead of the source browser generated by doxygen, the links to -# source code will now point to the output of htags. -# The default value is: NO. -# This tag requires that the tag SOURCE_BROWSER is set to YES. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a -# verbatim copy of the header file for each class for which an include is -# specified. Set to NO to disable this. -# See also: Section \class. -# The default value is: YES. - -VERBATIM_HEADERS = NO - -# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. -# Note: The availability of this option depends on whether or not doxygen was -# generated with the -Duse-libclang=ON option for CMake. -# The default value is: NO. - -CLANG_ASSISTED_PARSING = NO - -# If clang assisted parsing is enabled you can provide the compiler with command -# line options that you would normally use when invoking the compiler. Note that -# the include paths will already be set by doxygen for the files and directories -# specified with INPUT and INCLUDE_PATH. -# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. - -CLANG_OPTIONS = - -#--------------------------------------------------------------------------- -# Configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all -# compounds will be generated. Enable this if the project contains a lot of -# classes, structs, unions or interfaces. -# The default value is: YES. - -ALPHABETICAL_INDEX = NO - -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output -# The default value is: YES. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a -# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of -# it. -# The default directory is: html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each -# generated HTML page (for example: .htm, .php, .asp). -# The default value is: .html. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a -# standard header. -# -# To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. -# the setting GENERATE_TREEVIEW). It is highly recommended to start with a -# default header using -# doxygen -w html new_header.html new_footer.html new_stylesheet.css -# YourConfigFile -# and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally -# uses. -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description -# of the possible markers and block names see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard -# footer. See HTML_HEADER for more information on how to generate a default -# footer and what special commands can be used inside the footer. See also -# section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style -# sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. -# See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. -# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as -# it is more robust and this tag (HTML_STYLESHEET) will in the future become -# obsolete. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined -# cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. -# This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefore more robust against future updates. -# Doxygen will copy the style sheet files to the output directory. -# Note: The order of the extra style sheet files is of importance (e.g. the last -# style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that the -# files will be copied as-is; there are no commands or markers available. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value -# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 -# purple, and 360 is red again. -# Minimum value: 0, maximum value: 359, default value: 220. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A -# value of 255 will produce the most vivid colors. -# Minimum value: 0, maximum value: 255, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the -# luminance component of the colors in the HTML output. Values below 100 -# gradually make the output lighter, whereas values above 100 make the output -# darker. The value divided by 100 is the actual gamma applied, so 80 represents -# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not -# change the gamma. -# Minimum value: 40, maximum value: 240, default value: 80. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_DYNAMIC_SECTIONS = NO - -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries -# shown in the various tree structured indices initially; the user can expand -# and collapse entries dynamically later on. Doxygen will expand the tree to -# such a level that at most the specified number of entries are visible (unless -# a fully collapsed tree already exceeds this amount). So setting the number of -# entries 1 will produce a full collapsed tree by default. 0 is a special value -# representing an infinite number of entries and will result in a full expanded -# tree by default. -# Minimum value: 0, maximum value: 9999, default value: 100. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_INDEX_NUM_ENTRIES = 100 - -# If the GENERATE_DOCSET tag is set to YES, additional index files will be -# generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_DOCSET = NO - -# This tag determines the name of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# The default value is: Doxygen generated docs. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# This tag specifies a string that should uniquely identify the documentation -# set bundle. This should be a reverse domain-name style string, e.g. -# com.mycompany.MyDocSet. Doxygen will append .docset to the name. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. -# The default value is: org.doxygen.Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. -# The default value is: Publisher. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three -# additional HTML index files: index.hhp, index.hhc, and index.hhk. The -# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. -# -# The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML -# files are now used as the Windows 98 help format, and will replace the old -# Windows help format (.hlp) on all Windows platforms in the future. Compressed -# HTML files also contain an index, a table of contents, and you can search for -# words in the documentation. The HTML workshop also contains a viewer for -# compressed HTML files. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_HTMLHELP = NO - -# The CHM_FILE tag can be used to specify the file name of the resulting .chm -# file. You can add a path in front of the file if the result should not be -# written to the html output directory. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_FILE = lwip.chm - -# The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. -# The file has to be specified with full path. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -HHC_LOCATION = - -# The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -GENERATE_CHI = NO - -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) -# and project file content. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -CHM_INDEX_ENCODING = - -# The BINARY_TOC flag controls whether a binary table of contents is generated -# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it -# enables the Previous and Next buttons. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members to -# the table of contents of the HTML help documentation and to the tree view. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTMLHELP is set to YES. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that -# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help -# (.qch) of the generated HTML documentation. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify -# the file name of the resulting .qch file. The path specified is relative to -# the HTML output folder. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help -# Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt -# Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- -# folders). -# The default value is: doc. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_VIRTUAL_FOLDER = doc - -# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom -# filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- -# filters). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHP_SECT_FILTER_ATTRS = - -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. -# This tag requires that the tag GENERATE_QHP is set to YES. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be -# generated, together with the HTML files, they form an Eclipse help plugin. To -# install this plugin and make it available under the help contents menu in -# Eclipse, the contents of the directory containing the HTML and XML files needs -# to be copied into the plugins directory of eclipse. The name of the directory -# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. -# After copying Eclipse needs to be restarted before the help appears. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the Eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have this -# name. Each documentation set should have its own identifier. -# The default value is: org.doxygen.Project. -# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# If you want full control over the layout of the generated HTML pages it might -# be necessary to disable the index and replace it with your own. The -# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top -# of each HTML page. A value of NO enables the index and the value YES disables -# it. Since the tabs in the index contain the same information as the navigation -# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -DISABLE_INDEX = NO - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. If the tag -# value is set to YES, a side panel will be generated containing a tree-like -# index structure (just like the one that is generated for HTML Help). For this -# to work a browser that supports JavaScript, DHTML, CSS and frames is required -# (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = YES - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. -# -# Note that a value of 0 will completely suppress the enum values from appearing -# in the overview section. -# Minimum value: 0, maximum value: 20, default value: 4. -# This tag requires that the tag GENERATE_HTML is set to YES. - -ENUM_VALUES_PER_LINE = 4 - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used -# to set the initial width (in pixels) of the frame in which the tree is shown. -# Minimum value: 0, maximum value: 1500, default value: 250. -# This tag requires that the tag GENERATE_HTML is set to YES. - -TREEVIEW_WIDTH = 250 - -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to -# external symbols imported via tag files in a separate window. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of LaTeX formulas included as images in -# the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML -# output directory to force them to be regenerated. -# Minimum value: 8, maximum value: 50, default value: 10. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX -# installed or if you want to formulas look prettier in the HTML output. When -# enabled you may also need to install MathJax separately and configure the path -# to it using the MATHJAX_RELPATH option. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -USE_MATHJAX = NO - -# When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. -# Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. -# The default value is: HTML-CSS. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_FORMAT = HTML-CSS - -# When MathJax is enabled you need to specify the location relative to the HTML -# output directory using the MATHJAX_RELPATH option. The destination directory -# should contain the MathJax.js script. For instance, if the mathjax directory -# is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax -# Content Delivery Network so you can quickly see the result without installing -# MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest - -# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax -# extension names that should be enabled during MathJax rendering. For example -# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_EXTENSIONS = - -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces -# of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an -# example see the documentation. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_CODEFILE = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and -# should work on any modern browser. Note that when using HTML help -# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) -# there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then -# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to -# search using the keyboard; to jump to the search box use + S -# (what the is depends on the OS and browser, but it is typically -# , /
index.html - - diff --git a/components/net/lwip-2.0.2/doc/doxygen_docs.zip b/components/net/lwip-2.0.2/doc/doxygen_docs.zip deleted file mode 100644 index a5f42e2343148cb1cc22e6112f7f881dfaa0441e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2106820 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

PxqcS9! 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

P$9yeXeV+^$475AD&v_LTj~9XhH-vPve9;`;v;< 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

QsI#Z8 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 z⪙MiF=q$XA}YtuKjI@;LTl&C$T*@4Wwu)e|=YuW5a*PxV!&8g)2d{8AP`;>H?X{N}$e;_EG|q4NzT*N2?I7$W2#-z=}ejN$Y`BTG+dl z6Jz@sgX!r3k0?T^%>4u%q&)|&WyUmDmc=gCccR~Cc0eViV!RX9MLh1BvIrKX305}rL;I50W#UF8!2e~&dvt09J$BokdvVo(dCS7tvCyA zdJ3DD>==}#-wRN{p2O)kc`P~70^B@$FZDmGO&-@C+?}0X>I#lnKXZLE{i_z^bxxJF zsGMtSAomW5n|UMO7N@zh&_E|FDeZV6m9@GTZf&)i)|g$mZf4U!?8F4B*axSWzseol zKdVim%fyvTS$3TNS#1IfS*JE9YQ*XHZFIp>U+#IVzw1EVh$-ti9Vk=WE-V+q!$M74 z6)7jh|7BTa2SYzrZYn2uDQa8$m`nXwSThf)4bNt5;f|d1S<7DYZK3;DuiQ_CO`?4Q z-73Rwh)jirvE9i4rH<=g8f+xC>M6nLqjC>o>*+s=oy6e;q~3%Or%@%ev$yhQ6*`Sg zOur=Cosh<*(=8DBOZ5$$sk)HPp^!#~)_+@j1wm@r(oTurNPGm=+J-!DppvvR_e!EwcB5sh0Y0EeKy24 z{fBt^)QEfIRRaeuxiN{+m$-c=KNXPXY>rQ%9;=qh-H5A)It|a~(m5{K7{?vz=_tRZ z^&Te2yACRef4A#j>+g1H(BwKD)=cQB{2vTkY{P9PyH}PRJ1N^9*xEZ}4O7H2!bB>h z(o3-7s-xCG()9OA46mV{ofx$_N!Hg(kzq^I)}mo-_D5pv+lh9!41(!5xwPMI-5m@u zL6_LQ0@_;zEjdXI#Kn|Fw||0~sgxj;Ls!Nm;$9IB+C!`eAb)ME1szmDV|I<0g1_R5 zfDIUO8qJt4=HUI7-+fIawAGIx1GK&hW1cc1>)6{g9H^mZagk5V2FRPRuMdK@x}$Q0 zi7x*}CK59}50_lAl#?Wq0lRjNYoPByD=?Y8>_Ed?`prysE|jPKOHv09o;$f(7@|C( zuj7tJba>2Qdub@S2x_chvZl+wm?XZB$QX>BeJ!JH3HG`;Tync(@$!1bsY0xQS+cPD zw&8{91__D?;<7t|5Sk|LEMzzy+5M$4N0J7km=q(3qLeT3DJB8p7a@7F54ckH4b-f$ zRFVXCfH`lR1rX6LnxR)#tQ_ zrxSlSmq0tet%88BjYTPj2-<$cNe{!AS9&W)Kl#_HKz`wJh&on;Y1DKe5TCg{F-S(C zlvYD;xI*dtbYmvN<)Ii)ch{RICto4qrEy#fCRJj$w6rD=BM4CX^GqyOYhz+$<9TiD z^Kb>_{P(sXRU$6ru9+z7fvY+$$_XVWz)A%7&q?Y9o?>V~cMEhk3b1D2xF`f>w=gs| zQ6`ijnkt)7_l-BfFreMEBB#l>-keNEaggxF;3E(SIH9mJ<-JF@gwS96O6T;rGZi0q zo6|EFpbvTC;#u-bwB*suh{kg1A}G>DO*DwE)Rp&!JTVG%a;b<*G(SQjx2=j10&&QR zu70Di*Wmbi>)40K`Dr2hKFnUXsMqh|~4fH~<(~oYW zGV#4m-nN_xThjptS(OvJS^$mT{ch@Ty>lGHev{wJ)&1N3h`8u~q__tG7!Wm@4 z2XcB%ApD%>RBZEX~ zoZCcRLv@hzFM(Mggp*cm-6NEppC%6&) zWzgmMId$oW7hoJ7LOVbjPpgOHGRrR$usQVg%Om4;EXM~y`%9Qj2hP2Q4KqGqGCT;o z@~JruDpqyUb|*UEC1LO=ve$c)M|;|-3>+6bD3yj*BFLY-VVU_8W110{%JnxALRw#B z=HuUS@S&{RYTNg6{ExXTW#|DqENvG+|56rnWmj$c5Yz4o`-#xznomTx9~icu&#{^i zgD}*H?kslz5Gs5Xny5+8k^l(77{G#IFAc{Bz8*7v7W7|0boMw;$$6lB!`~~9olh3O z!-LPv)@uT`b2{dAF#qzP)j~t_Q&l`zp0o?LQ;A_9@T0RB?xOVgGJ0%)=7D%#k9%j& z>x~}oZ|g7G?;5L%F73=DwZ+cxFt&&(a7(?D^+wlD%MZOpDQDIIgq=-53&dR9NE9wy zn2p*bhTpV{c=e4@boxlcbtREzYrf0`rj#QQYi?1dO$_AL^wECjW@4*7VrB(QOo-VUWMlLdCOO_F6!vrz zNeKYQr5{7T)9w5snjx^0=W*w0bsyCs6pU!1wxr@!*@_%5PXdJQ13lPIwb%D-s(rsg zq#go3r;UwD5pR_}Yl9QF~>YN|s_ovcU z`zHbJ7p?7Fp0SXbd9EB@Kl}xKkX-5ZhE4T9 zgl{zA7GT|~%XcGAza%fffEAQ%;WY%2$$D%IrUwkse|hmvB_>B4ZT&Ql}`o0Vyd1bN^-=?MOeUtwV@JE9FlX?Dr%4{zgO5}Baoyaj~oWbk2PuUG(N1F)}?V zCG~I6$_X0|v22lif!Sh~-zN)G-}`GZvR40tYov{mu6_cGjPlIV*a+S>LtNxffzbZT z%pU*e@uXK)N1Rq|nJhQ+F&F@oz7Tan6FP4i{68;-uAu8(fzdLDtK`23rW}%&oYE!i zbbp3Kte)AfldEaSEkPqowz8P9Fe6m_)?(fR?(#jQ1ig+pqFIK4UskwEnBssA<4}=3 z2dtjNi}Dg4XW++8yOe9yKKn;i`JO54sP6)KMdwmY>EavfExP&dD*4Xm&P7?=XU}9P z*)ih;X%Hr}HO`fdN_QswGJSRn1D8DzzvgLM#{1?a`tr&M)fB*AZmvwtXzl_{&Ya<1 zc)1F+w#__IhBjX@p7y8Qa0wndT)eE#5-0TvhNzCc*}cG!Bnmo$l~Zoxdwx@Io5NJ$vE0V_}xZnHw0+d`)?8i_1|QTQgfY+xkY)Z+>`9>$GhS+be$gM~0M&J^ zJu``kjQR1{VwXl1Q$2R9lq|oli6?8EGt0ZM-#b95-(W#b&fhRq5f^QdK+NVIe31#)0)B60|Ly7gKAzr)GdUOMJOW1-ZX%BACR^|T+{Bmt zbBpNEyER&f^rl%7eJ*XBrSX60lR>K~llb zxZV^etoluuJ?)!K2~M>@lVidrLT+F0-#}126@XzbW`rZM2)%~IwG~dzMWDt85p!x=(uc`5^Vh+<}lox z&=H^NnW?*QUml_^p1XRxzZwJo?f3jSOd*Wff{|1T*%e*n@oErf=s7Qp|BiBT^ z5|A+J+M=&_6!2V?()w#|xd;~lCPySg%LsrYOI?CoO~Gj<7B;Ks6DiXo#Gm}d@BM_< zJqwb}6Ge^JE#XGf?d<p;%n<08~v0j#r*f#q5Dr~d8THZ6jZu3_^audSfoG5OkkpQx8DCEsWu=rqLFrL|foJFG>;4&eWu5%lL|40P&ctID49ONIoyC`2pmNG=?5w{X z`d%VnHv6ghars;$@cVr~(iX;y6kYNpx^aq?+$~E>N)wWRoV4^r;C-)OfuY2HDXR&? zQfSLroT`yz@^5xtEXzr6mv#*yU#XUr)leLFGpEk4${@KB@F3EvEP#6F`!)jA)duDM zd^^DZAwm|diS2x-92K1V_K30(;dhfkk6-ss;eu|qz^el^tlVRc?Sv6_BaP8AU{F-v z29e%W!{TsubK~={EGS5O0H|82D>bk%zCM8&ow4ShE0NyTYVVyN$K)naNXc9!9vTnmx6o}7bNbiqRFN}B^8h;O*)zJiq$@qD`JhoKkA+7_N#_qShehdS< zLvgxf2rH;2R$4l(^ad^ANd0%}XNz24$L3_#qQ}7MlW@DCqN1&~395gr1vLr!J}MjBnPl#$L%9AVUF|sPp{GG5mZg2Z=S+9Ebc;NqJC2aHQIP$vyr?9sJOsTMOGX zv0D4>)%ot8zV?lZ-aWth9QLmu7V*jN8~T+Qzmoc^ov+@1qqn7V+Pmt`hqA1Vfxe3Y zrsHG8=WuvX6|#!&T)E(R`_bY1BjyVJDHm`O#yuKKHv8;~`i#!AAno%y@BS_JS^09Y zTiuy?t#1I}zxwiRNDB0A+ReYX+Dd|5=#6go#;tg#R~_FM0Q%py@o>%`Ejkz=pk;g@ zpda@b$kN5uhQY$d-q^^-*}&zugW3Obj;CrFA?oF|Gg`Ff&8=zvdZ5(?67Q%S4x}#i zy9Qpi(1d?aaak=@ovnn%wG1*m^FF^!xo_=!%|Bc0+Y{u(r)SID?cOJH)J{P?dVk9} z9K9t7C{O;9M8Qse|ZCJK!Wa&1@#5W#2UwkWiEb zUmgOh6R41gH4kxdbN|x5T>8bIP`hHR59@T<5c*IzwqL`OH=`wj` ziOpUk8?DeGp9P*?bfo#kOOIW;w zJB)lC&!QX>G3cGLvqg;4QB}lf?&0$(h{O~tS3`bB5X)=h9cMt(c?PWeJmlfE$U~MX z=rL(en9R5=ShZwi2VA$vFcYjk%?)V_N=w*hovGz#cfI+aY2I~%5Um-XY)Yi&${~Lc zD{@l8N3#0w4HUz$j;6O@9!?HLHaMn8wXHGDo*X4;G0Tm4J(6}3iWC@%@vGfKbZ-<$ zn6l(cP$fddAV@cYR+V>dnpaH?3ZMrDZPioo+7!X6HBAi>y@nXM!|&4Fu_7SEROt)4 zX34o8Hh$!}wRH0pPifxBNjvP{Bz=fSy;q|yRTxbL-_9e z5t|IboeFz&oS77@ZPF);DdlgbEGpJqX+5*YmQcaF$xUdJrN%@`k)_+z`qZK!PD-xSg>P-dCTRO-QE^D(R3%|EOxv9;Ys~L$f9La~F})}o zT44psPO?NHx@lbM>vYZlbmAtTD-b?{x3I%_`a-&YJu5qu?e_Fze^%lc)f#R37e|tJ z%L@JWj0doXy`6H9iUw&(T1yr_u?mhkTsqi`@~1py#_jluU5@!=ZX}wKdlb4#O4Z|8 zWORBow_rq2>TVYod+DNCP<1cJhvc5oFG&}ABRY7YM?q8(isU;m?bZ;kjF4n`fNo#X zo8F?wwlOEN>QM4ar6n=3e|S-t_E9^%#P-IDy)6WyXkmPETinmu0Zkl#=sc_i=`s zs%aTZ8P1UdQ3}eg(Gra{TtRt{r7SGcPS~M;Z`9KCfpl6--$N>0NVNi|W{R7r9K84F z0u)aY4$J4G3KZha#9k+h!xLQqdle^fGif~LkXD`Ujjsk=Zcm@9L(lsr3&zhVknPyV z|1`PG$=F?m1;azE!LB<8A4LuZORVhDQa>LUO1=!u>FJzjM(8A~t4&f?w8W}~?mi;R zW7AL+T5=zn@UY8dj85^rYLb$LkdwEX*kvGmz&Dlchl{sjo*&&lc;(*PxA`~u?VhQ> z*D&{E%yd)-w4D;@i%qOIlqXlk;$3WzxB1=;=!RfCJ?0dKe^Wh~Ap4Ll%SEEOkkF@3 zbWt5+vJ_`YS#J#R=^gIx-t8uzAd^I>f(2{Oe2DC*f=i2$a;{)^M@y6-zCA7OPU`?~=qi%szoC!>k!2#%@jykT zc`IDl4Io?M5PAf<1ah7vmOgDQy*9vdCjFRXRIi|=nK&%##aI-mG^Y2Ex-aa$2o#5* zI73=?z#I1tpChG8hS5G7fdWJhV?OzgCHzmTLW(xp=#m>s&vYEpCG?OE84 z=Rh%Nq#??G87q~ERjAr>%?fWW5Xj5;asG&uL|vb2i^gt!hWXO{{TK6bHIIe-0__Vr z2uRi_rOJ{&Kc#xjn>Srd9rwtaulyY>ew(>+y}U7imKQWt+9j{PBPuU(da||v=OMsZ z`}3wl8(qmb^86uxNn~~yLXV&Qyzd+P*^|+-z}FL1LQ%R=KNu5AzLA)Sl3M~m_m~^| z$uDUZbHX>utrj0U09*_}JL(KtbU+q`jld*r7+sm~sG?p%Mlxq*VB4L5jwMk>m72S^27S*9mViP-_VL97l?-S(*$YAqR(&=iv{U(Gh3;;xH*s zE(ddgseKAkp^*^$Q2@8=(Ov-DEz|zP>HcsuQi0tZ%;1=u*SV%HRt2$Xlj5Ao$chLK zQ89$;k|LQuaYkg^T~)1$wPBI-s-~h_y660XO4>yloBeKZ@yg|e3)BS?wj6C67$A@#uJ&w zcyA2M$A%3qM|XI&F5TF(d&^9|fw^<7V-2@WbNR`y6kOxSTwix>p*9`X%+J4X;(T#_ zb~SjtcNvZ={gpg)XqG;D(UK=MU+{kA`QHMwCO`E?0SXAn1?T^gOK|-kb@~4T3u>2J zttIPqG$$MC4yq}F@v6x?t$8?K8uE1ezg(}#HBW|MBtua&6xFRiCC(e!7veB7UgC77}4O)2bCFed_pA z!*U7$J!U(MW_Zzc#|bA5yCFL*IO+*vYX>kDf`65F`t<$@@{>v+cS|qK-*Ex`$Y>ml z%aSotOf&47iWAiJ{s9XnQ}tQ=H&~F<7yAb+h%tJ+v){j?JH-Of960A?$boyuiOO@v zO~8UtU653p_oCIX_OeTKnY()O6{E$ZXDOG3uQQF13WKKCj0*U+1V&*ON`mAr!41=! zHcs2+-1|?|Vizm**P$oUn+VN;tgdi{1K@`%X!jqk;7FKgCY!|n%N10+`QZxEvbc_d z>&@&X`K#Z?>3UBpRj*_Ga0QKsUO5aK(6LQ4thz(Co-}4cl)_uj8iXf%b|>{}vZTuL zzhirTIW<8#)W(l+<`yzewg_ib;nV|1)2wX~z<?_bviN}OJGnNSB_H$Xi)vDStH7AJ``r`gc1OPH2qRVVFM1Gi#3Q9J}z zz?M{UEr_(>@u8>`lC&bSPYuN6RKtSJ!i1B6aJ!8qmvFa^?q~?}0~QQG?9(?JF)!x| z=`XZ#JxZ!#yd`HQV_;-YYD_0g_LRbO$kJ9U^$EWR0pDuI{s9XPY=g^te%n2lIkVS& zMbH&{2Dz2`FhXUw5&nP$<<}&cvJz%#jvwdV5g4|#t}VT_0%+Gr-I^n*QyQT1 z6_Pel|Mb97B0CfdgJY=;nYW|z($G&8K&^9>sCD?7qN@tcYQ!GEgc3SH6I5J7v?Ir( zClM5}73-Q<_bRTpvbZ+dwalk~Zxec)z+VS@MO)E-EUsGqd*-`g_-8#nzp`zQm2840 z&!wl8ak*@~{=0Mmi*LIKh$F+|rr+3i!AUtYl*^15$wf$9&FXXS+>*l1%Y{{DhDKzf zd`TpsQBds}Q*~}qi3t^LEh6gQp3Crma|J(23YLHJCl>6rZKGomq<<~XxKXn6DNI36}d#kwzw$B14 zuy!(^VHH|q)H+4D9b_mGx`Fb=o0EM-P%1<4)N$#4MXfTg9VaD-{J^=qDX6zHOsVW# zP6168%f$5iGR&SaFacJ1ed+9krGi{x6}L7EYSX9av}MLM z#g|LufzYi&?-?tDPi@yGUNyEN>8KkbHGd^@XaB@$dLAY((me@;MuW#&F?(o@LKtU9qVmDgJfQp)wBjGy5!^3@wjfsun zL5zu|;^Xvoc*tAkJDKm-|8B!sgm1CS<@_Q`$gS2|k3nIA`$QXHL3X5==T#0SBi4EIZrZ^!BgE6mQ^s(~n!!aeEKl(?dW=C3iouZUHniozJ-LQ^c*InkVKSr2=H#MQ zK@ls4);MazmxcQx&h#nQLu=BNKY|8r)e?hP&>V`SJVobxd+{qD!u{AdXQ!viUnk@4 z=`P243RgHki7;Qp4jLeCB1KD$2CP2$YS(tiWpLtaB4QA|uof%yR^wfB>5JV~WCK3R zRCL6P5!K@f0rrF}s}5+xvD50WZHCRMGlKj1Ul7I?ft}4%p{-`}(y(wAV7h7e!-Tl+ zR<9lnT#tB?U`!n7i`?0EdfR+=Ek1tevn3RKgh2`2_)bYPYsvfa&n8qkCmtw|?Qc_KYBrcNh{ z+#lX(nT_nBH6p*9N{p%^8j+9Ah!Mm&mqy6`AocaRF2K!KM?13OXFxYV6)aj_Vw|m1 z1ZHIBqLzPvY5vN|cathc)IYSOp{8DR;ExsD0G^5?`jm`o7IE{DKE=XU3Z`F!ERfB|_wMpd?burSX=kj~KLTWfHNj>RF*-7% zMlkyx)rjmkbEd90FpBUZPASArCLw2F<0Bin-nG^ZhaD@buAtj@W+{_s@bqaeKbi7mKwfH&%lXk0xY1NE*R5!~#yt`XS$NBWpDBxX)~vIxm%=|PLbEBt zW~5io@9kv6sJ|%^#yA<1O1}S_*Myt3B&_Fu%9&-O(a=e$KVu zsqV|y{H@B}ZcMd);5oOuFnDOm+@hyfmp*e`o@G(R?_<{BP`4Ua z*VnTp)CPv;uH?q`d}G;K+%o2&23quZlz8LJ*q4 zO$1M`pg$DS}F_>_br>3I%GOZ{=h{IU5I8UVjcI3+K;H_X9VEqUKcZZ=SHxa~egT z$R_Tyl ze`FSz2oan3@E(iOYhj^ppd+56Z3QU<;z6 zICFeU;rknG0UJ>-wL!HLD(5L@1nTu>++!HBxpc6qG>&gRPY_ zdL(#jhkoeBR)(mEw)(*Th@@nP+EnL%>Iv5^WW$|e#c)^t;e5;tfctA;jab=Ck4SOo zWFJdYqE3mH%**VgkU3RY7V9H>LW@GdWKb~DC=Rr%_aCN0ySfX}`*`#&!cRe- z=7!{*mTkgiTn6Mu!v1($ZgZj9!lDxPPPM61?ssRPp2IKCFu|5I4ufJCGFo8UWH16S zVj2*Nfd|DPa?B-kKN_Tq@;@46*Ayt? z-hV_$%+#p;z(>tt5j#8!d2;DWU`)ka$Kc{GimSI1OsYPr{WvC*P#1bWy-ky%1iP3& z`DHWhBLGTy_bji&LMxaMTeL>?kFmOSRr*A^^<{o`eT#@DqIr$PlgYWge{@d*WQixtPJyC&emn6&VM;uVmWf2YJtR_SXS&oo)2WuvxY|zY(+|5*o4L& zZcQvC1hAjXWRwi$n{D=gyjmoSEx{y`I33df@y9ePtO@UQ8zsd&vhDvRL>$UJ>)Ejf zz5MsuSg;u-LSy~`i0=XnNn)Y);6HS^6*hEuk(s8+J=v(%4VjbE{syrG-XstpYxgY6 zw+`!pZdv@5V&JtEl4%A zMDW-t)QST0S7ht5pcu$gDYvyi@92Yf4DU3&(q&-%G@K%@S=#Z_@kI1; zM+ph6G&_%kTMs{YQ=f;|s0(c-9yEy`@484fg*mfHX3s-m?}h&F7`0|QUX`jId2kM6 za}SYWgj+|ZezFa#pZ1d0|fc~FN^-Uk>8ZRr=^EJ65QO6xd0#I3}ji9Oc?bs-k8nI0} z9OcHS4`@Cqm0)3Or;6D)Z>9pGEhA!&Yr0Cb}YJ21@|O z9u>w!kO?IbCH+EbkU`Ppz+Xm}6TA0w7QnB9FHJfx+noEs^Vs5_H5NdZfsa|qZjWqc zvQyBol!Fw!=ljHXsK;b8heFQI*M4_bKn zQh53F?;rZcZ%I82cDqK3b)uv4WSO`yCcj?&6X42hoJF6SEtihg0Y`0MtUVB{`V7;J zXHKtfcqPr!bJ%zc`>9tmfymAOaGQyap`h3>^j@%tNGEdsJZQHhO+qV9E>#P31uId`2`(occ7kiKKtQB*{j2R*G z-k?=&jcu#Rw)N0lLz7L=E z=czRZ&k{_g&qr6K;(Ddw)6=S?b?dXtrS6VeZrS2~A$j_S>H32nIi(M(zCM+MTQ*+d zEcUW3G<=Jv;q9%p*!hlz`x>*!d_2DAq^k|EV~sQ06I#{p`zjsorL_uLmuG^ExV7W_a?Tmf4M3u7aiMJ+<1?LivSM>i{*mSVB^7?`T0QAEB55$V= ze-JB`YX7UM;lLQ+GB;m~glqa&Rl@+nBV*&RmeT4{v*`kQyUp1Y&zcEk7(zb$)arA5 z^kB>DQFC!yfn6#=%-j2KU$X2Kye44d90PAy>MLLThG|U>3a=AK;ef zkECID>UPQGgvKEr)m;0F-1j_=J;&Y<^N+YMkLo|(&s%;CXMn_+^yZ_3IKr~RZ6vtO zaUc$`lH5pai;f^_5YWQH&Od=R%%!wP44OiPZ)hYEzho)?3AE95;RA}vO=vnum5&EJ zuc@JT&l>K8H`o@jJn0v(^VP%*lh}>Qah2D>@g!=S@DH0isZQaf8x*ch>p)5o$3a#q z-t0F&0J7DLpJqo!^YH8L^lbN>;k=6Xwum%i!_C$2?{q2dT$cNEMoEfmh%^ur-ARGf zbuUNnb#c3ms@Pw3pA_DR%6SeCl|l_*0T98DWe5ONf#Xv)%Q+ZA99tZ$U*RxBSmGu_ z{H@F6XhU$cNbC&=EZ^b_|JXH1SG_`~jNQb2G`DxM@>)DsN z+UN+wA9`#G952c$ z-6{|1%*IwBgq@5aR@U-3S4%W30F!!@qU6U^zOd{@-!10lc-@*OWa zC)>-Ey~NvMqZPgVYF}$`-0wa7PISZm;+2OkBp|R$X)fr>A?+T<;`+?UkdEjFR1znA zkzq|;ktee%k*%`}28d;1Ylmnx(?pS788;Q0^&F}fq(+vGyh7OlmESB;hEC57hXJ};$%*n92t1Ntk8Pwv;i6DmB&r6aNu zO-++N1ktH>o&sE71gpdIx7-%`{jat@?cqH)w|s&;Jv*=5_)Yu8ZP!6dA5J7@X4C~GPT-ZQJ008L!ztqCP*4a*1SKr9U*5+TW=%o6;F70DA41aZU+DSH$ zzm=6g0c4?o$kaetG1%EnK?872^Uy!N=q;&?DwH7v2)&F|_O-S*o%!|K?Rfrfd%c*E zMR-O=r_awqg|Jy%k*y7W;py#7N{2U>myhIATf0$7DoY;}sYX^&w2r(`@lq1FIal^{ z`~CXwLh{oal{UMMCmfD0vZlZbhw;-L&1q$Vl*^1U-){;c`&Q*#~XWx=%VzL4jCPO@hD{lCTdal^y$(3 zuTL;y4M1-$K*%(WLM^9Zi`oHir@79ntxM+t>7EYdwI%?^-pht*eKMw>rK4boP&fm3 z1E!>3f2JL4`;Hh!j>%2I4*-uP({#?BZ)ni(h*K>v@;j}J+EN)4%tqc9R*d0HpnQpF zJ;=B~AbFJH%@x+3M#0$(^^=kE>-j!!N`X2rd>EW&r20pz0bdodMznJ#vDzxDjhM>; zze>iiB3@wB)LK=8n8$tay-5#tun5_?wT)E(=WJYA8M-c7Ub-Db89D;igO}ObrvTL`37BZmk;N??#OlZOV+giya?69DK$fv` zs7aO3gI@iZ_II|o2lFn-=@68KA)0ZmTwl37dzNy;O(-5T#a@a-W6bxK&U;)rlarg4 z;EwZ&#{AN9>hwIh2@w?U%)cQ;cw_KA7zl)7p-gQ$Idr=rS(ro!2nR(DrISm=oF~~R z54I3|6Yk5%SU!jQjXR5rgzjWI;Q-97n zY&pOla6D36-`HsA4BE)a*gj_7x>#pzC}ZyU@UaDMXZjxFB{H$xB$sAIkrD%`%ElFv z3k#1gHqjDZY6t=@7a=hO!*(x8(pF_yz-Qegq_|+_YQ!3_3HvT_kxGV85uZ{xq5AhT zPc@b0XI*d3?DtV$REmzVfnv$Dgs}iQn8V10pE430WvC)MX0mkZ!E8=bK3(+VG|}VW z;3;T2EUSR2WuA&k*Pm&x`|Gw?F#o9CFTsNt>q|x~WLr8CHAjOYsBJQJOuq;b8$o21 zH&JiKjOqSJu4h@d{aTh6fl;Ac{{@%^%jTxJy3vsHhMaghe2K}A8 z*N6^YRc?vEQL$DtlHu2>Z$TkAYvlIyFnNICGmlV+Hxdqr>jm}~)sKRJRmS!scXmbV z9(p4`|LPg(R-FiRef;J5&$J;e70+BX_>IQOsS!(R|Kj%+{nqzcLHT^Y8hM-nWoCoe za!x4dIP5%R60X47!hvVIj)WCDd)E7Lj_`q@h`($(y1zjp5*o{H!o;{n%wbmAm^N=H zot~8^r|~)nkSZ{^-`UcQa*V!+5A`-f?%x8Myw^&+TmOvJecTL@=oWM+O!{YlYI zF!s*GnDw#Tyav!2DSD+M z?XzgN(L}~@^Mq4%tZ8@#+W*(+#gEL#r@tClsyCED7|3pCL>Rdoa6^nIREEokNAI%y zj>GIA?+CSEPSA4;mZcW0`THUSpZE(Oo{*Eq;08zlC7!h^cXgpeQFi08t{gYbLu}d5 znSN3vMJ6MwT9I2&f6vgSs=xIZu<)kG> zr>RwI4#SQV0sfkSk}_w1+yRL32X-vPO|X#Sf|8bu?M;MbeEduYcse8EHgIx;b zgeu^qbp-?fg0lYp1;Q!w_vT?tL_an{Gb+kG+X-s~``?6s|DY3DvrQ8l7yy9H4>bKB zuVrWVzp%;L_GcdPHB}7(SS!2dv5o-I)P!W!Azj0$j(7uEh~5mlK`Ivaj}S2G-hn=_ z4@1aG_lhp`awYnbqigHYKl#1?nLK)Q0gaQ>{r+TdmoHZ$t*f&>y9m4=_-6&?<^**0 z$|g3~WDbHl!N@(0kFO{|wvyI$-lhUAU zRD@3EPh`p^I6NMRjU05uemTH+NWRR@z4XMplkUIaX`vWx%1Uo*yhs|m=99gjeAGLw z3i*!C{hnb}O=PqJRDnN~5?L{BLFpA%O<+ilCTJt)ArA!r>yM0OlsF79+?)NeIAOr9eOlJQFMDaj~hSA>+ z4rV|^36~Aucw^J`RCqsu2S7y|S+5?ekKb z4hTtk4UGn3nms9SIvkbgI<5|Gf7fa+l#CoU&~jbradl=POTnS|fpT4e#bq)n( z!zqRXi+3MjWYu}uVoyF2Qki9hw0RXx3*<;>M$B2SW;{Z-$m|7dqcv=Ho`-B~V~kSObV~d! z)@H3btiFr1R}xj(eMlc7Myb?A>~_IQCiA|o$62#T(#5EhDrQE?g=8a>f1y;BGSU-8 zXnPeiT`JRPzMyr^)bryt&*S3j=}%%IR!%+Rtc9x2OV8Mx(`F;s@2IJ-z-@W6K=erS zW`wwMP)4OdU1Wn|fgz&ioKPz7R2}Cdg^*$;_+G7PDPSN;G^kw#$C;{?wbUdTJ{R3F zwtdR0rPU8Vdz0xyPcn{%7rtJk=j7u$-e6F_t{E|LJKhku)vXs7*D8=}D{IBQWHCv{;AK^0v0IB4s-&vbv2`RDbB(}i zDwKXktzxB2(E2<*kJA+mnr3z{l-vR0K~v5YoiVV=f)|Yv`e2IOPNd_tImS59BzbYnj7=bfY&S4qlnYIfqzDmB#8->=z*`Ttc!zcu! ztAVI=VnfDq-@BC6q39-61O`tL1v$Am_&P}#__RDpdjxo?7<6ER#mNQM#(RbT;zAl% zi6$(J2|GpM!{g(2@i>FlD#z)nB4KJIr~%>?iwPe+yqp+y#Urw{HjFUN=^!dw`H$Tk zIP}!)mjedjF6+T$e?-S^IITTC2KgHkJwFeb_%2)|v*!c<1AYQ6Wl*G_fhC(8gV>r@ zP-(9}7Wd8%Lv3JxDiW;O->EM(e$cPU)Tb}nU;IDOkK#Yj4_*mLEB7TlC}xW$`cj*Y zN<;rA75!TUg5~zdQn(i9&+AL~xR3)!_!cxwUP^^zB(2w=%2;SPo!0cs0`Tw8j+4Sx z2;7|c`YtH7Z*e>7j4!x=aT!9!kBo~_yB-e{X-oo?l{WIi9GiTrPS)0DKbY|w{w)Cz;eynFpir1|h zWhL+)BVs0gW&-@_+yYUh(cJ#zn9zUXdtCtXH@*FHD5O?yWWQm8`eSZf5R5Tgt390Y zHe{&FGH@)3aZ`ls2ZA>8OkatD>QtNJPA4|3cQ?gKd>lnYu{ET~zK#Atjv0V))nTpD z5b9sJ-Q&i4J(;+=>W8{b=zo9aKX^JWc*%hDBdnhy`yaYJXD3_pf5lB-V*RAM3cv7n z8z90sr;IcmtkgQX6_J24J&dqW1{P09zEf_g&XtuX;`ZNczdpqfx7#ch9b(=1Hw?S# zdX5b1X7F-%z8&r%rk2u>qSJSI|1@|!-OHYw9G8z%RZ}C={Mx+k(tmBTwI$M$we4f) z8uVppDIc|e=Ti0}uQsifq|>8rZ#hjnbR zW3xZe;XjpPQI&5gtmioYI5D;MkD7y#Z^0fAlp@sux{}!>b3}<^x%&5#4Q2G_At#l~d06>1jAPXWXf3XOC46ZjHp4#lCDao&ebmEt~%Q|=>QFQ!8s)V-HI z6bwz7+Trw-Z%>vM4)8~`+$wNJ9MM8jV z8bIH7?85{K1#E`l$&_I!GV_%nKpd_LUQQ#2ZMW9?=J$v7Mw96(ASp zHHvu!48-T_au}y=Wq;hr-aw5f9%n;`$0Yq>B_e>-M}4;^76>t;!q$ml1L7xYC<@#_ zYx5|(M?0}L5FeDp5lXjlg-mKg&?-ZVEkjKu{jxsa#`PBXxkO*@SaYbt1w7_!)~|zx zd3mivA7j>3>tYXL+~$Wh&jMpJGjwyDSbQ#HSek_9&yySIj{~w8QP^m5?12v=%+&ly zKog-VFUY!@o#(mqJN1aN8)N8;~ zlLLers)`ao%AtxALDkDwx8H|GmPi=}B!ey2vmv;X%?KF4 zDbhEW#l8L(b;&-I8IU?yTHO?=P^R93&kzK@W~GV!vlaG4{L=$2A3dn@)vVnM&%vav zaT9@Tsuz}#WDczXKn~V!R-(Dv>}E>XZN)Xc`W$cex9(KTZ$E~lM*Rrdbw1n0nb!Mc z>bB5SMbXC#b5Xm_^cn)6=yK0^O6nrU3Pp=;dOsD1le7JF@O~;;y0x)=yiB&aee1n2 zYUJHXOm-9Yf=S4%bh}04=q1A#4_PquF-Dnrh-CD5SBzEA>ox1I()6227p)F^qM9Ugkl$2w#%>} zA#6%fgWP8fj2*%!)7(INrll?3DtM%Gz6GLd7937!dvV6k7)uyLf9er9TQiIR{f+28 zeTFD7@LoF(2?9(ZoSGP*^oK}k*ak;oPngiVkkv*#tUWM5Pse%Zc6!`v8}7ds&GK$t zQ7Djw!cDxwTU9Q)J|PQec*|_s+X)p0#(#4R*R}k6WDj%P_VRifV7J)uLuXqopWHI1{(}$CFvBn$e<`imeGzFQWe%alnZo2qHZPd!N+L=HSB&^`?L_ zbg7AV(p%pPD_Z7C8oUBf2GX3%OS}=LGjLszTd{;a#gDoT^to~9f$tLN(cBe5{ITxa zmxEn(DPJHgFZqzlZ{+n|EBvkiWWkyDM(a1@Frk4E1ID=i#ex|;N`Vsvzw-5m*>|mC z4uU}8V}7q#=EZYZ&U;6@G6V+Yuymbg5jUXdT3dP=27$o=%%yusq-t4~M6(4KHZ~^B z-$IeT>R|A&{~8|`?->esh+vnq!`3mDj)PAmcT8q@jwA%EfnU@SCtz2PBTLxhgkV)J z2>f#vBzlj2n!c)%WJnNjms2B55=lm7{$gr`x!t+i7PPuLi>I6KkH_Q5s~kLjd__RZ z2Jvx;I8B{2{%9%OAXJFB_{_EI=pxL9xN4&0c7h$4N0}U&_9TMNUp`Q#m=x1g0gQn* z1mn^Ch1{e7$?$rypf^Sgm?v?L0o9WBUbBGcPXzp31bjhXc%zxYAD`Fc5ozVHj88ic z{R>a+!lSa03$W2_WjpTnp*j`?g6-jcGGD`9y%v5<_-Amtnr(bsl3k7{v5`vrCvt|6 zp2HDVij7ETV1kUc~gvV1`%n0>PpX(YSZf>fP$ zaZc~2i%olDVV5U#_dZ)HNHo!Sf?~>G?aK4PIZYeaTPaC^3BjVGWB?4F!XDm+K0r2W zW>(slw4kkqSa9(`nOi^UX7cCF+MtZqc~p^rq31oIelFc!`6tyzXXgwzh`c?V2vGC+q55ou@};gn>w|%OvT=h`$*x zE7Fsz_S>w0m#!{GwSMf5dtevLhhc1ri^DyOl0X$ZuCa`h|Dxf^o*9lzuouBal=c*QjJVNA@9WJ$9*Mk9bm1Se-cmArU|lju~yLIfI1KTM8Sf z#+}86hvqX_pmcbJO+@c^$>k8`*55HZ$51E|d$*!I;+!<)*HkK_7hZK=?78^Z;C=ep z;ISs#-I+y2^}VI|wu~d5=6*w8J_lxMIs3}fIHZ0+m#6H3kk zM&zIdt9_f++m@0YlX`hvBR4VO@^+a@8TPGg5VrT-p*=43bH3&kQL-}<)3fEzZNUbf zmxr$Twl=-lT>}Xbg;@DZtGz*JOVZp`rI_{Jl1NMgl1aezdM37hN%(RGi+H#0enI%< zsg>4ij#+9Zm9ty>v^O(UL9u+d9Db?me{~Kzf;H12&;m`{ES0vwAF`^(Zl7TDHe%g+ z6mc#7L7Xv_wcMq$UTOFu2deAa{qOskRB@gT*+11X!B4gPf6y}jDkCi%y(bi){235H zX8y<_Uf5EuE=E!pk|V~ZSXuR|&K4Y3%TqMy9XqDD%e9y2r_OCSvkjiIl}jxdSxDvI zxz1N2wX@QV4t|u}RX?6$UGMAHK!nIXi}!dd04m^;#Bki04K90d^UZOTJ-t|pwO`cB zV?hj<6(sMln9pvZU_pUB5qtz^9{o;SN!kh}e8QVS=_`C-HDnOie!a^#xqJovuZ6J| zogJh0579LBk6Gb=#vrqS1seiHOAC^X z4w->W^`Aku*BS;A_lj)$-lz+qdw zPL2)mxPsGl?ssz!20mZc=^=XE9@#(GLt#*pus=u0{Ou(KU^KGS&HMuW` zVbo27(2ph}XkaH5vd>dPHc^z>i`ge`gZz|>^g50mKHghHb>T*0cG2<0?IkA>v0;EP zHCI3+QW>`k*uAOY9C*~sdi_N_yDSy&5djJQ`!;;DxC0kgG;R8 zDKd~U&k(Z%G?P*%mF^HYbDlv;pxjEF&#O#<_8p%E6LwDEm07R}1&cY^xs#~#tUAXr zAK|-n9E$Zj0^POMK1ku$x6YeTT)rg$yQj2?b7-H{6RKjAbo z=ikv*uyG^H3E$5NsM6S8Bgol@A6wKYJY8jFLeeUb-(Up&c{8Y!Eh(_0Y`6PiOlZSw zp}@!;wfIn804`d;_{Jycet4(MOHMK=qb=dW1MmqL+861VAYLkIs0_{A%dg)w{wN^J znw-tG2;KA?XO-C8&rQ!@OZ>Hc%E`#eMo#VBo87$PxSSMHl}(Kn5jq^z=v%HF zJWX4xzsaFE%?*EeCsZBAAKq!q2ShX*3%|Qd8a(_b#1VqGAPa=7J`dB zKV|La&b z0fdqchB5*5c7vMIJ5xm!GW>`Zy%Z3hV#3^C(&G~CbJj*AYv(83(5ju##-;TS*&4R) zM9(2imjk}Nxi$1|RL`h!yeZs<10H-r4?dNK0h*g8JPuR ziN(3l`4unQ7gl4|u7nD@89d6<5+x#js>jJ$ixb7YjWlEnd61j_CBy{M(XzazF2j9m z2+}s4AqHw78RyKpS7PF24d&CdhTo{ommJ-jH!ld-;$V}t9grI$UY9&?A5EDI6THd{ z3m!eNN$s^@sWZJMQhW^u=p3vdURuqT^Um@>KjhPJ{7QLcDC=Cc8YtNuhK5HnF+Li} zQKfS}KAi-(7&%?sN5IVv*aPV~DV1Qt=bwEiv zh!G=*S)fb#fY8Af6HFjF^N08Q$%TFGmnUi|Iga^}Xr$UspJbNTu_0Ev8M~;Wz&Tq5djq?4R1RZ2* z?+gN{Go{)%)NW6#5}K;jd*l^Vz?Xbm?K@brvuknq!NV`h#*be?$^H4?)Z%6%&~@cM zpw#>Ww}k(9aI$bTj+%w~%YYJe?H#tOBKQC_D^lRcj%4ga$h4HfsqHvnIJZu&{}9~1 zGU(cMZI{(o-)`$U+=?=^5n#pTfjQV}muBtHqqjeZPhfMDva$b#TvAr0HG`!NN*75gY9;Z?*MbVHm!0SrOrCpYQ_22y6`h8a!e0z zZ?CI2D43Z#*ILI7%jeN=C+*c@$EG7^X=ciM9g^;v2OQ^*VCY~>Lm6_}j~@509o(*M zBJT6pzn`uOXr-v=yIo$=Op@(QaQ--`b9ba0xjQ!uMxcts&Q%!$GT$-+M#Uyv_R!Zq zJdJSBI>2#WN1!P&AgG9mfdz9{CBUCxB%|KspU;NNnmsgOzE(MU&vDX{DNQKFRjy;g zMdgW-4jKRf3)isij1QaIGMzPW$rzG%JX^<}V@;)&23SZO!Rw3nO^7%3bJIs4` zG{(VyS{P}ktP{}@#5HTo?ZmW=vUP{7nU9ewnbY0<{G|ih&oGQ%^~sm^_ZY%^%K$V} zhT!UXzfJq%D&8Hqk@`6ebo_v+WDTnd{ue zNJ$?sfG}Nw$d|%MgLRN)(l!caz9hOhh0&QtkmrC3>$XtX8OY$T|AWayHsN&k7OprU z@{W!lXqqK%TV{TDs z;UkJ6r>NZCghP1|c^`eO&^9^Wb42CKt~trQwj@p5d7YcqPS_P(I0-YLxhu)#vhEzf z%AJxnS#jmED-N5iWmjv|*TWMX%DsJk(7E=$i^ycyrR~yO2PVk+)Mm<}vBYNW(<_w< zVJ!58nYBYLKWHu!%H3fqMbnkaC{@=SLXvZ)Y&f?ybR?-sZ{!O!4<5E^d0OBxSsQfU z=Y)AD6=m(*w?i`}ZY@n!1y@T6fXA{AMc}}}G(9$xv`r%%o21P;*vF|C7@1xqL}Y0%dbCTa5UF<4sJs~qQbuxO0dsBS3V+sx~hH>Jps zwP=ewcXWLDkSR(zo=6Mm&<7kkN{{DpUF_~hnz);#7i-^n_n+TwY*%S6AI^6iHDqAl zp5Yh`G1ZZ7*Sm97o>tPiJL~Btyd-Pb`+kX5YAOq%)8}YYb<;`G`Pqab!eKM!YF5$8 zlt(P;27ECcmu_%pPIg?A7nuy^fGI0r&PYclp0lF#h7552YKSR^?lsoJiMA%Kmlo!% zfG!xhMWDlcAg7)fYT`JO{-R9mCW}!f`Mdzr64Z+&AnXF)X)iKupFsJ8ydDL_Ul0XV zs(=mE$SmICciP%=Fj=)66>zH6hB7tMN+pPd*HK7~osuafMREK5e+2g=4LQ2gI`*e@{jqR~BK#}>_>zmTR) zdk7Wf2V!W@qYgmc#52L=r#= z*??j650H@3wz>!k#`6VFtlao;c!BUM%QN@}ZyO@!tbHs;<+owl=)a@8w;=^2cBH-n{HMc|N0SMb&&a>xSwf>^DZ7 zXt$%0AS!&-6%1DWI!X&Y9r;Tqf91~OXJln+!|mPozLt+)FAgxvckgZNF%6RVa||Po z;=OYCKzp0$Ps|2gMB`)CU%JN*Qb1k=C}JT*D=f=FG!oI@5u+Xv6-&V5zav@-9Jq zK%L`Z3E4LoE9XE9t;`Dr8g{mlV(Et8VV10jNeci4wEqolr-u_RkY-sD0qh*(yeX=? zGx`AVIlG2&9fEjCQ&8Ot7n*+^;7vFM?(#4!hD$5>(0b(}h$DotLWdB()+7N*7&}S; zM14aMLh%$x@W#UismKh>tZHK%BW`zFy!b2p(4`!nDMj8seQjc`j;$o2Q>8L+@SnC($#q~j_elmH50zG_d9jrf3 zJaE53af6f06|u&L@VdSAAznCchz$LBOJ{dNd;JtADUB4EYuvsA!T}}Zu8S=sK#K)J zcrlroO&2Z0p#uYM`q|6}+%>OX;M%-zEQjQ_qp7+BLf4pzNgAL(eeZ22vv(~sZg#&i za8iLEY&&?8eHMI4vB*&!b~TiNP2LaWoH+H+rxhRc(ZL?nXSh9+IYp%A^846 z$HVM}%pu3*8SeO`U(As0=F(bqpl>eULVCfXr?sILMkZdi5vC%9N=X2WBjGUgqtNu- zA`?rhN{7#SFhH6~3REnM*j<yQ30;@Wm+VXXOjE`wHVSdHD)sBg%&SV`JgTe6H>+Z==PHuc2sj4`iQl_ z$Ty~(2HA#gFDZcPM2O|UC0m(FM)@wRl;reAc+#Hoc_j*R^{xzK9Cqx1$0t%wB7TI4 z2?!SLJ(bN>7H*R4yd3HMrl`^`gn^}%B6UhPF4J(Ew((RDbs z&rF<;{3pEBj&u_RebRLnbtle`$ibLVQ2lo`d)reo<`j!e`MTRpOVQ%`GRx&tBmur0 z@b~Ig;u8;S|4z4oKnS4WK9Z0&QgaLdp$!Oxab>%x(@$bS#HZ(8frc6ehJqUaHeKrCr%Yes>FfTG3EyT^?nw8!xiikG!3Kp}5 z_=KM(uo@KjToCscW~zj8RcGNoimz&#UM2(F2&YU^VXaeH<2MnrTOqdQs!)^;rN8}Q z=`z$DRlcxpSp8vyQ9f0}sGVtAZBo^Oj9K6SH?ffjx-$(#I3hH1IE3f>4Tsr0Yntl0 zejwffc3m==_WEjKVD1E-Ahw1)s~Jrn(|DhvDB+Ra6%9?nIZMZas-*Ha?W|3Rd`y3dLEQ1x6{AF$TX=}Z1hlL*ePom3d z9&ZmOFwW6uU-N`lVkkQX+r#Z$YOZbg+iiqPrX)CXPb?;soX_IYH+=J}WXt4DZ(xKN zd(DC-RWR9A>=o9%Z*G$9nyK zu_!)H@?*xKOTA^K85PtZzaNHclFY$9-1HsjCc;CBP|gu zoB0E`v%UFG@M&H^@oiu?FTJ_)UM;IG7MM#_KiiXV= zEaeByOnlfJFpMuUKi&P@u^0xDJi6U^lLFJUQccvK**kQckqk8y1*vs(l8V5tyw=9o3!wV8@`OiA|6DQX87TC{gd)@7gC`qvVCG|RFBAnL z8CiOaH7eCWeAOp>~n4 z1;p>}G{F%MA8b6%v*_s8?>gaCz^K($*xS)DCtW7$K|zHh-*3kfGqkOG>$ARuvgKsEvW(Jo zygf|WagSUO+`QeHU(Wq}^JYEQ09<<+9;3bHs_KxyyFiDLnUI8WP*!D!jSJ|J|{`B6k zh}V%)@`lpkq5(-=3ptd}SgTm`SKb`mD`twHUK%b@8=~G%`uOBn4hlwdGlhoaps0}g zlD3&K(q%2^IH|4FL4C*NdeywfBk-$AQz&rhX^@3lcPfR7j{87fX>j~lMrACLQ|On7 zMP$FUx9iZ1{*x7bxdUaAq}DOL^Zwb;Cqe0#G?YE$4^tnKJgrbNF3eI#(StkrH4GHR zhIT_A_98>r#Z9go=l`5AU#wg&L~Q6K{gQ_=_!xqKYgNoxb!_KaL=c3Jm!H_nh~z}` zwjHhTOUl0w8dhqfe?rr5w1RiSqvj6tTu@^`48=u!?IR{Jq%H+9K`Q>M9&LnV>KD0> z3`7&YkpDw0(#+shDH$05ghYe>%g>p3S;cF^p1rUxpEoPEImOwN@7XMx)It>^jjxmy zjX|T0^cQ7KQuQ^#l}J?Z@(E~LhpMsol5)KN6NydiZ1aUsO#@CQ-WS=QB1<##Arb5G;LI>DkM z*VOW;R<55Urk6vgQP6ID^0)U(2X9>N6LY2yD_ixpyT|)2KePuyjQ7nIp=G#%P5->BEb`q01$|&Nj-6NP0Ez)ZiW%-{<7ym8H zhe1RRCzc20?|lafS3#qSf5Sh?U(A_J=YTQ!^E;9I7gHSBSYC_Iy~1UnO)LdKsx^Gm zB|Vnq3%E*6?NMnp&CgDNqqtgF5C-~ea6A6djhCSEEQfBeiObhKVoIdi7?2)Nv^Bkm zDGHo4b!q|g*aIFG1EYI@&tTVE)3Bbd1$)g&R13kk;=c@8lvFzdCq!hy>meXymf)7NU`Dop~d4qg6@c4;25s;SNi1 zpQ)ANKZ4l<4?VBcJ(iC--rZ8Z1b?7TH5ycf*KNoCv5eI-_aeiLm}`BT^Xk&6Hf{ZC z(a1|Pug{Q5+#kl6Sb<6`KQvX`SDRO=)TE{K&tFf%$pZfcW@>_NYC82wS7{{gxTVbP z-8S3wZJF+<1r~kV8+OnD2+VXmPa>sd` z51ziR{xrc!_j>i1e>i`a!=J|6boV~CYSYQy^#1rUxlC?ftZDcBzPPg1<#l_0?0@WR zrbQCTr32lRf`eG?d$<6QF0@Gdy1!k2d|XX`{}VA8{&;U+tHHmj1GC=WqJ07HSZksa zN{J~bO(CdwUe@`%0o}4dymIHz{w+t5QYbqZp(V4>$x2(>Zq8u;mw3iP-3F~)zXOAg z&XxX8Adafz>|X^EV>r&FzD>$F;VZ-uPa3SK9ONgdG~6l=(h)iZz`tP-;Eqq?C3rG& zocsIb_xG=`fWlElLNh9fATo}pd9kt3ru?Iq%hf@xDXtJ2IEEKVImuX{wV^?08$5WH zBTo+6w(!Bp)4`uFPE~<(h!su*deEBd!e|$Pku>Cz!h11Ye;=6YfwRlN>2KPllz>y>jXeXoij@@X`?duuRpW~Z2r z4RMk)Zo(d28aPw*u1f4r@A|GO<*{lC(DHzQlt$DhBO()dMs;?QT9xQ>N1A0@hJ?2% zSV1{iLMcRrGwKFloF=#~`%h;EE0xLLjcSQ$IIOv(6s4YFn4JwoVXX-<>xeeZD^*8G z!l8f3h{|R&9gO9Awa9^N0izMs*2_O@u+ZDd>vQD^*jbXPa8ey9LURT^o5KqJzoLFRiFVj^qsvS1N`>f&Jx?sW7>c*Gu)kZX9~AGKIjW;1mi?Z86%5 zU~vC#!(~JVo2GoCdiHEtm8j@vM4JO)VA7Ysnkr=f>Yg3Ky6DX% zmXuz;$iR&oXIG#zYo$s;@S3{${fKT@vJN>007Z{ zJ4i;x2F|9Y<~F9fx>m+6##aB@Oj*?W(b2LY_)J#|tjf|(ry!O3BY979G{w7}abV)h zydMCD77hduX&}T^xV&w*gNVo1krFp0mVOc;4QFlB0RYWh$%$pd(SLtNjcXas^i|%^o7Y?)M)KD;coUI*giU1QJObU^QwEn}RWl3KgtZE?KczPH{~J zz-uKRSEgqqXCk9l7nLZmrRoiRrT?b9F~J#J-9ln(I&TZpd;%T2VFVMD*jf(gCfjwI z=8!f3tYx4-roQMNJIF2W^dYKmA)B!E1-9~})(FmA!a#IZir8LjSVLYbz& z(Z)7&*B2`wpRLbi#OG#`#Vel>TQu{{eaHw}3HoE?sj{7KW7z~D^mov3xi(dQNse5x z4-Ba&A7M9(`kvenLii*Z_}Eb-kNlJ)F@@;)(Ny|j)wr+2p9RHeXD++g`Ymh^Ja`ZQ zrPN37xA+ZTRYp}e$n<^xKqVxmi-ZD-ee!t{8bW)b|BtYDijpnr)-BWCY1_7T+O}=m zwr$&X?zC;&wry4Z=T_A@x2jsJ7H{zoSSwv3yr=|BjD^hB$W53=xHPld$5 zBAx6MLO()M4a1_OD8l$KRmki>gQ4W(3g@ABb~AM_>M|6D!WjIUC=ys+dqS9gg1A8g z@vEfVWL;}xocctGgbF!cpt`f<*ux@gU3z9B@c8jdmwjsT2*n!0sc;-2*i84!y1vag zmZoS=k!T#!!?<>aJzI?#)=u24R3q@;D?g@JtDUpjkyp(2ovtw>p37pn`_tQ8>>OO(fXm?VniN2t0{HFxto` z{v0%qtr80NtwNb4^(}{-H~X_cwVDlIW>ranaGw#41nFY-5vK^68YX@|gp8&i5Z#+w zSy@5y_|In%cFfDS%Qsk`r74_{ziCtL4}F#It@5@l7=<*&p={B5@# zS{xGq`^Q9zF=e-$8$?Ps!l2NsqD)C4ao#CzC)Xr-K4suAWfbbE{m=b!2P!34!B`>K z`>J@JBU)fj-X}BsnC)#N%cyq>hVXXCC2O$GFizl{@n8}mT3ui6SAJWCCvcvNUCPAK zbqEk0O(08p_QV2g%ZR-%X77#Dhg?vVP8SI8E93(jMxO7KBY(I{9i`4lv_{_7LV!So z&yNndODukr)fILrilT)!kEcsqoxd4BcmU#^EaiW~RGW6&DlvUr+A8DbKaZK|3PC0y z`9feMSNH+un1p9J<`d`+T+(J5t;v@3q~Cjne!h$*1wqIWE+m54WDW!r;hZVS?NIZM zM%(8yr13k<_4v#TsXnmI9A@>5IPKu8t}HiJe5l<#j3_^kN>Xfs!ZY5gWLN_;^s(gN zGSKWHDgQEhWST9AKCwFq&aSb{Z-lJqh0r=jEoEF)(Pr5q{4!RX_01ygGCE-N8Y!QS zGMF0yV0}na;q!1e86iaJhMO$@WF&H6<&TCTm@-FT#4Z?|@J@2L{cD+Fm=ad1n5$6> zN%~_rYU%>!Q?%}eqt6V;4snr;k7uN6L7?w$hZQPu;ii@`^L>#r_blP3r_pz-FgRb!&Q64 z_YeM=RV(=X(B0cuX=P+Gev>o)nQ;vY@wu~g$A-C~QQdU!`7`&3J@v81?)$E5=L$f= zbjSz(-p$*cL=*={)FWYTi2RfAyRTICh&?S*>5J633G@ZvA&(3ZJp7dS!S?$3M~N~T zNAt=H_Y5A0b|@II-MUUKXWcvPlRBD?VAYv5d3K->#{ue7aQZ}i~6}pkLa_Wy6@DTueAjxZ~D59FP)jE zci_^E5}p)rmze>Ee_QtLwFcfLE%^@9Z+&~?XGN88X57(cs`va6tR@@vO`j)~Y4Q3n8?W{2mI2|hw9H_?Jp0lDFBaYR(EO~`Z z`2r^ceP>7G=?;0IqI4H+Oh=g;6w&^9`ou4|l|auWRHg$&Ymn&dKuud1r1e?b+f@ax zV%|A=u0m9ko{5D9NLkBf<%@iHsS4~QmH&EH7n4p5jGdvpq#hbXAzS)iJriKMjyb$R zsGt8ik)f5qE?$%3RcK!gEgx*H_Go6_3lT5z4{sSu!~|K=KbH3jjl~`ou;)hsT4d0#CXoFz zNYaCc5nUz5M_OeC_a{_*)bLhq?AO71o*B@Y(T(hqxJm`}u9*V{o_dc*gT$BI+!T9O$x~9^BdYzG+FJMmg&@_XQ7vF9G+c z2D*}ZQTZN(*PVZ3=uD}1#M1upN$)#+r;6%5+%HmxPoGbt2e5||{a7d(Jdi)FO{(tm z_##SN23^Hl7{0Wfzi;R^ql4aVDmg>ogWn3z3#j>}vhh&2^sr)3`HZBy`bed$(cSfS zz?(ra27+P-eiR}WM;?)Yfk9@4=zpGUZQ-EVfbh-r`SjWJTDkR&7Sf|+zO*+GJECjn zKIVn-Z1xeizyMiS2lRe!V&m=_m3A!P?Tpaqf`c^>4vm}`_AY%D+|fjVLL`_@Ol72A z4}$^8ga}NpH_z4wSVAx<<{qoORVzv-U9eAUgPhWtq-5CRL!$L0pWl2tlE2^G{rLjl z{>LT)+BE_n8xE}v^`%y_f*JSNb7a4H*lY}$+$N_`vQSQYCtHXmHwA4|9$DoF{J$5V z{~@`H(#9~)-yR@5kl)tZ|KA0ug=6$wp9K~_4A^c*u7Q1Rev}Jy20}4-OB2$-KJtb& zECDr9^e~OpLc+59_ccvu+|xNeyudr`kE4%;jBL-0?|XMzmTYNmY-u;%Z?N_So%9lwG&n9(k#*wD#jqm3NODE@%8ay;{C<}NbdPA}h^C>MBNMd1~b1mPOCTb>4E3;@74 z&;N}3{9kQNMrMX~%>UKKbfxKO`%4QyJ-Go3AxpUXFPwCGlJhjH^C01o*1n)gZV_we zED_BIe?G1`aY-a)y2`BQSp=a$;)U*GMm#^=I5a+VadPpbeS6sSnQ*`^_m|*$vTzwn z=PbU~IW3xEN=GhRa!X8m>SP+GN+Lwd7a3#RW-YQiozj>VIM%G2QYMTY*DQz6OIW(B zwlH;Y1hckSox=Z7G}^)DUM&Q*=))I-YpyzxCWaT6)c1nw2+U@s*Z+Anq(uXtmd7>^ zb24m~=+)2h=CEVlw2#9JOeZ4DJ26>3?SVn zz-Idk@4wHXQfxnRcLlW}FMeQB>YDnW_|HL!REQLX(=~s;;Kw|EI8G^%GJITSg;;RA zSpr&(a{$=Dqq8Ae&hN8RgSj1Bd8}tpMvnm#C@(EK*M*YQ5?DoeY_@V8(70&;JBjFw zG2{T?F!OVY^izi!%kJI92$1r7*sK-bN&f1LTE!E)9%Ik#Xt}BaWG=%~r$7(I?J&AV zAUCCWl%jiCH{W#gB{L}$1I6SM~wzQ84>g+gvZ}bopod9hbG8?&!T}&1W!k=%g*4Ch#s$8HDn8mbc7shth|K156>&0A9ovf5G83 zC`AgAPhnEnKtM}gHflKsp0|0%(X3%ILTSlQ>Nc$Yc9eNsHcx7dT2pDNir;1r=teC{ zCS+&pWB;k+!=HZ{46?QO z<{~_;T3XYcLAQo59W8zSe2YSE-8kLYN(~ql_;Vw*qv@O85?$IooE!(>R1*gs_ElFuuo$Il6D;|yOI0W}f ze(szW{#_$Rqnyh-d^>yB{JM_r<8Z5W>L2n8GdZ}A@BPJym+F1r$pdZ|IN5X~E*ZM* z?4sNSIh83I8>1f#Pw3a*VYX;#ZRFFW;y>=8OHBZDb>0Iju+P_Hwc-m%!IsD7!J!rq%@PfO$-DIVt@9o|J=L`XWMu({^r>gPRG53YTL3| z1#+gj>5M#$5G#gXB9Hk1>T*UUpuz}F!rhwl$Ex2Oe{Pu&F@J4f)BX+LRJ&m7ToHz< z`*_z5VjZy89q5v-Y%3iDws`ib1YfOzXnbTs%kwPwxaNj*QDcoq2=F%jUTMiB2o75C zJOD@Erz~}5Pj%gFUU_amU~mh3Ze75A$ho=yE(0ICqey&dWmcQB%`A*zZlN!#3J<*;HCCY`a<;H~@EZceE9qoQ0Fg>KQd16ux+s#v| zn%}hZ>7XJFh~4N$hu!M_og@=p!Fn7l+qi((;|OK@&Iouke3xxfptdlpc~pGJpxz$My_B7e97+@lwaA~cJ1DP*%FS@E4DwZafF0(x8!@1N z2B*hpCj#_Z#E^bJ=rfxn`mh=l(9bh;6-r9p2(!!E=2p z<28r-7;tfAJnty@QTLE7R&cn1^eeqx{4AAt7k$bVpTTSQX;~1FbVq6l#E6I1@nyq& zPn54+@J`5-ES_~ghv#kUY>;?_W3iDxo7xcuHKPTl)I^43%lNslykz(T)ECpIB4LD` z-lAfZAxGoCG@0p^O#x9Rm8CkUz{)b@^?49A?Cu{V#>A_lG{Zn*&&u6ycI13P%DEIZ zL2t}4>@1Jio1!qYdK5{teD%l?B}(Xf%KD-S32AS0q2HlNBhHF9QA%~_ zjr&KahY29n(_nJQj`@~T-TCnS^z&n)GV$WKOC<2EQ-NHS`tg46Yr3HY#4(mwtct%r$7o_T^J50Iihn;cccFn%?XLao3(4 zPN7g@5mS|do<>maNs1Sbly=AcP0ra81%Muyy7bM2aik*!`gbf6V_k6*~;zWD^QXm>>bi z^vF&p090mI;fqzeRnRdhkA_NN9#VZf%MYrJJ$Ufh*|;&I2XJuAZgKmA)nUPCW*O?w zj>DgTB;E^Dl=XX+Q|xVPX{D-zeX#?Zvspjtr{k}2F67w#YqfP0b#+{hrVc@8wZh@6 zs!0|2bLD_Z9w*TTEYT%wm0fQLM}R%;snKf^w{44kiMEQ%$2; zk?RjoloQWzE6731Q9rA5sZt9OAN6rOLGk@(7H_w`SDe>*FSpl=}UFE)^|<-j`A*>QUpPj zqT~9sZMNn^2YimVKz@=%daw;`mj)34R%ojfv({a}4FFy;o(tXMWBHN54%2(X$Oou- zh6YPw@M8|p0c&AgYCTA;_p@BjX^_@QQVb`ZWGrm71f; z%J&hEluk7dVN8y&IjE5^q6l)|qIL1eAk10eVb%o-S!t)p9+PMhV2r5!&oL* zI|s;m9cj%W&d`_4cBs4PL%<{>94NrO z-tVhTA7OMLabn`)Ay+-HE6V!Chbm5ZWo-=OIeUgB@~d+*E7}YLm3YoOP35ckonET) zSU24KZh^gvU%wlB%c_&ZntQy+F?h;xR~B_Zvmebq3Pv2!S5HLF%OTm-W#;}sEtR)#kJPrW_LcqBiU=n=tZHD0=92o}DC%!Z& z+DW1Xn$~GgST_$@mN!;EP>B{9mdlqH54R(-gmyNwf5aAnH zFlqrhQ5>aHhHqP#qW;7G0Ga;~DCp6m8N@GvS^@z8ApbuJ^uIvH!qIt7+G2nY26We3 zMt|O#{DCffJ~2p-8Iyv7O~&r>`Ca;Nv369-ewXb7k2}Wngmp)(VaF)HKS(P;j}MaIKw|Rflih z=y{gixN5jydftd#snxBwsT`>JqpHGDj`I6-sx8p36JbKPabx1>U(;nvW1G3IZu5

pjQ^}qw+;mHF4W&YKjWd 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 z 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%0DQ(ct@ah(YXqM)= z5WcEvEFf|u5<1kWrP;m^v-7 zP!eQ8}>AGRq2F$&mAh*s6We`-9|3 zN&RCR2 zoYEEVEHRy!M_tDd**FqrXx7xiYM>oGON93q>GwW}|3!L^dM)F7yWF_xX>HJPI?3Qi z2apgoD+W`7We*q4DB#4J|GF86{aH(|G9*R?$zDPaq1l1!h@6nkb>7X*CJpNDMKyF+ z5Y-YHn~%}uICh51p8o2JeW>qghs9vq@EaS=#+{MTz@>U_7!G*Ol%R|Oq!3iL-Vwk7kRk|s&gV9Q zwJy6KO=2D4^bgPh5JbknbeD804Jzho)N*^C3m3kCjvqs@7EC>_2X=VMRMd2G9E>^q zEszXR8flYBw-^`P0lS?T&Eu(wTCO(GDuUb^1x)==pou&qtv3WmU1T>-!oz}ej1 zEmFS1*q6uFAF|L}j~Tf>xV^iA>;Qcb(Fu`7TMZjMXV|s2vc&PMLzG~ zP0AR*o!8|2e>*p42jKM|xN?JjD!)>6^t63AG(IHoqmM)zxJNoz2D6_l!I!N8Vm6&L?fdMDGY|r5(u!U zY;q$30jB%Dax5nPN&0g&6{8+GpI}oHJn;+}m?6>v3@xV*)59RS#OCHyh%T0hL&cz` z0T$)JcoB^ly4123

-e6rN`0X20zQB5f3t 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

1jp{ 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�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

sJO;2#0#$$pJElMu$xwF8BLwfg3O9 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 h33dm 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 z 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

*M+XSvEX-k@$TJw$a+;BTH|;*A=rmm1nt(B z!PTkpFf!oCv=-~!itZO%Lt{3O`d$50K2p*~9(S>Dpr|jo2y|BX-dAdIe?E)h8Fzli zL;U{o(_PEKeut8!JZhs9VylI5BMlX`Ce4)BC6EdQL!KyRC0G`km~vJUwI_@~0}nO# zI$skXw(J-3sB)9$8~=wKZNQ+b^D?8UVwVq=Z(@!udNaFPG3q%-s#L`c7GZJ)4CdX0Bii<|)6|X|0-wLdxj_{~3e_&hO#hu)D1A@KE7LyS~`r?7c2qN$w*W zG|9btJCDJJ$qZMuWv;*s6)8d1StPPQYAJ{?iZY88s;;i>Y4%d02N9u=dk}a;senM% zE>(E*d3>1fGTly&Rs~==nv0Iom>~9=>^k-7d9s#mO%+F~(Cp|6n{o;w{rkd$<(2Adv2*hhl^q=m}+#%>MgAER1 z+arg_af!ilESctyJez3bMmf3Yo7mct4z0njWJNN(!kC=TUIVs?UA4mx_cvbLp9$X1 zHW?c~HH??6?wR4%4y|855B3c{PI53Y)77ZOfTlGjXhkXyz6pp+?c8u?zILwhefqOT zQ{iKjMpGsD{^;)>jj~rDQPH?Nt}?;EIY3Vol+08kH>Q*NRU@z1kNpdptWCrt`(Tu* zI(N}GPt}f==4Y(%7b|m70jP@gA2O9vjmaz_vMZ(EiAHkAc~xY<;=pPTZO5YB-4yvF zs`QohERa1*fobvzPZwzMhKtO#jkoeVt!SikMg*e z#DJKhzrN9?oiY1=qvT_HgClDltopo);~qTU?zJdGI4 zS~m`>&Pv)%hqz5m~Y}k=q`w%I1xgppuSm8V|W|t!g z=I(0YN!t}kxGfR@#ovIr3}r4(mx(XS3ULVuDU$xKfC<4g%r8%4C~_g3Sye+Iz-ijp zwuUW%P_8MeC8uil^H2yv0$<1!hYe~9>1%o*e4;xCo&0~mRDxWRq=8FpJ63x)_>x-f!&83>u=}p5}aur8Dv&OSePyV^3)B-YQ z+pcTjC3=5kxXTtWW5Cubnr%Cr&+@8^!GfxRBjH}pr zYy`)=*@43#L429HMZk>T;gr6LNf&)jeDC&3k-&q_5JL+(5i%Adv3osfWG4}d?+I_G zUX9weBySe*{MO7+6y}eklC`W9S$cbJ962e11$C&*VuX zb>k!Q$!-{fSh*l@?;atwJqG#6WGz~97%QeilIBgk_q^(YQE1DE5~nXYQkFPDV}4^2N;UrW!a}W4EGCHcZsw^ zD7kh@D=#)vpbz}h%w%|bcvzpnZl*0jG*>lEJ6Nbx`3E3A6Z9M)X*a?F#6(RE?g=ww z)(RcN5$6~q)usy1;5hxdqP!kH=efq$aCJ~#tf=@Ac6+x0YOLLC&(dbCUy zbr0a0K2*ZAo^mB?QV;cYR-Cic(W-$7c{OzJ@b@EoD=Y;Oa_ZT{(FVEV&I9dHjD%Qo znrEaGEPn4g6V zp{Q)6<(-5%J;P|rs;TNxZG{2nZpE=_Vl~6Cp%C+Zoxp)=??Ld)2Y6@m<8NdekwsLR zLhiz^ua(-D2Ze20Tt|<(vzK`Fxf>nOl|qYAYQ=}1lnwa#iw3DDzRM>u9$2t6jmeG2 zG7JX~J7b)aoqfF#Qbl3Y>V?i~+6eL84joJunlIp8@chnv?Q56XHeFj$0sfh*7BkOr zu4*L^IEgJzOS#^4Tj6cz*45}PoYO;UFVhBg7!SXHv7H0G(#+$@7a|CQ&#rG#M_Vtw z(uOQH_(*EL&vvkl#;HtcR*rOyXjX5vL3_FTCP?l+ppl*4dAw%5gSt=azd!6XrD`~G z5!~?&c5K=efh6JQBJUD0mD*CB z_LXK66MX~@-pGk0hEnA9f5kA$eMXz}zDW2$EUte}&U^|$svH-s+-h)r-a9|{nD*4O zSNXP;6(DKW%jDQb9ddtweBAe*QMpUCA`FP^>KinE-Eh+YQM7*6t>4Iy$P;l3-k`M$ zW@S4WDzbSZU5me8>+&S$WKKQLTx3ZD+4a=(Gz(+Cz_=3;=K-@Elaqbl6oS^Oj2p-#k&)_HP z;U^Xo;1|XvnvuYsO;F(D6h6`@{G}@+2z9(w5#B8S`Px6ennVZ!Kl`m zLJ|umfjjLoy|x8i?H$US(TP9h3v2{ca*|l_LF~&8KM1>>mm8TzuzH+KfZ$U51VBhH|DN;kzV>n@tE6mCRNR{UUkyCWUdH4{pLS?isSC zI=Xgoi?YZJcgtktT-_R;p_BMOGl#jJNB!q zNV<9|aS)yQebaxXl1hO=E@xqYfCkusfC&Ec9q^w&$;Qd?uP*YRmZd_)3P6v7`{>jm zgd5_tHd}>g6+%3)x?vWW6Z#5WP8NsdW^KAwk;W% z+S=qw-|ycj1+LLT&VDfPF01u-()auRi(!Qx8y_E2p=teYc~KU?2lCC1nVr^c0y~@Ddev% z@b)!FijceQt6;@*Ee`Ds*?>?fu^BG!XF|8qSjNh-D>Bn1})iy&5G(@Ny^wDnI##mC17aUvNrQA(CN0^Ioh5G#Yq)8TG;^5Zw#H~Eh65XpHP@)ZwInJw#=&Yd1Z-BBP7 z7}PW@ob`#NSB})s@7ISAOsdH_Pk7-&r=v@%c}YD_i2Jk2vB5-gAQVB$6!ZN2aeh!Q z`48pg1rt{|%ge87GBR0z%`As}K?%;aMX1hj3wcMX(JCRcbQxueXj>Do$}m4MFXs56 z^r1iqc7*QH8#P(4*y-f#ynXuRDPxCY<=E2Zl2bvyE~~XQynfmG+{#MEOyll>7tGe= z5VI5cKqDeSnPpG2EEEt&S}27l$oWy$yf9lMpR4kdXm=4ojpEzf9fN7%SdlCmd@Bk^ zfS%KYyQ0p|MXI-aeGJOy-^()Tv3hQ28UaT0BBUFE83aj~`!5oT>dbKiaHuYY^}PlV z4NFcL5%N{S9eJ#B84mBol3tZJcm7j@5H)pH@9&oc;A1KRP3{1M9>sar$k#NRR0AjA z$s!bY1l9%SR-hCjNuz^lU)r~zj`YRD--aCzhVA#NUz(>WmxL3u^Gd6~v@+CWLaC>;;Zz+YkMY>z7;>82?ep`Ml8DML43UAzy9f zS_@GC)O8oH%O0*A)d<78-XHaK=)@j1)lk5A6&Un5U6SIqMi~J( z+BJ6dVRh5HUa%i|Yf1$_<%s+O=M9!W#lp8a zB*rXndNuDChFfH)#5wk;D89Gdu>}ss2|0x=i`?rf%8|Gh((G8?exB@ zcrpxJo&e^m2CR1ixmUZ7E5{bk{GYDPkGwTS^yW$ugD@*FJ-*ZfzXFJV`*nne%OI+8 z99>xq^y>_H(5H?P2`Z-?6(vxH)1u)f&nfq^|XULR}HWK7D zzfaZS*?0tz?De&?jMVw_FO;Dwq+z1SS?E&-Z}+!a-Pn12*m>6V5nbr5rmu@&Nd%8G ze;*Pft>nBkYf`pT@GzQccDUW$km4&?zFnI^YH5M z4sq9^*A0@AE@zXGb=EHm;*wNBe7;-itT+43 zgEJvR2i^qOOnxl$zD{ZrW86N^zD=s}N_=UJ*tcvEt#eD>-ieQCJ?R^~6pv%znJTTJ z#Fs98%RR7A_Rc0-dDBlm;E+gOVeG-$8Q9;q?0n1o>B(^6Ou*XN4L^qOok4vh=0uR_ zskZUT@dcxHrzDl!GILr>_RO4qwV{!YFoZ?kRDO82ztO#hyIsYMu#Qi?LVY8#rQ$Nx z4PCX23hD0hd-^nmQc?7Q5^XZuogU8j04JPd<4u>e2HrCo3eq1hRVS;t1ruH^Yv|?% zuyW?RZL%h^oAZw;1NP4ERgxJe>HIiqQ>O_%RX^XP>DBHpl^Yam#}w`YQi5~5PO_IA zf77~sYS|BV-~p?sblQb`_|Hk#q-308jT#wOR4Z>;bs`xeWRce^NYVGe1d+s%5*8mq zK@_Lkf%V<=ft4Z|^#4fiAZn9$Sva(Vj|NEO9Tu#=6+p z1}hX7n;L!k?8-C(sw!YdU0Bt-S>y?}jR9dM1R`C;gn68x5WJ=05tP{rB9dei$QGds zd+%XD@&v_T4$94u8F7+#R}^wTMC|qU=o_iAgwK0M>Xwe-GR!VxQx;8BDKV zb>}P?;?lQ;Eb{cQxFIy;e328J$;d=?&I4TX(M2dN-K|;BVY81FAQ=Yp{&Lgo<^s=p z=HC1+feCrpZr62$RC~&G6xr?8&=+oD-!KyiNRKWzvGg8qCn6x8tW=gDQqjRtHmckwS>=H4-WcrvMR)k`b{OzFI=g1RPLBk!{puBNARQwD@ z3LH!>hq4e0rCG^QheGAA6wfo>uX1jwdU%Sgoxz@PB0{eJ%^zE~QAs~;+hTP$|8_QR z*iqO6wW>-4&G2>*sfN@+lRPOLn=kJYFhpKhv!2?gMwrv6$9+2xPYg&4wo+X_KnJq% z@R=s)x7nyxDsK9=0mtEIVH_9)Tc!|%sYThzGGbO8(|YIJA8xT@&x$A_NHmllQ7ym| zLB-I_^J;pU7cQW0UlV9KP5lJ83~}9-WH7Gua2nI~zP#5PmCgtK;xvQK54{q>sE$0| z7`4aK@pkOaq0jNf1ffJ7N*8}YAS@3`2p)y#V#Vn!t?@+a1rx!C?pvYarVEinDn+c^ zNEB+p0lCMA(+S4AN=ILF5?FgM3_LgF0LWP?cJgrV!%WoNSku2ffB$)+CH+DDhzA&Y z4j6!daR0ZV=ietDWi=aA1|;u86*!0);S*y8B&bzOV$+uXQdWQ-bJBg*X{7^S%%lRbIQSW5MPVW-GTl2>45=FG3n}IqabDK?+wPsB;W=^Dtf!GZlpZr z7aL}8zpW98Sfy*)&lnvhU2wUMoSzW``oEf)rVp62aElMKEv5q2%mnfF_+xced8_$TwuUjQ_DYC z-w?M<%~}x?#JeCS2x%>3?$w{&aQkHPs2ZSE(;F0*Oxw=>EO05DO0nJoKmO3YoSX`6 z=@+SlcLIW?C>aKuG>R5eJ@Z$LC#FNqxJ9Y!=oX9@$4!Yiw0X=!8TBr6`@n*h9%km~ zVVIoG9kok@kP0C$dVve-Q5y`EIse*}?AOC+kep1i3KEAI8=-X_6fE!z>ZtvZGEKSTEkP&Sg7S@|1@7gYTFgtp?ybR0g4>-?nB{ z1f#2g*UzA{*w86Y5a9s$j%N+Kv#jkolvl{5#t^{igj{eu261OVR=q%hmSwd)@5JDtnSQ7b-$ToU^wGoFeSgl$3sFzPr$pU*52 zig9x1{TX#UX-+#A5LCz73E2XFnBt zLFDL?DBiwIR|*+)jnbw-u`nh`Y=jGabh&M*(;d$cy*vTe<4PQl$6&~BCONCJ=4BMv zterfV2-Y$3bkT;T25aJ6EGQp@JO}ZmaIbZf>_5?2>QA1dv&7cx9ga={) zqmF0UH2(zrGx?96xn(H>6xOv8h1Pb%gLVFPm6$sY!(3ZnvT~;wt^?+cX{$9!MGleq*4wDLxPM=+!V{EiQF3scC4X#Q$8^RMeM0t`;+xA^svU zZuVD=ysFT|k%FcfwwPy~OFMO+!+1Y&c+8R`1E+5@6#U5d2DM7p)BWkJd7w4vlfXOF z0fS>vZbO(f4f`v|xlSP$M2}QL5VRGc`rcStXTZVJa0wCPz@fs}R($RwP@B`dkcuB5^5amDG8@mQ+U234vn`XpQ z-*F;>O*XHc+C&Z8&D#j=?8R|@dFLE>b)XTkSvEoHSFj3TN_O_B-2! z%DcJB9Wp;Mrcy3MaJps#8WTQ%l96D>2?HulxbHf4qe_nAq6~+Uw1n7((9` zlWlll87ivq+xy|`4~OW*Hs$X7Xjz?m^?=hb6G|g^=-GeB(*g!BXm60_7-i zf&|cbY0@`^y>be?k*2`&9f6Ekrv{wyJ81h>M+&h8WZD)Qlzf)XCCaDi=sq`u;-lF) z9es%vGe0@%t|bd;3aDhZ2-;AlqexmBw8*it1S1h|)8G-!p~(5wr*ihRD#57^kD>aCk5`khn$`kq}a#|35n+Aae{KGr{4o>;ic!xE{zv1VWE0O$*HHu~gmY)vGKtE)( zOq3Q2dQco`H35lDvXjQ^ZSMRUWX}pNgD6H^{Kk*Rqq;{p$?6wE1G9J=rVW;x!pmh? z@P5J>$e9(IhQ7%-a-jekQc)7)K`i~6u4C-Tk%o1`2dfQBhgBc_T{RRB+#3D7M0%mK z#$K(qI~If`7h<>w*&yy%?0&=RV_hdDM@e6mxLgj%*eKHk870xPfBMD7N4fuwS{odU zyZDw#T|JQRvwk*4M#PzZPpy8M4t?tWEp-sZD?VG+;yF*K35_eI$z-;rgF zdUa|8T3EmIdLJ$<6sX06%Z3ecnsVW$ z4!c&JSug51Q3YQ4s|w36CNIhCd99r%e+i=H(c__^wg zV^8r;VP7P09TM5u&~|G-Qi~TuuKE+9HNSU>)>RMq9;4SR1VfAgieJ($^-PwINq9YP z^lc6jsF4Ip$=MjDVy)2rb!JWy$D8Aw!#l%fZLLdUig(+Hr!|Vs~P72~P^# z$9EL$?oqs%0r5q9qxd9x&kLt&OjzXa1ttm7j^}~c%lb6+EL592Zs3exN-i;OL$pl)e9p`xwQZYGj5n{NpBm^~t`b+^|CR($v68}5= z|NZdbGqe_<4|sTp0{(w&{{I;(0Z$IIQWiLZfV+y1%)B%!nUYW?WugO;Ar>m$ky!hf zdHCVsr-}}{jHZSpzM$W#*`dZ+?CLqr8bde1ht-w+SM&SkEzA3M0PnZ$or4d?)LU3boZG(1o|9n5Wb4Pl0C`H-v~ zq@_SxF}WtakD27;PY%p%y;dEw5eo+MA=Um77)qb*ADWB*V*9n1DRD zk~IbobKMzl?k={ppn<}+rUSuF1S~;N7G;+n-WS_?Kq(&b(0265A(!em8hO zVm*Iw)wgP?n*${NxWDj>*8hTMxT||+w*p$%q4o5cdimIaxz`mmiMTche_PihxMp$C z|EG1$`QNSU5wF<8e}iWr{R^IviK5L(p964rjYKVkw1{lzk&m*P3JCz%2FHQlaP zM1P=tb3@JmXkW{}pnZ8?Zis3z>Frw33ph@oa8Q4wTs{3n8S`O1Dpyj39iCc93xwwo z4W#N9#1aoLj6Fqh2vmdu&ROv>p#=^cj8$)@nK=Sr`||x*?TG?%$4$PeRCzk~9rI)} z)sSJ=CD^j28-EVe%@Rbh`wmkij~N`@*)F#%19JZ*%$_gnYHrf@%_~{+5X9wkx1(-o z!YR&bkJ`R(1=fb;lSvXKjDFUfh_DOOk3AO-{8yYf#pO} zh)PN#`3TLfg{Dv}N3s1S{1pw>F1Cl69Q@fU$B#8(pmG0Ixqkf5%5{ECVu3XZHzU%Y z%JtviKmKI&r*ciU=MtczA+428Qb73q9uZO)>pSFi>EFtA-k-|#1q+#eXAGcn9h>F| zTw9g>iy0%J4-}{Q4UfCqfP2PjWhxOJ?Ju@Z|I}kq`d7s#Bt+apI`6KFtw#9_m*@KR zK3I_J9_;9ewew$6Ia(CZbrD^*7C^4I-g(8z+F9Z0vwhkow86?R8;yx z2o8#3C*Ak7%!*Dyk!TzG^SUywtMutA) z7}!(XF=j;3NJ`%;I5vAPKeNbJ>G{*R9x|K*G_HHp+Noc3#Qkx*6t&`goJrUJa5FCR z$EFk!J5v<M#Bh ze{*R>t^orX5nl}5&&1A=bAlEDWtm<3e(WDY-7a7_+J3sxyit&EA3YE9}*r%}Lvfu=HqfmmzZbQlEhS@WO z{U!%rvq3GU_~Ouf(h__=()Ser)Ht}eU0?H1ZnAG7;b|NAwpmIvcU|)Ht#~!kYu7bF z?}uqr(Fno#DrhOTr)`o}%}0WMW3v!RN_i zB-&Sr6lD{5Q1sJhM(i*78pBx8iMZ`D7cCaGoHHnMIOox)Y6mQ&4DaUAP{+xTC(^Yz zlwk3O<>O;qdm6Nt7njQDzK5h>fRNTz!Rn&zI#_K=AOnTh6raJ+?47mOlJ2OP?PvVX zyu}%KUcArdt;^IVu)R=iKIb;ilt=WCM?K!%tkqm2VF{^a4FusprL11ymW)|`#*x5c zUEj3+VGL1DbC_pP1C^ENbYc z&Rkdrs_Pom9SF!y+>66WNtq?Q?|?bY5h51s^iYO>nzoM+OS4r?EOr`b2H8IdGrK0h zg8IolHQZv9yshB1RMg=zrczE9t!H^su9cP3$!WA2v(7m_kp5x1xuX0xnG+>PPixx* zA$)fqrWV^21J$q9O5bq@2mjb{*yPtA7)bV&qyBZy!f-#(>yQ_I?5s^fx0jClJNRDy z8s|i63D%na#ydm_?03TP%K908?q|ppm{P~8qt-$~*e_`wVy)F+-KP*=@U?f(2~uRD zKU0r1l1=cs7{8E{VXrdW{FSKo0xB8`V7gah!YKSY5K1w|d>T4xWz|UIoFhLp!5iU5 z(ZK#3h`b0SZHF**wC8sZzIr304hfxRL9~BDehnJcr*43{2%C#5==ZJC1mD0~w8644 zOPVox4599Rtne|{`3~Vjij9ia0KSFwghg`_P9bIx>u+fq51z1wET(Xo`jFfG8K*P< zx2YjXC8z>Dy_RkyL^KhU@2?0+Fma4H1t4{UWpijd4&=_lhjx^o@(>F zArl#7#mM+xm;MJ$oehGc;UMS}C3nqRWIo&p8$ke_%qdcOLR2;Alv!Ji&3p2a@{jj{6b6wsQ6WX3H+Qm%e5 zm-J5H0@(a0!OgTL7vHOsK?c)vDVMn^cq4oQd?0kLP13G4gCV6EOWqY)SmTAj zR66JD$6A-On8fRC1Co*`dr*Yjd}G*Q39-0>g%D&!j~kK5XA%|=xLIw?itLzqfF)I{ z`suuof`v~rAIqw-Op_PUnaDhlv}e zH5uwH6k&q0Rxt14DK}-F6qF&IdINHYkx{^fflqg`@}@)cqAE2`;;?tvTH;^ntPq&4 zc7%Hm_^UK&v>`zUz#G<0Ss*shtYg&HAJ#f^=V8st`vY`}(OY;g6wUv->ALK6t^{2x5YDMN&n*OwFzw|eO3-}>i4D}oA`{j* zeWm0yQnF6=$w^KLE^YjobLkQV^4qT!m;YBo`wZ@VNX6N_OZWU~yLa~)te9znz$M8i z&&fm8xPIB!yN_JY&X1qb&s+nJq+QD=F>RM-U$U~7i+R^BJ%B@^Uai+K8!6vn!mC}i zmp^eYEd{3&-hQ6F@HVqwZvtI-;4WbqSo&BVz$0Q7F>)*yEQKCvy0wsz0R$t$YP=o)G5o_sRYMq=(dZW(|Raw!ZFb+CF}VU zxQ}3wuwt~IzDFHft}km(sub11T-1k$o<{#sGX)YnznMQYY6YjU+3&&a5X?hp7>CMK!0qXmkdKOS%d3)BqYg7u0el(-GVn0P>y^CyH{!NQrxrNDd&Cj1!zK@GNOLjA&o-u*kfN2mDu*jcOROkgi z5}8YhWNuN%nxF=~nq3?(rHdR1D%yq#1jio0zYblXPL7@*-#GQmtL4NL$^#rH0Sp0w z{h|eY2B`-du4c)H(dT)N4o=ThT=zf{^UD!GIk`f`7l{}576Mluhwg4MsvV-Up~pa9 zlOs+M--dpgeH+}si6{d<)e#Pf)ayq60w#Ue19adjC0ddSPYfZysXQj44+>56Jb7_< z1Sv1kkJfY<$6D$`o_m%`Q0l{N!ngMwKQ?!;XFy>D`+wV*{ZG~c96!#E|0!LA z&UknA6|8?Jnf%3==pzB4kB3CdA#0yFGhGc$tG(cs+}~;Hh|dGx%(vaBYt@!D-ORPLitVwbq4ZXdiF#i}w(w0y-{Z88&3se3 z1PWw=f0X8a?dD!(8j>bo<=fIC>YltZ!3?g2&hD@$|?F0qBBw>}sIk z%0=(4R*rVI&s;s~<*8K#BQlwqqiA>I3ox)3afIa^I;?8z{E}q-K^BwugjQ~wRK7gZ zz|y{Pt>?8jBJ<2A<;c7CbsirsRA+sZX#aj>hM}g8u#0-o07WaIwRa;ZLD?T@po zri)$Yg&~`{a5geq+9oI^&*d5OZ)p%HLEjs_fYV21RN9?T)Ak)cDF(6PiK zfTjU?L@5HyoKB#N3*>|_njCZ`7>I}~7!5E2k>+L4Xg|EzpgjC7(IXwVn@I35ZDBhp z?4WZyLJZj0!E5*_w(vCwu?}n^ghtshu#+Ry@fP+_^->LlBs(wpOmv_-%%id=Y5b*N zT<#}If9JZoi98-!3K_GBqDDTobzW}C8-?|=_rvcuix_`iTfCC7x~1?;;kS&Br=?*U;-_Y+Tx@C zMjWvjk4wYOsSm|STG5&{2$vuwWGSNGN2p0#4IfJR^&Xl(9 z+D~d7dlZYYpC86~5)N=$1&pOCDV4WG44(wIRJ^3?ou{lRl1+-YXnSi5pU_lUe7h7c z;HtPsKsoc~Grh6}<$uM`l}LO49t1Q`ku5v4A~GzDkyQia}8yS(>D5s$9#foH!qg znLm)I7n7!MC#*O2AU`l-SJKJZ6TN-{|cCZADxkfd_ zDEpCWp(!e@5Qz;}+i;lnIE>eL?AbUWJz7_i<*4KvSKZoE^)`@>f8@Df4)ACC3=N^^ zGjQv@S*738*Z6dI^Y`rPc-8t+wkDDU0+Dr|_++|eU{$UcIHMy2SQyU@KT4YvEah3F zXfly?*Q=M7hn5{J`_VGR&dL`%cbrYJepL#=eXhXPvbr>8x4 z>?^S<0R<3Viu`{3gCcKhzmCQvHsUF^LB`Be2| z!wYAbGAv)8$a%EOJeK9nCB!%@eHEV3=T6yF^EW|dLctA4pa~W zA@lBPL?b-fK%ASXtC53}ef#V5Rs1bCuQvy?36=@VPgUE*y{)->i5nno zQlj}Kl0)ntyLGHMs=Bfjhj2%kZQP{G`?rbQjo_eVa*3(>cxjR>}`#oFJM7{Wd zXUVPzE^4h-PfIBE0X%Ubo!vdWA^U90bUgRTZ(P-(@1zANs2;4D{eew%~iCi z-+{%l^J6q$4R%Dr`!#lpmq|%I@rVD=fu}Y?7G&?@V=-ReGHWNCP*3FU0>&1s0Ch6Wnlt3<#pL*~)4KqH(^=LlJdI zB8)4{l0Xz+1MA*rg2*}^PqMSn8k3EsjQ1pX%c~TIxs<2hDV_6A?>f52ShgU{5cWqf zfJbJ@Yy&_LMbLN!;`7s*?UlUm61JePR23!&)y7xN#*h$$44{88nNimk-qTxCA5({a zg%hXqfHn(oMG($F7P}BJg?E!w{(Sy79M7M{3h;DPoHYPm7)0>j8!uyP0MpjU*wOHR z@{Pkk@=cIF0Rx9DvV(bs5g0}DF4uQ3Hv=Qf1PH5faY-S)XIB+;!{UNe1q`?F{BgX> zsaZ)&cdwgYt6BTa(^v7qQwq25ix9Y<8R32ae z*QeUt$4x|Ca%8VD?C$1Tr@MN<5-7nCibJv}wDgJ_E{9zq7XR&{b4%g}YN#_|K^0~N z=ll=IKvX$`hG6WVV{rr-;iMT9GEX#7$E-dUZGJBw0j7}%R~RKB9g9|J7Iz@#*jRFg zXe<8noZEL`b@5a}a2Aydky1Z#adQ8;43vehUp8k(lF1>tSNxTT+<%_YUY-1f$D~OI zJmIGhuwOh;rA8Ak-&%%PB~Xh;K3j}?tZ!#lHGn+l|7p82XKo(O{cXFRF{{hc1KO^G zB6Sl4%gbv>6zdHW>2CUDg8L{{xH>B`SzoCVL=W(M<9nghdyjYrq0g@$Bruj7Y$X&> zh^gW%P_ZC$N~kQmFJ4GaUp46{0PGl|=*By+PjLfszjo~F7a{!E-?`6DW?cHj^};9$ z9ibxgiPLwv=a)eJC?;kL=1+uoW$R# zVheH=h{wBjyVj+$Al5S|TrA+yP?H8K%h&gi(_(R!4vf`pK({jjum{isu$j}TTI?5{ z+anmAn-(KyTPwcqP86ALAk#IQjBnUvRazd5gBrkx17>e+fZ1EJ6h-lVez_Wos-@$4 zYw-di?H0G`Mw^RxSKj0@7r8QvQQ|S-rB&~O)ES-%VD@$~BcJJi5h?f$74KRKZ_EMz zFFPh6ui-B{W>X&j)lsPxj=a4@Cff^t1x+$VqVe3)m#X?l;#un0RUC%No@0v=fiNf~ z$twXmCl1&^Oq(Tu9dk4xS0bxazr?S2`eXKlQX5ywZ%NsB+BXA!B`DXL33mY(m0y%c zgiZq5>%7u^Y9PHNxX0Hq4_&~7XOSSB;#|G6@)vS*iH-)Ij^=vLEWxcbftUg4TxN?0 ztRQ7Etd3&S*G8F?UrtT{8M+-LzJOv3xui-TW)Opc3mM!2Lmj2SeDkirG7p`$d&)TBBw*F$SB@WJ zLQ`oqd(1l~&sS7PSm2Mo&PplM=8w$!|yL(D@XMB!jMPY5SMX;i?*KDAT(a@VKGPGa67}%4U>ld79 zmJNSV=QfgME4y3qC)4g^bcSnz?ruBcsod?RjEA<8J;;Y3KVH;h8{~yRGjrg_B_HnW zuJ5>O{eEifC)8$?xNrQWH%4ZoP^#ZPbW9@0q2 zMx0PYGL;=UUQc7sFrpPR7COKpfR~Yb7`$9a#`Z{(!G_1vrmO#HzynSOD_2^ptm%J zD9rblAoCD@Z48;l*U+)dH&Gi)>IT|ll?T#1yF&Ndc|A*>$?0Nq;`fvEJ(5pwQP}$j zT6cukjlGS11#_l^FNeuyu43slR(Nw{d}OF;kZFjLFtt6`Kb<_Av!O9%V$cQDcySqz zE~O%JrqZdH=&x>Of#O=*MdFGsZLEhBIWXuI-x^KJjF4WiGbyz1h?tt$XRDMik!0uJ zZ5pnnI$XB*gJfE7(0k98XAe6OA^R&|Pth74VTH`8Slg(bKJEsVf*k}O`gAD(GB}sm zOvC~raJ?QJRsikfn)LVWlCKic0Fxf5j5{p!AeYpdcDr^t1c(3W5t8(ouBsM3zUagB z#i1%Y;c*Fcpqvc`{8;@9TiIu#yawvaMn~+gD^@|H{Py=S#aGo72>iolA{+oS@ZYXK z{>-kByVuhv0r{%xe`)RhE2IDhS2Hqy2Uk0ta)cY!6mpURnJy6Ddj0LJWG8Tx z-k^e@Kol_>D#0*|f?RUo+e2o}i$I)8)S5h^Ly@nZ+2g2CB8jk{zakPtR#5_C1()0y zO8^PvFv(+%hy2@P^Y9S+Us3Zl_j zXp1(^LcHhm*p zh`4L5e(Q<75Ste0cgZ*s$|p?srNaq;@%OvyfnJ?%3ellH zA=(#Zu|E@qXMMS}=~1=x&H@ymi;3qUvD0vg683n5(ucf~JdB^d&cqN3<;!|Pgx3>I zHI7Z4(`RquNuL!$Z^|E=h5Rn`%(^v#oYTBt%W|1v5l0~bVMlnTU0N=DJ3!#-{3oQkY$i_|JQj#!nD z*l2H}3A9Lo| z61|wae(P!a-X>jUtm|3YF=bGdqT~}J!jG8qq2+&%I)HF`Rw}+bLOfU!N_JdrJ{AGF z7;drjYAWf?$i@3JBLykfS$*|x`v91Z(5$-FuPuL%JS=pC)LaMAQ!|^Xmehjw+FJA; zOMJi(Ha=`3d+{xT&*jHy@ZoM_;{y&Xkqn3f2^+y=c)4Smir}hG`Vy?}j#(x3FpT4- znQIPn$*Q*>ZgdV?I&Y9RG+T)LRXdE$BM)F@`+5$I5FmL}t5TrMjYp8D=6Xm#Jgxm1 zfMn%5Lw7*!Uu_FwS~-OpvvO1zJ8`{Oik2{m7Srzm9#ZFMpTA%d9OJ;-*4Y$M%7k)D z^3%a|!rcByXXLg}t})pwyr#Ld=zuOXwNzaIy%FIBaT6~ZLfMw`R903A7mtwtoB(eA z>FK77Vfe-PhdKoY4c#?Mq$AjYLPd;SiM*$`d0~u+zjYR zz@8_xBUWf1&Us6LhnmjQ7@rFsX-+*;{(S_DB!np*{)U5f4MJzY%Tb6j5Z2m`%ASIHs5>nXT%V0^Z?D_Us&jLG{eb zPPDw@*qHYsDZRMMw5p? zn-6y;6Y^mU{2a@KzDef4+(r;JDMwNj)=aCg#)|-$S9I&-?rbI1}n?6L) z?qZE;`rsjwY4P~mWN09I&+A4s0pIIX!Cf0n`Da)B- zA;+@v5|sJ2VPZOD<+JmpP85vAWWNKq`#N#wP%D(7UeZP{n<$vcf1vPZdtsMaS+3H_ z{G_Tg^#0UvQ1TY+_W4*bVlC&yP{PA|%XGHdlMV`rvWh#XJt9<2M+vhjL{YhvukD&Ws6N~DxNt<_w_-t5h_x$5cAf<=VTZieO;r%@~> zV5W<{6Tgo_9iD!2-8eje%W}mPV-;}jqp)K_$p{`q5IjP@jB0@WNU&8zISkd`d-Hr)WEH!Jm;aLq$(=ra+g}Y)u8bNIEq4%j}xhyHI`y+4uAenm?22@nbK z{+oYi{jWUqXO}5uF~IQmPMb)&xo{;uCo$UyBfv^xUg*ewKM}9{XT}^@-XcArH@3F| z_R&`IS~YUae&J@y@U;sEZb+kS|BWdFl4F89A0Pbi=Q#b9<(&wlIu#Z&`8^O3v?ha| zFvV0-q7iQ=?L13n&gYn8F&%f+L0O~)p#8Y|4GA!9(3r22ev_o(VN5VHu0Q?}PVTqZ4)e=FHNj6JMojjvYWMVKCH zCCRa6ZL&WVXS`Xj2n-gJ^`LPwZcJ;4S>1dPYd$z?V5>pMY5eT_TWSBx!+(TF0W%hg zCcyP{5#W0IKX<=>-Yhd?eWU*)tWy7TW%su%S*sn+(oTSI-jw8bh*X>lC`;P#Si?l) zS`}{wJYPv$nPv!aqTL*28J2sY2;=wZ7fo@am~&cX#^GPsL{yCe@OVGW3CvydyO}}(I z=7c8H;q2TBq~?`=fBX1Z_`Mq3TA{-tYbP=7Z5Z7}_&9bwZ({$JA7~@_of+#mdOb`KkTnlv`2U;KJDIp>hyps2pBq!$5l#_VhfQ+no&DM_es# z4okNPNtUUCg%4SV@Mw$fbBJ$JJfD!vtRJ0UI#sU0#p@RN^s>ePvrhMUfls8JHJd<1W0aCJ1!rA0kZQdp|zTF z$0{71%^yadN{YwhM^Mgp^ue)e)2qmI@JCT_m5w#=y7U5Wq}g$qy<1z#w%F$z5{t?y z4?5G$S-gexj3aLdY2a_e*HLa=4-6;D!h?lVCH1uuQ2&sfH~m9)4h4{%*MBo;42XApP+!C~i!am47Xf7OY4N*X!WPgU-qnbj1j@}sf7vBNY@@mAEFjB%5b`7 zyoZ(xtZP1j4fj7sp2VTfZ@l|hPnLa+JOj>v=rqMw)o}oINgMZI@2doanqOFlxG)}9 zz*C%A7gr(&$^~+NZ>BAMkazP7;|%O-rU|sBBT;E}z%#5Q@AjJ1nuPz}OuLIprNlB) z3&H*N!U1?h&$bKdwow~&;I25an;(58I9BvksUwF*Rk5lYf7q0%$?3-h;UA6Ks*&)04`bnh zy84VQT4i`oQV8ESpF_qpYFtT9-+GNMUxEhHdZ|ZF4kfuP%AD%*i8VV3p;QnZ-u{nq ziGx!`!2{r|`YZi^6T$4A{)nio%#CdT-~T}bThv&00O$d{r&V*U$eXx-Qbe@9=A|uN z4$c?IAiJ*dnG5Jq5+2bKkO2Gu+wCCY3GuY^O&!IJ#Oq7Jj zHEq>uO4gx{Q#{_wa!fL8ZMDCdS79ATQ{BMo=2*hj5!KJk+W5L3{f*eLa{cS!bC`g9 zd~@UOz7~ya#XN}$0`;3gQh;cxJ9jOL7Nw!rfQgbxuB=b{^A?`Qlr@3xO1HOR4w<}U z(se)A)Qc;5{uo&iVy2p6n4m(^h(>$;fkp74_*~7QM+O=+&^Sw6nMnLVX;e#A7ZGwZFt$JyVgnXXMPX7w2!?es#Y`Ylen^LR5|k+wWg3;OfX6>3 zP_2YdW94&^p8SA$p_=kLL?&3Tsd~en503vLcUl)D{SFH6+UgXdD2i|UK`?#;E!4Gk z44ENDaVseG^|1WIOQ&NTT<`+{E?Q?pRvS#IF3k{6PJ9Q?-}m=Ie>i?*y+e zvb8MFkh;5pKR^+2ut_N&Z-T9nvtv2rA<#&n2`tE%0-_i;PFE-tKN^;U~$qyJBcl6@N{{q^90yp4N3@uoetB$_? zrZ(z~UMkJ^MUe$%euXLn-OmLA2&++(H!KpBu}azH1pS6OK0@!T$S(Z+ z_wg@``&8e0d6uM(e*?X|fzDzNVh^ltuX`3A;Ee5} z%qC6Eb*`=0Xe*wEVc8l)KEX$i@SEMqWhGEy5m6antFl>YiCf}n0MQ}6o z-Iki;c5wsp0V1T(u`f;KM@&^j^$${7>|QaQ7x-2fQ_A_9F#*Dpmq;orz8hwb$Q6(J zaq|}1mipi5ze*67#B_Zjq&VhL!d$JsKt%XX!`+e;=UU_~2)Tr9hWwN?7WzZv`s2}G z)TuE?Jo|33$|O-1n_a(Bvu)0hv2)=YV2GfQ4%!S=!Gw1tFLFr5UOYJTX3X_uU6zQ# z*Ox6XI{NfgC>xjCN$W>K#xIXhkrEFX`K8!e3uz%68d9+3re(%*w_(PjeZyos3|~qE zv?^^DSet8rB+NB|%=kjra$r^OBwg_Co4K-C3uRzQD!Imjzzc z%dVPGCAe!icxV+pSxy`}b*kmtF7*lx-to`ftF;oLh=e*Jd|!JEj0SIDKYj2>Y|RIX z1?iK^yS2T8xR;ecZjyB5)EbFt8ePgY!BXh~@`i5*=2ekPi6XtrR;*+O@bYhQs zLC_GfTI*f=a*MZBkGfV9j^utS&|DKIDER;&Z@swbrfXRCrS-DgZ68H8x=&-jRBSqj z`ipt4h}j0oHh6D;OtjiQ@^va9_mX3Jb-+K!_{mA~=6mbm1tQ``aRC`uV7D-wx`^ST zfoyL5x-05h^+ensV_^Kc5&HgZq?n|e{oJjC_q?Zs-^>-558@SPzhc-+Z^!fZ{s=xF z{L|!AJxMfqS{~G8zZdb2A`^Zjmo~iGvSs_kgLd_?p&zVwBu6v0-?A^tox7}Hmk-z_ z_9puVup%;5@e^Rsa6>tI)p9|2<+Rpsv*Yd$?$f;tzI?}-pS^wdh$q_h^9KtfB@p~{ zoh8+e`w|*uPSt5*eP&3?0iGwTfUe0aRH3L`xzfDh)scMd7;v3X*Kfc>9t&6SU=@LJ z>^YB_PY9 zW-)C4dc!$oOHgca!dJ(h%~n|2W!SM=`MKff|6&8*mZ*5`sk3c}mw&ncNK$>rlc7-m zB+r%w;p2?I1$cG*(`=Xv_zv7hFT*rXh_)W^+8O+&U@`A)?p+RD1P1YMo)s+=nUgzE z8D`K?twKj<{0ppJymD>lDh(eGhwn;3uU5Gpy-QAKs%L37Aeou|oY4pp72Wd7-P^m8 zFZz9Sh%~s}FAsYG7(-z%1uiugOLVvJx&!o6wPuyzWgk{kO%tjtd&}Zf(J1$$F6x;9 zk>8&&HY?zm(s$!lJ5GNYpPQb<#j%7|8b=N7MkG*aRos}EQz0iQ6~|@_!?r54HC3b> z6?z?FTgzZ|{@(8D?{Bk=Sl-EmvfbbC?w84CZ~{K$VST|I6Jp7oZD3%Ekt{Dduwt)F z-)**3Hcrd=PLts7+gYkI*;<_VW0v8bvb{s9c4$6f6U8!QyGqR&=H9%2{9-$@I^B_* z+J%rP7V{?~Ih60-RNQ8vnqhQfhC$S|CMq@Zpj^q)UBO{S!q1WoccM)6&N!TFo!NCa zu!eOlv!HE0^wVPX9Np)o&UN*sW(p*V1>jy$0)coE0>D2;ib7(#LFmsB6W7w!)WNGF z6XJJ35Ri+Lqb^u(r8GKOx%?Tr`l`LgVsg@MJ`d5YjeS>m16k-k7Sk-_J-OqO{DclG zd|PF8PW{C_Whp9DvE6(VqFebaDzND@_-L{?m3?maLH@Ff4_(TB*8H225L4`r5Q&-l z?#fLvLE`sEiSHjVmv`%GmR-CbO&U6dn|bTfT>C#T5p?(^2?U8IX}b*i=*(5V0+IVm z6FCNxLJB(;5+e}e;7tpA&)a269HFFuW!h0Hgcg|}ZLpoOBKNCXr#G8?V+|4{N38Yv zEbYh&8rBsnxw~x|XV@-hQsV^(1|OqP%No+y+1Z zvTO>lrkG2Xvt%Ec#-6qfI5@$iEQ3pZo@(socNB(c>)-qvPU+7yWu(g_Rt>ORQwQ|k zasT6x=|2+VA86LJ1r8$&*!3IVU`=O;fo8I`{3{6|hD7o_X?w!QKIO%_Yi=kA8AIDI zq7OLyZQCxn7<*kOEgQpyvg3rwGralf{yTk*V|T98H=gC;9sS|rljp;iC*6IA-$QC& zSyTh$$LJoDJuNEml%-_^mOkA%bBa@nr<+bnynHwNxq~49`AwA`?>k5>MEL6p>>T>@ z_Tmhe>}yl#@zi+%IKwv~5f!;r3IQhd>Jc)CJ%T7PUe#T&CY>}cjn7*}aOz)(S{dXiW?7hv_8jd%0QdTfM=Dn?<;{a=>vw^!g~2m@hk#F#EIXm9}^Im^n-1a^lu<#22 zFn#I%*N?>3#^xVd*?*?_KlS(jlj+q@Z08wJKBsi`zXk*(7lGq$dWiS548V%^6pu#f zY6v5N51UhleP$gKlLXtWVj%5FDdJzfzu?*rrNroLWO%!|=g=r4C8XG1@p*g2{MiAX zZ9@m-uOhmCnmwLVo-}bAk(sAE4vI?d6SRD85N|1zo-;uFz0?A%03l4O1L@OMRgv4f zyUOI7(hRol=T;!z;|I+7R(p#)?dGlle?0Zjp@cq&56 zx9EWs*s1)4kPDkn)d;|)7Fj_VVg;w-IN(wXzL!0aw@=XtA?kytfKj?FqP7>EQILe^sNKPiMBXg2yRQG%%M5-yQA zB0@Yj4vpc2x?gj3pf-;?La-wbcoKOOACh96L@z4D957`&VsfBkGaiRGGNOUo9oU4L zBpe|g%tx9_njd6NBqjX1%j$wMeS`1HwW#__@_c2z>Bde-g{qoTA%1|wb31}y<>MJYSXoyj;)Su+h)hMtxh_& z?R0G0w$rg~qhs5h}9uL01AJz|8YpgNPSye~XH0~mly)*g!%F0JpLIJ#U zJUtH?gZP_c>ih8AK>w+$X@G!sLgr0@@Y2bnK`%l0$Q16Wh;`k6z zxCCA)ws)9V_JnTt52;KlbIC=CX@#8dN&4V1r_Kb4z^S|S$uDz6Z)Zr82z`%0qlLwD z#4Io#Fmj;qSxGT>I=m$w6GNGs!fqcJ=@bDXJnEQl#zo#X`G3ao8rTQfFJUXqbckoa zXAEnyUoOEP5|s>N78ojWc?~sBMWAv;TPA! z7YEvXHZ7YF3ZsZb#d>J`eayz^=J0wZo^ZfWFn^@9yicvp@ItAOB%64RxQxQBo6z)` zBWF%?`OoAAinOtco}I(tk?HAtXaI^xkpmg+A;CjNk?HwUimAqCQ#HH`6YNgRNxj8F zC)x3#(9dDYJxx}z_p=2{(F*6Z)sz!&sAt-9jeIYkwQVYPLZB5#9BA-4Y96>oWVl{I6ou8o4TEJ&`En(Z zdyLX7p#mPm7wn(XmZY`~Ou|dWL7@pmFO8Awj&QIRwE=UdR=->2B}v++22yW#6PcIy zjyQyqGq-bbm@GDtrY`f@NlTl-itfLG;349jxjfoDDv06-)8N3r>>#YrA}W{&;k*74T-z3;_Y8fKqF)oQ*$Sv-DOEN!j)~bb>E1 zV>wRldxjBIwM`?=!t^Iy{LaJn^`Y`&d(r#wA&0##yl;c_=SR5a7}iGNVEUgihh z&`=2#!W6JLaUVZefjbn<4+IbqH%maSTaCz3f1Q&t+ZSRn{d7_~MV*3^fko$;TlK)~ z7!9^gvvtviC1W90uv|*w#Y)qXdpQBWaVRt$wQ;%mo&-_*y*7JIB|j`-toqLK`lw&G zd8eUg9&PE9K&Vk};m*ol>dYRFZ$0nllSi6dQ}wX}+Vz#;Nej(48mPpZcS|eM(4=K* zWqPkjkp((Vr?YVDF>g)H;mPU6+Gcooiw!CjWP~N({@7PvMI1;6mS~)VGW^*`f@l?s z19nO|RmH={MxNyWH=l7CU(f&6SZk;ayCC`iSF$?$$iGu|-^oyC6B{N$MpnSAtp_vm z09zp$b7+&zN6N#rO3$1k$*tvZ^Qb@7{)XOLy`K%?7hw=-J2}35WUyZvAd2GzX zuCLYLaN2?K^{oY098s;B0a4WXf_%Rb2M&7evoGU>2}aA~D}nAU%``f4PnGGEt80s6 zGu#7ScUD-+57G$NQ_aQ>NrJ9lta=;k3m3BvB85V@L1lXNHab5|m1#EyN>Uk&#^RWF zU4X#HUxa~==u=H9TBC^rG3w#g8LO}TG3ZuzvYe%q-H+L47WHj3KN9pGTPP}hEa~_e zp;`s{F+A<;X}`#!t!Zy`dPyV}!o0cXcu%_ejo|I0M=1W{ih2SZwauZ(c>hPMvcSv7 zbsFGqRsrUd=Ksm%SU4n3^#EwE&uFWxUgISuOX?_GK(rM~{xCALLp+^R+mar*QAlNo zDEb>g0m6o@!ctp>@)UmKp!h8dqgP0r+p2q(aa3*D(!p{`WmMT4=KegM^6T);trl-G zx%75FL~*=2v1a<-a2Np=i(fVyQD<8%fNPTF500X@E;=0=@b29R&=SV|5@Ytrypi}3=WK>D} z^fjawB8tpTvV|CioH`km4g24S~Z&iWLyRV{8&~~nW^;+3r!OiY` zei}TxkJqA5!4#9z)%LNy1cwIf9=h2Qhg(lt=c&1vA>ij&w+EOaN5oMk!Hnl0E#?D( zl`0M>pj4`sKb+)bj=8aTpk-p|=n$WM1ecMm6orG&F&ni55}8FfSMrOvu_7}XGGS6q z#K576nb`wfV45;O+3j-$N^G0x2n6~8*?ay<`+?CC;U-WPH-^sKJg|9QlDa|kRYB}G z72V+j9aV>$l_TGYiEY8-_2Gd@R9h=1+EcTuoPL2H*KF`EC#o~4qqZuu`l04iWy-5F z0q0t23rc_YWk8Vf=ag$-@izzxGOJ9vT%s8klx}yhhQ3ga=k_l?_ zXn()$tq8VgcR12Bn?NT5IdtXA{%5kQU$P|dAJur$gfrehfg_t3;i&I!$M|s>S%OEN z5eLSxe)7qy$P7BoD z@pI&$@hu>Ql=@c4vSVF?VZs@qOlN#1@}LZJY|eON;B?~gqacS3!9&-I^RHU*Xd19g zDG#627fz}{G0p7iLs=wg07(iTgKBlf`O)TAD_k<0&X`zLEce@(iyetj8u^##^zY_C zg0Z>KBvduZSSI|oL!`=Lz0PC{@oB=QVWjr2C+^yw$6f+qd$zV9%nqq&*#h z)aV-x5nM&ymh5H(X#8Ixb?+b?dY@J65ZRoX=yDOvVk%J(8nYG$BGeMJ1@@z&tB7dn z7CqO}l}@lKyS|dIw>kdgvq+70l4hHUF(4E2OYWKfE7%p+ZY@`d3EG*72q(F1lwO^p zoF}+!MkX01Tyhnb5~|8Y&gUq?{Fv-amU7A8Q+Jt-Dt^XvZRy>zf{sIpF)5pvas1|S zCl3@esoSrFI2MKjK1R>hr>&*I=kOWKQphqreu74*9fjn!Loi2qcv|JMb! z5WI=5gEwjvi#Jq9zvyn%uPl1GOcVFNI29>#0`0(%_k${z*E;wdwN6__b_)~Xa4=ej z?IV@DK+R98G{tM7CLW9w&^@cve(0|3Q~tS{(kmy`#R+rfc{_+5+AIk1oL?F^Gy!$KA^0Mfsu3+YJrSNI=k$y_}KC8m?&?Q;4ImQu6=_y9RCx76!?uA;7 z>P+2~@?AS)u_1-p(luEr@FEmNg7w~F;|*-GgPwU5)3|i3>PHp1<~dzfGrC(51wXFA ztPfsbPOkJ%7zWJqwi;46@Q_y$4_d(Z9no?>=C167O4*tmkI{mv)a9thu?Np z%2{A@_}WkFE;$6-^H>e|lgQAPdK2C_(}#(G)YlG&cE64Qye=%4>cPw>hKr#PP8D4l>*r{GKTM%Acm$C1`0~Dm&+;@;<;Nt^ialUflI0r*~a9&ItP$#9{PC%JR z-0&W;m;KSWW4AF=dCtpW*uC)G!LEw(YP{KKi1*D)-=1WlK`)wIIBn$K9ONOlX{N=Zfj*pm+EjP=KKVU0^t$IbT zNEvNseklSOi6_wRcfWf;6271nwr?99K#7l0F^3hTgi(uQ^bnZ|rDpg?#v!}@2J1`} zbtYsu$Ghgyvo<5BJ?9&qIdH!Yy!qMmL2E*gYm7XgU!b33u`d#Sj zBI1?I{@qfGh4P0})d@tvM@(&-+pqDp$~k`t0a5a}?pi}B1`TYE6skx=ar$2UJQLFe@-T4k@Kp&7ZJ*$R4_5EYxHl6NP39d`j z5sB7RIz@shzaEh^2#q=cx5fI_lCD_qj%v$&SaE`8lazv%^GoPvue_0;az046*u$;P zP#D6_K`OAFY=5FxufL!+v_dG2!Dw`iY=oyJ*UkJYA%6jM*OLK-xb+9sx;+e9EJnA` z({B6N*gx)yLKjtA7XSdPNC1FE@IQWcb89n0C)0no?<&=-0PQ=(_sMDwSi{T)7HmjR zEiEXv&HnNxqV2i8!KJ};BZxI~HN=n1h|G!=RSe;~2&31F*2h~X+t=;B_ovgL!cPv+URfXP!K5GLoh)hPEMD(fU&cD=UFIBX)$h;| zUIr&;uMON)jn3!CC(M3xXL#*^VQ*l8`k4jITDO3k9*)G5$8t{-p*Nr$an3hDd6(~b z4nIT!Ff1nBq+x=HcEVfN1L9lVB!|;!1pY`pl4y-K_&uqcWAi$j@Hh`n1)YqgsSr6; zo-}k0W9Iqqt?W(0F8Y&6jsxNNsYY~m3RtJyurQRKd?*~rm}Ca^V2bepEt1-U zsPHbp;mNu?;p{QMABR*=RtnPaJUDKeMtN|4qX4$HAj}EK$Vl%g_t1*>Ao=Xx z#y?T47|vhHNA}-l2ja)DwJDMe~%gbM6smK z8OoWvb$(x*ls~U)^?#JriID%=olvn(L|VV~IqZTWH{t5u$YRh?$$3ckiqNLe^QP&{=6f5ps)~5tcJbjaa(NH2H#v#T(R9b?` znj8ueWYrazdK{b02GT%>if5?V3OnQf1y}3cVa9$IGTpA>oV*!=nkVeW<7qbQ^W!(ID%!Ln)59mz3d z315OcE3-+u{~WBcVY!7xP&^?2h!{DTAqP!91e!Ks-TlVi;hKqU9wRU!Ga z@%AK@Gl1~BcDF+NW$i6>6WBzsl}xLBOC!<`ne1>uBMsI zSMPQIE5#1tjLpHpq-NA6z)PWWurE5))W};HfpHZ@>|o=7;Eg;r6(z^DAa7gx^~BP0 zK9G%$FiP1D{cjeF3BY32Ns=|48%=Lk0a&bt_4`j2Ybk?#!svvk#{{`~ex-H0##|*> zWfgG3QZrfd1*-WlF$LwoLy@x~OgJcYYe94uFF^E!Yd0?A#|*~2)BJtyyHbJoyq){h zp;5&0nl0djrEt%)vhCUH{j~5*amxo;VBl6;6f0^=jAja0%Q_7tq-PXE;%GjYQZV|f zq4w6mJQwul6OOBfWAIE6pdVG`;zIfCna{M&AaUH{T1UV7^N(j;iN8-+dV0~W zVFONB>b@psLJ(`x7bl@FH+Fsb5>chNDOi0gzMU|)a-bQFBlWH6fv{T*N!OgCC z*Tjw)cp6rl_ptOpRoJ`jikVc2glZY4$fY_nYie@VLWoq27t$Pg(Z)Wp!rEtw0%ltX z^KF}?6|#*=Wwr_jj)~aTQS3xo1$Zax#-p*r+uP>g5!}25w}8~3fw)0nst}q^9YAA6 zgFnBij*h35S;Fx_0%$Ct{H4Mf7V7m&Dl{0|JZWc1{r#hwD1J<7QK1C<^HD1;g|_3NiIS(Ims4{dEb2x; z>`wATPF^$PE4b%DaF7EmO&Ozucja_qsBtiP1G4xxM3mOv(bY#Az8li$V%QAY!L!{% z@N@U4nc5MG=+C>vi>n4R;9FL9Hf!b2vjA1M_*C`nXPJwif2lej0y!yX_r4#4h*Ivu ztFTnAF2ZVt>jGB~CF5f>ASrs1uvsK^Xx|68h4$HuWs-iE9g4sZ2@ps!%@tGJ#K3GQ z6A>fzsp>LZbf%b}s*bFhO6pHv2tt&ncq@<{!~_pEz8Isd7f5qD0wpp)YcCqo6$yk= zl2GnOcyBlkufDvb9okS#5arnr%tr$XQPQ5Po$wB6y8|M&bXW=?Q4F+n5+MFG2=pzp$MU%-Bs3!+{ z(1f*F_2k-kGhx+(ky1rN9fFt$+ot@>IY|E|jW#x3Iomn>A9+G;7F^_~y2oKRa z*w>z?2D9aWK$1)aGoyHv)s{dG#R042sCZxyMwD=FcGJjl%cY^5_6?kYyrY&iY8%F^ z3y!H-?i1i1ITGv22<8EUxm4KnhD$HYimJprX6q>`#`5vx3cK&jAH8Y`61%ERxc!sRBc@(_ zQ_nlX&&UtrEn>==p+~5t0=SjN3Oy<~(mc!fMkk4e_w?`u*zz)~Hn`$i#!<>dtQoGrtMnw76dt0|>hKL# zKvF*4+PN+qRr$nEdh;5H(gN`(dKXO9S-GXZko295lrR93Cl}Bu6C+kp_*4u`7`U12 zM2oq#;Ow)89g&&(Wl1GwT(W)ZBhSClEH*ZfQF5uu0wqGR^+&QXXPJOldT}1eOQ%%w zH2lhR>h{{8K;Ro;5)skY^pqoX_ykP2fCf4jH&i%5K8KuJuDp5T*IH}WVvE#->Qcku zv3jtmT-)(ek#VDB`s(|92?LM}h0;x+OqFWgV>d3ODNzWqK2EXY=04(aPgRn0M_%$TXiYR8bV*OJ{(Y|)5gZF}uQ)}$ z|KSiqkyr`@4X8CMtu~HVqol?#UMK4E%(XM{9Oy~H;x0($C0?{(N5S!9i8<15=Oca; zQ!YMjn4o;1Y5uOlMY~a#VS6+?vxcX@l6~6o;a>Qg6gzt?71ulbe{adcopNI10FJ;l zpa20;|92N}ZOo>pXKi9`_TA71aEac?!05Y)o*n?QwRih#DYp_s17PT%GW85#4RMKN z*!8>r8pl&o0B6Nu`&hw-Wv`qSa`AUW25DU==EYct)qXk#*3=wl2Fgy%}`5zx3+Rh0R&LxwYRLO zxFn3S5|R&Vip@y*=64Cl{@SdP;9@$>EjN8LCQ$vt^n^2R~xr zj7Vb4Vv0|XQ*HQjE0Rm`h!Jm`Uu^J1GNRX%Bs9?m25qz91ER@bk$<%c27UvnC1S*+ z)^9m1RX2daK#ef7fe+h*$R-Wd;8S>U7_7tLBc|;nxvZ#SmfGw^VHt)6FBKEM6B@22 zSz-{0uL(Og9hA?@#ZWX#21~&KDy;k7@tqm;%2TFD#AJ|1 zX*+zsVnI{l**BP!*%=t}``$6xtWLpW^#@iWPRlX70g(_=F2eiZ-e{ns4WPKMhg8!A zhO2pry94p^ngL(geoz5tW-~byNraX|oCLy#1%kOXueuz)gl`hq3EN0(7;F#90Y%l9rH9u}@ENY;1 zch3f~H*1#jCYX$Fl1a0qNR5F~W#bC3f{S=0HeEM8!RYA$F^Xdhc6AM}m=Gp?J63x3D7OPqEEdpiY?!NxQMo4=mfQK{?I%<=E1oOB!U;U_I(Aox|~`JnUocQWDVrdyxqRSV0q$cSR@%sfuR zkDjK*x{=w7A1k7sA?sZ2#fU#V=r)yla)TaGlZN%OA|7y(a8tOy&Nb@!KNyy2Kv|s= zBjxqX2eB5+ouD(AxHh#f5ZQouvOsM@%;ti#;PGcr_i%UWNd94ciQ)FRPdf^q+auFx z3rbufwKX>n8lw^rzK)bw#7S?XN!8_YL`%O)EXyJp*Q6yAe+bnO#e<<}!7Q+xA5GOO zeYFlNSY^LH0}cSJ=nT`NlGTXE$=t|b3OJR|5Gdh@ss)aRr-8JpE_dx}n=@V>ESWa( zi}UsqRHg;vQ6z4=lY~@U4K}n@Vh@7gwnk-AF8yH~eXz^EtkyTxTv!WIjmgF0-kU-QH=wy4P> zT!cx{l>Ect*XoNlw6Sipt8VN+0AU#f2^LvpqmsDmj0^S74NuMoTQwvBvcE;tw+!N1o9eWf;h8zu%0%1GIc-FGE&MeT?cCKIfhr%3r5hn zxV$vYO;nf(GbRE5Fk9?Pr}chXey~>``@@&i>X$y@`N^B4Z|20arL`{!McO8^Zx(l= zP{&wJDtj%#SfOcg&?GLnG7HW{>taDhJnF&;u=GSzyx_70zjW<0qXsz$phill>vK6S)bL&K%ZD=Vly!BapR65R+pNOtGpfE}T+>HZgpJV$er61g zEYXrL!RQLv!qcLLfr|aXORP@z^gMd>0<{gP-da#g1z!9xbhOVu3Mmn~?-u5O$2A=A zq5QvpWC0z+pMubV1SkTJS-*EJLj=j3{Bz^KdCuElro?JYpWlLaF06I9q``WOgiwdE z7~b5XoTVXU+Vv2>DBpnLo?(p;OYiXLSrC}Nj(yg>`fXgM`}8>PfL zrN(9K?GFC<$091>dx`Wqpzs4l{9n+?zf6JMf3pE<|F_$fKhKRnw<~ARhaNJvaI&K4 zvN~GWy*_UE61o(xZYDO0qc6XV-TXPf_i*!O;`MWhE}F{f-MIoP`d3?z=hsKZ7wXRH z=o`;QO*plskU_eeDm|~LB)x))*Zs*JLhZ7fQWLyuU|Ut z0NH@)ZM|ndet~(e@M_ss6)PC)Y;X<>aV z^<>P=)5p`JFW)W5s7W9)$-~IQk^I0><`8tYa%blrpEC(rt+BRis3xvA*~m{yLm!P@ zP0#{3w0s;@d*_Kk@_Lp!qhw(>SuAH@0wJ3pv0bO{hfR8KA9Y5)h|V@ebV7e_!8>T- z0B3HunYB8{PpYCnoON;?cZW^Jd4YbFm&NTW?kw4XBT8=j`SzCLP7(KinE*H19ifJI)c#ujgs20EY z8-@qm5$k@d*!nA3T;S_1!(|FvM=;5aeSq3(-N3U<(tehIil2Fuh&aQ5Jj(xV`Dgea z<==E!7o^5w{MU$Ztv#A~!_fa){;hwOe+Ys&&&F_G>Y?!RKEkaOZ%FHa14MWbfbvh_ zzm$KQ(BmkRVaNKeAm#mFJq>(%M+`J9|KuZt^O*_BtF4WrTn$l(t-Rq1^n#Z3!9;YSl=CqX2i@{R0 z?bM84Q%~)Tx(e6MbvU}S(D|)NjMb^jvPz!)Lm4vcK7)7XMt}2YnG53e>K?e?>^J5J z=GnOpV3lPuv#IT*Zu9iHslND*RMZV0`Bwh}qYG)O8IP>fqNHUW(}|7ETsS=mL#(Xj zeAZ4;pCnkw?r^XoHud}k!?8I%Ul|40rR4@~?l|hU!b?JjOkILC%R$Abv$RGZLGCoPqX1aH!KNdr=IOCkRUwhx;_ku za$*T4K>HXjnSxcZ+%*E}5seq#eD9gRZry}GsZUU=CPuL# zrk4`O(82T{p_vI5`z!%Z{!b+!Y))OhILYPy`VI8!X7j&Gz)r+}mw;hiL4g3jS<&010mr6N;h)=y|+TYHHUAy(j>@S7n)4Xb^7bzP08T?IT!Q8yX;wquQ) zLq!o-Htf8ecm=o0xrUmeQtoIuA|z;z9?*7{G_s%{Ub~9V6A6@jwNNVuam5Zse!=VD z!hG_wbka{H$1B2@zpe85%}2Smh14DC3WDY_blD@e;l>eN6>@&moAz^im8f$cD622v zTPOD29g>{|n_NM}?Ly7Z9>kl6O*?_&bwHvO5EeDM4B*mCW=*%Us+1YzE03C&net$< zQo(C}l^p5_;#Z^AIQ;VJnH*W$7`PUho31W$_m?X+BZB4FC%X>Ym3`{>;TYmL{*i{s<{h+?lt;rh5UQoj3FTv^Az;>zv} z|Gc376<5~kJS&yoDmhndgHf~oYR@l|JZ9qKR&8?z*h-O`qORx+Z+(~c1jLnfe8!a# zTy@B=!m)Rs@w(qp*h6UU`6mJMhJ>^AR6Dd{)CuSFT4euJBV`)?Z9UAB_4-#_8P{DO z!minfaFR9fbAqR922NVup02Di`r*^@)eKnl0T}!WEUV^4Md$!d_3O6aPnf+bB%b?Q)xQdWAA7htz`1|c)wg< z+9_axXxaEmmX2QX=DbCOUap&ndPz;pQF!ps6FE`kFl?1nZ1O9x{MNN^zJ!@Gk1s;+C*mnvEv* zWmbweiLg3#TGGi+tqHa8ow9oLo^Lu<37?)>^*v%EW`!*U&aJJkUOPucaymIBy0tFU zS{cb56M=Wo$F??m0r7_(iVcxxT2QpiLjfLzGGXjwM8KnP|M@5o1WVf;23yj7UAtra zZcQI0ULFgl*7}^;2Nb3c(I$OQ1 z??p5owgB8Wl*FmkM=!^t+D&H+Ft?{!3(@n7WK(j>$xhx4HdS@{a<$jl5)?I%{8(f~Bnv;zfU1r+habBtRA!`X{ci z-x^sQ4G{3p#7Uxm)FJ;CaBBlAK$q`7WnAlX=LT>(1?O{UPx7y!J>6HeTB2=0>ZG~R z!M{=`hmuL8ntL(w=%daZ-X;f%`_jd15XiH)c!PSAfH%Ed0mq3E#p6uyFL6y*W&l&{ z&Xf*sFppz8X_mxbttt{!jfXq9FN*3~=VmMRtQ0~+TXj50~f�EiyBPubJc0Ul0On1R0ghaC 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

fYreZ4 z36jPfREjXd4}U^?*|So|o@CBpOfj_SB}8J)C4I3~Fc>kZ6MtZ*L0nM5>7K1W^OO2> z@QmpQzuEJOKKp=b1Zg;8mI*%$bbXZGPUeF{(E0j(t!H_xE;iL`F1bAtakG}|lWa(u zdwlB~RjfH!S&f7)x|K9C{iImx@C-TAUQvb}k-iwmRWk4rwKK`V3umExfqzCY)#94l zO=3W;xQt=>QG+L_o_Dw6F^cHSw1gGXL;0m~9e3j;3+j5J&kv%>>b7u#8$*n$)k` zQ-6EAd_Rw^NvR-;2AdrC84b1@%DT7pJ)mq@7@>Pb#P2bSApoC! zv3YP#W;nistc$O*o9>ZUf{puJ)3(vG)iCbnv7d-82!(^V2`P|ZCNMY9QJZ(7xC`y0 zwcv1O-#?+2NZX)k39(0#vwDqZ<$!0>;bsenrcQFj=VW_QnnUaa!!{$dxOPX#o;!~K zNr=&g`WKYo3ow!X+45=QCzc$~V?CPIateSUF~ZKc4r7BKR!9ZKFOW!lmd5))XG`m_ zVWdF&=sJmm1aExAaVC5K`TR8yPY}c})3v5bG4?5YjpC%)lb}w873TxaGxNKR1#e<} zE$R@G`$iu@GK(B=rLygs_2Vhvva^jKA49sn(M!{F$TwObycrSO-#5M%aOsyEJi6aX z8YyjWy6NiKDcMMXo^Jw!YtX^MQ6>sGzlX5UuPjEY?l56Q7XKRl{9346xv|7EH<{hS zIn2fa~g2=IY&rP>QS*2 zd+$z?hwD+WEh{F;>XW*js5n1|FGfw zmD`BjM2Z4Ms3FFlpvtwU~mIlhgg- zViMAGO4Lp5oW4&Paapjp3TdM}HV3T_CFOYDy3KL_+4)wSItqDX{s#^m)Jiv0!IXJe z9?$C9d-eJLmicwhs6mSv*a`Iyh9o5j$*qL;Xj5s;qIAn7I$Nvi1>H&~S&hQaSfVxV zh26hHrq|bAKFj@$CLkKblZJ%;M-gls(!wlBQe>|o7A>v#zON}`yGvTKO{CcUtPZ44 z?vL{;3;-62-FS*-1nQ!8gfS|^A97m3 zVlqPHKVD~T-LJ*Vg8>_9mUI&bBccuu{t_#2uQ4qrdzrH%Kag?U#T^|_fvD0^$rKZs zk5Y0|Wup_tK(Q^18FcI7T#Exj;KkTdnYzhRnF z=Jg(T56A8P{esbBDn%~?>~){o|8EzJ#s9IAD^=J3HFtfjMjMz`g zS+eK{l8dsoF+|s5PRL?q{NPS7;rIpJXyRT+Ycai=30SkqE_@E%pQe~5V)KBYAjs+D z5{S^Zw8BK-IXU~`Gc8u7eDBFK) z;lA7Iir4xDF9W-35)wZn|fdkAz}5YsN|ci|9>I(76O3I6)3XC^JJTz-2h%^u@nqU56 zUXWN!;7-7V?Xdm*P}FgMLv1+Zpetdb>Cb6K9*s5S9w^AR3PInx%L?l(#1iF7jnOX~ zQfTe#?Fa+{pWBnJU}Cs~Mo}tH`V)=@nO3g&)QwmH}W}QRZK3* zC-^c0QcGVJ*xiw0Ek$AL)GOxp9HG3Ub`B-j`zjeM^XezI=i zycgy<5)xD0Sy&?M+}b)Y*$cTQs!+p_O*1jE?kfr6+-5M2*c%FVUKvgB!em+4WOZms zxUjWuzPq`(di~CClB8 z02s)z{n7;Yfn%h#FfY+MYKFze)`MYYbFr;kh7;PqEQYPSU#-jONd@g(+*&tApyd#^ zOLxxf94*n*bq*!f0C*O=R##Q0(pnVyHYVbgHT+J=;D_~KkqSKLAu*D(n3$~P=Fa)V zh+&g6tC>2qaDqY=iQ=6A+cOqx$2gfD8vL3KcCfF@q^JC|{3UpG#7VFOJ-S-rkg+=c z`_lB>8Sy@O@mW2}Z*5;hsc7n%Gy_9~Ahe%^@>V*>+Hs1#mZ56_?R?9A;|qwXC2r2_ zs$to(I*;FHbTcl9c$tow7yJj43GBDTE~}Gm`i=-($xn7L2{wU zTopn$b$uuVz*LSJmPsti)vFnb;U>JU+mY-y6PD-JI>0GMnj17zwZZQZuoZgRuwK!T z2vgdOqb3l4pS=srV{ERiP~=O;C(KV8xj=uF>a1(x#w#&g3-2wsTk2ho12QnAX4zX9 z0hZh;5pC{|DaRxHC^a()Y~|E?e^XM_T+L$&x=m9L7nB9lkCo~0vX(BNY!!xp*~D&F z=I|8&4UFNaQv(U{st3z6*L;SF;<0a^;-8(L!=Jvf zmzP7WxcsY+>~spl7>^JXAp(ygVPTG&X+0BipGxBI_J|gs15pc-U7kt{*yV~JJ>8gD zgI0|>)zlGxn3yRFGb!7=Ksms5)ASBjbS&2eka}(_0Q@{Nx2`8VA6n6gi>c;fqO_ql zze}(tRxnj~Mcu$pYOHTRO`bWMh-EL{fz_Oxny>Da)W^B$?-{=DrSM~56ZNZXv7)Eq{#nR&D@9^t#DOV9lJ8Qb{_FX8c%1nvmY3%qriHWl!(%e? zsvL7>9jf@Ml$ls_IxN^cDI;KylGkBDbHdTtCTm6U+)z~-UohNcvE%CPx|d_x{)chq z_TSSS-^mG07cl1AIF#xXl?*XRwoCEXHu;5W$=CWQF2U^vPUoMUzROpXGS)?mp+s3v2IXc{x)kxuSh_q#Fo zXnvuqJAkj1kRT-iDiNrX)2dXWCOCP&2IFEJMUrx4gmA>^lf#Ql(AAbz>u%26*GcdR zQcT_4Y%h;@)9&#Z$kzzDYW|j-*xgOq9fo6t?bXyH5+;o1N)Ex+c!PDKP^BA-MXsy9 zHBs|*7S~Y+8h@@x^>#EZ?xrNi%$c=S7l1DQTZ9pwYnQ89IKEf7ms_ zmy2*%yL`DGeZexVm|9B^Q8StYLs=%P4K6zcjf!aotwGAnxJC3{cevkQj5qZ@kFqA* z=8_6{9x`SSOKh@^P|j48x1uXKo8LDF-9mX@xxaGO74j@?B)35K2LsM$%zMnMwvV$E z02w;F{4sT2cj%T&AKjtxB<+p}zI;F@gas{3Mobsyb4yMlCOqXX*e<+fG@k8d7r$3w z5bIppN^Vbyl+TP4F%e}cF$*q-tq>LO9ojRT;xc7NkTP+Zzm!p$y_lfTv^F54kxd?W zVJO9J8g)mxKnLT=y{-Yl8qZpulCz%3W<9X(-9xOZJ(x3g;#~*6ba0>yyRLZS056-Y@tJXZ<#f zh`K|z>rXgN=B{sZ$}y2=KNqwcVghwRLcl7;dWmr4&!z3rVB#_|Z8n5P7gw=F2T_p1 zN}c%1%$o9UhnwHmH$x}sQ)Q>aw*E$Q9^GaZlA-@7ul6*gbIDmTSm?t?_RT$?Wj*y{G@K_({VUmEAG^ zaHsF-=`{bLsGjy0sf#BOFEC(=MT_g9Wu(%Z@7A00x;xy*-Io)lj!wxYU~cNhJLz=8 zam4fIFOQrO*BPTXv8Van7vHt!lJp~DM7fewx?Z2O;~euPX}l)ztZAq07nCbo+vfKa zbH2{RbEbyN)Qw8nj}b@fbqK|yiuphP>-kOxCkmhlXO zzofr;m%G?($Iix&QcN#Qbg~}?Mmd+;ny;HqtH~fXh`Y>O&|NPab-f)()={pi0*`S5 zvn|}?K;THSIz5$TUG8Dn%nj$GoN)x;-xCehRZFq$mUzOad}{9*4V%sd>+2$ae^BJ+bzbwtSY^s-9!ju zP6EPuY^+gwCdTVKRmVVisOi?j;Dz#h<45vMNpM61qTP1(kcik&cX4=BP;A&l$PI#y zW=m`&LZG7wcS`)6uE2?yr&{ARy`~GB|G-agV}1d0o&Bk=x2yS;5@c}`VRGD}(U73n z5r_g-Yz*_tJK^~OzUNYnHrp3KJ+#gNP}oU(|dAF8|$pyiMy5kH1FAw3>! zJ?!vL4aw`y124lnOL@!x)P0#Rw@&@)B+NiI%wUyeC*>i+-5e3_#vni5?L<0Dk~x#G zER?c6U_v>TH!Vt4W@d{x3yEwQ==F zNbz8HM8i;TaDz!TluzqE*1j=}9?m|gch)U{J88hPTb-UGDCMr-O#+MTHyF#~5liM3 z@8IA7UP#KB3x&Jz;Y>VL@d7_{sOiCLd1gX3YFOaHbx`pr^pK zCV}z6XY6fJl=kwMWwFjwt8YQ$cREX=BFtj)Yz!T?aU8h?if={H`z;Ej^5a&YLST_s zOGc$7B3fZ~R@<+_?4Z~g-7qiKn;eu2q!We#|By|aX*V^aYvVQXj0uUCun8GA2^)jG z7)&5#^7O}qZ)FoT=9V4@geaF}X6qvAtmMcyHsdHa99hy2*NlsPE+oeO6)t*P#kZwSzRSwE-yA>x3;pEOzw)VyHi8I z5NNDs(V3fsO;e)lXQWdqRB@N2bTFO5c^fBZicz&R+h}&6-Q$&>x@>>@El#AY8P*3f zn0VErRKwSuZUoyJ3gEP=-hWcxTYxi6F;v$dV|s)5%$}0HRIDy~_(Cg9)bdTQayqx( zVs=hhOpuR&+s|1C2F0#}(I2olceL(vN%pe$1$?d#f82F9Ai3N23SG1lr(#ai4;tS+ zyf)yOO6MNUq>khP9Vt20B7F?%X+bqy*l1UjP;otb8xm$ZctZwSn8% z7%ekNg@f==XikdiB>U{l?r#KzT#1UdeHbdIY%ga2xElWz3W@UbdF%)AAX6nVtR6On z9!w)vIb`EG!$pxVkV%vt{=+2OH=KU;0BUu5d(v%tsvy*ob4qdVJl`nXXSWJ6 z!IdsrCQ6d1b5YRAZIIc2jibglO%K4!Y ztl6IsoIH0qba4X+MBHG+Y*pIr2OZ~8Jv=?!uX`I2OkXg9KI6Mbv74H|>vK>YF57>YAc7jBLybb}I&=vaer|7>2d#{@#Avya5b`I`b*RA^~;lsj|0wFn@@0c(=1@=f_33Y#=r5s z`u@`0`|WAa?&4ET>-@esr7Y29PH_>Y5gGIf<+m#qr;8jn-u+)XRbrUA0sAZ){YU#T z@HAGB=qGh=cegj^pBi{)yY7>nzo#4^C1zk@-n0A{#pKms76Rd)K2BXXhl(80xVUM> z%ztLyFlS5r3{|k!&pk5WkDSsNXbkaCV@f(=N^D$IU$D9G3LRgpZmXJ;=;ebLkw^v> z!(y74>;NshE^Rp#uu*%rK4nA7@_g!4iBs4#t6s*Y&cjEw+)8+i_tKsKW!=!Ztvj2oTr(2b%~Tb_DDT(7@ZK?x&quX`Tv~nt`E_;uftL3Gf;c} zD&RP1mYgH`qM+uBEp_XM{7fVUa=qZuVQMU764}a>zcwLwO>0trjQSY2XtU%m-JJel z`9l|=G4>+vdH1yVAN<+qQ-Q&9fIS`yNYDN!o$#L`^8dU4{cj~U)^#MP=4KS@jR6&T zFdkW3$2E7S3w`cOn7wW%LvE`v7^5(X;iop=6^ zp*Z&n|Ig{|3l<+gK{uep_Njw~TU}`{L_1|wEu}BYJ&)GtFCqb~1W9MhW>;)2%P{7o7|;0Rmwdbu&!d1@SS(v)(>!vQ2{mkjxg#WgvV>9HAT zjN^hg<2ZTT0$v$uTI)_i2!`bnA!#>B51j696&#DkBeh5vjjY6wmaTwhP8JJ=7wCbFo@j-8Hd|O7;iIwAVmP}G1p+y%+`>AAxu(gi{Uk(RZRzl)QwSbKVQ4$24yW(p~2m0G_q*6<&5u7-E z7pe*h1=(Gcou$BWGgFE0csD74Z8a|2w`!L5y(A?Xz}S4{9`Y`uHI==&#CdM-jF`?A z1mG!f8~1Q^w-1)mvbg_G6PXmyL>_lhO)cGU-Igy+?Ifqz;`n7RHF4PwD6ln*$f_0r z=v4ntf$dIS#LtYM6``n(PR6;bhz!#Si4*xW!WodE9bu!qlu$1_hN?!w2n&;%1okmi z)S57;4=Q~lCzTYBVW75+W8rd^1tS!uvKeH_Hx+Ik|LEHDz<)*?2!LIh2?f3ea^XO0 z==;&r`M&sSAS{yFrlx@H6Oq2JIDuw0TG%79_pd5)Eu8j_?D-AbXYlLO%m$!}?B@4u zFYr{xR?wc6XHfY0W$TxlS8`5BOJ;#P_$#W13b)g;QrCTbcaXdOUsYrW?!Yb$8FfP> zMMN|oFd+g6WzK;m6^DJOL-$+ShdHF6M{+3J)%Ll#>8`4w1%BJk-;Y!`@m~>I7PjWAfwS@m z%ZmN=p`5wolf!HzI!MV9ufm|99;{Tn;Y%UJUJ+^NKu7)?1qdyQVjH6KuWNHjO$pzavb?>kA z%WNGN*@NJOgw&ZpBs4(}{6)W7bZdRnbf<=5?Eqf4qry01ey?42|{R5~-3 zh{hX6m+z?tXVb-QZ}pmDA`g5=@f7lnR3o*eT#mUC2c9{5|0G2|z0xU&d+ta1hi`W) zi&N})#@k$&;thTSU6EbY~rYO%b?NA^*`cKPU&kncJjLbI|( zQ&THp6Q1)tHfT__nh`QTw-^P(m+r8IXz6ZJL_=W{V}`(mXctD97Re_t*z=lqFibHS z))!8gl~Yrgjd2&T@!>2_k8_d9q;T>j4~3L1Od6#j|FYqbMWQM?In>L|Wb;tI?Jke( zp9Dz$F~6uh)HI8UzZu-%)nf~qa%bwa}ZkEXQ=sJ#!8Pvq_NQmwX9%2_uq9-nOz!GHZ%}W z9t98(08a>H?rdYt;NM@vb3Cl*1RbigJ;NCT!hx zJUTIY$R6Mg?T;hDn$&~{aBmLs!&o%zJj9n57Pv?;cPBia^MUGYy2rC$7g*?8P>t7F zL*;LCt|hL|GUuAmfS$|i{dvA1ukz|uLKGyg=|8CwPPT)*Hw}4cRpZ7An}Nof=?)QU z7D*}J4rWgaKa0l$BJ5AohkbDDG22#gCb2kv0+^ro!jcN14@_0I~5#zTpN=NtM5#gTf5 z_5akF$ciZ($2OTri61CqUE4tvd;nvt6a1?_hRTd(idj;Q%FfIyLjJ-HMJBr^dX}_F zmzOCJB$WLGq$(DHwMfmGtcjP6t$dz1ylHUk9P##tJ3B%Js4xBf^4EH)+3qq8;T#+4M zf#{zDSvM{;)QZ_$TH*)W;vzMO49F#q52tl#;7Rj!v&nP~B~5LYlTR2TWVTuXLzPJIB)0dLl2}W=hXRCQ6->dV;ARe@P@O7)WDi*RA`G@ z5@jdRb?{;pV1X=wMu7sho38uEtg@dG94QNGtnJIDp5Sb3+&{i4>aMvyE5_Prkxio9fn9K6}vhY zFSinih`89fkN~Gmol@#%2g_A&97l-zVFw&?aL_x__>!U9T-t-vh50Hah6+{l-}N9( zCrnVNHmp=u8GJEnXDAwEUwt{(~iL zrPKJHwW01MB`qj{Cw-gDYH%|9;A_+ZQ+l1lq<4*gYEShFlWc{*cT0DaX1FIzR?Vb} zfV~J=A;+R?pxDV8Z1TPS0xR;9^~K;KZ}%DJ&7HhL2syoXzZq|DTmy{KuHoSej#rWcpl zk!{vpr%io`NUjuM&J%db96K*sPd3)mBV*G#z~hP97A;=ZKVlQqouloA{}K3+A?z@k zx_GQV#*ANr0v4~`Jyn=bYc7P9jK;a3GD)=BxM2Vua0p+ ze zYv(;xCxh9!B#4sPMkmIi=jaj$C5N7|B6XBlob0l?H5$+ACAXE3N^TPo9L=OKetJ^= z1Ew??Fq=}_D*|Q_(}aLZ zuM5IDPZ|mIkqXQzsigOCFi6MpZM)eT8@`~%WO~w<`S}@rtOXYMMQQk@cMSuE%mn_$-=xcEbxKo-?&^nbo%2%kIFsHMJ$l7onZOZ(7r#OOUCu3qyWM;MWE?rb z%0l^H#@g7v zO&;l-UT{w_%u+2Qj*p9N`(rs77OZ2_zD7sGk6jxDN?#B1pz9lvy-QatL+rwZg!2pM zWudXid|CT(_$;S+B$C0v)%t7({uiaPHCmQ}?369{vfp)!1 z`<6$#5h-bZ{_=XTLB8HqmFnbtkwm>?KG+gyryzRQQi*ar7@t2h0W-40VuMarU`+WQ zCXTlJ&M;vz^(%f~g#O$Kh=mU7Lx>>$Z>(>epYd#j2*CzKCqv$pT0~;-@syMJ$AwS| z0WkT|wc3?Hr%_bKfNxqDf01ib=9$+C8l2x#Mrb-}Dp3qadfOC{7Aa`y9H z43XutMn$8RtXUa-NgTj2KEkgs&l@@WsQYHA6E{d~V*Ek7CY%jwFbS}_BV^o*!ztE% z<~qoM^;pE=(=w=~L2`YZ3;wF*NXPk%pevx(^B=euY+3#xW7KgGJSeuNTL(KzICw9v zdfqhugV)`(k!19}$GEL2V9U4Y8;oKAf%1MBm5W0_Fx~}SLK&qDe#~Gur>1xddfj9J z>Bp~h^!SnCMcG^ANqJzahXQ=Jn-(%}^kCqw43z4fGZQ)2)q{oAf>mR)Mbf@>jcIjM zde^yf`#%j%;68kz+L`Xw2hQ|*UF9a=O`Jp>W0ik5>TT>~Eu@|AwmgrflA+%W-Mbo@ zEb56UD#K(<`tNr%za4y8v0JjaA{6Wg$VbDN>ADQ#E6=gY)iSAa(b!sa=1@K^a$YH& z6%V0ZB^Qb%x@;~Wn#M|@-@biCG>aya-7@h>eh%q6^>Od^Ks;iA>i%gy^W=*{fT+g*v z4Jsc5yWXROBCmO^C%y&+n?q|)d&UeSx;gu_rWGX}&9w-E2=~V$tb)0!Ab_cuoYbC( z?>6QkB_`T2FB7{QZr#bSE+4A(4^l9N6eHDYpefu8H_#)Wtq-klI~psQbGe9pnr!OJ ze}zy_hi|C6qO@NH*K3N1SdC(cUDy;rw~zZPu|3A|1X;SOkh()Xj>5AV_ zMrL4(XeMJXv!$gyo)?i%)6*C2qk%a=Sw`*9;OJ;vNVK?6Epb?7wPqlLTnD8h-7qLI zSx4LVVebUIcY`1IL%hdv|%g&gXu|{y}X02?1bH{Z0 z>}h|wMtP~njf3BNYwy5{mkk#xJ{+023v@DazF^PGs2xkVh}E_q2<u$-pB!0Fz+$Pt>!Y@!i2QE~L$4EBZbA z2=?|+v@H#}yzAMW8j!C^egQ-n=9bN0_3mSZ9W`IXBwFOFS zYmZJx9j(~gX2%1zD3GsM+t;i|7bl9uv?*Gg7EJuA^JzWGG#1(0^3(85m)p}^`zLBX-jZvQU;$Ca`94sy08PGf`!LyxB_h+Vn z6YMI*``o@8XUPOBh-fqavto7Cw--D1S*zMYdc9S_?O3(xHwb!oaB)_ysSMk!@fStV zdaI6^e4d>p5saxOsmO0fx4qnJjO@H`bgMYT$vnlE1tPcFU*EbTKhVB6t6x{09X-2RQ!Y&Bedn+yM#y=y8}nMkLYa&j|Sz(G1r#Nu=(gq&OK0 z$_FBwy=N`tO{mUs*yF4cy~UKJiBn`p=a~DH6iJ=PYWa6A6<>TzHDt{DiPNqLlRsmA zXWr8D?sv#+a2asGz>ZMyBXDpRRqnO}S2tP13Xh8%w<&nkE;`cd8KqhRNPR%&w8ZkY zDTjH@cZLi(Qs;XNOzu6q8viW$*%B2zVhEu3}aLnh{4UNE9w) zJdY~Xs6*>+x(elfmaGDioIOH^g%BFEj~~V% zL+*hx${Z@xAmOi!ik|6(V@T1=YcI5|V@R!+%GCcT6}!=_msO}Fnb6twXY?_X=c)*? z-vc!tSR^`*!DaBkO+%YYsfleVVSdUc;SoMPdh(opW_}d8_K^ga}r)eA4Y$4)#+S^?IlODFw_0Bq-Avb_hQGR3k?8S)-+G9j^w%|*e z3{Vgzm1-D%{Ru(s4{H;IZWxotQrv@-9yG7-Tihlu0eBr#`{)t2pMsaFJOG5e>fHz> z5a9t3D$IPiVx1$=(n1zkxJZxyq2eoH50QowYMpY5`jdxx`YmOIR-Z;|Oy?C5Mh@&>OZeO>=6D*Ee}qbBp{}3)!#<6O3X>pq^ixOY)fZvixURZk zkqsJmJY31_N&ceeu5;+ST(m2x4`v!|3ww17!6`p*&;aMy$4w9d!~q(uGG#ugA}&K{ za7R~xCz7gk8PQq}vlDSIK&UuC2=BD|A3wID`e;N{3t)+;6_cvDn+zvjre(dgnX|8I zd`c06E#+21V{*?&bj+=;2FD)v{6LS5%9@&*LZ_ptoP=IgF+Kb>-W<*Lhi-P%Yd@X4 z!{^1=ov+Df&RAFwD^}JdQVbZNQ+{SdY03T=q~tP8G!`i{P_9#7a)CQrG##T5owP}9 z6yfhM;6o@Wy8}BXwH%#i!0iyMVrDhiew#JdIg*hJ`$!0PAmSTH7Q&{PU|OWmw!aWZ za@{o6&O-k6ThK<_X86rZ!l&^kFZq3)$i)Sv+gC?*o-M4k-b|BCY``|qH$2=VMALOa zTp;XFnY#a2&?_5gHj#`*wL&1}W_%~i1qp%HbT+px*Vc%a@Qo0bS~#ba*Ug#K9XUsb zoO|YN+iF!q$B_DImG?8&AjUSgcE;zcYBOZ(#m)v7`&(d0OO7lVRjrK=5(vZ$^)d`s zl@dtFz{I8P!w8EUfwtjNr+Mxx{1k;#uX#xeZh%$}lw?)6r>sodl7o(QqXCUsi z37d1xPG$d^vG7#9;R?mfEDqI_LP2WE7<$H>BXrT$q;o!+nl7fRG?xZxmQ4cE7{j=v z$L3REXIT{OPhntBiCs6%8*}d5$-luZCaTEqepj z+cK7x-;&)%g)sB#S#hVkkLPL>;s=`7`mws)t!vy;6vLsz;s^HEJ8xeH8Ovq6?RKsB zd&=TFo{)(kM``SZZMY%$5+1RL5|d#bXh`4fL9J(Xff-FC4`^bq@Gv}Dn@+@yyAfjR zPg)Ebn7%!4%uQ?7t_6JwtzN6s9k(8nI8C<*s&)Yv?$?BynRvR~Sx?pRrz(z%AMKt& z7T4};+-uiAzIaD8<=enIKkVe!Y-<_GnSR|7^jcQ5>J64#2%cXQl|qmEAj5;^7H`X3 zD2WH5{hD32A#au4ZxRYM^Gt|*$VOI;vGsRL@2LJg6&50s_5cY|U+s|xjzsSqG8eBC zAUZTRu_acF5}!fj=%-)-Tantq*erciqbN~Tt4ur#RYdORc|VxVF>Skj`<@!;P}TE+ zdSzX4>!8@7Z)sH8vF#jGp>L0agF1Hy>aevDVMrM&=_gzLYKCG3e=KRfdyUwk zf7=|4KYR~=yq8=pBg+?eM}JNQmFllfnd-BoM-5?v*pzU~1V5ltVKo!NnCj7ADN(`r zSs{5`b(~O*-x|vwUU`@m8D|91(~V+Q%CK_|HQQFZc{%aI(p$81BHBz<7N~SN-d1J` zh3zN59u>@c+Q?@}*gT-MeemQKRQNW^>QN{GDo!0u*Xq zR2;CZ51ufvDC{M4`gW8(TJ4+gJ)-_gwm|&5C$TiNfgA$3+0O$Gg8#ppJ|L1bAq~?{ zh!(utR)NF~FS?&OmmEZ>hP&?Xq2G93ljy4IC}wtZ-$}Gzcz`o@W#vr2P-q?L2#?I$??m#6aI+h&0X z@x{1|EC1RyD`NuVA>#O&!@}cU`Pa7D%NW2@VMe%}TX+K0`2Rn~&M`Rib=&r_la8H^ zjgD>Gwr$(Copfv)ourd=Y}+aCjdnPZMQe#g5rW3S{_ zdOZ9glpLP-hntP$k4Un!cNZ}LP_eUP@Fowh#|PZS1LUzVQhtVkB4TdI7hU~eSfh&m zzZ2JDx|JL6_Stz{nq2W5-?GvXOuu7Cl4FSG?pTb3e6=HJ^s=`{1hCBzE%`_>197cE zzFV>4@4YHwB9d`vsQN3Qs~TBv&x7q7s3I2kMsHAS@p3h;(Fh}Im2{uL3Wfo1X93PQ z^(|o$g?YlXYTVC*1)>hAAB<#e0LqPh#Th$%G?Ll-qX2k`!mf4D6`Kzl2;1>^XfLS%9yh!Rb-#Qkv znZKcdn~n^+02$hXre1LpI3v))IKa9D%lOk&+cM9*Lpb4HB$)({leat^Bv6Nl^GhBa z`x4qndV0(a(5s6GMU2(iuLS7XWj+`WaBBxpR_bxWj%K|a1iW~jqFj;UeX(J<9cwas z(67*BxQ!}hcvt@U_diIpK%yfm`7)wWb?TuY zvHWBR@~TC7*d`v6L*aZxwa0x*Y+_*8yAF-V>lLK#*j*64Dd;8pcT1p7OQ%!s8STKb zHDPwPQx2=X16^HMJx(vK<1_GmuU}45rEd49E`^rn^ARg5XbTImwm4RjX$7T^ganVS zp~qPR&x_3xS@5I=MD;1~as^iXL$5QY>z1eHqP?JNB*d!^kC~(u*M{?9I0~r~}E~ya`lszQP5Gm%{@fkvd;BX9) z+H90*sKV1_@=Nk-KJQF&J}$nV0*B-5AUjgi3&tnQZw9HJ(+wPN$CuOLV=Me%!aQs|!RbYNCvAP%PQYR10S%y{8pK zJ*_&PT~rY+no@5XiRK4ALZ_zoEJr?|rt+k71?@6@1G~_u5r@_R;LM8nm)6ba&zvEL zBR1An%oFy2@MR3AKu_Xts{OtkCC+T>LlXOOr$lmk!LO>{Htuq2{0R7iGdnRi;gewx zRa`4kPJ(vPKyG$ECTUrhQsI#SWb(++t`GwxnjJVgwl^mHVqCt*0tU3S^YhbPNeMnIIi~6Vnc-7;2`b?2_*%6xFM$cxB1k9rz*9 zUj0}L3;i!&<+Q&|7FnIK7CfAHEL-WDN-nAxO)4-=)?!X*oc2W?MDlc6l)Wkh7*WG8 z$$w4M@{s+l1qqt>+FIh(*=i8?_5A3S?ds=c@}~cqKneO;#DFJ6d++cU7}iT0xt7Xy zy}im9_<+s{x6|_D++QJQA+C2}2 zHnI+<1o+w9U+k(GkC5i~7(P|c`z~Ey6fN(gfeT@NVfjWU82C<48pn+&?+lhd&Pb^Z zQnNscW28jaD3_|v;sN&qB*d^|Uy<+%YYjieagNbErf7SNmy`16rw}RP&T8;@Kb{~A z|AP@pMRGP1OgI=31va`$A~fh|lAp`fME{qeZ{J@Bx5QdR2UZ`2n!QN{#2l~*@T$XG zCl-yvO(xoRbJ zh~L%48I@3C%g(N)pJ>MzA)8nHLL|v+Y^QB+I~WnE#NejDXUtt)A1A8c41m(I!vdJi za1q2<9>0;GR5vhB@=)s4QEi}ZZX&xy%3420ZL?2id$Z`ZHw>Im#Xev7dZ`?*&ovW{ zE=XE*s6C}fsfkDKJRAUKLFo9LiYYvQ~vaHfRr-Mg#bbbc#h<%AX<}$ zvI#{~XGoL%3{j_#Bf#9~V%Ai5KmG0ZMeVvP75#KaOEa~h_9>Dq_?1k$<*CZ}=l+pn z_X5lJY)RXRVtpi-^)~prK25x$K_C|((?RJ{~?HwXZB-6@} zR|*y_m5u$^YUf)_Z$!{u6Lt9Kq#2hQ0KO2I#@W*I>PoH_r^lD==lwgJge+x$q7(94 zE)NMaRR3exm;P&aUujB^v5rBq}3DIQ*`HV6wseLVE4mrT2RSy%Q65 zK4>}GYM&@=ABd8mm7~zPm6Ql0_sr3%^h<(9K3oKzmLTv!2Z>&KLj%w!&B%phUgeB{ zaj@Sq2+6{}Y{d|=F=AiEpy$BTPdcCXw!gx=Aw47h=)~t%wwR1oAEpB!R!jQP$&Dzb zPmmd>$0;@fxKvAV{vcM*uJCgQ)S=anB(o6uH0_h5IjV%g0@l`vh=f2Huuzeb=r`Py zqv?@N9pBFQ__x$ z3MK&MAwt-wWIzGqW)aO2v2A2cSr5EXl7_^V-2GlczAO1`&uf%8w)=ofuxkJzI(spM z_0rmmu8xLyDkZX__{G-NG#o>pjrH)joYt4EL%8o5S6L=a$mHb%A8qH!N+er_4A<{y z=WWt@0;A6O)m%3g8r7ny7j^)-GP6ec1ux7)dT@II+a^?gmB&|!MYRIKV=>cD_t%mj#c zVsReyn}TNdmJWF}-1CbVt5-LOJ?POi8{m`^5at}bJIMDS3G-T>dc^VzlFn%mLryP) zVqLD4kw!KOyr^zwadjv5nl|$uWm%}4{Of*Dz)oi{!UfGdk;!IybYTERPofK@MT!DM zC!3MFBq9y~R!x?cfUvr4*?cs260u9L6tWwTMz=pJf$WUnaA`LmJg3PLZsR^Bwd%Xq z)i$khes~yur2f?$o+e)E_WO{wP^xU9yn$NoHVbdVbupPvMC>X_?D8UJ>b9hGr3nH+P z_6SAG#tQw*w%7?0H~{;q>ZvwNqkhN8F9MaVzy=^ZR02ZALTMBFlA_%XsdfSbtXkAl z>{CO%&q<}N>hHSs3)-M}w&*pVYZgCaL4CLm@|I?{dhGFLt7Swh$F-uOD_JO!L-eE! zkqPSKA($1~&*s-YyibHqs~h{g!lb&8lvAmi;xz+W-WQWOt&|!*InRi?MQppen8J(O z5wFU(r+Z&PaQ46Jgg@Z2@~CTg%??8AdLdb*3aY(ELJ9Dt&Y~7ASs)-Xaj&geB%plJ z%K*FLvG{&n?IlJ{>TXvj7SX9oF;U$GVMEa_aYLig5tK4F;B;ahB83;zJAQ^Cfoj=U*gzv6pd-Yg^tA5`duQ&*Ut{g+~ zkZloBr!Z3P(2B%sK3&CM{wZlVuxv99;&`a5pT>5yhMnU2zFBeB?gEi9_!}1vW%j_h z>xS@pERVyL|K|w96C;7LsZbHlNjC~jQDiqky|<~=%*gvA$e!N=y zZ>btq)C7|SDfKW)rvg1|M*Jo59-~&O&JAY`{G&W2GLg{4R+a<9Tl4dsoX((|7;A-n zqbn1sMUIWARqQeuJWejJQ|tM0pd-btj){%M$5q=^T0YQMzS%P0#yC-3j(#qXkZNHw zKtgwL-%zEWC@&n{LYwKXSA< z?LzzLZRFWaI;JA3f$7c2EFk!~?Y-m_?E@ptfNE!00md0aKPo=hmr5^@| z(#@Pfs?q8#@wClfaT`bdl%$D^ z`z9`{Sa%S4s0b8j4qjX^zt2dD2TrPt=7~kx&M_L1YC0$ZAv!2Jm>NNudN=}6QZi@? zL1tP`c?eO09uW$`ALCKX0XT2gu3!AeMkKh&z`X=;jgkkrMj`k|LpL$Da5OP;{>M$q zf0;JmAnJ7@m^%p&&s$Rb50Fdqpxgy*xozNL@vKWX0QhuiYqP9|15~-#3yvNRZY&*c z4+p!Kj{_eHpW^LrL*x?ycc`ouI~T1ph14y^xEc)QXcl-WL8#?dNcPa$7~rJx^!~YBw&d_9#eW zT|0~-3ct2V%{I(Xm_THj?v8Nv*B)+=C_zn{w=i_Lrt8(UlIv@jBXb1|_EAt42g-6j z0SgCN@#_p6^hpLoHKW5f&3tO45lp#s(z0-ZGN+J~=Bq95eW|Z9>rRA}0Y675kSv4T?SapVsga_aeg$x!Ll{>qKVG$7@jh0g~;R z7>eHp&;3JuCPKu$V0MSatd9Ey?fpG*M@3HJwg)F(?%GHTq>z;77rlS=Igw&yy6j8n zm)OfnL-ymSi_k%p+&`_-^$RAM+tq4w{_wEpCVIU?S5TUmZWw9a>Al7lkXuqvmz{Nu z%+ZK&V)aSF`8}*T-xycIa#x;B97zgGMUm}>6Ks|XL)+n&@Q;~CPhfH z*mDk@2KiewY>{I*tQLcS8*NH_Qs3^Xq7~ltvgov8%(M1rZ8CQ@4RhZod_3sg=t-1& z%QOA1B7axW43O+j62eMH7_02CR=ijAlOHZ*cQQtUm}%{v;nPVX?9>fFS<29BO#DMp^ zp5`Abt@|MhCT2>=cRkt1OuyJy;tqZm0_prDQfp{#RM3jy2*9ss z^XonV>sng&u;p2?@czu-w5(=%G_kDSAviA-r}U?v4hIqW^^2&5k3W7@9lI82_8sx^rH9&u*>;FQ)l6BD53t}AI0hV$#3$NP!i z-b-_zgO-#N0p2E1&x!%Rfw&r%DlIwdxsn1`|ny)c6Kmc$PK})&{k}z%`tO^zZ^@Au2OQHR8g7W)s`_Z47*2A(ri{`2C zN@Joy%M%~Kjjbu-*F_tW5>_;Q$ zpa2icOKROnm#xHKF!t2C=MM3JJ8TEC+!_4j;@^NDsIrH&zw&kQT}GTSxl~aW{cd>J zhRQUcc}qc`z)o7S@xem_is3%T=`G`D(9Of#3J4?G*y6#B_pyvAqa!z8Ht*?K+afZ0krz**01z zq?1<@d;gv2zAIu5hZi5`*JkSd72gD?1Hmy{62d?Z(MQ&H!ah1Px|JQFat($)tc)I$ zJ$Rq8co>B9!Pe=0csGK?{pQ~F%^$1$Jq{`TBYNJcFkw5T(*5uTknLRWbhWQ?t7WZB$ z>b8;P{_qOTWDeY>{1U(`v3O8@ngmxV8YF$h-a)ENc80qX>l{Yav-RzAe0_)DJ}sz; z2rf{|P>2d>diEpw6Iy}nB|^3EvbjZCaWjk3-g zMV$+Z#(g)T;F3+LQ;3EJ0j<;>TItTrbclu-qOs+y1`Tzb=2)oK=^tljccH2en_5r(fQ9!%;a9Az&DWxb+PYv-t4Cb!cSO zfc8DleS|7;;{1m4pQ_wUlghUb2p}K{fGYQoN4%4* zjlG_pwTS`1du?lHZ1R^nSN)&PYswJt4jW?NF;dyyzu>4%f4ChRuCTj3OuP*em3<9A z$4Xj`-UglA$uZ(|dDuUmUI;0zRT7u3F8Tak{HIA|wzj~rDjh;@MY61IaReI|TW#%Q^~iNK zDJ^)R&D$;Mj_MJ($USYc!NUIP8R^+6^j$l}>IPE7qxW-5VZVkeK9oVS{1PKUJ*@5- zTle9|1%k#650w<*T*g}!v50bGvDSJ_Y%%enxi4?`Rn=`bdR$b+I z8_{4plQDDTPL67&rn5fGgc>EVWj~@5?1}=`H-H-ZH=5NNQWk(d7mVRWy@P&dtz-6Q znD|Zk&`q9$5TtFM*@iyRdhDe``0&EM30p9D!JO^8> zo^~K^W57#ZE*sRM3Z7|z?PcUQ3F-A91T$mN+=%c_XP4=M%pM4 zc_Vy8#kWL~li?eQ0cQHs*%=Z4efiW9)Asl%N<8_V8muFS7=i3%efW>*UtIpA2)_#I z!uGdaeHdMZ-G{p(H7lp$wNxWRir_s^)064NN(4TEDt?LtTF`!{W}IJwa`QZxjadu2 z0lP@j5+1XJ$TaQ$$m7c{x@3ovQUF-5nP~N88;>SWn_F|ZePR~t-=vHk*U|Ic@bP#V zpvoa({Qex6$7i?62avJMp)15f#t8|)3oO?Zi95Rj)LgP1-3>KzV@Z;#ku}qe!cwt2 z&InjfpGis3rCNxF%5Sw8 z&DR0TLX7)`SUWE(NwtEsM@ss~8h}i<|2#8LG!YsJouO}1r~zm5^u%sBXj2-Cgv-r9 zhQ+jekVZ5kgGW4J(TSE=u;VJGDzv=O`2CluB}gw_#LDoSa=jiiS<=I*n{SiqQgIzq zi5wF{`FyLf1wT22p%XbXRT(o)MDjwL?5%mF*Y8upf7rnj0?AwZIeFZj&iickb<>ZFHgV6M~f{ z8w6YygKxBNxaJrw{4}9$7VWQvL4%8^2Kk)E)?lr+2(}2Oko`O1TU{*NnCp0lkcB~S z+mjbF=9t!&?YTrtPU%{bZ^!itlpF-UgQ;-#*^>Cer-31d;r zpS~X0wcJl6H&+y_V0E}wE)?_G|6nlV3xu#d{BC?SbZyfw+1YEmfw0;^EQ4Z;kQ%{g zY@!|9_IX=^>p`@=4<$&5DB0mvpTx0@Vp=@flUK*-^?EyCwF^Yd8*oiF#Qajk6M(Bp~>(CM|;!NQP{((BFi@KRZXcQ6$ zD%QD$K${a5R4=W?thREQWoQLcl|j3Udd&958IGDwfQsx7`eoYOKgFLV0!7Um8hID# z8i`s&3_aQY!?1M?S&POM6|B{K(FYGaGu?9IGlQkpv={@E2!UKdO&@W=P|Px29J@x7 zP8+tql#BVEG|wZL<-w&e7YC^eSq-g2Kc@LzJEK`{~x{6(#a-T z0D+$#5$MWiprnRqqG35aEu2{eEsQGvhu+47P2vdmVK8-WYmC}5LUk8Y)S|(6ygNh0 zcuam@I;Z$glls94v%$JbNtKESL=RhPl7#|NGAWsfXbVK!D+5%cN09&gZ46D|+ns>H ztsF48{loV2_iwYY_a{6qOAG1pq8heED-DMAMYHx0rN7R&G%{Z1I^uNIRrB5ZH$zDPW#BV>f% z3*+PpL3NVXBO=a6J>I>aj0XUaTp?DWKagBb=dc%Vi6gMtJ@>0#li2p3BIPk>^fbbU zw+5k335NS@Tm-1Vzf6pk=l~YwV)h-9*!|u68D4djWIb4h02H%|`CbOunLJ5{cy~sk zG{GDJTYE{w>xdX7D=f@pA=3@Tf(fJ%7%_boOr(G%BPC+Vr7n&Gr?0YD>PZMIC#^6O zjJ(a(%;J9$a-{%-T%$jP+zS=&O8_C43WQPQdM6;wPZFnN_7V@hJ zb%Ik!+H^FCNGh42FVe*=>Al9#F{f*YB6u9#Wo-hJ$I}Z){;0)Gq;esd@GEq`UlYwV z8cPWfwCh57;oKq1+Vj&7Z1KPHQcbZzsGb=}f` zM%)lvYDSClCn!c&T0N71BOxx4FLt zH+G9h9#@9}*SwW~AKWGy+WA%9l?cHWaUOy@yDWgu|wyqS&>K>Rgr&0FaNoJV!BPMSxq;$SGxJ|+Dx)|T+L4r&g(NE!bX6=Sus zxebVl!IpPL3i&H4Mt|v5^lw70XU-CE=^sKakt6Ogj`%TeI09Nvk}D-bH1X?ewaXtXw*p{i$0*QfP<^T#z_bJ_2%-EfjXHK@LbSR!Y; zstXdXDTM+ROt>3JR4FQ<_HrHFOUaf&4!(AWFG0VO;1UzTnuVM~V_{E_)NR5;;~<{j zRTsvOE3Dsn?u65O2_dFKRGEp_uQV}W?1)@E2StsuduQ{itHBXc9R-Ny5ovCmb2Jx>u+vBPNgU^)bo#ZjHV|xPdlLEZviSk+5f8>*_yZm7BY4g z#(H{A&IZo^n&tL<(@H2}o8{`8;a-x^Tp**opa*9jg*#-bW=)R9tgV} z{P5-VZrGjq@sltsUv#Xi9*jpNDJvD*Nf8Rv|Y;;YT!KuZ`)Qby^2cyb)s8@F13r33&Dz< zz4-WWv-*CTW1n?wuI)_>=$l0MzuJH>O=(Xfz9r;riGXyp`Yh2tZV>^IQey0y1W2Dh zYi=-_Y3#PsiGO(6G554tNwg4f5-D?qolv6lesIAqI!B?9o){3L@@NWok|(S28qK*B zo$#M7;N29;O9KX3HkF@!;EVC63p`j7b)X7}SWG~h=2COa{pkXKF?Too!U4=(eE@U! zl9`4%^5tPOCr50}3$#H_kDwwFT9dV7YwPka^$rH0-f7mOP&Yx%RDW)z0QQT{2G&uzgN9 zvHN$dtSvvP>s(69YZ$+=aduZ$)QHbS~ONK z_Bk>#aVanQZttZVAz{!>o+6aRuAKg?W5ayOVBS>YL^slo9`i@Pi~FPB6~@ka@#1U! z+6;xg@=J%?HAgfJV#mEZdk%B-FZj&jPfSJUU!30&v@}59b`;WMy5{Ipriw$C#@f7y zn(@IvIj7LS<+yHuikJx@{4tJe^ZxQOda4rez;{fyhh%YPqib08*6dwd^b=u=l1`$h zJM{vd&WpWv#^i`FVsotg0Nl094zQk4qrA#n@}ROGJ+XG8B??RE4)|+5^HHgPHA$)4 zbs+<><7rq`cC)HWs+vytEy~178CVX|Ju{!{n^t54-zeYW@<`jdB7160NoLzayG~t^opLn^|T1o zOkAO-Qg;-DS*uNZQqa;srK3UIWvo( z2iVj66T54PWebrDFxSZd?12Bcul)PD|K9>0AUeSbaF*zMqz2W?&l$8wa$ufi1Oc^V zFN*`=emcC!i8P#;a8MMm(^ELMOc@{_yF(gVv>{h%*Ibz*npXPlYHG8~(;uDl=y>7G zYbtkLj6HIX?e%fboinSTHO_46d%kaLm}z8qq6HcFj>FqFxTt%+iv#LVXjr* zoY~M##=xo8!8O|~?F8KdsvKR+daxM>#(_Jm^yl^Uv=x^I!MwNQG?>N;6tAi^$KYe} zG=Vd-7KXpVsg_aIj_TH7bf1eJI?Uh@%_ee_c&~UM&BB{+}G$YICuh% zn0p*h^1@OJiCLqK%_nRmc+Rh{M=Ysusv*i9#dU_t-v&`rX+nlsYzfHV1cJp(B-x{1 z5k#0K4EodnR{wm({ekj$)aeLSm5Lb#<2?Q%`pBH@gd=Hhepv8~9e)xNHd?7@)N2O1 z`%IyBAbL~tepP}IsJ4hv<$A$ZvCSmXn=Z^0D!jc%d}{f#%U5JM(R%!67Lg8g(xS!Z zgV2YPu0Wb*kf%yAYKj%|wziRGhGg^G*Hw(!Y;D0~%dpX=QGw&G8W6!HyiW4i3nKA8 z13PyME*Db76gtDt=PWQ=qAOD)wm~^opnHKks|VsvfA*pf;o0VA`4-`5Y(kB64mvR; zfY-kqUY#z@|1L0P7%D@4Zum{6ohG2bIHqqtO#!vpURxds9BfS-keoniuZvD%V#qtl zbG{0m&)gJ)BDSh!^g*$YuHS%D_biB?uhkmWn2*L7G%uq-@%&X$hCK^bI|}k=xR7bG z=Z03i7wx``)t$9(FCEYFjFs9;t5<(Qy__|aiU$ac9K?pM8-3(O9b^>zs_L>Z!|?Tf zMziOEwV0eP)|vPVA%%vGO<61c0beh4J@M$mrw%&wyMfNbb@Z)C0eRL&1C<6Mclsdh?z*ke1rJ)p5s-rGxS*>L%t%f69%~QKQgdRuDJkK5$ zMTBP4BV~+-lJ_=$?7f*2*)lmxiuOWh5fB%1Y*V9`bH?R+Hl5rGC|Io#R{wmoJ&Eh% z(DV%WO?04Hv_<9`vuZqV4Mlb^8D?B6{}JiI-9{wYWce68%?!JhFllEPmPUX z1wsfQIYCp)1$lCvS|kOKoG^e4%0-%)7Y4^pE5?w~B)IPdz)@hAJ%}H_YUEoM;jEJd zxsOw<{<7*@uc}RtRt(~3?-L%S2K9|O%g>@p84do~-2OGzkeo3x>hRZtJjb$7yx=IF zk7l!)ktlXwByUV1k_kQCZH}a8}p!Xs_`^qaD%cfk+YO{EYXzeb2*B*{c8LN}b z{L69#Sr-bh@pCQ2Shf`8^5*f4hCp0&zsLTfIM|IQJ`M3SsnVf`q<}kcA0DC`$%^?>19CX?VB&cfJM5w*sDB?M$ zLqlpx_fCVSELihkt->J)iisj&V0PjN3L*6SGy%qhIW~gnY(rR^%EkH*LKd($ehcyB zZsji<;APqNWa9;ycRz48pLVVvayG9s#YYW~+5AIn45!!D5SN2NbF;5#ljj@CD<(_j z&s6!a2UX02$#}@m<`jNAIylcaNY0@vuJh+~3T8LPkIrZ6NEZPa|A;mYmDT0;b9vc4 zxa&PRf9eG_#-mvb2OatG{ldGfe+AM!B6q##_5AWCcMHs*=DIwmlUn&>y1jGTZ&!Qd z_|xU=Lw~MzFpuw{3|`GoL&S8PL^4lY%FX7{SDQASa=HS!4Cz`;BI9|qc^9|Kn{nfE zA|#TWiCARKz#1iB=m86(8t(9IEreN#@o_rQNsq)dx__o@_j1J$08m3H79Uru3YSnw zzG;cRG8?^JS87te2(tV;5~3Zyq-nwE zg8J#TB|6Fcs7YJ>Lmqn*Ese)|YY)xrvBodwn)hg2vyCqsIv#ZSw(9R(+*_l`vQU^Z zh`3xvRf%Ok6ZbQTpd|D)*=s!HBH$;)a;`q&FqkEYzKUz$YUOvG`UirT6vqnsby>Fk zGcMubOLyZ2ED+Ej8xRo5|8p7zY!vnMENlUzsIAf8v*>@Z`i`iB_031;9W(_44jDmd z(-2z!yiE*It&+-?6B8CCK>K?dQ_lxaz$CGBX{1&gJ2|})URvWe@ndV+&_0bZQRb!BAW$(4S&h4qSrL0 z-&UH|2ghEE=VHW=(j-s(+Uka{Ei#Tq<7iY5tWFWp7!cepNpPElSHg@$GCNF46w+I> z6bPe)SrWCE1bXP4>Ng|Whf$0NlLN#hq(w3;YXE|7o{#SZ1guot(~uDYoj^EPlfyog z5#sz4k50*+3FsCwq9u|R`5IlvP$hOE$B6;MAce^+37GFw)nBJ&3J?EbukN=SfBQT_ zA|vcNw&#W(?V&mFN97oL_6q`=Tf3_$4C-fWH{cE=r@oWcB9RC*X3YjxkWS0QF*`L3 zF*$#&ODn6~iNKmMs{fh~T6^h7Kn%{=lMu+Tyo}!wAN3bRwRZ#S{X~fJLum@6tL2_R( zf6jx@Fi51w5_Vg|jQtk*=!Tb@>myee?{n!=aHKU{>X*mWoQJOpa%%z_(yOc$cv|2n zyxvNlUDw@>dnmWEBzjhe`3ke*LGVIo!OJKjd;$O?Nt3Zj+0O=TK<-{;Oj>?w67svZE74GhaMi*Rdq`1%`xh#&a%&qjL4;~5$#t?S&41x1lIBHcNju`yJeKi z7P63s>c-{?-*v-}7I!I6O)V`hbJ(&tB^5Q^u~uxewPmGD?5^%_!0W4*_1}Y^SGJ23 z;4|bo3nmA{RLuLg_rl5azTuUUxEoM0?yUP`P&K&V8{J=8Qlg5)(6vqrs&CYNRl%r$ z1yK`OS0qmheJ^s&sGjYLyHaRs`^F2v{l#_5QAG3za7Ae?U}8j%7#am2~ArG z$`aARyXY4=AIB(r^~>8BSW|0q>+{0^Q5PajF39!yDIYFx`I9W#xUeKnO{Gmx}F=x~jRQ z76|qS`lFhWYb-6=z z%E1m4nrhrto}H(?m*vEtuVZH=G{yBF70*4gBI=c4A4`_chIEVYkM2ozD@XHwV33lO zA0gTNR!@eRXOVCCm5jkly8Ly*%&U2PK9i_+4c3;FoGsu$(_3$bFHFLfaDnJ)wK-5}bYzqNd)< ze;9N5QZh$_#bQctm03{?JAzs8q*k2Z>%*(z?)91Lma|UknNifkq;1aJ*%1OtOWtKC zN80D@N9BVHpP!wS-@3n^(p4Qb2O+p!ArU5g2(sw#3bNOj;SFME&V0>@UL%7a#8T+$ zaF$eQz!_H^ZTc!w8>GIPBgs!meRvF%UP=2wD$!9*1^~WIksIuqLwd{t=ml%oJD}W! zpmVgel5N(99L*cz+l){M906jReL%$|FfPZ-WoO&V<3mV#Uw@cG23Ug7nqHe_%%=L` zJ^_~Koi(qer1BWI+*rBF0-Gtk)t8x?W$}V-5h4yG=W`pEK!y@aM=+MYOLd+NXOy|` z4bnC*?b2~39&Lwnd3R20f@>-kI$a6ca8&aJ$15tbbOfGJgoMZ`f|Osj0j`ZS#&2du zC#5YSEn$*swj^i;nc0$bDx@O!vh`#Q3bggm$D;DjHGtf4R=;A+4o~8Cbz&Kn5fur< z0hT+>b{icYD=&oYSvoF2e^)v&YXNVeT?Z|t=4vyC!V{iIjyJmf>MuW_2uDhZXSG6i zF}r6w_RibL`9dV;chDexruABWvuU~*p~Mx^jU!XaosvV+=}9cn&1z@MCEL%B>5CQx zt1Q1@zub^4lH!jJ4GjZg+g6e7IjdgeYOn3``mmhafk0S}MCn|d(jk$(h4Pxjl$%jU zK1H5%s;{r99 zy(>A@PZq$s%#GpuQ!qF-7o`D za6VS_tMlDH2!*jLRNSnl*n9?#n-v3g(2H*sf&f(-{Y|NqJWhWg{bJ~}y7ngA_5R9z zVb&{A^(aoZ2KAYalbJPUD$qxl#c%8KqEy1V4LFUJ5l6Lmmk`L0c$U?VIUac_$Cm+E z>uq&dQ?lMk(a5r!C+WqMR`juu{J0XDJGqh|@ta=)tN&FS+=Q%65Uc#VBThpXaxJp4w| zJe;)b0JhS6i*|2~gYvnPw!Xk_-jW8b@dt=oN|4u9j_?M{g_&DF-WK# zTlx8HvC|qvB#dmw`Ha31A6da|jx@7SsoRK?*qrRkh0K{3sFS;i!_KA@b)k$aM|dcT zszG}V?KB(ratRJ-s83~n5c9HXybbJ;l?lvG#s=UyQ@QAFZG{-0`K6qFw$kYBATidU z`gJ+J2EZR<{0z5Lw{3`4n9!X~L&bZZ5JM#Df)arP0v^t% zl&#a@`EsQzNb9{&CgGW9PIZgoy<-X=nKH7=&1<9MCa$qR2y!xibtY0-3&WXtOqNT& zU9v>aiJB2HCfib#M<>EL4+#<$jxS29D*aur7kOX*0wZz!6n zD#$VWo{#j&{6reytq+_x@=X^~l=Z1B*o&qUsOl6BIQkGjuSbM1#H zMl!V4fHCQD0Ygns98vc#EWR#+Uorkh#oH{j6x&w~j5aJ~2GZDgJ9`^hi+oZ)Sy8)1kzi^pqv$wAjEa~IuNN!0W8?>leohez)0h4H2P zH|Fe5zR&l^2Ub6&S^wGmGE}HzAQ%=eS14kTIy{Y<-`qdAH?Ca*EM9-_guUsD8$Box zSQIm0!MMR%a~RB%J$`)KDv`^n9rC8A=qrj$mV!}4wP0`s#$lNQ{lus5>Uj`?zJhO0 zB?+b1bg`wF_S)r1XW8*FG>f&7^XCXRFG^)EQ&MYOccfmCQs^xG_SN@hAoh8@SDaw6 z-5^yJ2B^@&@c+>ER#ACoS=)7RcXubaJHcH7f#4e4-6as*HMj)`PH=a3cXxuj2g`qx zR9AP^SN)Fnw}a<^GZ>7q_p|o8=DZ45!`sgC7ZODxGK!!R1E>3wA-Jj~KQJFmCKIw7 z&&}A3XUXES+i~QLLuPj$VK#V(4%GgOP91&=Fy!%@P*Y`5L54FHP@f)yDB>1O)k&V7NFu)o9 zj)nfWH6jfaXa*%Gzg080b9uTmpycJQ_{_cn^bNIg)s9{BVtqlhCT!uw_x|`3-Cmc< z_2>S;VPa5wEZdXkDbw4iUWv2sJ$EA(^M|LM^Y+I%iQ*3NdGc#49~y4Id!;a7hCOfU ztj(+QJV$5DRNj~aJm5LOXzQ78gf+ZxXO*xS=Q6SJ>BLuw7~XMGtZMW=uO4_Hjnawuqf{m$o=SgMDz$)8m43$Iqsa{&E z7X$Iu7oD-CGe)D?vkgfO>w86V8omq&QA-I65|M2vrc&88 zkv?MVhNFxajrcL}=l-f-Xei*y3{{m^E2(JwyXSE}RY2vCXYn}0!|O<(a;W(SuXx2Y zVinJ$^$P$nvb#zO008tnKL}m`fZuGF6BqRei1n@iKoMxo+KJ}2{z7rprpPgP{`4|` zeFY9r(6X@`ZsJdv^~UWXQ!U+IB2>X{mV4fZEN5aX+^+6m3VPvDAy`rtAV`u-P7H6l zC8egf1I?d^7#tir0`}2(kPDqjUHI#-#vwT>8tWKVo+~GyaVS@7fVI#BXdLQn-4E=-RHKTSI~|IZevV z8($R-ORW^*91yDeV1E+$0*L7>VK|DqjCa-y8GY8ce&ws;A$te0$qsPLWf@7V*uK3G zo|Zt6#OseBi7KK?E$JTwfS@)IB>5KskSp>+07T&-XM}M64w6{?El2`?5lIFR0I&WX zB$<980DvG#BC}s;s@eDS-ai9Z?Pd(zX<>}fB^XToxb;l0Jw|=;I5EvdMD>n zF3UeVhjL@RI*;8bCA4bnP0Cjbt;3{xW$_~+!WB}Ce~>Mcb>&%7%}kCKb-OIX;n-V|$a)a6|+p)!+YWriLB zLxiIi?-tz1vv2Lq-F&o9@kl;QC=c@PIq5*B+4C%|2KNU^t_cd?DmZ?-R}R136%SoK z;qbHNV^*1VJubbV4iCrbsYEDx!MplsH5TK-k2wrCzHgnCPiWufaX(BY;atDcD*8#q zE;UP08X6}{E8#Z`jlUAh^FCg%{_CUAy9AuDr^nG@BKS!`7D*Y@>BuoqzC@Z&<%`G& zL2Q>h?|3$hsS?sPlSz6}rS8F_$}z9$!i1a;f|Hayl`&<|9Ku*6hs*@7rp6~Wiuq^3=pX^pQyK?Mbbv&i5u zeg#O@YC3A@tQG3Xd3d_TS8&KDlS>Z);&yS(2QLS(RqlKRmZW99Tt+B8V>8MMa> z2`Ff zH?!ZG>PhM|90Q~lGt-+>KDjCtX?zOB6M!}Qu8Y$M0PC7ObkQ*`D{ja%^Z#jSDMmYcH+{o(x zqufZ(|Bc*;H4EKU@c%M5V*ZjF;d&IDJwK{8BDIzupZgzjBkzFRh_mAV%iM^}dBXoc zxsf+{45(U^|8H_5ynp6Kuwgruko$bS_^#evQJ=KIkPO&l8N7vH0H9tF2F@#XurFk? zxfiA#aT`6Y*mHHvHIbmWUw%Wq*usOu6SJqKW#4q-jeoYBun@-7uI^Cu4(blwO2YyH z!p+#LLyHBSt(O3ysxx8uUQ3#W&aVKWnq&M0qI zxxN8duY}*DSFySATjg3Eq8F_96AGXPK!Cq(n(d)Uqxzg)iGp+ceD*4Ps-lx74EZ=% zZij;)!oj~*&W#=&IOr!xSvq`qlhOq&-&=&LsfZUQ87qCL=Pgje_7;yLF$0q*!mN~a zQ*U%^*F;mOFcyRrgvf~`+I_nFSpcRZNTyuLQKyJ??|=s`y#lve960V4m%cmuxuMr( z?GTQj_T`|r{QE(_Mr_)oo>uvngMRdd!g`^N!qcv#Vy}yuERl8pCA2mNeq@i@@vZQ=rtC(LzO1Z8UMOg>ZE1nga*PQ zg#hzK{Z9wIgMprbNvVUHLvO(Be$0GT5i_IAW{HrY2(OY$jn*q2qQx&m+dp3 zK4N5KBxqeeMDO`~AEWLG$}=Zw6|{RnDY!|>skaDm+j{I-m~xgM2){#2K^|?dTq)Qm z<~{g(O0KTR5Ec{}s|*j8rsX5OmY|O^#E{(sB{wyWKN%+|{)})!Ch77371V@J3v#Go zwxp*9XB`F;6yHw*I3h(Q!Gq&N2Gn6bgE98NY6`2AerY8{B`d!F%xid$HkD$%eTDYU~R$A`v}DC|WN5XcSMX`J^3Pb4JJUN~YU?gQ+r>H$(m6lU@>jkl#@ zR!y(JEQAJVONWoX1}se!dvAYMWi4@z^SzCXk zF--6dAbIhmhn5CdqMQOr1X=*_A;q;(U^;Xq= z1uhkF)(vY(6t2Z$$qBgm3zHzlwKaHg;C<^LO1Xpk zPzY8*brikasQo1zABE7qEPM8Vbvq$mpTtar5Q36oIL2(e4MKUHv;)8|G4Kv70(e{O zfo}*O*u)>UF()cheDW3|o-@4-(i*pj>BP)DdPb{1agSv17SF9ZUtFkaF8JPSe2Ok%`1mIudFZdTj zBD(B_YZk*hlZShkjQf+vtJsn}+)S65yXVs&KVzQYEuSw)_tt<)zx~x+0HcC}A4x=E zJ!Wh%J99v%E}T9bv4eufxadr)lMU~kSa3xhVZv=jBBWB>H+11Vl}v50S{eE!{NuJ* z?cTbA5*Mo=JF~HE4^l42yViEd>mk;KjE+1gS|}#IYw7xyBnuUx+nYZLuzk$G5n%5? zGyu)qUkR}Ji_hDoYK;={Z2$q*fZ>&L2A^B^wt|xNUj&%%e-L2FzX>oqfB*{z2rv(d zUj&!{p?*w_@}x>)Cb3j)Kpn*^Mop6~d?VvT|KTAD*fzyQ1qqwB`pWXJb_XH7W-B+B z#NR;YNV&IjC8iEezB3V+q>g5#*sl8-s$9;T=8 zN@+K2?~N#q*X=Fr2OsbIrsp3kzUC4p4P&`lNYN4GHD}X!*sTY4THY7Qxm08_sG&Sz z*|u0^v5+h9>T89CKoNj}>Duo0UB6&pAjqd{<`%ENOd+p-NTw1Q?G+0S&=nu6cnvBS zNfHN>l@k_ky%#jgOso715iqk5juZ3w6~TEw$`@Vi9p*5v!chpagHY`tr)p-K%Vf2l z{>Tfm56s71__%cz;~0>BqMw)a9co=gf9&0)ckG3xCA*_9A9lOjK)u&AT-?rDII%8? zS3a&TPkkKK-C)Z&tPhrH6?qUq+sBG}++adhTdknALRiA7b~zbRJ`pTnC4n37d^?X0 zMzNY4`|eB@I+kkl>ir&DDyE<-CsV)H{+Vy6s_qL2cKHB+VDJb@xm$Q3EuG_ghL1Q`3fU4qJvYWCn0uIc!7ZRp?-T=x8EceldB5VaUkCG5uf`Nl{A#jwr>I`Ur-8XhfRDM(n8h*VU2w65GszL z9j77Tm?t`azr8iV{YL(I)i#L?C-sk5PxmzZlAAdmq^@4EqHMV$>*5YX0ccG&r(q$WVRfhR*nAt}2&eSmNnz z$A0#k(vW3B2a6vUYIr_FgA8IaMHh^-`Ccm9nG9REfJr1+;3*W(J8pg1{1cB7Z*PaKPJ#ZLp1^6$43G{_(83DA$tG_KPt-^8<0mbe7Vjh@b1fz83d0Jzti15 z*!~o9bAHE)q5zJT%lyv?5StH9`oL2CAw(U18*kpYAa zH_K9H=tJ%Jq*8`t?mFblgAi^%5>u`AKIb)qUGiG6k-%fw2K)Ldj0GU3QJOdcac}^{ zG(vT%UN4`#r6tfXvBC3N{&Z&EOv2YvQbJ%uYgsm>q?(+lncie|M6Demv}T8XVnx(0 zANxoHnp>fzfQdsDO^Sk|_(h+Z(rh?%#EGWMln4#54d+IKG>bFa|1 zPyZ!~Uf*UY;8p-0`q+Ow9NJF2Ajsc~4^e^P9p)otreO(0EcS>*(7BYXGWJ^-uyBv z7m<;Ez4=wVy!q+dq9*}we!YT{U(J&0m#!IA_C%A9;v)K6_8`HbGXr0tuCLSUFVov6 zf7jdGRpbpmLJU`tSx2nYq7kAJy5bZ5yyVC>in7?aTSLag&Jjt&u-Qa>zVJhY8-NG` z%;G{rq$xrHf-Jz!T$DS3gE;R`h@b_NW;QZn1@Z!T{%b2^9|sEsp8tk`=f59TcLlFz zM^&wIFUMb={}LlkM_*ZJHvv;&qcboS768wGz;mJ?$_DWKXMgHi67Ac=<+feq(pc4u)Abl2JW2vA@u9LH^vqE$Y? z0V{p{0V5-VP`#yesLL5yUHu*}IeSa@uTvr3B-+UxU;=Rlrow+*$^C08{1YW8QQMCM zP=e>N_dp9HZA_kKcLg8miwi^uK0;KRdcfBBjoT`anPiA+m#~y*+9@AN?Pl z0al>87PTpxP%oVU$yPM&R7l0t9Ja=wmt2g&lOOUp|%DhX_6s z-SzLfnwMc7w(Y;W-#KsTAd<}wBL&jJUNnl}4hHv**gh#IW4Y3fvNcn@Tp10QFS>4gzyRFD3&M;ZUd^DGh;Chkwu+S@4 zTIS7ma?#vDU(a*9#?6Rn7$?tue0g;uy(+P_$?_ciifwvwZ6OK}fgB+^NO9hXEWk3G zhZq_;Y006AQlL(%>E&vHus}@pqb`K9_CF6dObbqU`eh#sQAzRGdny1ZL6ff|iXgXb zDQzrkMcO9F&0**}+*yWTw5@OF0_Ycr^OR7Q>PaY#PE9;`yrdqIEuqo_W6^k>3ySN3 zZ(wD)=;)?0z2OGi171uZ7Oe9wFfQ)LgXhN`uKLGlyrNFrPytnX-s41aKy843uF9fN zg+tE=pWh}B0=|z{C1gJm`?u>O0#-jN-E|WKqu>J>@;%e1%>Dpa^rB!E%A)}1R7z$L|Gauao^Ca7GTdZdJn)y08-)XJm!F94P*Aw=aE~PZ8aU>ES)FLws zyLV*R*3=aQ*rd0RT|J>*xb(o$=DPqW0Z<#T95Msc23$wlKzaPj1QOZ17xewb1X2C!adX?p&&0RYo~ezR&2tyiR>%!5#hZ2rc)7L2Vux+ zuxIf+BkpH~)SGmok{JvWW4Y;CK>p+my z@}rBLyOatm#CTKb)6;36uQ9`!pU@ftKgTo2MH@`^%=o7u1BBA#O#28&lH)Q87KluU zElBj(__it+vIkP~InAg(kFhW?e8sp)eG1jgWip9;NHdJ5^RM9-$!|Gj38@lyZ z*gN~^6EVX$YV_L#Qt65pxz49ar6@f2Km|@c&d!N@%`*p17resD6WpIFNJLVxE96M^ z#4-Lg-msdJtFxbIEH@jmOej^!&K2ljL@Kyw1*az{JIWsz8h2P)G?&h1kjdtVOz&>G zl~x`@(+}5opuLI1_9bLqSCUtZb&@vHZEPdAtNqG(lFnNPSpj{_9!Jb0<=j)NYy-4v zOIaHkt0wikSq12B881)FGnUeixW>9?O9AA7E3%4j69)D6@|LO69DOP*mxGHV!-|s) znx*MnPkEL)jk+pA<7eaLwT^KR7c;1SeN#>Zr=NwH73={xR1(|9UZ8aso`TjLw$Kev zP?xDcO14M{R((^qx#p+s`D(Pr^z@kQ!Tf2#TvQFJFNV0F_g~%nvxT?Yg}c{9*%F7z zVZlsXHhE1opzXk&cC`}NI4h6kGFNslaGT#Q&BeC~W-;$ErQym#hjcFX|CDLM*qw`81=3P7ir3Pxl}OTpH(lyig&1Clc4o=-6?$U zT(_3$7P8vw**@;1Mg7THxKXc_k~lVdUbLf`rZ6S0h+W|Ni#?fmZd+XN=#CQK=pT<1 zGqadv^t)orP)z2%Ee;O>MR!1Bs~tdT>7jDuB$y-%o%e!`H?9IjKF$Nzki^iDoY-fd zFl|U5!;((Wb$a9l61JV~t*;e{q(;{u8T- z!-$Lch$~EYVa|%p>(tQ)VZ7{ccJ-8#DFYL=Z^6`?<-a5#hSM#mK(!(6y22}3NDFkR zs=E)O{a@F=_Nq%@+TJB%)_Xf}xE@i%lx}=`h=ygWcy9FmU_m&qNN-g@l_qB8;}bum zU3fk-X{)Tie}YrB(ouK{H{wxJQHI8RYnBn962I~c^VfS*iKd?V129N=03TxD^M6=C z{&H^ujnCn4VLuTgi{EDGms^QaGm!E~`O9tz!quGRUz$MeJ*XfNo_2sYgihoL3{%n%m2lc_X`Sd{u>nj;sp8s01D^%GWKu@K;ii> zP&gn3`5P3z`(L4OVB+`B9UaU_LA^T-M6K7;#%SiOOv9ft4NodiKq7;(!Slf?-FmBSn_ zXhi^wj(-ezA`rrX(hadDit<60sR17c0!(kvyM3Z&$Abdaff#<=)beR(m&ErUI&Vc2 zNeie-xO;{jDDqQkwj~Czciu+{y`byvYw;oo884>aeOO^|vO$Ne~1lB*@|Q z1nDyoF*K+euKn#D&RIBSu>EJOrA6lwhr>04-L8kzx{%pMHwsp6=X)@ge2u$mDYdwl z7lRG)l-_d=?SML6%LgE!*CT337x*m?_Kth9vj3pZ6{`lNh(uvvQ2@hYV$YmW`a zR~e%86{?r7%Uyn3i0xl08p!99mdLDUTqdgIu=}7f~>5hR_L{p#@nC{fS zJRvm>xr#2jrzQfK4*E6PmrO?>9FXZS^6(2I95uIH5EBJ59r}OGbik(B@+@hE_3P!> z5NAD5@u>V{nQa0{EE|u{LiPMFnGP$)OB&he#GXp_KQkTE;Z~f6TQgf{?Y}b}VTG(k zVD*!T*=OYH7|q|*E6ec_SjcQ0C4NnJ85bTh=}(WV)29fNf~=AWFXN2BK`;@I(U{(Q?L%tf$1(hqQ8-H82!hf+k3W4tZAd<(UL1@JHp^v zu`!3#$X;$?&7Niza5RIh^$k)_hm#NP=SOe9QR}zhIAZ1Q(!n?DUP8C9&1k)JmM8 zr&47T`w7@UvPE$TXPkaEb6gtSLDAN_fOHeO~LGbf${-Ff6aH}2JcRjy;;$YZga~yoZfMPoILj*Pqu-Kp-*O|J%H3EH4zMJR zb4!j7)2w7ReT|&sijrGAya{^EodBxRFj?DCj=D^VhA4v~v<^8J9KA=J07ZuQ6&*`=$Yszj<)hjZlEZ3)i z3)I-p~3^z!a-iL~fKfaRY3@|Hd_ za%r#8`k5Tqk;)29mTTIE>~Y=q&N$Tu;b9Y}qQt;+l|jNRc_Qnv@X&lDfNp z`tU?}ry*FiWQVpA-bpH3t;N1j;D8`fL7+jXy5Bf+-*Nod32Lic?WR*Wu2%U-7A|=I z$}a1Aa9@s)U*cHpDobD3dgwd^>6nNDI?Dn5`5Y*#jZQ-c+>YE+m@Qfi%eOc)e&xy1 zF$H{v39@M3rPhT8EF`EZ+eYjs<2Eu^xYSTr8pDcUbEWQ;#n|snct>#h#R#BHjQI@Y z>X$>XCUZwe5r264)GMBYe|Id^X)(SArEwVC8~pre-c?(|ol6b0)$S(q@&;|gU3i+^ z=R^jE!{B@{{yK%K@za(|zuPJha695NL*lTi?O>6PD-)8S`_Fv~!^fF>hQSIet&(2`}CH?C|B(@53qoMl9ix?)l}aEI!0 zc$D@*YhI-l%2&h>pu_FF7Y1*jX9?6WBXifr&t}8as^C**6NRBc8zoCf(#7LHC2cH^ zszf!PUFFKyu7ush=x%wIEBU&(^TySGPo8W(Q!V3vU+VORI>CBjaADKMOf4YlK;N~WOXkeg=lQdcW1 zmy5>84b71|%N(V$GiB$`lAq`wJ_!Na7Q5Kx-eqlXWR299^%W<`O}nk-8+>SNKZ$fY zR*5xk0F;kh7$`wu_UzUW;MgM*y!M)i zw?6V4W02)kcQ+@CDt@pd3vxYL{+3ENOq~i>trtef$WfO;ZJ{ilPrsBgsGaE52@}r` z$fJo(PB4y-o;}qoCMnNySLo-(zOI7R&hs}-oL=8LKeRkyLvlj4eM+yp zN{{Yk!Rct?o_DEl{^Wu)FM8hQC()!AuOk2|Z|bFjzmt5BgWdh7>PX0y6t#X}QfGYprEX!v>L0C7G-F{VcT1MR4<&j@=C*y2r= zWiC%|h=07co3u{imPxA~d{BOOFjrM%ZC5UvQ`%7gB{|Znd2zx8$R`o+GQ_F&VYR+$ zJv=)n6zze*4&}GrH*&lhvQs~5YZ6glQ}A3ssOp6rE?meE_k;k7dx_$$LOcXY^Bl%; zfQaW%BaS&%ROAZL${vAE4C`kicTu^`IKo zkaG#s>VqtP305rko|ddrK3@}QRDQgT5g&V!i5{z};r&Q_c6&SK8x3Qs=Yz&$kjIvQ zy5^Bel(nky*$e4f<$O(|rRdvF1y@y?kDQIPzH5-x$oi77_SR^fGutNaBpdu{YW6V|UgVk_<{%yqj_-r`K+}Ndx@O zNu9os*iQ>nuyhvwKhOl|1B zt_L)kN@@!`BR_hzO-3z+TSBcnBU&UoV0c78ZP!=1aWn5orHVYnezy1_?}E7~DNaN~ zP(KQ@dLC@%U-TBzH|serKEke>dA_mn#4l|{q~?=I;=)f%b%Tr<;ml1?J;6|A*zMu< zf8r1kNi->nLWuWz+kB?*ajLz<_MY~yQ}T-2s8tK_JtPW%KK|CE`x|BdV-EfGeFUIA z#`&zfnBXDSSMrgU*{MVoyu~K~*hBEWAup9R$`H4AOSKGId)g2FH_f~&!;3a}w@wXS ziIZm5ih~!*JhF=oiu^#t;wWnbVvWG$T4Sjbrs+mAq;51F_ZtR{v%yY>2$Ll02X8@L3XN z?(X&%mgb<^v$>uh*NG#MUI(3hpV?l~d|@iOZH)rZH0*Ht#@1LrBs=tY;WH)5pbf$Tf=n^FlkV7t`-_z1=MUn-byTEGWP4%y9x2T7W6O_ z-toaK`w2s3Vn6aD@!^eRxM4r?t=??Bk15T;gjKGeqZudi^Cx^p;ZC}hoL|&z?voc( z8C$_43RxR+sfa6C{F)O0Q&Hb`yH46Cyk0rp>x7*^>a;-B6ClY1)S)4VzS?A|gh}LD zyi`oHMeVcyalgf{7LT=t{~E4MJqD|qDxDOc_dO+Iq-`LivTxTsD@qmm0XmCc6$%;0 zlKeNL5APzAoM=NhM95R|g;dGJ!F7t?hEr+X?)Wphav6Pi%cB2!O@^)bImBp758t}9 zFR3)HCub16skg~>CG!+P`f5NKA| z`=eQ*1hMB0(CToeV8>AqyvK4)1N&8;$xbV@K_9`5o+*}#3}{vm83w}wpVDY8T3}kE zEn4z$xgk783^e?rK}K^)jmy!x1}s{CH7kU@G%LI(v+eD*p)F1XniXE$Yy)OpFU<;N zK(hi5bOlr>KWG*bSP^>ByDT4HJPE2fEJhIn1R=H40#Qe&0lIo00EoZB2^ZWzjZFO* zm9ASsP{3(v(wp0pULsg4#_m*QIjRtEMY5c99muy~ZKFc7#^bScc8Ph1wM8(nZ)J7N z^2_Zhhe>H7aAVN`JbbT{Y1ihKBnGf(Rms^4 zA&FUD1iZh7Dg2NlRvze~*&C&$X&ttW8*hq;ln-GTV&>zeM=>7W8n9HGt^F`9VaTz4 zZ#_!OJa`>dP;E*YhKg2KR^18Wr*TNRn;l+U?F`J}GZoL8IbJHj9FB$NH@{T*{B+wT z#7DsPD`+)?E@~zSa~7l)n+++VlDMf@pv2f=oYK0p&f=dOjfk+kD2P z?<&Boh9z%sJGYbtd=k=>Hp!ZEqqptdxAY(*mGEf|^gr?28wXi*J!Pzx^k`awf4o*o zt?sm_8=)7F(m@~M_~U`y)NGQqTIWj)P_RHI0Te9UAEiv0yo0eVqz8vksAgy`(XOn- zMna3_ZY5J9l|l8AZxkx7`?8YS)WLMa)>Tg|HR7M1y(R1}xCrzsoHI48?WN#pV@5m# zWkA2@>P803!iYe=ZQ2QFOp{Jet7KNkdJHVWCo9>8?ZjTUgT4W`VMU92jU)WNqZt*E z)v9w`56n=;TF>iwdn9~RB;AZ!WL2SOe@leM_%<*b3pIzVh+OXALTb z6arL)Brgfl7GD2a6(&Uvi;@YrhsL99_xgoHxbbX+*LmpA<#AR%IY=3teU4}{kj~r? zvbvSG=$J(+NC-X+LAf!~% zb#j*sR=bB(Z-m&~Pc}~iK9h4E3f*jZ#;+gKv6e$(EDyPPj@s1p(Z?#rC=14I^WVyx z23H%jPf~=5t}dh?XZX_%{NH5!Wa>#!gMCH8f~tl_nAgxx>p3DXu&#x_+z6{cp5f^)WE|J@>f|i zOc)1m$CF){k4m;L)r6n~Se&L^QX>_^f0MdDdh`e}UgfK^91rUnJ^r+>r7m04^g(sJ z_?d>^3G%$H(Q-VL$king&qVR$uI=loZw@cgS^4LKoMDBA5o?TVxBN!Z{23Cim8p>y zkHf;M{3gwXJz*X7_gc8qW zR+AY4{`h)XHDZ#%H&9o}l2*(C6Zqy+wBlx`yWW4RUoQ4HWxb|^{W``B9Q`5s5w0b`(N8(tQuy1JK>jZvgE;cAzuO={{tEU@6Cy|3lZ9NH34w#S(Pltpl})cZ4DkK z-x5U1_48(Eu@MXNX1C(XVjmE9X8>|$UqH^RSRfn#32TjCp=HwylgkdSSCbbzK0?j< z9kR2H3D(4Rc9_?)qNg@9qr8MU5wniNcOLTl^oq4ZWYJ^3DD*h*tbb6tU7_dx zk!9zY$NF0MZBBkwMa6g7kP*9sBbrM6uTHf!?71ZqhYy(T>A(}LSduQioW?@5Ll$X~ zrRBRI4tV~^IJ@FP1F=vYY}A30<0?hbyh4NVBZfqvj(yL32nW8{V)pC3dX3I{isZE# z1N?*377Jb3$3ugCCz1d>yQ=)bzxppygRwNB5=-|G38G zphlB3vxBO=W)N9cbfW0q=sxyKPiEpCIuw$>v|%#on^^19(C^karkgkJ6<9|-5QP@* z$LIuDlb4lg(eOl9m3=@J^Muhvx$SxYQveuz7P5u{?RovNLH}6H^Z*22bePB~tWs+` z>CifuzO*}H+ff@np*MuK0_!Yfbm=p`Ry!90*_EU$%%LMzCk&`ma)=bK@aKnS`#y{F z<4^?IvHF04%?f|!_WlpzcqJX zs(jn625yB-U>NvENwedB+zS6O38>pl|8jQ1Lr#=TTWTOfHwJ;zC)O7^1CIXYfur6M zfV5ix>-IL$f4y?#oP~bAJ)dD?{5YbQ@BMJsHL*7|0O(>EHnz8_>dK-%iP=5wcPQW! zMMZ907Ed(Q*^aLS#cT}1zOLS6iTu)L($2CQ+QpSIw!8AfuaslT)e)DGMjHyF{yAI= zZsD!=U|`+->N;uSAYyF+x9e{&);2W)HxFXGrT>~VGhX>ixf)hP0tAa>r)4`ngVw9t z*l@fs>odD6QupCaD`|cSqA%hSJdE{d1`D&7_dnJLV86OXf^mqwNcuJG``jyXoJjZW zZr3{~^(k$2Ot&;XHArf6NZL`NhCdo2`IGwAhg)`1AR;znzE11TN^9fi1~0zYEFOYa z&`YHGQREnEyCa*-#nl6Ys|0gnfJ9P&egG=zF6?+#aZEYO!bAl%+?XqxN)js(8C?8> z6vSqVQXIXs#bMOs%{P{EN}Tdb8;TU8+vQ3<0YqMJDA~k8eZ}uSD}r@T%APxbtKaFj ztDk{$G-vtTTVf4d>IVSZ{k{%XtTE1w@};Au4v^FA9qU{yc%3jCq$;`Kf5x;UjHoWu zH$)1M3*sK^pFRd1ys}#%>E+R$j1I*Kj`MdE;;@!L$-#|t&Y_!Q1y6*5BNtWP{lt$} zNT0`~BW!igA*vt~#Ykfv&8p$33{EUWZPkI6l?PTk_Sn2`rZGkx{1K}e_&)ypYI^UT zEUODN5)nq24uxoHA*TZN$HTjgTC*7r(HwBHruzL=!-xWSY6&i!yZGJ2b8$f;{^`4Wq5g!fH*tJ;U1a34|)GOP%$! ze2Bgl>e~PKZGClp9a^{ZFEJK((Z#>SSk9EW7bR6ya01poZH%ii8Ka}48LSi>eTBuv z{h{fz3$-_Kwc=%`7Oz~KJ-oiv4tI7Kz zH&}M6FLObgJ|Nq4d?tYvTcz%s#C5#6UwfXUlY$QJ&F5Ytz|nkY@crdBaBxr$Q7CPb z$Q46Vk4vf-$;G$bX9v*y+r^3GJZgTu?bZ~K|@fMphW8+G7Wwa3* z7^b&==3ry}8YV7aYK<0lWul?<%Mc6$t&NyBkck9o%14z$(f(6mAsgJa^18GjezkF< z!ud|h>;6-VCo1A{ex7e(j-h6<9#uQ|)68O=Z(MNhjw?9Kdgh*KDjvz~-_tMY4}PIg zGfNK*q~sJ?yWV$oT3EBKo?9)Pdp_8}fd|#vhZg#XUQ(Zwk<O-rvr{%}Wo`fe@~A7SJ&Om^bpZ!rwQnf2`_ zAYA!hYt|g?jsEiX^VgcSeS5mAxO$;9-+z~^r6&MI$>C9!lSSopXO)FOQ}Q|f>cEc& z#?ujjW_Lk*P0a0?r6xeoOa_2w_o`j~2GZahVcNKye zDJcPxl?#^lsfQnPRrepA?q>#g?1#@y^Z_Y9u!u`fbq&xR5>D9%VV3CHc>lM_^DRSpN=#DTqkv)y1?>w8%?vSTqa~U6zgpZ?hYJ-q1CU^MPk*>g-3?rslN&!5huVFSqC5;r+3TFi^8Q_IThdE`=OjM}A(&%c*i}>YZbIAH$V@$Od z$Vgy;#0n`Sg&GN$<~a&JHR`AJu|wMF`?24Npq;)-;6g55j_e=VIyjt1*&w;4p()`P zGFB&1iRIW<_@LO1nhg1r`VNu-Ro3E%R!ml_c>RujO^Joai3#lkw}s_Esc<iGKZod~isEj4O-28%_WRK2Rpj4BHSD#!NQs*{P&WbX0Z5G{>{0Y1fvU<*dW zg;gs%sD>+)oyqEBYG@2M2{l)_RW1RZ0urA2u95cciHy26je))CN!rRf+9!9;<#{i) znnYj@r-Mn4f*C~GvWu2f$96VuJ2t-5@!}TlE%)WlFd&vzTn>^`JfuAPRYBfoy zajjhp+5K0*9;7VuD3OmoCzTA#p+ATju$Yy7+?B9!Qig8&a8Hi*S@ENcIT#P~J3(U! zMJep}s5ON43#3;*zBt-P^F)Dw5C~RwToUt;d*SU&Xuz!EX=Qa2F~;ox!Ag(Z$Mt%~1j0XxH8=7b;!)`tTeO z$xJi#pQW6g;n&!{RpTAa9%q*DPO@$60C1hK3INwVFxm`$lm|~+4tfXeAA6$X$mq5Q z6DDl*ML~_-<8t!{?SCm*lMnby$r`A({_m2tDWGJnYfIDboT7nghD&rNrubhaYXbjKvKIAHvUVE4j~f6s#4Datg5mN0BEw-mFTHO@wjckcWKEmtKT6gv z2Ap_OcYl?v<^C#JTV@hbdEIrZSj+;Htf6ONFo=PCmD0X@y*Ru_7g57O&yg*yuAF>@ ztVRf>8z`_kN~V}Th%c-IZDON+G#p*g+2`|h#U?0Ww5vlck3OZ?^7d^7D}>7Mjvee3 zo)>{A>`8|A?~=7ww`I7fuS@Sx$-Bwc$y9

8RF^daTZ=KLh^^2T- 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

X{YP;DkiYo>_~#1v6p&DY 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 z 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.local type A, AAAA or ANY returns relevant IP addresses -- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses - returns .local -Answers will use the supplied TTL (in seconds) -MDNS allows UTF-8 names, but it is recommended to stay within ASCII, -since the default case-insensitive comparison assumes this. - -It is recommended to call this function after an IPv4 address has been set, -since there is currently no check if the v4 address is valid. - -Call mdns_resp_netif_settings_changed() every time the IP address -on the netif has changed. - -To stop responding on a netif, run - mdns_resp_remove_netif(struct netif *netif) - - -Adding services: -================ - -The netif first needs to be registered. Then run - mdns_resp_add_service(struct netif *netif, char *name, char *service, - u16_t proto, u16_t port, u32_t dns_ttl, - service_get_txt_fn_t txt_fn, void *txt_userdata); - -The name and service pointers will be copied. Name refers to the name of the -service instance, and service is the type of service, like _http -proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp. -If this call returns successfully, the following queries will be answered: -- _services._dns-sd._udp.local type PTR returns ..local -- ..local type PTR returns ...local -- ...local type SRV returns hostname and port of service -- ...local type TXT builds text strings by calling txt_fn - with the supplied userdata. The callback adds strings to the reply by calling - mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt, - int txt_len). Example callback method: - - static void srv_txt(struct mdns_service *service, void *txt_userdata) - { - res = mdns_resp_add_service_txtitem(service, "path=/", 6); - LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return); - } - - Since a hostname struct is used for TXT storage each single item can be max - 63 bytes long, and the total max length (including length bytes for each - item) is 255 bytes. - -If your device runs a webserver on port 80, an example call might be: - - mdns_resp_add_service(netif, "myweb", "_http" - DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL); - -which will publish myweb._http._tcp.local for any hosts looking for web servers, -and point them to .local:80 - -Relevant information will be sent as additional records to reduce number of -requests required from a client. - -Removing services is currently not supported. Services are removed when the -netif is removed. - diff --git a/components/net/lwip-2.0.2/doc/mqtt_client.txt b/components/net/lwip-2.0.2/doc/mqtt_client.txt deleted file mode 100644 index 3e67defdc5..0000000000 --- a/components/net/lwip-2.0.2/doc/mqtt_client.txt +++ /dev/null @@ -1,162 +0,0 @@ -MQTT client for lwIP - -Author: Erik Andersson - -Details of the MQTT protocol can be found at: -http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html - ------------------------------------------------------------------ -1. Initial steps, reserve memory and make connection to server: - -1.1: Provide storage - -Static allocation: - mqtt_client_t static_client; - example_do_connect(&static_client); - -Dynamic allocation: - mqtt_client_t *client = mqtt_client_new(); - if(client != NULL) { - example_do_connect(&client); - } - -1.2: Establish Connection with server - -void example_do_connect(mqtt_client_t *client) -{ - struct mqtt_connect_client_info_t ci; - err_t err; - - /* Setup an empty client info structure */ - memset(&ci, 0, sizeof(ci)); - - /* Minimal amount of information required is client identifier, so set it here */ - ci.client_id = "lwip_test"; - - /* Initiate client and connect to server, if this fails immediately an error code is returned - otherwise mqtt_connection_cb will be called with connection result after attempting - to establish a connection with the server. - For now MQTT version 3.1.1 is always used */ - - err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci); - - /* For now just print the result code if something goes wrong - if(err != ERR_OK) { - printf("mqtt_connect return %d\n", err); - } -} - -Connection to server can also be probed by calling mqtt_client_is_connected(client) - ------------------------------------------------------------------ -2. Implementing the connection status callback - - -static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) -{ - err_t err; - if(status == MQTT_CONNECT_ACCEPTED) { - printf("mqtt_connection_cb: Successfully connected\n"); - - /* Setup callback for incoming publish requests */ - mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg); - - /* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */ - err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg); - - if(err != ERR_OK) { - printf("mqtt_subscribe return: %d\n", err); - } - } else { - printf("mqtt_connection_cb: Disconnected, reason: %d\n", status); - - /* Its more nice to be connected, so try to reconnect */ - example_do_connect(client); - } -} - -static void mqtt_sub_request_cb(void *arg, err_t result) -{ - /* Just print the result code here for simplicity, - normal behaviour would be to take some action if subscribe fails like - notifying user, retry subscribe or disconnect from server */ - printf("Subscribe result: %d\n", result); -} - ------------------------------------------------------------------ -3. Implementing callbacks for incoming publish and data - -/* The idea is to demultiplex topic and create some reference to be used in data callbacks - Example here uses a global variable, better would be to use a member in arg - If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of - the topic string and use it in mqtt_incoming_data_cb -*/ -static int inpub_id; -static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) -{ - printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len); - - /* Decode topic string into a user defined reference */ - if(strcmp(topic, "print_payload") == 0) { - inpub_id = 0; - } else if(topic[0] == 'A') { - /* All topics starting with 'A' might be handled at the same way */ - inpub_id = 1; - } else { - /* For all other topics */ - inpub_id = 2; - } -} - -static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) -{ - printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags); - - if(flags & MQTT_DATA_FLAG_LAST) { - /* Last fragment of payload received (or whole part if payload fits receive buffer - See MQTT_VAR_HEADER_BUFFER_LEN) */ - - /* Call function or do action depending on reference, in this case inpub_id */ - if(inpub_id == 0) { - /* Don't trust the publisher, check zero termination */ - if(data[len-1] == 0) { - printf("mqtt_incoming_data_cb: %s\n", (const char *)data); - } - } else if(inpub_id == 1) { - /* Call an 'A' function... */ - } else { - printf("mqtt_incoming_data_cb: Ignoring payload...\n"); - } - } else { - /* Handle fragmented payload, store in buffer, write to file or whatever */ - } -} - ------------------------------------------------------------------ -4. Using outgoing publish - - -void example_publish(mqtt_client_t *client, void *arg) -{ - const char *pub_payload= "PubSubHubLubJub"; - err_t err; - u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ - u8_t retain = 0; /* No don't retain such crappy payload... */ - err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg); - if(err != ERR_OK) { - printf("Publish err: %d\n", err); - } -} - -/* Called when publish is complete either with sucess or failure */ -static void mqtt_pub_request_cb(void *arg, err_t result) -{ - if(result != ERR_OK) { - printf("Publish result: %d\n", result); - } -} - ------------------------------------------------------------------ -5. Disconnecting - -Simply call mqtt_disconnect(client) diff --git a/components/net/lwip-2.0.2/doc/ppp.txt b/components/net/lwip-2.0.2/doc/ppp.txt deleted file mode 100644 index 8b88b3a671..0000000000 --- a/components/net/lwip-2.0.2/doc/ppp.txt +++ /dev/null @@ -1,529 +0,0 @@ -PPP interface for lwIP - -Author: Sylvain Rochet - -Table of Contents: - -1 - Supported PPP protocols and features -2 - Raw API PPP example for all protocols -3 - PPPoS input path (raw API, IRQ safe API, TCPIP API) -4 - Thread safe PPP API (PPPAPI) -5 - Notify phase callback (PPP_NOTIFY_PHASE) -6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x - - - -1 Supported PPP protocols and features -====================================== - -Supported Low level protocols: -* PPP over serial using HDLC-like framing, such as wired dialup modems - or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems -* PPP over Ethernet, such as xDSL modems -* PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator), - IP tunnel over UDP, such as VPN access - -Supported auth protocols: -* PAP, Password Authentication Protocol -* CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5 -* MSCHAPv1, Microsoft version of CHAP, version 1 -* MSCHAPv2, Microsoft version of CHAP, version 2 -* EAP, Extensible Authentication Protocol - -Supported address protocols: -* IPCP, IP Control Protocol, IPv4 addresses negotiation -* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation - -Supported encryption protocols: -* MPPE, Microsoft Point-to-Point Encryption - -Supported compression or miscellaneous protocols, for serial links only: -* PFC, Protocol Field Compression -* ACFC, Address-and-Control-Field-Compression -* ACCM, Asynchronous-Control-Character-Map -* VJ, Van Jacobson TCP/IP Header Compression - - - -2 Raw API PPP example for all protocols -======================================= - -As usual, raw API for lwIP means the lightweight API which *MUST* only be used -for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems. - -/* - * Globals - * ======= - */ - -/* The PPP control block */ -ppp_pcb *ppp; - -/* The PPP IP interface */ -struct netif ppp_netif; - - -/* - * PPP status callback - * =================== - * - * PPP status callback is called on PPP status change (up, down, …) from lwIP - * core thread - */ - -/* PPP status callback example */ -static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) { - struct netif *pppif = ppp_netif(pcb); - LWIP_UNUSED_ARG(ctx); - - switch(err_code) { - case PPPERR_NONE: { -#if LWIP_DNS - const ip_addr_t *ns; -#endif /* LWIP_DNS */ - printf("status_cb: Connected\n"); -#if PPP_IPV4_SUPPORT - printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr)); - printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw)); - printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask)); -#if LWIP_DNS - ns = dns_getserver(0); - printf(" dns1 = %s\n", ipaddr_ntoa(ns)); - ns = dns_getserver(1); - printf(" dns2 = %s\n", ipaddr_ntoa(ns)); -#endif /* LWIP_DNS */ -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0))); -#endif /* PPP_IPV6_SUPPORT */ - break; - } - case PPPERR_PARAM: { - printf("status_cb: Invalid parameter\n"); - break; - } - case PPPERR_OPEN: { - printf("status_cb: Unable to open PPP session\n"); - break; - } - case PPPERR_DEVICE: { - printf("status_cb: Invalid I/O device for PPP\n"); - break; - } - case PPPERR_ALLOC: { - printf("status_cb: Unable to allocate resources\n"); - break; - } - case PPPERR_USER: { - printf("status_cb: User interrupt\n"); - break; - } - case PPPERR_CONNECT: { - printf("status_cb: Connection lost\n"); - break; - } - case PPPERR_AUTHFAIL: { - printf("status_cb: Failed authentication challenge\n"); - break; - } - case PPPERR_PROTOCOL: { - printf("status_cb: Failed to meet protocol\n"); - break; - } - case PPPERR_PEERDEAD: { - printf("status_cb: Connection timeout\n"); - break; - } - case PPPERR_IDLETIMEOUT: { - printf("status_cb: Idle Timeout\n"); - break; - } - case PPPERR_CONNECTTIME: { - printf("status_cb: Max connect time reached\n"); - break; - } - case PPPERR_LOOPBACK: { - printf("status_cb: Loopback detected\n"); - break; - } - default: { - printf("status_cb: Unknown error code %d\n", err_code); - break; - } - } - -/* - * This should be in the switch case, this is put outside of the switch - * case for example readability. - */ - - if (err_code == PPPERR_NONE) { - return; - } - - /* ppp_close() was previously called, don't reconnect */ - if (err_code == PPPERR_USER) { - /* ppp_free(); -- can be called here */ - return; - } - - /* - * Try to reconnect in 30 seconds, if you need a modem chatscript you have - * to do a much better signaling here ;-) - */ - ppp_connect(pcb, 30); - /* OR ppp_listen(pcb); */ -} - - -/* - * Creating a new PPPoS session - * ============================ - * - * In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial. - */ - -#include "netif/ppp/pppos.h" - -/* - * PPPoS serial output callback - * - * ppp_pcb, PPP control block - * data, buffer to write to serial port - * len, length of the data buffer - * ctx, optional user-provided callback context pointer - * - * Return value: len if write succeed - */ -static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) { - return uart_write(UART, data, len); -} - -/* - * Create a new PPPoS interface - * - * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface - * output_cb, PPPoS serial output callback - * status_cb, PPP status callback, called on PPP status change (up, down, …) - * ctx_cb, optional user-provided callback context pointer - */ -ppp = pppos_create(&ppp_netif, - output_cb, status_cb, ctx_cb); - - -/* - * Creating a new PPPoE session - * ============================ - */ - -#include "netif/ppp/pppoe.h" - -/* - * Create a new PPPoE interface - * - * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface - * ethif, already existing and setup Ethernet interface to use - * service_name, PPPoE service name discriminator (not supported yet) - * concentrator_name, PPPoE concentrator name discriminator (not supported yet) - * status_cb, PPP status callback, called on PPP status change (up, down, …) - * ctx_cb, optional user-provided callback context pointer - */ -ppp = pppoe_create(&ppp_netif, - ðif, - service_name, concentrator_name, - status_cb, ctx_cb); - - -/* - * Creating a new PPPoL2TP session - * =============================== - */ - -#include "netif/ppp/pppol2tp.h" - -/* - * Create a new PPPoL2TP interface - * - * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface - * netif, optional already existing and setup output netif, necessary if you - * want to set this interface as default route to settle the chicken - * and egg problem with VPN links - * ipaddr, IP to connect to - * port, UDP port to connect to (usually 1701) - * secret, L2TP secret to use - * secret_len, size in bytes of the L2TP secret - * status_cb, PPP status callback, called on PPP status change (up, down, …) - * ctx_cb, optional user-provided callback context pointer - */ -ppp = pppol2tp_create(&ppp_netif, - struct netif *netif, ip_addr_t *ipaddr, u16_t port, - u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - - -/* - * Initiate PPP client connection - * ============================== - */ - -/* Set this interface as default route */ -ppp_set_default(ppp); - -/* - * Basic PPP client configuration. Can only be set if PPP session is in the - * dead state (i.e. disconnected). We don't need to provide thread-safe - * equivalents through PPPAPI because those helpers are only changing - * structure members while session is inactive for lwIP core. Configuration - * only need to be done once. - */ - -/* Ask the peer for up to 2 DNS server addresses. */ -ppp_set_usepeerdns(ppp, 1); - -/* Auth configuration, this is pretty self-explanatory */ -ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); - -/* - * Initiate PPP negotiation, without waiting (holdoff=0), can only be called - * if PPP session is in the dead state (i.e. disconnected). - */ -u16_t holdoff = 0; -ppp_connect(ppp, holdoff); - - -/* - * Initiate PPP server listener - * ============================ - */ - -/* - * Basic PPP server configuration. Can only be set if PPP session is in the - * dead state (i.e. disconnected). We don't need to provide thread-safe - * equivalents through PPPAPI because those helpers are only changing - * structure members while session is inactive for lwIP core. Configuration - * only need to be done once. - */ -ip4_addr_t addr; - -/* Set our address */ -IP4_ADDR(&addr, 192,168,0,1); -ppp_set_ipcp_ouraddr(ppp, &addr); - -/* Set peer(his) address */ -IP4_ADDR(&addr, 192,168,0,2); -ppp_set_ipcp_hisaddr(ppp, &addr); - -/* Set primary DNS server */ -IP4_ADDR(&addr, 192,168,10,20); -ppp_set_ipcp_dnsaddr(ppp, 0, &addr); - -/* Set secondary DNS server */ -IP4_ADDR(&addr, 192,168,10,21); -ppp_set_ipcp_dnsaddr(ppp, 1, &addr); - -/* Auth configuration, this is pretty self-explanatory */ -ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password"); - -/* Require peer to authenticate */ -ppp_set_auth_required(ppp, 1); - -/* - * Only for PPPoS, the PPP session should be up and waiting for input. - * - * Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing. - * The listen call is meant for future support of PPPoE and PPPoL2TP server - * mode, where we will need to negotiate the incoming PPPoE session or L2TP - * session before initiating PPP itself. We need this call because there is - * two passive modes for PPPoS, ppp_set_passive and ppp_set_silent. - */ -ppp_set_silent(pppos, 1); - -/* - * Initiate PPP listener (i.e. wait for an incoming connection), can only - * be called if PPP session is in the dead state (i.e. disconnected). - */ -ppp_listen(ppp); - - -/* - * Closing PPP connection - * ====================== - */ - -/* - * Initiate the end of the PPP session, without carrier lost signal - * (nocarrier=0), meaning a clean shutdown of PPP protocols. - * You can call this function at anytime. - */ -u8_t nocarrier = 0; -ppp_close(ppp, nocarrier); -/* - * Then you must wait your status_cb() to be called, it may takes from a few - * seconds to several tens of seconds depending on the current PPP state. - */ - -/* - * Freeing a PPP connection - * ======================== - */ - -/* - * Free the PPP control block, can only be called if PPP session is in the - * dead state (i.e. disconnected). You need to call ppp_close() before. - */ -ppp_free(ppp); - - - -3 PPPoS input path (raw API, IRQ safe API, TCPIP API) -===================================================== - -Received data on serial port should be sent to lwIP using the pppos_input() -function or the pppos_input_tcpip() function. - -If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input() -is not IRQ safe and then *MUST* only be called inside your main loop. - -Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ -safe and can be safely called from an interrupt context, using that is going -to reduce your need of buffer if pppos_input() is called byte after byte in -your rx serial interrupt. - -if NO_SYS is 0, the thread safe way outside an interrupt context is to use -the pppos_input_tcpip() function to pass input data to the lwIP core thread -using the TCPIP API. This is thread safe in all cases but you should avoid -passing data byte after byte because it uses heavy locking (mailbox) and it -allocates pbuf, better fill them ! - -if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input() -from an RX thread, however pppos_input() is not thread safe by itself. You can -do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and -ppp_free() if pppos_input() can still be running, doing this is NOT thread safe -at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you -really know what you are doing, your move ;-) - - -/* - * Fonction to call for received data - * - * ppp, PPP control block - * buffer, input buffer - * buffer_len, buffer length in bytes - */ -void pppos_input(ppp, buffer, buffer_len); - -or - -void pppos_input_tcpip(ppp, buffer, buffer_len); - - - -4 Thread safe PPP API (PPPAPI) -============================== - -There is a thread safe API for all corresponding ppp_* functions, you have to -enable LWIP_PPP_API in your lwipopts.h file, then see -include/netif/ppp/pppapi.h, this is actually pretty obvious. - - - -5 Notify phase callback (PPP_NOTIFY_PHASE) -========================================== - -Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let -you configure a callback that is called on each PPP internal state change. -This is different from the status callback which only warns you about -up(running) and down(dead) events. - -Notify phase callback can be used, for example, to set a LED pattern depending -on the current phase of the PPP session. Here is a callback example which -tries to mimic what we usually see on xDSL modems while they are negotiating -the link, which should be self-explanatory: - -static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) { - switch (phase) { - - /* Session is down (either permanently or briefly) */ - case PPP_PHASE_DEAD: - led_set(PPP_LED, LED_OFF); - break; - - /* We are between two sessions */ - case PPP_PHASE_HOLDOFF: - led_set(PPP_LED, LED_SLOW_BLINK); - break; - - /* Session just started */ - case PPP_PHASE_INITIALIZE: - led_set(PPP_LED, LED_FAST_BLINK); - break; - - /* Session is running */ - case PPP_PHASE_RUNNING: - led_set(PPP_LED, LED_ON); - break; - - default: - break; - } -} - - - -6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x -=============================================== - -PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting -from previous lwIP version is pretty easy: - -* Previous PPP API used an integer to identify PPP sessions, we are now - using ppp_pcb* control block, therefore all functions changed from "int ppp" - to "ppp_pcb *ppp" - -* struct netif was moved outside the PPP structure, you have to provide a netif - for PPP interface in pppoX_create() functions - -* PPP session are not started automatically after you created them anymore, - you have to call ppp_connect(), this way you can configure the session before - starting it. - -* Previous PPP API used CamelCase, we are now using snake_case. - -* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore, - PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed - pppoe_, common functions are now prefixed ppp_. - -* New PPPERR_ error codes added, check you have all of them in your status - callback function - -* Only the following include files should now be used in user application: - #include "netif/ppp/pppapi.h" - #include "netif/ppp/pppos.h" - #include "netif/ppp/pppoe.h" - #include "netif/ppp/pppol2tp.h" - - Functions from ppp.h can be used, but you don't need to include this header - file as it is already included by above header files. - -* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create - your own serial rx thread - -* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed - PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above - because you might have been fooled by that - -* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use - the PPPAPI API instead. - -* ppp_sighup and ppp_close functions were merged using an optional argument - "nocarrier" on ppp_close. - -* DNS servers are now only remotely asked if LWIP_DNS is set and if - ppp_set_usepeerdns() is set to true, they are now automatically registered - using the dns_setserver() function so you don't need to do that in the PPP - callback anymore. - -* PPPoS does not use the SIO API anymore, as such it now requires a serial - output callback in place of sio_write - -* PPP_MAXIDLEFLAG is now in ms instead of jiffies diff --git a/components/net/lwip-2.0.2/doc/rawapi.txt b/components/net/lwip-2.0.2/doc/rawapi.txt deleted file mode 100644 index 0cdfdcead1..0000000000 --- a/components/net/lwip-2.0.2/doc/rawapi.txt +++ /dev/null @@ -1,499 +0,0 @@ -Raw TCP/IP interface for lwIP - -Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons - -lwIP provides three Application Program's Interfaces (APIs) for programs -to use for communication with the TCP/IP code: -* low-level "core" / "callback" or "raw" API. -* higher-level "sequential" API. -* BSD-style socket API. - -The raw API (sometimes called native API) is an event-driven API designed -to be used without an operating system that implements zero-copy send and -receive. This API is also used by the core stack for interaction between -the various protocols. It is the only API available when running lwIP -without an operating system. - -The sequential API provides a way for ordinary, sequential, programs -to use the lwIP stack. It is quite similar to the BSD socket API. The -model of execution is based on the blocking open-read-write-close -paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP -code and the application program must reside in different execution -contexts (threads). - -The socket API is a compatibility API for existing applications, -currently it is built on top of the sequential API. It is meant to -provide all functions needed to run socket API applications running -on other platforms (e.g. unix / windows etc.). However, due to limitations -in the specification of this API, there might be incompatibilities -that require small modifications of existing programs. - -** Multithreading - -lwIP started targeting single-threaded environments. When adding multi- -threading support, instead of making the core thread-safe, another -approach was chosen: there is one main thread running the lwIP core -(also known as the "tcpip_thread"). When running in a multithreaded -environment, raw API functions MUST only be called from the core thread -since raw API functions are not protected from concurrent access (aside -from pbuf- and memory management functions). Application threads using -the sequential- or socket API communicate with this main thread through -message passing. - - As such, the list of functions that may be called from - other threads or an ISR is very limited! Only functions - from these API header files are thread-safe: - - api.h - - netbuf.h - - netdb.h - - netifapi.h - - pppapi.h - - sockets.h - - sys.h - - Additionaly, memory (de-)allocation functions may be - called from multiple threads (not ISR!) with NO_SYS=0 - since they are protected by SYS_LIGHTWEIGHT_PROT and/or - semaphores. - - Netconn or Socket API functions are thread safe against the - core thread but they are not reentrant at the control block - granularity level. That is, a UDP or TCP control block must - not be shared among multiple threads without proper locking. - - If SYS_LIGHTWEIGHT_PROT is set to 1 and - LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, - pbuf_free() may also be called from another thread or - an ISR (since only then, mem_free - for PBUF_RAM - may - be called from an ISR: otherwise, the HEAP is only - protected by semaphores). - - -** The remainder of this document discusses the "raw" API. ** - -The raw TCP/IP interface allows the application program to integrate -better with the TCP/IP code. Program execution is event based by -having callback functions being called from within the TCP/IP -code. The TCP/IP code and the application program both run in the same -thread. The sequential API has a much higher overhead and is not very -well suited for small systems since it forces a multithreaded paradigm -on the application. - -The raw TCP/IP interface is not only faster in terms of code execution -time but is also less memory intensive. The drawback is that program -development is somewhat harder and application programs written for -the raw TCP/IP interface are more difficult to understand. Still, this -is the preferred way of writing applications that should be small in -code size and memory usage. - -All APIs can be used simultaneously by different application -programs. In fact, the sequential API is implemented as an application -program using the raw TCP/IP interface. - -Do not confuse the lwIP raw API with raw Ethernet or IP sockets. -The former is a way of interfacing the lwIP network stack (including -TCP and UDP), the later refers to processing raw Ethernet or IP data -instead of TCP connections or UDP packets. - -Raw API applications may never block since all packet processing -(input and output) as well as timer processing (TCP mainly) is done -in a single execution context. - ---- Callbacks - -Program execution is driven by callbacks functions, which are then -invoked by the lwIP core when activity related to that application -occurs. A particular application may register to be notified via a -callback function for events such as incoming data available, outgoing -data sent, error notifications, poll timer expiration, connection -closed, etc. An application can provide a callback function to perform -processing for any or all of these events. Each callback is an ordinary -C function that is called from within the TCP/IP code. Every callback -function is passed the current TCP or UDP connection state as an -argument. Also, in order to be able to keep program specific state, -the callback functions are called with a program specified argument -that is independent of the TCP/IP state. - -The function for setting the application connection state is: - -- void tcp_arg(struct tcp_pcb *pcb, void *arg) - - Specifies the program specific state that should be passed to all - other callback functions. The "pcb" argument is the current TCP - connection control block, and the "arg" argument is the argument - that will be passed to the callbacks. - - ---- TCP connection setup - -The functions used for setting up connections is similar to that of -the sequential API and of the BSD socket API. A new TCP connection -identifier (i.e., a protocol control block - PCB) is created with the -tcp_new() function. This PCB can then be either set to listen for new -incoming connections or be explicitly connected to another host. - -- struct tcp_pcb *tcp_new(void) - - Creates a new connection identifier (PCB). If memory is not - available for creating the new pcb, NULL is returned. - -- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port) - - Binds the pcb to a local IP address and port number. The IP address - can be specified as IP_ADDR_ANY in order to bind the connection to - all local IP addresses. - - If another connection is bound to the same port, the function will - return ERR_USE, otherwise ERR_OK is returned. - -- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb) - - Commands a pcb to start listening for incoming connections. When an - incoming connection is accepted, the function specified with the - tcp_accept() function will be called. The pcb will have to be bound - to a local port with the tcp_bind() function. - - The tcp_listen() function returns a new connection identifier, and - the one passed as an argument to the function will be - deallocated. The reason for this behavior is that less memory is - needed for a connection that is listening, so tcp_listen() will - reclaim the memory needed for the original connection and allocate a - new smaller memory block for the listening connection. - - tcp_listen() may return NULL if no memory was available for the - listening connection. If so, the memory associated with the pcb - passed as an argument to tcp_listen() will not be deallocated. - -- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) - - Same as tcp_listen, but limits the number of outstanding connections - in the listen queue to the value specified by the backlog argument. - To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h. - -- void tcp_accept(struct tcp_pcb *pcb, - err_t (* accept)(void *arg, struct tcp_pcb *newpcb, - err_t err)) - - Specified the callback function that should be called when a new - connection arrives on a listening connection. - -- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port, err_t (* connected)(void *arg, - struct tcp_pcb *tpcb, - err_t err)); - - Sets up the pcb to connect to the remote host and sends the - initial SYN segment which opens the connection. - - The tcp_connect() function returns immediately; it does not wait for - the connection to be properly setup. Instead, it will call the - function specified as the fourth argument (the "connected" argument) - when the connection is established. If the connection could not be - properly established, either because the other host refused the - connection or because the other host didn't answer, the "err" - callback function of this pcb (registered with tcp_err, see below) - will be called. - - The tcp_connect() function can return ERR_MEM if no memory is - available for enqueueing the SYN segment. If the SYN indeed was - enqueued successfully, the tcp_connect() function returns ERR_OK. - - ---- Sending TCP data - -TCP data is sent by enqueueing the data with a call to -tcp_write(). When the data is successfully transmitted to the remote -host, the application will be notified with a call to a specified -callback function. - -- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, - u8_t apiflags) - - Enqueues the data pointed to by the argument dataptr. The length of - the data is passed as the len parameter. The apiflags can be one or more of: - - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated - for the data to be copied into. If this flag is not given, no new memory - should be allocated and the data should only be referenced by pointer. This - also means that the memory behind dataptr must not change until the data is - ACKed by the remote host - - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is omitted, - the PSH flag is set in the last segment created by this call to tcp_write. - If this flag is given, the PSH flag is not set. - - The tcp_write() function will fail and return ERR_MEM if the length - of the data exceeds the current send buffer size or if the length of - the queue of outgoing segment is larger than the upper limit defined - in lwipopts.h. The number of bytes available in the output queue can - be retrieved with the tcp_sndbuf() function. - - The proper way to use this function is to call the function with at - most tcp_sndbuf() bytes of data. If the function returns ERR_MEM, - the application should wait until some of the currently enqueued - data has been successfully received by the other host and try again. - -- void tcp_sent(struct tcp_pcb *pcb, - err_t (* sent)(void *arg, struct tcp_pcb *tpcb, - u16_t len)) - - Specifies the callback function that should be called when data has - successfully been received (i.e., acknowledged) by the remote - host. The len argument passed to the callback function gives the - amount bytes that was acknowledged by the last acknowledgment. - - ---- Receiving TCP data - -TCP data reception is callback based - an application specified -callback function is called when new data arrives. When the -application has taken the data, it has to call the tcp_recved() -function to indicate that TCP can advertise increase the receive -window. - -- void tcp_recv(struct tcp_pcb *pcb, - err_t (* recv)(void *arg, struct tcp_pcb *tpcb, - struct pbuf *p, err_t err)) - - Sets the callback function that will be called when new data - arrives. The callback function will be passed a NULL pbuf to - indicate that the remote host has closed the connection. If - there are no errors and the callback function is to return - ERR_OK, then it must free the pbuf. Otherwise, it must not - free the pbuf so that lwIP core code can store it. - -- void tcp_recved(struct tcp_pcb *pcb, u16_t len) - - Must be called when the application has received the data. The len - argument indicates the length of the received data. - - ---- Application polling - -When a connection is idle (i.e., no data is either transmitted or -received), lwIP will repeatedly poll the application by calling a -specified callback function. This can be used either as a watchdog -timer for killing connections that have stayed idle for too long, or -as a method of waiting for memory to become available. For instance, -if a call to tcp_write() has failed because memory wasn't available, -the application may use the polling functionality to call tcp_write() -again when the connection has been idle for a while. - -- void tcp_poll(struct tcp_pcb *pcb, - err_t (* poll)(void *arg, struct tcp_pcb *tpcb), - u8_t interval) - - Specifies the polling interval and the callback function that should - be called to poll the application. The interval is specified in - number of TCP coarse grained timer shots, which typically occurs - twice a second. An interval of 10 means that the application would - be polled every 5 seconds. - - ---- Closing and aborting connections - -- err_t tcp_close(struct tcp_pcb *pcb) - - Closes the connection. The function may return ERR_MEM if no memory - was available for closing the connection. If so, the application - should wait and try again either by using the acknowledgment - callback or the polling functionality. If the close succeeds, the - function returns ERR_OK. - - The pcb is deallocated by the TCP code after a call to tcp_close(). - -- void tcp_abort(struct tcp_pcb *pcb) - - Aborts the connection by sending a RST (reset) segment to the remote - host. The pcb is deallocated. This function never fails. - - ATTENTION: When calling this from one of the TCP callbacks, make - sure you always return ERR_ABRT (and never return ERR_ABRT otherwise - or you will risk accessing deallocated memory or memory leaks! - - -If a connection is aborted because of an error, the application is -alerted of this event by the err callback. Errors that might abort a -connection are when there is a shortage of memory. The callback -function to be called is set using the tcp_err() function. - -- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, - err_t err)) - - The error callback function does not get the pcb passed to it as a - parameter since the pcb may already have been deallocated. - - ---- UDP interface - -The UDP interface is similar to that of TCP, but due to the lower -level of complexity of UDP, the interface is significantly simpler. - -- struct udp_pcb *udp_new(void) - - Creates a new UDP pcb which can be used for UDP communication. The - pcb is not active until it has either been bound to a local address - or connected to a remote address. - -- void udp_remove(struct udp_pcb *pcb) - - Removes and deallocates the pcb. - -- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port) - - Binds the pcb to a local address. The IP-address argument "ipaddr" - can be IP_ADDR_ANY to indicate that it should listen to any local IP - address. The function currently always return ERR_OK. - -- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, - u16_t port) - - Sets the remote end of the pcb. This function does not generate any - network traffic, but only set the remote address of the pcb. - -- err_t udp_disconnect(struct udp_pcb *pcb) - - Remove the remote end of the pcb. This function does not generate - any network traffic, but only removes the remote address of the pcb. - -- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p) - - Sends the pbuf p. The pbuf is not deallocated. - -- void udp_recv(struct udp_pcb *pcb, - void (* recv)(void *arg, struct udp_pcb *upcb, - struct pbuf *p, - ip_addr_t *addr, - u16_t port), - void *recv_arg) - - Specifies a callback function that should be called when a UDP - datagram is received. - - ---- System initalization - -A truly complete and generic sequence for initializing the lwIP stack -cannot be given because it depends on additional initializations for -your runtime environment (e.g. timers). - -We can give you some idea on how to proceed when using the raw API. -We assume a configuration using a single Ethernet netif and the -UDP and TCP transport layers, IPv4 and the DHCP client. - -Call these functions in the order of appearance: - -- lwip_init() - - Initialize the lwIP stack and all of its subsystems. - -- netif_add(struct netif *netif, const ip4_addr_t *ipaddr, - const ip4_addr_t *netmask, const ip4_addr_t *gw, - void *state, netif_init_fn init, netif_input_fn input) - - Adds your network interface to the netif_list. Allocate a struct - netif and pass a pointer to this structure as the first argument. - Give pointers to cleared ip_addr structures when using DHCP, - or fill them with sane numbers otherwise. The state pointer may be NULL. - - The init function pointer must point to a initialization function for - your Ethernet netif interface. The following code illustrates its use. - - err_t netif_if_init(struct netif *netif) - { - u8_t i; - - for (i = 0; i < ETHARP_HWADDR_LEN; i++) { - netif->hwaddr[i] = some_eth_addr[i]; - } - init_my_eth_device(); - return ERR_OK; - } - - For Ethernet drivers, the input function pointer must point to the lwIP - function ethernet_input() declared in "netif/etharp.h". Other drivers - must use ip_input() declared in "lwip/ip.h". - -- netif_set_default(struct netif *netif) - - Registers the default network interface. - -- netif_set_link_up(struct netif *netif) - - This is the hardware link state; e.g. whether cable is plugged for wired - Ethernet interface. This function must be called even if you don't know - the current state. Having link up and link down events is optional but - DHCP and IPv6 discover benefit well from those events. - -- netif_set_up(struct netif *netif) - - This is the administrative (= software) state of the netif, when the - netif is fully configured this function must be called. - -- dhcp_start(struct netif *netif) - - Creates a new DHCP client for this interface on the first call. - - You can peek in the netif->dhcp struct for the actual DHCP status. - -- sys_check_timeouts() - - When the system is running, you have to periodically call - sys_check_timeouts() which will handle all timers for all protocols in - the stack; add this to your main loop or equivalent. - - ---- Optimalization hints - -The first thing you want to optimize is the lwip_standard_checksum() -routine from src/core/inet.c. You can override this standard -function with the #define LWIP_CHKSUM . - -There are C examples given in inet.c or you might want to -craft an assembly function for this. RFC1071 is a good -introduction to this subject. - -Other significant improvements can be made by supplying -assembly or inline replacements for htons() and htonl() -if you're using a little-endian architecture. -#define lwip_htons(x) -#define lwip_htonl(x) -If you #define them to htons() and htonl(), you should -#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from -defining hton*/ntoh* compatibility macros. - -Check your network interface driver if it reads at -a higher speed than the maximum wire-speed. If the -hardware isn't serviced frequently and fast enough -buffer overflows are likely to occur. - -E.g. when using the cs8900 driver, call cs8900if_service(ethif) -as frequently as possible. When using an RTOS let the cs8900 interrupt -wake a high priority task that services your driver using a binary -semaphore or event flag. Some drivers might allow additional tuning -to match your application and network. - -For a production release it is recommended to set LWIP_STATS to 0. -Note that speed performance isn't influenced much by simply setting -high values to the memory options. - -For more optimization hints take a look at the lwIP wiki. - ---- Zero-copy MACs - -To achieve zero-copy on transmit, the data passed to the raw API must -remain unchanged until sent. Because the send- (or write-)functions return -when the packets have been enqueued for sending, data must be kept stable -after that, too. - -This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions -must *not* be reused by the application unless their ref-count is 1. - -For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too, -but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while -PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change). - -Also, data passed to tcp_write without the copy-flag must not be changed! - -Therefore, be careful which type of PBUF you use and if you copy TCP data -or not! diff --git a/components/net/lwip-2.0.2/doc/savannah.txt b/components/net/lwip-2.0.2/doc/savannah.txt deleted file mode 100644 index d7d19eb6eb..0000000000 --- a/components/net/lwip-2.0.2/doc/savannah.txt +++ /dev/null @@ -1,120 +0,0 @@ -Daily Use Guide for using Savannah for lwIP - -Table of Contents: - -1 - Obtaining lwIP from the Git repository -2 - Committers/developers Git access using SSH -3 - Merging a development branch to master branch -4 - How to release lwIP - - - -1 Obtaining lwIP from the Git repository ----------------------------------------- - -To perform an anonymous Git clone of the master branch (this is where -bug fixes and incremental enhancements occur), do this: - git clone git://git.savannah.nongnu.org/lwip.git - -Or, obtain a stable branch (updated with bug fixes only) as follows: - git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git - -Or, obtain a specific (fixed) release as follows: - git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git - - -2 Committers/developers Git access using SSH --------------------------------------------- - -The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption. -As such, Git commits to the server occur through a SSH tunnel for project members. -To create a SSH2 key pair in UNIX-like environments, do this: - ssh-keygen -t dsa - -Under Windows, a recommended SSH client is "PuTTY", freely available with good -documentation and a graphic user interface. Use its key generator. - -Now paste the id_dsa.pub contents into your Savannah account public key list. Wait -a while so that Savannah can update its configuration (This can take minutes). - -Try to login using SSH: - ssh -v your_login@git.sv.gnu.org - -If it tells you: - Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686 - - Interactive shell login is not possible for security reasons. - VCS commands are allowed. - Last login: Tue May 15 23:10:12 2012 from 82.245.102.129 - You tried to execute: - Sorry, you are not allowed to execute that command. - Shared connection to git.sv.gnu.org closed. - -then you could login; Savannah refuses to give you a shell - which is OK, as we -are allowed to use SSH for Git only. Now, you should be able to do this: - git clone your_login@git.sv.gnu.org:/srv/git/lwip.git - -After which you can edit your local files with bug fixes or new features and -commit them. Make sure you know what you are doing when using Git to make -changes on the repository. If in doubt, ask on the lwip-members mailing list. - -(If SSH asks about authenticity of the host, you can check the key -fingerprint against https://savannah.nongnu.org/git/?group=lwip - - -3 - Merging a development branch to master branch -------------------------------------------------- - -Merging is a straightforward process in Git. How to merge all changes in a -development branch since our last merge from main: - -Checkout the master branch: - git checkout master - -Merge the development branch to master: - git merge your-development-branch - -Resolve any conflict. - -Commit the merge result. - git commit -a - -Push your commits: - git push - - -4 How to release lwIP ---------------------- - -First, tag the release using Git: (I use release number 1.4.1 throughout -this example). - git tag -a STABLE-1_4_1 - -Share the tag reference by pushing it to remote: - git push origin STABLE-1_4_1 - -Prepare the release: - cp -r lwip lwip-1.4.1 - rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes - -Archive the current directory using tar, gzip'd, bzip2'd and zip'd. - tar czvf lwip-1.4.1.tar.gz lwip-1.4.1 - tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1 - zip -r lwip-1.4.1.zip lwip-1.4.1 - -Now, sign the archives with a detached GPG binary signature as follows: - gpg -b lwip-1.4.1.tar.gz - gpg -b lwip-1.4.1.tar.bz2 - gpg -b lwip-1.4.1.zip - -Upload these files using anonymous FTP: - ncftp ftp://savannah.gnu.org/incoming/savannah/lwip - ncftp> mput *1.4.1.* - -Additionally, you may post a news item on Savannah, like this: - -A new 1.4.1 release is now available here: -http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1 - -You will have to submit this via the user News interface, then approve -this via the Administrator News interface. diff --git a/components/net/lwip-2.0.2/doc/sys_arch.txt b/components/net/lwip-2.0.2/doc/sys_arch.txt deleted file mode 100644 index 4dc727b657..0000000000 --- a/components/net/lwip-2.0.2/doc/sys_arch.txt +++ /dev/null @@ -1,303 +0,0 @@ -sys_arch interface for lwIP - -Author: Adam Dunkels - Simon Goldschmidt - -The operating system emulation layer provides a common interface -between the lwIP code and the underlying operating system kernel. The -general idea is that porting lwIP to new architectures requires only -small changes to a few header files and a new sys_arch -implementation. It is also possible to do a sys_arch implementation -that does not rely on any underlying operating system. - -The sys_arch provides semaphores, mailboxes and mutexes to lwIP. For the full -lwIP functionality, multiple threads support can be implemented in the -sys_arch, but this is not required for the basic lwIP -functionality. Timer scheduling is implemented in lwIP, but can be implemented -by the sys_arch port (LWIP_TIMERS_CUSTOM==1). - -In addition to the source file providing the functionality of sys_arch, -the OS emulation layer must provide several header files defining -macros used throughout lwip. The files required and the macros they -must define are listed below the sys_arch description. - -Semaphores can be either counting or binary - lwIP works with both -kinds. Mailboxes should be implemented as a queue which allows multiple messages -to be posted (implementing as a rendez-vous point where only one message can be -posted at a time can have a highly negative impact on performance). A message -in a mailbox is just a pointer, nothing more. - -Semaphores are represented by the type "sys_sem_t" which is typedef'd -in the sys_arch.h file. Mailboxes are equivalently represented by the -type "sys_mbox_t". Mutexes are represented by the type "sys_mutex_t". -lwIP does not place any restrictions on how these types are represented -internally. - -Since lwIP 1.4.0, semaphore, mutexes and mailbox functions are prototyped in a way that -allows both using pointers or actual OS structures to be used. This way, memory -required for such types can be either allocated in place (globally or on the -stack) or on the heap (allocated internally in the "*_new()" functions). - -The following functions must be implemented by the sys_arch: - -- void sys_init(void) - - Is called to initialize the sys_arch layer. - -- err_t sys_sem_new(sys_sem_t *sem, u8_t count) - - Creates a new semaphore. The semaphore is allocated to the memory that 'sem' - points to (which can be both a pointer or the actual OS structure). - The "count" argument specifies the initial state of the semaphore (which is - either 0 or 1). - If the semaphore has been created, ERR_OK should be returned. Returning any - other error will provide a hint what went wrong, but except for assertions, - no real error handling is implemented. - -- void sys_sem_free(sys_sem_t *sem) - - Deallocates a semaphore. - -- void sys_sem_signal(sys_sem_t *sem) - - Signals a semaphore. - -- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) - - Blocks the thread while waiting for the semaphore to be - signaled. If the "timeout" argument is non-zero, the thread should - only be blocked for the specified time (measured in - milliseconds). If the "timeout" argument is zero, the thread should be - blocked until the semaphore is signalled. - - If the timeout argument is non-zero, the return value is the number of - milliseconds spent waiting for the semaphore to be signaled. If the - semaphore wasn't signaled within the specified time, the return value is - SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore - (i.e., it was already signaled), the function may return zero. - - Notice that lwIP implements a function with a similar name, - sys_sem_wait(), that uses the sys_arch_sem_wait() function. - -- int sys_sem_valid(sys_sem_t *sem) - - Returns 1 if the semaphore is valid, 0 if it is not valid. - When using pointers, a simple way is to check the pointer for != NULL. - When directly using OS structures, implementing this may be more complex. - This may also be a define, in which case the function is not prototyped. - -- void sys_sem_set_invalid(sys_sem_t *sem) - - Invalidate a semaphore so that sys_sem_valid() returns 0. - ATTENTION: This does NOT mean that the semaphore shall be deallocated: - sys_sem_free() is always called before calling this function! - This may also be a define, in which case the function is not prototyped. - -- void sys_mutex_new(sys_mutex_t *mutex) - - Creates a new mutex. The mutex is allocated to the memory that 'mutex' - points to (which can be both a pointer or the actual OS structure). - If the mutex has been created, ERR_OK should be returned. Returning any - other error will provide a hint what went wrong, but except for assertions, - no real error handling is implemented. - -- void sys_mutex_free(sys_mutex_t *mutex) - - Deallocates a mutex. - -- void sys_mutex_lock(sys_mutex_t *mutex) - - Blocks the thread until the mutex can be grabbed. - -- void sys_mutex_unlock(sys_mutex_t *mutex) - - Releases the mutex previously locked through 'sys_mutex_lock()'. - -- void sys_mutex_valid(sys_mutex_t *mutex) - - Returns 1 if the mutes is valid, 0 if it is not valid. - When using pointers, a simple way is to check the pointer for != NULL. - When directly using OS structures, implementing this may be more complex. - This may also be a define, in which case the function is not prototyped. - -- void sys_mutex_set_invalid(sys_mutex_t *mutex) - - Invalidate a mutex so that sys_mutex_valid() returns 0. - ATTENTION: This does NOT mean that the mutex shall be deallocated: - sys_mutex_free() is always called before calling this function! - This may also be a define, in which case the function is not prototyped. - -- err_t sys_mbox_new(sys_mbox_t *mbox, int size) - - Creates an empty mailbox for maximum "size" elements. Elements stored - in mailboxes are pointers. You have to define macros "_MBOX_SIZE" - in your lwipopts.h, or ignore this parameter in your implementation - and use a default size. - If the mailbox has been created, ERR_OK should be returned. Returning any - other error will provide a hint what went wrong, but except for assertions, - no real error handling is implemented. - -- void sys_mbox_free(sys_mbox_t *mbox) - - Deallocates a mailbox. If there are messages still present in the - mailbox when the mailbox is deallocated, it is an indication of a - programming error in lwIP and the developer should be notified. - -- void sys_mbox_post(sys_mbox_t *mbox, void *msg) - - Posts the "msg" to the mailbox. This function have to block until - the "msg" is really posted. - -- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) - - Try to post the "msg" to the mailbox. Returns ERR_MEM if this one - is full, else, ERR_OK if the "msg" is posted. - -- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) - - Blocks the thread until a message arrives in the mailbox, but does - not block the thread longer than "timeout" milliseconds (similar to - the sys_arch_sem_wait() function). If "timeout" is 0, the thread should - be blocked until a message arrives. The "msg" argument is a result - parameter that is set by the function (i.e., by doing "*msg = - ptr"). The "msg" parameter maybe NULL to indicate that the message - should be dropped. - - The return values are the same as for the sys_arch_sem_wait() function: - Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a - timeout. - - Note that a function with a similar name, sys_mbox_fetch(), is - implemented by lwIP. - -- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) - - This is similar to sys_arch_mbox_fetch, however if a message is not - present in the mailbox, it immediately returns with the code - SYS_MBOX_EMPTY. On success 0 is returned. - - To allow for efficient implementations, this can be defined as a - function-like macro in sys_arch.h instead of a normal function. For - example, a naive implementation could be: - #define sys_arch_mbox_tryfetch(mbox,msg) \ - sys_arch_mbox_fetch(mbox,msg,1) - although this would introduce unnecessary delays. - -- int sys_mbox_valid(sys_mbox_t *mbox) - - Returns 1 if the mailbox is valid, 0 if it is not valid. - When using pointers, a simple way is to check the pointer for != NULL. - When directly using OS structures, implementing this may be more complex. - This may also be a define, in which case the function is not prototyped. - -- void sys_mbox_set_invalid(sys_mbox_t *mbox) - - Invalidate a mailbox so that sys_mbox_valid() returns 0. - ATTENTION: This does NOT mean that the mailbox shall be deallocated: - sys_mbox_free() is always called before calling this function! - This may also be a define, in which case the function is not prototyped. - -If threads are supported by the underlying operating system and if -such functionality is needed in lwIP, the following function will have -to be implemented as well: - -- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) - - Starts a new thread named "name" with priority "prio" that will begin its - execution in the function "thread()". The "arg" argument will be passed as an - argument to the thread() function. The stack size to used for this thread is - the "stacksize" parameter. The id of the new thread is returned. Both the id - and the priority are system dependent. - -When lwIP is used from more than one context (e.g. from multiple threads OR from -main-loop and from interrupts), the SYS_LIGHTWEIGHT_PROT protection SHOULD be enabled! - -- sys_prot_t sys_arch_protect(void) - - This optional function does a "fast" critical region protection and returns - the previous protection level. This function is only called during very short - critical regions. An embedded system which supports ISR-based drivers might - want to implement this function by disabling interrupts. Task-based systems - might want to implement this by using a mutex or disabling tasking. This - function should support recursive calls from the same task or interrupt. In - other words, sys_arch_protect() could be called while already protected. In - that case the return value indicates that it is already protected. - - sys_arch_protect() is only required if your port is supporting an operating - system. - -- void sys_arch_unprotect(sys_prot_t pval) - - This optional function does a "fast" set of critical region protection to the - value specified by pval. See the documentation for sys_arch_protect() for - more information. This function is only required if your port is supporting - an operating system. - -For some configurations, you also need: - -- u32_t sys_now(void) - - This optional function returns the current time in milliseconds (don't care - for wraparound, this is only used for time diffs). - Not implementing this function means you cannot use some modules (e.g. TCP - timestamps, internal timeouts for NO_SYS==1). - - -Note: - -Be careful with using mem_malloc() in sys_arch. When malloc() refers to -mem_malloc() you can run into a circular function call problem. In mem.c -mem_init() tries to allcate a semaphore using mem_malloc, which of course -can't be performed when sys_arch uses mem_malloc. - -------------------------------------------------------------------------------- -Additional files required for the "OS support" emulation layer: -------------------------------------------------------------------------------- - -cc.h - Architecture environment, some compiler specific, some - environment specific (probably should move env stuff - to sys_arch.h.) - - Typedefs for the types used by lwip - - u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t - - Compiler hints for packing lwip's structures - - PACK_STRUCT_FIELD(x) - PACK_STRUCT_STRUCT - PACK_STRUCT_BEGIN - PACK_STRUCT_END - - Platform specific diagnostic output - - LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. - LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. - Portability defines for printf formatters: - U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F - - "lightweight" synchronization mechanisms - - SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. - SYS_ARCH_PROTECT(x) - enter protection mode. - SYS_ARCH_UNPROTECT(x) - leave protection mode. - - If the compiler does not provide memset() this file must include a - definition of it, or include a file which defines it. - - This file must either include a system-local which defines - the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO - to make lwip/arch.h define the codes which are used throughout. - - -perf.h - Architecture specific performance measurement. - Measurement calls made throughout lwip, these can be defined to nothing. - PERF_START - start measuring something. - PERF_STOP(x) - stop measuring something, and record the result. - -sys_arch.h - Tied to sys_arch.c - - Arch dependent types for the following objects: - sys_sem_t, sys_mbox_t, sys_thread_t, - And, optionally: - sys_prot_t - - Defines to set vars of sys_mbox_t and sys_sem_t to NULL. - SYS_MBOX_NULL NULL - SYS_SEM_NULL NULL diff --git a/components/net/lwip-2.0.2/src/FILES b/components/net/lwip-2.0.2/src/FILES deleted file mode 100644 index 0be0741d08..0000000000 --- a/components/net/lwip-2.0.2/src/FILES +++ /dev/null @@ -1,15 +0,0 @@ -api/ - The code for the high-level wrapper API. Not needed if - you use the lowel-level call-back/raw API. - -apps/ - Higher layer applications that are specifically programmed - with the lwIP low-level raw API. - -core/ - The core of the TPC/IP stack; protocol implementations, - memory and buffer management, and the low-level raw API. - -include/ - lwIP include files. - -netif/ - Generic network interface device drivers are kept here. - -For more information on the various subdirectories, check the FILES -file in each directory. diff --git a/components/net/lwip-2.0.2/src/Filelists.mk b/components/net/lwip-2.0.2/src/Filelists.mk deleted file mode 100644 index 7d30bb8f53..0000000000 --- a/components/net/lwip-2.0.2/src/Filelists.mk +++ /dev/null @@ -1,181 +0,0 @@ -# -# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -# OF SUCH DAMAGE. -# -# This file is part of the lwIP TCP/IP stack. -# -# Author: Adam Dunkels -# - -# COREFILES, CORE4FILES: The minimum set of files needed for lwIP. -COREFILES=$(LWIPDIR)/core/init.c \ - $(LWIPDIR)/core/def.c \ - $(LWIPDIR)/core/dns.c \ - $(LWIPDIR)/core/inet_chksum.c \ - $(LWIPDIR)/core/ip.c \ - $(LWIPDIR)/core/mem.c \ - $(LWIPDIR)/core/memp.c \ - $(LWIPDIR)/core/netif.c \ - $(LWIPDIR)/core/pbuf.c \ - $(LWIPDIR)/core/raw.c \ - $(LWIPDIR)/core/stats.c \ - $(LWIPDIR)/core/sys.c \ - $(LWIPDIR)/core/tcp.c \ - $(LWIPDIR)/core/tcp_in.c \ - $(LWIPDIR)/core/tcp_out.c \ - $(LWIPDIR)/core/timeouts.c \ - $(LWIPDIR)/core/udp.c - -CORE4FILES=$(LWIPDIR)/core/ipv4/autoip.c \ - $(LWIPDIR)/core/ipv4/dhcp.c \ - $(LWIPDIR)/core/ipv4/etharp.c \ - $(LWIPDIR)/core/ipv4/icmp.c \ - $(LWIPDIR)/core/ipv4/igmp.c \ - $(LWIPDIR)/core/ipv4/ip4_frag.c \ - $(LWIPDIR)/core/ipv4/ip4.c \ - $(LWIPDIR)/core/ipv4/ip4_addr.c - -CORE6FILES=$(LWIPDIR)/core/ipv6/dhcp6.c \ - $(LWIPDIR)/core/ipv6/ethip6.c \ - $(LWIPDIR)/core/ipv6/icmp6.c \ - $(LWIPDIR)/core/ipv6/inet6.c \ - $(LWIPDIR)/core/ipv6/ip6.c \ - $(LWIPDIR)/core/ipv6/ip6_addr.c \ - $(LWIPDIR)/core/ipv6/ip6_frag.c \ - $(LWIPDIR)/core/ipv6/mld6.c \ - $(LWIPDIR)/core/ipv6/nd6.c - -# APIFILES: The files which implement the sequential and socket APIs. -APIFILES=$(LWIPDIR)/api/api_lib.c \ - $(LWIPDIR)/api/api_msg.c \ - $(LWIPDIR)/api/err.c \ - $(LWIPDIR)/api/netbuf.c \ - $(LWIPDIR)/api/netdb.c \ - $(LWIPDIR)/api/netifapi.c \ - $(LWIPDIR)/api/sockets.c \ - $(LWIPDIR)/api/tcpip.c - -# NETIFFILES: Files implementing various generic network interface functions -NETIFFILES=$(LWIPDIR)/netif/ethernet.c \ - $(LWIPDIR)/netif/slipif.c - -# SIXLOWPAN: 6LoWPAN -SIXLOWPAN=$(LWIPDIR)/netif/lowpan6.c \ - -# PPPFILES: PPP -PPPFILES=$(LWIPDIR)/netif/ppp/auth.c \ - $(LWIPDIR)/netif/ppp/ccp.c \ - $(LWIPDIR)/netif/ppp/chap-md5.c \ - $(LWIPDIR)/netif/ppp/chap_ms.c \ - $(LWIPDIR)/netif/ppp/chap-new.c \ - $(LWIPDIR)/netif/ppp/demand.c \ - $(LWIPDIR)/netif/ppp/eap.c \ - $(LWIPDIR)/netif/ppp/ecp.c \ - $(LWIPDIR)/netif/ppp/eui64.c \ - $(LWIPDIR)/netif/ppp/fsm.c \ - $(LWIPDIR)/netif/ppp/ipcp.c \ - $(LWIPDIR)/netif/ppp/ipv6cp.c \ - $(LWIPDIR)/netif/ppp/lcp.c \ - $(LWIPDIR)/netif/ppp/magic.c \ - $(LWIPDIR)/netif/ppp/mppe.c \ - $(LWIPDIR)/netif/ppp/multilink.c \ - $(LWIPDIR)/netif/ppp/ppp.c \ - $(LWIPDIR)/netif/ppp/pppapi.c \ - $(LWIPDIR)/netif/ppp/pppcrypt.c \ - $(LWIPDIR)/netif/ppp/pppoe.c \ - $(LWIPDIR)/netif/ppp/pppol2tp.c \ - $(LWIPDIR)/netif/ppp/pppos.c \ - $(LWIPDIR)/netif/ppp/upap.c \ - $(LWIPDIR)/netif/ppp/utils.c \ - $(LWIPDIR)/netif/ppp/vj.c \ - $(LWIPDIR)/netif/ppp/polarssl/arc4.c \ - $(LWIPDIR)/netif/ppp/polarssl/des.c \ - $(LWIPDIR)/netif/ppp/polarssl/md4.c \ - $(LWIPDIR)/netif/ppp/polarssl/md5.c \ - $(LWIPDIR)/netif/ppp/polarssl/sha1.c - -# LWIPNOAPPSFILES: All LWIP files without apps -LWIPNOAPPSFILES=$(COREFILES) \ - $(CORE4FILES) \ - $(CORE6FILES) \ - $(APIFILES) \ - $(NETIFFILES) \ - $(PPPFILES) \ - $(SIXLOWPAN) - -# SNMPFILES: SNMPv2c agent -SNMPFILES=$(LWIPDIR)/apps/snmp/snmp_asn1.c \ - $(LWIPDIR)/apps/snmp/snmp_core.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_icmp.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_interfaces.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_ip.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_snmp.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_system.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_tcp.c \ - $(LWIPDIR)/apps/snmp/snmp_mib2_udp.c \ - $(LWIPDIR)/apps/snmp/snmp_msg.c \ - $(LWIPDIR)/apps/snmp/snmpv3.c \ - $(LWIPDIR)/apps/snmp/snmp_netconn.c \ - $(LWIPDIR)/apps/snmp/snmp_pbuf_stream.c \ - $(LWIPDIR)/apps/snmp/snmp_raw.c \ - $(LWIPDIR)/apps/snmp/snmp_scalar.c \ - $(LWIPDIR)/apps/snmp/snmp_table.c \ - $(LWIPDIR)/apps/snmp/snmp_threadsync.c \ - $(LWIPDIR)/apps/snmp/snmp_traps.c \ - $(LWIPDIR)/apps/snmp/snmpv3_mbedtls.c \ - $(LWIPDIR)/apps/snmp/snmpv3_dummy.c - -# HTTPDFILES: HTTP server -HTTPDFILES=$(LWIPDIR)/apps/httpd/fs.c \ - $(LWIPDIR)/apps/httpd/httpd.c - -# LWIPERFFILES: IPERF server -LWIPERFFILES=$(LWIPDIR)/apps/lwiperf/lwiperf.c - -# SNTPFILES: SNTP client -SNTPFILES=$(LWIPDIR)/apps/sntp/sntp.c - -# MDNSFILES: MDNS responder -MDNSFILES=$(LWIPDIR)/apps/mdns/mdns.c - -# NETBIOSNSFILES: NetBIOS name server -NETBIOSNSFILES=$(LWIPDIR)/apps/netbiosns/netbiosns.c - -# TFTPFILES: TFTP server files -TFTPFILES=$(LWIPDIR)/apps/tftp/tftp_server.c - -# MQTTFILES: MQTT client files -MQTTFILES=$(LWIPDIR)/apps/mqtt/mqtt.c - -# LWIPAPPFILES: All LWIP APPs -LWIPAPPFILES=$(SNMPFILES) \ - $(HTTPDFILES) \ - $(LWIPERFFILES) \ - $(SNTPFILES) \ - $(MDNSFILES) \ - $(NETBIOSNSFILES) \ - $(TFTPFILES) \ - $(MQTTFILES) diff --git a/components/net/lwip-2.0.2/src/api/api_lib.c b/components/net/lwip-2.0.2/src/api/api_lib.c deleted file mode 100644 index 7d9c12768d..0000000000 --- a/components/net/lwip-2.0.2/src/api/api_lib.c +++ /dev/null @@ -1,1010 +0,0 @@ -/** - * @file - * Sequential API External module - * - * @defgroup netconn Netconn API - * @ingroup sequential_api - * Thread-safe, to be called from non-TCPIP threads only. - * TX/RX handling based on @ref netbuf (containing @ref pbuf) - * to avoid copying data around. - * - * @defgroup netconn_common Common functions - * @ingroup netconn - * For use with TCP and UDP - * - * @defgroup netconn_tcp TCP only - * @ingroup netconn - * TCP only functions - * - * @defgroup netconn_udp UDP only - * @ingroup netconn - * UDP only functions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -/* This is the part of the API that is linked with - the application */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/api.h" -#include "lwip/memp.h" - -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/api_msg.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/priv/tcpip_priv.h" - -#include - -#define API_MSG_VAR_REF(name) API_VAR_REF(name) -#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) -#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM) -#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL) -#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) - -static err_t netconn_close_shutdown(struct netconn *conn, u8_t how); - -/** - * Call the lower part of a netconn_* function - * This function is then running in the thread context - * of tcpip_thread and has exclusive access to lwIP core code. - * - * @param fn function to call - * @param apimsg a struct containing the function to call and its parameters - * @return ERR_OK if the function was called, another err_t if not - */ -static err_t -netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg) -{ - err_t err; - -#ifdef LWIP_DEBUG - /* catch functions that don't set err */ - apimsg->err = ERR_VAL; -#endif /* LWIP_DEBUG */ - -#if LWIP_NETCONN_SEM_PER_THREAD - apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg)); - if (err == ERR_OK) { - return apimsg->err; - } - return err; -} - -/** - * Create a new netconn (of a specific type) that has a callback function. - * The corresponding pcb is also created. - * - * @param t the type of 'connection' to create (@see enum netconn_type) - * @param proto the IP protocol for RAW IP pcbs - * @param callback a function to call on status changes (RX available, TX'ed) - * @return a newly allocated struct netconn or - * NULL on memory error - */ -struct netconn* -netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) -{ - struct netconn *conn; - API_MSG_VAR_DECLARE(msg); - API_MSG_VAR_ALLOC_RETURN_NULL(msg); - - conn = netconn_alloc(t, callback); - if (conn != NULL) { - err_t err; - - API_MSG_VAR_REF(msg).msg.n.proto = proto; - API_MSG_VAR_REF(msg).conn = conn; - err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg)); - if (err != ERR_OK) { - LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); - LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); -#if LWIP_TCP - LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); -#endif /* LWIP_TCP */ -#if !LWIP_NETCONN_SEM_PER_THREAD - LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); - sys_sem_free(&conn->op_completed); -#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ - sys_mbox_free(&conn->recvmbox); - memp_free(MEMP_NETCONN, conn); - API_MSG_VAR_FREE(msg); - return NULL; - } - } - API_MSG_VAR_FREE(msg); - return conn; -} - -/** - * @ingroup netconn_common - * Close a netconn 'connection' and free its resources. - * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate - * after this returns. - * - * @param conn the netconn to delete - * @return ERR_OK if the connection was deleted - */ -err_t -netconn_delete(struct netconn *conn) -{ - err_t err; - API_MSG_VAR_DECLARE(msg); - - /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ - if (conn == NULL) { - return ERR_OK; - } - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; -#if LWIP_TCP -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - API_MSG_VAR_REF(msg).msg.sd.polls_left = - ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; -#endif /* LWIP_TCP */ -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - if (err != ERR_OK) { - return err; - } - - netconn_free(conn); - - return ERR_OK; -} - -/** - * Get the local or remote IP address and port of a netconn. - * For RAW netconns, this returns the protocol instead of a port! - * - * @param conn the netconn to query - * @param addr a pointer to which to save the IP address - * @param port a pointer to which to save the port (or protocol for RAW) - * @param local 1 to get the local IP address, 0 to get the remote one - * @return ERR_CONN for invalid connections - * ERR_OK if the information was retrieved - */ -err_t -netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.ad.local = local; -#if LWIP_MPU_COMPATIBLE - err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg)); - *addr = msg->msg.ad.ipaddr; - *port = msg->msg.ad.port; -#else /* LWIP_MPU_COMPATIBLE */ - msg.msg.ad.ipaddr = addr; - msg.msg.ad.port = port; - err = netconn_apimsg(lwip_netconn_do_getaddr, &msg); -#endif /* LWIP_MPU_COMPATIBLE */ - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_common - * Bind a netconn to a specific local IP address and port. - * Binding one netconn twice might not always be checked correctly! - * - * @param conn the netconn to bind - * @param addr the local IP address to bind the netconn to - * (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses) - * @param port the local port to bind the netconn to (not used for RAW) - * @return ERR_OK if bound, any other err_t on failure - */ -err_t -netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ - if (addr == NULL) { - addr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV4 && LWIP_IPV6 - /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, - * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind - */ - if ((netconn_get_ipv6only(conn) == 0) && - ip_addr_cmp(addr, IP6_ADDR_ANY)) { - addr = IP_ANY_TYPE; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; - err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_common - * Connect a netconn to a specific remote IP address and port. - * - * @param conn the netconn to connect - * @param addr the remote IP address to connect to - * @param port the remote port to connect to (no used for RAW) - * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise - */ -err_t -netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ - if (addr == NULL) { - addr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; - err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_udp - * Disconnect a netconn from its current peer (only valid for UDP netconns). - * - * @param conn the netconn to disconnect - * @return See @ref err_t - */ -err_t -netconn_disconnect(struct netconn *conn) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Set a TCP netconn into listen mode - * - * @param conn the tcp netconn to set to listen mode - * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 - * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns - * don't return any error (yet?)) - */ -err_t -netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) -{ -#if LWIP_TCP - API_MSG_VAR_DECLARE(msg); - err_t err; - - /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ - LWIP_UNUSED_ARG(backlog); - - LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; -#endif /* TCP_LISTEN_BACKLOG */ - err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(backlog); - return ERR_ARG; -#endif /* LWIP_TCP */ -} - -/** - * @ingroup netconn_tcp - * Accept a new connection on a TCP listening netconn. - * - * @param conn the TCP listen netconn - * @param new_conn pointer where the new connection is stored - * @return ERR_OK if a new connection has been received or an error - * code otherwise - */ -err_t -netconn_accept(struct netconn *conn, struct netconn **new_conn) -{ -#if LWIP_TCP - void *accept_ptr; - struct netconn *newconn; -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_DECLARE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - - LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); - *new_conn = NULL; - LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); - - if (ERR_IS_FATAL(conn->last_err)) { - /* don't recv on fatal errors: this might block the application task - waiting on acceptmbox forever! */ - return conn->last_err; - } - if (!sys_mbox_valid(&conn->acceptmbox)) { - return ERR_CLSD; - } - -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_ALLOC(msg); -#endif /* TCP_LISTEN_BACKLOG */ - -#if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - return ERR_TIMEOUT; - } -#else - sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); -#endif /* LWIP_SO_RCVTIMEO*/ - newconn = (struct netconn *)accept_ptr; - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); - - if (accept_ptr == &netconn_aborted) { - /* a connection has been aborted: out of pcbs or out of netconns during accept */ - /* @todo: set netconn error, but this would be fatal and thus block further accepts */ -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - return ERR_ABRT; - } - if (newconn == NULL) { - /* connection has been aborted */ - /* in this special case, we set the netconn error from application thread, as - on a ready-to-accept listening netconn, there should not be anything running - in tcpip_thread */ - NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); -#if TCP_LISTEN_BACKLOG - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - return ERR_CLSD; - } -#if TCP_LISTEN_BACKLOG - /* Let the stack know that we have accepted the connection. */ - API_MSG_VAR_REF(msg).conn = newconn; - /* don't care for the return value of lwip_netconn_do_recv */ - netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); -#endif /* TCP_LISTEN_BACKLOG */ - - *new_conn = newconn; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(new_conn); - return ERR_ARG; -#endif /* LWIP_TCP */ -} - -/** - * @ingroup netconn_common - * Receive data: actual implementation that doesn't care whether pbuf or netbuf - * is received - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new pbuf/netbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - */ -static err_t -netconn_recv_data(struct netconn *conn, void **new_buf) -{ - void *buf = NULL; - u16_t len; -#if LWIP_TCP - API_MSG_VAR_DECLARE(msg); -#if LWIP_MPU_COMPATIBLE - msg = NULL; -#endif -#endif /* LWIP_TCP */ - - LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); - *new_buf = NULL; - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - if (!sys_mbox_valid(&conn->recvmbox)) { - /* This happens when calling this function after receiving FIN */ - return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD; - } - } -#endif /* LWIP_TCP */ - LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); - - if (ERR_IS_FATAL(conn->last_err)) { - /* don't recv on fatal errors: this might block the application task - waiting on recvmbox forever! */ - /* @todo: this does not allow us to fetch data that has been put into recvmbox - before the fatal error occurred - is that a problem? */ - return conn->last_err; - } -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - API_MSG_VAR_ALLOC(msg); - } -#endif /* LWIP_TCP */ - -#if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - API_MSG_VAR_FREE(msg); - } -#endif /* LWIP_TCP */ - return ERR_TIMEOUT; - } -#else - sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); -#endif /* LWIP_SO_RCVTIMEO*/ - -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - /* Let the stack know that we have taken the data. */ - /* @todo: Speedup: Don't block and wait for the answer here - (to prevent multiple thread-switches). */ - API_MSG_VAR_REF(msg).conn = conn; - if (buf != NULL) { - API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len; - } else { - API_MSG_VAR_REF(msg).msg.r.len = 1; - } - - /* don't care for the return value of lwip_netconn_do_recv */ - netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - /* If we are closed, we indicate that we no longer wish to use the socket */ - if (buf == NULL) { - API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); - if (conn->pcb.ip == NULL) { - /* race condition: RST during recv */ - return conn->last_err == ERR_OK ? ERR_RST : conn->last_err; - } - /* RX side is closed, so deallocate the recvmbox */ - netconn_close_shutdown(conn, NETCONN_SHUT_RD); - /* Don' store ERR_CLSD as conn->err since we are only half-closed */ - return ERR_CLSD; - } - len = ((struct pbuf *)buf)->tot_len; - } -#endif /* LWIP_TCP */ -#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) - else -#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ -#if (LWIP_UDP || LWIP_RAW) - { - LWIP_ASSERT("buf != NULL", buf != NULL); - len = netbuf_len((struct netbuf*)buf); - } -#endif /* (LWIP_UDP || LWIP_RAW) */ - -#if LWIP_SO_RCVBUF - SYS_ARCH_DEC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); - - LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); - - *new_buf = buf; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; -} - -/** - * @ingroup netconn_tcp - * Receive data (in form of a pbuf) from a TCP netconn - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new pbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - * ERR_ARG if conn is not a TCP netconn - */ -err_t -netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) -{ - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) && - NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); - - return netconn_recv_data(conn, (void **)new_buf); -} - -/** - * @ingroup netconn_common - * Receive data (in form of a netbuf containing a packet buffer) from a netconn - * - * @param conn the netconn from which to receive data - * @param new_buf pointer where a new netbuf is stored when received data - * @return ERR_OK if data has been received, an error code otherwise (timeout, - * memory error or another error) - */ -err_t -netconn_recv(struct netconn *conn, struct netbuf **new_buf) -{ -#if LWIP_TCP - struct netbuf *buf = NULL; - err_t err; -#endif /* LWIP_TCP */ - - LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); - *new_buf = NULL; - LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); - -#if LWIP_TCP -#if (LWIP_UDP || LWIP_RAW) - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) -#endif /* (LWIP_UDP || LWIP_RAW) */ - { - struct pbuf *p = NULL; - /* This is not a listening netconn, since recvmbox is set */ - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - return ERR_MEM; - } - - err = netconn_recv_data(conn, (void **)&p); - if (err != ERR_OK) { - memp_free(MEMP_NETBUF, buf); - return err; - } - LWIP_ASSERT("p != NULL", p != NULL); - - buf->p = p; - buf->ptr = p; - buf->port = 0; - ip_addr_set_zero(&buf->addr); - *new_buf = buf; - /* don't set conn->last_err: it's only ERR_OK, anyway */ - return ERR_OK; - } -#endif /* LWIP_TCP */ -#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) - else -#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ - { -#if (LWIP_UDP || LWIP_RAW) - return netconn_recv_data(conn, (void **)new_buf); -#endif /* (LWIP_UDP || LWIP_RAW) */ - } -} - -/** - * @ingroup netconn_udp - * Send data (in form of a netbuf) to a specific remote IP address and port. - * Only to be used for UDP and RAW netconns (not TCP). - * - * @param conn the netconn over which to send data - * @param buf a netbuf containing the data to send - * @param addr the remote IP address to which to send the data - * @param port the remote port to which to send the data - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t -netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port) -{ - if (buf != NULL) { - ip_addr_set(&buf->addr, addr); - buf->port = port; - return netconn_send(conn, buf); - } - return ERR_VAL; -} - -/** - * @ingroup netconn_udp - * Send data over a UDP or RAW netconn (that is already connected). - * - * @param conn the UDP or RAW netconn over which to send data - * @param buf a netbuf containing the data to send - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t -netconn_send(struct netconn *conn, struct netbuf *buf) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); - - LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.b = buf; - err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Send data over a TCP netconn. - * - * @param conn the TCP netconn over which to send data - * @param dataptr pointer to the application buffer that contains the data to send - * @param size size of the application data to send - * @param apiflags combination of following flags : - * - NETCONN_COPY: data will be copied into memory belonging to the stack - * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent - * - NETCONN_DONTBLOCK: only write the data if all data can be written at once - * @param bytes_written pointer to a location that receives the number of written bytes - * @return ERR_OK if data was sent, any other err_t on error - */ -err_t -netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, - u8_t apiflags, size_t *bytes_written) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - u8_t dontblock; - - LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;); - if (size == 0) { - return ERR_OK; - } - dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout != 0) { - dontblock = 1; - } -#endif /* LWIP_SO_SNDTIMEO */ - if (dontblock && !bytes_written) { - /* This implies netconn_write() cannot be used for non-blocking send, since - it has no way to return the number of bytes written. */ - return ERR_VAL; - } - - API_MSG_VAR_ALLOC(msg); - /* non-blocking write sends as much */ - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.w.dataptr = dataptr; - API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags; - API_MSG_VAR_REF(msg).msg.w.len = size; -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout != 0) { - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - API_MSG_VAR_REF(msg).msg.w.time_started = sys_now(); - } else { - API_MSG_VAR_REF(msg).msg.w.time_started = 0; - } -#endif /* LWIP_SO_SNDTIMEO */ - - /* For locking the core: this _can_ be delayed on low memory/low send buffer, - but if it is, this is done inside api_msg.c:do_write(), so we can use the - non-blocking version here. */ - err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg)); - if ((err == ERR_OK) && (bytes_written != NULL)) { - if (dontblock) { - /* nonblocking write: maybe the data has been sent partly */ - *bytes_written = API_MSG_VAR_REF(msg).msg.w.len; - } else { - /* blocking call succeeded: all data has been sent if it */ - *bytes_written = size; - } - } - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Close or shutdown a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to close or shutdown - * @param how fully close or only shutdown one side? - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -static err_t -netconn_close_shutdown(struct netconn *conn, u8_t how) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - LWIP_UNUSED_ARG(how); - - LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - API_MSG_VAR_REF(msg).conn = conn; -#if LWIP_TCP - /* shutting down both ends is the same as closing */ - API_MSG_VAR_REF(msg).msg.sd.shut = how; -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - /* get the time we started, which is later compared to - sys_now() + conn->send_timeout */ - API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - API_MSG_VAR_REF(msg).msg.sd.polls_left = - ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ -#endif /* LWIP_TCP */ - err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} - -/** - * @ingroup netconn_tcp - * Close a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to close - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -err_t -netconn_close(struct netconn *conn) -{ - /* shutting down both ends is the same as closing */ - return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); -} - -/** - * @ingroup netconn_tcp - * Shut down one or both sides of a TCP netconn (doesn't delete it). - * - * @param conn the TCP netconn to shut down - * @param shut_rx shut down the RX side (no more read possible after this) - * @param shut_tx shut down the TX side (no more write possible after this) - * @return ERR_OK if the netconn was closed, any other err_t on error - */ -err_t -netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) -{ - return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)); -} - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** - * @ingroup netconn_udp - * Join multicast groups for UDP netconns. - * - * @param conn the UDP netconn for which to change multicast addresses - * @param multiaddr IP address of the multicast group to join or leave - * @param netif_addr the IP address of the network interface on which to send - * the igmp message - * @param join_or_leave flag whether to send a join- or leave-message - * @return ERR_OK if the action was taken, any err_t on error - */ -err_t -netconn_join_leave_group(struct netconn *conn, - const ip_addr_t *multiaddr, - const ip_addr_t *netif_addr, - enum netconn_igmp join_or_leave) -{ - API_MSG_VAR_DECLARE(msg); - err_t err; - - LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); - - API_MSG_VAR_ALLOC(msg); - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ - if (multiaddr == NULL) { - multiaddr = IP4_ADDR_ANY; - } - if (netif_addr == NULL) { - netif_addr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); - API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr); - API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; - err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - - return err; -} -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/** - * @ingroup netconn_common - * Execute a DNS query, only one IP address is returned - * - * @param name a string representation of the DNS host name to query - * @param addr a preallocated ip_addr_t where to store the resolved IP address - * @param dns_addrtype IP address type (IPv4 / IPv6) - * @return ERR_OK: resolving succeeded - * ERR_MEM: memory error, try again later - * ERR_ARG: dns client not initialized or invalid hostname - * ERR_VAL: dns server response was invalid - */ -#if LWIP_IPV4 && LWIP_IPV6 -err_t -netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) -#else -err_t -netconn_gethostbyname(const char *name, ip_addr_t *addr) -#endif -{ - API_VAR_DECLARE(struct dns_api_msg, msg); -#if !LWIP_MPU_COMPATIBLE - sys_sem_t sem; -#endif /* LWIP_MPU_COMPATIBLE */ - err_t err; - err_t cberr; - - LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); -#if LWIP_MPU_COMPATIBLE - if (strlen(name) >= DNS_MAX_NAME_LENGTH) { - return ERR_ARG; - } -#endif - - API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM); -#if LWIP_MPU_COMPATIBLE - strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1); - API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0; -#else /* LWIP_MPU_COMPATIBLE */ - msg.err = &err; - msg.sem = &sem; - API_VAR_REF(msg).addr = API_VAR_REF(addr); - API_VAR_REF(msg).name = name; -#endif /* LWIP_MPU_COMPATIBLE */ -#if LWIP_IPV4 && LWIP_IPV6 - API_VAR_REF(msg).dns_addrtype = dns_addrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_NETCONN_SEM_PER_THREAD - API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else /* LWIP_NETCONN_SEM_PER_THREAD*/ - err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); - if (err != ERR_OK) { - API_VAR_FREE(MEMP_DNS_API_MSG, msg); - return err; - } -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - cberr = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg)); - if (cberr != ERR_OK) { -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); -#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ - API_VAR_FREE(MEMP_DNS_API_MSG, msg); - return cberr; - } - sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem)); -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); -#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ - -#if LWIP_MPU_COMPATIBLE - *addr = msg->addr; - err = msg->err; -#endif /* LWIP_MPU_COMPATIBLE */ - - API_VAR_FREE(MEMP_DNS_API_MSG, msg); - return err; -} -#endif /* LWIP_DNS*/ - -#if LWIP_NETCONN_SEM_PER_THREAD -void -netconn_thread_init(void) -{ - sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); - if ((sem == NULL) || !sys_sem_valid(sem)) { - /* call alloc only once */ - LWIP_NETCONN_THREAD_SEM_ALLOC(); - LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); - } -} - -void -netconn_thread_cleanup(void) -{ - sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); - if ((sem != NULL) && sys_sem_valid(sem)) { - /* call free only once */ - LWIP_NETCONN_THREAD_SEM_FREE(); - } -} -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - -#endif /* LWIP_NETCONN */ diff --git a/components/net/lwip-2.0.2/src/api/api_msg.c b/components/net/lwip-2.0.2/src/api/api_msg.c deleted file mode 100644 index dd99c1e01b..0000000000 --- a/components/net/lwip-2.0.2/src/api/api_msg.c +++ /dev/null @@ -1,1947 +0,0 @@ -/** - * @file - * Sequential API Internal module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/api_msg.h" - -#include "lwip/ip.h" -#include "lwip/ip_addr.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/raw.h" - -#include "lwip/memp.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/mld6.h" -#include "lwip/priv/tcpip_priv.h" - -#include - -/* netconns are polled once per second (e.g. continue write on memory error) */ -#define NETCONN_TCP_POLL_INTERVAL 2 - -#define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \ - (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0) -#define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) - -/* forward declarations */ -#if LWIP_TCP -#if LWIP_TCPIP_CORE_LOCKING -#define WRITE_DELAYED , 1 -#define WRITE_DELAYED_PARAM , u8_t delayed -#else /* LWIP_TCPIP_CORE_LOCKING */ -#define WRITE_DELAYED -#define WRITE_DELAYED_PARAM -#endif /* LWIP_TCPIP_CORE_LOCKING */ -static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM); -static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM); -#endif - -#if LWIP_TCPIP_CORE_LOCKING -#define TCPIP_APIMSG_ACK(m) NETCONN_SET_SAFE_ERR((m)->conn, (m)->err) -#else /* LWIP_TCPIP_CORE_LOCKING */ -#define TCPIP_APIMSG_ACK(m) do { NETCONN_SET_SAFE_ERR((m)->conn, (m)->err); sys_sem_signal(LWIP_API_MSG_SEM(m)); } while(0) -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_TCP -u8_t netconn_aborted; -#endif /* LWIP_TCP */ - -#if LWIP_RAW -/** - * Receive callback function for RAW netconns. - * Doesn't 'eat' the packet, only copies it and sends it to - * conn->recvmbox - * - * @see raw.h (struct raw_pcb.recv) for parameters and return value - */ -static u8_t -recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr) -{ - struct pbuf *q; - struct netbuf *buf; - struct netconn *conn; - - LWIP_UNUSED_ARG(addr); - conn = (struct netconn *)arg; - - if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) { -#if LWIP_SO_RCVBUF - int recv_avail; - SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) { - return 0; - } -#endif /* LWIP_SO_RCVBUF */ - /* copy the whole packet into new pbufs */ - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if (q != NULL) { - if (pbuf_copy(q, p) != ERR_OK) { - pbuf_free(q); - q = NULL; - } - } - - if (q != NULL) { - u16_t len; - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - pbuf_free(q); - return 0; - } - - buf->p = q; - buf->ptr = q; - ip_addr_copy(buf->addr, *ip_current_src_addr()); - buf->port = pcb->protocol; - - len = q->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { - netbuf_delete(buf); - return 0; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } - } - } - - return 0; /* do not eat the packet */ -} -#endif /* LWIP_RAW*/ - -#if LWIP_UDP -/** - * Receive callback function for UDP netconns. - * Posts the packet to conn->recvmbox or deletes it on memory error. - * - * @see udp.h (struct udp_pcb.recv) for parameters - */ -static void -recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr, u16_t port) -{ - struct netbuf *buf; - struct netconn *conn; - u16_t len; -#if LWIP_SO_RCVBUF - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ - - LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ - LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_udp must have an argument", arg != NULL); - conn = (struct netconn *)arg; - LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); - -#if LWIP_SO_RCVBUF - SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || - ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { -#else /* LWIP_SO_RCVBUF */ - if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) { -#endif /* LWIP_SO_RCVBUF */ - pbuf_free(p); - return; - } - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf == NULL) { - pbuf_free(p); - return; - } else { - buf->p = p; - buf->ptr = p; - ip_addr_set(&buf->addr, addr); - buf->port = port; -#if LWIP_NETBUF_RECVINFO - { - /* get the UDP header - always in the first pbuf, ensured by udp_input */ - const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr(); -#if LWIP_CHECKSUM_ON_COPY - buf->flags = NETBUF_FLAG_DESTADDR; -#endif /* LWIP_CHECKSUM_ON_COPY */ - ip_addr_set(&buf->toaddr, ip_current_dest_addr()); - buf->toport_chksum = udphdr->dest; - } -#endif /* LWIP_NETBUF_RECVINFO */ - } - - len = p->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { - netbuf_delete(buf); - return; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } -} -#endif /* LWIP_UDP */ - -#if LWIP_TCP -/** - * Receive callback function for TCP netconns. - * Posts the packet to conn->recvmbox, but doesn't delete it on errors. - * - * @see tcp.h (struct tcp_pcb.recv) for parameters and return value - */ -static err_t -recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct netconn *conn; - u16_t len; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL); - LWIP_ASSERT("recv_tcp must have an argument", arg != NULL); - conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb); - - if (!sys_mbox_valid(&conn->recvmbox)) { - /* recvmbox already deleted */ - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - return ERR_OK; - } - /* Unlike for UDP or RAW pcbs, don't check for available space - using recv_avail since that could break the connection - (data is already ACKed) */ - - /* don't overwrite fatal errors! */ - if (err != ERR_OK) { - NETCONN_SET_SAFE_ERR(conn, err); - } - - if (p != NULL) { - len = p->tot_len; - } else { - len = 0; - } - - if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { - /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ - return ERR_MEM; - } else { -#if LWIP_SO_RCVBUF - SYS_ARCH_INC(conn->recv_avail, len); -#endif /* LWIP_SO_RCVBUF */ - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); - } - - return ERR_OK; -} - -/** - * Poll callback function for TCP netconns. - * Wakes up an application thread that waits for a connection to close - * or data to be sent. The application thread then takes the - * appropriate action to go on. - * - * Signals the conn->sem. - * netconn_close waits for conn->sem if closing failed. - * - * @see tcp.h (struct tcp_pcb.poll) for parameters and return value - */ -static err_t -poll_tcp(void *arg, struct tcp_pcb *pcb) -{ - struct netconn *conn = (struct netconn *)arg; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - if (conn->state == NETCONN_WRITE) { - lwip_netconn_do_writemore(conn WRITE_DELAYED); - } else if (conn->state == NETCONN_CLOSE) { -#if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER - if (conn->current_msg && conn->current_msg->msg.sd.polls_left) { - conn->current_msg->msg.sd.polls_left--; - } -#endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */ - lwip_netconn_do_close_internal(conn WRITE_DELAYED); - } - /* @todo: implement connect timeout here? */ - - /* Did a nonblocking write fail before? Then check available write-space. */ - if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) { - /* If the queued byte- or pbuf-count drops below the configured low-water limit, - let select mark this pcb as writable again. */ - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && - (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { - conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - } - } - - return ERR_OK; -} - -/** - * Sent callback function for TCP netconns. - * Signals the conn->sem and calls API_EVENT. - * netconn_write waits for conn->sem if send buffer is low. - * - * @see tcp.h (struct tcp_pcb.sent) for parameters and return value - */ -static err_t -sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct netconn *conn = (struct netconn *)arg; - - LWIP_UNUSED_ARG(pcb); - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - if (conn) { - if (conn->state == NETCONN_WRITE) { - lwip_netconn_do_writemore(conn WRITE_DELAYED); - } else if (conn->state == NETCONN_CLOSE) { - lwip_netconn_do_close_internal(conn WRITE_DELAYED); - } - - /* If the queued byte- or pbuf-count drops below the configured low-water limit, - let select mark this pcb as writable again. */ - if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) && - (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) { - conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE; - API_EVENT(conn, NETCONN_EVT_SENDPLUS, len); - } - } - - return ERR_OK; -} - -/** - * Error callback function for TCP netconns. - * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. - * The application thread has then to decide what to do. - * - * @see tcp.h (struct tcp_pcb.err) for parameters - */ -static void -err_tcp(void *arg, err_t err) -{ - struct netconn *conn; - enum netconn_state old_state; - - conn = (struct netconn *)arg; - LWIP_ASSERT("conn != NULL", (conn != NULL)); - - conn->pcb.tcp = NULL; - - /* reset conn->state now before waking up other threads */ - old_state = conn->state; - conn->state = NETCONN_NONE; - - if (old_state == NETCONN_CLOSE) { - /* RST during close: let close return success & dealloc the netconn */ - err = ERR_OK; - NETCONN_SET_SAFE_ERR(conn, ERR_OK); - } else { - /* no check since this is always fatal! */ - SYS_ARCH_SET(conn->last_err, err); - } - - /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */ - - /* Notify the user layer about a connection error. Used to signal select. */ - API_EVENT(conn, NETCONN_EVT_ERROR, 0); - /* Try to release selects pending on 'read' or 'write', too. - They will get an error if they actually try to read or write. */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - - /* pass NULL-message to recvmbox to wake up pending recv */ - if (sys_mbox_valid(&conn->recvmbox)) { - /* use trypost to prevent deadlock */ - sys_mbox_trypost(&conn->recvmbox, NULL); - } - /* pass NULL-message to acceptmbox to wake up pending accept */ - if (sys_mbox_valid(&conn->acceptmbox)) { - /* use trypost to preven deadlock */ - sys_mbox_trypost(&conn->acceptmbox, NULL); - } - - if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || - (old_state == NETCONN_CONNECT)) { - /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary - since the pcb has already been deleted! */ - int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn); - SET_NONBLOCKING_CONNECT(conn, 0); - - if (!was_nonblocking_connect) { - sys_sem_t* op_completed_sem; - /* set error return code */ - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - conn->current_msg->err = err; - op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem)); - conn->current_msg = NULL; - /* wake up the waiting task */ - NETCONN_SET_SAFE_ERR(conn, err); - sys_sem_signal(op_completed_sem); - } - } else { - LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); - } -} - -/** - * Setup a tcp_pcb with the correct callback function pointers - * and their arguments. - * - * @param conn the TCP netconn to setup - */ -static void -setup_tcp(struct netconn *conn) -{ - struct tcp_pcb *pcb; - - pcb = conn->pcb.tcp; - tcp_arg(pcb, conn); - tcp_recv(pcb, recv_tcp); - tcp_sent(pcb, sent_tcp); - tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL); - tcp_err(pcb, err_tcp); -} - -/** - * Accept callback function for TCP netconns. - * Allocates a new netconn and posts that to conn->acceptmbox. - * - * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value - */ -static err_t -accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - struct netconn *newconn; - struct netconn *conn = (struct netconn *)arg; - - LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state))); - - if (conn == NULL) { - return ERR_VAL; - } - if (!sys_mbox_valid(&conn->acceptmbox)) { - LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); - return ERR_VAL; - } - - if (newpcb == NULL) { - /* out-of-pcbs during connect: pass on this error to the application */ - if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - return ERR_VAL; - } - - /* We have to set the callback here even though - * the new socket is unknown. newconn->socket is marked as -1. */ - newconn = netconn_alloc(conn->type, conn->callback); - if (newconn == NULL) { - /* outof netconns: pass on this error to the application */ - if (sys_mbox_trypost(&conn->acceptmbox, &netconn_aborted) == ERR_OK) { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - return ERR_MEM; - } - newconn->pcb.tcp = newpcb; - setup_tcp(newconn); - /* no protection: when creating the pcb, the netconn is not yet known - to the application thread */ - newconn->last_err = err; - - /* handle backlog counter */ - tcp_backlog_delayed(newpcb); - - if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { - /* When returning != ERR_OK, the pcb is aborted in tcp_process(), - so do nothing here! */ - /* remove all references to this netconn from the pcb */ - struct tcp_pcb* pcb = newconn->pcb.tcp; - tcp_arg(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_sent(pcb, NULL); - tcp_poll(pcb, NULL, 0); - tcp_err(pcb, NULL); - /* remove reference from to the pcb from this netconn */ - newconn->pcb.tcp = NULL; - /* no need to drain since we know the recvmbox is empty. */ - sys_mbox_free(&newconn->recvmbox); - sys_mbox_set_invalid(&newconn->recvmbox); - netconn_free(newconn); - return ERR_MEM; - } else { - /* Register event with callback */ - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Create a new pcb of a specific type. - * Called from lwip_netconn_do_newconn(). - * - * @param msg the api_msg_msg describing the connection type - */ -static void -pcb_new(struct api_msg *msg) -{ - enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4; - - LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL); - -#if LWIP_IPV6 && LWIP_IPV4 - /* IPv6: Dual-stack by default, unless netconn_set_ipv6only() is called */ - if(NETCONNTYPE_ISIPV6(netconn_type(msg->conn))) { - iptype = IPADDR_TYPE_ANY; - } -#endif - - /* Allocate a PCB for this connection */ - switch(NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->conn->pcb.raw = raw_new_ip_type(iptype, msg->msg.n.proto); - if (msg->conn->pcb.raw != NULL) { -#if LWIP_IPV6 - /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ - if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { - msg->conn->pcb.raw->chksum_reqd = 1; - msg->conn->pcb.raw->chksum_offset = 2; - } -#endif /* LWIP_IPV6 */ - raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); - } - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->conn->pcb.udp = udp_new_ip_type(iptype); - if (msg->conn->pcb.udp != NULL) { -#if LWIP_UDPLITE - if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); - } -#endif /* LWIP_UDPLITE */ - if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); - } - udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn); - } - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - msg->conn->pcb.tcp = tcp_new_ip_type(iptype); - if (msg->conn->pcb.tcp != NULL) { - setup_tcp(msg->conn); - } - break; -#endif /* LWIP_TCP */ - default: - /* Unsupported netconn type, e.g. protocol disabled */ - msg->err = ERR_VAL; - return; - } - if (msg->conn->pcb.ip == NULL) { - msg->err = ERR_MEM; - } -} - -/** - * Create a new pcb of a specific type inside a netconn. - * Called from netconn_new_with_proto_and_callback. - * - * @param m the api_msg_msg describing the connection type - */ -void -lwip_netconn_do_newconn(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp == NULL) { - pcb_new(msg); - } - /* Else? This "new" connection already has a PCB allocated. */ - /* Is this an error condition? Should it be deleted? */ - /* We currently just are happy and return. */ - - TCPIP_APIMSG_ACK(msg); -} - -/** - * Create a new netconn (of a specific type) that has a callback function. - * The corresponding pcb is NOT created! - * - * @param t the type of 'connection' to create (@see enum netconn_type) - * @param callback a function to call on status changes (RX available, TX'ed) - * @return a newly allocated struct netconn or - * NULL on memory error - */ -struct netconn* -netconn_alloc(enum netconn_type t, netconn_callback callback) -{ - struct netconn *conn; - int size; - - conn = (struct netconn *)memp_malloc(MEMP_NETCONN); - if (conn == NULL) { - return NULL; - } - - conn->last_err = ERR_OK; - conn->type = t; - conn->pcb.tcp = NULL; - - /* If all sizes are the same, every compiler should optimize this switch to nothing */ - switch(NETCONNTYPE_GROUP(t)) { -#if LWIP_RAW - case NETCONN_RAW: - size = DEFAULT_RAW_RECVMBOX_SIZE; - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - size = DEFAULT_UDP_RECVMBOX_SIZE; - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - size = DEFAULT_TCP_RECVMBOX_SIZE; - break; -#endif /* LWIP_TCP */ - default: - LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0); - goto free_and_return; - } - - if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { - goto free_and_return; - } -#if !LWIP_NETCONN_SEM_PER_THREAD - if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { - sys_mbox_free(&conn->recvmbox); - goto free_and_return; - } -#endif - -#if LWIP_TCP - sys_mbox_set_invalid(&conn->acceptmbox); -#endif - conn->state = NETCONN_NONE; -#if LWIP_SOCKET - /* initialize socket to -1 since 0 is a valid socket */ - conn->socket = -1; -#endif /* LWIP_SOCKET */ - conn->callback = callback; -#if LWIP_TCP - conn->current_msg = NULL; - conn->write_offset = 0; -#endif /* LWIP_TCP */ -#if LWIP_SO_SNDTIMEO - conn->send_timeout = 0; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - conn->recv_timeout = 0; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; - conn->recv_avail = 0; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - conn->linger = -1; -#endif /* LWIP_SO_LINGER */ - conn->flags = 0; - return conn; -free_and_return: - memp_free(MEMP_NETCONN, conn); - return NULL; -} - -/** - * Delete a netconn and all its resources. - * The pcb is NOT freed (since we might not be in the right thread context do this). - * - * @param conn the netconn to free - */ -void -netconn_free(struct netconn *conn) -{ - LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); - LWIP_ASSERT("recvmbox must be deallocated before calling this function", - !sys_mbox_valid(&conn->recvmbox)); -#if LWIP_TCP - LWIP_ASSERT("acceptmbox must be deallocated before calling this function", - !sys_mbox_valid(&conn->acceptmbox)); -#endif /* LWIP_TCP */ - -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(&conn->op_completed); - sys_sem_set_invalid(&conn->op_completed); -#endif - - memp_free(MEMP_NETCONN, conn); -} - -/** - * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in - * these mboxes - * - * @param conn the netconn to free - * @bytes_drained bytes drained from recvmbox - * @accepts_drained pending connections drained from acceptmbox - */ -static void -netconn_drain(struct netconn *conn) -{ - void *mem; -#if LWIP_TCP - struct pbuf *p; -#endif /* LWIP_TCP */ - - /* This runs in tcpip_thread, so we don't need to lock against rx packets */ - - /* Delete and drain the recvmbox. */ - if (sys_mbox_valid(&conn->recvmbox)) { - while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { -#if LWIP_TCP - if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) { - if (mem != NULL) { - p = (struct pbuf*)mem; - /* pcb might be set to NULL already by err_tcp() */ - if (conn->pcb.tcp != NULL) { - tcp_recved(conn->pcb.tcp, p->tot_len); - } - pbuf_free(p); - } - } else -#endif /* LWIP_TCP */ - { - netbuf_delete((struct netbuf *)mem); - } - } - sys_mbox_free(&conn->recvmbox); - sys_mbox_set_invalid(&conn->recvmbox); - } - - /* Delete and drain the acceptmbox. */ -#if LWIP_TCP - if (sys_mbox_valid(&conn->acceptmbox)) { - while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { - if (mem != &netconn_aborted) { - struct netconn *newconn = (struct netconn *)mem; - /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ - /* pcb might be set to NULL already by err_tcp() */ - /* drain recvmbox */ - netconn_drain(newconn); - if (newconn->pcb.tcp != NULL) { - tcp_abort(newconn->pcb.tcp); - newconn->pcb.tcp = NULL; - } - netconn_free(newconn); - } - } - sys_mbox_free(&conn->acceptmbox); - sys_mbox_set_invalid(&conn->acceptmbox); - } -#endif /* LWIP_TCP */ -} - -#if LWIP_TCP -/** - * Internal helper function to close a TCP netconn: since this sometimes - * doesn't work at the first attempt, this function is called from multiple - * places. - * - * @param conn the TCP netconn to close - */ -static err_t -lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) -{ - err_t err; - u8_t shut, shut_rx, shut_tx, close; - u8_t close_finished = 0; - struct tcp_pcb* tpcb; -#if LWIP_SO_LINGER - u8_t linger_wait_required = 0; -#endif /* LWIP_SO_LINGER */ - - LWIP_ASSERT("invalid conn", (conn != NULL)); - LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)); - LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE)); - LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - - tpcb = conn->pcb.tcp; - shut = conn->current_msg->msg.sd.shut; - shut_rx = shut & NETCONN_SHUT_RD; - shut_tx = shut & NETCONN_SHUT_WR; - /* shutting down both ends is the same as closing - (also if RD or WR side was shut down before already) */ - if (shut == NETCONN_SHUT_RDWR) { - close = 1; - } else if (shut_rx && - ((tpcb->state == FIN_WAIT_1) || - (tpcb->state == FIN_WAIT_2) || - (tpcb->state == CLOSING))) { - close = 1; - } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) { - close = 1; - } else { - close = 0; - } - - /* Set back some callback pointers */ - if (close) { - tcp_arg(tpcb, NULL); - } - if (tpcb->state == LISTEN) { - tcp_accept(tpcb, NULL); - } else { - /* some callbacks have to be reset if tcp_close is not successful */ - if (shut_rx) { - tcp_recv(tpcb, NULL); - tcp_accept(tpcb, NULL); - } - if (shut_tx) { - tcp_sent(tpcb, NULL); - } - if (close) { - tcp_poll(tpcb, NULL, 0); - tcp_err(tpcb, NULL); - } - } - /* Try to close the connection */ - if (close) { -#if LWIP_SO_LINGER - /* check linger possibilites before calling tcp_close */ - err = ERR_OK; - /* linger enabled/required at all? (i.e. is there untransmitted data left?) */ - if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) { - if ((conn->linger == 0)) { - /* data left but linger prevents waiting */ - tcp_abort(tpcb); - tpcb = NULL; - } else if (conn->linger > 0) { - /* data left and linger says we should wait */ - if (netconn_is_nonblocking(conn)) { - /* data left on a nonblocking netconn -> cannot linger */ - err = ERR_WOULDBLOCK; - } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= - (conn->linger * 1000)) { - /* data left but linger timeout has expired (this happens on further - calls to this function through poll_tcp */ - tcp_abort(tpcb); - tpcb = NULL; - } else { - /* data left -> need to wait for ACK after successful close */ - linger_wait_required = 1; - } - } - } - if ((err == ERR_OK) && (tpcb != NULL)) -#endif /* LWIP_SO_LINGER */ - { - err = tcp_close(tpcb); - } - } else { - err = tcp_shutdown(tpcb, shut_rx, shut_tx); - } - if (err == ERR_OK) { - close_finished = 1; -#if LWIP_SO_LINGER - if (linger_wait_required) { - /* wait for ACK of all unsent/unacked data by just getting called again */ - close_finished = 0; - err = ERR_INPROGRESS; - } -#endif /* LWIP_SO_LINGER */ - } else { - if (err == ERR_MEM) { - /* Closing failed because of memory shortage, try again later. Even for - nonblocking netconns, we have to wait since no standard socket application - is prepared for close failing because of resource shortage. - Check the timeout: this is kind of an lwip addition to the standard sockets: - we wait for some time when failing to allocate a segment for the FIN */ -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; -#if LWIP_SO_SNDTIMEO - if (conn->send_timeout > 0) { - close_timeout = conn->send_timeout; - } -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_LINGER - if (conn->linger >= 0) { - /* use linger timeout (seconds) */ - close_timeout = conn->linger * 1000U; - } -#endif - if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - if (conn->current_msg->msg.sd.polls_left == 0) { -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - close_finished = 1; - if (close) { - /* in this case, we want to RST the connection */ - tcp_abort(tpcb); - err = ERR_OK; - } - } - } else { - /* Closing failed for a non-memory error: give up */ - close_finished = 1; - } - } - if (close_finished) { - /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ - sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - conn->current_msg->err = err; - conn->current_msg = NULL; - conn->state = NETCONN_NONE; - if (err == ERR_OK) { - if (close) { - /* Set back some callback pointers as conn is going away */ - conn->pcb.tcp = NULL; - /* Trigger select() in socket layer. Make sure everybody notices activity - on the connection, error first! */ - API_EVENT(conn, NETCONN_EVT_ERROR, 0); - } - if (shut_rx) { - API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); - } - if (shut_tx) { - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - } - } - NETCONN_SET_SAFE_ERR(conn, err); -#if LWIP_TCPIP_CORE_LOCKING - if (delayed) -#endif - { - /* wake up the application task */ - sys_sem_signal(op_completed_sem); - } - return ERR_OK; - } - if (!close_finished) { - /* Closing failed and we want to wait: restore some of the callbacks */ - /* Closing of listen pcb will never fail! */ - LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN)); - if (shut_tx) { - tcp_sent(tpcb, sent_tcp); - } - /* when waiting for close, set up poll interval to 500ms */ - tcp_poll(tpcb, poll_tcp, 1); - tcp_err(tpcb, err_tcp); - tcp_arg(tpcb, conn); - /* don't restore recv callback: we don't want to receive any more data */ - } - /* If closing didn't succeed, we get called again either - from poll_tcp or from sent_tcp */ - LWIP_ASSERT("err != ERR_OK", err != ERR_OK); - return err; -} -#endif /* LWIP_TCP */ - -/** - * Delete the pcb inside a netconn. - * Called from netconn_delete. - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_delconn(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - enum netconn_state state = msg->conn->state; - LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ - (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); -#if LWIP_NETCONN_FULLDUPLEX - /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ - if (state != NETCONN_NONE) { - if ((state == NETCONN_WRITE) || - ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { - /* close requested, abort running write/connect */ - sys_sem_t* op_completed_sem; - LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); - op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); - msg->conn->current_msg->err = ERR_CLSD; - msg->conn->current_msg = NULL; - msg->conn->write_offset = 0; - msg->conn->state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); - sys_sem_signal(op_completed_sem); - } - } -#else /* LWIP_NETCONN_FULLDUPLEX */ - if (((state != NETCONN_NONE) && - (state != NETCONN_LISTEN) && - (state != NETCONN_CONNECT)) || - ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) { - /* This means either a blocking write or blocking connect is running - (nonblocking write returns and sets state to NONE) */ - msg->err = ERR_INPROGRESS; - } else -#endif /* LWIP_NETCONN_FULLDUPLEX */ - { - LWIP_ASSERT("blocking connect in progress", - (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); - msg->err = ERR_OK; - /* Drain and delete mboxes */ - netconn_drain(msg->conn); - - if (msg->conn->pcb.tcp != NULL) { - - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - raw_remove(msg->conn->pcb.raw); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->conn->pcb.udp->recv_arg = NULL; - udp_remove(msg->conn->pcb.udp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - msg->conn->state = NETCONN_CLOSE; - msg->msg.sd.shut = NETCONN_SHUT_RDWR; - msg->conn->current_msg = msg; -#if LWIP_TCPIP_CORE_LOCKING - if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_close_internal(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing - the application thread, so we can return at this point! */ - return; -#endif /* LWIP_TCP */ - default: - break; - } - msg->conn->pcb.tcp = NULL; - } - /* tcp netconns don't come here! */ - - /* @todo: this lets select make the socket readable and writable, - which is wrong! errfd instead? */ - API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); - API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); - } - if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) { - TCPIP_APIMSG_ACK(msg); - } -} - -/** - * Bind a pcb contained in a netconn - * Called from netconn_bind. - * - * @param m the api_msg_msg pointing to the connection and containing - * the IP address and port to bind to - */ -void -lwip_netconn_do_bind(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_VAL; - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; -#endif /* LWIP_TCP */ - default: - break; - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has - * been established (or reset by the remote host). - * - * @see tcp.h (struct tcp_pcb.connected) for parameters and return values - */ -static err_t -lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct netconn *conn; - int was_blocking; - sys_sem_t* op_completed_sem = NULL; - - LWIP_UNUSED_ARG(pcb); - - conn = (struct netconn *)arg; - - if (conn == NULL) { - return ERR_VAL; - } - - LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT); - LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect", - (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn)); - - if (conn->current_msg != NULL) { - conn->current_msg->err = err; - op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - } - if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) { - setup_tcp(conn); - } - was_blocking = !IN_NONBLOCKING_CONNECT(conn); - SET_NONBLOCKING_CONNECT(conn, 0); - LWIP_ASSERT("blocking connect state error", - (was_blocking && op_completed_sem != NULL) || - (!was_blocking && op_completed_sem == NULL)); - conn->current_msg = NULL; - conn->state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(conn, ERR_OK); - API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); - - if (was_blocking) { - sys_sem_signal(op_completed_sem); - } - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Connect a pcb contained inside a netconn - * Called from netconn_connect. - * - * @param m the api_msg_msg pointing to the connection and containing - * the IP address and port to connect to - */ -void -lwip_netconn_do_connect(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (msg->conn->pcb.tcp == NULL) { - /* This may happen when calling netconn_connect() a second time */ - msg->err = ERR_CLSD; - } else { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - /* Prevent connect while doing any other action. */ - if (msg->conn->state == NETCONN_CONNECT) { - msg->err = ERR_ALREADY; - } else if (msg->conn->state != NETCONN_NONE) { - msg->err = ERR_ISCONN; - } else { - setup_tcp(msg->conn); - msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), - msg->msg.bc.port, lwip_netconn_do_connected); - if (msg->err == ERR_OK) { - u8_t non_blocking = netconn_is_nonblocking(msg->conn); - msg->conn->state = NETCONN_CONNECT; - SET_NONBLOCKING_CONNECT(msg->conn, non_blocking); - if (non_blocking) { - msg->err = ERR_INPROGRESS; - } else { - msg->conn->current_msg = msg; - /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()), - when the connection is established! */ -#if LWIP_TCPIP_CORE_LOCKING - LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - return; - } - } - } - break; -#endif /* LWIP_TCP */ - default: - LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0)); - break; - } - } - /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), - so use TCPIP_APIMSG_ACK() here. */ - TCPIP_APIMSG_ACK(msg); -} - -/** - * Disconnect a pcb contained inside a netconn - * Only used for UDP netconns. - * Called from netconn_disconnect. - * - * @param m the api_msg_msg pointing to the connection to disconnect - */ -void -lwip_netconn_do_disconnect(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - -#if LWIP_UDP - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { - udp_disconnect(msg->conn->pcb.udp); - msg->err = ERR_OK; - } else -#endif /* LWIP_UDP */ - { - msg->err = ERR_VAL; - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * Set a TCP pcb contained in a netconn into listen mode - * Called from netconn_listen. - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_listen(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_CONN; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - if (msg->conn->state == NETCONN_NONE) { - struct tcp_pcb* lpcb; - if (msg->conn->pcb.tcp->state != CLOSED) { - /* connection is not closed, cannot listen */ - msg->err = ERR_VAL; - } else { - err_t err; - u8_t backlog; -#if TCP_LISTEN_BACKLOG - backlog = msg->msg.lb.backlog; -#else /* TCP_LISTEN_BACKLOG */ - backlog = TCP_DEFAULT_LISTEN_BACKLOG; -#endif /* TCP_LISTEN_BACKLOG */ -#if LWIP_IPV4 && LWIP_IPV6 - /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY, - * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen - */ - if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) && - (netconn_get_ipv6only(msg->conn) == 0)) { - /* change PCB type to IPADDR_TYPE_ANY */ - IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY); - IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - lpcb = tcp_listen_with_backlog_and_err(msg->conn->pcb.tcp, backlog, &err); - - if (lpcb == NULL) { - /* in this case, the old pcb is still allocated */ - msg->err = err; - } else { - /* delete the recvmbox and allocate the acceptmbox */ - if (sys_mbox_valid(&msg->conn->recvmbox)) { - /** @todo: should we drain the recvmbox here? */ - sys_mbox_free(&msg->conn->recvmbox); - sys_mbox_set_invalid(&msg->conn->recvmbox); - } - msg->err = ERR_OK; - if (!sys_mbox_valid(&msg->conn->acceptmbox)) { - msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); - } - if (msg->err == ERR_OK) { - msg->conn->state = NETCONN_LISTEN; - msg->conn->pcb.tcp = lpcb; - tcp_arg(msg->conn->pcb.tcp, msg->conn); - tcp_accept(msg->conn->pcb.tcp, accept_function); - } else { - /* since the old pcb is already deallocated, free lpcb now */ - tcp_close(lpcb); - msg->conn->pcb.tcp = NULL; - } - } - } - } else if (msg->conn->state == NETCONN_LISTEN) { - /* already listening, allow updating of the backlog */ - msg->err = ERR_OK; - tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog); - } - } else { - msg->err = ERR_ARG; - } - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* LWIP_TCP */ - -/** - * Send some data on a RAW or UDP pcb contained in a netconn - * Called from netconn_send - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_send(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - msg->err = ERR_CONN; - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { - msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); - } else { - msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); - } - break; -#endif -#if LWIP_UDP - case NETCONN_UDP: -#if LWIP_CHECKSUM_ON_COPY - if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { - msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p, - msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); - } else { - msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p, - &msg->msg.b->addr, msg->msg.b->port, - msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum); - } -#else /* LWIP_CHECKSUM_ON_COPY */ - if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { - msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p); - } else { - msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - break; -#endif /* LWIP_UDP */ - default: - break; - } - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_TCP -/** - * Indicate data has been received from a TCP pcb contained in a netconn - * Called from netconn_recv - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_recv(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - u32_t remaining = msg->msg.r.len; - do { - u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining; - tcp_recved(msg->conn->pcb.tcp, recved); - remaining -= recved; - } while (remaining != 0); - } - } - TCPIP_APIMSG_ACK(msg); -} - -#if TCP_LISTEN_BACKLOG -/** Indicate that a TCP pcb has been accepted - * Called from netconn_accept - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_accepted(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { - tcp_backlog_accepted(msg->conn->pcb.tcp); - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* TCP_LISTEN_BACKLOG */ - -/** - * See if more data needs to be written from a previous call to netconn_write. - * Called initially from lwip_netconn_do_write. If the first call can't send all data - * (because of low memory or empty send-buffer), this function is called again - * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the - * blocking application thread (waiting in netconn_write) is released. - * - * @param conn netconn (that is currently in state NETCONN_WRITE) to process - * @return ERR_OK - * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished - */ -static err_t -lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) -{ - err_t err; - const void *dataptr; - u16_t len, available; - u8_t write_finished = 0; - size_t diff; - u8_t dontblock; - u8_t apiflags; - - LWIP_ASSERT("conn != NULL", conn != NULL); - LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE)); - LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL); - LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL); - LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len", - conn->write_offset < conn->current_msg->msg.w.len); - - apiflags = conn->current_msg->msg.w.apiflags; - dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); - -#if LWIP_SO_SNDTIMEO - if ((conn->send_timeout != 0) && - ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { - write_finished = 1; - if (conn->write_offset == 0) { - /* nothing has been written */ - err = ERR_WOULDBLOCK; - conn->current_msg->msg.w.len = 0; - } else { - /* partial write */ - err = ERR_OK; - conn->current_msg->msg.w.len = conn->write_offset; - conn->write_offset = 0; - } - } else -#endif /* LWIP_SO_SNDTIMEO */ - { - dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset; - diff = conn->current_msg->msg.w.len - conn->write_offset; - if (diff > 0xffffUL) { /* max_u16_t */ - len = 0xffff; - apiflags |= TCP_WRITE_FLAG_MORE; - } else { - len = (u16_t)diff; - } - available = tcp_sndbuf(conn->pcb.tcp); - if (available < len) { - /* don't try to write more than sendbuf */ - len = available; - if (dontblock) { - if (!len) { - err = ERR_WOULDBLOCK; - goto err_mem; - } - } else { - apiflags |= TCP_WRITE_FLAG_MORE; - } - } - LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len)); - err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); - /* if OK or memory error, check available space */ - if ((err == ERR_OK) || (err == ERR_MEM)) { -err_mem: - if (dontblock && (len < conn->current_msg->msg.w.len)) { - /* non-blocking write did not write everything: mark the pcb non-writable - and let poll_tcp check writable space to mark the pcb writable again */ - API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); - conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE; - } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT) || - (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT)) { - /* The queued byte- or pbuf-count exceeds the configured low-water limit, - let select mark this pcb as non-writable. */ - API_EVENT(conn, NETCONN_EVT_SENDMINUS, len); - } - } - - if (err == ERR_OK) { - err_t out_err; - conn->write_offset += len; - if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) { - /* return sent length */ - conn->current_msg->msg.w.len = conn->write_offset; - /* everything was written */ - write_finished = 1; - } - out_err = tcp_output(conn->pcb.tcp); - if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { - /* If tcp_output fails with fatal error or no route is found, - don't try writing any more but return the error - to the application thread. */ - err = out_err; - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } else if (err == ERR_MEM) { - /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called. - For blocking sockets, we do NOT return to the application - thread, since ERR_MEM is only a temporary error! Non-blocking - will remain non-writable until sent_tcp/poll_tcp is called */ - - /* tcp_write returned ERR_MEM, try tcp_output anyway */ - err_t out_err = tcp_output(conn->pcb.tcp); - if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) { - /* If tcp_output fails with fatal error or no route is found, - don't try writing any more but return the error - to the application thread. */ - err = out_err; - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } else if (dontblock) { - /* non-blocking write is done on ERR_MEM */ - err = ERR_WOULDBLOCK; - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } else { - /* On errors != ERR_MEM, we don't try writing any more but return - the error to the application thread. */ - write_finished = 1; - conn->current_msg->msg.w.len = 0; - } - } - if (write_finished) { - /* everything was written: set back connection state - and back to application task */ - sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg); - conn->current_msg->err = err; - conn->current_msg = NULL; - conn->write_offset = 0; - conn->state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(conn, err); -#if LWIP_TCPIP_CORE_LOCKING - if (delayed) -#endif - { - sys_sem_signal(op_completed_sem); - } - } -#if LWIP_TCPIP_CORE_LOCKING - else { - return ERR_MEM; - } -#endif - return ERR_OK; -} -#endif /* LWIP_TCP */ - -/** - * Send some data on a TCP pcb contained in a netconn - * Called from netconn_write - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_write(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) { -#if LWIP_TCP - if (msg->conn->state != NETCONN_NONE) { - /* netconn is connecting, closing or in blocking write */ - msg->err = ERR_INPROGRESS; - } else if (msg->conn->pcb.tcp != NULL) { - msg->conn->state = NETCONN_WRITE; - /* set all the variables used by lwip_netconn_do_writemore */ - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0); - msg->conn->current_msg = msg; - msg->conn->write_offset = 0; -#if LWIP_TCPIP_CORE_LOCKING - if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_writemore(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG - since lwip_netconn_do_writemore ACKs it! */ - return; - } else { - msg->err = ERR_CONN; - } -#else /* LWIP_TCP */ - msg->err = ERR_VAL; -#endif /* LWIP_TCP */ -#if (LWIP_UDP || LWIP_RAW) - } else { - msg->err = ERR_VAL; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * Return a connection's local or remote address - * Called from netconn_getaddr - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_getaddr(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (msg->conn->pcb.ip != NULL) { - if (msg->msg.ad.local) { - ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), - msg->conn->pcb.ip->local_ip); - } else { - ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), - msg->conn->pcb.ip->remote_ip); - } - - msg->err = ERR_OK; - switch (NETCONNTYPE_GROUP(msg->conn->type)) { -#if LWIP_RAW - case NETCONN_RAW: - if (msg->msg.ad.local) { - API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; - } else { - /* return an error as connecting is only a helper for upper layers */ - msg->err = ERR_CONN; - } - break; -#endif /* LWIP_RAW */ -#if LWIP_UDP - case NETCONN_UDP: - if (msg->msg.ad.local) { - API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port; - } else { - if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) { - msg->err = ERR_CONN; - } else { - API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port; - } - } - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case NETCONN_TCP: - if ((msg->msg.ad.local == 0) && - ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) { - /* pcb is not connected and remote name is requested */ - msg->err = ERR_CONN; - } else { - API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port); - } - break; -#endif /* LWIP_TCP */ - default: - LWIP_ASSERT("invalid netconn_type", 0); - break; - } - } else { - msg->err = ERR_CONN; - } - TCPIP_APIMSG_ACK(msg); -} - -/** - * Close or half-shutdown a TCP pcb contained in a netconn - * Called from netconn_close - * In contrast to closing sockets, the netconn is not deallocated. - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_close(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - -#if LWIP_TCP - enum netconn_state state = msg->conn->state; - /* First check if this is a TCP netconn and if it is in a correct state - (LISTEN doesn't support half shutdown) */ - if ((msg->conn->pcb.tcp != NULL) && - (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) && - ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) { - /* Check if we are in a connected state */ - if (state == NETCONN_CONNECT) { - /* TCP connect in progress: cannot shutdown */ - msg->err = ERR_CONN; - } else if (state == NETCONN_WRITE) { -#if LWIP_NETCONN_FULLDUPLEX - if (msg->msg.sd.shut & NETCONN_SHUT_WR) { - /* close requested, abort running write */ - sys_sem_t* write_completed_sem; - LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL); - write_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg); - msg->conn->current_msg->err = ERR_CLSD; - msg->conn->current_msg = NULL; - msg->conn->write_offset = 0; - msg->conn->state = NETCONN_NONE; - state = NETCONN_NONE; - NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD); - sys_sem_signal(write_completed_sem); - } else { - LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD); - /* In this case, let the write continue and do not interfere with - conn->current_msg or conn->state! */ - msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0); - } - } - if (state == NETCONN_NONE) { -#else /* LWIP_NETCONN_FULLDUPLEX */ - msg->err = ERR_INPROGRESS; - } else { -#endif /* LWIP_NETCONN_FULLDUPLEX */ - if (msg->msg.sd.shut & NETCONN_SHUT_RD) { - /* Drain and delete mboxes */ - netconn_drain(msg->conn); - } - LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL && - msg->conn->write_offset == 0); - msg->conn->state = NETCONN_CLOSE; - msg->conn->current_msg = msg; -#if LWIP_TCPIP_CORE_LOCKING - if (lwip_netconn_do_close_internal(msg->conn, 0) != ERR_OK) { - LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE); - UNLOCK_TCPIP_CORE(); - sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); - LOCK_TCPIP_CORE(); - LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); - } -#else /* LWIP_TCPIP_CORE_LOCKING */ - lwip_netconn_do_close_internal(msg->conn); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */ - return; - } - } else -#endif /* LWIP_TCP */ - { - msg->err = ERR_CONN; - } - TCPIP_APIMSG_ACK(msg); -} - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** - * Join multicast groups for UDP netconns. - * Called from netconn_join_leave_group - * - * @param m the api_msg_msg pointing to the connection - */ -void -lwip_netconn_do_join_leave_group(void *m) -{ - struct api_msg *msg = (struct api_msg*)m; - - if (ERR_IS_FATAL(msg->conn->last_err)) { - msg->err = msg->conn->last_err; - } else { - if (msg->conn->pcb.tcp != NULL) { - if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) { -#if LWIP_UDP -#if LWIP_IPV6 && LWIP_IPV6_MLD - if (NETCONNTYPE_ISIPV6(msg->conn->type)) { - if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); - } else { - msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr))); - } - } - else -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - { -#if LWIP_IGMP - if (msg->msg.jl.join_or_leave == NETCONN_JOIN) { - msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); - } else { - msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)), - ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr))); - } -#endif /* LWIP_IGMP */ - } -#endif /* LWIP_UDP */ -#if (LWIP_TCP || LWIP_RAW) - } else { - msg->err = ERR_VAL; -#endif /* (LWIP_TCP || LWIP_RAW) */ - } - } else { - msg->err = ERR_CONN; - } - } - TCPIP_APIMSG_ACK(msg); -} -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/** - * Callback function that is called when DNS name is resolved - * (or on timeout). A waiting application thread is waked up by - * signaling the semaphore. - */ -static void -lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg) -{ - struct dns_api_msg *msg = (struct dns_api_msg*)arg; - - /* we trust the internal implementation to be correct :-) */ - LWIP_UNUSED_ARG(name); - - if (ipaddr == NULL) { - /* timeout or memory error */ - API_EXPR_DEREF(msg->err) = ERR_VAL; - } else { - /* address was resolved */ - API_EXPR_DEREF(msg->err) = ERR_OK; - API_EXPR_DEREF(msg->addr) = *ipaddr; - } - /* wake up the application task waiting in netconn_gethostbyname */ - sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); -} - -/** - * Execute a DNS query - * Called from netconn_gethostbyname - * - * @param arg the dns_api_msg pointing to the query - */ -void -lwip_netconn_do_gethostbyname(void *arg) -{ - struct dns_api_msg *msg = (struct dns_api_msg*)arg; - u8_t addrtype = -#if LWIP_IPV4 && LWIP_IPV6 - msg->dns_addrtype; -#else - LWIP_DNS_ADDRTYPE_DEFAULT; -#endif - - API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name, - API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype); - if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) { - /* on error or immediate success, wake up the application - * task waiting in netconn_gethostbyname */ - sys_sem_signal(API_EXPR_REF_SEM(msg->sem)); - } -} -#endif /* LWIP_DNS */ - -#endif /* LWIP_NETCONN */ diff --git a/components/net/lwip-2.0.2/src/api/err.c b/components/net/lwip-2.0.2/src/api/err.c deleted file mode 100644 index 35e9c025ea..0000000000 --- a/components/net/lwip-2.0.2/src/api/err.c +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file - * Error Management module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/err.h" -#include "lwip/def.h" -#include "lwip/sys.h" - -#include "lwip/errno.h" - -#if !NO_SYS -/** Table to quickly map an lwIP error (err_t) to a socket error - * by using -err as an index */ -static const int err_to_errno_table[] = { - 0, /* ERR_OK 0 No error, everything OK. */ - ENOMEM, /* ERR_MEM -1 Out of memory error. */ - ENOBUFS, /* ERR_BUF -2 Buffer error. */ - EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */ - EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ - EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ - EINVAL, /* ERR_VAL -6 Illegal value. */ - EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ - EADDRINUSE, /* ERR_USE -8 Address in use. */ - EALREADY, /* ERR_ALREADY -9 Already connecting. */ - EISCONN, /* ERR_ISCONN -10 Conn already established.*/ - ENOTCONN, /* ERR_CONN -11 Not connected. */ - -1, /* ERR_IF -12 Low-level netif error */ - ECONNABORTED, /* ERR_ABRT -13 Connection aborted. */ - ECONNRESET, /* ERR_RST -14 Connection reset. */ - ENOTCONN, /* ERR_CLSD -15 Connection closed. */ - EIO /* ERR_ARG -16 Illegal argument. */ -}; - -int -err_to_errno(err_t err) -{ - if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_to_errno_table))) { - return EIO; - } - return err_to_errno_table[-err]; -} -#endif /* !NO_SYS */ - -#ifdef LWIP_DEBUG - -static const char *err_strerr[] = { - "Ok.", /* ERR_OK 0 */ - "Out of memory error.", /* ERR_MEM -1 */ - "Buffer error.", /* ERR_BUF -2 */ - "Timeout.", /* ERR_TIMEOUT -3 */ - "Routing problem.", /* ERR_RTE -4 */ - "Operation in progress.", /* ERR_INPROGRESS -5 */ - "Illegal value.", /* ERR_VAL -6 */ - "Operation would block.", /* ERR_WOULDBLOCK -7 */ - "Address in use.", /* ERR_USE -8 */ - "Already connecting.", /* ERR_ALREADY -9 */ - "Already connected.", /* ERR_ISCONN -10 */ - "Not connected.", /* ERR_CONN -11 */ - "Low-level netif error.", /* ERR_IF -12 */ - "Connection aborted.", /* ERR_ABRT -13 */ - "Connection reset.", /* ERR_RST -14 */ - "Connection closed.", /* ERR_CLSD -15 */ - "Illegal argument." /* ERR_ARG -16 */ -}; - -/** - * Convert an lwip internal error to a string representation. - * - * @param err an lwip internal err_t - * @return a string representation for err - */ -const char * -lwip_strerr(err_t err) -{ - if ((err > 0) || (-err >= (err_t)LWIP_ARRAYSIZE(err_strerr))) { - return "Unknown error."; - } - return err_strerr[-err]; -} - -#endif /* LWIP_DEBUG */ diff --git a/components/net/lwip-2.0.2/src/api/netbuf.c b/components/net/lwip-2.0.2/src/api/netbuf.c deleted file mode 100644 index eb250115ff..0000000000 --- a/components/net/lwip-2.0.2/src/api/netbuf.c +++ /dev/null @@ -1,246 +0,0 @@ -/** - * @file - * Network buffer management - * - * @defgroup netbuf Network buffers - * @ingroup netconn - * Network buffer descriptor for @ref netconn. Based on @ref pbuf internally - * to avoid copying data around.\n - * Buffers must not be shared accross multiple threads, all functions except - * netbuf_new() and netbuf_delete() are not thread-safe. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netbuf.h" -#include "lwip/memp.h" - -#include - -/** - * @ingroup netbuf - * Create (allocate) and initialize a new netbuf. - * The netbuf doesn't yet contain a packet buffer! - * - * @return a pointer to a new netbuf - * NULL on lack of memory - */ -struct -netbuf *netbuf_new(void) -{ - struct netbuf *buf; - - buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); - if (buf != NULL) { - memset(buf, 0, sizeof(struct netbuf)); - } - return buf; -} - -/** - * @ingroup netbuf - * Deallocate a netbuf allocated by netbuf_new(). - * - * @param buf pointer to a netbuf allocated by netbuf_new() - */ -void -netbuf_delete(struct netbuf *buf) -{ - if (buf != NULL) { - if (buf->p != NULL) { - pbuf_free(buf->p); - buf->p = buf->ptr = NULL; - } - memp_free(MEMP_NETBUF, buf); - } -} - -/** - * @ingroup netbuf - * Allocate memory for a packet buffer for a given netbuf. - * - * @param buf the netbuf for which to allocate a packet buffer - * @param size the size of the packet buffer to allocate - * @return pointer to the allocated memory - * NULL if no memory could be allocated - */ -void * -netbuf_alloc(struct netbuf *buf, u16_t size) -{ - LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); - - /* Deallocate any previously allocated memory. */ - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); - if (buf->p == NULL) { - return NULL; - } - LWIP_ASSERT("check that first pbuf can hold size", - (buf->p->len >= size)); - buf->ptr = buf->p; - return buf->p->payload; -} - -/** - * @ingroup netbuf - * Free the packet buffer included in a netbuf - * - * @param buf pointer to the netbuf which contains the packet buffer to free - */ -void -netbuf_free(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_free: invalid buf", (buf != NULL), return;); - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = buf->ptr = NULL; -} - -/** - * @ingroup netbuf - * Let a netbuf reference existing (non-volatile) data. - * - * @param buf netbuf which should reference the data - * @param dataptr pointer to the data to reference - * @param size size of the data - * @return ERR_OK if data is referenced - * ERR_MEM if data couldn't be referenced due to lack of memory - */ -err_t -netbuf_ref(struct netbuf *buf, const void *dataptr, u16_t size) -{ - LWIP_ERROR("netbuf_ref: invalid buf", (buf != NULL), return ERR_ARG;); - if (buf->p != NULL) { - pbuf_free(buf->p); - } - buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); - if (buf->p == NULL) { - buf->ptr = NULL; - return ERR_MEM; - } - ((struct pbuf_rom*)buf->p)->payload = dataptr; - buf->p->len = buf->p->tot_len = size; - buf->ptr = buf->p; - return ERR_OK; -} - -/** - * @ingroup netbuf - * Chain one netbuf to another (@see pbuf_chain) - * - * @param head the first netbuf - * @param tail netbuf to chain after head, freed by this function, may not be reference after returning - */ -void -netbuf_chain(struct netbuf *head, struct netbuf *tail) -{ - LWIP_ERROR("netbuf_chain: invalid head", (head != NULL), return;); - LWIP_ERROR("netbuf_chain: invalid tail", (tail != NULL), return;); - pbuf_cat(head->p, tail->p); - head->ptr = head->p; - memp_free(MEMP_NETBUF, tail); -} - -/** - * @ingroup netbuf - * Get the data pointer and length of the data inside a netbuf. - * - * @param buf netbuf to get the data from - * @param dataptr pointer to a void pointer where to store the data pointer - * @param len pointer to an u16_t where the length of the data is stored - * @return ERR_OK if the information was retrieved, - * ERR_BUF on error. - */ -err_t -netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) -{ - LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;); - LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;); - LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;); - - if (buf->ptr == NULL) { - return ERR_BUF; - } - *dataptr = buf->ptr->payload; - *len = buf->ptr->len; - return ERR_OK; -} - -/** - * @ingroup netbuf - * Move the current data pointer of a packet buffer contained in a netbuf - * to the next part. - * The packet buffer itself is not modified. - * - * @param buf the netbuf to modify - * @return -1 if there is no next part - * 1 if moved to the next part but now there is no next part - * 0 if moved to the next part and there are still more parts - */ -s8_t -netbuf_next(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_next: invalid buf", (buf != NULL), return -1;); - if (buf->ptr->next == NULL) { - return -1; - } - buf->ptr = buf->ptr->next; - if (buf->ptr->next == NULL) { - return 1; - } - return 0; -} - -/** - * @ingroup netbuf - * Move the current data pointer of a packet buffer contained in a netbuf - * to the beginning of the packet. - * The packet buffer itself is not modified. - * - * @param buf the netbuf to modify - */ -void -netbuf_first(struct netbuf *buf) -{ - LWIP_ERROR("netbuf_first: invalid buf", (buf != NULL), return;); - buf->ptr = buf->p; -} - -#endif /* LWIP_NETCONN */ diff --git a/components/net/lwip-2.0.2/src/api/netdb.c b/components/net/lwip-2.0.2/src/api/netdb.c deleted file mode 100644 index ccd9586fda..0000000000 --- a/components/net/lwip-2.0.2/src/api/netdb.c +++ /dev/null @@ -1,413 +0,0 @@ -/** - * @file - * API functions for name resolving - * - * @defgroup netdbapi NETDB API - * @ingroup socket - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ - -#include "lwip/netdb.h" - -#if LWIP_DNS && LWIP_SOCKET - -#include "lwip/err.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/api.h" -#include "lwip/dns.h" - -#include /* memset */ -#include /* atoi */ - -/** helper struct for gethostbyname_r to access the char* buffer */ -struct gethostbyname_r_helper { - ip_addr_t *addr_list[2]; - ip_addr_t addr; - char *aliases; -}; - -/** h_errno is exported in netdb.h for access by applications. */ -#if LWIP_DNS_API_DECLARE_H_ERRNO -int h_errno; -#endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ - -/** define "hostent" variables storage: 0 if we use a static (but unprotected) - * set of variables for lwip_gethostbyname, 1 if we use a local storage */ -#ifndef LWIP_DNS_API_HOSTENT_STORAGE -#define LWIP_DNS_API_HOSTENT_STORAGE 0 -#endif - -/** define "hostent" variables storage */ -#if LWIP_DNS_API_HOSTENT_STORAGE -#define HOSTENT_STORAGE -#else -#define HOSTENT_STORAGE static -#endif /* LWIP_DNS_API_STATIC_HOSTENT */ - -/** - * Returns an entry containing addresses of address family AF_INET - * for the host with name name. - * Due to dns_gethostbyname limitations, only one address is returned. - * - * @param name the hostname to resolve - * @return an entry containing addresses of address family AF_INET - * for the host with name name - */ -struct hostent* -lwip_gethostbyname(const char *name) -{ - err_t err; - ip_addr_t addr; - - /* buffer variables for lwip_gethostbyname() */ - HOSTENT_STORAGE struct hostent s_hostent; - HOSTENT_STORAGE char *s_aliases; - HOSTENT_STORAGE ip_addr_t s_hostent_addr; - HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2]; - HOSTENT_STORAGE char s_hostname[DNS_MAX_NAME_LENGTH + 1]; - - /* query host IP address */ - err = netconn_gethostbyname(name, &addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); - h_errno = HOST_NOT_FOUND; - return NULL; - } - - /* fill hostent */ - s_hostent_addr = addr; - s_phostent_addr[0] = &s_hostent_addr; - s_phostent_addr[1] = NULL; - strncpy(s_hostname, name, DNS_MAX_NAME_LENGTH); - s_hostname[DNS_MAX_NAME_LENGTH] = 0; - s_hostent.h_name = s_hostname; - s_aliases = NULL; - s_hostent.h_aliases = &s_aliases; - s_hostent.h_addrtype = AF_INET; - s_hostent.h_length = sizeof(ip_addr_t); - s_hostent.h_addr_list = (char**)&s_phostent_addr; - -#if DNS_DEBUG - /* dump hostent */ - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_name == %s\n", s_hostent.h_name)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_aliases == %p\n", (void*)s_hostent.h_aliases)); - /* h_aliases are always empty */ - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addrtype == %d\n", s_hostent.h_addrtype)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_length == %d\n", s_hostent.h_length)); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list == %p\n", (void*)s_hostent.h_addr_list)); - if (s_hostent.h_addr_list != NULL) { - u8_t idx; - for (idx=0; s_hostent.h_addr_list[idx]; idx++) { - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx])); - LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ipaddr_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx]))); - } - } -#endif /* DNS_DEBUG */ - -#if LWIP_DNS_API_HOSTENT_STORAGE - /* this function should return the "per-thread" hostent after copy from s_hostent */ - return sys_thread_hostent(&s_hostent); -#else - return &s_hostent; -#endif /* LWIP_DNS_API_HOSTENT_STORAGE */ -} - -/** - * Thread-safe variant of lwip_gethostbyname: instead of using a static - * buffer, this function takes buffer and errno pointers as arguments - * and uses these for the result. - * - * @param name the hostname to resolve - * @param ret pre-allocated struct where to store the result - * @param buf pre-allocated buffer where to store additional data - * @param buflen the size of buf - * @param result pointer to a hostent pointer that is set to ret on success - * and set to zero on error - * @param h_errnop pointer to an int where to store errors (instead of modifying - * the global h_errno) - * @return 0 on success, non-zero on error, additional error information - * is stored in *h_errnop instead of h_errno to be thread-safe - */ -int -lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop) -{ - err_t err; - struct gethostbyname_r_helper *h; - char *hostname; - size_t namelen; - int lh_errno; - - if (h_errnop == NULL) { - /* ensure h_errnop is never NULL */ - h_errnop = &lh_errno; - } - - if (result == NULL) { - /* not all arguments given */ - *h_errnop = EINVAL; - return -1; - } - /* first thing to do: set *result to nothing */ - *result = NULL; - if ((name == NULL) || (ret == NULL) || (buf == NULL)) { - /* not all arguments given */ - *h_errnop = EINVAL; - return -1; - } - - namelen = strlen(name); - if (buflen < (sizeof(struct gethostbyname_r_helper) + namelen + 1 + (MEM_ALIGNMENT - 1))) { - /* buf can't hold the data needed + a copy of name */ - *h_errnop = ERANGE; - return -1; - } - - h = (struct gethostbyname_r_helper*)LWIP_MEM_ALIGN(buf); - hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper); - - /* query host IP address */ - err = netconn_gethostbyname(name, &h->addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); - *h_errnop = HOST_NOT_FOUND; - return -1; - } - - /* copy the hostname into buf */ - MEMCPY(hostname, name, namelen); - hostname[namelen] = 0; - - /* fill hostent */ - h->addr_list[0] = &h->addr; - h->addr_list[1] = NULL; - h->aliases = NULL; - ret->h_name = hostname; - ret->h_aliases = &h->aliases; - ret->h_addrtype = AF_INET; - ret->h_length = sizeof(ip_addr_t); - ret->h_addr_list = (char**)&h->addr_list; - - /* set result != NULL */ - *result = ret; - - /* return success */ - return 0; -} - -/** - * Frees one or more addrinfo structures returned by getaddrinfo(), along with - * any additional storage associated with those structures. If the ai_next field - * of the structure is not null, the entire list of structures is freed. - * - * @param ai struct addrinfo to free - */ -void -lwip_freeaddrinfo(struct addrinfo *ai) -{ - struct addrinfo *next; - - while (ai != NULL) { - next = ai->ai_next; - memp_free(MEMP_NETDB, ai); - ai = next; - } -} - -/** - * Translates the name of a service location (for example, a host name) and/or - * a service name and returns a set of socket addresses and associated - * information to be used in creating a socket with which to address the - * specified service. - * Memory for the result is allocated internally and must be freed by calling - * lwip_freeaddrinfo()! - * - * Due to a limitation in dns_gethostbyname, only the first address of a - * host is returned. - * Also, service names are not supported (only port numbers)! - * - * @param nodename descriptive name or address string of the host - * (may be NULL -> local address) - * @param servname port number as string of NULL - * @param hints structure containing input values that set socktype and protocol - * @param res pointer to a pointer where to store the result (set to NULL on failure) - * @return 0 on success, non-zero on failure - * - * @todo: implement AI_V4MAPPED, AI_ADDRCONFIG - */ -int -lwip_getaddrinfo(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) -{ - err_t err; - ip_addr_t addr; - struct addrinfo *ai; - struct sockaddr_storage *sa = NULL; - int port_nr = 0; - size_t total_size; - size_t namelen = 0; - int ai_family; - - if (res == NULL) { - return EAI_FAIL; - } - *res = NULL; - if ((nodename == NULL) && (servname == NULL)) { - return EAI_NONAME; - } - - if (hints != NULL) { - ai_family = hints->ai_family; - if ((ai_family != AF_UNSPEC) -#if LWIP_IPV4 - && (ai_family != AF_INET) -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - && (ai_family != AF_INET6) -#endif /* LWIP_IPV6 */ - ) { - return EAI_FAMILY; - } - } else { - ai_family = AF_UNSPEC; - } - - if (servname != NULL) { - /* service name specified: convert to port number - * @todo?: currently, only ASCII integers (port numbers) are supported (AI_NUMERICSERV)! */ - port_nr = atoi(servname); - if ((port_nr <= 0) || (port_nr > 0xffff)) { - return EAI_SERVICE; - } - } - - if (nodename != NULL) { - /* service location specified, try to resolve */ - if ((hints != NULL) && (hints->ai_flags & AI_NUMERICHOST)) { - /* no DNS lookup, just parse for an address string */ - if (!ipaddr_aton(nodename, &addr)) { - return EAI_NONAME; - } -#if LWIP_IPV4 && LWIP_IPV6 - if ((IP_IS_V6_VAL(addr) && ai_family == AF_INET) || - (IP_IS_V4_VAL(addr) && ai_family == AF_INET6)) { - return EAI_NONAME; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - } else { -#if LWIP_IPV4 && LWIP_IPV6 - /* AF_UNSPEC: prefer IPv4 */ - u8_t type = NETCONN_DNS_IPV4_IPV6; - if (ai_family == AF_INET) { - type = NETCONN_DNS_IPV4; - } else if (ai_family == AF_INET6) { - type = NETCONN_DNS_IPV6; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - err = netconn_gethostbyname_addrtype(nodename, &addr, type); - if (err != ERR_OK) { - return EAI_FAIL; - } - } - } else { - /* service location specified, use loopback address */ - if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { - ip_addr_set_any(ai_family == AF_INET6, &addr); - } else { - ip_addr_set_loopback(ai_family == AF_INET6, &addr); - } - } - - total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); - if (nodename != NULL) { - namelen = strlen(nodename); - if (namelen > DNS_MAX_NAME_LENGTH) { - /* invalid name length */ - return EAI_FAIL; - } - LWIP_ASSERT("namelen is too long", total_size + namelen + 1 > total_size); - total_size += namelen + 1; - } - /* If this fails, please report to lwip-devel! :-) */ - LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!", - total_size <= NETDB_ELEM_SIZE); - ai = (struct addrinfo *)memp_malloc(MEMP_NETDB); - if (ai == NULL) { - return EAI_MEMORY; - } - memset(ai, 0, total_size); - /* cast through void* to get rid of alignment warnings */ - sa = (struct sockaddr_storage *)(void*)((u8_t*)ai + sizeof(struct addrinfo)); - if (IP_IS_V6_VAL(addr)) { -#if LWIP_IPV6 - struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa; - /* set up sockaddr */ - inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); - sa6->sin6_family = AF_INET6; - sa6->sin6_len = sizeof(struct sockaddr_in6); - sa6->sin6_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET6; -#endif /* LWIP_IPV6 */ - } else { -#if LWIP_IPV4 - struct sockaddr_in *sa4 = (struct sockaddr_in*)sa; - /* set up sockaddr */ - inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); - sa4->sin_family = AF_INET; - sa4->sin_len = sizeof(struct sockaddr_in); - sa4->sin_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET; -#endif /* LWIP_IPV4 */ - } - - /* set up addrinfo */ - if (hints != NULL) { - /* copy socktype & protocol from hints if specified */ - ai->ai_socktype = hints->ai_socktype; - ai->ai_protocol = hints->ai_protocol; - } - if (nodename != NULL) { - /* copy nodename to canonname if specified */ - ai->ai_canonname = ((char*)ai + sizeof(struct addrinfo) + sizeof(struct sockaddr_storage)); - MEMCPY(ai->ai_canonname, nodename, namelen); - ai->ai_canonname[namelen] = 0; - } - ai->ai_addrlen = sizeof(struct sockaddr_storage); - ai->ai_addr = (struct sockaddr*)sa; - - *res = ai; - - return 0; -} - -#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/components/net/lwip-2.0.2/src/api/netifapi.c b/components/net/lwip-2.0.2/src/api/netifapi.c deleted file mode 100644 index fef05a34dc..0000000000 --- a/components/net/lwip-2.0.2/src/api/netifapi.c +++ /dev/null @@ -1,221 +0,0 @@ -/** - * @file - * Network Interface Sequential API module - * - * @defgroup netifapi NETIF API - * @ingroup sequential_api - * Thread-safe functions to be called from non-TCPIP threads - * - * @defgroup netifapi_netif NETIF related - * @ingroup netifapi - * To be called from non-TCPIP threads - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netifapi.h" -#include "lwip/memp.h" -#include "lwip/priv/tcpip_priv.h" - -#define NETIFAPI_VAR_REF(name) API_VAR_REF(name) -#define NETIFAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct netifapi_msg, name) -#define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) -#define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) - -/** - * Call netif_add() inside the tcpip_thread context. - */ -static err_t -netifapi_do_netif_add(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct netifapi_msg */ - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; - - if (!netif_add( msg->netif, -#if LWIP_IPV4 - API_EXPR_REF(msg->msg.add.ipaddr), - API_EXPR_REF(msg->msg.add.netmask), - API_EXPR_REF(msg->msg.add.gw), -#endif /* LWIP_IPV4 */ - msg->msg.add.state, - msg->msg.add.init, - msg->msg.add.input)) { - return ERR_IF; - } else { - return ERR_OK; - } -} - -#if LWIP_IPV4 -/** - * Call netif_set_addr() inside the tcpip_thread context. - */ -static err_t -netifapi_do_netif_set_addr(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct netifapi_msg */ - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; - - netif_set_addr( msg->netif, - API_EXPR_REF(msg->msg.add.ipaddr), - API_EXPR_REF(msg->msg.add.netmask), - API_EXPR_REF(msg->msg.add.gw)); - return ERR_OK; -} -#endif /* LWIP_IPV4 */ - -/** - * Call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) inside the - * tcpip_thread context. - */ -static err_t -netifapi_do_netif_common(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct netifapi_msg */ - struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; - - if (msg->msg.common.errtfunc != NULL) { - return msg->msg.common.errtfunc(msg->netif); - } else { - msg->msg.common.voidfunc(msg->netif); - return ERR_OK; - } -} - -/** - * @ingroup netifapi_netif - * Call netif_add() in a thread-safe way by running that function inside the - * tcpip_thread context. - * - * @note for params @see netif_add() - */ -err_t -netifapi_netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input) -{ - err_t err; - NETIFAPI_VAR_DECLARE(msg); - NETIFAPI_VAR_ALLOC(msg); - -#if LWIP_IPV4 - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY4; - } - if (netmask == NULL) { - netmask = IP4_ADDR_ANY4; - } - if (gw == NULL) { - gw = IP4_ADDR_ANY4; - } -#endif /* LWIP_IPV4 */ - - NETIFAPI_VAR_REF(msg).netif = netif; -#if LWIP_IPV4 - NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); - NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); - NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); -#endif /* LWIP_IPV4 */ - NETIFAPI_VAR_REF(msg).msg.add.state = state; - NETIFAPI_VAR_REF(msg).msg.add.init = init; - NETIFAPI_VAR_REF(msg).msg.add.input = input; - err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -} - -#if LWIP_IPV4 -/** - * @ingroup netifapi_netif - * Call netif_set_addr() in a thread-safe way by running that function inside the - * tcpip_thread context. - * - * @note for params @see netif_set_addr() - */ -err_t -netifapi_netif_set_addr(struct netif *netif, - const ip4_addr_t *ipaddr, - const ip4_addr_t *netmask, - const ip4_addr_t *gw) -{ - err_t err; - NETIFAPI_VAR_DECLARE(msg); - NETIFAPI_VAR_ALLOC(msg); - - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY4; - } - if (netmask == NULL) { - netmask = IP4_ADDR_ANY4; - } - if (gw == NULL) { - gw = IP4_ADDR_ANY4; - } - - NETIFAPI_VAR_REF(msg).netif = netif; - NETIFAPI_VAR_REF(msg).msg.add.ipaddr = NETIFAPI_VAR_REF(ipaddr); - NETIFAPI_VAR_REF(msg).msg.add.netmask = NETIFAPI_VAR_REF(netmask); - NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); - err = tcpip_api_call(netifapi_do_netif_set_addr, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -} -#endif /* LWIP_IPV4 */ - -/** - * call the "errtfunc" (or the "voidfunc" if "errtfunc" is NULL) in a thread-safe - * way by running that function inside the tcpip_thread context. - * - * @note use only for functions where there is only "netif" parameter. - */ -err_t -netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - netifapi_errt_fn errtfunc) -{ - err_t err; - NETIFAPI_VAR_DECLARE(msg); - NETIFAPI_VAR_ALLOC(msg); - - NETIFAPI_VAR_REF(msg).netif = netif; - NETIFAPI_VAR_REF(msg).msg.common.voidfunc = voidfunc; - NETIFAPI_VAR_REF(msg).msg.common.errtfunc = errtfunc; - err = tcpip_api_call(netifapi_do_netif_common, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -} - -#endif /* LWIP_NETIF_API */ diff --git a/components/net/lwip-2.0.2/src/api/sockets.c b/components/net/lwip-2.0.2/src/api/sockets.c deleted file mode 100644 index 87e0f86dff..0000000000 --- a/components/net/lwip-2.0.2/src/api/sockets.c +++ /dev/null @@ -1,2852 +0,0 @@ -/** - * @file - * Sockets BSD-Like API module - * - * @defgroup socket Socket API - * @ingroup sequential_api - * BSD-style socket API.\n - * Thread-safe, to be called from non-TCPIP threads only.\n - * Can be activated by defining @ref LWIP_SOCKET to 1.\n - * Header is in posix/sys/socket.h\b - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * Improved by Marc Boucher and David Haas - * - */ - -#include "lwip/opt.h" - -#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sockets.h" -#include "lwip/api.h" -#include "lwip/sys.h" -#include "lwip/igmp.h" -#include "lwip/inet.h" -#include "lwip/tcp.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/priv/tcpip_priv.h" -#if LWIP_CHECKSUM_ON_COPY -#include "lwip/inet_chksum.h" -#endif - -#include - -/* If the netconn API is not required publicly, then we include the necessary - files here to get the implementation */ -#if !LWIP_NETCONN -#undef LWIP_NETCONN -#define LWIP_NETCONN 1 -#include "api_msg.c" -#include "api_lib.c" -#include "netbuf.c" -#undef LWIP_NETCONN -#define LWIP_NETCONN 0 -#endif - -#if LWIP_IPV4 -#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ - (sin)->sin_len = sizeof(struct sockaddr_in); \ - (sin)->sin_family = AF_INET; \ - (sin)->sin_port = lwip_htons((port)); \ - inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ - memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0) -#define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \ - inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \ - (port) = lwip_ntohs((sin)->sin_port); }while(0) -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -#define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ - (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ - (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = lwip_htons((port)); \ - (sin6)->sin6_flowinfo = 0; \ - inet6_addr_from_ip6addr(&(sin6)->sin6_addr, ipaddr); \ - (sin6)->sin6_scope_id = 0; }while(0) -#define SOCKADDR6_TO_IP6ADDR_PORT(sin6, ipaddr, port) do { \ - inet6_addr_to_ip6addr(ip_2_ip6(ipaddr), &((sin6)->sin6_addr)); \ - (port) = lwip_ntohs((sin6)->sin6_port); }while(0) -#endif /* LWIP_IPV6 */ - -#if LWIP_IPV4 && LWIP_IPV6 -static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port); - -#define IS_SOCK_ADDR_LEN_VALID(namelen) (((namelen) == sizeof(struct sockaddr_in)) || \ - ((namelen) == sizeof(struct sockaddr_in6))) -#define IS_SOCK_ADDR_TYPE_VALID(name) (((name)->sa_family == AF_INET) || \ - ((name)->sa_family == AF_INET6)) -#define SOCK_ADDR_TYPE_MATCH(name, sock) \ - ((((name)->sa_family == AF_INET) && !(NETCONNTYPE_ISIPV6((sock)->conn->type))) || \ - (((name)->sa_family == AF_INET6) && (NETCONNTYPE_ISIPV6((sock)->conn->type)))) -#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) do { \ - if (IP_IS_V6(ipaddr)) { \ - IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port); \ - } else { \ - IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port); \ - } } while(0) -#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) sockaddr_to_ipaddr_port(sockaddr, ipaddr, &(port)) -#define DOMAIN_TO_NETCONN_TYPE(domain, type) (((domain) == AF_INET) ? \ - (type) : (enum netconn_type)((type) | NETCONN_TYPE_IPV6)) -#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ -#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in6)) -#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET6) -#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 -#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ - IP6ADDR_PORT_TO_SOCKADDR((struct sockaddr_in6*)(void*)(sockaddr), ip_2_ip6(ipaddr), port) -#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ - SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) -#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) -#else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ -#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) -#define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) -#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 -#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ - IP4ADDR_PORT_TO_SOCKADDR((struct sockaddr_in*)(void*)(sockaddr), ip_2_ip4(ipaddr), port) -#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ - SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, port) -#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) -#endif /* LWIP_IPV6 */ - -#define IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) (((name)->sa_family == AF_UNSPEC) || \ - IS_SOCK_ADDR_TYPE_VALID(name)) -#define SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock) (((name)->sa_family == AF_UNSPEC) || \ - SOCK_ADDR_TYPE_MATCH(name, sock)) -#define IS_SOCK_ADDR_ALIGNED(name) ((((mem_ptr_t)(name)) % 4) == 0) - - -#define LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype) do { if ((optlen) < sizeof(opttype)) { return EINVAL; }}while(0) -#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, opttype) do { \ - LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ - if ((sock)->conn == NULL) { return EINVAL; } }while(0) -#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype) do { \ - LWIP_SOCKOPT_CHECK_OPTLEN(optlen, opttype); \ - if (((sock)->conn == NULL) || ((sock)->conn->pcb.tcp == NULL)) { return EINVAL; } }while(0) -#define LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, opttype, netconntype) do { \ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, opttype); \ - if (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) != netconntype) { return ENOPROTOOPT; } }while(0) - - -#define LWIP_SETGETSOCKOPT_DATA_VAR_REF(name) API_VAR_REF(name) -#define LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(name) API_VAR_DECLARE(struct lwip_setgetsockopt_data, name) -#define LWIP_SETGETSOCKOPT_DATA_VAR_FREE(name) API_VAR_FREE(MEMP_SOCKET_SETGETSOCKOPT_DATA, name) -#if LWIP_MPU_COMPATIBLE -#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) do { \ - name = (struct lwip_setgetsockopt_data *)memp_malloc(MEMP_SOCKET_SETGETSOCKOPT_DATA); \ - if (name == NULL) { \ - sock_set_errno(sock, ENOMEM); \ - return -1; \ - } }while(0) -#else /* LWIP_MPU_COMPATIBLE */ -#define LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(name, sock) -#endif /* LWIP_MPU_COMPATIBLE */ - -#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD -#define LWIP_SO_SNDRCVTIMEO_OPTTYPE int -#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) (*(int *)(optval) = (val)) -#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((s32_t)*(const int*)(optval)) -#else -#define LWIP_SO_SNDRCVTIMEO_OPTTYPE struct timeval -#define LWIP_SO_SNDRCVTIMEO_SET(optval, val) do { \ - s32_t loc = (val); \ - ((struct timeval *)(optval))->tv_sec = (loc) / 1000U; \ - ((struct timeval *)(optval))->tv_usec = ((loc) % 1000U) * 1000U; }while(0) -#define LWIP_SO_SNDRCVTIMEO_GET_MS(optval) ((((const struct timeval *)(optval))->tv_sec * 1000U) + (((const struct timeval *)(optval))->tv_usec / 1000U)) -#endif - -#define NUM_SOCKETS MEMP_NUM_NETCONN - -/** This is overridable for the rare case where more than 255 threads - * select on the same socket... - */ -#ifndef SELWAIT_T -#define SELWAIT_T u8_t -#endif - -#include -#ifdef SAL_USING_POSIX -#include -#endif - -/** Contains all internal pointers and states used for a socket */ -struct lwip_sock { - /** sockets currently are built on netconns, each socket has one netconn */ - struct netconn *conn; - /** data that was left from the previous read */ - void *lastdata; - /** offset in the data that was left from the previous read */ - u16_t lastoffset; - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ - s16_t rcvevent; - /** number of times data was ACKed (free send buffer), set by event_callback(), - tested by select */ - u16_t sendevent; - /** error happened for this socket, set by event_callback(), tested by select */ - u16_t errevent; - /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ - u8_t err; - /** counter of how many threads are waiting for this socket using select */ - SELWAIT_T select_waiting; - -#ifdef SAL_USING_POSIX - rt_wqueue_t wait_head; -#endif -}; - -#if LWIP_NETCONN_SEM_PER_THREAD -#define SELECT_SEM_T sys_sem_t* -#define SELECT_SEM_PTR(sem) (sem) -#else /* LWIP_NETCONN_SEM_PER_THREAD */ -#define SELECT_SEM_T sys_sem_t -#define SELECT_SEM_PTR(sem) (&(sem)) -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - -/** Description for a task waiting in select */ -struct lwip_select_cb { - /** Pointer to the next waiting task */ - struct lwip_select_cb *next; - /** Pointer to the previous waiting task */ - struct lwip_select_cb *prev; - /** readset passed to select */ - fd_set *readset; - /** writeset passed to select */ - fd_set *writeset; - /** unimplemented: exceptset passed to select */ - fd_set *exceptset; - /** don't signal the same semaphore twice: set to 1 when signalled */ - int sem_signalled; - /** semaphore to wake up a task waiting for select */ - SELECT_SEM_T sem; -}; - -/** A struct sockaddr replacement that has the same alignment as sockaddr_in/ - * sockaddr_in6 if instantiated. - */ -union sockaddr_aligned { - struct sockaddr sa; -#if LWIP_IPV6 - struct sockaddr_in6 sin6; -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - struct sockaddr_in sin; -#endif /* LWIP_IPV4 */ -}; - -#if LWIP_IGMP -/* Define the number of IPv4 multicast memberships, default is one per socket */ -#ifndef LWIP_SOCKET_MAX_MEMBERSHIPS -#define LWIP_SOCKET_MAX_MEMBERSHIPS NUM_SOCKETS -#endif - -/* This is to keep track of IP_ADD_MEMBERSHIP calls to drop the membership when - a socket is closed */ -struct lwip_socket_multicast_pair { - /** the socket */ - struct lwip_sock* sock; - /** the interface address */ - ip4_addr_t if_addr; - /** the group address */ - ip4_addr_t multi_addr; -}; - -struct lwip_socket_multicast_pair socket_ipv4_multicast_memberships[LWIP_SOCKET_MAX_MEMBERSHIPS]; - -static int lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); -static void lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr); -static void lwip_socket_drop_registered_memberships(int s); -#endif /* LWIP_IGMP */ - -/** The global array of available sockets */ -static struct lwip_sock sockets[NUM_SOCKETS]; -/** The global list of tasks waiting for select */ -static struct lwip_select_cb *select_cb_list; -/** This counter is increased from lwip_select when the list is changed - and checked in event_callback to see if it has changed. */ -static volatile int select_cb_ctr; - -#if LWIP_SOCKET_SET_ERRNO -#ifndef set_errno -#define set_errno(err) do { if (err) { errno = (err); } } while(0) -#endif -#else /* LWIP_SOCKET_SET_ERRNO */ -#define set_errno(err) -#endif /* LWIP_SOCKET_SET_ERRNO */ - -#define sock_set_errno(sk, e) do { \ - const int sockerr = (e); \ - sk->err = (u8_t)sockerr; \ - set_errno(sockerr); \ -} while (0) - -/* Forward declaration of some functions */ -static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); -#if !LWIP_TCPIP_CORE_LOCKING -static void lwip_getsockopt_callback(void *arg); -static void lwip_setsockopt_callback(void *arg); -#endif -static u8_t lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen); -static u8_t lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen); - -#if LWIP_IPV4 && LWIP_IPV6 -static void -sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* ipaddr, u16_t* port) -{ - if ((sockaddr->sa_family) == AF_INET6) { - SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, *port); - ipaddr->type = IPADDR_TYPE_V6; - } else { - SOCKADDR4_TO_IP4ADDR_PORT((const struct sockaddr_in*)(const void*)(sockaddr), ipaddr, *port); - ipaddr->type = IPADDR_TYPE_V4; - } -} -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -/** LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ -void -lwip_socket_thread_init(void) -{ - netconn_thread_init(); -} - -/** LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ -void -lwip_socket_thread_cleanup(void) -{ - netconn_thread_cleanup(); -} - -/** - * Map a externally used socket index to the internal socket representation. - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -static struct lwip_sock * -get_socket(int s) -{ - struct lwip_sock *sock; - - s -= LWIP_SOCKET_OFFSET; - - if ((s < 0) || (s >= NUM_SOCKETS)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET)); - set_errno(EBADF); - return NULL; - } - - sock = &sockets[s]; - - if (!sock->conn) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); - set_errno(EBADF); - return NULL; - } - - return sock; -} - -/** - * Same as get_socket but doesn't set errno - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -static struct lwip_sock * -tryget_socket(int s) -{ - s -= LWIP_SOCKET_OFFSET; - if ((s < 0) || (s >= NUM_SOCKETS)) { - return NULL; - } - if (!sockets[s].conn) { - return NULL; - } - return &sockets[s]; -} - -/** - * Same as tryget_socket but a global routine. - * - * @param s externally used socket index - * @return struct lwip_sock for the socket or NULL if not found - */ -struct lwip_sock * -lwip_tryget_socket(int s) -{ - return tryget_socket(s); -} - -/** - * Allocate a new socket for a given netconn. - * - * @param newconn the netconn for which to allocate a socket - * @param accepted 1 if socket has been created by accept(), - * 0 if socket has been created by socket() - * @return the index of the new socket; -1 on error - */ -static int -alloc_socket(struct netconn *newconn, int accepted) -{ - int i; - SYS_ARCH_DECL_PROTECT(lev); - - /* allocate a new socket identifier */ - for (i = 0; i < NUM_SOCKETS; ++i) { - /* Protect socket array */ - SYS_ARCH_PROTECT(lev); - if (!sockets[i].conn && (sockets[i].select_waiting == 0)) { - sockets[i].conn = newconn; - /* The socket is not yet known to anyone, so no need to protect - after having marked it as used. */ - SYS_ARCH_UNPROTECT(lev); - sockets[i].lastdata = NULL; - sockets[i].lastoffset = 0; - sockets[i].rcvevent = 0; - /* TCP sendbuf is empty, but the socket is not yet writable until connected - * (unless it has been created by accept()). */ - sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); - sockets[i].errevent = 0; - sockets[i].err = 0; -#ifdef SAL_USING_POSIX - rt_wqueue_init(&sockets[i].wait_head); -#endif - return i + LWIP_SOCKET_OFFSET; - } - SYS_ARCH_UNPROTECT(lev); - } - return -1; -} - -/** Free a socket. The socket's netconn must have been - * delete before! - * - * @param sock the socket to free - * @param is_tcp != 0 for TCP sockets, used to free lastdata - */ -static void -free_socket(struct lwip_sock *sock, int is_tcp) -{ - void *lastdata; - - lastdata = sock->lastdata; - sock->lastdata = NULL; - sock->lastoffset = 0; - sock->err = 0; - - /* Protect socket array */ - SYS_ARCH_SET(sock->conn, NULL); - /* don't use 'sock' after this line, as another task might have allocated it */ - - if (lastdata != NULL) { - if (is_tcp) { - pbuf_free((struct pbuf *)lastdata); - } else { - netbuf_delete((struct netbuf *)lastdata); - } - } -} - -/* Below this, the well-known socket functions are implemented. - * Use google.com or opengroup.org to get a good description :-) - * - * Exceptions are documented! - */ - -int -lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - struct lwip_sock *sock, *nsock; - struct netconn *newconn; - ip_addr_t naddr; - u16_t port = 0; - int newsock; - err_t err; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s)); - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s)); - set_errno(EWOULDBLOCK); - return -1; - } - - /* wait for a new connection */ - err = netconn_accept(sock->conn, &newconn); - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - } else if (err == ERR_CLSD) { - sock_set_errno(sock, EINVAL); - } else { - sock_set_errno(sock, err_to_errno(err)); - } - return -1; - } - LWIP_ASSERT("newconn != NULL", newconn != NULL); - - newsock = alloc_socket(newconn, 1); - if (newsock == -1) { - netconn_delete(newconn); - sock_set_errno(sock, ENFILE); - return -1; - } - LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET)); - /* RT-Thread has changed callback when using BSD socket API, so remove this assert. */ - /* LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback); */ - nsock = &sockets[newsock - LWIP_SOCKET_OFFSET]; - - /* See event_callback: If data comes in right away after an accept, even - * though the server task might not have created a new socket yet. - * In that case, newconn->socket is counted down (newconn->socket--), - * so nsock->rcvevent is >= 1 here! - */ - SYS_ARCH_PROTECT(lev); - nsock->rcvevent += (s16_t)(-1 - newconn->socket); - newconn->socket = newsock; - SYS_ARCH_UNPROTECT(lev); - - /* Note that POSIX only requires us to check addr is non-NULL. addrlen must - * not be NULL if addr is valid. - */ - if (addr != NULL) { - union sockaddr_aligned tempaddr; - /* get the IP address and port of the remote host */ - err = netconn_peer(newconn, &naddr, &port); - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err)); - netconn_delete(newconn); - free_socket(nsock, 1); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); - - IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); - if (*addrlen > tempaddr.sa.sa_len) { - *addrlen = tempaddr.sa.sa_len; - } - MEMCPY(addr, &tempaddr, *addrlen); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); - ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port)); - } else { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d", s, newsock)); - } - - sock_set_errno(sock, 0); - return newsock; -} - -int -lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct lwip_sock *sock; - ip_addr_t local_addr; - u16_t local_port; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - /* check size, family and alignment of 'name' */ - LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(namelen); - - SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); - ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&local_addr), ip_2_ip6(&local_addr)); - IP_SET_TYPE_VAL(local_addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - err = netconn_bind(sock->conn, &local_addr, local_port); - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s)); - sock_set_errno(sock, 0); - return 0; -} - -int -lwip_close(int s) -{ - struct lwip_sock *sock; - int is_tcp = 0; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (sock->conn != NULL) { - is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP; - } else { - LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL); - } - -#if LWIP_IGMP - /* drop all possibly joined IGMP memberships */ - lwip_socket_drop_registered_memberships(s); -#endif /* LWIP_IGMP */ - - err = netconn_delete(sock->conn); - if (err != ERR_OK) { - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - free_socket(sock, is_tcp); - set_errno(0); - return 0; -} - -int -lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - struct lwip_sock *sock; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { - /* sockaddr does not match socket type (IPv4/IPv6) */ - sock_set_errno(sock, err_to_errno(ERR_VAL)); - return -1; - } - - LWIP_UNUSED_ARG(namelen); - if (name->sa_family == AF_UNSPEC) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s)); - err = netconn_disconnect(sock->conn); - } else { - ip_addr_t remote_addr; - u16_t remote_port; - - /* check size, family and alignment of 'name' */ - LWIP_ERROR("lwip_connect: invalid address", IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID_OR_UNSPEC(name) && IS_SOCK_ADDR_ALIGNED(name), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - SOCKADDR_TO_IPADDR_PORT(name, &remote_addr, remote_port); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s)); - ip_addr_debug_print_val(SOCKETS_DEBUG, remote_addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", remote_port)); - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(remote_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&remote_addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&remote_addr), ip_2_ip6(&remote_addr)); - IP_SET_TYPE_VAL(remote_addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - err = netconn_connect(sock->conn, &remote_addr, remote_port); - } - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err)); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s)); - sock_set_errno(sock, 0); - return 0; -} - -/** - * Set a socket into listen mode. - * The socket may not have been used for another connection previously. - * - * @param s the socket to set to listening mode - * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1) - * @return 0 on success, non-zero on failure - */ -int -lwip_listen(int s, int backlog) -{ - struct lwip_sock *sock; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - /* limit the "backlog" parameter to fit in an u8_t */ - backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff); - - err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog); - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return -1; - } - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - - sock_set_errno(sock, 0); - return 0; -} - -int -lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - struct lwip_sock *sock; - void *buf = NULL; - struct pbuf *p; - u16_t buflen, copylen; - int off = 0; - u8_t done = 0; - err_t err; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); - sock = get_socket(s); - if (!sock) { - return -1; - } - - do { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); - /* Check if there is data left from the last recv operation. */ - if (sock->lastdata) { - buf = sock->lastdata; - } else { - /* If this is non-blocking call, then check first */ - if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) && - (sock->rcvevent <= 0)) { - if (off > 0) { - /* already received data, return that */ - sock_set_errno(sock, 0); - return off; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s)); - set_errno(EWOULDBLOCK); - return -1; - } - - /* No data was left from the previous operation, so we try to get - some from the network. */ - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf); - } else { - err = netconn_recv(sock->conn, (struct netbuf **)&buf); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n", - err, buf)); - - if (err != ERR_OK) { - if (off > 0) { - if (err == ERR_CLSD) { - /* closed but already received data, ensure select gets the FIN, too */ - event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0); - } - /* already received data, return that */ - sock_set_errno(sock, 0); - return off; - } - /* We should really do some error checking here. */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n", - s, lwip_strerr(err))); - sock_set_errno(sock, err_to_errno(err)); - if (err == ERR_CLSD) { - return 0; - } else { - return -1; - } - } - LWIP_ASSERT("buf != NULL", buf != NULL); - sock->lastdata = buf; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - p = (struct pbuf *)buf; - } else { - p = ((struct netbuf *)buf)->p; - } - buflen = p->tot_len; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n", - buflen, len, off, sock->lastoffset)); - - buflen -= sock->lastoffset; - - if (len > buflen) { - copylen = buflen; - } else { - copylen = (u16_t)len; - } - - /* copy the contents of the received buffer into - the supplied memory pointer mem */ - pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset); - - off += copylen; - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen); - len -= copylen; - if ((len <= 0) || - (p->flags & PBUF_FLAG_PUSH) || - (sock->rcvevent <= 0) || - ((flags & MSG_PEEK) != 0)) { - done = 1; - } - } else { - done = 1; - } - - /* Check to see from where the data was.*/ - if (done) { -#if !SOCKETS_DEBUG - if (from && fromlen) -#endif /* !SOCKETS_DEBUG */ - { - u16_t port; - ip_addr_t tmpaddr; - ip_addr_t *fromaddr; - union sockaddr_aligned saddr; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - fromaddr = &tmpaddr; - netconn_getaddr(sock->conn, fromaddr, &port, 0); - } else { - port = netbuf_fromport((struct netbuf *)buf); - fromaddr = netbuf_fromaddr((struct netbuf *)buf); - } - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ - if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) { - ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr)); - IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); - ip_addr_debug_print(SOCKETS_DEBUG, fromaddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off)); -#if SOCKETS_DEBUG - if (from && fromlen) -#endif /* SOCKETS_DEBUG */ - { - if (*fromlen > saddr.sa.sa_len) { - *fromlen = saddr.sa.sa_len; - } - MEMCPY(from, &saddr, *fromlen); - } - } - } - - /* If we don't peek the incoming message... */ - if ((flags & MSG_PEEK) == 0) { - /* If this is a TCP socket, check if there is data left in the - buffer. If so, it should be saved in the sock structure for next - time around. */ - if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) { - sock->lastdata = buf; - sock->lastoffset += copylen; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); - } else { - sock->lastdata = NULL; - sock->lastoffset = 0; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { - pbuf_free((struct pbuf *)buf); - } else { - netbuf_delete((struct netbuf *)buf); - } - buf = NULL; - } - } - } while (!done); - - sock_set_errno(sock, 0); - return off; -} - -int -lwip_read(int s, void *mem, size_t len) -{ - return lwip_recvfrom(s, mem, len, 0, NULL, NULL); -} - -int -lwip_recv(int s, void *mem, size_t len, int flags) -{ - return lwip_recvfrom(s, mem, len, flags, NULL, NULL); -} - -int -lwip_send(int s, const void *data, size_t size, int flags) -{ - struct lwip_sock *sock; - err_t err; - u8_t write_flags; - size_t written; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n", - s, data, size, flags)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -#if (LWIP_UDP || LWIP_RAW) - return lwip_sendto(s, data, size, flags, NULL, 0); -#else /* (LWIP_UDP || LWIP_RAW) */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* (LWIP_UDP || LWIP_RAW) */ - } - - write_flags = NETCONN_COPY | - ((flags & MSG_MORE) ? NETCONN_MORE : 0) | - ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); - written = 0; - err = netconn_write_partly(sock->conn, data, size, write_flags, &written); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d written=%"SZT_F"\n", s, err, written)); - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? (int)written : -1); -} - -int -lwip_sendmsg(int s, const struct msghdr *msg, int flags) -{ - struct lwip_sock *sock; - int i; -#if LWIP_TCP - u8_t write_flags; - size_t written; -#endif - int size = 0; - err_t err = ERR_OK; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - LWIP_ERROR("lwip_sendmsg: invalid msghdr", msg != NULL, - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - LWIP_UNUSED_ARG(msg->msg_control); - LWIP_UNUSED_ARG(msg->msg_controllen); - LWIP_UNUSED_ARG(msg->msg_flags); - LWIP_ERROR("lwip_sendmsg: invalid msghdr iov", (msg->msg_iov != NULL && msg->msg_iovlen != 0), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -#if LWIP_TCP - write_flags = NETCONN_COPY | - ((flags & MSG_MORE) ? NETCONN_MORE : 0) | - ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); - - for (i = 0; i < msg->msg_iovlen; i++) { - u8_t apiflags = write_flags; - if (i + 1 < msg->msg_iovlen) { - apiflags |= NETCONN_MORE; - } - written = 0; - err = netconn_write_partly(sock->conn, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, write_flags, &written); - if (err == ERR_OK) { - size += written; - /* check that the entire IO vector was accepected, if not return a partial write */ - if (written != msg->msg_iov[i].iov_len) - break; - } - /* none of this IO vector was accepted, but previous was, return partial write and conceal ERR_WOULDBLOCK */ - else if (err == ERR_WOULDBLOCK && size > 0) { - err = ERR_OK; - /* let ERR_WOULDBLOCK persist on the netconn since we are returning ERR_OK */ - break; - } else { - size = -1; - break; - } - } - sock_set_errno(sock, err_to_errno(err)); - return size; -#else /* LWIP_TCP */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_TCP */ - } - /* else, UDP and RAW NETCONNs */ -#if LWIP_UDP || LWIP_RAW - { - struct netbuf *chain_buf; - - LWIP_UNUSED_ARG(flags); - LWIP_ERROR("lwip_sendmsg: invalid msghdr name", (((msg->msg_name == NULL) && (msg->msg_namelen == 0)) || - IS_SOCK_ADDR_LEN_VALID(msg->msg_namelen)) , - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - - /* initialize chain buffer with destination */ - chain_buf = netbuf_new(); - if (!chain_buf) { - sock_set_errno(sock, err_to_errno(ERR_MEM)); - return -1; - } - if (msg->msg_name) { - u16_t remote_port; - SOCKADDR_TO_IPADDR_PORT((const struct sockaddr *)msg->msg_name, &chain_buf->addr, remote_port); - netbuf_fromport(chain_buf) = remote_port; - } -#if LWIP_NETIF_TX_SINGLE_PBUF - for (i = 0; i < msg->msg_iovlen; i++) { - size += msg->msg_iov[i].iov_len; - } - /* Allocate a new netbuf and copy the data into it. */ - if (netbuf_alloc(chain_buf, (u16_t)size) == NULL) { - err = ERR_MEM; - } else { - /* flatten the IO vectors */ - size_t offset = 0; - for (i = 0; i < msg->msg_iovlen; i++) { - MEMCPY(&((u8_t*)chain_buf->p->payload)[offset], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len); - offset += msg->msg_iov[i].iov_len; - } -#if LWIP_CHECKSUM_ON_COPY - { - /* This can be improved by using LWIP_CHKSUM_COPY() and aggregating the checksum for each IO vector */ - u16_t chksum = ~inet_chksum_pbuf(chain_buf->p); - netbuf_set_chksum(chain_buf, chksum); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - err = ERR_OK; - } -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* create a chained netbuf from the IO vectors. NOTE: we assemble a pbuf chain - manually to avoid having to allocate, chain, and delete a netbuf for each iov */ - for (i = 0; i < msg->msg_iovlen; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); - if (p == NULL) { - err = ERR_MEM; /* let netbuf_delete() cleanup chain_buf */ - break; - } - p->payload = msg->msg_iov[i].iov_base; - LWIP_ASSERT("iov_len < u16_t", msg->msg_iov[i].iov_len <= 0xFFFF); - p->len = p->tot_len = (u16_t)msg->msg_iov[i].iov_len; - /* netbuf empty, add new pbuf */ - if (chain_buf->p == NULL) { - chain_buf->p = chain_buf->ptr = p; - /* add pbuf to existing pbuf chain */ - } else { - pbuf_cat(chain_buf->p, p); - } - } - /* save size of total chain */ - if (err == ERR_OK) { - size = netbuf_len(chain_buf); - } -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - if (err == ERR_OK) { -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(chain_buf->addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&chain_buf->addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&chain_buf->addr), ip_2_ip6(&chain_buf->addr)); - IP_SET_TYPE_VAL(chain_buf->addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - /* send the data */ - err = netconn_send(sock->conn, chain_buf); - } - - /* deallocated the buffer */ - netbuf_delete(chain_buf); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? size : -1); - } -#else /* LWIP_UDP || LWIP_RAW */ - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_UDP || LWIP_RAW */ -} - -int -lwip_sendto(int s, const void *data, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - struct lwip_sock *sock; - err_t err; - u16_t short_size; - u16_t remote_port; - struct netbuf buf; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -#if LWIP_TCP - return lwip_send(s, data, size, flags); -#else /* LWIP_TCP */ - LWIP_UNUSED_ARG(flags); - sock_set_errno(sock, err_to_errno(ERR_ARG)); - return -1; -#endif /* LWIP_TCP */ - } - - /* @todo: split into multiple sendto's? */ - LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff); - short_size = (u16_t)size; - LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || - (IS_SOCK_ADDR_LEN_VALID(tolen) && - IS_SOCK_ADDR_TYPE_VALID(to) && IS_SOCK_ADDR_ALIGNED(to))), - sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;); - LWIP_UNUSED_ARG(tolen); - - /* initialize a buffer */ - buf.p = buf.ptr = NULL; -#if LWIP_CHECKSUM_ON_COPY - buf.flags = 0; -#endif /* LWIP_CHECKSUM_ON_COPY */ - if (to) { - SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); - } else { - remote_port = 0; - ip_addr_set_any(NETCONNTYPE_ISIPV6(netconn_type(sock->conn)), &buf.addr); - } - netbuf_fromport(&buf) = remote_port; - - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", - s, data, short_size, flags)); - ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); - - /* make the buffer point to the data that should be sent */ -#if LWIP_NETIF_TX_SINGLE_PBUF - /* Allocate a new netbuf and copy the data into it. */ - if (netbuf_alloc(&buf, short_size) == NULL) { - err = ERR_MEM; - } else { -#if LWIP_CHECKSUM_ON_COPY - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { - u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); - netbuf_set_chksum(&buf, chksum); - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - { - MEMCPY(buf.p->payload, data, short_size); - } - err = ERR_OK; - } -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - err = netbuf_ref(&buf, data, short_size); -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (err == ERR_OK) { -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ - if (IP_IS_V6_VAL(buf.addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&buf.addr))) { - unmap_ipv4_mapped_ipv6(ip_2_ip4(&buf.addr), ip_2_ip6(&buf.addr)); - IP_SET_TYPE_VAL(buf.addr, IPADDR_TYPE_V4); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - /* send the data */ - err = netconn_send(sock->conn, &buf); - } - - /* deallocated the buffer */ - netbuf_free(&buf); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? short_size : -1); -} - -int -lwip_socket(int domain, int type, int protocol) -{ - struct netconn *conn; - int i; - - LWIP_UNUSED_ARG(domain); /* @todo: check this */ - - /* create a netconn */ - switch (type) { - case SOCK_RAW: - conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), - (u8_t)protocol, event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - case SOCK_DGRAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, - ((protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP)) , - event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - case SOCK_STREAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_TCP), event_callback); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", - domain, type, protocol)); - set_errno(EINVAL); - return -1; - } - - if (!conn) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n")); - set_errno(ENOBUFS); - return -1; - } - - i = alloc_socket(conn, 0); - - if (i == -1) { - netconn_delete(conn); - set_errno(ENFILE); - return -1; - } - conn->socket = i; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); - set_errno(0); - return i; -} - -int -lwip_write(int s, const void *data, size_t size) -{ - return lwip_send(s, data, size, 0); -} - -int -lwip_writev(int s, const struct iovec *iov, int iovcnt) -{ - struct msghdr msg; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - /* Hack: we have to cast via number to cast from 'const' pointer to non-const. - Blame the opengroup standard for this inconsistency. */ - msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); - msg.msg_iovlen = iovcnt; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - return lwip_sendmsg(s, &msg, 0); -} - -/** - * Go through the readset and writeset lists and see which socket of the sockets - * set in the sets has events. On return, readset, writeset and exceptset have - * the sockets enabled that had events. - * - * @param maxfdp1 the highest socket index in the sets - * @param readset_in set of sockets to check for read events - * @param writeset_in set of sockets to check for write events - * @param exceptset_in set of sockets to check for error events - * @param readset_out set of sockets that had read events - * @param writeset_out set of sockets that had write events - * @param exceptset_out set os sockets that had error events - * @return number of sockets that had events (read/write/exception) (>= 0) - */ -static int -lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in, - fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out) -{ - int i, nready = 0; - fd_set lreadset, lwriteset, lexceptset; - struct lwip_sock *sock; - SYS_ARCH_DECL_PROTECT(lev); - - FD_ZERO(&lreadset); - FD_ZERO(&lwriteset); - FD_ZERO(&lexceptset); - - /* Go through each socket in each list to count number of sockets which - currently match */ - for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { - /* if this FD is not in the set, continue */ - if (!(readset_in && FD_ISSET(i, readset_in)) && - !(writeset_in && FD_ISSET(i, writeset_in)) && - !(exceptset_in && FD_ISSET(i, exceptset_in))) { - continue; - } - /* First get the socket's status (protected)... */ - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - void* lastdata = sock->lastdata; - s16_t rcvevent = sock->rcvevent; - u16_t sendevent = sock->sendevent; - u16_t errevent = sock->errevent; - SYS_ARCH_UNPROTECT(lev); - - /* ... then examine it: */ - /* See if netconn of this socket is ready for read */ - if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) { - FD_SET(i, &lreadset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i)); - nready++; - } - /* See if netconn of this socket is ready for write */ - if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) { - FD_SET(i, &lwriteset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i)); - nready++; - } - /* See if netconn of this socket had an error */ - if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) { - FD_SET(i, &lexceptset); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i)); - nready++; - } - } else { - SYS_ARCH_UNPROTECT(lev); - /* continue on to next FD in list */ - } - } - /* copy local sets to the ones provided as arguments */ - *readset_out = lreadset; - *writeset_out = lwriteset; - *exceptset_out = lexceptset; - - LWIP_ASSERT("nready >= 0", nready >= 0); - return nready; -} - -int -lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout) -{ - u32_t waitres = 0; - int nready; - fd_set lreadset, lwriteset, lexceptset; - u32_t msectimeout; - struct lwip_select_cb select_cb; - int i; - int maxfdp2; -#if LWIP_NETCONN_SEM_PER_THREAD - int waited = 0; -#endif - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", - maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, - timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, - timeout ? (s32_t)timeout->tv_usec : (s32_t)-1)); - - /* Go through each socket in each list to count number of sockets which - currently match */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - - /* If we don't have any current events, then suspend if we are supposed to */ - if (!nready) { - if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); - /* This is OK as the local fdsets are empty and nready is zero, - or we would have returned earlier. */ - goto return_copy_fdsets; - } - - /* None ready: add our semaphore to list: - We don't actually need any dynamic memory. Our entry on the - list is only valid while we are in this function, so it's ok - to use local variables. */ - - select_cb.next = NULL; - select_cb.prev = NULL; - select_cb.readset = readset; - select_cb.writeset = writeset; - select_cb.exceptset = exceptset; - select_cb.sem_signalled = 0; -#if LWIP_NETCONN_SEM_PER_THREAD - select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else /* LWIP_NETCONN_SEM_PER_THREAD */ - if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { - /* failed to create semaphore */ - set_errno(ENOMEM); - return -1; - } -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - /* Protect the select_cb_list */ - SYS_ARCH_PROTECT(lev); - - /* Put this select_cb on top of list */ - select_cb.next = select_cb_list; - if (select_cb_list != NULL) { - select_cb_list->prev = &select_cb; - } - select_cb_list = &select_cb; - /* Increasing this counter tells event_callback that the list has changed. */ - select_cb_ctr++; - - /* Now we can safely unprotect */ - SYS_ARCH_UNPROTECT(lev); - - /* Increase select_waiting for each socket we are interested in */ - maxfdp2 = maxfdp1; - for (i = LWIP_SOCKET_OFFSET; i < maxfdp1; i++) { - if ((readset && FD_ISSET(i, readset)) || - (writeset && FD_ISSET(i, writeset)) || - (exceptset && FD_ISSET(i, exceptset))) { - struct lwip_sock *sock; - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - sock->select_waiting++; - LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); - } else { - /* Not a valid socket */ - nready = -1; - maxfdp2 = i; - SYS_ARCH_UNPROTECT(lev); - break; - } - SYS_ARCH_UNPROTECT(lev); - } - } - - if (nready >= 0) { - /* Call lwip_selscan again: there could have been events between - the last scan (without us on the list) and putting us on the list! */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - if (!nready) { - /* Still none ready, just wait to be woken */ - if (timeout == 0) { - /* Wait forever */ - msectimeout = 0; - } else { - msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000)); - if (msectimeout == 0) { - /* Wait 1ms at least (0 means wait forever) */ - msectimeout = 1; - } - } - - waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); -#if LWIP_NETCONN_SEM_PER_THREAD - waited = 1; -#endif - } - } - - /* Decrease select_waiting for each socket we are interested in */ - for (i = LWIP_SOCKET_OFFSET; i < maxfdp2; i++) { - if ((readset && FD_ISSET(i, readset)) || - (writeset && FD_ISSET(i, writeset)) || - (exceptset && FD_ISSET(i, exceptset))) { - struct lwip_sock *sock; - SYS_ARCH_PROTECT(lev); - sock = tryget_socket(i); - if (sock != NULL) { - /* for now, handle select_waiting==0... */ - LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); - if (sock->select_waiting > 0) { - sock->select_waiting--; - } - } else { - /* Not a valid socket */ - nready = -1; - } - SYS_ARCH_UNPROTECT(lev); - } - } - /* Take us off the list */ - SYS_ARCH_PROTECT(lev); - if (select_cb.next != NULL) { - select_cb.next->prev = select_cb.prev; - } - if (select_cb_list == &select_cb) { - LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL); - select_cb_list = select_cb.next; - } else { - LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); - select_cb.prev->next = select_cb.next; - } - /* Increasing this counter tells event_callback that the list has changed. */ - select_cb_ctr++; - SYS_ARCH_UNPROTECT(lev); - -#if LWIP_NETCONN_SEM_PER_THREAD - if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { - /* don't leave the thread-local semaphore signalled */ - sys_arch_sem_wait(select_cb.sem, 1); - } -#else /* LWIP_NETCONN_SEM_PER_THREAD */ - sys_sem_free(&select_cb.sem); -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - if (nready < 0) { - /* This happens when a socket got closed while waiting */ - set_errno(EBADF); - return -1; - } - - if (waitres == SYS_ARCH_TIMEOUT) { - /* Timeout */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); - /* This is OK as the local fdsets are empty and nready is zero, - or we would have returned earlier. */ - goto return_copy_fdsets; - } - - /* See what's set */ - nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); -return_copy_fdsets: - set_errno(0); - if (readset) { - *readset = lreadset; - } - if (writeset) { - *writeset = lwriteset; - } - if (exceptset) { - *exceptset = lexceptset; - } - return nready; -} - -/** - * Callback registered in the netconn layer for each socket-netconn. - * Processes recvevent (data available) and wakes up tasks waiting for select. - */ -static void -event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) -{ - int s; - struct lwip_sock *sock; - struct lwip_select_cb *scb; - int last_select_cb_ctr; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_UNUSED_ARG(len); - - /* Get socket */ - if (conn) { - s = conn->socket; - if (s < 0) { - /* Data comes in right away after an accept, even though - * the server task might not have created a new socket yet. - * Just count down (or up) if that's the case and we - * will use the data later. Note that only receive events - * can happen before the new socket is set up. */ - SYS_ARCH_PROTECT(lev); - if (conn->socket < 0) { - if (evt == NETCONN_EVT_RCVPLUS) { - conn->socket--; - } - SYS_ARCH_UNPROTECT(lev); - return; - } - s = conn->socket; - SYS_ARCH_UNPROTECT(lev); - } - - sock = get_socket(s); - if (!sock) { - return; - } - } else { - return; - } - - SYS_ARCH_PROTECT(lev); - /* Set event as required */ - switch (evt) { - case NETCONN_EVT_RCVPLUS: - sock->rcvevent++; - break; - case NETCONN_EVT_RCVMINUS: - sock->rcvevent--; - break; - case NETCONN_EVT_SENDPLUS: - sock->sendevent = 1; - break; - case NETCONN_EVT_SENDMINUS: - sock->sendevent = 0; - break; - case NETCONN_EVT_ERROR: - sock->errevent = 1; - break; - default: - LWIP_ASSERT("unknown event", 0); - break; - } - - if (sock->select_waiting == 0) { - /* noone is waiting for this socket, no need to check select_cb_list */ - SYS_ARCH_UNPROTECT(lev); - return; - } - - /* Now decide if anyone is waiting for this socket */ - /* NOTE: This code goes through the select_cb_list list multiple times - ONLY IF a select was actually waiting. We go through the list the number - of waiting select calls + 1. This list is expected to be small. */ - - /* At this point, SYS_ARCH is still protected! */ -again: - for (scb = select_cb_list; scb != NULL; scb = scb->next) { - /* remember the state of select_cb_list to detect changes */ - last_select_cb_ctr = select_cb_ctr; - if (scb->sem_signalled == 0) { - /* semaphore not signalled yet */ - int do_signal = 0; - /* Test this select call for our socket */ - if (sock->rcvevent > 0) { - if (scb->readset && FD_ISSET(s, scb->readset)) { - do_signal = 1; - } - } - if (sock->sendevent != 0) { - if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { - do_signal = 1; - } - } - if (sock->errevent != 0) { - if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { - do_signal = 1; - } - } - if (do_signal) { - scb->sem_signalled = 1; - /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might - lead to the select thread taking itself off the list, invalidating the semaphore. */ - sys_sem_signal(SELECT_SEM_PTR(scb->sem)); - } - } - /* unlock interrupts with each step */ - SYS_ARCH_UNPROTECT(lev); - /* this makes sure interrupt protection time is short */ - SYS_ARCH_PROTECT(lev); - if (last_select_cb_ctr != select_cb_ctr) { - /* someone has changed select_cb_list, restart at the beginning */ - goto again; - } - } - SYS_ARCH_UNPROTECT(lev); -} - -/** - * Close one end of a full-duplex connection. - */ -int -lwip_shutdown(int s, int how) -{ - struct lwip_sock *sock; - err_t err; - u8_t shut_rx = 0, shut_tx = 0; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); - - sock = get_socket(s); - if (!sock) { - return -1; - } - - if (sock->conn != NULL) { - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - sock_set_errno(sock, EOPNOTSUPP); - return -1; - } - } else { - sock_set_errno(sock, ENOTCONN); - return -1; - } - - if (how == SHUT_RD) { - shut_rx = 1; - } else if (how == SHUT_WR) { - shut_tx = 1; - } else if (how == SHUT_RDWR) { - shut_rx = 1; - shut_tx = 1; - } else { - sock_set_errno(sock, EINVAL); - return -1; - } - err = netconn_shutdown(sock->conn, shut_rx, shut_tx); - - sock_set_errno(sock, err_to_errno(err)); - return (err == ERR_OK ? 0 : -1); -} - -static int -lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local) -{ - struct lwip_sock *sock; - union sockaddr_aligned saddr; - ip_addr_t naddr; - u16_t port; - err_t err; - - sock = get_socket(s); - if (!sock) { - return -1; - } - - /* get the IP address and port */ - err = netconn_getaddr(sock->conn, &naddr, &port, local); - if (err != ERR_OK) { - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */ - if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && - IP_IS_V4_VAL(naddr)) { - ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&naddr), ip_2_ip4(&naddr)); - IP_SET_TYPE_VAL(naddr, IPADDR_TYPE_V6); - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, &naddr, port); - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); - ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); - - if (*namelen > saddr.sa.sa_len) { - *namelen = saddr.sa.sa_len; - } - MEMCPY(name, &saddr, *namelen); - - sock_set_errno(sock, 0); - return 0; -} - -int -lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getaddrname(s, name, namelen, 0); -} - -int -lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - return lwip_getaddrname(s, name, namelen, 1); -} - -int -lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - u8_t err; - struct lwip_sock *sock = get_socket(s); -#if !LWIP_TCPIP_CORE_LOCKING - LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - - if (!sock) { - return -1; - } - - if ((NULL == optval) || (NULL == optlen)) { - sock_set_errno(sock, EFAULT); - return -1; - } - -#if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); - err = lwip_getsockopt_impl(s, level, optname, optval, optlen); - UNLOCK_TCPIP_CORE(); - -#else /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_MPU_COMPATIBLE - /* MPU_COMPATIBLE copies the optval data, so check for max size here */ - if (*optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { - sock_set_errno(sock, ENOBUFS); - return -1; - } -#endif /* LWIP_MPU_COMPATIBLE */ - - LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = *optlen; -#if !LWIP_MPU_COMPATIBLE - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.p = optval; -#endif /* !LWIP_MPU_COMPATIBLE */ - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; -#if LWIP_NETCONN_SEM_PER_THREAD - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; -#endif - err = tcpip_callback(lwip_getsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); - if (err != ERR_OK) { - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); - - /* write back optlen and optval */ - *optlen = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen; -#if LWIP_MPU_COMPATIBLE - MEMCPY(optval, LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen); -#endif /* LWIP_MPU_COMPATIBLE */ - - /* maybe lwip_getsockopt_internal has changed err */ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - sock_set_errno(sock, err); - return err ? -1 : 0; -} - -#if !LWIP_TCPIP_CORE_LOCKING -/** lwip_getsockopt_callback: only used without CORE_LOCKING - * to get into the tcpip_thread - */ -static void -lwip_getsockopt_callback(void *arg) -{ - struct lwip_setgetsockopt_data *data; - LWIP_ASSERT("arg != NULL", arg != NULL); - data = (struct lwip_setgetsockopt_data*)arg; - - data->err = lwip_getsockopt_impl(data->s, data->level, data->optname, -#if LWIP_MPU_COMPATIBLE - data->optval, -#else /* LWIP_MPU_COMPATIBLE */ - data->optval.p, -#endif /* LWIP_MPU_COMPATIBLE */ - &data->optlen); - - sys_sem_signal((sys_sem_t*)(data->completed_sem)); -} -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -/** lwip_getsockopt_impl: the actual implementation of getsockopt: - * same argument as lwip_getsockopt, either called directly or through callback - */ -static u8_t -lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - u8_t err = 0; - struct lwip_sock *sock = tryget_socket(s); - if (!sock) { - return EBADF; - } - - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - -#if LWIP_TCP - case SO_ACCEPTCONN: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) { - return ENOPROTOOPT; - } - if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) { - *(int*)optval = 1; - } else { - *(int*)optval = 0; - } - break; -#endif /* LWIP_TCP */ - - /* The option flags */ - case SO_BROADCAST: - case SO_KEEPALIVE: -#if SO_REUSE - case SO_REUSEADDR: -#endif /* SO_REUSE */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - *(int*)optval = ip_get_option(sock->conn->pcb.ip, optname); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", - s, optname, (*(int*)optval?"on":"off"))); - break; - - case SO_TYPE: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { - case NETCONN_RAW: - *(int*)optval = SOCK_RAW; - break; - case NETCONN_TCP: - *(int*)optval = SOCK_STREAM; - break; - case NETCONN_UDP: - *(int*)optval = SOCK_DGRAM; - break; - default: /* unrecognized socket type */ - *(int*)optval = netconn_type(sock->conn); - LWIP_DEBUGF(SOCKETS_DEBUG, - ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", - s, *(int *)optval)); - } /* switch (netconn_type(sock->conn)) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", - s, *(int *)optval)); - break; - - case SO_ERROR: - LWIP_SOCKOPT_CHECK_OPTLEN(*optlen, int); - /* only overwrite ERR_OK or temporary errors */ - if (((sock->err == 0) || (sock->err == EINPROGRESS)) && (sock->conn != NULL)) { - sock_set_errno(sock, err_to_errno(sock->conn->last_err)); - } - *(int *)optval = (sock->err == 0xFF ? (int)-1 : (int)sock->err); - sock->err = 0; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", - s, *(int *)optval)); - break; - -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_sendtimeout(sock->conn)); - break; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - LWIP_SO_SNDRCVTIMEO_SET(optval, netconn_get_recvtimeout(sock->conn)); - break; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - *(int *)optval = netconn_get_recvbufsize(sock->conn); - break; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - case SO_LINGER: - { - s16_t conn_linger; - struct linger* linger = (struct linger*)optval; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, struct linger); - conn_linger = sock->conn->linger; - if (conn_linger >= 0) { - linger->l_onoff = 1; - linger->l_linger = (int)conn_linger; - } else { - linger->l_onoff = 0; - linger->l_linger = 0; - } - } - break; -#endif /* LWIP_SO_LINGER */ -#if LWIP_UDP - case SO_NO_CHECK: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_UDP); -#if LWIP_UDPLITE - if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { - /* this flag is only available for UDP, not for UDP lite */ - return EAFNOSUPPORT; - } -#endif /* LWIP_UDPLITE */ - *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0; - break; -#endif /* LWIP_UDP*/ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - case IP_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - *(int*)optval = sock->conn->pcb.ip->ttl; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", - s, *(int *)optval)); - break; - case IP_TOS: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - *(int*)optval = sock->conn->pcb.ip->tos; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", - s, *(int *)optval)); - break; -#if LWIP_MULTICAST_TX_OPTIONS - case IP_MULTICAST_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - return ENOPROTOOPT; - } - *(u8_t*)optval = udp_get_multicast_ttl(sock->conn->pcb.udp); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n", - s, *(int *)optval)); - break; - case IP_MULTICAST_IF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, struct in_addr); - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_UDP) { - return ENOPROTOOPT; - } - inet_addr_from_ip4addr((struct in_addr*)optval, udp_get_multicast_netif_addr(sock->conn->pcb.udp)); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n", - s, *(u32_t *)optval)); - break; - case IP_MULTICAST_LOOP: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, u8_t); - if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) { - *(u8_t*)optval = 1; - } else { - *(u8_t*)optval = 0; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n", - s, *(int *)optval)); - break; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - /* Special case: all IPPROTO_TCP option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_TCP); - if (sock->conn->pcb.tcp->state == LISTEN) { - return EINVAL; - } - switch (optname) { - case TCP_NODELAY: - *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", - s, (*(int*)optval)?"on":"off") ); - break; - case TCP_KEEPALIVE: - *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", - s, *(int *)optval)); - break; - -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) = %d\n", - s, *(int *)optval)); - break; - case TCP_KEEPINTVL: - *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) = %d\n", - s, *(int *)optval)); - break; - case TCP_KEEPCNT: - *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) = %d\n", - s, *(int *)optval)); - break; -#endif /* LWIP_TCP_KEEPALIVE */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - *(int*)optval = (netconn_get_ipv6only(sock->conn) ? 1 : 0); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n", - s, *(int *)optval)); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE - /* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - /* Special case: all IPPROTO_UDPLITE option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, *optlen, int); - /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { - return ENOPROTOOPT; - } - switch (optname) { - case UDPLITE_SEND_CSCOV: - *(int*)optval = sock->conn->pcb.udp->chksum_len_tx; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n", - s, (*(int*)optval)) ); - break; - case UDPLITE_RECV_CSCOV: - *(int*)optval = sock->conn->pcb.udp->chksum_len_rx; - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n", - s, (*(int*)optval)) ); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP */ - /* Level: IPPROTO_RAW */ - case IPPROTO_RAW: - switch (optname) { -#if LWIP_IPV6 && LWIP_RAW - case IPV6_CHECKSUM: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, *optlen, int, NETCONN_RAW); - if (sock->conn->pcb.raw->chksum_reqd == 0) { - *(int *)optval = -1; - } else { - *(int *)optval = sock->conn->pcb.raw->chksum_offset; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM) = %d\n", - s, (*(int*)optval)) ); - break; -#endif /* LWIP_IPV6 && LWIP_RAW */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; - break; - } /* switch (level) */ - - return err; -} - -int -lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - u8_t err = 0; - struct lwip_sock *sock = get_socket(s); -#if !LWIP_TCPIP_CORE_LOCKING - LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - - if (!sock) { - return -1; - } - - if (NULL == optval) { - sock_set_errno(sock, EFAULT); - return -1; - } - -#if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); - err = lwip_setsockopt_impl(s, level, optname, optval, optlen); - UNLOCK_TCPIP_CORE(); - -#else /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_MPU_COMPATIBLE - /* MPU_COMPATIBLE copies the optval data, so check for max size here */ - if (optlen > LWIP_SETGETSOCKOPT_MAXOPTLEN) { - sock_set_errno(sock, ENOBUFS); - return -1; - } -#endif /* LWIP_MPU_COMPATIBLE */ - - LWIP_SETGETSOCKOPT_DATA_VAR_ALLOC(data, sock); - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).s = s; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).level = level; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optname = optname; - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optlen = optlen; -#if LWIP_MPU_COMPATIBLE - MEMCPY(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval, optval, optlen); -#else /* LWIP_MPU_COMPATIBLE */ - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).optval.pc = (const void*)optval; -#endif /* LWIP_MPU_COMPATIBLE */ - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err = 0; -#if LWIP_NETCONN_SEM_PER_THREAD - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else - LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem = &sock->conn->op_completed; -#endif - err = tcpip_callback(lwip_setsockopt_callback, &LWIP_SETGETSOCKOPT_DATA_VAR_REF(data)); - if (err != ERR_OK) { - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - sock_set_errno(sock, err_to_errno(err)); - return -1; - } - sys_arch_sem_wait((sys_sem_t*)(LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).completed_sem), 0); - - /* maybe lwip_getsockopt_internal has changed err */ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - sock_set_errno(sock, err); - return err ? -1 : 0; -} - -#if !LWIP_TCPIP_CORE_LOCKING -/** lwip_setsockopt_callback: only used without CORE_LOCKING - * to get into the tcpip_thread - */ -static void -lwip_setsockopt_callback(void *arg) -{ - struct lwip_setgetsockopt_data *data; - LWIP_ASSERT("arg != NULL", arg != NULL); - data = (struct lwip_setgetsockopt_data*)arg; - - data->err = lwip_setsockopt_impl(data->s, data->level, data->optname, -#if LWIP_MPU_COMPATIBLE - data->optval, -#else /* LWIP_MPU_COMPATIBLE */ - data->optval.pc, -#endif /* LWIP_MPU_COMPATIBLE */ - data->optlen); - - sys_sem_signal((sys_sem_t*)(data->completed_sem)); -} -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -/** lwip_setsockopt_impl: the actual implementation of setsockopt: - * same argument as lwip_setsockopt, either called directly or through callback - */ -static u8_t -lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - u8_t err = 0; - struct lwip_sock *sock = tryget_socket(s); - if (!sock) { - return EBADF; - } - - switch (level) { - -/* Level: SOL_SOCKET */ - case SOL_SOCKET: - switch (optname) { - - /* SO_ACCEPTCONN is get-only */ - - /* The option flags */ - case SO_BROADCAST: - case SO_KEEPALIVE: -#if SO_REUSE - case SO_REUSEADDR: -#endif /* SO_REUSE */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - if (*(const int*)optval) { - ip_set_option(sock->conn->pcb.ip, optname); - } else { - ip_reset_option(sock->conn->pcb.ip, optname); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", - s, optname, (*(const int*)optval?"on":"off"))); - break; - - /* SO_TYPE is get-only */ - /* SO_ERROR is get-only */ - -#if LWIP_SO_SNDTIMEO - case SO_SNDTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - netconn_set_sendtimeout(sock->conn, LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); - break; -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO - case SO_RCVTIMEO: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, LWIP_SO_SNDRCVTIMEO_OPTTYPE); - netconn_set_recvtimeout(sock->conn, (int)LWIP_SO_SNDRCVTIMEO_GET_MS(optval)); - break; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - case SO_RCVBUF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); - netconn_set_recvbufsize(sock->conn, *(const int*)optval); - break; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - case SO_LINGER: - { - const struct linger* linger = (const struct linger*)optval; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, struct linger); - if (linger->l_onoff) { - int lingersec = linger->l_linger; - if (lingersec < 0) { - return EINVAL; - } - if (lingersec > 0xFFFF) { - lingersec = 0xFFFF; - } - sock->conn->linger = (s16_t)lingersec; - } else { - sock->conn->linger = -1; - } - } - break; -#endif /* LWIP_SO_LINGER */ -#if LWIP_UDP - case SO_NO_CHECK: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP); -#if LWIP_UDPLITE - if ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0) { - /* this flag is only available for UDP, not for UDP lite */ - return EAFNOSUPPORT; - } -#endif /* LWIP_UDPLITE */ - if (*(const int*)optval) { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM); - } else { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM); - } - break; -#endif /* LWIP_UDP */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -/* Level: IPPROTO_IP */ - case IPPROTO_IP: - switch (optname) { - case IP_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - sock->conn->pcb.ip->ttl = (u8_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n", - s, sock->conn->pcb.ip->ttl)); - break; - case IP_TOS: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - sock->conn->pcb.ip->tos = (u8_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n", - s, sock->conn->pcb.ip->tos)); - break; -#if LWIP_MULTICAST_TX_OPTIONS - case IP_MULTICAST_TTL: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); - udp_set_multicast_ttl(sock->conn->pcb.udp, (u8_t)(*(const u8_t*)optval)); - break; - case IP_MULTICAST_IF: - { - ip4_addr_t if_addr; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct in_addr, NETCONN_UDP); - inet_addr_to_ip4addr(&if_addr, (const struct in_addr*)optval); - udp_set_multicast_netif_addr(sock->conn->pcb.udp, &if_addr); - } - break; - case IP_MULTICAST_LOOP: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, u8_t, NETCONN_UDP); - if (*(const u8_t*)optval) { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP); - } else { - udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP); - } - break; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ -#if LWIP_IGMP - case IP_ADD_MEMBERSHIP: - case IP_DROP_MEMBERSHIP: - { - /* If this is a TCP or a RAW socket, ignore these options. */ - /* @todo: assign membership to this socket so that it is dropped when closing the socket */ - err_t igmp_err; - const struct ip_mreq *imr = (const struct ip_mreq *)optval; - ip4_addr_t if_addr; - ip4_addr_t multi_addr; - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, struct ip_mreq, NETCONN_UDP); - inet_addr_to_ip4addr(&if_addr, &imr->imr_interface); - inet_addr_to_ip4addr(&multi_addr, &imr->imr_multiaddr); - if (optname == IP_ADD_MEMBERSHIP) { - if (!lwip_socket_register_membership(s, &if_addr, &multi_addr)) { - /* cannot track membership (out of memory) */ - err = ENOMEM; - igmp_err = ERR_OK; - } else { - igmp_err = igmp_joingroup(&if_addr, &multi_addr); - } - } else { - igmp_err = igmp_leavegroup(&if_addr, &multi_addr); - lwip_socket_unregister_membership(s, &if_addr, &multi_addr); - } - if (igmp_err != ERR_OK) { - err = EADDRNOTAVAIL; - } - } - break; -#endif /* LWIP_IGMP */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - -#if LWIP_TCP -/* Level: IPPROTO_TCP */ - case IPPROTO_TCP: - /* Special case: all IPPROTO_TCP option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); - if (sock->conn->pcb.tcp->state == LISTEN) { - return EINVAL; - } - switch (optname) { - case TCP_NODELAY: - if (*(const int*)optval) { - tcp_nagle_disable(sock->conn->pcb.tcp); - } else { - tcp_nagle_enable(sock->conn->pcb.tcp); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", - s, (*(const int *)optval)?"on":"off") ); - break; - case TCP_KEEPALIVE: - sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_idle)); - break; - -#if LWIP_TCP_KEEPALIVE - case TCP_KEEPIDLE: - sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_idle)); - break; - case TCP_KEEPINTVL: - sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_intvl)); - break; - case TCP_KEEPCNT: - sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(const int*)optval); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n", - s, sock->conn->pcb.tcp->keep_cnt)); - break; -#endif /* LWIP_TCP_KEEPALIVE */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_TCP*/ - -#if LWIP_IPV6 -/* Level: IPPROTO_IPV6 */ - case IPPROTO_IPV6: - switch (optname) { - case IPV6_V6ONLY: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_TCP); - if (*(const int*)optval) { - netconn_set_ipv6only(sock->conn, 1); - } else { - netconn_set_ipv6only(sock->conn, 0); - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n", - s, (netconn_get_ipv6only(sock->conn) ? 1 : 0))); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE - /* Level: IPPROTO_UDPLITE */ - case IPPROTO_UDPLITE: - /* Special case: all IPPROTO_UDPLITE option take an int */ - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB(sock, optlen, int); - /* If this is no UDP lite socket, ignore any options. */ - if (!NETCONNTYPE_ISUDPLITE(netconn_type(sock->conn))) { - return ENOPROTOOPT; - } - switch (optname) { - case UDPLITE_SEND_CSCOV: - if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { - /* don't allow illegal values! */ - sock->conn->pcb.udp->chksum_len_tx = 8; - } else { - sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(const int*)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n", - s, (*(const int*)optval)) ); - break; - case UDPLITE_RECV_CSCOV: - if ((*(const int*)optval != 0) && ((*(const int*)optval < 8) || (*(const int*)optval > 0xffff))) { - /* don't allow illegal values! */ - sock->conn->pcb.udp->chksum_len_rx = 8; - } else { - sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(const int*)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n", - s, (*(const int*)optval)) ); - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; -#endif /* LWIP_UDP */ - /* Level: IPPROTO_RAW */ - case IPPROTO_RAW: - switch (optname) { -#if LWIP_IPV6 && LWIP_RAW - case IPV6_CHECKSUM: - /* It should not be possible to disable the checksum generation with ICMPv6 - * as per RFC 3542 chapter 3.1 */ - if(sock->conn->pcb.raw->protocol == IPPROTO_ICMPV6) { - return EINVAL; - } - - LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_RAW); - if (*(const int *)optval < 0) { - sock->conn->pcb.raw->chksum_reqd = 0; - } else if (*(const int *)optval & 1) { - /* Per RFC3542, odd offsets are not allowed */ - return EINVAL; - } else { - sock->conn->pcb.raw->chksum_reqd = 1; - sock->conn->pcb.raw->chksum_offset = (u16_t)*(const int *)optval; - } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, IPV6_CHECKSUM, ..) -> %d\n", - s, sock->conn->pcb.raw->chksum_reqd)); - break; -#endif /* LWIP_IPV6 && LWIP_RAW */ - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_RAW, UNIMPL: optname=0x%x, ..)\n", - s, optname)); - err = ENOPROTOOPT; - break; - } /* switch (optname) */ - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", - s, level, optname)); - err = ENOPROTOOPT; - break; - } /* switch (level) */ - - return err; -} - -int -lwip_ioctl(int s, long cmd, void *argp) -{ - struct lwip_sock *sock = get_socket(s); - u8_t val; -#if LWIP_SO_RCVBUF - u16_t buflen = 0; - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ - - if (!sock) { - return -1; - } - - switch (cmd) { -#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE - case FIONREAD: - if (!argp) { - sock_set_errno(sock, EINVAL); - return -1; - } -#if LWIP_FIONREAD_LINUXMODE - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - struct pbuf *p; - if (sock->lastdata) { - p = ((struct netbuf *)sock->lastdata)->p; - *((int*)argp) = p->tot_len - sock->lastoffset; - } else { - struct netbuf *rxbuf; - err_t err; - if (sock->rcvevent <= 0) { - *((int*)argp) = 0; - } else { - err = netconn_recv(sock->conn, &rxbuf); - if (err != ERR_OK) { - *((int*)argp) = 0; - } else { - sock->lastdata = rxbuf; - sock->lastoffset = 0; - *((int*)argp) = rxbuf->p->tot_len; - } - } - } - return 0; - } -#endif /* LWIP_FIONREAD_LINUXMODE */ - -#if LWIP_SO_RCVBUF - /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ - SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); - if (recv_avail < 0) { - recv_avail = 0; - } - *((int*)argp) = recv_avail; - - /* Check if there is data left from the last recv operation. /maq 041215 */ - if (sock->lastdata) { - struct pbuf *p = (struct pbuf *)sock->lastdata; - if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { - p = ((struct netbuf *)p)->p; - } - buflen = p->tot_len; - buflen -= sock->lastoffset; - - *((int*)argp) += buflen; - } - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); - sock_set_errno(sock, 0); - return 0; -#else /* LWIP_SO_RCVBUF */ - break; -#endif /* LWIP_SO_RCVBUF */ -#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - - case (long)FIONBIO: - val = 0; - if (argp && *(u32_t*)argp) { - val = 1; - } - netconn_set_nonblocking(sock->conn, val); - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); - sock_set_errno(sock, 0); - return 0; - - default: - break; - } /* switch (cmd) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - return -1; -} - -/** A minimal implementation of fcntl. - * Currently only the commands F_GETFL and F_SETFL are implemented. - * Only the flag O_NONBLOCK is implemented. - */ -int -lwip_fcntl(int s, int cmd, int val) -{ - struct lwip_sock *sock = get_socket(s); - int ret = -1; - - if (!sock) { - return -1; - } - - switch (cmd) { - case F_GETFL: - ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0; - sock_set_errno(sock, 0); - break; - case F_SETFL: - if ((val & ~O_NONBLOCK) == 0) { - /* only O_NONBLOCK, all other bits are zero */ - netconn_set_nonblocking(sock->conn, val & O_NONBLOCK); - ret = 0; - sock_set_errno(sock, 0); - } else { - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - } - break; - default: - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val)); - sock_set_errno(sock, ENOSYS); /* not yet implemented */ - break; - } - return ret; -} - -#if LWIP_IGMP -/** Register a new IGMP membership. On socket close, the membership is dropped automatically. - * - * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). - * - * @return 1 on success, 0 on failure - */ -static int -lwip_socket_register_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) -{ - struct lwip_sock *sock = get_socket(s); - int i; - - if (!sock) { - return 0; - } - - for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if (socket_ipv4_multicast_memberships[i].sock == NULL) { - socket_ipv4_multicast_memberships[i].sock = sock; - ip4_addr_copy(socket_ipv4_multicast_memberships[i].if_addr, *if_addr); - ip4_addr_copy(socket_ipv4_multicast_memberships[i].multi_addr, *multi_addr); - return 1; - } - } - return 0; -} - -/** Unregister a previously registered membership. This prevents dropping the membership - * on socket close. - * - * ATTENTION: this function is called from tcpip_thread (or under CORE_LOCK). - */ -static void -lwip_socket_unregister_membership(int s, const ip4_addr_t *if_addr, const ip4_addr_t *multi_addr) -{ - struct lwip_sock *sock = get_socket(s); - int i; - - if (!sock) { - return; - } - - for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if ((socket_ipv4_multicast_memberships[i].sock == sock) && - ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].if_addr, if_addr) && - ip4_addr_cmp(&socket_ipv4_multicast_memberships[i].multi_addr, multi_addr)) { - socket_ipv4_multicast_memberships[i].sock = NULL; - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); - return; - } - } -} - -/** Drop all memberships of a socket that were not dropped explicitly via setsockopt. - * - * ATTENTION: this function is NOT called from tcpip_thread (or under CORE_LOCK). - */ -static void -lwip_socket_drop_registered_memberships(int s) -{ - struct lwip_sock *sock = get_socket(s); - int i; - - if (!sock) { - return; - } - - for (i = 0; i < LWIP_SOCKET_MAX_MEMBERSHIPS; i++) { - if (socket_ipv4_multicast_memberships[i].sock == sock) { - ip_addr_t multi_addr, if_addr; - ip_addr_copy_from_ip4(multi_addr, socket_ipv4_multicast_memberships[i].multi_addr); - ip_addr_copy_from_ip4(if_addr, socket_ipv4_multicast_memberships[i].if_addr); - socket_ipv4_multicast_memberships[i].sock = NULL; - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].if_addr); - ip4_addr_set_zero(&socket_ipv4_multicast_memberships[i].multi_addr); - - netconn_join_leave_group(sock->conn, &multi_addr, &if_addr, NETCONN_LEAVE); - } - } -} -#endif /* LWIP_IGMP */ -#endif /* LWIP_SOCKET */ diff --git a/components/net/lwip-2.0.2/src/api/tcpip.c b/components/net/lwip-2.0.2/src/api/tcpip.c deleted file mode 100644 index 07b2f98434..0000000000 --- a/components/net/lwip-2.0.2/src/api/tcpip.c +++ /dev/null @@ -1,518 +0,0 @@ -/** - * @file - * Sequential API Main thread module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/tcpip_priv.h" -#include "lwip/sys.h" -#include "lwip/memp.h" -#include "lwip/mem.h" -#include "lwip/init.h" -#include "lwip/ip.h" -#include "lwip/pbuf.h" -#include "lwip/etharp.h" -#include "netif/ethernet.h" - -#define TCPIP_MSG_VAR_REF(name) API_VAR_REF(name) -#define TCPIP_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct tcpip_msg, name) -#define TCPIP_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM) -#define TCPIP_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_TCPIP_MSG_API, name) - -/* global variables */ -static tcpip_init_done_fn tcpip_init_done; -static void *tcpip_init_done_arg; -static sys_mbox_t mbox; - -#if LWIP_TCPIP_CORE_LOCKING -/** The global semaphore to lock the stack. */ -sys_mutex_t lock_tcpip_core; -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -#if LWIP_TIMERS -/* wait for a message, timeouts are processed while waiting */ -#define TCPIP_MBOX_FETCH(mbox, msg) sys_timeouts_mbox_fetch(mbox, msg) -#else /* LWIP_TIMERS */ -/* wait for a message with timers disabled (e.g. pass a timer-check trigger into tcpip_thread) */ -#define TCPIP_MBOX_FETCH(mbox, msg) sys_mbox_fetch(mbox, msg) -#endif /* LWIP_TIMERS */ - -/** - * The main lwIP thread. This thread has exclusive access to lwIP core functions - * (unless access to them is not locked). Other threads communicate with this - * thread using message boxes. - * - * It also starts all the timers to make sure they are running in the right - * thread context. - * - * @param arg unused argument - */ -static void -tcpip_thread(void *arg) -{ - struct tcpip_msg *msg; - LWIP_UNUSED_ARG(arg); - - if (tcpip_init_done != NULL) { - tcpip_init_done(tcpip_init_done_arg); - } - - LOCK_TCPIP_CORE(); - while (1) { /* MAIN Loop */ - UNLOCK_TCPIP_CORE(); - LWIP_TCPIP_THREAD_ALIVE(); - /* wait for a message, timeouts are processed while waiting */ - TCPIP_MBOX_FETCH(&mbox, (void **)&msg); - LOCK_TCPIP_CORE(); - if (msg == NULL) { - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); - LWIP_ASSERT("tcpip_thread: invalid message", 0); - continue; - } - switch (msg->type) { -#if !LWIP_TCPIP_CORE_LOCKING - case TCPIP_MSG_API: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); - msg->msg.api_msg.function(msg->msg.api_msg.msg); - break; - case TCPIP_MSG_API_CALL: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); - msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg); - sys_sem_signal(msg->msg.api_call.sem); - break; -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - -#if !LWIP_TCPIP_CORE_LOCKING_INPUT - case TCPIP_MSG_INPKT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); - msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); - memp_free(MEMP_TCPIP_MSG_INPKT, msg); - break; -#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ - -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS - case TCPIP_MSG_TIMEOUT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); - sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; - case TCPIP_MSG_UNTIMEOUT: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); - sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - - case TCPIP_MSG_CALLBACK: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); - msg->msg.cb.function(msg->msg.cb.ctx); - memp_free(MEMP_TCPIP_MSG_API, msg); - break; - - case TCPIP_MSG_CALLBACK_STATIC: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); - msg->msg.cb.function(msg->msg.cb.ctx); - break; - - default: - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); - LWIP_ASSERT("tcpip_thread: invalid message", 0); - break; - } - } -} - -/** - * Pass a received packet to tcpip_thread for input processing - * - * @param p the received packet - * @param inp the network interface on which the packet was received - * @param input_fn input function to call - */ -err_t -tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn) -{ -#if LWIP_TCPIP_CORE_LOCKING_INPUT - err_t ret; - LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp)); - LOCK_TCPIP_CORE(); - ret = input_fn(p, inp); - UNLOCK_TCPIP_CORE(); - return ret; -#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_INPKT; - msg->msg.inp.p = p; - msg->msg.inp.netif = inp; - msg->msg.inp.input_fn = input_fn; - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_INPKT, msg); - return ERR_MEM; - } - return ERR_OK; -#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ -} - -/** - * @ingroup lwip_os - * Pass a received packet to tcpip_thread for input processing with - * ethernet_input or ip_input. Don't call directly, pass to netif_add() - * and call netif->input(). - * - * @param p the received packet, p->payload pointing to the Ethernet header or - * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or - * NETIF_FLAG_ETHERNET flags) - * @param inp the network interface on which the packet was received - */ -err_t -tcpip_input(struct pbuf *p, struct netif *inp) -{ -#if LWIP_ETHERNET - if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { - return tcpip_inpkt(p, inp, ethernet_input); - } else -#endif /* LWIP_ETHERNET */ - return tcpip_inpkt(p, inp, ip_input); -} - -/** - * Call a specific function in the thread context of - * tcpip_thread for easy access synchronization. - * A function called in that way may access lwIP core code - * without fearing concurrent access. - * - * @param function the function to call - * @param ctx parameter passed to f - * @param block 1 to block until the request is posted, 0 to non-blocking mode - * @return ERR_OK if the function was called, another err_t if not - */ -err_t -tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) -{ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_CALLBACK; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - if (block) { - sys_mbox_post(&mbox, msg); - } else { - if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { - memp_free(MEMP_TCPIP_MSG_API, msg); - return ERR_MEM; - } - } - return ERR_OK; -} - -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS -/** - * call sys_timeout in tcpip_thread - * - * @param msecs time in milliseconds for timeout - * @param h function to be called on timeout - * @param arg argument to pass to timeout function h - * @return ERR_MEM on memory error, ERR_OK otherwise - */ -err_t -tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) -{ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_TIMEOUT; - msg->msg.tmo.msecs = msecs; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - sys_mbox_post(&mbox, msg); - return ERR_OK; -} - -/** - * call sys_untimeout in tcpip_thread - * - * @param h function to be called on timeout - * @param arg argument to pass to timeout function h - * @return ERR_MEM on memory error, ERR_OK otherwise - */ -err_t -tcpip_untimeout(sys_timeout_handler h, void *arg) -{ - struct tcpip_msg *msg; - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return ERR_MEM; - } - - msg->type = TCPIP_MSG_UNTIMEOUT; - msg->msg.tmo.h = h; - msg->msg.tmo.arg = arg; - sys_mbox_post(&mbox, msg); - return ERR_OK; -} -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - - -/** - * Sends a message to TCPIP thread to call a function. Caller thread blocks on - * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, - * this has to be done by the user. - * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way - * with least runtime overhead. - * - * @param fn function to be called from TCPIP thread - * @param apimsg argument to API function - * @param sem semaphore to wait on - * @return ERR_OK if the function was called, another err_t if not - */ -err_t -tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) -{ -#if LWIP_TCPIP_CORE_LOCKING - LWIP_UNUSED_ARG(sem); - LOCK_TCPIP_CORE(); - fn(apimsg); - UNLOCK_TCPIP_CORE(); - return ERR_OK; -#else /* LWIP_TCPIP_CORE_LOCKING */ - TCPIP_MSG_VAR_DECLARE(msg); - - LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - TCPIP_MSG_VAR_ALLOC(msg); - TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; - TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; - TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; - sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); - sys_arch_sem_wait(sem, 0); - TCPIP_MSG_VAR_FREE(msg); - return ERR_OK; -#endif /* LWIP_TCPIP_CORE_LOCKING */ -} - -/** - * Synchronously calls function in TCPIP thread and waits for its completion. - * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or - * LWIP_NETCONN_SEM_PER_THREAD. - * If not, a semaphore is created and destroyed on every call which is usually - * an expensive/slow operation. - * @param fn Function to call - * @param call Call parameters - * @return Return value from tcpip_api_call_fn - */ -err_t -tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) -{ -#if LWIP_TCPIP_CORE_LOCKING - err_t err; - LOCK_TCPIP_CORE(); - err = fn(call); - UNLOCK_TCPIP_CORE(); - return err; -#else /* LWIP_TCPIP_CORE_LOCKING */ - TCPIP_MSG_VAR_DECLARE(msg); - -#if !LWIP_NETCONN_SEM_PER_THREAD - err_t err = sys_sem_new(&call->sem, 0); - if (err != ERR_OK) { - return err; - } -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - - TCPIP_MSG_VAR_ALLOC(msg); - TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; - TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; - TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn; -#if LWIP_NETCONN_SEM_PER_THREAD - TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET(); -#else /* LWIP_NETCONN_SEM_PER_THREAD */ - TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem; -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); - sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0); - TCPIP_MSG_VAR_FREE(msg); - -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_free(&call->sem); -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - return call->err; -#endif /* LWIP_TCPIP_CORE_LOCKING */ -} - -/** - * Allocate a structure for a static callback message and initialize it. - * This is intended to be used to send "static" messages from interrupt context. - * - * @param function the function to call - * @param ctx parameter passed to function - * @return a struct pointer to pass to tcpip_trycallback(). - */ -struct tcpip_callback_msg* -tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx) -{ - struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); - if (msg == NULL) { - return NULL; - } - msg->type = TCPIP_MSG_CALLBACK_STATIC; - msg->msg.cb.function = function; - msg->msg.cb.ctx = ctx; - return (struct tcpip_callback_msg*)msg; -} - -/** - * Free a callback message allocated by tcpip_callbackmsg_new(). - * - * @param msg the message to free - */ -void -tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg) -{ - memp_free(MEMP_TCPIP_MSG_API, msg); -} - -/** - * Try to post a callback-message to the tcpip_thread mbox - * This is intended to be used to send "static" messages from interrupt context. - * - * @param msg pointer to the message to post - * @return sys_mbox_trypost() return code - */ -err_t -tcpip_trycallback(struct tcpip_callback_msg* msg) -{ - LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); - return sys_mbox_trypost(&mbox, msg); -} - -/** - * @ingroup lwip_os - * Initialize this module: - * - initialize all sub modules - * - start the tcpip_thread - * - * @param initfunc a function to call when tcpip_thread is running and finished initializing - * @param arg argument to pass to initfunc - */ -void -tcpip_init(tcpip_init_done_fn initfunc, void *arg) -{ - lwip_init(); - - tcpip_init_done = initfunc; - tcpip_init_done_arg = arg; - if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { - LWIP_ASSERT("failed to create tcpip_thread mbox", 0); - } -#if LWIP_TCPIP_CORE_LOCKING - if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) { - LWIP_ASSERT("failed to create lock_tcpip_core", 0); - } -#endif /* LWIP_TCPIP_CORE_LOCKING */ - - sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); -} - -/** - * Simple callback function used with tcpip_callback to free a pbuf - * (pbuf_free has a wrong signature for tcpip_callback) - * - * @param p The pbuf (chain) to be dereferenced. - */ -static void -pbuf_free_int(void *p) -{ - struct pbuf *q = (struct pbuf *)p; - pbuf_free(q); -} - -/** - * A simple wrapper function that allows you to free a pbuf from interrupt context. - * - * @param p The pbuf (chain) to be dereferenced. - * @return ERR_OK if callback could be enqueued, an err_t if not - */ -err_t -pbuf_free_callback(struct pbuf *p) -{ - return tcpip_callback_with_block(pbuf_free_int, p, 0); -} - -/** - * A simple wrapper function that allows you to free heap memory from - * interrupt context. - * - * @param m the heap memory to free - * @return ERR_OK if callback could be enqueued, an err_t if not - */ -err_t -mem_free_callback(void *m) -{ - return tcpip_callback_with_block(mem_free, m, 0); -} - -#endif /* !NO_SYS */ diff --git a/components/net/lwip-2.0.2/src/apps/README.md b/components/net/lwip-2.0.2/src/apps/README.md deleted file mode 100644 index 26670858c5..0000000000 --- a/components/net/lwip-2.0.2/src/apps/README.md +++ /dev/null @@ -1,6 +0,0 @@ -Some net apps for current version LwIP. - -The RT-Thread develop team ported apps. It's easy to use it on finsh/msh. - -- ping -- tftp diff --git a/components/net/lwip-2.0.2/src/apps/httpd/fs.c b/components/net/lwip-2.0.2/src/apps/httpd/fs.c deleted file mode 100644 index 35b5e31038..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/fs.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/apps/httpd_opts.h" -#include "lwip/def.h" -#include "lwip/apps/fs.h" -#include "fsdata.h" -#include - - -#if HTTPD_USE_CUSTOM_FSDATA -#include "fsdata_custom.c" -#else /* HTTPD_USE_CUSTOM_FSDATA */ -#include "fsdata.c" -#endif /* HTTPD_USE_CUSTOM_FSDATA */ - -/*-----------------------------------------------------------------------------------*/ - -#if LWIP_HTTPD_CUSTOM_FILES -int fs_open_custom(struct fs_file *file, const char *name); -void fs_close_custom(struct fs_file *file); -#if LWIP_HTTPD_FS_ASYNC_READ -u8_t fs_canread_custom(struct fs_file *file); -u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); -int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_read_custom(struct fs_file *file, char *buffer, int count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - -/*-----------------------------------------------------------------------------------*/ -err_t -fs_open(struct fs_file *file, const char *name) -{ - const struct fsdata_file *f; - - if ((file == NULL) || (name == NULL)) { - return ERR_ARG; - } - -#if LWIP_HTTPD_CUSTOM_FILES - if (fs_open_custom(file, name)) { - file->is_custom_file = 1; - return ERR_OK; - } - file->is_custom_file = 0; -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - - for (f = FS_ROOT; f != NULL; f = f->next) { - if (!strcmp(name, (const char *)f->name)) { - file->data = (const char *)f->data; - file->len = f->len; - file->index = f->len; - file->pextension = NULL; - file->flags = f->flags; -#if HTTPD_PRECALCULATED_CHECKSUM - file->chksum_count = f->chksum_count; - file->chksum = f->chksum; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ -#if LWIP_HTTPD_FILE_STATE - file->state = fs_state_init(file, name); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - return ERR_OK; - } - } - /* file not found */ - return ERR_VAL; -} - -/*-----------------------------------------------------------------------------------*/ -void -fs_close(struct fs_file *file) -{ -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file) { - fs_close_custom(file); - } -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#if LWIP_HTTPD_FILE_STATE - fs_state_free(file, file->state); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - LWIP_UNUSED_ARG(file); -} -/*-----------------------------------------------------------------------------------*/ -#if LWIP_HTTPD_DYNAMIC_FILE_READ -#if LWIP_HTTPD_FS_ASYNC_READ -int -fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg) -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int -fs_read(struct fs_file *file, char *buffer, int count) -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -{ - int read; - if(file->index == file->len) { - return FS_READ_EOF; - } -#if LWIP_HTTPD_FS_ASYNC_READ - LWIP_UNUSED_ARG(callback_fn); - LWIP_UNUSED_ARG(callback_arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file) { -#if LWIP_HTTPD_FS_ASYNC_READ - return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ - return fs_read_custom(file, buffer, count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - } -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - - read = file->len - file->index; - if(read > count) { - read = count; - } - - MEMCPY(buffer, (file->data + file->index), read); - file->index += read; - - return(read); -} -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -/*-----------------------------------------------------------------------------------*/ -#if LWIP_HTTPD_FS_ASYNC_READ -int -fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg) -{ - if (file != NULL) { -#if LWIP_HTTPD_FS_ASYNC_READ -#if LWIP_HTTPD_CUSTOM_FILES - if (!fs_canread_custom(file)) { - if (fs_wait_read_custom(file, callback_fn, callback_arg)) { - return 0; - } - } -#else /* LWIP_HTTPD_CUSTOM_FILES */ - LWIP_UNUSED_ARG(callback_fn); - LWIP_UNUSED_ARG(callback_arg); -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - } - return 1; -} -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -/*-----------------------------------------------------------------------------------*/ -int -fs_bytes_left(struct fs_file *file) -{ - return file->len - file->index; -} diff --git a/components/net/lwip-2.0.2/src/apps/httpd/fs/404.html b/components/net/lwip-2.0.2/src/apps/httpd/fs/404.html deleted file mode 100644 index 40b343a91e..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/fs/404.html +++ /dev/null @@ -1,21 +0,0 @@ - -lwIP - A Lightweight TCP/IP Stack - - - - -
- SICS logo - -

lwIP - A Lightweight TCP/IP Stack

-

404 - Page not found

-

- Sorry, the page you are requesting was not found on this - server. -

-
-   -
- - diff --git a/components/net/lwip-2.0.2/src/apps/httpd/fs/img/sics.gif b/components/net/lwip-2.0.2/src/apps/httpd/fs/img/sics.gif deleted file mode 100644 index 0a4fc7bb07050eec9226ca93bc9ad237f35502c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 724 zcmZ?wbhEHbbYoCrSjxa~Q`<5tD{KG${gWq8=I7_%uwlcpWy=~G8p_Jb4zT=SA;^3z!7uBu>UZ()&> z+r1;Oh0mFly?klC)5cAV$sD}98F{LBUHERS_hGGKac5`W-mvIltqUt73*&`X?UVf< z%Uqmm^}K~z9MaFS-jwgVGIUF9Z77P_s7Vc}y?@_XT+GT)AcZF$6%$qQsA+Q0bF z!Mss%ktc&>+n*qp2aIzy6-8A8zNf3ovHkU%wPnH@(O;*7g5`QX{a~M@%VFg!JaWkVUk6yFE1wL^V{({yi?^s!by^W;pXIz%mY}~L;uBR^JK|)kW|Avap zVzxyL+2N;b1q1f77^T<4c)gUoN8c;6;F^+^0^VN o#HPS7gPr3^SVM!%(d|c@c+6frXclnOc-SHmma$O4k%7S)08~d;ZvX%Q diff --git a/components/net/lwip-2.0.2/src/apps/httpd/fs/index.html b/components/net/lwip-2.0.2/src/apps/httpd/fs/index.html deleted file mode 100644 index ab575ef089..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/fs/index.html +++ /dev/null @@ -1,47 +0,0 @@ - -lwIP - A Lightweight TCP/IP Stack - - - - -
- SICS logo - -

lwIP - A Lightweight TCP/IP Stack

-

- The web page you are watching was served by a simple web - server running on top of the lightweight TCP/IP stack lwIP. -

-

- lwIP is an open source implementation of the TCP/IP - protocol suite that was originally written by Adam Dunkels - of the Swedish Institute of Computer Science but now is - being actively developed by a team of developers - distributed world-wide. Since it's release, lwIP has - spurred a lot of interest and has been ported to several - platforms and operating systems. lwIP can be used either - with or without an underlying OS. -

-

- The focus of the lwIP TCP/IP implementation is to reduce - the RAM usage while still having a full scale TCP. This - makes lwIP suitable for use in embedded systems with tens - of kilobytes of free RAM and room for around 40 kilobytes - of code ROM. -

-

- More information about lwIP can be found at the lwIP - homepage at http://savannah.nongnu.org/projects/lwip/ - or at the lwIP wiki at http://lwip.wikia.com/. -

-
-   -
- - - diff --git a/components/net/lwip-2.0.2/src/apps/httpd/fsdata.c b/components/net/lwip-2.0.2/src/apps/httpd/fsdata.c deleted file mode 100644 index 6170ce6326..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/fsdata.c +++ /dev/null @@ -1,298 +0,0 @@ -#include "lwip/apps/fs.h" -#include "lwip/def.h" -#include "fsdata.h" - - -#define file_NULL (struct fsdata_file *) NULL - - -static const unsigned int dummy_align__img_sics_gif = 0; -static const unsigned char data__img_sics_gif[] = { -/* /img/sics.gif (14 chars) */ -0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00, - -/* HTTP header */ -/* "HTTP/1.0 200 OK -" (17 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, -0x0a, -/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) -" (63 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, -0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, -0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, -0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, -/* "Content-type: image/gif - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, -0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a, -/* raw file data (724 bytes) */ -0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39, -0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6, -0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e, -0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99, -0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5, -0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b, -0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00, -0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f, -0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac, -0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31, -0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9, -0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51, -0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78, -0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0, -0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07, -0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42, -0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c, -0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01, -0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10, -0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8, -0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4, -0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86, -0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06, -0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07, -0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29, -0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a, -0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97, -0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9, -0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70, -0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c, -0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01, -0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24, -0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29, -0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73, -0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab, -0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45, -0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8, -0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5, -0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10, -0x41,0x00,0x00,0x3b,}; - -static const unsigned int dummy_align__404_html = 1; -static const unsigned char data__404_html[] = { -/* /404.html (10 chars) */ -0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00, - -/* HTTP header */ -/* "HTTP/1.0 404 File not found -" (29 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c, -0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a, -/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) -" (63 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, -0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, -0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, -0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, -/* "Content-type: text/html - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, -0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, -/* raw file data (565 bytes) */ -0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, -0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, -0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, -0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, -0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, -0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, -0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, -0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, -0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, -0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, -0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, -0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, -0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, -0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, -0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, -0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, -0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, -0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, -0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, -0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20, -0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a, -0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72, -0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75, -0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20, -0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e, -0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76, -0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, -0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, -0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, -0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, -0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, -0x6d,0x6c,0x3e,0x0d,0x0a,}; - -static const unsigned int dummy_align__index_html = 2; -static const unsigned char data__index_html[] = { -/* /index.html (12 chars) */ -0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00, - -/* HTTP header */ -/* "HTTP/1.0 200 OK -" (17 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, -0x0a, -/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip) -" (63 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, -0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, -0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, -0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, -/* "Content-type: text/html - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, -0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, -/* raw file data (1751 bytes) */ -0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, -0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, -0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, -0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, -0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, -0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, -0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, -0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, -0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, -0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, -0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, -0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, -0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, -0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, -0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, -0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, -0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, -0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, -0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, -0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77, -0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20, -0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72, -0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20, -0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72, -0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20, -0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67, -0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20, -0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c, -0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70, -0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20, -0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20, -0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50, -0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63, -0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61, -0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69, -0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20, -0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77, -0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f, -0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b, -0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, -0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75, -0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53, -0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e, -0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e, -0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c, -0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f, -0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20, -0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77, -0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65, -0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c, -0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70, -0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69, -0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20, -0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73, -0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61, -0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61, -0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77, -0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65, -0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68, -0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75, -0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a, -0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f, -0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, -0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09, -0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67, -0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61, -0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c, -0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69, -0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e, -0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, -0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f, -0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72, -0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34, -0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a, -0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d, -0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72, -0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49, -0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61, -0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20, -0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d, -0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70, -0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67, -0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f, -0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61, -0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72, -0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f, -0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74, -0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61, -0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d, -0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b, -0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, -0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c, -0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, -0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, -0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, -0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, -0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, -0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,}; - - - -const struct fsdata_file file__img_sics_gif[] = { { -file_NULL, -data__img_sics_gif, -data__img_sics_gif + 16, -sizeof(data__img_sics_gif) - 16, -1, -}}; - -const struct fsdata_file file__404_html[] = { { -file__img_sics_gif, -data__404_html, -data__404_html + 12, -sizeof(data__404_html) - 12, -1, -}}; - -const struct fsdata_file file__index_html[] = { { -file__404_html, -data__index_html, -data__index_html + 12, -sizeof(data__index_html) - 12, -1, -}}; - -#define FS_ROOT file__index_html -#define FS_NUMFILES 3 - diff --git a/components/net/lwip-2.0.2/src/apps/httpd/fsdata.h b/components/net/lwip-2.0.2/src/apps/httpd/fsdata.h deleted file mode 100644 index ac4548c785..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/fsdata.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_FSDATA_H -#define LWIP_FSDATA_H - -#include "lwip/apps/httpd_opts.h" -#include "lwip/apps/fs.h" - -struct fsdata_file { - const struct fsdata_file *next; - const unsigned char *name; - const unsigned char *data; - int len; - u8_t flags; -#if HTTPD_PRECALCULATED_CHECKSUM - u16_t chksum_count; - const struct fsdata_chksum *chksum; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ -}; - -#endif /* LWIP_FSDATA_H */ diff --git a/components/net/lwip-2.0.2/src/apps/httpd/httpd.c b/components/net/lwip-2.0.2/src/apps/httpd/httpd.c deleted file mode 100644 index 43195d7c54..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/httpd.c +++ /dev/null @@ -1,2629 +0,0 @@ -/** - * @file - * LWIP HTTP server implementation - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -/** - * @defgroup httpd HTTP server - * @ingroup apps - * - * This httpd supports for a - * rudimentary server-side-include facility which will replace tags of the form - * in any file whose extension is .shtml, .shtm or .ssi with - * strings provided by an include handler whose pointer is provided to the - * module via function http_set_ssi_handler(). - * Additionally, a simple common - * gateway interface (CGI) handling mechanism has been added to allow clients - * to hook functions to particular request URIs. - * - * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h. - * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h. - * - * By default, the server assumes that HTTP headers are already present in - * each file stored in the file system. By defining LWIP_HTTPD_DYNAMIC_HEADERS in - * lwipopts.h, this behavior can be changed such that the server inserts the - * headers automatically based on the extension of the file being served. If - * this mode is used, be careful to ensure that the file system image used - * does not already contain the header information. - * - * File system images without headers can be created using the makefsfile - * tool with the -h command line option. - * - * - * Notes about valid SSI tags - * -------------------------- - * - * The following assumptions are made about tags used in SSI markers: - * - * 1. No tag may contain '-' or whitespace characters within the tag name. - * 2. Whitespace is allowed between the tag leadin "". - * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters. - * - * Notes on CGI usage - * ------------------ - * - * The simple CGI support offered here works with GET method requests only - * and can handle up to 16 parameters encoded into the URI. The handler - * function may not write directly to the HTTP output but must return a - * filename that the HTTP server will send to the browser as a response to - * the incoming CGI request. - * - * - * - * The list of supported file types is quite short, so if makefsdata complains - * about an unknown extension, make sure to add it (and its doctype) to - * the 'g_psHTTPHeaders' list. - */ -#include "lwip/init.h" -#include "lwip/apps/httpd.h" -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/apps/fs.h" -#include "httpd_structs.h" -#include "lwip/def.h" -#include "lwip/ip.h" -#include "lwip/tcp.h" - -#include /* memset */ -#include /* atoi */ -#include - -#if LWIP_TCP && LWIP_CALLBACK_API - -/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */ -#define MIN_REQ_LEN 7 - -#define CRLF "\r\n" -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE -#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive" -#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive" -#endif - -/** These defines check whether tcp_write has to copy data or not */ - -/** This was TI's check whether to let TCP copy data or not - * \#define HTTP_IS_DATA_VOLATILE(hs) ((hs->file < (char *)0x20000000) ? 0 : TCP_WRITE_FLAG_COPY) - */ -#ifndef HTTP_IS_DATA_VOLATILE -#if LWIP_HTTPD_SSI -/* Copy for SSI files, no copy for non-SSI files */ -#define HTTP_IS_DATA_VOLATILE(hs) ((hs)->ssi ? TCP_WRITE_FLAG_COPY : 0) -#else /* LWIP_HTTPD_SSI */ -/** Default: don't copy if the data is sent from file-system directly */ -#define HTTP_IS_DATA_VOLATILE(hs) (((hs->file != NULL) && (hs->handle != NULL) && (hs->file == \ - (const char*)hs->handle->data + hs->handle->len - hs->left)) \ - ? 0 : TCP_WRITE_FLAG_COPY) -#endif /* LWIP_HTTPD_SSI */ -#endif - -/** Default: headers are sent from ROM */ -#ifndef HTTP_IS_HDR_VOLATILE -#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0 -#endif - -/* Return values for http_send_*() */ -#define HTTP_DATA_TO_SEND_BREAK 2 -#define HTTP_DATA_TO_SEND_CONTINUE 1 -#define HTTP_NO_DATA_TO_SEND 0 - -typedef struct -{ - const char *name; - u8_t shtml; -} default_filename; - -const default_filename g_psDefaultFilenames[] = { - {"/index.shtml", 1 }, - {"/index.ssi", 1 }, - {"/index.shtm", 1 }, - {"/index.html", 0 }, - {"/index.htm", 0 } -}; - -#define NUM_DEFAULT_FILENAMES (sizeof(g_psDefaultFilenames) / \ - sizeof(default_filename)) - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST -/** HTTP request is copied here from pbufs for simple parsing */ -static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH+1]; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -#if LWIP_HTTPD_SUPPORT_POST -#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN -#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN -#endif -#endif -#ifndef LWIP_HTTPD_URI_BUF_LEN -#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN -#endif -#if LWIP_HTTPD_URI_BUF_LEN -/* Filename for response file to send when POST is finished or - * search for default files when a directory is requested. */ -static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN+1]; -#endif - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/* The number of individual strings that comprise the headers sent before each - * requested file. - */ -#define NUM_FILE_HDR_STRINGS 5 -#define HDR_STRINGS_IDX_HTTP_STATUS 0 /* e.g. "HTTP/1.0 200 OK\r\n" */ -#define HDR_STRINGS_IDX_SERVER_NAME 1 /* e.g. "Server: "HTTPD_SERVER_AGENT"\r\n" */ -#define HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE 2 /* e.g. "Content-Length: xy\r\n" and/or "Connection: keep-alive\r\n" */ -#define HDR_STRINGS_IDX_CONTENT_LEN_NR 3 /* the byte count, when content-length is used */ -#define HDR_STRINGS_IDX_CONTENT_TYPE 4 /* the content type (or default answer content type including default document) */ - -/* The dynamically generated Content-Length buffer needs space for CRLF + NULL */ -#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3 -#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE -/* The dynamically generated Content-Length buffer shall be able to work with - ~953 MB (9 digits) */ -#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) -#endif -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -#if LWIP_HTTPD_SSI - -#define HTTPD_LAST_TAG_PART 0xFFFF - -enum tag_check_state { - TAG_NONE, /* Not processing an SSI tag */ - TAG_LEADIN, /* Tag lead in "" being processed */ - TAG_SENDING /* Sending tag replacement string */ -}; - -struct http_ssi_state { - const char *parsed; /* Pointer to the first unparsed byte in buf. */ -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - const char *tag_started;/* Pointer to the first opening '<' of the tag. */ -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ - const char *tag_end; /* Pointer to char after the closing '>' of the tag. */ - u32_t parse_left; /* Number of unparsed bytes in buf. */ - u16_t tag_index; /* Counter used by tag parsing state machine */ - u16_t tag_insert_len; /* Length of insert in string tag_insert */ -#if LWIP_HTTPD_SSI_MULTIPART - u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */ -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - u8_t tag_name_len; /* Length of the tag name in string tag_name */ - char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */ - char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */ - enum tag_check_state tag_state; /* State of the tag processor */ -}; -#endif /* LWIP_HTTPD_SSI */ - -struct http_state { -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - struct http_state *next; -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - struct fs_file file_handle; - struct fs_file *handle; - const char *file; /* Pointer to first unsent byte in buf. */ - - struct tcp_pcb *pcb; -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - struct pbuf *req; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -#if LWIP_HTTPD_DYNAMIC_FILE_READ - char *buf; /* File read buffer. */ - int buf_len; /* Size of file read buffer, buf. */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - u32_t left; /* Number of unsent bytes in buf. */ - u8_t retries; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - u8_t keepalive; -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ -#if LWIP_HTTPD_SSI - struct http_ssi_state *ssi; -#endif /* LWIP_HTTPD_SSI */ -#if LWIP_HTTPD_CGI - char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ - char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ -#endif /* LWIP_HTTPD_CGI */ -#if LWIP_HTTPD_DYNAMIC_HEADERS - const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */ - char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE]; - u16_t hdr_pos; /* The position of the first unsent header byte in the - current string */ - u16_t hdr_index; /* The index of the hdr string currently being sent. */ -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_TIMING - u32_t time_started; -#endif /* LWIP_HTTPD_TIMING */ -#if LWIP_HTTPD_SUPPORT_POST - u32_t post_content_len_left; -#if LWIP_HTTPD_POST_MANUAL_WND - u32_t unrecved_bytes; - u8_t no_auto_wnd; - u8_t post_finished; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ -#endif /* LWIP_HTTPD_SUPPORT_POST*/ -}; - -#if HTTPD_USE_MEM_POOL -LWIP_MEMPOOL_DECLARE(HTTPD_STATE, MEMP_NUM_PARALLEL_HTTPD_CONNS, sizeof(struct http_state), "HTTPD_STATE") -#if LWIP_HTTPD_SSI -LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS, sizeof(struct http_ssi_state), "HTTPD_SSI_STATE") -#define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x)) -#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE) -#endif /* LWIP_HTTPD_SSI */ -#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE) -#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x)) -#else /* HTTPD_USE_MEM_POOL */ -#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state)) -#define HTTP_FREE_HTTP_STATE(x) mem_free(x) -#if LWIP_HTTPD_SSI -#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state)) -#define HTTP_FREE_SSI_STATE(x) mem_free(x) -#endif /* LWIP_HTTPD_SSI */ -#endif /* HTTPD_USE_MEM_POOL */ - -static err_t http_close_conn(struct tcp_pcb *pcb, struct http_state *hs); -static err_t http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn); -static err_t http_find_file(struct http_state *hs, const char *uri, int is_09); -static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char* params); -static err_t http_poll(void *arg, struct tcp_pcb *pcb); -static u8_t http_check_eof(struct tcp_pcb *pcb, struct http_state *hs); -#if LWIP_HTTPD_FS_ASYNC_READ -static void http_continue(void *connection); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -#if LWIP_HTTPD_SSI -/* SSI insert handler function pointer. */ -tSSIHandler g_pfnSSIHandler; -#if !LWIP_HTTPD_SSI_RAW -int g_iNumTags; -const char **g_ppcTags; -#endif /* !LWIP_HTTPD_SSI_RAW */ - -#define LEN_TAG_LEAD_IN 5 -const char * const g_pcTagLeadIn = ""; -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_CGI -/* CGI handler information */ -const tCGI *g_pCGIs; -int g_iNumCGIs; -int http_cgi_paramcount; -#define http_cgi_params hs->params -#define http_cgi_param_vals hs->param_vals -#elif LWIP_HTTPD_CGI_SSI -char *http_cgi_params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ -char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ -#endif /* LWIP_HTTPD_CGI */ - -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED -/** global list of active HTTP connections, use to kill the oldest when - running out of memory */ -static struct http_state *http_connections; - -static void -http_add_connection(struct http_state *hs) -{ - /* add the connection to the list */ - hs->next = http_connections; - http_connections = hs; -} - -static void -http_remove_connection(struct http_state *hs) -{ - /* take the connection off the list */ - if (http_connections) { - if (http_connections == hs) { - http_connections = hs->next; - } else { - struct http_state *last; - for(last = http_connections; last->next != NULL; last = last->next) { - if (last->next == hs) { - last->next = hs->next; - break; - } - } - } - } -} - -static void -http_kill_oldest_connection(u8_t ssi_required) -{ - struct http_state *hs = http_connections; - struct http_state *hs_free_next = NULL; - while(hs && hs->next) { -#if LWIP_HTTPD_SSI - if (ssi_required) { - if (hs->next->ssi != NULL) { - hs_free_next = hs; - } - } else -#else /* LWIP_HTTPD_SSI */ - LWIP_UNUSED_ARG(ssi_required); -#endif /* LWIP_HTTPD_SSI */ - { - hs_free_next = hs; - } - LWIP_ASSERT("broken list", hs != hs->next); - hs = hs->next; - } - if (hs_free_next != NULL) { - LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL); - LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL); - /* send RST when killing a connection because of memory shortage */ - http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ - } -} -#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - -#define http_add_connection(hs) -#define http_remove_connection(hs) - -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - -#if LWIP_HTTPD_SSI -/** Allocate as struct http_ssi_state. */ -static struct http_ssi_state* -http_ssi_state_alloc(void) -{ - struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE(); -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - if (ret == NULL) { - http_kill_oldest_connection(1); - ret = HTTP_ALLOC_SSI_STATE(); - } -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - if (ret != NULL) { - memset(ret, 0, sizeof(struct http_ssi_state)); - } - return ret; -} - -/** Free a struct http_ssi_state. */ -static void -http_ssi_state_free(struct http_ssi_state *ssi) -{ - if (ssi != NULL) { - HTTP_FREE_SSI_STATE(ssi); - } -} -#endif /* LWIP_HTTPD_SSI */ - -/** Initialize a struct http_state. - */ -static void -http_state_init(struct http_state* hs) -{ - /* Initialize the structure. */ - memset(hs, 0, sizeof(struct http_state)); -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Indicate that the headers are not yet valid */ - hs->hdr_index = NUM_FILE_HDR_STRINGS; -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -} - -/** Allocate a struct http_state. */ -static struct http_state* -http_state_alloc(void) -{ - struct http_state *ret = HTTP_ALLOC_HTTP_STATE(); -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - if (ret == NULL) { - http_kill_oldest_connection(0); - ret = HTTP_ALLOC_HTTP_STATE(); - } -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - if (ret != NULL) { - http_state_init(ret); - http_add_connection(ret); - } - return ret; -} - -/** Free a struct http_state. - * Also frees the file data if dynamic. - */ -static void -http_state_eof(struct http_state *hs) -{ - if(hs->handle) { -#if LWIP_HTTPD_TIMING - u32_t ms_needed = sys_now() - hs->time_started; - u32_t needed = LWIP_MAX(1, (ms_needed/100)); - LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n", - ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed))); -#endif /* LWIP_HTTPD_TIMING */ - fs_close(hs->handle); - hs->handle = NULL; - } -#if LWIP_HTTPD_DYNAMIC_FILE_READ - if (hs->buf != NULL) { - mem_free(hs->buf); - hs->buf = NULL; - } -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -#if LWIP_HTTPD_SSI - if (hs->ssi) { - http_ssi_state_free(hs->ssi); - hs->ssi = NULL; - } -#endif /* LWIP_HTTPD_SSI */ -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - if (hs->req) { - pbuf_free(hs->req); - hs->req = NULL; - } -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -} - -/** Free a struct http_state. - * Also frees the file data if dynamic. - */ -static void -http_state_free(struct http_state *hs) -{ - if (hs != NULL) { - http_state_eof(hs); - http_remove_connection(hs); - HTTP_FREE_HTTP_STATE(hs); - } -} - -/** Call tcp_write() in a loop trying smaller and smaller length - * - * @param pcb tcp_pcb to send - * @param ptr Data to send - * @param length Length of data to send (in/out: on return, contains the - * amount of data sent) - * @param apiflags directly passed to tcp_write - * @return the return value of tcp_write - */ -static err_t -http_write(struct tcp_pcb *pcb, const void* ptr, u16_t *length, u8_t apiflags) -{ - u16_t len, max_len; - err_t err; - LWIP_ASSERT("length != NULL", length != NULL); - len = *length; - if (len == 0) { - return ERR_OK; - } - /* We cannot send more data than space available in the send buffer. */ - max_len = tcp_sndbuf(pcb); - if (max_len < len) { - len = max_len; - } -#ifdef HTTPD_MAX_WRITE_LEN - /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ - max_len = HTTPD_MAX_WRITE_LEN(pcb); - if(len > max_len) { - len = max_len; - } -#endif /* HTTPD_MAX_WRITE_LEN */ - do { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying go send %d bytes\n", len)); - err = tcp_write(pcb, ptr, len, apiflags); - if (err == ERR_MEM) { - if ((tcp_sndbuf(pcb) == 0) || - (tcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) { - /* no need to try smaller sizes */ - len = 1; - } else { - len /= 2; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, - ("Send failed, trying less (%d bytes)\n", len)); - } - } while ((err == ERR_MEM) && (len > 1)); - - if (err == ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len)); - *length = len; - } else { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); - *length = 0; - } - -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - /* ensure nagle is normally enabled (only disabled for persistent connections - when all data has been enqueued but the connection stays open for the next - request */ - tcp_nagle_enable(pcb); -#endif - - return err; -} - -/** - * The connection shall be actively closed (using RST to close from fault states). - * Reset the sent- and recv-callbacks. - * - * @param pcb the tcp pcb to reset callbacks - * @param hs connection state to free - */ -static err_t -http_close_or_abort_conn(struct tcp_pcb *pcb, struct http_state *hs, u8_t abort_conn) -{ - err_t err; - LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void*)pcb)); - -#if LWIP_HTTPD_SUPPORT_POST - if (hs != NULL) { - if ((hs->post_content_len_left != 0) -#if LWIP_HTTPD_POST_MANUAL_WND - || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0)) -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - ) { - /* make sure the post code knows that the connection is closed */ - http_uri_buf[0] = 0; - httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); - } - } -#endif /* LWIP_HTTPD_SUPPORT_POST*/ - - - tcp_arg(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_err(pcb, NULL); - tcp_poll(pcb, NULL, 0); - tcp_sent(pcb, NULL); - if (hs != NULL) { - http_state_free(hs); - } - - if (abort_conn) { - tcp_abort(pcb); - return ERR_OK; - } - err = tcp_close(pcb); - if (err != ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void*)pcb)); - /* error closing, try again later in poll */ - tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); - } - return err; -} - -/** - * The connection shall be actively closed. - * Reset the sent- and recv-callbacks. - * - * @param pcb the tcp pcb to reset callbacks - * @param hs connection state to free - */ -static err_t -http_close_conn(struct tcp_pcb *pcb, struct http_state *hs) -{ - return http_close_or_abort_conn(pcb, hs, 0); -} - -/** End of file: either close the connection (Connection: close) or - * close the file (Connection: keep-alive) - */ -static void -http_eof(struct tcp_pcb *pcb, struct http_state *hs) -{ - /* HTTP/1.1 persistent connection? (Not supported for SSI) */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { - http_remove_connection(hs); - - http_state_eof(hs); - http_state_init(hs); - /* restore state: */ - hs->pcb = pcb; - hs->keepalive = 1; - http_add_connection(hs); - /* ensure nagle doesn't interfere with sending all data as fast as possible: */ - tcp_nagle_disable(pcb); - } else -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - { - http_close_conn(pcb, hs); - } -} - -#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI -/** - * Extract URI parameters from the parameter-part of an URI in the form - * "test.cgi?x=y" @todo: better explanation! - * Pointers to the parameters are stored in hs->param_vals. - * - * @param hs http connection state - * @param params pointer to the NULL-terminated parameter string from the URI - * @return number of parameters extracted - */ -static int -extract_uri_parameters(struct http_state *hs, char *params) -{ - char *pair; - char *equals; - int loop; - - LWIP_UNUSED_ARG(hs); - - /* If we have no parameters at all, return immediately. */ - if(!params || (params[0] == '\0')) { - return(0); - } - - /* Get a pointer to our first parameter */ - pair = params; - - /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the - * remainder (if any) */ - for(loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) { - - /* Save the name of the parameter */ - http_cgi_params[loop] = pair; - - /* Remember the start of this name=value pair */ - equals = pair; - - /* Find the start of the next name=value pair and replace the delimiter - * with a 0 to terminate the previous pair string. */ - pair = strchr(pair, '&'); - if(pair) { - *pair = '\0'; - pair++; - } else { - /* We didn't find a new parameter so find the end of the URI and - * replace the space with a '\0' */ - pair = strchr(equals, ' '); - if(pair) { - *pair = '\0'; - } - - /* Revert to NULL so that we exit the loop as expected. */ - pair = NULL; - } - - /* Now find the '=' in the previous pair, replace it with '\0' and save - * the parameter value string. */ - equals = strchr(equals, '='); - if(equals) { - *equals = '\0'; - http_cgi_param_vals[loop] = equals + 1; - } else { - http_cgi_param_vals[loop] = NULL; - } - } - - return loop; -} -#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ - -#if LWIP_HTTPD_SSI -/** - * Insert a tag (found in an shtml in the form of "" into the file. - * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement - * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN). - * The amount of data written is stored to ssi->tag_insert_len. - * - * @todo: return tag_insert_len - maybe it can be removed from struct http_state? - * - * @param hs http connection state - */ -static void -get_tag_insert(struct http_state *hs) -{ -#if LWIP_HTTPD_SSI_RAW - const char* tag; -#else /* LWIP_HTTPD_SSI_RAW */ - int tag; -#endif /* LWIP_HTTPD_SSI_RAW */ - size_t len; - struct http_ssi_state *ssi; -#if LWIP_HTTPD_SSI_MULTIPART - u16_t current_tag_part; -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - - LWIP_ASSERT("hs != NULL", hs != NULL); - ssi = hs->ssi; - LWIP_ASSERT("ssi != NULL", ssi != NULL); -#if LWIP_HTTPD_SSI_MULTIPART - current_tag_part = ssi->tag_part; - ssi->tag_part = HTTPD_LAST_TAG_PART; -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if LWIP_HTTPD_SSI_RAW - tag = ssi->tag_name; -#endif - - if(g_pfnSSIHandler -#if !LWIP_HTTPD_SSI_RAW - && g_ppcTags && g_iNumTags -#endif /* !LWIP_HTTPD_SSI_RAW */ - ) { - - /* Find this tag in the list we have been provided. */ -#if LWIP_HTTPD_SSI_RAW - { -#else /* LWIP_HTTPD_SSI_RAW */ - for(tag = 0; tag < g_iNumTags; tag++) { - if(strcmp(ssi->tag_name, g_ppcTags[tag]) == 0) -#endif /* LWIP_HTTPD_SSI_RAW */ - { - ssi->tag_insert_len = g_pfnSSIHandler(tag, ssi->tag_insert, - LWIP_HTTPD_MAX_TAG_INSERT_LEN -#if LWIP_HTTPD_SSI_MULTIPART - , current_tag_part, &ssi->tag_part -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if LWIP_HTTPD_FILE_STATE - , (hs->handle ? hs->handle->state : NULL) -#endif /* LWIP_HTTPD_FILE_STATE */ - ); -#if LWIP_HTTPD_SSI_RAW - if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN) -#endif /* LWIP_HTTPD_SSI_RAW */ - { - return; - } - } - } - } - - /* If we drop out, we were asked to serve a page which contains tags that - * we don't have a handler for. Merely echo back the tags with an error - * marker. */ -#define UNKNOWN_TAG1_TEXT "***UNKNOWN TAG " -#define UNKNOWN_TAG1_LEN 18 -#define UNKNOWN_TAG2_TEXT "***" -#define UNKNOWN_TAG2_LEN 7 - len = LWIP_MIN(sizeof(ssi->tag_name), LWIP_MIN(strlen(ssi->tag_name), - LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN))); - MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN); - MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len); - MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN); - ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0; - - len = strlen(ssi->tag_insert); - LWIP_ASSERT("len <= 0xffff", len <= 0xffff); - ssi->tag_insert_len = (u16_t)len; -} -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/** - * Generate the relevant HTTP headers for the given filename and write - * them into the supplied buffer. - */ -static void -get_http_headers(struct http_state *hs, const char *uri) -{ - size_t content_type; - char *tmp; - char *ext; - char *vars; - u8_t add_content_len; - - /* In all cases, the second header we send is the server identification - so set it here. */ - hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER]; - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = NULL; - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = NULL; - - /* Is this a normal file or the special case we use to send back the - default "404: Page not found" response? */ - if (uri == NULL) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT]; - } else -#endif - { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML]; - } - - /* Set up to send the first header string. */ - hs->hdr_index = 0; - hs->hdr_pos = 0; - return; - } - /* We are dealing with a particular filename. Look for one other - special case. We assume that any filename with "404" in it must be - indicative of a 404 server error whereas all other files require - the 200 OK header. */ - if (strstr(uri, "404")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; - } else if (strstr(uri, "400")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST]; - } else if (strstr(uri, "501")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL]; - } else { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK]; - } - - /* Determine if the URI has any variables and, if so, temporarily remove - them. */ - vars = strchr(uri, '?'); - if(vars) { - *vars = '\0'; - } - - /* Get a pointer to the file extension. We find this by looking for the - last occurrence of "." in the filename passed. */ - ext = NULL; - tmp = strchr(uri, '.'); - while (tmp) { - ext = tmp + 1; - tmp = strchr(ext, '.'); - } - if (ext != NULL) { - /* Now determine the content type and add the relevant header for that. */ - for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) { - /* Have we found a matching extension? */ - if(!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) { - break; - } - } - } else { - content_type = NUM_HTTP_HEADERS; - } - - /* Reinstate the parameter marker if there was one in the original URI. */ - if (vars) { - *vars = '?'; - } - -#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI - /* Does the URL passed have any file extension? If not, we assume it - is a special-case URL used for control state notification and we do - not send any HTTP headers with the response. */ - if (!ext) { - /* Force the header index to a value indicating that all headers - have already been sent. */ - hs->hdr_index = NUM_FILE_HDR_STRINGS; - return; - } -#endif /* LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI */ - add_content_len = 1; - /* Did we find a matching extension? */ - if(content_type < NUM_HTTP_HEADERS) { - /* yes, store it */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[content_type].content_type; - } else if (!ext) { - /* no, no extension found -> use binary transfer to prevent the browser adding '.txt' on save */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP; - } else { - /* No - use the default, plain text file type. */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE; - } - /* Add content-length header? */ -#if LWIP_HTTPD_SSI - if (hs->ssi != NULL) { - add_content_len = 0; /* @todo: get maximum file length from SSI */ - } else -#endif /* LWIP_HTTPD_SSI */ - if ((hs->handle == NULL) || - ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { - add_content_len = 0; - } - if (add_content_len) { - size_t len; - lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, - hs->handle->len); - len = strlen(hs->hdr_content_len); - if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) { - SMEMCPY(&hs->hdr_content_len[len], CRLF "\0", 3); - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len; - } else { - add_content_len = 0; - } - } -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (add_content_len) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN]; - } else { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; - } -#else /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - if (add_content_len) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - - /* Set up to send the first header string. */ - hs->hdr_index = 0; - hs->hdr_pos = 0; -} - -/** Sub-function of http_send(): send dynamic headers - * - * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued - * - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body - * - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending, - * so don't send HTTP body yet - */ -static u8_t -http_send_headers(struct tcp_pcb *pcb, struct http_state *hs) -{ - err_t err; - u16_t len; - u8_t data_to_send = HTTP_NO_DATA_TO_SEND; - u16_t hdrlen, sendlen; - - /* How much data can we send? */ - len = tcp_sndbuf(pcb); - sendlen = len; - - while(len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) { - const void *ptr; - u16_t old_sendlen; - u8_t apiflags; - /* How much do we have to send from the current header? */ - hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]); - - /* How much of this can we send? */ - sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos); - - /* Send this amount of data or as much as we can given memory - * constraints. */ - ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos); - old_sendlen = sendlen; - apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr); - if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) { - /* content-length is always volatile */ - apiflags |= TCP_WRITE_FLAG_COPY; - } - if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) { - apiflags |= TCP_WRITE_FLAG_MORE; - } - err = http_write(pcb, ptr, &sendlen, apiflags); - if ((err == ERR_OK) && (old_sendlen != sendlen)) { - /* Remember that we added some more data to be transmitted. */ - data_to_send = HTTP_DATA_TO_SEND_CONTINUE; - } else if (err != ERR_OK) { - /* special case: http_write does not try to send 1 byte */ - sendlen = 0; - } - - /* Fix up the header position for the next time round. */ - hs->hdr_pos += sendlen; - len -= sendlen; - - /* Have we finished sending this string? */ - if(hs->hdr_pos == hdrlen) { - /* Yes - move on to the next one */ - hs->hdr_index++; - /* skip headers that are NULL (not all headers are required) */ - while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) && - (hs->hdrs[hs->hdr_index] == NULL)) { - hs->hdr_index++; - } - hs->hdr_pos = 0; - } - } - - if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file == NULL)) { - /* When we are at the end of the headers, check for data to send - * instead of waiting for ACK from remote side to continue - * (which would happen when sending files from async read). */ - if(http_check_eof(pcb, hs)) { - data_to_send = HTTP_DATA_TO_SEND_CONTINUE; - } - } - /* If we get here and there are still header bytes to send, we send - * the header information we just wrote immediately. If there are no - * more headers to send, but we do have file data to send, drop through - * to try to send some file data too. */ - if((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) { - LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n")); - return HTTP_DATA_TO_SEND_BREAK; - } - return data_to_send; -} -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -/** Sub-function of http_send(): end-of-file (or block) is reached, - * either close the file or read the next block (if supported). - * - * @returns: 0 if the file is finished or no data has been read - * 1 if the file is not finished and data has been read - */ -static u8_t -http_check_eof(struct tcp_pcb *pcb, struct http_state *hs) -{ - int bytes_left; -#if LWIP_HTTPD_DYNAMIC_FILE_READ - int count; -#ifdef HTTPD_MAX_WRITE_LEN - int max_write_len; -#endif /* HTTPD_MAX_WRITE_LEN */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - - /* Do we have a valid file handle? */ - if (hs->handle == NULL) { - /* No - close the connection. */ - http_eof(pcb, hs); - return 0; - } - bytes_left = fs_bytes_left(hs->handle); - if (bytes_left <= 0) { - /* We reached the end of the file so this request is done. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } -#if LWIP_HTTPD_DYNAMIC_FILE_READ - /* Do we already have a send buffer allocated? */ - if(hs->buf) { - /* Yes - get the length of the buffer */ - count = LWIP_MIN(hs->buf_len, bytes_left); - } else { - /* We don't have a send buffer so allocate one now */ - count = tcp_sndbuf(pcb); - if(bytes_left < count) { - count = bytes_left; - } -#ifdef HTTPD_MAX_WRITE_LEN - /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ - max_write_len = HTTPD_MAX_WRITE_LEN(pcb); - if (count > max_write_len) { - count = max_write_len; - } -#endif /* HTTPD_MAX_WRITE_LEN */ - do { - hs->buf = (char*)mem_malloc((mem_size_t)count); - if (hs->buf != NULL) { - hs->buf_len = count; - break; - } - count = count / 2; - } while (count > 100); - - /* Did we get a send buffer? If not, return immediately. */ - if (hs->buf == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n")); - return 0; - } - } - - /* Read a block of data from the file. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count)); - -#if LWIP_HTTPD_FS_ASYNC_READ - count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ - count = fs_read(hs->handle, hs->buf, count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - if (count < 0) { - if (count == FS_READ_DELAYED) { - /* Delayed read, wait for FS to unblock us */ - return 0; - } - /* We reached the end of the file so this request is done. - * @todo: close here for HTTP/1.1 when reading file fails */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } - - /* Set up to send the block of data we just read */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count)); - hs->left = count; - hs->file = hs->buf; -#if LWIP_HTTPD_SSI - if (hs->ssi) { - hs->ssi->parse_left = count; - hs->ssi->parsed = hs->buf; - } -#endif /* LWIP_HTTPD_SSI */ -#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0); -#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */ - return 1; -} - -/** Sub-function of http_send(): This is the normal send-routine for non-ssi files - * - * @returns: - 1: data has been written (so call tcp_ouput) - * - 0: no data has been written (no need to call tcp_output) - */ -static u8_t -http_send_data_nonssi(struct tcp_pcb *pcb, struct http_state *hs) -{ - err_t err; - u16_t len; - u8_t data_to_send = 0; - - /* We are not processing an SHTML file so no tag checking is necessary. - * Just send the data as we received it from the file. */ - len = (u16_t)LWIP_MIN(hs->left, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - - return data_to_send; -} - -#if LWIP_HTTPD_SSI -/** Sub-function of http_send(): This is the send-routine for ssi files - * - * @returns: - 1: data has been written (so call tcp_ouput) - * - 0: no data has been written (no need to call tcp_output) - */ -static u8_t -http_send_data_ssi(struct tcp_pcb *pcb, struct http_state *hs) -{ - err_t err = ERR_OK; - u16_t len; - u8_t data_to_send = 0; - - struct http_ssi_state *ssi = hs->ssi; - LWIP_ASSERT("ssi != NULL", ssi != NULL); - /* We are processing an SHTML file so need to scan for tags and replace - * them with insert strings. We need to be careful here since a tag may - * straddle the boundary of two blocks read from the file and we may also - * have to split the insert string between two tcp_write operations. */ - - /* How much data could we send? */ - len = tcp_sndbuf(pcb); - - /* Do we have remaining data to send before parsing more? */ - if(ssi->parsed > hs->file) { - len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - - /* If the send buffer is full, return now. */ - if(tcp_sndbuf(pcb) == 0) { - return data_to_send; - } - } - - LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left)); - - /* We have sent all the data that was already parsed so continue parsing - * the buffer contents looking for SSI tags. */ - while((ssi->parse_left) && (err == ERR_OK)) { - if (len == 0) { - return data_to_send; - } - switch(ssi->tag_state) { - case TAG_NONE: - /* We are not currently processing an SSI tag so scan for the - * start of the lead-in marker. */ - if(*ssi->parsed == g_pcTagLeadIn[0]) { - /* We found what could be the lead-in for a new tag so change - * state appropriately. */ - ssi->tag_state = TAG_LEADIN; - ssi->tag_index = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->tag_started = ssi->parsed; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - - case TAG_LEADIN: - /* We are processing the lead-in marker, looking for the start of - * the tag name. */ - - /* Have we reached the end of the leadin? */ - if(ssi->tag_index == LEN_TAG_LEAD_IN) { - ssi->tag_index = 0; - ssi->tag_state = TAG_FOUND; - } else { - /* Have we found the next character we expect for the tag leadin? */ - if(*ssi->parsed == g_pcTagLeadIn[ssi->tag_index]) { - /* Yes - move to the next one unless we have found the complete - * leadin, in which case we start looking for the tag itself */ - ssi->tag_index++; - } else { - /* We found an unexpected character so this is not a tag. Move - * back to idle state. */ - ssi->tag_state = TAG_NONE; - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - } - break; - - case TAG_FOUND: - /* We are reading the tag name, looking for the start of the - * lead-out marker and removing any whitespace found. */ - - /* Remove leading whitespace between the tag leading and the first - * tag name character. */ - if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || - (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || - (*ssi->parsed == '\r'))) { - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - } - - /* Have we found the end of the tag name? This is signalled by - * us finding the first leadout character or whitespace */ - if((*ssi->parsed == g_pcTagLeadOut[0]) || - (*ssi->parsed == ' ') || (*ssi->parsed == '\t') || - (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) { - - if(ssi->tag_index == 0) { - /* We read a zero length tag so ignore it. */ - ssi->tag_state = TAG_NONE; - } else { - /* We read a non-empty tag so go ahead and look for the - * leadout string. */ - ssi->tag_state = TAG_LEADOUT; - LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff); - ssi->tag_name_len = (u8_t)ssi->tag_index; - ssi->tag_name[ssi->tag_index] = '\0'; - if(*ssi->parsed == g_pcTagLeadOut[0]) { - ssi->tag_index = 1; - } else { - ssi->tag_index = 0; - } - } - } else { - /* This character is part of the tag name so save it */ - if(ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) { - ssi->tag_name[ssi->tag_index++] = *ssi->parsed; - } else { - /* The tag was too long so ignore it. */ - ssi->tag_state = TAG_NONE; - } - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - - break; - - /* We are looking for the end of the lead-out marker. */ - case TAG_LEADOUT: - /* Remove leading whitespace between the tag leading and the first - * tag leadout character. */ - if((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || - (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || - (*ssi->parsed == '\r'))) { - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - } - - /* Have we found the next character we expect for the tag leadout? */ - if(*ssi->parsed == g_pcTagLeadOut[ssi->tag_index]) { - /* Yes - move to the next one unless we have found the complete - * leadout, in which case we need to call the client to process - * the tag. */ - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - - if(ssi->tag_index == (LEN_TAG_LEAD_OUT - 1)) { - /* Call the client to ask for the insert string for the - * tag we just found. */ -#if LWIP_HTTPD_SSI_MULTIPART - ssi->tag_part = 0; /* start with tag part 0 */ -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - get_tag_insert(hs); - - /* Next time through, we are going to be sending data - * immediately, either the end of the block we start - * sending here or the insert string. */ - ssi->tag_index = 0; - ssi->tag_state = TAG_SENDING; - ssi->tag_end = ssi->parsed; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->parsed = ssi->tag_started; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - - /* If there is any unsent data in the buffer prior to the - * tag, we need to send it now. */ - if (ssi->tag_end > hs->file) { - /* How much of the data can we send? */ -#if LWIP_HTTPD_SSI_INCLUDE_TAG - len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); -#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - /* we would include the tag in sending */ - len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); -#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - if(ssi->tag_started <= hs->file) { - /* pretend to have sent the tag, too */ - len += ssi->tag_end - ssi->tag_started; - } -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - hs->file += len; - hs->left -= len; - } - } - } else { - ssi->tag_index++; - } - } else { - /* We found an unexpected character so this is not a tag. Move - * back to idle state. */ - ssi->parse_left--; - ssi->parsed++; - ssi->tag_state = TAG_NONE; - } - break; - - /* - * We have found a valid tag and are in the process of sending - * data as a result of that discovery. We send either remaining data - * from the file prior to the insert point or the insert string itself. - */ - case TAG_SENDING: - /* Do we have any remaining file data to send from the buffer prior - * to the tag? */ - if(ssi->tag_end > hs->file) { - /* How much of the data can we send? */ -#if LWIP_HTTPD_SSI_INCLUDE_TAG - len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); -#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file); - /* we would include the tag in sending */ - len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); -#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - if (len != 0) { - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - } else { - err = ERR_OK; - } - if (err == ERR_OK) { - data_to_send = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - if(ssi->tag_started <= hs->file) { - /* pretend to have sent the tag, too */ - len += ssi->tag_end - ssi->tag_started; - } -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - hs->file += len; - hs->left -= len; - } - } else { -#if LWIP_HTTPD_SSI_MULTIPART - if(ssi->tag_index >= ssi->tag_insert_len) { - /* Did the last SSIHandler have more to send? */ - if (ssi->tag_part != HTTPD_LAST_TAG_PART) { - /* If so, call it again */ - ssi->tag_index = 0; - get_tag_insert(hs); - } - } -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - - /* Do we still have insert data left to send? */ - if(ssi->tag_index < ssi->tag_insert_len) { - /* We are sending the insert string itself. How much of the - * insert can we send? */ - len = (ssi->tag_insert_len - ssi->tag_index); - - /* Note that we set the copy flag here since we only have a - * single tag insert buffer per connection. If we don't do - * this, insert corruption can occur if more than one insert - * is processed before we call tcp_output. */ - err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len, - HTTP_IS_TAG_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - ssi->tag_index += len; - /* Don't return here: keep on sending data */ - } - } else { -#if LWIP_HTTPD_SSI_MULTIPART - if (ssi->tag_part == HTTPD_LAST_TAG_PART) -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - { - /* We have sent all the insert data so go back to looking for - * a new tag. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n")); - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->parsed = ssi->tag_end; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - } - } - break; - default: - break; - } - } - } - - /* If we drop out of the end of the for loop, this implies we must have - * file data to send so send it now. In TAG_SENDING state, we've already - * handled this so skip the send if that's the case. */ - if((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) { - len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - } - return data_to_send; -} -#endif /* LWIP_HTTPD_SSI */ - -/** - * Try to send more data on this pcb. - * - * @param pcb the pcb to send data - * @param hs connection state - */ -static u8_t -http_send(struct tcp_pcb *pcb, struct http_state *hs) -{ - u8_t data_to_send = HTTP_NO_DATA_TO_SEND; - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void*)pcb, - (void*)hs, hs != NULL ? (int)hs->left : 0)); - -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->unrecved_bytes != 0) { - return 0; - } -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - - /* If we were passed a NULL state structure pointer, ignore the call. */ - if (hs == NULL) { - return 0; - } - -#if LWIP_HTTPD_FS_ASYNC_READ - /* Check if we are allowed to read from this file. - (e.g. SSI might want to delay sending until data is available) */ - if (!fs_is_file_ready(hs->handle, http_continue, hs)) { - return 0; - } -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Do we have any more header data to send for this file? */ - if (hs->hdr_index < NUM_FILE_HDR_STRINGS) { - data_to_send = http_send_headers(pcb, hs); - if ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) && - (hs->hdr_index < NUM_FILE_HDR_STRINGS)) { - return data_to_send; - } - } -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - - /* Have we run out of file data to send? If so, we need to read the next - * block from the file. */ - if (hs->left == 0) { - if (!http_check_eof(pcb, hs)) { - return 0; - } - } - -#if LWIP_HTTPD_SSI - if(hs->ssi) { - data_to_send = http_send_data_ssi(pcb, hs); - } else -#endif /* LWIP_HTTPD_SSI */ - { - data_to_send = http_send_data_nonssi(pcb, hs); - } - - if((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) { - /* We reached the end of the file so this request is done. - * This adds the FIN flag right into the last data segment. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n")); - return data_to_send; -} - -#if LWIP_HTTPD_SUPPORT_EXTSTATUS -/** Initialize a http connection with a file to send for an error message - * - * @param hs http connection state - * @param error_nr HTTP error number - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_find_error_file(struct http_state *hs, u16_t error_nr) -{ - const char *uri1, *uri2, *uri3; - err_t err; - - if (error_nr == 501) { - uri1 = "/501.html"; - uri2 = "/501.htm"; - uri3 = "/501.shtml"; - } else { - /* 400 (bad request is the default) */ - uri1 = "/400.html"; - uri2 = "/400.htm"; - uri3 = "/400.shtml"; - } - err = fs_open(&hs->file_handle, uri1); - if (err != ERR_OK) { - err = fs_open(&hs->file_handle, uri2); - if (err != ERR_OK) { - err = fs_open(&hs->file_handle, uri3); - if (err != ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n", - error_nr)); - return ERR_ARG; - } - } - } - return http_init_file(hs, &hs->file_handle, 0, NULL, 0, NULL); -} -#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ -#define http_find_error_file(hs, error_nr) ERR_ARG -#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ - -/** - * Get the file struct for a 404 error page. - * Tries some file names and returns NULL if none found. - * - * @param uri pointer that receives the actual file name URI - * @return file struct for the error page or NULL no matching file was found - */ -static struct fs_file * -http_get_404_file(struct http_state *hs, const char **uri) -{ - err_t err; - - *uri = "/404.html"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.html doesn't exist. Try 404.htm instead. */ - *uri = "/404.htm"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.htm doesn't exist either. Try 404.shtml instead. */ - *uri = "/404.shtml"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.htm doesn't exist either. Indicate to the caller that it should - * send back a default 404 page. - */ - *uri = NULL; - return NULL; - } - } - } - - return &hs->file_handle; -} - -#if LWIP_HTTPD_SUPPORT_POST -static err_t -http_handle_post_finished(struct http_state *hs) -{ -#if LWIP_HTTPD_POST_MANUAL_WND - /* Prevent multiple calls to httpd_post_finished, since it might have already - been called before from httpd_post_data_recved(). */ - if (hs->post_finished) { - return ERR_OK; - } - hs->post_finished = 1; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - /* application error or POST finished */ - /* NULL-terminate the buffer */ - http_uri_buf[0] = 0; - httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); - return http_find_file(hs, http_uri_buf, 0); -} - -/** Pass received POST body data to the application and correctly handle - * returning a response document or closing the connection. - * ATTENTION: The application is responsible for the pbuf now, so don't free it! - * - * @param hs http connection state - * @param p pbuf to pass to the application - * @return ERR_OK if passed successfully, another err_t if the response file - * hasn't been found (after POST finished) - */ -static err_t -http_post_rxpbuf(struct http_state *hs, struct pbuf *p) -{ - err_t err; - - if (p != NULL) { - /* adjust remaining Content-Length */ - if (hs->post_content_len_left < p->tot_len) { - hs->post_content_len_left = 0; - } else { - hs->post_content_len_left -= p->tot_len; - } - } -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - /* prevent connection being closed if httpd_post_data_recved() is called nested */ - hs->unrecved_bytes++; -#endif - err = httpd_post_receive_data(hs, p); -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - hs->unrecved_bytes--; -#endif - if (err != ERR_OK) { - /* Ignore remaining content in case of application error */ - hs->post_content_len_left = 0; - } - if (hs->post_content_len_left == 0) { -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->unrecved_bytes != 0) { - return ERR_OK; - } -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - /* application error or POST finished */ - return http_handle_post_finished(hs); - } - - return ERR_OK; -} - -/** Handle a post request. Called from http_parse_request when method 'POST' - * is found. - * - * @param p The input pbuf (containing the POST header and body). - * @param hs The http connection state. - * @param data HTTP request (header and part of body) from input pbuf(s). - * @param data_len Size of 'data'. - * @param uri The HTTP URI parsed from input pbuf(s). - * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP - * header starts). - * @return ERR_OK: POST correctly parsed and accepted by the application. - * ERR_INPROGRESS: POST not completely parsed (no error yet) - * another err_t: Error parsing POST or denied by the application - */ -static err_t -http_post_request(struct pbuf *inp, struct http_state *hs, - char *data, u16_t data_len, char *uri, char *uri_end) -{ - err_t err; - /* search for end-of-header (first double-CRLF) */ - char* crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); - - if (crlfcrlf != NULL) { - /* search for "Content-Length: " */ -#define HTTP_HDR_CONTENT_LEN "Content-Length: " -#define HTTP_HDR_CONTENT_LEN_LEN 16 -#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 - char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); - if (scontent_len != NULL) { - char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); - if (scontent_len_end != NULL) { - int content_len; - char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN; - content_len = atoi(content_len_num); - if (content_len == 0) { - /* if atoi returns 0 on error, fix this */ - if ((content_len_num[0] != '0') || (content_len_num[1] != '\r')) { - content_len = -1; - } - } - if (content_len >= 0) { - /* adjust length of HTTP header passed to application */ - const char *hdr_start_after_uri = uri_end + 1; - u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data); - u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri); - u8_t post_auto_wnd = 1; - http_uri_buf[0] = 0; - /* trim http header */ - *crlfcrlf = 0; - err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len, - http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd); - if (err == ERR_OK) { - /* try to pass in data of the first pbuf(s) */ - struct pbuf *q = inp; - u16_t start_offset = hdr_len; -#if LWIP_HTTPD_POST_MANUAL_WND - hs->no_auto_wnd = !post_auto_wnd; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - /* set the Content-Length to be received for this POST */ - hs->post_content_len_left = (u32_t)content_len; - - /* get to the pbuf where the body starts */ - while((q != NULL) && (q->len <= start_offset)) { - start_offset -= q->len; - q = q->next; - } - if (q != NULL) { - /* hide the remaining HTTP header */ - pbuf_header(q, -(s16_t)start_offset); -#if LWIP_HTTPD_POST_MANUAL_WND - if (!post_auto_wnd) { - /* already tcp_recved() this data... */ - hs->unrecved_bytes = q->tot_len; - } -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - pbuf_ref(q); - return http_post_rxpbuf(hs, q); - } else if (hs->post_content_len_left == 0) { - q = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); - return http_post_rxpbuf(hs, q); - } else { - return ERR_OK; - } - } else { - /* return file passed from application */ - return http_find_file(hs, http_uri_buf, 0); - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n", - content_len_num)); - return ERR_ARG; - } - } - } - /* If we come here, headers are fully received (double-crlf), but Content-Length - was not included. Since this is currently the only supported method, we have - to fail in this case! */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Error when parsing Content-Length\n")); - return ERR_ARG; - } - /* if we come here, the POST is incomplete */ -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - return ERR_INPROGRESS; -#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - return ERR_ARG; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -} - -#if LWIP_HTTPD_POST_MANUAL_WND -/** A POST implementation can call this function to update the TCP window. - * This can be used to throttle data reception (e.g. when received data is - * programmed to flash and data is received faster than programmed). - * - * @param connection A connection handle passed to httpd_post_begin for which - * httpd_post_finished has *NOT* been called yet! - * @param recved_len Length of data received (for window update) - */ -void httpd_post_data_recved(void *connection, u16_t recved_len) -{ - struct http_state *hs = (struct http_state*)connection; - if (hs != NULL) { - if (hs->no_auto_wnd) { - u16_t len = recved_len; - if (hs->unrecved_bytes >= recved_len) { - hs->unrecved_bytes -= recved_len; - } else { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n")); - len = (u16_t)hs->unrecved_bytes; - hs->unrecved_bytes = 0; - } - if (hs->pcb != NULL) { - if (len != 0) { - tcp_recved(hs->pcb, len); - } - if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) { - /* finished handling POST */ - http_handle_post_finished(hs); - http_send(hs->pcb, hs); - } - } - } - } -} -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - -#endif /* LWIP_HTTPD_SUPPORT_POST */ - -#if LWIP_HTTPD_FS_ASYNC_READ -/** Try to send more data if file has been blocked before - * This is a callback function passed to fs_read_async(). - */ -static void -http_continue(void *connection) -{ - struct http_state *hs = (struct http_state*)connection; - if (hs && (hs->pcb) && (hs->handle)) { - LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL); - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n")); - if (http_send(hs->pcb, hs)) { - /* If we wrote anything to be sent, go ahead and send it now. */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); - tcp_output(hs->pcb); - } - } -} -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -/** - * When data has been received in the correct state, try to parse it - * as a HTTP request. - * - * @param inp the received pbuf - * @param hs the connection state - * @param pcb the tcp_pcb which received this packet - * @return ERR_OK if request was OK and hs has been initialized correctly - * ERR_INPROGRESS if request was OK so far but not fully received - * another err_t otherwise - */ -static err_t -http_parse_request(struct pbuf *inp, struct http_state *hs, struct tcp_pcb *pcb) -{ - char *data; - char *crlf; - u16_t data_len; - struct pbuf *p = inp; -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - u16_t clen; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -#if LWIP_HTTPD_SUPPORT_POST - err_t err; -#endif /* LWIP_HTTPD_SUPPORT_POST */ - - LWIP_UNUSED_ARG(pcb); /* only used for post */ - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("hs != NULL", hs != NULL); - - if ((hs->handle != NULL) || (hs->file != NULL)) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n")); - /* already sending a file */ - /* @todo: abort? */ - return ERR_USE; - } - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - - LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len)); - - /* first check allowed characters in this pbuf? */ - - /* enqueue the pbuf */ - if (hs->req == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n")); - hs->req = p; - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n")); - pbuf_cat(hs->req, p); - } - /* increase pbuf ref counter as it is freed when we return but we want to - keep it on the req list */ - pbuf_ref(p); - - if (hs->req->next != NULL) { - data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH); - pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0); - data = httpd_req_buf; - } else -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - { - data = (char *)p->payload; - data_len = p->len; - if (p->len != p->tot_len) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n")); - } - } - - /* received enough data for minimal request? */ - if (data_len >= MIN_REQ_LEN) { - /* wait for CRLF before parsing anything */ - crlf = lwip_strnstr(data, CRLF, data_len); - if (crlf != NULL) { -#if LWIP_HTTPD_SUPPORT_POST - int is_post = 0; -#endif /* LWIP_HTTPD_SUPPORT_POST */ - int is_09 = 0; - char *sp1, *sp2; - u16_t left_len, uri_len; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n")); - /* parse method */ - if (!strncmp(data, "GET ", 4)) { - sp1 = data + 3; - /* received GET request */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n")); -#if LWIP_HTTPD_SUPPORT_POST - } else if (!strncmp(data, "POST ", 5)) { - /* store request type */ - is_post = 1; - sp1 = data + 4; - /* received GET request */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n")); -#endif /* LWIP_HTTPD_SUPPORT_POST */ - } else { - /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ - data[4] = 0; - /* unsupported method! */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n", - data)); - return http_find_error_file(hs, 501); - } - /* if we come here, method is OK, parse URI */ - left_len = (u16_t)(data_len - ((sp1 +1) - data)); - sp2 = lwip_strnstr(sp1 + 1, " ", left_len); -#if LWIP_HTTPD_SUPPORT_V09 - if (sp2 == NULL) { - /* HTTP 0.9: respond with correct protocol version */ - sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len); - is_09 = 1; -#if LWIP_HTTPD_SUPPORT_POST - if (is_post) { - /* HTTP/0.9 does not support POST */ - goto badrequest; - } -#endif /* LWIP_HTTPD_SUPPORT_POST */ - } -#endif /* LWIP_HTTPD_SUPPORT_V09 */ - uri_len = (u16_t)(sp2 - (sp1 + 1)); - if ((sp2 != 0) && (sp2 > sp1)) { - /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */ - if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) { - char *uri = sp1 + 1; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - /* This is HTTP/1.0 compatible: for strict 1.1, a connection - would always be persistent unless "close" was specified. */ - if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || - lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { - hs->keepalive = 1; - } else { - hs->keepalive = 0; - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ - *sp1 = 0; - uri[uri_len] = 0; - LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n", - data, uri)); -#if LWIP_HTTPD_SUPPORT_POST - if (is_post) { -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - struct pbuf *q = hs->req; -#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - struct pbuf *q = inp; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - err = http_post_request(q, hs, data, data_len, uri, sp2); - if (err != ERR_OK) { - /* restore header for next try */ - *sp1 = ' '; - *sp2 = ' '; - uri[uri_len] = ' '; - } - if (err == ERR_ARG) { - goto badrequest; - } - return err; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - return http_find_file(hs, uri, is_09); - } - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n")); - } - } - } - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - clen = pbuf_clen(hs->req); - if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) && - (clen <= LWIP_HTTPD_REQ_QUEUELEN)) { - /* request not fully received (too short or CRLF is missing) */ - return ERR_INPROGRESS; - } else -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - { -#if LWIP_HTTPD_SUPPORT_POST -badrequest: -#endif /* LWIP_HTTPD_SUPPORT_POST */ - LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n")); - /* could not parse request */ - return http_find_error_file(hs, 400); - } -} - -/** Try to find the file specified by uri and, if found, initialize hs - * accordingly. - * - * @param hs the connection state - * @param uri the HTTP header URI - * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_find_file(struct http_state *hs, const char *uri, int is_09) -{ - size_t loop; - struct fs_file *file = NULL; - char *params = NULL; - err_t err; -#if LWIP_HTTPD_CGI - int i; -#endif /* LWIP_HTTPD_CGI */ -#if !LWIP_HTTPD_SSI - const -#endif /* !LWIP_HTTPD_SSI */ - /* By default, assume we will not be processing server-side-includes tags */ - u8_t tag_check = 0; - - /* Have we been asked for the default file (in root or a directory) ? */ -#if LWIP_HTTPD_MAX_REQUEST_URI_LEN - size_t uri_len = strlen(uri); - if ((uri_len > 0) && (uri[uri_len-1] == '/') && - ((uri != http_uri_buf) || (uri_len == 1))) { - size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len - 1); - if (copy_len > 0) { - MEMCPY(http_uri_buf, uri, copy_len); - http_uri_buf[copy_len] = 0; - } -#else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - if ((uri[0] == '/') && (uri[1] == 0)) { -#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - /* Try each of the configured default filenames until we find one - that exists. */ - for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) { - const char* file_name; -#if LWIP_HTTPD_MAX_REQUEST_URI_LEN - if (copy_len > 0) { - size_t len_left = sizeof(http_uri_buf) - copy_len - 1; - if (len_left > 0) { - size_t name_len = strlen(g_psDefaultFilenames[loop].name); - size_t name_copy_len = LWIP_MIN(len_left, name_len); - MEMCPY(&http_uri_buf[copy_len], g_psDefaultFilenames[loop].name, name_copy_len); - } - file_name = http_uri_buf; - } else -#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - { - file_name = g_psDefaultFilenames[loop].name; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name)); - err = fs_open(&hs->file_handle, file_name); - if(err == ERR_OK) { - uri = file_name; - file = &hs->file_handle; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n")); -#if LWIP_HTTPD_SSI - tag_check = g_psDefaultFilenames[loop].shtml; -#endif /* LWIP_HTTPD_SSI */ - break; - } - } - } - if (file == NULL) { - /* No - we've been asked for a specific file. */ - /* First, isolate the base URI (without any parameters) */ - params = (char *)strchr(uri, '?'); - if (params != NULL) { - /* URI contains parameters. NULL-terminate the base URI */ - *params = '\0'; - params++; - } - -#if LWIP_HTTPD_CGI - http_cgi_paramcount = -1; - /* Does the base URI we have isolated correspond to a CGI handler? */ - if (g_iNumCGIs && g_pCGIs) { - for (i = 0; i < g_iNumCGIs; i++) { - if (strcmp(uri, g_pCGIs[i].pcCGIName) == 0) { - /* - * We found a CGI that handles this URI so extract the - * parameters and call the handler. - */ - http_cgi_paramcount = extract_uri_parameters(hs, params); - uri = g_pCGIs[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params, - hs->param_vals); - break; - } - } - } -#endif /* LWIP_HTTPD_CGI */ - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri)); - - err = fs_open(&hs->file_handle, uri); - if (err == ERR_OK) { - file = &hs->file_handle; - } else { - file = http_get_404_file(hs, &uri); - } -#if LWIP_HTTPD_SSI - if (file != NULL) { - /* See if we have been asked for an shtml file and, if so, - enable tag checking. */ - const char* ext = NULL, *sub; - char* param = (char*)strstr(uri, "?"); - if (param != NULL) { - /* separate uri from parameters for now, set back later */ - *param = 0; - } - sub = uri; - ext = uri; - for (sub = strstr(sub, "."); sub != NULL; sub = strstr(sub, ".")) - { - ext = sub; - sub++; - } - tag_check = 0; - for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) { - tag_check = 1; - break; - } - } - if (param != NULL) { - *param = '?'; - } - } -#endif /* LWIP_HTTPD_SSI */ - } - if (file == NULL) { - /* None of the default filenames exist so send back a 404 page */ - file = http_get_404_file(hs, &uri); - } - return http_init_file(hs, file, is_09, uri, tag_check, params); -} - -/** Initialize a http connection with a file to send (if found). - * Called by http_find_file and http_find_error_file. - * - * @param hs http connection state - * @param file file structure to send (or NULL if not found) - * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) - * @param uri the HTTP header URI - * @param tag_check enable SSI tag checking - * @param params != NULL if URI has parameters (separated by '?') - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, - u8_t tag_check, char* params) -{ - if (file != NULL) { - /* file opened, initialise struct http_state */ -#if LWIP_HTTPD_SSI - if (tag_check) { - struct http_ssi_state *ssi = http_ssi_state_alloc(); - if (ssi != NULL) { - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; - ssi->parsed = file->data; - ssi->parse_left = file->len; - ssi->tag_end = file->data; - hs->ssi = ssi; - } - } -#else /* LWIP_HTTPD_SSI */ - LWIP_UNUSED_ARG(tag_check); -#endif /* LWIP_HTTPD_SSI */ - hs->handle = file; - hs->file = file->data; - LWIP_ASSERT("File length must be positive!", (file->len >= 0)); -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file && (file->data == NULL)) { - /* custom file, need to read data first (via fs_read_custom) */ - hs->left = 0; - } else -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - { - hs->left = file->len; - } - hs->retries = 0; -#if LWIP_HTTPD_TIMING - hs->time_started = sys_now(); -#endif /* LWIP_HTTPD_TIMING */ -#if !LWIP_HTTPD_DYNAMIC_HEADERS - LWIP_ASSERT("HTTP headers not included in file system", - (hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0); -#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_SUPPORT_V09 - if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) { - /* HTTP/0.9 responses are sent without HTTP header, - search for the end of the header. */ - char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left); - if (file_start != NULL) { - size_t diff = file_start + 4 - hs->file; - hs->file += diff; - hs->left -= (u32_t)diff; - } - } -#endif /* LWIP_HTTPD_SUPPORT_V09*/ -#if LWIP_HTTPD_CGI_SSI - if (params != NULL) { - /* URI contains parameters, call generic CGI handler */ - int count; -#if LWIP_HTTPD_CGI - if (http_cgi_paramcount >= 0) { - count = http_cgi_paramcount; - } else -#endif - { - count = extract_uri_parameters(hs, params); - } - httpd_cgi_handler(uri, count, http_cgi_params, http_cgi_param_vals -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , hs->handle->state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); - } -#else /* LWIP_HTTPD_CGI_SSI */ - LWIP_UNUSED_ARG(params); -#endif /* LWIP_HTTPD_CGI_SSI */ - } else { - hs->handle = NULL; - hs->file = NULL; - hs->left = 0; - hs->retries = 0; - } -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Determine the HTTP headers to send based on the file extension of - * the requested URI. */ - if ((hs->handle == NULL) || ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) == 0)) { - get_http_headers(hs, uri); - } -#else /* LWIP_HTTPD_DYNAMIC_HEADERS */ - LWIP_UNUSED_ARG(uri); -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { -#if LWIP_HTTPD_SSI - if (hs->ssi != NULL) { - hs->keepalive = 0; - } else -#endif /* LWIP_HTTPD_SSI */ - { - if ((hs->handle != NULL) && - ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED|FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { - hs->keepalive = 0; - } - } - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - return ERR_OK; -} - -/** - * The pcb had an error and is already deallocated. - * The argument might still be valid (if != NULL). - */ -static void -http_err(void *arg, err_t err) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_UNUSED_ARG(err); - - LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err))); - - if (hs != NULL) { - http_state_free(hs); - } -} - -/** - * Data has been sent and acknowledged by the remote host. - * This means that more data can be sent. - */ -static err_t -http_sent(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct http_state *hs = (struct http_state *)arg; - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void*)pcb)); - - LWIP_UNUSED_ARG(len); - - if (hs == NULL) { - return ERR_OK; - } - - hs->retries = 0; - - http_send(pcb, hs); - - return ERR_OK; -} - -/** - * The poll function is called every 2nd second. - * If there has been no data sent (which resets the retries) in 8 seconds, close. - * If the last portion of a file has not been sent in 2 seconds, close. - * - * This could be increased, but we don't want to waste resources for bad connections. - */ -static err_t -http_poll(void *arg, struct tcp_pcb *pcb) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n", - (void*)pcb, (void*)hs, tcp_debug_state_str(pcb->state))); - - if (hs == NULL) { - err_t closed; - /* arg is null, close. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n")); - closed = http_close_conn(pcb, NULL); - LWIP_UNUSED_ARG(closed); -#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR - if (closed == ERR_MEM) { - tcp_abort(pcb); - return ERR_ABRT; - } -#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */ - return ERR_OK; - } else { - hs->retries++; - if (hs->retries == HTTPD_MAX_RETRIES) { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n")); - http_close_conn(pcb, hs); - return ERR_OK; - } - - /* If this connection has a file open, try to send some more data. If - * it has not yet received a GET request, don't do this since it will - * cause the connection to close immediately. */ - if(hs && (hs->handle)) { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n")); - if(http_send(pcb, hs)) { - /* If we wrote anything to be sent, go ahead and send it now. */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); - tcp_output(pcb); - } - } - } - - return ERR_OK; -} - -/** - * Data has been received on this pcb. - * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). - */ -static err_t -http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void*)pcb, - (void*)p, lwip_strerr(err))); - - if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) { - /* error or closed by other side? */ - if (p != NULL) { - /* Inform TCP that we have taken the data. */ - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - if (hs == NULL) { - /* this should not happen, only to be robust */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n")); - } - http_close_conn(pcb, hs); - return ERR_OK; - } - -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->no_auto_wnd) { - hs->unrecved_bytes += p->tot_len; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - { - /* Inform TCP that we have taken the data. */ - tcp_recved(pcb, p->tot_len); - } - -#if LWIP_HTTPD_SUPPORT_POST - if (hs->post_content_len_left > 0) { - /* reset idle counter when POST data is received */ - hs->retries = 0; - /* this is data for a POST, pass the complete pbuf to the application */ - http_post_rxpbuf(hs, p); - /* pbuf is passed to the application, don't free it! */ - if (hs->post_content_len_left == 0) { - /* all data received, send response or close connection */ - http_send(pcb, hs); - } - return ERR_OK; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - if (hs->handle == NULL) { - err_t parsed = http_parse_request(p, hs, pcb); - LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK - || parsed == ERR_INPROGRESS ||parsed == ERR_ARG || parsed == ERR_USE); -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - if (parsed != ERR_INPROGRESS) { - /* request fully parsed or error */ - if (hs->req != NULL) { - pbuf_free(hs->req); - hs->req = NULL; - } - } -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - pbuf_free(p); - if (parsed == ERR_OK) { -#if LWIP_HTTPD_SUPPORT_POST - if (hs->post_content_len_left == 0) -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", (const void*)hs->file, hs->left)); - http_send(pcb, hs); - } - } else if (parsed == ERR_ARG) { - /* @todo: close on ERR_USE? */ - http_close_conn(pcb, hs); - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); - /* already sending but still receiving data, we might want to RST here? */ - pbuf_free(p); - } - } - return ERR_OK; -} - -/** - * A new incoming connection has been accepted. - */ -static err_t -http_accept(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct http_state *hs; - LWIP_UNUSED_ARG(err); - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void*)pcb, arg)); - - if ((err != ERR_OK) || (pcb == NULL)) { - return ERR_VAL; - } - - /* Set priority */ - tcp_setprio(pcb, HTTPD_TCP_PRIO); - - /* Allocate memory for the structure that holds the state of the - connection - initialized by that function. */ - hs = http_state_alloc(); - if (hs == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n")); - return ERR_MEM; - } - hs->pcb = pcb; - - /* Tell TCP that this is the structure we wish to be passed for our - callbacks. */ - tcp_arg(pcb, hs); - - /* Set up the various callback functions */ - tcp_recv(pcb, http_recv); - tcp_err(pcb, http_err); - tcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); - tcp_sent(pcb, http_sent); - - return ERR_OK; -} - -/** - * @ingroup httpd - * Initialize the httpd: set up a listening PCB and bind it to the defined port - */ -void -httpd_init(void) -{ - struct tcp_pcb *pcb; - err_t err; - -#if HTTPD_USE_MEM_POOL - LWIP_MEMPOOL_INIT(HTTPD_STATE); -#if LWIP_HTTPD_SSI - LWIP_MEMPOOL_INIT(HTTPD_SSI_STATE); -#endif -#endif - LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n")); - - pcb = tcp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL); - tcp_setprio(pcb, HTTPD_TCP_PRIO); - /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */ - err = tcp_bind(pcb, IP_ANY_TYPE, HTTPD_SERVER_PORT); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK); - pcb = tcp_listen(pcb); - LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL); - tcp_accept(pcb, http_accept); -} - -#if LWIP_HTTPD_SSI -/** - * Set the SSI handler function. - * - * @param ssi_handler the SSI handler function - * @param tags an array of SSI tag strings to search for in SSI-enabled files - * @param num_tags number of tags in the 'tags' array - */ -void -http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags) -{ - LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n")); - - LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL); - g_pfnSSIHandler = ssi_handler; - -#if LWIP_HTTPD_SSI_RAW - LWIP_UNUSED_ARG(tags); - LWIP_UNUSED_ARG(num_tags); -#else /* LWIP_HTTPD_SSI_RAW */ - LWIP_ASSERT("no tags given", tags != NULL); - LWIP_ASSERT("invalid number of tags", num_tags > 0); - - g_ppcTags = tags; - g_iNumTags = num_tags; -#endif /* !LWIP_HTTPD_SSI_RAW */ -} -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_CGI -/** - * Set an array of CGI filenames/handler functions - * - * @param cgis an array of CGI filenames/handler functions - * @param num_handlers number of elements in the 'cgis' array - */ -void -http_set_cgi_handlers(const tCGI *cgis, int num_handlers) -{ - LWIP_ASSERT("no cgis given", cgis != NULL); - LWIP_ASSERT("invalid number of handlers", num_handlers > 0); - - g_pCGIs = cgis; - g_iNumCGIs = num_handlers; -} -#endif /* LWIP_HTTPD_CGI */ - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/components/net/lwip-2.0.2/src/apps/httpd/httpd_structs.h b/components/net/lwip-2.0.2/src/apps/httpd/httpd_structs.h deleted file mode 100644 index fbd135a8c6..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/httpd_structs.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef LWIP_HTTPD_STRUCTS_H -#define LWIP_HTTPD_STRUCTS_H - -#include "lwip/apps/httpd.h" - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/** This struct is used for a list of HTTP header strings for various - * filename extensions. */ -typedef struct -{ - const char *extension; - const char *content_type; -} tHTTPHeader; - -/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and - * RFC 2616 HTTP/1.1 for header field definitions) */ -static const char * const g_psHTTPHeaderStrings[] = -{ - "HTTP/1.0 200 OK\r\n", - "HTTP/1.0 404 File not found\r\n", - "HTTP/1.0 400 Bad Request\r\n", - "HTTP/1.0 501 Not Implemented\r\n", - "HTTP/1.1 200 OK\r\n", - "HTTP/1.1 404 File not found\r\n", - "HTTP/1.1 400 Bad Request\r\n", - "HTTP/1.1 501 Not Implemented\r\n", - "Content-Length: ", - "Connection: Close\r\n", - "Connection: keep-alive\r\n", - "Connection: keep-alive\r\nContent-Length: ", - "Server: "HTTPD_SERVER_AGENT"\r\n", - "\r\n

404: The requested file cannot be found.

\r\n" -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - ,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n

404: The requested file cannot be found.

\r\n" -#endif -}; - -/* Indexes into the g_psHTTPHeaderStrings array */ -#define HTTP_HDR_OK 0 /* 200 OK */ -#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */ -#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */ -#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */ -#define HTTP_HDR_OK_11 4 /* 200 OK */ -#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */ -#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */ -#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */ -#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/ -#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */ -#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */ -#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/ -#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */ -#define DEFAULT_404_HTML 13 /* default 404 body */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE -#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */ -#endif - - -#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n" -#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n" -#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n" -#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n" -#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n" -#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n" -#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n" -#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n" -#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n" -#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n" -#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n" -#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n" -#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n" -#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n" -#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n" - -#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n" - -/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES - * and http://www.iana.org/assignments/media-types for registered content types - * and subtypes) */ -static const tHTTPHeader g_psHTTPHeaders[] = -{ - { "html", HTTP_HDR_HTML}, - { "htm", HTTP_HDR_HTML}, - { "shtml",HTTP_HDR_SSI}, - { "shtm", HTTP_HDR_SSI}, - { "ssi", HTTP_HDR_SSI}, - { "gif", HTTP_HDR_GIF}, - { "png", HTTP_HDR_PNG}, - { "jpg", HTTP_HDR_JPG}, - { "bmp", HTTP_HDR_BMP}, - { "ico", HTTP_HDR_ICO}, - { "class",HTTP_HDR_APP}, - { "cls", HTTP_HDR_APP}, - { "js", HTTP_HDR_JS}, - { "ram", HTTP_HDR_RA}, - { "css", HTTP_HDR_CSS}, - { "swf", HTTP_HDR_SWF}, - { "xml", HTTP_HDR_XML}, - { "xsl", HTTP_HDR_XML}, - { "pdf", HTTP_HDR_PDF}, - { "json", HTTP_HDR_JSON} -}; - -#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader)) - -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -#if LWIP_HTTPD_SSI -static const char * const g_pcSSIExtensions[] = { - ".shtml", ".shtm", ".ssi", ".xml" -}; -#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *)) -#endif /* LWIP_HTTPD_SSI */ - -#endif /* LWIP_HTTPD_STRUCTS_H */ diff --git a/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata b/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata deleted file mode 100644 index 37b4203e6e..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/perl - -open(OUTPUT, "> fsdata.c"); - -chdir("fs"); -open(FILES, "find . -type f |"); - -while($file = ) { - - # Do not include files in CVS directories nor backup files. - if($file =~ /(CVS|~)/) { - next; - } - - chop($file); - - open(HEADER, "> /tmp/header") || die $!; - if($file =~ /404/) { - print(HEADER "HTTP/1.0 404 File not found\r\n"); - } else { - print(HEADER "HTTP/1.0 200 OK\r\n"); - } - print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"); - if($file =~ /\.html$/) { - print(HEADER "Content-type: text/html\r\n"); - } elsif($file =~ /\.gif$/) { - print(HEADER "Content-type: image/gif\r\n"); - } elsif($file =~ /\.png$/) { - print(HEADER "Content-type: image/png\r\n"); - } elsif($file =~ /\.jpg$/) { - print(HEADER "Content-type: image/jpeg\r\n"); - } elsif($file =~ /\.class$/) { - print(HEADER "Content-type: application/octet-stream\r\n"); - } elsif($file =~ /\.ram$/) { - print(HEADER "Content-type: audio/x-pn-realaudio\r\n"); - } else { - print(HEADER "Content-type: text/plain\r\n"); - } - print(HEADER "\r\n"); - close(HEADER); - - unless($file =~ /\.plain$/ || $file =~ /cgi/) { - system("cat /tmp/header $file > /tmp/file"); - } else { - system("cp $file /tmp/file"); - } - - open(FILE, "/tmp/file"); - unlink("/tmp/file"); - unlink("/tmp/header"); - - $file =~ s/\.//; - $fvar = $file; - $fvar =~ s-/-_-g; - $fvar =~ s-\.-_-g; - print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); - print(OUTPUT "\t/* $file */\n\t"); - for($j = 0; $j < length($file); $j++) { - printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); - } - printf(OUTPUT "0,\n"); - - - $i = 0; - while(read(FILE, $data, 1)) { - if($i == 0) { - print(OUTPUT "\t"); - } - printf(OUTPUT "%#02x, ", unpack("C", $data)); - $i++; - if($i == 10) { - print(OUTPUT "\n"); - $i = 0; - } - } - print(OUTPUT "};\n\n"); - close(FILE); - push(@fvars, $fvar); - push(@files, $file); -} - -for($i = 0; $i < @fvars; $i++) { - $file = $files[$i]; - $fvar = $fvars[$i]; - - if($i == 0) { - $prevfile = "NULL"; - } else { - $prevfile = "file" . $fvars[$i - 1]; - } - print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); - print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); - print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); -} - -print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n"); -print(OUTPUT "#define FS_NUMFILES $i\n"); diff --git a/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata.c b/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata.c deleted file mode 100644 index 934e721948..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/makefsdata.c +++ /dev/null @@ -1,1033 +0,0 @@ -/** - * makefsdata: Converts a directory structure for use with the lwIP httpd. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jim Pettinato - * Simon Goldschmidt - * - * @todo: - * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and - * PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments - */ - -#include -#include -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include "windows.h" -#else -#include -#endif -#include -#include -#include -#include - -/** Makefsdata can generate *all* files deflate-compressed (where file size shrinks). - * Since nearly all browsers support this, this is a good way to reduce ROM size. - * To compress the files, "miniz.c" must be downloaded seperately. - */ -#ifndef MAKEFS_SUPPORT_DEFLATE -#define MAKEFS_SUPPORT_DEFLATE 0 -#endif - -#define COPY_BUFSIZE (1024*1024) /* 1 MByte */ - -#if MAKEFS_SUPPORT_DEFLATE -#include "../miniz.c" - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint; - -#define my_max(a,b) (((a) > (b)) ? (a) : (b)) -#define my_min(a,b) (((a) < (b)) ? (a) : (b)) - -/* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression. - COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */ -#define COMP_OUT_BUF_SIZE COPY_BUFSIZE - -/* OUT_BUF_SIZE is the size of the output buffer used during decompression. - OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */ -#define OUT_BUF_SIZE COPY_BUFSIZE -static uint8 s_outbuf[OUT_BUF_SIZE]; -static uint8 s_checkbuf[OUT_BUF_SIZE]; - -/* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k). - This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */ -tdefl_compressor g_deflator; -tinfl_decompressor g_inflator; - -int deflate_level = 10; /* default compression level, can be changed via command line */ -#define USAGE_ARG_DEFLATE " [-defl<:compr_level>]" -#else /* MAKEFS_SUPPORT_DEFLATE */ -#define USAGE_ARG_DEFLATE "" -#endif /* MAKEFS_SUPPORT_DEFLATE */ - -/* Compatibility defines Win32 vs. DOS */ -#ifdef WIN32 - -#define FIND_T WIN32_FIND_DATAA -#define FIND_T_FILENAME(fInfo) (fInfo.cFileName) -#define FIND_T_IS_DIR(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) -#define FIND_T_IS_FILE(fInfo) ((fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) -#define FIND_RET_T HANDLE -#define FINDFIRST_FILE(path, result) FindFirstFileA(path, result) -#define FINDFIRST_DIR(path, result) FindFirstFileA(path, result) -#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) -#define FINDFIRST_SUCCEEDED(ret) (ret != INVALID_HANDLE_VALUE) -#define FINDNEXT_SUCCEEDED(ret) (ret == TRUE) - -#define GETCWD(path, len) GetCurrentDirectoryA(len, path) -#define CHDIR(path) SetCurrentDirectoryA(path) -#define CHDIR_SUCCEEDED(ret) (ret == TRUE) - -#else - -#define FIND_T struct ffblk -#define FIND_T_FILENAME(fInfo) (fInfo.ff_name) -#define FIND_T_IS_DIR(fInfo) ((fInfo.ff_attrib & FA_DIREC) == FA_DIREC) -#define FIND_T_IS_FILE(fInfo) (1) -#define FIND_RET_T int -#define FINDFIRST_FILE(path, result) findfirst(path, result, FA_ARCH) -#define FINDFIRST_DIR(path, result) findfirst(path, result, FA_DIREC) -#define FINDNEXT(ff_res, result) FindNextFileA(ff_res, result) -#define FINDFIRST_SUCCEEDED(ret) (ret == 0) -#define FINDNEXT_SUCCEEDED(ret) (ret == 0) - -#define GETCWD(path, len) getcwd(path, len) -#define CHDIR(path) chdir(path) -#define CHDIR_SUCCEEDED(ret) (ret == 0) - -#endif - -#define NEWLINE "\r\n" -#define NEWLINE_LEN 2 - -/* define this to get the header variables we use to build HTTP headers */ -#define LWIP_HTTPD_DYNAMIC_HEADERS 1 -#define LWIP_HTTPD_SSI 1 -#include "lwip/init.h" -#include "../httpd_structs.h" -#include "lwip/apps/fs.h" - -#include "../core/inet_chksum.c" -#include "../core/def.c" - -/** (Your server name here) */ -const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n"; -char serverIDBuffer[1024]; - -/* change this to suit your MEM_ALIGNMENT */ -#define PAYLOAD_ALIGNMENT 4 -/* set this to 0 to prevent aligning payload */ -#define ALIGN_PAYLOAD 1 -/* define this to a type that has the required alignment */ -#define PAYLOAD_ALIGN_TYPE "unsigned int" -static int payload_alingment_dummy_counter = 0; - -#define HEX_BYTES_PER_LINE 16 - -#define MAX_PATH_LEN 256 - -struct file_entry -{ - struct file_entry* next; - const char* filename_c; -}; - -int process_sub(FILE *data_file, FILE *struct_file); -int process_file(FILE *data_file, FILE *struct_file, const char *filename); -int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, - u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed); -int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i); -int s_put_ascii(char *buf, const char *ascii_string, int len, int *i); -void concat_files(const char *file1, const char *file2, const char *targetfile); -int check_path(char* path, size_t size); - -/* 5 bytes per char + 3 bytes per line */ -static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)]; - -char curSubdir[MAX_PATH_LEN]; -char lastFileVar[MAX_PATH_LEN]; -char hdr_buf[4096]; - -unsigned char processSubs = 1; -unsigned char includeHttpHeader = 1; -unsigned char useHttp11 = 0; -unsigned char supportSsi = 1; -unsigned char precalcChksum = 0; -unsigned char includeLastModified = 0; -#if MAKEFS_SUPPORT_DEFLATE -unsigned char deflateNonSsiFiles = 0; -size_t deflatedBytesReduced = 0; -size_t overallDataBytes = 0; -#endif - -struct file_entry* first_file = NULL; -struct file_entry* last_file = NULL; - -static void print_usage(void) -{ - printf(" Usage: htmlgen [targetdir] [-s] [-e] [-i] [-11] [-nossi] [-c] [-f:] [-m] [-svr:]" USAGE_ARG_DEFLATE NEWLINE NEWLINE); - printf(" targetdir: relative or absolute path to files to convert" NEWLINE); - printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE); - printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE); - printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE); - printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE); - printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE); - printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE); - printf(" switch -m: include \"Last-Modified\" header based on file time" NEWLINE); - printf(" switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE); -#if MAKEFS_SUPPORT_DEFLATE - printf(" switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE); - printf(" ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE); -#endif - printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE); - printf(" process files in subdirectory 'fs'" NEWLINE); -} - -int main(int argc, char *argv[]) -{ - char path[MAX_PATH_LEN]; - char appPath[MAX_PATH_LEN]; - FILE *data_file; - FILE *struct_file; - int filesProcessed; - int i; - char targetfile[MAX_PATH_LEN]; - strcpy(targetfile, "fsdata.c"); - - memset(path, 0, sizeof(path)); - memset(appPath, 0, sizeof(appPath)); - - printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE); - printf(" by Jim Pettinato - circa 2003 " NEWLINE); - printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE); - - strcpy(path, "fs"); - for (i = 1; i < argc; i++) { - if (argv[i] == NULL) { - continue; - } - if (argv[i][0] == '-') { - if (strstr(argv[i], "-svr:") == argv[i]) { - snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]); - serverID = serverIDBuffer; - printf("Using Server-ID: \"%s\"\n", serverID); - } else if (strstr(argv[i], "-s") == argv[i]) { - processSubs = 0; - } else if (strstr(argv[i], "-e") == argv[i]) { - includeHttpHeader = 0; - } else if (strstr(argv[i], "-11") == argv[i]) { - useHttp11 = 1; - } else if (strstr(argv[i], "-nossi") == argv[i]) { - supportSsi = 0; - } else if (strstr(argv[i], "-c") == argv[i]) { - precalcChksum = 1; - } else if (strstr(argv[i], "-f:") == argv[i]) { - strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1); - targetfile[sizeof(targetfile) - 1] = 0; - printf("Writing to file \"%s\"\n", targetfile); - } else if (strstr(argv[i], "-m") == argv[i]) { - includeLastModified = 1; - } else if (strstr(argv[i], "-defl") == argv[i]) { -#if MAKEFS_SUPPORT_DEFLATE - char* colon = strstr(argv[i], ":"); - if (colon) { - if (colon[1] != 0) { - int defl_level = atoi(&colon[1]); - if ((defl_level >= 0) && (defl_level <= 10)) { - deflate_level = defl_level; - } else { - printf("ERROR: deflate level must be [0..10]" NEWLINE); - exit(0); - } - } - } - deflateNonSsiFiles = 1; - printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level); -#else - printf("WARNING: Deflate support is disabled\n"); -#endif - } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) { - print_usage(); - exit(0); - } - } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) { - print_usage(); - exit(0); - } else { - strncpy(path, argv[i], sizeof(path)-1); - path[sizeof(path)-1] = 0; - } - } - - if (!check_path(path, sizeof(path))) { - printf("Invalid path: \"%s\"." NEWLINE, path); - exit(-1); - } - - GETCWD(appPath, MAX_PATH_LEN); - /* if command line param or subdir named 'fs' not found spout usage verbiage */ - if (!CHDIR_SUCCEEDED(CHDIR(path))) { - /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */ - printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path); - print_usage(); - exit(-1); - } - CHDIR(appPath); - - printf("HTTP %sheader will %s statically included." NEWLINE, - (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""), - (includeHttpHeader ? "be" : "not be")); - - sprintf(curSubdir, ""); /* start off in web page's root directory - relative paths */ - printf(" Processing all files in directory %s", path); - if (processSubs) { - printf(" and subdirectories..." NEWLINE NEWLINE); - } else { - printf("..." NEWLINE NEWLINE); - } - - data_file = fopen("fsdata.tmp", "wb"); - if (data_file == NULL) { - printf("Failed to create file \"fsdata.tmp\"\n"); - exit(-1); - } - struct_file = fopen("fshdr.tmp", "wb"); - if (struct_file == NULL) { - printf("Failed to create file \"fshdr.tmp\"\n"); - fclose(data_file); - exit(-1); - } - - CHDIR(path); - - fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE); - fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE); - fprintf(data_file, "#include \"fsdata.h\"" NEWLINE NEWLINE NEWLINE); - - fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE); - /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */ - fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE); - /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */ - fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE); - - /* define alignment defines */ -#if ALIGN_PAYLOAD - fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE); -#endif - fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE" NEWLINE "#define FSDATA_ALIGN_PRE" NEWLINE "#endif" NEWLINE); - fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE); -#if ALIGN_PAYLOAD - fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE); -#endif - - sprintf(lastFileVar, "NULL"); - - filesProcessed = process_sub(data_file, struct_file); - - /* data_file now contains all of the raw data.. now append linked list of - * file header structs to allow embedded app to search for a file name */ - fprintf(data_file, NEWLINE NEWLINE); - fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar); - fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed); - - fclose(data_file); - fclose(struct_file); - - CHDIR(appPath); - /* append struct_file to data_file */ - printf(NEWLINE "Creating target file..." NEWLINE NEWLINE); - concat_files("fsdata.tmp", "fshdr.tmp", targetfile); - - /* if succeeded, delete the temporary files */ - if (remove("fsdata.tmp") != 0) { - printf("Warning: failed to delete fsdata.tmp\n"); - } - if (remove("fshdr.tmp") != 0) { - printf("Warning: failed to delete fshdr.tmp\n"); - } - - printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed); -#if MAKEFS_SUPPORT_DEFLATE - if (deflateNonSsiFiles) { - printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE, - (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced*100.0)/overallDataBytes)); - } -#endif - printf(NEWLINE); - - while (first_file != NULL) { - struct file_entry* fe = first_file; - first_file = fe->next; - free(fe); - } - - return 0; -} - -int check_path(char* path, size_t size) -{ - size_t slen; - if (path[0] == 0) { - /* empty */ - return 0; - } - slen = strlen(path); - if (slen >= size) { - /* not NULL-terminated */ - return 0; - } - while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) { - /* path should not end with trailing backslash */ - path[slen] = 0; - slen--; - } - if (slen == 0) { - return 0; - } - return 1; -} - -static void copy_file(const char *filename_in, FILE *fout) -{ - FILE *fin; - size_t len; - void* buf; - fin = fopen(filename_in, "rb"); - if (fin == NULL) { - printf("Failed to open file \"%s\"\n", filename_in); - exit(-1); - } - buf = malloc(COPY_BUFSIZE); - while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) { - fwrite(buf, 1, len, fout); - } - free(buf); - fclose(fin); -} - -void concat_files(const char *file1, const char *file2, const char *targetfile) -{ - FILE *fout; - fout = fopen(targetfile, "wb"); - if (fout == NULL) { - printf("Failed to open file \"%s\"\n", targetfile); - exit(-1); - } - copy_file(file1, fout); - copy_file(file2, fout); - fclose(fout); -} - -int process_sub(FILE *data_file, FILE *struct_file) -{ - FIND_T fInfo; - FIND_RET_T fret; - int filesProcessed = 0; - - if (processSubs) { - /* process subs recursively */ - size_t sublen = strlen(curSubdir); - size_t freelen = sizeof(curSubdir) - sublen - 1; - LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir)); - fret = FINDFIRST_DIR("*", &fInfo); - if (FINDFIRST_SUCCEEDED(fret)) { - do { - const char *curName = FIND_T_FILENAME(fInfo); - if ((curName[0] == '.') || (strcmp(curName, "CVS") == 0)) { - continue; - } - if (!FIND_T_IS_DIR(fInfo)) { - continue; - } - if (freelen > 0) { - CHDIR(curName); - strncat(curSubdir, "/", freelen); - strncat(curSubdir, curName, freelen - 1); - curSubdir[sizeof(curSubdir) - 1] = 0; - printf("processing subdirectory %s/..." NEWLINE, curSubdir); - filesProcessed += process_sub(data_file, struct_file); - CHDIR(".."); - curSubdir[sublen] = 0; - } else { - printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, curName); - } - } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); - } - } - - fret = FINDFIRST_FILE("*.*", &fInfo); - if (FINDFIRST_SUCCEEDED(fret)) { - /* at least one file in directory */ - do { - if (FIND_T_IS_FILE(fInfo)) { - const char *curName = FIND_T_FILENAME(fInfo); - printf("processing %s/%s..." NEWLINE, curSubdir, curName); - if (process_file(data_file, struct_file, curName) < 0) { - printf(NEWLINE "Error... aborting" NEWLINE); - return -1; - } - filesProcessed++; - } - } while (FINDNEXT_SUCCEEDED(FINDNEXT(fret, &fInfo))); - } - return filesProcessed; -} - -u8_t* get_file_data(const char* filename, int* file_size, int can_be_compressed, int* is_compressed) -{ - FILE *inFile; - size_t fsize = 0; - u8_t* buf; - size_t r; - int rs; - inFile = fopen(filename, "rb"); - if (inFile == NULL) { - printf("Failed to open file \"%s\"\n", filename); - exit(-1); - } - fseek(inFile, 0, SEEK_END); - rs = ftell(inFile); - if (rs < 0) { - printf("ftell failed with %d\n", errno); - exit(-1); - } - fsize = (size_t)rs; - fseek(inFile, 0, SEEK_SET); - buf = (u8_t*)malloc(fsize); - LWIP_ASSERT("buf != NULL", buf != NULL); - r = fread(buf, 1, fsize, inFile); - *file_size = fsize; - *is_compressed = 0; -#if MAKEFS_SUPPORT_DEFLATE - overallDataBytes += fsize; - if (deflateNonSsiFiles) { - if (can_be_compressed) { - if (fsize < OUT_BUF_SIZE) { - u8_t* ret_buf; - tdefl_status status; - size_t in_bytes = fsize; - size_t out_bytes = OUT_BUF_SIZE; - const void *next_in = buf; - void *next_out = s_outbuf; - /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */ - mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (!deflate_level) { - comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - } - status = tdefl_init(&g_deflator, NULL, NULL, comp_flags); - if (status != TDEFL_STATUS_OKAY) { - printf("tdefl_init() failed!\n"); - exit(-1); - } - memset(s_outbuf, 0, sizeof(s_outbuf)); - status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH); - if (status != TDEFL_STATUS_DONE) { - printf("deflate failed: %d\n", status); - exit(-1); - } - LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE); - if (out_bytes < fsize) { - ret_buf = (u8_t*)malloc(out_bytes); - LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL); - memcpy(ret_buf, s_outbuf, out_bytes); - { - /* sanity-check compression be inflating and comparing to the original */ - tinfl_status dec_status; - tinfl_decompressor inflator; - size_t dec_in_bytes = out_bytes; - size_t dec_out_bytes = OUT_BUF_SIZE; - next_out = s_checkbuf; - - tinfl_init(&inflator); - memset(s_checkbuf, 0, sizeof(s_checkbuf)); - dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0); - LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE); - LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes); - LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize)); - } - /* free original buffer, use compressed data + size */ - free(buf); - buf = ret_buf; - *file_size = out_bytes; - printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes*100.0)/fsize)); - deflatedBytesReduced += (size_t)(fsize - out_bytes); - *is_compressed = 1; - } else { - printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize)); - } - } else { - printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE); - } - } else { - printf(" - SSI file, cannot be compressed" NEWLINE); - } - } -#else - LWIP_UNUSED_ARG(can_be_compressed); -#endif - fclose(inFile); - return buf; -} - -void process_file_data(FILE* data_file, u8_t* file_data, size_t file_size) -{ - size_t written, i, src_off=0; - - size_t off = 0; - for (i = 0; i < file_size; i++) { - LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5); - sprintf(&file_buffer_c[off], "0x%02.2x,", file_data[i]); - off += 5; - if ((++src_off % HEX_BYTES_PER_LINE) == 0) { - LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN); - memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN); - off += NEWLINE_LEN; - } - if (off + 20 >= sizeof(file_buffer_c)) { - written = fwrite(file_buffer_c, 1, off, data_file); - LWIP_ASSERT("written == off", written == off); - off = 0; - } - } - written = fwrite(file_buffer_c, 1, off, data_file); - LWIP_ASSERT("written == off", written == off); -} - -int write_checksums(FILE *struct_file, const char *varname, - u16_t hdr_len, u16_t hdr_chksum, const u8_t* file_data, size_t file_size) -{ - int chunk_size = TCP_MSS; - int offset, src_offset; - size_t len; - int i = 0; -#if LWIP_TCP_TIMESTAMPS - /* when timestamps are used, usable space is 12 bytes less per segment */ - chunk_size -= 12; -#endif - - fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); - fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname); - - if (hdr_len > 0) { - /* add checksum for HTTP header */ - fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len); - i++; - } - src_offset = 0; - for (offset = hdr_len; ; offset += len) { - unsigned short chksum; - void* data = (void*)&file_data[src_offset]; - len = LWIP_MIN(chunk_size, (int)file_size - src_offset); - if (len == 0) { - break; - } - chksum = ~inet_chksum(data, (u16_t)len); - /* add checksum for data */ - fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, offset, chksum, len); - i++; - } - fprintf(struct_file, "};" NEWLINE); - fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); - return i; -} - -static int is_valid_char_for_c_var(char x) -{ - if (((x >= 'A') && (x <= 'Z')) || - ((x >= 'a') && (x <= 'z')) || - ((x >= '0') && (x <= '9')) || - (x == '_')) { - return 1; - } - return 0; -} - -static void fix_filename_for_c(char* qualifiedName, size_t max_len) -{ - struct file_entry* f; - size_t len = strlen(qualifiedName); - char *new_name = (char*)malloc(len + 2); - int filename_ok; - int cnt = 0; - size_t i; - if (len + 3 == max_len) { - printf("File name too long: \"%s\"\n", qualifiedName); - exit(-1); - } - strcpy(new_name, qualifiedName); - for (i = 0; i < len; i++) { - if (!is_valid_char_for_c_var(new_name[i])) { - new_name[i] = '_'; - } - } - do { - filename_ok = 1; - for (f = first_file; f != NULL; f = f->next) { - if (!strcmp(f->filename_c, new_name)) { - filename_ok = 0; - cnt++; - /* try next unique file name */ - sprintf(&new_name[len], "%d", cnt); - break; - } - } - } while (!filename_ok && (cnt < 999)); - if (!filename_ok) { - printf("Failed to get unique file name: \"%s\"\n", qualifiedName); - exit(-1); - } - strcpy(qualifiedName, new_name); - free(new_name); -} - -static void register_filename(const char* qualifiedName) -{ - struct file_entry* fe = (struct file_entry*)malloc(sizeof(struct file_entry)); - fe->filename_c = strdup(qualifiedName); - fe->next = NULL; - if (first_file == NULL) { - first_file = last_file = fe; - } else { - last_file->next = fe; - last_file = fe; - } -} - -int is_ssi_file(const char* filename) -{ - size_t loop; - for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (strstr(filename, g_pcSSIExtensions[loop])) { - return 1; - } - } - return 0; -} - -int process_file(FILE *data_file, FILE *struct_file, const char *filename) -{ - char varname[MAX_PATH_LEN]; - int i = 0; - char qualifiedName[MAX_PATH_LEN]; - int file_size; - u16_t http_hdr_chksum = 0; - u16_t http_hdr_len = 0; - int chksum_count = 0; - u8_t flags = 0; - const char* flags_str; - u8_t has_content_len; - u8_t* file_data; - int is_compressed = 0; - - /* create qualified name (@todo: prepend slash or not?) */ - sprintf(qualifiedName,"%s/%s", curSubdir, filename); - /* create C variable name */ - strcpy(varname, qualifiedName); - /* convert slashes & dots to underscores */ - fix_filename_for_c(varname, MAX_PATH_LEN); - register_filename(varname); -#if ALIGN_PAYLOAD - /* to force even alignment of array, type 1 */ - fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE); - fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); - fprintf(data_file, "#endif" NEWLINE); -#endif /* ALIGN_PAYLOAD */ - fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname); - /* encode source file name (used by file system, not returned to browser) */ - fprintf(data_file, "/* %s (%d chars) */" NEWLINE, qualifiedName, strlen(qualifiedName)+1); - file_put_ascii(data_file, qualifiedName, strlen(qualifiedName)+1, &i); -#if ALIGN_PAYLOAD - /* pad to even number of bytes to assure payload is on aligned boundary */ - while(i % PAYLOAD_ALIGNMENT != 0) { - fprintf(data_file, "0x%02.2x,", 0); - i++; - } -#endif /* ALIGN_PAYLOAD */ - fprintf(data_file, NEWLINE); - - has_content_len = !is_ssi_file(filename); - file_data = get_file_data(filename, &file_size, includeHttpHeader && has_content_len, &is_compressed); - if (includeHttpHeader) { - file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed); - flags = FS_FILE_FLAGS_HEADER_INCLUDED; - if (has_content_len) { - flags |= FS_FILE_FLAGS_HEADER_PERSISTENT; - } - } - if (precalcChksum) { - chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size); - } - - /* build declaration of struct fsdata_file in temp file */ - fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); - fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); - fprintf(struct_file, "data_%s," NEWLINE, varname); - fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); - fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); - switch(flags) - { - case(FS_FILE_FLAGS_HEADER_INCLUDED): - flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED"; - break; - case(FS_FILE_FLAGS_HEADER_PERSISTENT): - flags_str = "FS_FILE_FLAGS_HEADER_PERSISTENT"; - break; - case(FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT): - flags_str = "FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT"; - break; - default: - flags_str = "0"; - break; - } - fprintf(struct_file, "%s," NEWLINE, flags_str); - if (precalcChksum) { - fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); - fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); - fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); - } - fprintf(struct_file, "}};" NEWLINE NEWLINE); - strcpy(lastFileVar, varname); - - /* write actual file contents */ - i = 0; - fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); - process_file_data(data_file, file_data, file_size); - fprintf(data_file, "};" NEWLINE NEWLINE); - free(file_data); - return 0; -} - -int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, - u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed) -{ - int i = 0; - int response_type = HTTP_HDR_OK; - const char* file_type; - const char *cur_string; - size_t cur_len; - int written = 0; - size_t hdr_len = 0; - u16_t acc; - const char *file_ext; - int j; - u8_t provide_last_modified = includeLastModified; - - memset(hdr_buf, 0, sizeof(hdr_buf)); - - if (useHttp11) { - response_type = HTTP_HDR_OK_11; - } - - fprintf(data_file, NEWLINE "/* HTTP header */"); - if (strstr(filename, "404") == filename) { - response_type = HTTP_HDR_NOT_FOUND; - if (useHttp11) { - response_type = HTTP_HDR_NOT_FOUND_11; - } - } else if (strstr(filename, "400") == filename) { - response_type = HTTP_HDR_BAD_REQUEST; - if (useHttp11) { - response_type = HTTP_HDR_BAD_REQUEST_11; - } - } else if (strstr(filename, "501") == filename) { - response_type = HTTP_HDR_NOT_IMPL; - if (useHttp11) { - response_type = HTTP_HDR_NOT_IMPL_11; - } - } - cur_string = g_psHTTPHeaderStrings[response_type]; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - cur_string = serverID; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - file_ext = filename; - if (file_ext != NULL) { - while(strstr(file_ext, ".") != NULL) { - file_ext = strstr(file_ext, "."); - file_ext++; - } - } - if ((file_ext == NULL) || (*file_ext == 0)) { - printf("failed to get extension for file \"%s\", using default.\n", filename); - file_type = HTTP_HDR_DEFAULT_TYPE; - } else { - file_type = NULL; - for (j = 0; j < NUM_HTTP_HEADERS; j++) { - if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { - file_type = g_psHTTPHeaders[j].content_type; - break; - } - } - if (file_type == NULL) { - printf("failed to get file type for extension \"%s\", using default.\n", file_ext); - file_type = HTTP_HDR_DEFAULT_TYPE; - } - } - - /* Content-Length is used for persistent connections in HTTP/1.1 but also for - download progress in older versions - @todo: just use a big-enough buffer and let the HTTPD send spaces? */ - if (provide_content_len) { - char intbuf[MAX_PATH_LEN]; - int content_len = file_size; - memset(intbuf, 0, sizeof(intbuf)); - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%d+ bytes) */" NEWLINE, cur_string, content_len, cur_len+2); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - _itoa(content_len, intbuf, 10); - strcat(intbuf, "\r\n"); - cur_len = strlen(intbuf); - written += file_put_ascii(data_file, intbuf, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], intbuf, cur_len); - hdr_len += cur_len; - } - } - if (provide_last_modified) { - char modbuf[256]; - struct stat stat_data; - struct tm* t; - memset(modbuf, 0, sizeof(modbuf)); - memset(&stat_data, 0, sizeof(stat_data)); - cur_string = modbuf; - strcpy(modbuf, "Last-Modified: "); - if (stat(filename, &stat_data) != 0) { - printf("stat(%s) failed with error %d\n", filename, errno); - exit(-1); - } - t = gmtime(&stat_data.st_mtime); - if (t == NULL) { - printf("gmtime() failed with error %d\n", errno); - exit(-1); - } - strftime(&modbuf[15], sizeof(modbuf)-15, "%a, %d %b %Y %H:%M:%S GMT", t); - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%d+ bytes) */" NEWLINE, cur_string, cur_len+2); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - modbuf[0] = 0; - strcat(modbuf, "\r\n"); - cur_len = strlen(modbuf); - written += file_put_ascii(data_file, modbuf, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], modbuf, cur_len); - hdr_len += cur_len; - } - } - - /* HTTP/1.1 implements persistent connections */ - if (useHttp11) { - if (provide_content_len) { - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; - } else { - /* no Content-Length available, so a persistent connection is no possible - because the client does not know the data length */ - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; - } - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - } - -#if MAKEFS_SUPPORT_DEFLATE - if (is_compressed) { - /* tell the client about the deflate encoding */ - LWIP_ASSERT("error", deflateNonSsiFiles); - cur_string = "Content-Encoding: deflate\r\n"; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - } -#else - LWIP_UNUSED_ARG(is_compressed); -#endif - - /* write content-type, ATTENTION: this includes the double-CRLF! */ - cur_string = file_type; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - - /* ATTENTION: headers are done now (double-CRLF has been written!) */ - - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - - LWIP_ASSERT("hdr_len <= 0xffff", hdr_len <= 0xffff); - LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); - acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); - *http_hdr_len = (u16_t)hdr_len; - *http_hdr_chksum = acc; - } - - return written; -} - -int file_put_ascii(FILE *file, const char* ascii_string, int len, int *i) -{ - int x; - for (x = 0; x < len; x++) { - unsigned char cur = ascii_string[x]; - fprintf(file, "0x%02.2x,", cur); - if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { - fprintf(file, NEWLINE); - } - } - return len; -} - -int s_put_ascii(char *buf, const char *ascii_string, int len, int *i) -{ - int x; - int idx = 0; - for (x = 0; x < len; x++) { - unsigned char cur = ascii_string[x]; - sprintf(&buf[idx], "0x%02.2x,", cur); - idx += 5; - if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { - sprintf(&buf[idx], NEWLINE); - idx += NEWLINE_LEN; - } - } - return len; -} diff --git a/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/readme.txt b/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/readme.txt deleted file mode 100644 index 3768585ef9..0000000000 --- a/components/net/lwip-2.0.2/src/apps/httpd/makefsdata/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -This directory contains a script ('makefsdata') to create C code suitable for -httpd for given html pages (or other files) in a directory. - -There is also a plain C console application doing the same and extended a bit. - -Usage: htmlgen [targetdir] [-s] [-i]s - targetdir: relative or absolute path to files to convert - switch -s: toggle processing of subdirectories (default is on) - switch -e: exclude HTTP header from file (header is created at runtime, default is on) - switch -11: include HTTP 1.1 header (1.0 is default) - - if targetdir not specified, makefsdata will attempt to - process files in subdirectory 'fs'. diff --git a/components/net/lwip-2.0.2/src/apps/lwiperf/lwiperf.c b/components/net/lwip-2.0.2/src/apps/lwiperf/lwiperf.c deleted file mode 100644 index efabe478e3..0000000000 --- a/components/net/lwip-2.0.2/src/apps/lwiperf/lwiperf.c +++ /dev/null @@ -1,661 +0,0 @@ -/** - * @file - * lwIP iPerf server implementation - */ - -/** - * @defgroup iperf Iperf server - * @ingroup apps - * - * This is a simple performance measuring server to check your bandwith using - * iPerf2 on a PC as client. - * It is currently a minimal implementation providing an IPv4 TCP server only. - * - * @todo: implement UDP mode and IPv6 - */ - -/* - * Copyright (c) 2014 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - */ - -#include "lwip/apps/lwiperf.h" - -#include "lwip/tcp.h" -#include "lwip/sys.h" - -#include - -/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */ -#if LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API - -/** Specify the idle timeout (in seconds) after that the test fails */ -#ifndef LWIPERF_TCP_MAX_IDLE_SEC -#define LWIPERF_TCP_MAX_IDLE_SEC 10U -#endif -#if LWIPERF_TCP_MAX_IDLE_SEC > 255 -#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t -#endif - -/* File internal memory allocation (struct lwiperf_*): this defaults to - the heap */ -#ifndef LWIPERF_ALLOC -#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type)) -#define LWIPERF_FREE(type, item) mem_free(item) -#endif - -/** If this is 1, check that received data has the correct format */ -#ifndef LWIPERF_CHECK_RX_DATA -#define LWIPERF_CHECK_RX_DATA 0 -#endif - -/** This is the Iperf settings struct sent from the client */ -typedef struct _lwiperf_settings { -#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000 -#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001 - u32_t flags; - u32_t num_threads; /* unused for now */ - u32_t remote_port; - u32_t buffer_len; /* unused for now */ - u32_t win_band; /* TCP window / UDP rate: unused for now */ - u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */ -} lwiperf_settings_t; - -/** Basic connection handle */ -struct _lwiperf_state_base; -typedef struct _lwiperf_state_base lwiperf_state_base_t; -struct _lwiperf_state_base { - /* 1=tcp, 0=udp */ - u8_t tcp; - /* 1=server, 0=client */ - u8_t server; - lwiperf_state_base_t* next; - lwiperf_state_base_t* related_server_state; -}; - -/** Connection handle for a TCP iperf session */ -typedef struct _lwiperf_state_tcp { - lwiperf_state_base_t base; - struct tcp_pcb* server_pcb; - struct tcp_pcb* conn_pcb; - u32_t time_started; - lwiperf_report_fn report_fn; - void* report_arg; - u8_t poll_count; - u8_t next_num; - u32_t bytes_transferred; - lwiperf_settings_t settings; - u8_t have_settings_buf; -} lwiperf_state_tcp_t; - -/** List of active iperf sessions */ -static lwiperf_state_base_t* lwiperf_all_connections; -/** A const buffer to send from: we want to measure sending, not copying! */ -static const u8_t lwiperf_txbuf_const[1600] = { - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', - '0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', -}; - -static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb); -static void lwiperf_tcp_err(void *arg, err_t err); - -/** Add an iperf session to the 'active' list */ -static void -lwiperf_list_add(lwiperf_state_base_t* item) -{ - if (lwiperf_all_connections == NULL) { - lwiperf_all_connections = item; - } else { - item = lwiperf_all_connections; - } -} - -/** Remove an iperf session from the 'active' list */ -static void -lwiperf_list_remove(lwiperf_state_base_t* item) -{ - lwiperf_state_base_t* prev = NULL; - lwiperf_state_base_t* iter; - for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) { - if (iter == item) { - if (prev == NULL) { - lwiperf_all_connections = iter->next; - } else { - prev->next = item; - } - /* @debug: ensure this item is listed only once */ - for (iter = iter->next; iter != NULL; iter = iter->next) { - LWIP_ASSERT("duplicate entry", iter != item); - } - break; - } - } -} - -/** Call the report function of an iperf tcp session */ -static void -lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) -{ - if ((conn != NULL) && (conn->report_fn != NULL)) { - u32_t now, duration_ms, bandwidth_kbitpsec; - now = sys_now(); - duration_ms = now - conn->time_started; - if (duration_ms == 0) { - bandwidth_kbitpsec = 0; - } else { - bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U; - } - conn->report_fn(conn->report_arg, report_type, - &conn->conn_pcb->local_ip, conn->conn_pcb->local_port, - &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port, - conn->bytes_transferred, duration_ms, bandwidth_kbitpsec); - } -} - -/** Close an iperf tcp session */ -static void -lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) -{ - err_t err; - - lwip_tcp_conn_report(conn, report_type); - lwiperf_list_remove(&conn->base); - if (conn->conn_pcb != NULL) { - tcp_arg(conn->conn_pcb, NULL); - tcp_poll(conn->conn_pcb, NULL, 0); - tcp_sent(conn->conn_pcb, NULL); - tcp_recv(conn->conn_pcb, NULL); - tcp_err(conn->conn_pcb, NULL); - err = tcp_close(conn->conn_pcb); - if (err != ERR_OK) { - /* don't want to wait for free memory here... */ - tcp_abort(conn->conn_pcb); - } - } else { - /* no conn pcb, this is the server pcb */ - err = tcp_close(conn->server_pcb); - LWIP_ASSERT("error", err != ERR_OK); - } - LWIPERF_FREE(lwiperf_state_tcp_t, conn); -} - -/** Try to send more data on an iperf tcp session */ -static err_t -lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) -{ - int send_more; - err_t err; - u16_t txlen; - u16_t txlen_max; - void* txptr; - u8_t apiflags; - - LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); - - do { - send_more = 0; - if (conn->settings.amount & PP_HTONL(0x80000000)) { - /* this session is time-limited */ - u32_t now = sys_now(); - u32_t diff_ms = now - conn->time_started; - u32_t time = (u32_t)-(s32_t)lwip_htonl(conn->settings.amount); - u32_t time_ms = time * 10; - if (diff_ms >= time_ms) { - /* time specified by the client is over -> close the connection */ - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); - return ERR_OK; - } - } else { - /* this session is byte-limited */ - u32_t amount_bytes = lwip_htonl(conn->settings.amount); - /* @todo: this can send up to 1*MSS more than requested... */ - if (amount_bytes >= conn->bytes_transferred) { - /* all requested bytes transferred -> close the connection */ - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); - return ERR_OK; - } - } - - if (conn->bytes_transferred < 24) { - /* transmit the settings a first time */ - txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred]; - txlen_max = (u16_t)(24 - conn->bytes_transferred); - apiflags = TCP_WRITE_FLAG_COPY; - } else if (conn->bytes_transferred < 48) { - /* transmit the settings a second time */ - txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24]; - txlen_max = (u16_t)(48 - conn->bytes_transferred); - apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; - send_more = 1; - } else { - /* transmit data */ - /* @todo: every x bytes, transmit the settings again */ - txptr = LWIP_CONST_CAST(void*, &lwiperf_txbuf_const[conn->bytes_transferred % 10]); - txlen_max = TCP_MSS; - if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ - txlen_max = TCP_MSS - 24; - } - apiflags = 0; /* no copying needed */ - send_more = 1; - } - txlen = txlen_max; - do { - err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); - if (err == ERR_MEM) { - txlen /= 2; - } - } while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2))); - - if (err == ERR_OK) { - conn->bytes_transferred += txlen; - } else { - send_more = 0; - } - } while(send_more); - - tcp_output(conn->conn_pcb); - return ERR_OK; -} - -/** TCP sent callback, try to send more data */ -static err_t -lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */ - LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - LWIP_UNUSED_ARG(len); - - conn->poll_count = 0; - - return lwiperf_tcp_client_send_more(conn); -} - -/** TCP connected callback (active connection), send data now */ -static err_t -lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - if (err != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); - return ERR_OK; - } - conn->poll_count = 0; - conn->time_started = sys_now(); - return lwiperf_tcp_client_send_more(conn); -} - -/** Start TCP connection back to the client (either parallel or after the - * receive test has finished. - */ -static err_t -lwiperf_tx_start(lwiperf_state_tcp_t* conn) -{ - err_t err; - lwiperf_state_tcp_t* client_conn; - struct tcp_pcb* newpcb; - ip_addr_t remote_addr; - u16_t remote_port; - - client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (client_conn == NULL) { - return ERR_MEM; - } - newpcb = tcp_new(); - if (newpcb == NULL) { - LWIPERF_FREE(lwiperf_state_tcp_t, client_conn); - return ERR_MEM; - } - - MEMCPY(client_conn, conn, sizeof(lwiperf_state_tcp_t)); - client_conn->base.server = 0; - client_conn->server_pcb = NULL; - client_conn->conn_pcb = newpcb; - client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */ - client_conn->poll_count = 0; - client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */ - client_conn->bytes_transferred = 0; - client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */ - - tcp_arg(newpcb, client_conn); - tcp_sent(newpcb, lwiperf_tcp_client_sent); - tcp_poll(newpcb, lwiperf_tcp_poll, 2U); - tcp_err(newpcb, lwiperf_tcp_err); - - ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip); - remote_port = (u16_t)lwip_htonl(client_conn->settings.remote_port); - - err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); - if (err != ERR_OK) { - lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL); - return err; - } - lwiperf_list_add(&client_conn->base); - return ERR_OK; -} - -/** Receive data on an iperf tcp session */ -static err_t -lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -{ - u8_t tmp; - u16_t tot_len; - u32_t packet_idx; - struct pbuf* q; - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - - LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - - if (err != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); - return ERR_OK; - } - if (p == NULL) { - /* connection closed -> test done */ - if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == - PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { - /* client requested transmission after end of test */ - lwiperf_tx_start(conn); - } - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); - return ERR_OK; - } - tot_len = p->tot_len; - - conn->poll_count = 0; - - if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { - /* wait for 24-byte header */ - if (p->tot_len < sizeof(lwiperf_settings_t)) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_VAL; - } - if (!conn->have_settings_buf) { - if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); - pbuf_free(p); - return ERR_VAL; - } - conn->have_settings_buf = 1; - if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == - PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { - /* client requested parallel transmission test */ - err_t err2 = lwiperf_tx_start(conn); - if (err2 != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); - pbuf_free(p); - return err2; - } - } - } else { - if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_VAL; - } - } - conn->bytes_transferred += sizeof(lwiperf_settings_t); - if (conn->bytes_transferred <= 24) { - conn->time_started = sys_now(); - tcp_recved(tpcb, p->tot_len); - pbuf_free(p); - return ERR_OK; - } - conn->next_num = 4; /* 24 bytes received... */ - tmp = pbuf_header(p, -24); - LWIP_ASSERT("pbuf_header failed", tmp == 0); - } - - packet_idx = 0; - for (q = p; q != NULL; q = q->next) { -#if LWIPERF_CHECK_RX_DATA - const u8_t* payload = (const u8_t*)q->payload; - u16_t i; - for (i = 0; i < q->len; i++) { - u8_t val = payload[i]; - u8_t num = val - '0'; - if (num == conn->next_num) { - conn->next_num++; - if (conn->next_num == 10) { - conn->next_num = 0; - } - } else { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_VAL; - } - } -#endif - packet_idx += q->len; - } - LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); - conn->bytes_transferred += packet_idx; - tcp_recved(tpcb, tot_len); - pbuf_free(p); - return ERR_OK; -} - -/** Error callback, iperf tcp session aborted */ -static void -lwiperf_tcp_err(void *arg, err_t err) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - LWIP_UNUSED_ARG(err); - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); -} - -/** TCP poll callback, try to send more data */ -static err_t -lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb) -{ - lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; - LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); - return ERR_OK; /* lwiperf_tcp_close frees conn */ - } - - if (!conn->base.server) { - lwiperf_tcp_client_send_more(conn); - } - - return ERR_OK; -} - -/** This is called when a new client connects for an iperf tcp session */ -static err_t -lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - lwiperf_state_tcp_t *s, *conn; - if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) { - return ERR_VAL; - } - - s = (lwiperf_state_tcp_t*)arg; - conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (conn == NULL) { - return ERR_MEM; - } - memset(conn, 0, sizeof(lwiperf_state_tcp_t)); - conn->base.tcp = 1; - conn->base.server = 1; - conn->base.related_server_state = &s->base; - conn->server_pcb = s->server_pcb; - conn->conn_pcb = newpcb; - conn->time_started = sys_now(); - conn->report_fn = s->report_fn; - conn->report_arg = s->report_arg; - - /* setup the tcp rx connection */ - tcp_arg(newpcb, conn); - tcp_recv(newpcb, lwiperf_tcp_recv); - tcp_poll(newpcb, lwiperf_tcp_poll, 2U); - tcp_err(conn->conn_pcb, lwiperf_tcp_err); - - lwiperf_list_add(&conn->base); - return ERR_OK; -} - -/** - * @ingroup iperf - * Start a TCP iperf server on the default TCP port (5001) and listen for - * incoming connections from iperf clients. - * - * @returns a connection handle that can be used to abort the server - * by calling @ref lwiperf_abort() - */ -void* -lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg) -{ - return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, - report_fn, report_arg); -} - -/** - * @ingroup iperf - * Start a TCP iperf server on a specific IP address and port and listen for - * incoming connections from iperf clients. - * - * @returns a connection handle that can be used to abort the server - * by calling @ref lwiperf_abort() - */ -void* -lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void* report_arg) -{ - err_t err; - struct tcp_pcb* pcb; - lwiperf_state_tcp_t* s; - - if (local_addr == NULL) { - return NULL; - } - - s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (s == NULL) { - return NULL; - } - memset(s, 0, sizeof(lwiperf_state_tcp_t)); - s->base.tcp = 1; - s->base.server = 1; - s->report_fn = report_fn; - s->report_arg = report_arg; - - pcb = tcp_new(); - if (pcb != NULL) { - err = tcp_bind(pcb, local_addr, local_port); - if (err == ERR_OK) { - s->server_pcb = tcp_listen_with_backlog(pcb, 1); - } - } - if (s->server_pcb == NULL) { - if (pcb != NULL) { - tcp_close(pcb); - } - LWIPERF_FREE(lwiperf_state_tcp_t, s); - return NULL; - } - pcb = NULL; - - tcp_arg(s->server_pcb, s); - tcp_accept(s->server_pcb, lwiperf_tcp_accept); - - lwiperf_list_add(&s->base); - return s; -} - -/** - * @ingroup iperf - * Abort an iperf session (handle returned by lwiperf_start_tcp_server*()) - */ -void -lwiperf_abort(void* lwiperf_session) -{ - lwiperf_state_base_t* i, *dealloc, *last = NULL; - - for (i = lwiperf_all_connections; i != NULL; ) { - if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) { - dealloc = i; - i = i->next; - if (last != NULL) { - last->next = i; - } - LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */ - } else { - last = i; - i = i->next; - } - } -} - -#endif /* LWIP_IPV4 && LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/components/net/lwip-2.0.2/src/apps/mdns/mdns.c b/components/net/lwip-2.0.2/src/apps/mdns/mdns.c deleted file mode 100644 index 14334fc856..0000000000 --- a/components/net/lwip-2.0.2/src/apps/mdns/mdns.c +++ /dev/null @@ -1,2028 +0,0 @@ -/** - * @file - * MDNS responder implementation - * - * @defgroup mdns MDNS - * @ingroup apps - * - * RFC 6762 - Multicast DNS\n - * RFC 6763 - DNS-Based Service Discovery\n - * - * @verbinclude mdns.txt - * - * Things left to implement: - * ------------------------- - * - * - Probing/conflict resolution - * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off... - * - Checking that source address of unicast requests are on the same network - * - Limiting multicast responses to 1 per second per resource record - * - Fragmenting replies if required - * - Subscribe to netif address/link change events and act on them (currently needs to be done manually) - * - Handling multi-packet known answers - * - Individual known answer detection for all local IPv6 addresses - * - Dynamic size of outgoing packet - */ - -/* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "lwip/apps/mdns.h" -#include "lwip/apps/mdns_priv.h" -#include "lwip/netif.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/mem.h" -#include "lwip/prot/dns.h" - -#include - -#if LWIP_MDNS_RESPONDER - -#if (LWIP_IPV4 && !LWIP_IGMP) - #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h" -#endif -#if (LWIP_IPV6 && !LWIP_IPV6_MLD) -#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP) - #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif - -#if LWIP_IPV4 -#include "lwip/igmp.h" -/* IPv4 multicast group 224.0.0.251 */ -static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT; -#endif - -#if LWIP_IPV6 -#include "lwip/mld6.h" -/* IPv6 multicast group FF02::FB */ -static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT; -#endif - -#define MDNS_PORT 5353 -#define MDNS_TTL 255 - -/* Stored offsets to beginning of domain names - * Used for compression. - */ -#define NUM_DOMAIN_OFFSETS 10 -#define DOMAIN_JUMP_SIZE 2 -#define DOMAIN_JUMP 0xc000 - -static u8_t mdns_netif_client_id; -static struct udp_pcb *mdns_pcb; - -#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id)) - -#define TOPDOMAIN_LOCAL "local" - -#define REVERSE_PTR_TOPDOMAIN "arpa" -#define REVERSE_PTR_V4_DOMAIN "in-addr" -#define REVERSE_PTR_V6_DOMAIN "ip6" - -#define SRV_PRIORITY 0 -#define SRV_WEIGHT 0 - -/* Payload size allocated for each outgoing UDP packet */ -#define OUTPACKET_SIZE 500 - -/* Lookup from hostname -> IPv4 */ -#define REPLY_HOST_A 0x01 -/* Lookup from IPv4/v6 -> hostname */ -#define REPLY_HOST_PTR_V4 0x02 -/* Lookup from hostname -> IPv6 */ -#define REPLY_HOST_AAAA 0x04 -/* Lookup from hostname -> IPv6 */ -#define REPLY_HOST_PTR_V6 0x08 - -/* Lookup for service types */ -#define REPLY_SERVICE_TYPE_PTR 0x10 -/* Lookup for instances of service */ -#define REPLY_SERVICE_NAME_PTR 0x20 -/* Lookup for location of service instance */ -#define REPLY_SERVICE_SRV 0x40 -/* Lookup for text info on service instance */ -#define REPLY_SERVICE_TXT 0x80 - -static const char *dnssd_protos[] = { - "_udp", /* DNSSD_PROTO_UDP */ - "_tcp", /* DNSSD_PROTO_TCP */ -}; - -/** Description of a service */ -struct mdns_service { - /** TXT record to answer with */ - struct mdns_domain txtdata; - /** Name of service, like 'myweb' */ - char name[MDNS_LABEL_MAXLEN + 1]; - /** Type of service, like '_http' */ - char service[MDNS_LABEL_MAXLEN + 1]; - /** Callback function and userdata - * to update txtdata buffer */ - service_get_txt_fn_t txt_fn; - void *txt_userdata; - /** TTL in seconds of SRV/TXT replies */ - u32_t dns_ttl; - /** Protocol, TCP or UDP */ - u16_t proto; - /** Port of the service */ - u16_t port; -}; - -/** Description of a host/netif */ -struct mdns_host { - /** Hostname */ - char name[MDNS_LABEL_MAXLEN + 1]; - /** Pointer to services */ - struct mdns_service *services[MDNS_MAX_SERVICES]; - /** TTL in seconds of A/AAAA/PTR replies */ - u32_t dns_ttl; -}; - -/** Information about received packet */ -struct mdns_packet { - /** Sender IP/port */ - ip_addr_t source_addr; - u16_t source_port; - /** If packet was received unicast */ - u16_t recv_unicast; - /** Netif that received the packet */ - struct netif *netif; - /** Packet data */ - struct pbuf *pbuf; - /** Current parsing offset in packet */ - u16_t parse_offset; - /** Identifier. Used in legacy queries */ - u16_t tx_id; - /** Number of questions in packet, - * read from packet header */ - u16_t questions; - /** Number of unparsed questions */ - u16_t questions_left; - /** Number of answers in packet, - * (sum of normal, authorative and additional answers) - * read from packet header */ - u16_t answers; - /** Number of unparsed answers */ - u16_t answers_left; -}; - -/** Information about outgoing packet */ -struct mdns_outpacket { - /** Netif to send the packet on */ - struct netif *netif; - /** Packet data */ - struct pbuf *pbuf; - /** Current write offset in packet */ - u16_t write_offset; - /** Identifier. Used in legacy queries */ - u16_t tx_id; - /** Destination IP/port if sent unicast */ - ip_addr_t dest_addr; - u16_t dest_port; - /** Number of questions written */ - u16_t questions; - /** Number of normal answers written */ - u16_t answers; - /** Number of additional answers written */ - u16_t additional; - /** Offsets for written domain names in packet. - * Used for compression */ - u16_t domain_offsets[NUM_DOMAIN_OFFSETS]; - /** If all answers in packet should set cache_flush bit */ - u8_t cache_flush; - /** If reply should be sent unicast */ - u8_t unicast_reply; - /** If legacy query. (tx_id needed, and write - * question again in reply before answer) */ - u8_t legacy_query; - /* Reply bitmask for host information */ - u8_t host_replies; - /* Bitmask for which reverse IPv6 hosts to answer */ - u8_t host_reverse_v6_replies; - /* Reply bitmask per service */ - u8_t serv_replies[MDNS_MAX_SERVICES]; -}; - -/** Domain, type and class. - * Shared between questions and answers */ -struct mdns_rr_info { - struct mdns_domain domain; - u16_t type; - u16_t klass; -}; - -struct mdns_question { - struct mdns_rr_info info; - /** unicast reply requested */ - u16_t unicast; -}; - -struct mdns_answer { - struct mdns_rr_info info; - /** cache flush command bit */ - u16_t cache_flush; - /* Validity time in seconds */ - u32_t ttl; - /** Length of variable answer */ - u16_t rd_length; - /** Offset of start of variable answer in packet */ - u16_t rd_offset; -}; - -/** - * Add a label part to a domain - * @param domain The domain to add a label to - * @param label The label to add, like <hostname>, 'local', 'com' or '' - * @param len The length of the label - * @return ERR_OK on success, an err_t otherwise if label too long - */ -err_t -mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len) -{ - if (len > MDNS_LABEL_MAXLEN) { - return ERR_VAL; - } - if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) { - return ERR_VAL; - } - /* Allow only zero marker on last byte */ - if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) { - return ERR_VAL; - } - domain->name[domain->length] = len; - domain->length++; - if (len) { - MEMCPY(&domain->name[domain->length], label, len); - domain->length += len; - } - return ERR_OK; -} - -/** - * Internal readname function with max 6 levels of recursion following jumps - * while decompressing name - */ -static u16_t -mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth) -{ - u8_t c; - - do { - if (depth > 5) { - /* Too many jumps */ - return MDNS_READNAME_ERROR; - } - - c = pbuf_get_at(p, offset); - offset++; - - /* is this a compressed label? */ - if((c & 0xc0) == 0xc0) { - u16_t jumpaddr; - if (offset >= p->tot_len) { - /* Make sure both jump bytes fit in the packet */ - return MDNS_READNAME_ERROR; - } - jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff)); - offset++; - if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) { - u16_t res; - /* Recursive call, maximum depth will be checked */ - res = mdns_readname_loop(p, jumpaddr, domain, depth + 1); - /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */ - if (res == MDNS_READNAME_ERROR) { - return res; - } - } else { - return MDNS_READNAME_ERROR; - } - break; - } - - /* normal label */ - if (c <= MDNS_LABEL_MAXLEN) { - u8_t label[MDNS_LABEL_MAXLEN]; - err_t res; - - if (c + domain->length >= MDNS_DOMAIN_MAXLEN) { - return MDNS_READNAME_ERROR; - } - if (c != 0) { - if (pbuf_copy_partial(p, label, c, offset) != c) { - return MDNS_READNAME_ERROR; - } - offset += c; - } - res = mdns_domain_add_label(domain, (char *) label, c); - if (res != ERR_OK) { - return MDNS_READNAME_ERROR; - } - } else { - /* bad length byte */ - return MDNS_READNAME_ERROR; - } - } while (c != 0); - - return offset; -} - -/** - * Read possibly compressed domain name from packet buffer - * @param p The packet - * @param offset start position of domain name in packet - * @param domain The domain name destination - * @return The new offset after the domain, or MDNS_READNAME_ERROR - * if reading failed - */ -u16_t -mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain) -{ - memset(domain, 0, sizeof(struct mdns_domain)); - return mdns_readname_loop(p, offset, domain, 0); -} - -/** - * Print domain name to debug output - * @param domain The domain name - */ -static void -mdns_domain_debug_print(struct mdns_domain *domain) -{ - u8_t *src = domain->name; - u8_t i; - - while (*src) { - u8_t label_len = *src; - src++; - for (i = 0; i < label_len; i++) { - LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i])); - } - src += label_len; - LWIP_DEBUGF(MDNS_DEBUG, (".")); - } -} - -/** - * Return 1 if contents of domains match (case-insensitive) - * @param a Domain name to compare 1 - * @param b Domain name to compare 2 - * @return 1 if domains are equal ignoring case, 0 otherwise - */ -int -mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b) -{ - u8_t *ptra, *ptrb; - u8_t len; - int res; - - if (a->length != b->length) { - return 0; - } - - ptra = a->name; - ptrb = b->name; - while (*ptra && *ptrb && ptra < &a->name[a->length]) { - if (*ptra != *ptrb) { - return 0; - } - len = *ptra; - ptra++; - ptrb++; - res = lwip_strnicmp((char *) ptra, (char *) ptrb, len); - if (res != 0) { - return 0; - } - ptra += len; - ptrb += len; - } - if (*ptra != *ptrb && ptra < &a->name[a->length]) { - return 0; - } - return 1; -} - -/** - * Call user supplied function to setup TXT data - * @param service The service to build TXT record for - */ -static void -mdns_prepare_txtdata(struct mdns_service *service) -{ - memset(&service->txtdata, 0, sizeof(struct mdns_domain)); - if (service->txt_fn) { - service->txt_fn(service, service->txt_userdata); - } -} - -#if LWIP_IPV4 -/** - * Build domain for reverse lookup of IPv4 address - * like 12.0.168.192.in-addr.arpa. for 192.168.0.12 - * @param domain Where to write the domain name - * @param addr Pointer to an IPv4 address to encode - * @return ERR_OK if domain was written, an err_t otherwise - */ -static err_t -mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr) -{ - int i; - err_t res; - const u8_t *ptr; - if (!domain || !addr) { - return ERR_ARG; - } - memset(domain, 0, sizeof(struct mdns_domain)); - ptr = (const u8_t *) addr; - for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) { - char buf[4]; - u8_t val = ptr[i]; - - lwip_itoa(buf, sizeof(buf), val); - res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - } - res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, NULL, 0); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - - return ERR_OK; -} -#endif - -#if LWIP_IPV6 -/** - * Build domain for reverse lookup of IP address - * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab - * @param domain Where to write the domain name - * @param addr Pointer to an IPv6 address to encode - * @return ERR_OK if domain was written, an err_t otherwise - */ -static err_t -mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr) -{ - int i; - err_t res; - const u8_t *ptr; - if (!domain || !addr) { - return ERR_ARG; - } - memset(domain, 0, sizeof(struct mdns_domain)); - ptr = (const u8_t *) addr; - for (i = sizeof(ip6_addr_t) - 1; i >= 0; i--) { - char buf; - u8_t byte = ptr[i]; - int j; - for (j = 0; j < 2; j++) { - if ((byte & 0x0F) < 0xA) { - buf = '0' + (byte & 0x0F); - } else { - buf = 'a' + (byte & 0x0F) - 0xA; - } - res = mdns_domain_add_label(domain, &buf, sizeof(buf)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - byte >>= 4; - } - } - res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN)-1)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, NULL, 0); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - - return ERR_OK; -} -#endif - -/* Add .local. to domain */ -static err_t -mdns_add_dotlocal(struct mdns_domain *domain) -{ - err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL)-1)); - LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res); - return mdns_domain_add_label(domain, NULL, 0); -} - -/** - * Build the .local. domain name - * @param domain Where to write the domain name - * @param mdns TMDNS netif descriptor. - * @return ERR_OK if domain .local. was written, an err_t otherwise - */ -static err_t -mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns) -{ - err_t res; - memset(domain, 0, sizeof(struct mdns_domain)); - LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL); - res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name)); - LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Build the lookup-all-services special DNS-SD domain name - * @param domain Where to write the domain name - * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise - */ -static err_t -mdns_build_dnssd_domain(struct mdns_domain *domain) -{ - err_t res; - memset(domain, 0, sizeof(struct mdns_domain)); - res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services")-1)); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd")-1)); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP])); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Build domain name for a service - * @param domain Where to write the domain name - * @param service The service struct, containing service name, type and protocol - * @param include_name Whether to include the service name in the domain - * @return ERR_OK if domain was written. If service name is included, - * ...local. will be written, otherwise ..local. - * An err_t is returned on error. - */ -static err_t -mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name) -{ - err_t res; - memset(domain, 0, sizeof(struct mdns_domain)); - if (include_name) { - res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name)); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - } - res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto])); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Check which replies we should send for a host/netif based on question - * @param netif The network interface that received the question - * @param rr Domain/type/class from a question - * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for - * if reply bit has REPLY_HOST_PTR_V6 set - * @return Bitmask of which replies to send - */ -static int -check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply) -{ - err_t res; - int replies = 0; - struct mdns_domain mydomain; - - LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */ - - if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { - /* Invalid class */ - return replies; - } - - /* Handle PTR for our addresses */ - if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) { -#if LWIP_IPV6 - int i; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i)); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - replies |= REPLY_HOST_PTR_V6; - /* Mark which addresses where requested */ - if (reverse_v6_reply) { - *reverse_v6_reply |= (1 << i); - } - } - } - } -#endif -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { - res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif)); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - replies |= REPLY_HOST_PTR_V4; - } - } -#endif - } - - res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif)); - /* Handle requests for our hostname */ - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - /* TODO return NSEC if unsupported protocol requested */ -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) - && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) { - replies |= REPLY_HOST_A; - } -#endif -#if LWIP_IPV6 - if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_HOST_AAAA; - } -#endif - } - - return replies; -} - -/** - * Check which replies we should send for a service based on question - * @param service A registered MDNS service - * @param rr Domain/type/class from a question - * @return Bitmask of which replies to send - */ -static int -check_service(struct mdns_service *service, struct mdns_rr_info *rr) -{ - err_t res; - int replies = 0; - struct mdns_domain mydomain; - - if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { - /* Invalid class */ - return 0; - } - - res = mdns_build_dnssd_domain(&mydomain); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && - (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { - /* Request for all service types */ - replies |= REPLY_SERVICE_TYPE_PTR; - } - - res = mdns_build_service_domain(&mydomain, service, 0); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && - (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { - /* Request for the instance of my service */ - replies |= REPLY_SERVICE_NAME_PTR; - } - - res = mdns_build_service_domain(&mydomain, service, 1); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - /* Request for info about my service */ - if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_SERVICE_SRV; - } - if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_SERVICE_TXT; - } - } - - return replies; -} - -/** - * Return bytes needed to write before jump for best result of compressing supplied domain - * against domain in outpacket starting at specified offset. - * If a match is found, offset is updated to where to jump to - * @param pbuf Pointer to pbuf with the partially constructed DNS packet - * @param offset Start position of a domain written earlier. If this location is suitable - * for compression, the pointer is updated to where in the domain to jump to. - * @param domain The domain to write - * @return Number of bytes to write of the new domain before writing a jump to the offset. - * If compression can not be done against this previous domain name, the full new - * domain length is returned. - */ -u16_t -mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain) -{ - struct mdns_domain target; - u16_t target_end; - u8_t target_len; - u8_t writelen = 0; - u8_t *ptr; - if (pbuf == NULL) { - return domain->length; - } - target_end = mdns_readname(pbuf, *offset, &target); - if (target_end == MDNS_READNAME_ERROR) { - return domain->length; - } - target_len = (u8_t)(target_end - *offset); - ptr = domain->name; - while (writelen < domain->length) { - u8_t domainlen = (u8_t)(domain->length - writelen); - u8_t labellen; - if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) { - /* Compare domains if target is long enough, and we have enough left of the domain */ - u8_t targetpos = (u8_t)(target.length - domainlen); - if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) { - /* We are checking at or beyond a jump in the original, stop looking */ - break; - } - if (target.length >= domainlen && - memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) { - *offset += targetpos; - return writelen; - } - } - /* Skip to next label in domain */ - labellen = *ptr; - writelen += 1 + labellen; - ptr += 1 + labellen; - } - /* Nothing found */ - return domain->length; -} - -/** - * Write domain to outpacket. Compression will be attempted, - * unless domain->skip_compression is set. - * @param outpkt The outpacket to write to - * @param domain The domain name to write - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) -{ - int i; - err_t res; - u16_t writelen = domain->length; - u16_t jump_offset = 0; - u16_t jump; - - if (!domain->skip_compression) { - for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { - u16_t offset = outpkt->domain_offsets[i]; - if (offset) { - u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain); - if (len < writelen) { - writelen = len; - jump_offset = offset; - } - } - } - } - - if (writelen) { - /* Write uncompressed part of name */ - res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - - /* Store offset of this new domain */ - for (i = 0; i < NUM_DOMAIN_OFFSETS; ++i) { - if (outpkt->domain_offsets[i] == 0) { - outpkt->domain_offsets[i] = outpkt->write_offset; - break; - } - } - - outpkt->write_offset += writelen; - } - if (jump_offset) { - /* Write jump */ - jump = lwip_htons(DOMAIN_JUMP | jump_offset); - res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += DOMAIN_JUMP_SIZE; - } - return ERR_OK; -} - -/** - * Write a question to an outpacket - * A question contains domain, type and class. Since an answer also starts with these fields this function is also - * called from mdns_add_answer(). - * @param outpkt The outpacket to write to - * @param domain The domain name the answer is for - * @param type The DNS type of the answer (like 'AAAA', 'SRV') - * @param klass The DNS type of the answer (like 'IN') - * @param unicast If highest bit in class should be set, to instruct the responder to - * reply with a unicast packet - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast) -{ - u16_t question_len; - u16_t field16; - err_t res; - - if (!outpkt->pbuf) { - /* If no pbuf is active, allocate one */ - outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); - if (!outpkt->pbuf) { - return ERR_MEM; - } - outpkt->write_offset = SIZEOF_DNS_HDR; - } - - /* Worst case calculation. Domain string might be compressed */ - question_len = domain->length + sizeof(type) + sizeof(klass); - if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) { - /* No space */ - return ERR_MEM; - } - - /* Write name */ - res = mdns_write_domain(outpkt, domain); - if (res != ERR_OK) { - return res; - } - - /* Write type */ - field16 = lwip_htons(type); - res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += sizeof(field16); - - /* Write class */ - if (unicast) { - klass |= 0x8000; - } - field16 = lwip_htons(klass); - res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += sizeof(field16); - - return ERR_OK; -} - -/** - * Write answer to reply packet. - * buf or answer_domain can be null. The rd_length written will be buf_length + - * size of (compressed) domain. Most uses will need either buf or answer_domain, - * special case is SRV that starts with 3 u16 and then a domain name. - * @param reply The outpacket to write to - * @param domain The domain name the answer is for - * @param type The DNS type of the answer (like 'AAAA', 'SRV') - * @param klass The DNS type of the answer (like 'IN') - * @param cache_flush If highest bit in class should be set, to instruct receiver that - * this reply replaces any earlier answer for this domain/type/class - * @param ttl Validity time in seconds to send out for IP address data in DNS replies - * @param buf Pointer to buffer of answer data - * @param buf_length Length of variable data - * @param answer_domain A domain to write after any buffer data as answer - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush, - u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain) -{ - u16_t answer_len; - u16_t field16; - u16_t rdlen_offset; - u16_t answer_offset; - u32_t field32; - err_t res; - - if (!reply->pbuf) { - /* If no pbuf is active, allocate one */ - reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); - if (!reply->pbuf) { - return ERR_MEM; - } - reply->write_offset = SIZEOF_DNS_HDR; - } - - /* Worst case calculation. Domain strings might be compressed */ - answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/; - if (buf) { - answer_len += (u16_t)buf_length; - } - if (answer_domain) { - answer_len += answer_domain->length; - } - if (reply->write_offset + answer_len > reply->pbuf->tot_len) { - /* No space */ - return ERR_MEM; - } - - /* Answer starts with same data as question, then more fields */ - mdns_add_question(reply, domain, type, klass, cache_flush); - - /* Write TTL */ - field32 = lwip_htonl(ttl); - res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset); - if (res != ERR_OK) { - return res; - } - reply->write_offset += sizeof(field32); - - /* Store offsets and skip forward to the data */ - rdlen_offset = reply->write_offset; - reply->write_offset += sizeof(field16); - answer_offset = reply->write_offset; - - if (buf) { - /* Write static data */ - res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset); - if (res != ERR_OK) { - return res; - } - reply->write_offset += (u16_t)buf_length; - } - - if (answer_domain) { - /* Write name answer (compressed if possible) */ - res = mdns_write_domain(reply, answer_domain); - if (res != ERR_OK) { - return res; - } - } - - /* Write rd_length after when we know the answer size */ - field16 = lwip_htons(reply->write_offset - answer_offset); - res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset); - - return res; -} - -/** - * Helper function for mdns_read_question/mdns_read_answer - * Reads a domain, type and class from the packet - * @param pkt The MDNS packet to read from. The parse_offset field will be - * incremented to point to the next unparsed byte. - * @param info The struct to fill with domain, type and class - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info) -{ - u16_t field16, copied; - pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain); - if (pkt->parse_offset == MDNS_READNAME_ERROR) { - return ERR_VAL; - } - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - info->type = lwip_ntohs(field16); - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - info->klass = lwip_ntohs(field16); - - return ERR_OK; -} - -/** - * Read a question from the packet. - * All questions have to be read before the answers. - * @param pkt The MDNS packet to read from. The questions_left field will be decremented - * and the parse_offset will be updated. - * @param question The struct to fill with question data - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question) -{ - /* Safety check */ - if (pkt->pbuf->tot_len < pkt->parse_offset) { - return ERR_VAL; - } - - if (pkt->questions_left) { - err_t res; - pkt->questions_left--; - - memset(question, 0, sizeof(struct mdns_question)); - res = mdns_read_rr_info(pkt, &question->info); - if (res != ERR_OK) { - return res; - } - - /* Extract unicast flag from class field */ - question->unicast = question->info.klass & 0x8000; - question->info.klass &= 0x7FFF; - - return ERR_OK; - } - return ERR_VAL; -} - -/** - * Read an answer from the packet - * The variable length reply is not copied, its pbuf offset and length is stored instead. - * @param pkt The MDNS packet to read. The answers_left field will be decremented and - * the parse_offset will be updated. - * @param answer The struct to fill with answer data - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer) -{ - /* Read questions first */ - if (pkt->questions_left) { - return ERR_VAL; - } - - /* Safety check */ - if (pkt->pbuf->tot_len < pkt->parse_offset) { - return ERR_VAL; - } - - if (pkt->answers_left) { - u16_t copied, field16; - u32_t ttl; - err_t res; - pkt->answers_left--; - - memset(answer, 0, sizeof(struct mdns_answer)); - res = mdns_read_rr_info(pkt, &answer->info); - if (res != ERR_OK) { - return res; - } - - /* Extract cache_flush flag from class field */ - answer->cache_flush = answer->info.klass & 0x8000; - answer->info.klass &= 0x7FFF; - - copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset); - if (copied != sizeof(ttl)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - answer->ttl = lwip_ntohl(ttl); - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - answer->rd_length = lwip_ntohs(field16); - - answer->rd_offset = pkt->parse_offset; - pkt->parse_offset += answer->rd_length; - - return ERR_OK; - } - return ERR_VAL; -} - -#if LWIP_IPV4 -/** Write an IPv4 address (A) RR to outpacket */ -static err_t -mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) -{ - struct mdns_domain host; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n")); - return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL); -} - -/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */ -static err_t -mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) -{ - struct mdns_domain host, revhost; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n")); - return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); -} -#endif - -#if LWIP_IPV6 -/** Write an IPv6 address (AAAA) RR to outpacket */ -static err_t -mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) -{ - struct mdns_domain host; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n")); - return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_t), NULL); -} - -/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */ -static err_t -mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) -{ - struct mdns_domain host, revhost; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n")); - return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); -} -#endif - -/** Write an all-services -> servicetype PTR RR to outpacket */ -static err_t -mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) -{ - struct mdns_domain service_type, service_dnssd; - mdns_build_service_domain(&service_type, service, 0); - mdns_build_dnssd_domain(&service_dnssd); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); - return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type); -} - -/** Write a servicetype -> servicename PTR RR to outpacket */ -static err_t -mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) -{ - struct mdns_domain service_type, service_instance; - mdns_build_service_domain(&service_type, service, 0); - mdns_build_service_domain(&service_instance, service, 1); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n")); - return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance); -} - -/** Write a SRV RR to outpacket */ -static err_t -mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service) -{ - struct mdns_domain service_instance, srvhost; - u16_t srvdata[3]; - mdns_build_service_domain(&service_instance, service, 1); - mdns_build_host_domain(&srvhost, mdns); - if (reply->legacy_query) { - /* RFC 6762 section 18.14: - * In legacy unicast responses generated to answer legacy queries, - * name compression MUST NOT be performed on SRV records. - */ - srvhost.skip_compression = 1; - } - srvdata[0] = lwip_htons(SRV_PRIORITY); - srvdata[1] = lwip_htons(SRV_WEIGHT); - srvdata[2] = lwip_htons(service->port); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n")); - return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, - (const u8_t *) &srvdata, sizeof(srvdata), &srvhost); -} - -/** Write a TXT RR to outpacket */ -static err_t -mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service) -{ - struct mdns_domain service_instance; - mdns_build_service_domain(&service_instance, service, 1); - mdns_prepare_txtdata(service); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n")); - return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, - (u8_t *) &service->txtdata.name, service->txtdata.length, NULL); -} - -/** - * Setup outpacket as a reply to the incoming packet - */ -static void -mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in) -{ - memset(out, 0, sizeof(struct mdns_outpacket)); - out->cache_flush = 1; - out->netif = in->netif; - - /* Copy source IP/port to use when responding unicast, or to choose - * which pcb to use for multicast (IPv4/IPv6) - */ - SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t)); - out->dest_port = in->source_port; - - if (in->source_port != MDNS_PORT) { - out->unicast_reply = 1; - out->cache_flush = 0; - if (in->questions == 1) { - out->legacy_query = 1; - out->tx_id = in->tx_id; - } - } - - if (in->recv_unicast) { - out->unicast_reply = 1; - } -} - -/** - * Send chosen answers as a reply - * - * Add all selected answers (first write will allocate pbuf) - * Add additional answers based on the selected answers - * Send the packet - */ -static void -mdns_send_outpacket(struct mdns_outpacket *outpkt) -{ - struct mdns_service *service; - err_t res; - int i; - struct mdns_host* mdns = NETIF_TO_HOST(outpkt->netif); - - /* Write answers to host questions */ -#if LWIP_IPV4 - if (outpkt->host_replies & REPLY_HOST_A) { - res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - if (outpkt->host_replies & REPLY_HOST_PTR_V4) { - res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } -#endif -#if LWIP_IPV6 - if (outpkt->host_replies & REPLY_HOST_AAAA) { - int addrindex; - for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { - if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { - res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - } - } - if (outpkt->host_replies & REPLY_HOST_PTR_V6) { - u8_t rev_addrs = outpkt->host_reverse_v6_replies; - int addrindex = 0; - while (rev_addrs) { - if (rev_addrs & 1) { - res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - addrindex++; - rev_addrs >>= 1; - } - } -#endif - - /* Write answers to service questions */ - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) { - res = mdns_add_servicetype_ptr_answer(outpkt, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { - res = mdns_add_servicename_ptr_answer(outpkt, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) { - res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) { - res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->answers++; - } - } - - /* All answers written, add additional RRs */ - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { - /* Our service instance requested, include SRV & TXT - * if they are already not requested. */ - if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) { - res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - - if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) { - res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - } - - /* If service instance, SRV, record or an IP address is requested, - * supply all addresses for the host - */ - if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) || - (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) { -#if LWIP_IPV6 - if (!(outpkt->host_replies & REPLY_HOST_AAAA)) { - int addrindex; - for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; ++addrindex) { - if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { - res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - } - } -#endif -#if LWIP_IPV4 - if (!(outpkt->host_replies & REPLY_HOST_A)) { - res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } -#endif - } - } - - if (outpkt->pbuf) { - const ip_addr_t *mcast_destaddr; - struct dns_hdr hdr; - - /* Write header */ - memset(&hdr, 0, sizeof(hdr)); - hdr.flags1 = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE; - hdr.numanswers = lwip_htons(outpkt->answers); - hdr.numextrarr = lwip_htons(outpkt->additional); - if (outpkt->legacy_query) { - hdr.numquestions = lwip_htons(1); - hdr.id = lwip_htons(outpkt->tx_id); - } - pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr)); - - /* Shrink packet */ - pbuf_realloc(outpkt->pbuf, outpkt->write_offset); - - if (IP_IS_V6_VAL(outpkt->dest_addr)) { -#if LWIP_IPV6 - mcast_destaddr = &v6group; -#endif - } else { -#if LWIP_IPV4 - mcast_destaddr = &v4group; -#endif - } - /* Send created packet */ - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply)); - if (outpkt->unicast_reply) { - udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif); - } else { - udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, MDNS_PORT, outpkt->netif); - } - } - -cleanup: - if (outpkt->pbuf) { - pbuf_free(outpkt->pbuf); - outpkt->pbuf = NULL; - } -} - -/** - * Send unsolicited answer containing all our known data - * @param netif The network interface to send on - * @param destination The target address to send to (usually multicast address) - */ -static void -mdns_announce(struct netif *netif, const ip_addr_t *destination) -{ - struct mdns_outpacket announce; - int i; - struct mdns_host* mdns = NETIF_TO_HOST(netif); - - memset(&announce, 0, sizeof(announce)); - announce.netif = netif; - announce.cache_flush = 1; -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) - announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4; -#endif -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6; - announce.host_reverse_v6_replies |= (1 << i); - } - } -#endif - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *serv = mdns->services[i]; - if (serv) { - announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR | - REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; - } - } - - announce.dest_port = MDNS_PORT; - SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr)); - mdns_send_outpacket(&announce); -} - -/** - * Handle question MDNS packet - * 1. Parse all questions and set bits what answers to send - * 2. Clear pending answers if known answers are supplied - * 3. Put chosen answers in new packet and send as reply - */ -static void -mdns_handle_question(struct mdns_packet *pkt) -{ - struct mdns_service *service; - struct mdns_outpacket reply; - int replies = 0; - int i; - err_t res; - struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif); - - mdns_init_outpacket(&reply, pkt); - - while (pkt->questions_left) { - struct mdns_question q; - - res = mdns_read_question(pkt, &q); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n")); - return; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain ")); - mdns_domain_debug_print(&q.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass)); - - if (q.unicast) { - /* Reply unicast if any question is unicast */ - reply.unicast_reply = 1; - } - - reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies); - replies |= reply.host_replies; - - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - reply.serv_replies[i] |= check_service(service, &q.info); - replies |= reply.serv_replies[i]; - } - - if (replies && reply.legacy_query) { - /* Add question to reply packet (legacy packet only has 1 question) */ - res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0); - if (res != ERR_OK) { - goto cleanup; - } - } - } - - /* Handle known answers */ - while (pkt->answers_left) { - struct mdns_answer ans; - u8_t rev_v6; - int match; - - res = mdns_read_answer(pkt, &ans); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n")); - goto cleanup; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain ")); - mdns_domain_debug_print(&ans.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); - - - if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) { - /* Skip known answers for ANY type & class */ - continue; - } - - rev_v6 = 0; - match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6); - if (match && (ans.ttl > (mdns->dns_ttl / 2))) { - /* The RR in the known answer matches an RR we are planning to send, - * and the TTL is less than half gone. - * If the payload matches we should not send that answer. - */ - if (ans.info.type == DNS_RRTYPE_PTR) { - /* Read domain and compare */ - struct mdns_domain known_ans, my_ans; - u16_t len; - len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); - res = mdns_build_host_domain(&my_ans, mdns); - if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { -#if LWIP_IPV4 - if (match & REPLY_HOST_PTR_V4) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n")); - reply.host_replies &= ~REPLY_HOST_PTR_V4; - } -#endif -#if LWIP_IPV6 - if (match & REPLY_HOST_PTR_V6) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n")); - reply.host_reverse_v6_replies &= ~rev_v6; - if (reply.host_reverse_v6_replies == 0) { - reply.host_replies &= ~REPLY_HOST_PTR_V6; - } - } -#endif - } - } else if (match & REPLY_HOST_A) { -#if LWIP_IPV4 - if (ans.rd_length == sizeof(ip4_addr_t) && - pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n")); - reply.host_replies &= ~REPLY_HOST_A; - } -#endif - } else if (match & REPLY_HOST_AAAA) { -#if LWIP_IPV6 - if (ans.rd_length == sizeof(ip6_addr_t) && - /* TODO this clears all AAAA responses if first addr is set as known */ - pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n")); - reply.host_replies &= ~REPLY_HOST_AAAA; - } -#endif - } - } - - for (i = 0; i < MDNS_MAX_SERVICES; ++i) { - service = mdns->services[i]; - if (!service) { - continue; - } - match = reply.serv_replies[i] & check_service(service, &ans.info); - if (match && (ans.ttl > (service->dns_ttl / 2))) { - /* The RR in the known answer matches an RR we are planning to send, - * and the TTL is less than half gone. - * If the payload matches we should not send that answer. - */ - if (ans.info.type == DNS_RRTYPE_PTR) { - /* Read domain and compare */ - struct mdns_domain known_ans, my_ans; - u16_t len; - len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); - if (len != MDNS_READNAME_ERROR) { - if (match & REPLY_SERVICE_TYPE_PTR) { - res = mdns_build_service_domain(&my_ans, service, 0); - if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR; - } - } - if (match & REPLY_SERVICE_NAME_PTR) { - res = mdns_build_service_domain(&my_ans, service, 1); - if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR; - } - } - } - } else if (match & REPLY_SERVICE_SRV) { - /* Read and compare to my SRV record */ - u16_t field16, len, read_pos; - struct mdns_domain known_ans, my_ans; - read_pos = ans.rd_offset; - do { - /* Check priority field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) { - break; - } - read_pos += len; - /* Check weight field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) { - break; - } - read_pos += len; - /* Check port field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) { - break; - } - read_pos += len; - /* Check host field */ - len = mdns_readname(pkt->pbuf, read_pos, &known_ans); - mdns_build_host_domain(&my_ans, mdns); - if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) { - break; - } - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_SRV; - } while (0); - } else if (match & REPLY_SERVICE_TXT) { - mdns_prepare_txtdata(service); - if (service->txtdata.length == ans.rd_length && - pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_TXT; - } - } - } - } - } - - mdns_send_outpacket(&reply); - -cleanup: - if (reply.pbuf) { - /* This should only happen if we fail to alloc/write question for legacy query */ - pbuf_free(reply.pbuf); - reply.pbuf = NULL; - } -} - -/** - * Handle response MDNS packet - * Only prints debug for now. Will need more code to do conflict resolution. - */ -static void -mdns_handle_response(struct mdns_packet *pkt) -{ - /* Ignore all questions */ - while (pkt->questions_left) { - struct mdns_question q; - err_t res; - - res = mdns_read_question(pkt, &q); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n")); - return; - } - } - - while (pkt->answers_left) { - struct mdns_answer ans; - err_t res; - - res = mdns_read_answer(pkt, &ans); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n")); - return; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain ")); - mdns_domain_debug_print(&ans.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); - } -} - -/** - * Receive input function for MDNS packets. - * Handles both IPv4 and IPv6 UDP pcbs. - */ -static void -mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - struct dns_hdr hdr; - struct mdns_packet packet; - struct netif *recv_netif = ip_current_input_netif(); - u16_t offset = 0; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr)? 6 : 4, p->tot_len)); - - if (NETIF_TO_HOST(recv_netif) == NULL) { - /* From netif not configured for MDNS */ - goto dealloc; - } - - if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) { - /* Too small */ - goto dealloc; - } - offset += SIZEOF_DNS_HDR; - - if (DNS_HDR_GET_OPCODE(&hdr)) { - /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */ - goto dealloc; - } - - memset(&packet, 0, sizeof(packet)); - SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr)); - packet.source_port = port; - packet.netif = recv_netif; - packet.pbuf = p; - packet.parse_offset = offset; - packet.tx_id = lwip_ntohs(hdr.id); - packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions); - packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr); - -#if LWIP_IPV6 - if (IP_IS_V6(ip_current_dest_addr())) { - if (!ip_addr_cmp(ip_current_dest_addr(), &v6group)) { - packet.recv_unicast = 1; - } - } -#endif -#if LWIP_IPV4 - if (!IP_IS_V6(ip_current_dest_addr())) { - if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) { - packet.recv_unicast = 1; - } - } -#endif - - if (hdr.flags1 & DNS_FLAG1_RESPONSE) { - mdns_handle_response(&packet); - } else { - mdns_handle_question(&packet); - } - -dealloc: - pbuf_free(p); -} - -/** - * @ingroup mdns - * Initiate MDNS responder. Will open UDP sockets on port 5353 - */ -void -mdns_resp_init(void) -{ - err_t res; - - mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL); -#if LWIP_MULTICAST_TX_OPTIONS - udp_set_multicast_ttl(mdns_pcb, MDNS_TTL); -#else - mdns_pcb->ttl = MDNS_TTL; -#endif - res = udp_bind(mdns_pcb, IP_ANY_TYPE, MDNS_PORT); - LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("Failed to bind pcb", res == ERR_OK); - udp_recv(mdns_pcb, mdns_recv, NULL); - - mdns_netif_client_id = netif_alloc_client_data_id(); -} - -/** - * @ingroup mdns - * Announce IP settings have changed on netif. - * Call this in your callback registered by netif_set_status_callback(). - * This function may go away in the future when netif supports registering - * multiple callback functions. - * @param netif The network interface where settings have changed. - */ -void -mdns_resp_netif_settings_changed(struct netif *netif) -{ - LWIP_ERROR("mdns_resp_netif_ip_changed: netif != NULL", (netif != NULL), return); - - if (NETIF_TO_HOST(netif) == NULL) { - return; - } - - /* Announce on IPv6 and IPv4 */ -#if LWIP_IPV6 - mdns_announce(netif, IP6_ADDR_ANY); -#endif -#if LWIP_IPV4 - mdns_announce(netif, IP4_ADDR_ANY); -#endif -} - -/** - * @ingroup mdns - * Activate MDNS responder for a network interface and send announce packets. - * @param netif The network interface to activate. - * @param hostname Name to use. Queries for <hostname>.local will be answered - * with the IP addresses of the netif. The hostname will be copied, the - * given pointer can be on the stack. - * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies - * @return ERR_OK if netif was added, an err_t otherwise - */ -err_t -mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl) -{ - err_t res; - struct mdns_host* mdns; - - LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - - LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL); - mdns = (struct mdns_host *) mem_malloc(sizeof(struct mdns_host)); - LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM); - - netif_set_client_data(netif, mdns_netif_client_id, mdns); - - memset(mdns, 0, sizeof(struct mdns_host)); - MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname))); - mdns->dns_ttl = dns_ttl; - - /* Join multicast groups */ -#if LWIP_IPV4 - res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group)); - if (res != ERR_OK) { - goto cleanup; - } -#endif -#if LWIP_IPV6 - res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group)); - if (res != ERR_OK) { - goto cleanup; - } -#endif - - mdns_resp_netif_settings_changed(netif); - return ERR_OK; - -cleanup: - mem_free(mdns); - netif_set_client_data(netif, mdns_netif_client_id, NULL); - return res; -} - -/** - * @ingroup mdns - * Stop responding to MDNS queries on this interface, leave multicast groups, - * and free the helper structure and any of its services. - * @param netif The network interface to remove. - * @return ERR_OK if netif was removed, an err_t otherwise - */ -err_t -mdns_resp_remove_netif(struct netif *netif) -{ - int i; - struct mdns_host* mdns; - - LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL); - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *service = mdns->services[i]; - if (service) { - mem_free(service); - } - } - - /* Leave multicast groups */ -#if LWIP_IPV4 - igmp_leavegroup_netif(netif, ip_2_ip4(&v4group)); -#endif -#if LWIP_IPV6 - mld6_leavegroup_netif(netif, ip_2_ip6(&v6group)); -#endif - - mem_free(mdns); - netif_set_client_data(netif, mdns_netif_client_id, NULL); - return ERR_OK; -} - -/** - * @ingroup mdns - * Add a service to the selected network interface. - * @param netif The network interface to publish this service on - * @param name The name of the service - * @param service The service type, like "_http" - * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP - * for others ("_udp") - * @param port The port the service listens to - * @param dns_ttl Validity time in seconds to send out for service data in DNS replies - * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to - * allow dynamic replies. - * @param txt_data Userdata pointer for txt_fn - * @return ERR_OK if the service was added to the netif, an err_t otherwise - */ -err_t -mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data) -{ - int i; - int slot = -1; - struct mdns_service *srv; - struct mdns_host* mdns; - - LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); - - LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL); - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - if (mdns->services[i] == NULL) { - slot = i; - break; - } - } - LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM); - - srv = (struct mdns_service*)mem_malloc(sizeof(struct mdns_service)); - LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM); - - memset(srv, 0, sizeof(struct mdns_service)); - - MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); - MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); - srv->txt_fn = txt_fn; - srv->txt_userdata = txt_data; - srv->proto = (u16_t)proto; - srv->port = port; - srv->dns_ttl = dns_ttl; - - mdns->services[slot] = srv; - - /* Announce on IPv6 and IPv4 */ -#if LWIP_IPV6 - mdns_announce(netif, IP6_ADDR_ANY); -#endif -#if LWIP_IPV4 - mdns_announce(netif, IP4_ADDR_ANY); -#endif - - return ERR_OK; -} - -/** - * @ingroup mdns - * Call this function from inside the service_get_txt_fn_t callback to add text data. - * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte. - * @param service The service provided to the get_txt callback - * @param txt String to add to the TXT field. - * @param txt_len Length of string - * @return ERR_OK if the string was added to the reply, an err_t otherwise - */ -err_t -mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len) -{ - LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service); - - /* Use a mdns_domain struct to store txt chunks since it is the same encoding */ - return mdns_domain_add_label(&service->txtdata, txt, txt_len); -} - -#endif /* LWIP_MDNS_RESPONDER */ diff --git a/components/net/lwip-2.0.2/src/apps/mqtt/mqtt.c b/components/net/lwip-2.0.2/src/apps/mqtt/mqtt.c deleted file mode 100644 index a0e77b9719..0000000000 --- a/components/net/lwip-2.0.2/src/apps/mqtt/mqtt.c +++ /dev/null @@ -1,1341 +0,0 @@ -/** - * @file - * MQTT client - * - * @defgroup mqtt MQTT client - * @ingroup apps - * @verbinclude mqtt_client.txt - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack - * - * Author: Erik Andersson - * - * - * @todo: - * - Handle large outgoing payloads for PUBLISH messages - * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics) - * - Add support for legacy MQTT protocol version - * - * Please coordinate changes and requests with Erik Andersson - * Erik Andersson - * - */ -#include "lwip/apps/mqtt.h" -#include "lwip/timeouts.h" -#include "lwip/ip_addr.h" -#include "lwip/mem.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/tcp.h" -#include - -#if LWIP_TCP && LWIP_CALLBACK_API - -/** - * MQTT_DEBUG: Default is off. - */ -#if !defined MQTT_DEBUG || defined __DOXYGEN__ -#define MQTT_DEBUG LWIP_DBG_OFF -#endif - -#define MQTT_DEBUG_TRACE (MQTT_DEBUG | LWIP_DBG_TRACE) -#define MQTT_DEBUG_STATE (MQTT_DEBUG | LWIP_DBG_STATE) -#define MQTT_DEBUG_WARN (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define MQTT_DEBUG_WARN_STATE (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define MQTT_DEBUG_SERIOUS (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - -static void mqtt_cyclic_timer(void *arg); - -/** - * MQTT client connection states - */ -enum { - TCP_DISCONNECTED, - TCP_CONNECTING, - MQTT_CONNECTING, - MQTT_CONNECTED -}; - -/** - * MQTT control message types - */ -enum mqtt_message_type { - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 -}; - -/** Helpers to extract control packet type and qos from first byte in fixed header */ -#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4) -#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1) - -/** - * MQTT connect flags, only used in CONNECT message - */ -enum mqtt_connect_flag { - MQTT_CONNECT_FLAG_USERNAME = 1 << 7, - MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, - MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, - MQTT_CONNECT_FLAG_WILL = 1 << 2, - MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 -}; - - -#if defined(LWIP_DEBUG) -static const char * const mqtt_message_type_str[15] = -{ - "UNDEFINED", - "CONNECT", - "CONNACK", - "PUBLISH", - "PUBACK", - "PUBREC", - "PUBREL", - "PUBCOMP", - "SUBSCRIBE", - "SUBACK", - "UNSUBSCRIBE", - "UNSUBACK", - "PINGREQ", - "PINGRESP", - "DISCONNECT" -}; - -/** - * Message type value to string - * @param msg_type see enum mqtt_message_type - * - * @return Control message type text string - */ -static const char * -mqtt_msg_type_to_str(u8_t msg_type) -{ - if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) { - msg_type = 0; - } - return mqtt_message_type_str[msg_type]; -} - -#endif - - -/** - * Generate MQTT packet identifier - * @param client MQTT client - * @return New packet identifier, range 1 to 65535 - */ -static u16_t -msg_generate_packet_id(mqtt_client_t *client) -{ - client->pkt_id_seq++; - if (client->pkt_id_seq == 0) { - client->pkt_id_seq++; - } - return client->pkt_id_seq; -} - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Output ring buffer */ - - -#define MQTT_RINGBUF_IDX_MASK ((MQTT_OUTPUT_RINGBUF_SIZE) - 1) - -/** Add single item to ring buffer */ -#define mqtt_ringbuf_put(rb, item) ((rb)->buf)[(rb)->put++ & MQTT_RINGBUF_IDX_MASK] = (item) - -/** Return number of bytes in ring buffer */ -#define mqtt_ringbuf_len(rb) ((u16_t)((rb)->put - (rb)->get)) - -/** Return number of bytes free in ring buffer */ -#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb)) - -/** Return number of bytes possible to read without wrapping around */ -#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - ((rb)->get & MQTT_RINGBUF_IDX_MASK))) - -/** Return pointer to ring buffer get position */ -#define mqtt_ringbuf_get_ptr(rb) (&(rb)->buf[(rb)->get & MQTT_RINGBUF_IDX_MASK]) - -#define mqtt_ringbuf_advance_get_idx(rb, len) ((rb)->get += (len)) - - -/** - * Try send as many bytes as possible from output ring buffer - * @param rb Output ring buffer - * @param tpcb TCP connection handle - */ -static void -mqtt_output_send(struct mqtt_ringbuf_t *rb, struct tcp_pcb *tpcb) -{ - err_t err; - u8_t wrap = 0; - u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb); - u16_t send_len = tcp_sndbuf(tpcb); - LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL); - - if (send_len == 0 || ringbuf_lin_len == 0) { - return; - } - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n", - send_len, ringbuf_lin_len, ((rb)->get & MQTT_RINGBUF_IDX_MASK), ((rb)->put & MQTT_RINGBUF_IDX_MASK))); - - if (send_len > ringbuf_lin_len) { - /* Space in TCP output buffer is larger than available in ring buffer linear portion */ - send_len = ringbuf_lin_len; - /* Wrap around if more data in ring buffer after linear portion */ - wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len); - } - err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0)); - if ((err == ERR_OK) && wrap) { - mqtt_ringbuf_advance_get_idx(rb, send_len); - /* Use the lesser one of ring buffer linear length and TCP send buffer size */ - send_len = LWIP_MIN(tcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb)); - err = tcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY); - } - - if (err == ERR_OK) { - mqtt_ringbuf_advance_get_idx(rb, send_len); - /* Flush */ - tcp_output(tpcb); - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); - } -} - - - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Request queue */ - -/** - * Create request item - * @param r_objs Pointer to request objects - * @param pkt_id Packet identifier of request - * @param cb Packet callback to call when requests lifetime ends - * @param arg Parameter following callback - * @return Request or NULL if failed to create - */ -static struct mqtt_request_t * -mqtt_create_request(struct mqtt_request_t *r_objs, u16_t pkt_id, mqtt_request_cb_t cb, void *arg) -{ - struct mqtt_request_t *r = NULL; - u8_t n; - LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); - for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { - /* Item point to itself if not in use */ - if (r_objs[n].next == &r_objs[n]) { - r = &r_objs[n]; - r->next = NULL; - r->cb = cb; - r->arg = arg; - r->pkt_id = pkt_id; - break; - } - } - return r; -} - - -/** - * Append request to pending request queue - * @param tail Pointer to request queue tail pointer - * @param r Request to append - */ -static void -mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r) -{ - struct mqtt_request_t *head = NULL; - s16_t time_before = 0; - struct mqtt_request_t *iter; - - LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); - - /* Iterate trough queue to find head, and count total timeout time */ - for (iter = *tail; iter != NULL; iter = iter->next) { - time_before += iter->timeout_diff; - head = iter; - } - - LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT); - r->timeout_diff = MQTT_REQ_TIMEOUT - time_before; - if (head == NULL) { - *tail = r; - } else { - head->next = r; - } -} - - -/** - * Delete request item - * @param r Request item to delete - */ -static void -mqtt_delete_request(struct mqtt_request_t *r) -{ - if (r != NULL) { - r->next = r; - } -} - -/** - * Remove a request item with a specific packet identifier from request queue - * @param tail Pointer to request queue tail pointer - * @param pkt_id Packet identifier of request to take - * @return Request item if found, NULL if not - */ -static struct mqtt_request_t * -mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id) -{ - struct mqtt_request_t *iter = NULL, *prev = NULL; - LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL); - /* Search all request for pkt_id */ - for (iter = *tail; iter != NULL; iter = iter->next) { - if (iter->pkt_id == pkt_id) { - break; - } - prev = iter; - } - - /* If request was found */ - if (iter != NULL) { - /* unchain */ - if (prev == NULL) { - *tail= iter->next; - } else { - prev->next = iter->next; - } - /* If exists, add remaining timeout time for the request to next */ - if (iter->next != NULL) { - iter->next->timeout_diff += iter->timeout_diff; - } - iter->next = NULL; - } - return iter; -} - -/** - * Handle requests timeout - * @param tail Pointer to request queue tail pointer - * @param t Time since last call in seconds - */ -static void -mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) -{ - struct mqtt_request_t *r = *tail; - LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); - while (t > 0 && r != NULL) { - if (t >= r->timeout_diff) { - t -= (u8_t)r->timeout_diff; - /* Unchain */ - *tail = r->next; - /* Notify upper layer about timeout */ - if (r->cb != NULL) { - r->cb(r->arg, ERR_TIMEOUT); - } - mqtt_delete_request(r); - /* Tail might be be modified in callback, so re-read it in every iteration */ - r = *(struct mqtt_request_t * const volatile *)tail; - } else { - r->timeout_diff -= t; - t = 0; - } - } -} - -/** - * Free all request items - * @param tail Pointer to request queue tail pointer - */ -static void -mqtt_clear_requests(struct mqtt_request_t **tail) -{ - struct mqtt_request_t *iter, *next; - LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL); - for (iter = *tail; iter != NULL; iter = next) { - next = iter->next; - mqtt_delete_request(iter); - } - *tail = NULL; -} -/** - * Initialize all request items - * @param r_objs Pointer to request objects - */ -static void -mqtt_init_requests(struct mqtt_request_t *r_objs) -{ - u8_t n; - LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL); - for (n = 0; n < MQTT_REQ_MAX_IN_FLIGHT; n++) { - /* Item pointing to itself indicates unused */ - r_objs[n].next = &r_objs[n]; - } -} - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Output message build helpers */ - - -static void -mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value) -{ - mqtt_ringbuf_put(rb, value); -} - -static -void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value) -{ - mqtt_ringbuf_put(rb, value >> 8); - mqtt_ringbuf_put(rb, value & 0xff); -} - -static void -mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length) -{ - u16_t n; - for (n = 0; n < length; n++) { - mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]); - } -} - -static void -mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length) -{ - u16_t n; - mqtt_ringbuf_put(rb, length >> 8); - mqtt_ringbuf_put(rb, length & 0xff); - for (n = 0; n < length; n++) { - mqtt_ringbuf_put(rb, str[n]); - } -} - -/** - * Append fixed header - * @param rb Output ring buffer - * @param msg_type see enum mqtt_message_type - * @param dup MQTT DUP flag - * @param qos MQTT QoS field - * @param retain MQTT retain flag - * @param r_length Remaining length after fixed header - */ - -static void -mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t dup, - u8_t qos, u8_t retain, u16_t r_length) -{ - /* Start with control byte */ - mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1))); - /* Encode remaining length field */ - do { - mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0)); - r_length >>= 7; - } while (r_length > 0); -} - - -/** - * Check output buffer space - * @param rb Output ring buffer - * @param r_length Remaining length after fixed header - * @return 1 if message will fit, 0 if not enough buffer space - */ -static u8_t -mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length) -{ - /* Start with length of type byte + remaining length */ - u16_t total_len = 1 + r_length; - - LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL); - - /* Calculate number of required bytes to contain the remaining bytes field and add to total*/ - do { - total_len++; - r_length >>= 7; - } while (r_length > 0); - - return (total_len <= mqtt_ringbuf_free(rb)); -} - - -/** - * Close connection to server - * @param client MQTT client - * @param reason Reason for disconnection - */ -static void -mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason) -{ - LWIP_ASSERT("mqtt_close: client != NULL", client != NULL); - - /* Bring down TCP connection if not already done */ - if (client->conn != NULL) { - err_t res; - tcp_recv(client->conn, NULL); - tcp_err(client->conn, NULL); - tcp_sent(client->conn, NULL); - res = tcp_close(client->conn); - if (res != ERR_OK) { - tcp_abort(client->conn); - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_close: Close err=%s\n", lwip_strerr(res))); - } - client->conn = NULL; - } - - /* Remove all pending requests */ - mqtt_clear_requests(&client->pend_req_queue); - /* Stop cyclic timer */ - sys_untimeout(mqtt_cyclic_timer, client); - - /* Notify upper layer of disconnection if changed state */ - if (client->conn_state != TCP_DISCONNECTED) { - - client->conn_state = TCP_DISCONNECTED; - if (client->connect_cb != NULL) { - client->connect_cb(client, client->connect_arg, reason); - } - } -} - - -/** - * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states - * @param arg MQTT client - */ -static void -mqtt_cyclic_timer(void *arg) -{ - u8_t restart_timer = 1; - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL); - - if (client->conn_state == MQTT_CONNECTING) { - client->cyclic_tick++; - if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: CONNECT attempt to server timed out\n")); - /* Disconnect TCP */ - mqtt_close(client, MQTT_CONNECT_TIMEOUT); - restart_timer = 0; - } - } else if (client->conn_state == MQTT_CONNECTED) { - /* Handle timeout for pending requests */ - mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL); - - /* keep_alive > 0 means keep alive functionality shall be used */ - if (client->keep_alive > 0) { - - client->server_watchdog++; - /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */ - if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive/2)) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Server incoming keep-alive timeout\n")); - mqtt_close(client, MQTT_CONNECT_TIMEOUT); - restart_timer = 0; - } - - /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */ - if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_cyclic_timer: Sending keep-alive message to server\n")); - if (mqtt_output_check_space(&client->output, 0) != 0) { - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0); - client->cyclic_tick = 0; - } - } else { - client->cyclic_tick++; - } - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state)); - restart_timer = 0; - } - if (restart_timer) { - sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, arg); - } -} - - -/** - * Send PUBACK, PUBREC or PUBREL response message - * @param client MQTT client - * @param msg PUBACK, PUBREC or PUBREL - * @param pkt_id Packet identifier - * @param qos QoS value - * @return ERR_OK if successful, ERR_MEM if out of memory - */ -static err_t -pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos) -{ - err_t err = ERR_OK; - if (mqtt_output_check_space(&client->output, 2)) { - mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2); - mqtt_output_append_u16(&client->output, pkt_id); - mqtt_output_send(&client->output, client->conn); - } else { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n", - mqtt_msg_type_to_str(msg), pkt_id)); - err = ERR_MEM; - } - return err; -} - -/** - * Subscribe response from server - * @param r Matching request - * @param result Result code from server - */ -static void -mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result) -{ - if (r->cb != NULL) { - r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT); - } -} - - -/** - * Complete MQTT message received or buffer full - * @param client MQTT client - * @param fixed_hdr_idx header index - * @param length length received part - * @param remaining_length Remaining length of complete message - */ -static mqtt_connection_status_t - mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length) -{ - mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; - - u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx; - - /* Control packet type */ - u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]); - u16_t pkt_id = 0; - - if (pkt_type == MQTT_MSG_TYPE_CONNACK) { - if (client->conn_state == MQTT_CONNECTING) { - /* Get result code from CONNACK */ - res = (mqtt_connection_status_t)var_hdr_payload[1]; - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: Connect response code %d\n", res)); - if (res == MQTT_CONNECT_ACCEPTED) { - /* Reset cyclic_tick when changing to connected state */ - client->cyclic_tick = 0; - client->conn_state = MQTT_CONNECTED; - /* Notify upper layer */ - if (client->connect_cb != 0) { - client->connect_cb(client, client->connect_arg, res); - } - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Received CONNACK in connected state\n")); - } - } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,( "mqtt_message_received: Received PINGRESP from server\n")); - - } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) { - u16_t payload_offset = 0; - u16_t payload_length = length; - u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]); - - if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) { - /* Should have topic and pkt id*/ - uint8_t *topic; - uint16_t after_topic; - u8_t bkp; - u16_t topic_len = var_hdr_payload[0]; - topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]); - - topic = var_hdr_payload + 2; - after_topic = 2 + topic_len; - /* Check length, add one byte even for QoS 0 so that zero termination will fit */ - if ((after_topic + (qos? 2 : 1)) > length) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); - goto out_disconnect; - } - - /* id for QoS 1 and 2 */ - if (qos > 0) { - client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1]; - after_topic += 2; - } else { - client->inpub_pkt_id = 0; - } - /* Take backup of byte after topic */ - bkp = topic[topic_len]; - /* Zero terminate string */ - topic[topic_len] = 0; - /* Payload data remaining in receive buffer */ - payload_length = length - after_topic; - payload_offset = after_topic; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %d\n", - qos, topic, remaining_length + payload_length)); - if (client->pub_cb != NULL) { - client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length); - } - /* Restore byte after topic */ - topic[topic_len] = bkp; - } - if (payload_length > 0 || remaining_length == 0) { - client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0); - /* Reply if QoS > 0 */ - if (remaining_length == 0 && qos > 0) { - /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */ - u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n", - mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id)); - pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0); - } - } - } else { - /* Get packet identifier */ - pkt_id = (u16_t)var_hdr_payload[0] << 8; - pkt_id |= (u16_t)var_hdr_payload[1]; - if (pkt_id == 0) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: Got message with illegal packet identifier: 0\n")); - goto out_disconnect; - } - if (pkt_type == MQTT_MSG_TYPE_PUBREC) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n",pkt_id)); - pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1); - - } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n",pkt_id)); - pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0); - - } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK || - pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) { - struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id); - if (r != NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); - if (pkt_type == MQTT_MSG_TYPE_SUBACK) { - if (length < 3) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_message_received: To small SUBACK packet\n")); - goto out_disconnect; - } else { - mqtt_incomming_suback(r, var_hdr_payload[2]); - } - } else if (r->cb != NULL) { - r->cb(r->arg, ERR_OK); - } - mqtt_delete_request(r); - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received unknown message type: %d\n", pkt_type)); - goto out_disconnect; - } - } - return res; -out_disconnect: - return MQTT_CONNECT_DISCONNECTED; -} - - -/** - * MQTT incoming message parser - * @param client MQTT client - * @param p PBUF chain of received data - * @return Connection status - */ -static mqtt_connection_status_t -mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p) -{ - u16_t in_offset = 0; - u32_t msg_rem_len = 0; - u8_t fixed_hdr_idx = 0; - u8_t b = 0; - - while (p->tot_len > in_offset) { - if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) { - - if (fixed_hdr_idx < client->msg_idx) { - b = client->rx_buffer[fixed_hdr_idx]; - } else { - b = pbuf_get_at(p, in_offset++); - client->rx_buffer[client->msg_idx++] = b; - } - fixed_hdr_idx++; - - if (fixed_hdr_idx >= 2) { - msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7); - if ((b & 0x80) == 0) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: Remaining length after fixed header: %d\n", msg_rem_len)); - if (msg_rem_len == 0) { - /* Complete message with no extra headers of payload received */ - mqtt_message_received(client, fixed_hdr_idx, 0, 0); - client->msg_idx = 0; - fixed_hdr_idx = 0; - } else { - /* Bytes remaining in message */ - msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx; - } - } - } - } else { - u16_t cpy_len, cpy_start, buffer_space; - - cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx; - - /* Allow to copy the lesser one of available length in input data or bytes remaining in message */ - cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len); - - /* Limit to available space in buffer */ - buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start; - if (cpy_len > buffer_space) { - cpy_len = buffer_space; - } - pbuf_copy_partial(p, client->rx_buffer+cpy_start, cpy_len, in_offset); - - /* Advance get and put indexes */ - client->msg_idx += cpy_len; - in_offset += cpy_len; - msg_rem_len -= cpy_len; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_parse_incoming: msg_idx: %d, cpy_len: %d, remaining %d\n", client->msg_idx, cpy_len, msg_rem_len)); - if (msg_rem_len == 0 || cpy_len == buffer_space) { - /* Whole message received or buffer is full */ - mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len); - if (res != MQTT_CONNECT_ACCEPTED) { - return res; - } - if (msg_rem_len == 0) { - /* Reset parser state */ - client->msg_idx = 0; - /* msg_tot_len = 0; */ - fixed_hdr_idx = 0; - } - } - } - } - return MQTT_CONNECT_ACCEPTED; -} - - -/** - * TCP received callback function. @see tcp_recv_fn - * @param arg MQTT client - * @param p PBUF chain of received data - * @param err Passed as return value if not ERR_OK - * @return ERR_OK or err passed into callback - */ -static err_t -mqtt_tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL); - LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb); - - if (p == NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n")); - mqtt_close(client, MQTT_CONNECT_DISCONNECTED); - } else { - mqtt_connection_status_t res; - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_recv_cb: Recv err=%d\n", err)); - pbuf_free(p); - return err; - } - - /* Tell remote that data has been received */ - tcp_recved(pcb, p->tot_len); - res = mqtt_parse_incoming(client, p); - pbuf_free(p); - - if (res != MQTT_CONNECT_ACCEPTED) { - mqtt_close(client, res); - } - /* If keep alive functionality is used */ - if (client->keep_alive != 0) { - /* Reset server alive watchdog */ - client->server_watchdog = 0; - } - - } - return ERR_OK; -} - - -/** - * TCP data sent callback function. @see tcp_sent_fn - * @param arg MQTT client - * @param tpcb TCP connection handle - * @param len Number of bytes sent - * @return ERR_OK - */ -static err_t -mqtt_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - - LWIP_UNUSED_ARG(tpcb); - LWIP_UNUSED_ARG(len); - - if (client->conn_state == MQTT_CONNECTED) { - struct mqtt_request_t *r; - - /* Reset keep-alive send timer and server watchdog */ - client->cyclic_tick = 0; - client->server_watchdog = 0; - /* QoS 0 publish has no response from server, so call its callbacks here */ - while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n")); - if (r->cb != NULL) { - r->cb(r->arg, ERR_OK); - } - mqtt_delete_request(r); - } - /* Try send any remaining buffers from output queue */ - mqtt_output_send(&client->output, client->conn); - } - return ERR_OK; -} - -/** - * TCP error callback function. @see tcp_err_fn - * @param arg MQTT client - * @param err Error encountered - */ -static void -mqtt_tcp_err_cb(void *arg, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_UNUSED_ARG(err); /* only used for debug output */ - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg)); - LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL); - /* Set conn to null before calling close as pcb is already deallocated*/ - client->conn = 0; - mqtt_close(client, MQTT_CONNECT_DISCONNECTED); -} - -/** - * TCP poll callback function. @see tcp_poll_fn - * @param arg MQTT client - * @param tpcb TCP connection handle - * @return err ERR_OK - */ -static err_t -mqtt_tcp_poll_cb(void *arg, struct tcp_pcb *tpcb) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - if (client->conn_state == MQTT_CONNECTED) { - /* Try send any remaining buffers from output queue */ - mqtt_output_send(&client->output, tpcb); - } - return ERR_OK; -} - -/** - * TCP connect callback function. @see tcp_connected_fn - * @param arg MQTT client - * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error - * @return ERR_OK - */ -static err_t -mqtt_tcp_connect_cb(void *arg, struct tcp_pcb *tpcb, err_t err) -{ - mqtt_client_t* client = (mqtt_client_t *)arg; - - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_tcp_connect_cb: TCP connect error %d\n", err)); - return err; - } - - /* Initiate receiver state */ - client->msg_idx = 0; - - /* Setup TCP callbacks */ - tcp_recv(tpcb, mqtt_tcp_recv_cb); - tcp_sent(tpcb, mqtt_tcp_sent_cb); - tcp_poll(tpcb, mqtt_tcp_poll_cb, 2); - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_tcp_connect_cb: TCP connection established to server\n")); - /* Enter MQTT connect state */ - client->conn_state = MQTT_CONNECTING; - - /* Start cyclic timer */ - sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL*1000, mqtt_cyclic_timer, client); - client->cyclic_tick = 0; - - /* Start transmission from output queue, connect message is the first one out*/ - mqtt_output_send(&client->output, client->conn); - - return ERR_OK; -} - - - -/*---------------------------------------------------------------------------------------------------- */ -/* Public API */ - - -/** - * @ingroup mqtt - * MQTT publish function. - * @param client MQTT client - * @param topic Publish topic string - * @param payload Data to publish (NULL is allowed) - * @param payload_length: Length of payload (0 is allowed) - * @param qos Quality of service, 0 1 or 2 - * @param retain MQTT retain flag - * @param cb Callback to call when publish is complete or has timed out - * @param arg User supplied argument to publish callback - * @return ERR_OK if successful - * ERR_CONN if client is disconnected - * ERR_MEM if short on memory - */ -err_t -mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, - mqtt_request_cb_t cb, void *arg) -{ - struct mqtt_request_t *r; - u16_t pkt_id; - size_t topic_strlen; - size_t total_len; - u16_t topic_len; - u16_t remaining_length; - - LWIP_ASSERT("mqtt_publish: client != NULL", client); - LWIP_ASSERT("mqtt_publish: topic != NULL", topic); - LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN); - - topic_strlen = strlen(topic); - LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); - topic_len = (u16_t)topic_strlen; - total_len = 2 + topic_len + payload_length; - LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); - remaining_length = (u16_t)total_len; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic)); - - if (qos > 0) { - remaining_length += 2; - /* Generate pkt_id id for QoS1 and 2 */ - pkt_id = msg_generate_packet_id(client); - } else { - /* Use reserved value pkt_id 0 for QoS 0 in request handle */ - pkt_id = 0; - } - - r = mqtt_create_request(client->req_list, pkt_id, cb, arg); - if (r == NULL) { - return ERR_MEM; - } - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - mqtt_delete_request(r); - return ERR_MEM; - } - /* Append fixed header */ - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length); - - /* Append Topic */ - mqtt_output_append_string(&client->output, topic, topic_len); - - /* Append packet if for QoS 1 and 2*/ - if (qos > 0) { - mqtt_output_append_u16(&client->output, pkt_id); - } - - /* Append optional publish payload */ - if ((payload != NULL) && (payload_length > 0)) { - mqtt_output_append_buf(&client->output, payload, payload_length); - } - - mqtt_append_request(&client->pend_req_queue, r); - mqtt_output_send(&client->output, client->conn); - return ERR_OK; -} - - -/** - * @ingroup mqtt - * MQTT subscribe/unsubscribe function. - * @param client MQTT client - * @param topic topic to subscribe to - * @param qos Quality of service, 0 1 or 2 (only used for subscribe) - * @param cb Callback to call when subscribe/unsubscribe reponse is received - * @param arg User supplied argument to publish callback - * @param sub 1 for subscribe, 0 for unsubscribe - * @return ERR_OK if successful, @see err_t enum for other results - */ -err_t -mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub) -{ - size_t topic_strlen; - size_t total_len; - u16_t topic_len; - u16_t remaining_length; - u16_t pkt_id; - struct mqtt_request_t *r; - - LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client); - LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic); - - topic_strlen = strlen(topic); - LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); - topic_len = (u16_t)topic_strlen; - /* Topic string, pkt_id, qos for subscribe */ - total_len = topic_len + 2 + 2 + (sub != 0); - LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); - remaining_length = (u16_t)total_len; - - LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3); - if (client->conn_state == TCP_DISCONNECTED) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n")); - return ERR_CONN; - } - - pkt_id = msg_generate_packet_id(client); - r = mqtt_create_request(client->req_list, pkt_id, cb, arg); - if (r == NULL) { - return ERR_MEM; - } - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - mqtt_delete_request(r); - return ERR_MEM; - } - - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id)); - - mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length); - /* Packet id */ - mqtt_output_append_u16(&client->output, pkt_id); - /* Topic */ - mqtt_output_append_string(&client->output, topic, topic_len); - /* QoS */ - if (sub != 0) { - mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2)); - } - - mqtt_append_request(&client->pend_req_queue, r); - mqtt_output_send(&client->output, client->conn); - return ERR_OK; -} - - -/** - * @ingroup mqtt - * Set callback to handle incoming publish requests from server - * @param client MQTT client - * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload - * @param data_cb Callback for each fragment of payload that arrives - * @param arg User supplied argument to both callbacks - */ -void -mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, - mqtt_incoming_data_cb_t data_cb, void *arg) -{ - LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL); - client->data_cb = data_cb; - client->pub_cb = pub_cb; - client->inpub_arg = arg; -} - -/** - * @ingroup mqtt - * Create a new MQTT client instance - * @return Pointer to instance on success, NULL otherwise - */ -mqtt_client_t * -mqtt_client_new(void) -{ - mqtt_client_t *client = (mqtt_client_t *)mem_malloc(sizeof(mqtt_client_t)); - if (client != NULL) { - memset(client, 0, sizeof(mqtt_client_t)); - } - return client; -} - - -/** - * @ingroup mqtt - * Connect to MQTT server - * @param client MQTT client - * @param ip_addr Server IP - * @param port Server port - * @param cb Connection state change callback - * @param arg User supplied argument to connection callback - * @param client_info Client identification and connection options - * @return ERR_OK if successful, @see err_t enum for other results - */ -err_t -mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg, - const struct mqtt_connect_client_info_t *client_info) -{ - err_t err; - size_t len; - u16_t client_id_length; - /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */ - u16_t remaining_length = 2 + 4 + 1 + 1 + 2; - u8_t flags = 0, will_topic_len = 0, will_msg_len = 0; - - LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL); - LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL); - LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL); - LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL); - - if (client->conn_state != TCP_DISCONNECTED) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n")); - return ERR_ISCONN; - } - - /* Wipe clean */ - memset(client, 0, sizeof(mqtt_client_t)); - client->connect_arg = arg; - client->connect_cb = cb; - client->keep_alive = client_info->keep_alive; - mqtt_init_requests(client->req_list); - - /* Build connect message */ - if (client_info->will_topic != NULL && client_info->will_msg != NULL) { - flags |= MQTT_CONNECT_FLAG_WILL; - flags |= (client_info->will_qos & 3) << 3; - if (client_info->will_retain) { - flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; - } - len = strlen(client_info->will_topic); - LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL); - will_topic_len = (u8_t)len; - len = strlen(client_info->will_msg); - LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); - will_msg_len = (u8_t)len; - len = remaining_length + 2 + will_topic_len + 2 + will_msg_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - - /* Don't complicate things, always connect using clean session */ - flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; - - len = strlen(client_info->client_id); - LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL); - client_id_length = (u16_t)len; - len = remaining_length + 2 + client_id_length; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - return ERR_MEM; - } - - client->conn = tcp_new(); - if (client->conn == NULL) { - return ERR_MEM; - } - - /* Set arg pointer for callbacks */ - tcp_arg(client->conn, client); - /* Any local address, pick random local port number */ - err = tcp_bind(client->conn, IP_ADDR_ANY, 0); - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n", err)); - goto tcp_fail; - } - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port)); - - /* Connect to server */ - err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb); - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err)); - goto tcp_fail; - } - /* Set error callback */ - tcp_err(client->conn, mqtt_tcp_err_cb); - client->conn_state = TCP_CONNECTING; - - /* Append fixed header */ - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length); - /* Append Protocol string */ - mqtt_output_append_string(&client->output, "MQTT", 4); - /* Append Protocol level */ - mqtt_output_append_u8(&client->output, 4); - /* Append connect flags */ - mqtt_output_append_u8(&client->output, flags); - /* Append keep-alive */ - mqtt_output_append_u16(&client->output, client_info->keep_alive); - /* Append client id */ - mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); - /* Append will message if used */ - if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) { - mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); - mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); - } - return ERR_OK; - -tcp_fail: - tcp_abort(client->conn); - client->conn = NULL; - return err; -} - - -/** - * @ingroup mqtt - * Disconnect from MQTT server - * @param client MQTT client - */ -void -mqtt_disconnect(mqtt_client_t *client) -{ - LWIP_ASSERT("mqtt_disconnect: client != NULL", client); - /* If connection in not already closed */ - if (client->conn_state != TCP_DISCONNECTED) { - /* Set conn_state before calling mqtt_close to prevent callback from being called */ - client->conn_state = TCP_DISCONNECTED; - mqtt_close(client, (mqtt_connection_status_t)0); - } -} - -/** - * @ingroup mqtt - * Check connection with server - * @param client MQTT client - * @return 1 if connected to server, 0 otherwise - */ -u8_t -mqtt_client_is_connected(mqtt_client_t *client) -{ - LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); - return client->conn_state == MQTT_CONNECTED; -} - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/components/net/lwip-2.0.2/src/apps/netbiosns/netbiosns.c b/components/net/lwip-2.0.2/src/apps/netbiosns/netbiosns.c deleted file mode 100644 index 2dfbe65901..0000000000 --- a/components/net/lwip-2.0.2/src/apps/netbiosns/netbiosns.c +++ /dev/null @@ -1,367 +0,0 @@ -/** - * @file - * NetBIOS name service responder - */ - -/** - * @defgroup netbiosns NETBIOS responder - * @ingroup apps - * - * This is an example implementation of a NetBIOS name server. - * It responds to name queries for a configurable name. - * Name resolving is not supported. - * - * Note that the device doesn't broadcast it's own name so can't - * detect duplicate names! - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/apps/netbiosns.h" - -#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/udp.h" -#include "lwip/netif.h" - -#include - -/** default port number for "NetBIOS Name service */ -#define NETBIOS_PORT 137 - -/** size of a NetBIOS name */ -#define NETBIOS_NAME_LEN 16 - -/** The Time-To-Live for NetBIOS name responds (in seconds) - * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ -#define NETBIOS_NAME_TTL 300000u - -/** NetBIOS header flags */ -#define NETB_HFLAG_RESPONSE 0x8000U -#define NETB_HFLAG_OPCODE 0x7800U -#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U -#define NETB_HFLAG_AUTHORATIVE 0x0400U -#define NETB_HFLAG_TRUNCATED 0x0200U -#define NETB_HFLAG_RECURS_DESIRED 0x0100U -#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U -#define NETB_HFLAG_BROADCAST 0x0010U -#define NETB_HFLAG_REPLYCODE 0x0008U -#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U - -/** NetBIOS name flags */ -#define NETB_NFLAG_UNIQUE 0x8000U -#define NETB_NFLAG_NODETYPE 0x6000U -#define NETB_NFLAG_NODETYPE_HNODE 0x6000U -#define NETB_NFLAG_NODETYPE_MNODE 0x4000U -#define NETB_NFLAG_NODETYPE_PNODE 0x2000U -#define NETB_NFLAG_NODETYPE_BNODE 0x0000U - -/** NetBIOS message header */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_hdr { - PACK_STRUCT_FIELD(u16_t trans_id); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FIELD(u16_t questions); - PACK_STRUCT_FIELD(u16_t answerRRs); - PACK_STRUCT_FIELD(u16_t authorityRRs); - PACK_STRUCT_FIELD(u16_t additionalRRs); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message name part */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_name_hdr { - PACK_STRUCT_FLD_8(u8_t nametype); - PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]); - PACK_STRUCT_FIELD(u16_t type); - PACK_STRUCT_FIELD(u16_t cls); - PACK_STRUCT_FIELD(u32_t ttl); - PACK_STRUCT_FIELD(u16_t datalen); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FLD_S(ip4_addr_p_t addr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_resp -{ - struct netbios_hdr resp_hdr; - struct netbios_name_hdr resp_name; -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef NETBIOS_LWIP_NAME -#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME -#else -static char netbiosns_local_name[NETBIOS_NAME_LEN]; -#define NETBIOS_LOCAL_NAME netbiosns_local_name -#endif - -struct udp_pcb *netbiosns_pcb; - -/** Decode a NetBIOS name (from packet to string) */ -static int -netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) -{ - char *pname; - char cname; - char cnbname; - int idx = 0; - - LWIP_UNUSED_ARG(name_dec_len); - - /* Start decoding netbios name. */ - pname = name_enc; - for (;;) { - /* Every two characters of the first level-encoded name - * turn into one character in the decoded name. */ - cname = *pname; - if (cname == '\0') - break; /* no more characters */ - if (cname == '.') - break; /* scope ID follows */ - if (cname < 'A' || cname > 'Z') { - /* Not legal. */ - return -1; - } - cname -= 'A'; - cnbname = cname << 4; - pname++; - - cname = *pname; - if (cname == '\0' || cname == '.') { - /* No more characters in the name - but we're in - * the middle of a pair. Not legal. */ - return -1; - } - if (cname < 'A' || cname > 'Z') { - /* Not legal. */ - return -1; - } - cname -= 'A'; - cnbname |= cname; - pname++; - - /* Do we have room to store the character? */ - if (idx < NETBIOS_NAME_LEN) { - /* Yes - store the character. */ - name_dec[idx++] = (cnbname!=' '?cnbname:'\0'); - } - } - - return 0; -} - -#if 0 /* function currently unused */ -/** Encode a NetBIOS name (from string to packet) - currently unused because - we don't ask for names. */ -static int -netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) -{ - char *pname; - char cname; - unsigned char ucname; - int idx = 0; - - /* Start encoding netbios name. */ - pname = name_enc; - - for (;;) { - /* Every two characters of the first level-encoded name - * turn into one character in the decoded name. */ - cname = *pname; - if (cname == '\0') - break; /* no more characters */ - if (cname == '.') - break; /* scope ID follows */ - if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { - /* Not legal. */ - return -1; - } - - /* Do we have room to store the character? */ - if (idx >= name_dec_len) { - return -1; - } - - /* Yes - store the character. */ - ucname = cname; - name_dec[idx++] = ('A'+((ucname>>4) & 0x0F)); - name_dec[idx++] = ('A'+( ucname & 0x0F)); - pname++; - } - - /* Fill with "space" coding */ - for (;idx < name_dec_len - 1;) { - name_dec[idx++] = 'C'; - name_dec[idx++] = 'A'; - } - - /* Terminate string */ - name_dec[idx] = '\0'; - - return 0; -} -#endif /* 0 */ - -/** NetBIOS Name service recv callback */ -static void -netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - LWIP_UNUSED_ARG(arg); - - /* if packet is valid */ - if (p != NULL) { - char netbios_name[NETBIOS_NAME_LEN+1]; - struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload; - struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1); - - /* we only answer if we got a default interface */ - if (netif_default != NULL) { - /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ - /* if the packet is a NetBIOS name query question */ - if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && - ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && - (netbios_hdr->questions == PP_NTOHS(1))) { - /* decode the NetBIOS name */ - netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); - /* if the packet is for us */ - if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { - struct pbuf *q; - struct netbios_resp *resp; - - q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); - if (q != NULL) { - resp = (struct netbios_resp*)q->payload; - - /* prepare NetBIOS header response */ - resp->resp_hdr.trans_id = netbios_hdr->trans_id; - resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | - NETB_HFLAG_OPCODE_NAME_QUERY | - NETB_HFLAG_AUTHORATIVE | - NETB_HFLAG_RECURS_DESIRED); - resp->resp_hdr.questions = 0; - resp->resp_hdr.answerRRs = PP_HTONS(1); - resp->resp_hdr.authorityRRs = 0; - resp->resp_hdr.additionalRRs = 0; - - /* prepare NetBIOS header datas */ - MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); - resp->resp_name.nametype = netbios_name_hdr->nametype; - resp->resp_name.type = netbios_name_hdr->type; - resp->resp_name.cls = netbios_name_hdr->cls; - resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); - resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr)); - resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); - ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); - - /* send the NetBIOS response */ - udp_sendto(upcb, q, addr, port); - - /* free the "reference" pbuf */ - pbuf_free(q); - } - } - } - } - /* free the pbuf */ - pbuf_free(p); - } -} - -/** - * @ingroup netbiosns - * Init netbios responder - */ -void -netbiosns_init(void) -{ -#ifdef NETBIOS_LWIP_NAME - LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); -#endif - - netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (netbiosns_pcb != NULL) { - /* we have to be allowed to send broadcast packets! */ - ip_set_option(netbiosns_pcb, SOF_BROADCAST); - udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); - udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); - } -} - -#ifndef NETBIOS_LWIP_NAME -/** - * @ingroup netbiosns - * Set netbios name. ATTENTION: the hostname must be less than 15 characters! - */ -void -netbiosns_set_name(const char* hostname) -{ - size_t copy_len = strlen(hostname); - LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); - if (copy_len >= NETBIOS_NAME_LEN) { - copy_len = NETBIOS_NAME_LEN - 1; - } - MEMCPY(netbiosns_local_name, hostname, copy_len + 1); -} -#endif - -/** - * @ingroup netbiosns - * Stop netbios responder - */ -void -netbiosns_stop(void) -{ - if (netbiosns_pcb != NULL) { - udp_remove(netbiosns_pcb); - netbiosns_pcb = NULL; - } -} - -#endif /* LWIP_IPV4 && LWIP_UDP */ diff --git a/components/net/lwip-2.0.2/src/apps/ping/ping.c b/components/net/lwip-2.0.2/src/apps/ping/ping.c deleted file mode 100644 index 6251504f59..0000000000 --- a/components/net/lwip-2.0.2/src/apps/ping/ping.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * netutils: ping implementation - */ - -#include - -#ifdef RT_LWIP_ICMP /* don't build if not configured for use in rtconfig.h */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * PING_DEBUG: Enable debugging for PING. - */ -#ifndef PING_DEBUG -#define PING_DEBUG LWIP_DBG_ON -#endif - -/** ping receive timeout - in milliseconds */ -#define PING_RCV_TIMEO (2 * RT_TICK_PER_SECOND) -/** ping delay - in milliseconds */ -#define PING_DELAY (1 * RT_TICK_PER_SECOND) - -/** ping identifier - must fit on a u16_t */ -#ifndef PING_ID -#define PING_ID 0xAFAF -#endif - -/** ping additional data size to include in the packet */ -#ifndef PING_DATA_SIZE -#define PING_DATA_SIZE 32 -#endif - -/* ping variables */ -static u16_t ping_seq_num; -struct _ip_addr -{ - rt_uint8_t addr0, addr1, addr2, addr3; -}; - -/** Prepare a echo ICMP request */ -static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) -{ - size_t i; - size_t data_len = len - sizeof(struct icmp_echo_hdr); - - ICMPH_TYPE_SET(iecho, ICMP_ECHO); - ICMPH_CODE_SET(iecho, 0); - iecho->chksum = 0; - iecho->id = PING_ID; - iecho->seqno = htons(++ping_seq_num); - - /* fill the additional data buffer with some data */ - for (i = 0; i < data_len; i++) - { - ((char*) iecho)[sizeof(struct icmp_echo_hdr) + i] = (char) i; - } - -#ifdef RT_LWIP_USING_HW_CHECKSUM - iecho->chksum = 0; -#else - iecho->chksum = inet_chksum(iecho, len); -#endif - -} - -/* Ping using the socket ip */ -err_t lwip_ping_send(int s, ip_addr_t *addr, int size) -{ - int err; - struct icmp_echo_hdr *iecho; - struct sockaddr_in to; - int ping_size = sizeof(struct icmp_echo_hdr) + size; - LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); - - iecho = rt_malloc(ping_size); - if (iecho == RT_NULL) - { - return ERR_MEM; - } - - ping_prepare_echo(iecho, (u16_t) ping_size); - - to.sin_len = sizeof(to); - to.sin_family = AF_INET; -#if LWIP_IPV4 && LWIP_IPV6 - to.sin_addr.s_addr = addr->u_addr.ip4.addr; -#elif LWIP_IPV4 - to.sin_addr.s_addr = addr->addr; -#elif LWIP_IPV6 -#error Not supported IPv6. -#endif - - err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*) &to, sizeof(to)); - rt_free(iecho); - - return (err == ping_size ? ERR_OK : ERR_VAL); -} - -int lwip_ping_recv(int s, int *ttl) -{ - char buf[64]; - int fromlen = sizeof(struct sockaddr_in), len; - struct sockaddr_in from; - struct ip_hdr *iphdr; - struct icmp_echo_hdr *iecho; - - while ((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*) &from, (socklen_t*) &fromlen)) > 0) - { - if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) - { - iphdr = (struct ip_hdr *) buf; - iecho = (struct icmp_echo_hdr *) (buf + (IPH_HL(iphdr) * 4)); - if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) - { - *ttl = iphdr->_ttl; - return len; - } - } - } - - return len; -} - -#ifndef RT_USING_NETDEV - -/* using the lwIP custom ping */ -rt_err_t ping(char* target_name, rt_uint32_t times, rt_size_t size) -{ -#if LWIP_VERSION_MAJOR >= 2U - struct timeval timeout = { PING_RCV_TIMEO / RT_TICK_PER_SECOND, PING_RCV_TIMEO % RT_TICK_PER_SECOND }; -#else - int timeout = PING_RCV_TIMEO * 1000UL / RT_TICK_PER_SECOND; -#endif - - int s, ttl, recv_len; - ip_addr_t target_addr; - rt_uint32_t send_times; - rt_tick_t recv_start_tick; - struct addrinfo hint, *res = NULL; - struct sockaddr_in *h = NULL; - struct in_addr ina; - - send_times = 0; - ping_seq_num = 0; - - if (size == 0) - { - size = PING_DATA_SIZE; - } - - memset(&hint, 0, sizeof(hint)); - /* convert URL to IP */ - if (lwip_getaddrinfo(target_name, NULL, &hint, &res) != 0) - { - rt_kprintf("ping: unknown host %s\n", target_name); - return -RT_ERROR; - } - memcpy(&h, &res->ai_addr, sizeof(struct sockaddr_in *)); - memcpy(&ina, &h->sin_addr, sizeof(ina)); - lwip_freeaddrinfo(res); - if (inet_aton(inet_ntoa(ina), &target_addr) == 0) - { - rt_kprintf("ping: unknown host %s\n", target_name); - return -RT_ERROR; - } - /* new a socket */ - if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) - { - rt_kprintf("ping: create socket failed\n"); - return -RT_ERROR; - } - - lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - - while (1) - { - int elapsed_time; - - if (lwip_ping_send(s, &target_addr, size) == ERR_OK) - { - recv_start_tick = rt_tick_get(); - if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) - { - elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND; - rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", recv_len, inet_ntoa(ina), send_times, - ttl, elapsed_time); - } - else - { - rt_kprintf("From %s icmp_seq=%d timeout\n", inet_ntoa(ina), send_times); - } - } - else - { - rt_kprintf("Send %s - error\n", inet_ntoa(ina)); - } - - send_times++; - if (send_times >= times) - { - /* send ping times reached, stop */ - break; - } - - rt_thread_delay(PING_DELAY); /* take a delay */ - } - - lwip_close(s); - - return RT_EOK; -} -#ifdef RT_USING_FINSH -#include - -FINSH_FUNCTION_EXPORT(ping, ping network host); - -int cmd_ping(int argc, char **argv) -{ - if (argc == 1) - { - rt_kprintf("Please input: ping \n"); - } - else - { - ping(argv[1], 4, 0); - } - - return 0; -} -MSH_CMD_EXPORT_ALIAS(cmd_ping, ping, ping network host); -#endif /* RT_USING_FINSH */ - -#endif /* RT_USING_NETDEV */ - -#endif /* RT_LWIP_ICMP */ - diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.c deleted file mode 100644 index f35b760462..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.c +++ /dev/null @@ -1,749 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) encoding - * - * @todo not optimised (yet), favor correctness over speed, favor speed over size - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_asn1.h" - -#define PBUF_OP_EXEC(code) \ - if ((code) != ERR_OK) { \ - return ERR_BUF; \ - } - -/** - * Encodes a TLV into a pbuf stream. - * - * @param pbuf_stream points to a pbuf stream - * @param tlv TLV to encode - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) -{ - u8_t data; - u8_t length_bytes_required; - - /* write type */ - if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { - /* extended format is not used by SNMP so we do not accept those values */ - return ERR_ARG; - } - if (tlv->type_len != 0) { - /* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */ - return ERR_ARG; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type)); - tlv->type_len = 1; - - /* write length */ - if (tlv->value_len <= 127) { - length_bytes_required = 1; - } else if (tlv->value_len <= 255) { - length_bytes_required = 2; - } else { - length_bytes_required = 3; - } - - /* check for forced min length */ - if (tlv->length_len > 0) { - if (tlv->length_len < length_bytes_required) { - /* unable to code requested length in requested number of bytes */ - return ERR_ARG; - } - - length_bytes_required = tlv->length_len; - } else { - tlv->length_len = length_bytes_required; - } - - if (length_bytes_required > 1) { - /* multi byte representation required */ - length_bytes_required--; - data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */ - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - - while (length_bytes_required > 1) { - if (length_bytes_required == 2) { - /* append high byte */ - data = (u8_t)(tlv->value_len >> 8); - } else { - /* append leading 0x00 */ - data = 0x00; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - length_bytes_required--; - } - } - - /* append low byte */ - data = (u8_t)(tlv->value_len & 0xFF); - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - - return ERR_OK; -} - -/** - * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param raw_len raw data length - * @param raw points raw data - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len) -{ - PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len)); - - return ERR_OK; -} - -/** - * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u32t_cnt() - */ -err_t -snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value) -{ - if (octets_needed > 5) { - return ERR_ARG; - } - if (octets_needed == 5) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* (only) one least significant octet */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); - - return ERR_OK; -} - -/** - * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u64t_cnt() - */ -err_t -snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) -{ - if (octets_needed > 9) { - return ERR_ARG; - } - if (octets_needed == 9) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 4) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); - } - - /* skip to low u32 */ - value++; - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); - } - - /* always write at least one octet (also in case of value == 0) */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); - - return ERR_OK; -} - -/** - * Encodes s32_t integer into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) - * @param value is the host order s32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_s32t_cnt() - */ -err_t -snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value) -{ - while (octets_needed > 1) { - octets_needed--; - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* (only) one least significant octet */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); - - return ERR_OK; -} - -/** - * Encodes object identifier into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param oid points to object identifier array - * @param oid_len object identifier array length - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len) -{ - if (oid_len > 1) { - /* write compressed first two sub id's */ - u32_t compressed_byte = ((oid[0] * 40) + oid[1]); - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte)); - oid_len -= 2; - oid += 2; - } else { - /* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ - /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ - return ERR_ARG; - } - - while (oid_len > 0) { - u32_t sub_id; - u8_t shift, tail; - - oid_len--; - sub_id = *oid; - tail = 0; - shift = 28; - while (shift > 0) { - u8_t code; - - code = (u8_t)(sub_id >> shift); - if ((code != 0) || (tail != 0)) { - tail = 1; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80)); - } - shift -= 7; - } - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F)); - - /* proceed to next sub-identifier */ - oid++; - } - return ERR_OK; -} - -/** - * Returns octet count for length. - * - * @param length parameter length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) -{ - if (length < 0x80U) { - *octets_needed = 1; - } else if (length < 0x100U) { - *octets_needed = 2; - } else { - *octets_needed = 3; - } -} - -/** - * Returns octet count for an u32_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) -{ - if (value < 0x80UL) { - *octets_needed = 1; - } else if (value < 0x8000UL) { - *octets_needed = 2; - } else if (value < 0x800000UL) { - *octets_needed = 3; - } else if (value < 0x80000000UL) { - *octets_needed = 4; - } else { - *octets_needed = 5; - } -} - -/** - * Returns octet count for an u64_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) -{ - /* check if high u32 is 0 */ - if (*value == 0x00) { - /* only low u32 is important */ - value++; - snmp_asn1_enc_u32t_cnt(*value, octets_needed); - } else { - /* low u32 does not matter for length determination */ - snmp_asn1_enc_u32t_cnt(*value, octets_needed); - *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ - } -} - -/** - * Returns octet count for an s32_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. - */ -void -snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) -{ - if (value < 0) { - value = ~value; - } - if (value < 0x80L) { - *octets_needed = 1; - } else if (value < 0x8000L) { - *octets_needed = 2; - } else if (value < 0x800000L) { - *octets_needed = 3; - } else { - *octets_needed = 4; - } -} - -/** - * Returns octet count for an object identifier. - * - * @param oid points to object identifier array - * @param oid_len object identifier array length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed) -{ - u32_t sub_id; - - *octets_needed = 0; - if (oid_len > 1) { - /* compressed prefix in one octet */ - (*octets_needed)++; - oid_len -= 2; - oid += 2; - } - while (oid_len > 0) { - oid_len--; - sub_id = *oid; - - sub_id >>= 7; - (*octets_needed)++; - while (sub_id > 0) { - sub_id >>= 7; - (*octets_needed)++; - } - oid++; - } -} - -/** - * Decodes a TLV from a pbuf stream. - * - * @param pbuf_stream points to a pbuf stream - * @param tlv returns decoded TLV - * @return ERR_OK if successful, ERR_VAL if we can't decode - */ -err_t -snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) -{ - u8_t data; - - /* decode type first */ - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - tlv->type = data; - - if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { - /* extended format is not used by SNMP so we do not accept those values */ - return ERR_VAL; - } - tlv->type_len = 1; - - /* now, decode length */ - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (data < 0x80) { /* short form */ - tlv->length_len = 1; - tlv->value_len = data; - } else if (data > 0x80) { /* long form */ - u8_t length_bytes = data - 0x80; - tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */ - tlv->value_len = 0; - - while (length_bytes > 0) { - /* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */ - if (tlv->value_len > 0xFF) { - return ERR_VAL; - } - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - tlv->value_len <<= 8; - tlv->value_len |= data; - - /* take care for special value used for indefinite length */ - if (tlv->value_len == 0xFFFF) { - return ERR_VAL; - } - - length_bytes--; - } - } else { /* data == 0x80 indefinite length form */ - /* (not allowed for SNMP; RFC 1157, 3.2.2) */ - return ERR_VAL; - } - - return ERR_OK; -} - -/** - * Decodes positive integer (counter, gauge, timeticks) into u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) -{ - u8_t data; - - if ((len > 0) && (len <= 5)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - *value <<= 8; - *value |= data; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - -/** - * Decodes large positive integer (counter64) into 2x u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) -{ - u8_t data; - - if (len <= 4) { - /* high u32 is 0 */ - *value = 0; - /* directly skip to low u32 */ - value++; - } - - if ((len > 0) && (len <= 9)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (len == 4) { - /* skip to low u32 */ - value++; - *value = 0; - } else { - *value <<= 8; - } - - *value |= data; - len--; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - -/** - * Decodes integer into s32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed! - */ -err_t -snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value) -{ -#if BYTE_ORDER == LITTLE_ENDIAN - u8_t *lsb_ptr = (u8_t*)value; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; -#endif - u8_t sign; - u8_t data; - - if ((len > 0) && (len < 5)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - if (data & 0x80) { - /* negative, start from -1 */ - *value = -1; - sign = 1; - *lsb_ptr &= data; - } else { - /* positive, start from 0 */ - *value = 0; - sign = 0; - *lsb_ptr |= data; - } - - /* OR/AND octets with value */ - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - -#if BYTE_ORDER == LITTLE_ENDIAN - *value <<= 8; -#endif -#if BYTE_ORDER == BIG_ENDIAN - *value >>= 8; -#endif - - if (sign) { - *lsb_ptr |= 255; - *lsb_ptr &= data; - } else { - *lsb_ptr |= data; - } - } - - return ERR_OK; - } - - return ERR_VAL; -} - -/** - * Decodes object identifier from incoming message into array of u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded object identifier - * @param oid return decoded object identifier - * @param oid_len return decoded object identifier length - * @param oid_max_len size of oid buffer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len) -{ - u32_t *oid_ptr; - u8_t data; - - *oid_len = 0; - oid_ptr = oid; - if (len > 0) { - if (oid_max_len < 2) { - return ERR_MEM; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - /* first compressed octet */ - if (data == 0x2B) { - /* (most) common case 1.3 (iso.org) */ - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = 3; - oid_ptr++; - } else if (data < 40) { - *oid_ptr = 0; - oid_ptr++; - *oid_ptr = data; - oid_ptr++; - } else if (data < 80) { - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = data - 40; - oid_ptr++; - } else { - *oid_ptr = 2; - oid_ptr++; - *oid_ptr = data - 80; - oid_ptr++; - } - *oid_len = 2; - } else { - /* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */ - return ERR_OK; - } - - while ((len > 0) && (*oid_len < oid_max_len)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - if ((data & 0x80) == 0x00) { - /* sub-identifier uses single octet */ - *oid_ptr = data; - } else { - /* sub-identifier uses multiple octets */ - u32_t sub_id = (data & ~0x80); - while ((len > 0) && ((data & 0x80) != 0)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - sub_id = (sub_id << 7) + (data & ~0x80); - } - - if ((data & 0x80) != 0) { - /* "more bytes following" bit still set at end of len */ - return ERR_VAL; - } - *oid_ptr = sub_id; - } - oid_ptr++; - (*oid_len)++; - } - - if (len > 0) { - /* OID to long to fit in our buffer */ - return ERR_MEM; - } - - return ERR_OK; -} - -/** - * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) - * from incoming message into array. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded raw data (zero is valid, e.g. empty string!) - * @param buf return raw bytes - * @param buf_len returns length of the raw return value - * @param buf_max_len buffer size - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len) -{ - if (len > buf_max_len) { - /* not enough dst space */ - return ERR_MEM; - } - *buf_len = len; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); - buf++; - len--; - } - - return ERR_OK; -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.h b/components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.h deleted file mode 100644 index ec50d8c9e3..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_asn1.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) codec. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_ASN1_H -#define LWIP_HDR_APPS_SNMP_ASN1_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/err.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_pbuf_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80 - -#define SNMP_ASN1_CLASS_MASK 0xC0 -#define SNMP_ASN1_CONTENTTYPE_MASK 0x20 -#define SNMP_ASN1_DATATYPE_MASK 0x1F -#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */ - -/* context specific (SNMP) tags (from SNMP spec. RFC1157) */ -#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0 -#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1 -#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2 -#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3 -#define SNMP_ASN1_CONTEXT_PDU_TRAP 4 -#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5 - -#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0 -#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2 - -struct snmp_asn1_tlv -{ - u8_t type; /* only U8 because extended types are not specified by SNMP */ - u8_t type_len; /* encoded length of 'type' field (normally 1) */ - u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */ - u16_t value_len; /* encoded length of the value */ -}; -#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len) -#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len) -#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0); - -err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); -err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); -err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); -err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); -err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len); -err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len); - -err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); - -void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); -void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); -void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); -void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); -void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); -err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len); -err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value); -err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value); -err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); -err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_core.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_core.c deleted file mode 100644 index c041833617..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_core.c +++ /dev/null @@ -1,1349 +0,0 @@ -/** - * @file - * MIB tree access/construction functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel -*/ - -/** - * @defgroup snmp SNMPv2c agent - * @ingroup apps - * SNMPv2c compatible agent\n - * There is also a MIB compiler and a MIB viewer in lwIP contrib repository - * (lwip-contrib/apps/LwipMibCompiler).\n - * The agent implements the most important MIB2 MIBs including IPv6 support - * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version - * whithout IPv6 statistics (TODO).\n - * Rewritten by Martin Hentschel and - * Dirk Ziegelmeier \n - * Work on SNMPv3 has started, but is not finished.\n - * - * 0 Agent Capabilities - * ==================== - * - * Features: - * --------- - * - SNMPv2c support. - * - Low RAM usage - no memory pools, stack only. - * - MIB2 implementation is separated from SNMP stack. - * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. - * - Simple and generic API for MIB implementation. - * - Comfortable node types and helper functions for scalar arrays and tables. - * - Counter64, bit and truthvalue datatype support. - * - Callbacks for SNMP writes e.g. to implement persistency. - * - Runs on two APIs: RAW and netconn. - * - Async API is gone - the stack now supports netconn API instead, - * so blocking operations can be done in MIB calls. - * SNMP runs in a worker thread when netconn API is used. - * - Simplified thread sync support for MIBs - useful when MIBs - * need to access variables shared with other threads where no locking is - * possible. Used in MIB2 to access lwIP stats from lwIP thread. - * - * MIB compiler (code generator): - * ------------------------------ - * - Provided in lwIP contrib repository. - * - Written in C#. MIB viewer used Windows Forms. - * - Developed on Windows with Visual Studio 2010. - * - Can be compiled and used on all platforms with http://www.monodevelop.com/. - * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) - * (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). - * - MIB parser, C file generation framework and LWIP code generation are cleanly - * separated, which means the code may be useful as a base for code generation - * of other SNMP agents. - * - * Notes: - * ------ - * - Stack and MIB compiler were used to implement a Profinet device. - * Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. - * - * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416 - * ------------------------------------------- - * Note the S in SNMP stands for "Simple". Note that "Simple" is - * relative. SNMP is simple compared to the complex ISO network - * management protocols CMIP (Common Management Information Protocol) - * and CMOT (CMip Over Tcp). - * - * MIB II - * ------ - * The standard lwIP stack management information base. - * This is a required MIB, so this is always enabled. - * The groups EGP, CMOT and transmission are disabled by default. - * - * Most mib-2 objects are not writable except: - * sysName, sysLocation, sysContact, snmpEnableAuthenTraps. - * Writing to or changing the ARP and IP address and route - * tables is not possible. - * - * Note lwIP has a very limited notion of IP routing. It currently - * doen't have a route table and doesn't have a notion of the U,G,H flags. - * Instead lwIP uses the interface list with only one default interface - * acting as a single gateway interface (G) for the default route. - * - * The agent returns a "virtual table" with the default route 0.0.0.0 - * for the default interface and network routes (no H) for each - * network interface in the netif_list. - * All routes are considered to be up (U). - * - * Loading additional MIBs - * ----------------------- - * MIBs can only be added in compile-time, not in run-time. - * - * - * 1 Building the Agent - * ==================== - * First of all you'll need to add the following define - * to your local lwipopts.h: - * \#define LWIP_SNMP 1 - * - * and add the source files your makefile. - * - * Note you'll might need to adapt you network driver to update - * the mib2 variables for your interface. - * - * 2 Running the Agent - * =================== - * The following function calls must be made in your program to - * actually get the SNMP agent running. - * - * Before starting the agent you should supply pointers - * for sysContact, sysLocation, and snmpEnableAuthenTraps. - * You can do this by calling - * - * - snmp_mib2_set_syscontact() - * - snmp_mib2_set_syslocation() - * - snmp_set_auth_traps_enabled() - * - * You can register a callback which is called on successful write access: - * snmp_set_write_callback(). - * - * Additionally you may want to set - * - * - snmp_mib2_set_sysdescr() - * - snmp_set_device_enterprise_oid() - * - snmp_mib2_set_sysname() - * - * Also before starting the agent you need to setup - * one or more trap destinations using these calls: - * - * - snmp_trap_dst_enable() - * - snmp_trap_dst_ip_set() - * - * If you need more than MIB2, set the MIBs you want to use - * by snmp_set_mibs(). - * - * Finally, enable the agent by calling snmp_init() - * - * @defgroup snmp_core Core - * @ingroup snmp - * - * @defgroup snmp_traps Traps - * @ingroup snmp - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_core_priv.h" -#include "lwip/netif.h" -#include - - -#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) - #error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_SNMP) - #error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif - -struct snmp_statistics snmp_stats; -static const struct snmp_obj_id snmp_device_enterprise_oid_default = {SNMP_DEVICE_ENTERPRISE_OID_LEN, SNMP_DEVICE_ENTERPRISE_OID}; -static const struct snmp_obj_id* snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; - -const u32_t snmp_zero_dot_zero_values[] = { 0, 0 }; -const struct snmp_obj_id_const_ref snmp_zero_dot_zero = { LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values }; - - -#if SNMP_LWIP_MIB2 -#include "lwip/apps/snmp_mib2.h" -static const struct snmp_mib* const default_mibs[] = { &mib2 }; -static u8_t snmp_num_mibs = 1; -#else -static const struct snmp_mib* const default_mibs[] = { NULL }; -static u8_t snmp_num_mibs = 0; -#endif - -/* List of known mibs */ -static struct snmp_mib const * const *snmp_mibs = default_mibs; - -/** - * @ingroup snmp_core - * Sets the MIBs to use. - * Example: call snmp_set_mibs() as follows: - * static const struct snmp_mib *my_snmp_mibs[] = { - * &mib2, - * &private_mib - * }; - * snmp_set_mibs(my_snmp_mibs, LWIP_ARRAYSIZE(my_snmp_mibs)); - */ -void -snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs) -{ - LWIP_ASSERT("mibs pointer must be != NULL", (mibs != NULL)); - LWIP_ASSERT("num_mibs pointer must be != 0", (num_mibs != 0)); - snmp_mibs = mibs; - snmp_num_mibs = num_mibs; -} - -/** - * @ingroup snmp_core - * 'device enterprise oid' is used for 'device OID' field in trap PDU's (for identification of generating device) - * as well as for value returned by MIB-2 'sysObjectID' field (if internal MIB2 implementation is used). - * The 'device enterprise oid' shall point to an OID located under 'private-enterprises' branch (1.3.6.1.4.1.XXX). If a vendor - * wants to provide a custom object there, he has to get its own enterprise oid from IANA (http://www.iana.org). It - * is not allowed to use LWIP enterprise ID! - * In order to identify a specific device it is recommended to create a dedicated OID for each device type under its own - * enterprise oid. - * e.g. - * device a > 1.3.6.1.4.1.XXX(ent-oid).1(devices).1(device a) - * device b > 1.3.6.1.4.1.XXX(ent-oid).1(devices).2(device b) - * for more details see description of 'sysObjectID' field in RFC1213-MIB - */ -void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid) -{ - if (device_enterprise_oid == NULL) { - snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; - } else { - snmp_device_enterprise_oid = device_enterprise_oid; - } -} - -/** - * @ingroup snmp_core - * Get 'device enterprise oid' - */ -const struct snmp_obj_id* snmp_get_device_enterprise_oid(void) -{ - return snmp_device_enterprise_oid; -} - -#if LWIP_IPV4 -/** - * Conversion from InetAddressIPv4 oid to lwIP ip4_addr - * @param oid points to u32_t ident[4] input - * @param ip points to output struct - */ -u8_t -snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip) -{ - if ((oid[0] > 0xFF) || - (oid[1] > 0xFF) || - (oid[2] > 0xFF) || - (oid[3] > 0xFF)) { - ip4_addr_copy(*ip, *IP4_ADDR_ANY4); - return 0; - } - - IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]); - return 1; -} - -/** - * Convert ip4_addr to InetAddressIPv4 (no InetAddressType) - * @param ip points to input struct - * @param oid points to u32_t ident[4] output - */ -void -snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid) -{ - oid[0] = ip4_addr1(ip); - oid[1] = ip4_addr2(ip); - oid[2] = ip4_addr3(ip); - oid[3] = ip4_addr4(ip); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Conversion from InetAddressIPv6 oid to lwIP ip6_addr - * @param oid points to u32_t oid[16] input - * @param ip points to output struct - */ -u8_t -snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip) -{ - if ((oid[0] > 0xFF) || - (oid[1] > 0xFF) || - (oid[2] > 0xFF) || - (oid[3] > 0xFF) || - (oid[4] > 0xFF) || - (oid[5] > 0xFF) || - (oid[6] > 0xFF) || - (oid[7] > 0xFF) || - (oid[8] > 0xFF) || - (oid[9] > 0xFF) || - (oid[10] > 0xFF) || - (oid[11] > 0xFF) || - (oid[12] > 0xFF) || - (oid[13] > 0xFF) || - (oid[14] > 0xFF) || - (oid[15] > 0xFF)) { - ip6_addr_set_any(ip); - return 0; - } - - ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); - ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); - ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); - ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); - return 1; -} - -/** - * Convert ip6_addr to InetAddressIPv6 (no InetAddressType) - * @param ip points to input struct - * @param oid points to u32_t ident[16] output - */ -void -snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid) -{ - oid[0] = (ip->addr[0] & 0xFF000000) >> 24; - oid[1] = (ip->addr[0] & 0x00FF0000) >> 16; - oid[2] = (ip->addr[0] & 0x0000FF00) >> 8; - oid[3] = (ip->addr[0] & 0x000000FF) >> 0; - oid[4] = (ip->addr[1] & 0xFF000000) >> 24; - oid[5] = (ip->addr[1] & 0x00FF0000) >> 16; - oid[6] = (ip->addr[1] & 0x0000FF00) >> 8; - oid[7] = (ip->addr[1] & 0x000000FF) >> 0; - oid[8] = (ip->addr[2] & 0xFF000000) >> 24; - oid[9] = (ip->addr[2] & 0x00FF0000) >> 16; - oid[10] = (ip->addr[2] & 0x0000FF00) >> 8; - oid[11] = (ip->addr[2] & 0x000000FF) >> 0; - oid[12] = (ip->addr[3] & 0xFF000000) >> 24; - oid[13] = (ip->addr[3] & 0x00FF0000) >> 16; - oid[14] = (ip->addr[3] & 0x0000FF00) >> 8; - oid[15] = (ip->addr[3] & 0x000000FF) >> 0; -} -#endif /* LWIP_IPV6 */ - -#if LWIP_IPV4 || LWIP_IPV6 -/** - * Convert to InetAddressType+InetAddress+InetPortNumber - * @param ip IP address - * @param port Port - * @param oid OID - * @return OID length - */ -u8_t -snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid) -{ - u8_t idx; - - idx = snmp_ip_to_oid(ip, oid); - oid[idx] = port; - idx++; - - return idx; -} - -/** - * Convert to InetAddressType+InetAddress - * @param ip IP address - * @param oid OID - * @return OID length - */ -u8_t -snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid) -{ - if (IP_IS_ANY_TYPE_VAL(*ip)) { - oid[0] = 0; /* any */ - oid[1] = 0; /* no IP OIDs follow */ - return 2; - } else if (IP_IS_V6(ip)) { -#if LWIP_IPV6 - oid[0] = 2; /* ipv6 */ - oid[1] = 16; /* 16 InetAddressIPv6 OIDs follow */ - snmp_ip6_to_oid(ip_2_ip6(ip), &oid[2]); - return 18; -#else /* LWIP_IPV6 */ - return 0; -#endif /* LWIP_IPV6 */ - } else { -#if LWIP_IPV4 - oid[0] = 1; /* ipv4 */ - oid[1] = 4; /* 4 InetAddressIPv4 OIDs follow */ - snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]); - return 6; -#else /* LWIP_IPV4 */ - return 0; -#endif /* LWIP_IPV4 */ - } -} - -/** - * Convert from InetAddressType+InetAddress to ip_addr_t - * @param oid OID - * @param oid_len OID length - * @param ip IP address - * @return Parsed OID length - */ -u8_t -snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) -{ - /* InetAddressType */ - if (oid_len < 1) { - return 0; - } - - if (oid[0] == 0) { /* any */ - /* 1x InetAddressType, 1x OID len */ - if (oid_len < 2) { - return 0; - } - if (oid[1] != 0) { - return 0; - } - - memset(ip, 0, sizeof(*ip)); - IP_SET_TYPE(ip, IPADDR_TYPE_ANY); - - return 2; - } else if (oid[0] == 1) { /* ipv4 */ -#if LWIP_IPV4 - /* 1x InetAddressType, 1x OID len, 4x InetAddressIPv4 */ - if (oid_len < 6) { - return 0; - } - - /* 4x ipv4 OID */ - if (oid[1] != 4) { - return 0; - } - - IP_SET_TYPE(ip, IPADDR_TYPE_V4); - if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) { - return 0; - } - - return 6; -#else /* LWIP_IPV4 */ - return 0; -#endif /* LWIP_IPV4 */ - } else if (oid[0] == 2) { /* ipv6 */ -#if LWIP_IPV6 - /* 1x InetAddressType, 1x OID len, 16x InetAddressIPv6 */ - if (oid_len < 18) { - return 0; - } - - /* 16x ipv6 OID */ - if (oid[1] != 16) { - return 0; - } - - IP_SET_TYPE(ip, IPADDR_TYPE_V6); - if (!snmp_oid_to_ip6(&oid[2], ip_2_ip6(ip))) { - return 0; - } - - return 18; -#else /* LWIP_IPV6 */ - return 0; -#endif /* LWIP_IPV6 */ - } else { /* unsupported InetAddressType */ - return 0; - } -} - -/** - * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t - * @param oid OID - * @param oid_len OID length - * @param ip IP address - * @param port Port - * @return Parsed OID length - */ -u8_t -snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) -{ - u8_t idx = 0; - - /* InetAddressType + InetAddress */ - idx += snmp_oid_to_ip(&oid[idx], oid_len-idx, ip); - if (idx == 0) { - return 0; - } - - /* InetPortNumber */ - if (oid_len < (idx+1)) { - return 0; - } - if (oid[idx] > 0xffff) { - return 0; - } - *port = (u16_t)oid[idx]; - idx++; - - return idx; -} - -#endif /* LWIP_IPV4 || LWIP_IPV6 */ - -/** - * Assign an OID to struct snmp_obj_id - * @param target Assignment target - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("oid_len <= LWIP_SNMP_OBJ_ID_LEN", oid_len <= SNMP_MAX_OBJ_ID_LEN); - - target->len = oid_len; - - if (oid_len > 0) { - MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); - } -} - -/** - * Prefix an OID to OID in struct snmp_obj_id - * @param target Assignment target to prefix - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("target->len + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); - - if (oid_len > 0) { - /* move existing OID to make room at the beginning for OID to insert */ - int i; - for (i = target->len-1; i>=0; i--) { - target->id[i + oid_len] = target->id[i]; - } - - /* paste oid at the beginning */ - MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); - } -} - -/** - * Combine two OIDs into struct snmp_obj_id - * @param target Assignmet target - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - */ -void -snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - snmp_oid_assign(target, oid1, oid1_len); - snmp_oid_append(target, oid2, oid2_len); -} - -/** - * Append OIDs to struct snmp_obj_id - * @param target Assignment target to append to - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("offset + oid_len <= LWIP_SNMP_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); - - if (oid_len > 0) { - MEMCPY(&target->id[target->len], oid, oid_len * sizeof(u32_t)); - target->len += oid_len; - } -} - -/** - * Compare two OIDs - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - * @return -1: OID1<OID2 1: OID1 >OID2 0: equal - */ -s8_t -snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - u8_t level = 0; - LWIP_ASSERT("'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 != NULL) || (oid1_len == 0)); - LWIP_ASSERT("'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 != NULL) || (oid2_len == 0)); - - while ((level < oid1_len) && (level < oid2_len)) { - if (*oid1 < *oid2) { - return -1; - } - if (*oid1 > *oid2) { - return 1; - } - - level++; - oid1++; - oid2++; - } - - /* common part of both OID's is equal, compare length */ - if (oid1_len < oid2_len) { - return -1; - } - if (oid1_len > oid2_len) { - return 1; - } - - /* they are equal */ - return 0; -} - - -/** - * Check of two OIDs are equal - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - * @return 1: equal 0: non-equal - */ -u8_t -snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0)? 1 : 0; -} - -/** - * Convert netif to interface index - * @param netif netif - * @return index - */ -u8_t -netif_to_num(const struct netif *netif) -{ - u8_t result = 0; - struct netif *netif_iterator = netif_list; - - while (netif_iterator != NULL) { - result++; - - if (netif_iterator == netif) { - return result; - } - - netif_iterator = netif_iterator->next; - } - - LWIP_ASSERT("netif not found in netif_list", 0); - return 0; -} - -static const struct snmp_mib* -snmp_get_mib_from_oid(const u32_t *oid, u8_t oid_len) -{ - const u32_t* list_oid; - const u32_t* searched_oid; - u8_t i, l; - - u8_t max_match_len = 0; - const struct snmp_mib* matched_mib = NULL; - - LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); - - if (oid_len == 0) { - return NULL; - } - - for (i = 0; i < snmp_num_mibs; i++) { - LWIP_ASSERT("MIB array not initialized correctly", (snmp_mibs[i] != NULL)); - LWIP_ASSERT("MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid != NULL)); - - if (oid_len >= snmp_mibs[i]->base_oid_len) { - l = snmp_mibs[i]->base_oid_len; - list_oid = snmp_mibs[i]->base_oid; - searched_oid = oid; - - while (l > 0) { - if (*list_oid != *searched_oid) { - break; - } - - l--; - list_oid++; - searched_oid++; - } - - if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len)) { - max_match_len = snmp_mibs[i]->base_oid_len; - matched_mib = snmp_mibs[i]; - } - } - } - - return matched_mib; -} - -static const struct snmp_mib* -snmp_get_next_mib(const u32_t *oid, u8_t oid_len) -{ - u8_t i; - const struct snmp_mib* next_mib = NULL; - - LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); - - if (oid_len == 0) { - return NULL; - } - - for (i = 0; i < snmp_num_mibs; i++) { - if (snmp_mibs[i]->base_oid != NULL) { - /* check if mib is located behind starting point */ - if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0) { - if ((next_mib == NULL) || - (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, - next_mib->base_oid, next_mib->base_oid_len) < 0)) { - next_mib = snmp_mibs[i]; - } - } - } - } - - return next_mib; -} - -static const struct snmp_mib* -snmp_get_mib_between(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - const struct snmp_mib* next_mib = snmp_get_next_mib(oid1, oid1_len); - - LWIP_ASSERT("'oid2' param must not be NULL!", (oid2 != NULL)); - LWIP_ASSERT("'oid2_len' param must be greater than 0!", (oid2_len > 0)); - - if (next_mib != NULL) { - if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0) { - return next_mib; - } - } - - return NULL; -} - -u8_t -snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance) -{ - u8_t result = SNMP_ERR_NOSUCHOBJECT; - const struct snmp_mib *mib; - const struct snmp_node *mn = NULL; - - mib = snmp_get_mib_from_oid(oid, oid_len); - if (mib != NULL) { - u8_t oid_instance_len; - - mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len); - if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) { - /* get instance */ - const struct snmp_leaf_node* leaf_node = (const struct snmp_leaf_node*)(const void*)mn; - - node_instance->node = mn; - snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len); - - result = leaf_node->get_instance( - oid, - oid_len - oid_instance_len, - node_instance); - -#ifdef LWIP_DEBUG - if (result == SNMP_ERR_NOERROR) { - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); - } - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n")); - } - } -#endif - } - } - - return result; -} - -u8_t -snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance) -{ - const struct snmp_mib *mib; - const struct snmp_node *mn = NULL; - const u32_t* start_oid = NULL; - u8_t start_oid_len = 0; - - /* resolve target MIB from passed OID */ - mib = snmp_get_mib_from_oid(oid, oid_len); - if (mib == NULL) { - /* passed OID does not reference any known MIB, start at the next closest MIB */ - mib = snmp_get_next_mib(oid, oid_len); - - if (mib != NULL) { - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - } else { - start_oid = oid; - start_oid_len = oid_len; - } - - /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */ - while ((mib != NULL) && (mn == NULL)) { - u8_t oid_instance_len; - - /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */ - mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len); - if (mn != NULL) { - snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len); /* set oid to node */ - snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len); /* set (relative) instance oid */ - } else { - /* OID does not reference a node, search for the next closest node inside MIB; set instance_oid.len to zero because we want the first instance of this node */ - mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid); - node_instance->instance_oid.len = 0; - } - - /* validate the node; if the node has no further instance or the returned instance is invalid, search for the next in MIB and validate again */ - node_instance->node = mn; - while (mn != NULL) { - u8_t result; - - /* clear fields which may have values from previous loops */ - node_instance->asn1_type = 0; - node_instance->access = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE; - node_instance->get_value = NULL; - node_instance->set_test = NULL; - node_instance->set_value = NULL; - node_instance->release_instance = NULL; - node_instance->reference.ptr = NULL; - node_instance->reference_len = 0; - - result = ((const struct snmp_leaf_node*)(const void*)mn)->get_next_instance( - node_oid->id, - node_oid->len, - node_instance); - - if (result == SNMP_ERR_NOERROR) { -#ifdef LWIP_DEBUG - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); - } - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value function is specified\n")); - } -#endif - - /* validate node because the node may be not accessible for example (but let the caller decide what is valid */ - if ((validate_node_instance_method == NULL) || - (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR)) { - /* node_oid "returns" the full result OID (including the instance part) */ - snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); - break; - } - - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - /* - the instance itself is not valid, ask for next instance from same node. - we don't have to change any variables because node_instance->instance_oid is used as input (starting point) - as well as output (resulting next OID), so we have to simply call get_next_instance method again - */ - } else { - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - - /* the node has no further instance, skip to next node */ - mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid); /* misuse node_instance->instance_oid as tmp buffer */ - if (mn != NULL) { - /* prepare for next loop */ - snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); - node_instance->instance_oid.len = 0; - node_instance->node = mn; - } - } - } - - if (mn != NULL) { - /* - we found a suitable next node, - now we have to check if a inner MIB is located between the searched OID and the resulting OID. - this is possible because MIB's may be located anywhere in the global tree, that means also in - the subtree of another MIB (e.g. if searched OID is .2 and resulting OID is .4, then another - MIB having .3 as root node may exist) - */ - const struct snmp_mib *intermediate_mib; - intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len); - - if (intermediate_mib != NULL) { - /* search for first node inside intermediate mib in next loop */ - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - - mn = NULL; - mib = intermediate_mib; - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - /* else { we found out target node } */ - } else { - /* - there is no further (suitable) node inside this MIB, search for the next MIB with following priority - 1. search for inner MIB's (whose root is located inside tree of current MIB) - 2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any - 3. take the next closest MIB (not being related to the current MIB) - */ - const struct snmp_mib *next_mib; - next_mib = snmp_get_next_mib(start_oid, start_oid_len); /* returns MIB's related to point 1 and 3 */ - - /* is the found MIB an inner MIB? (point 1) */ - if ((next_mib != NULL) && (next_mib->base_oid_len > mib->base_oid_len) && - (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) { - /* yes it is -> continue at inner MIB */ - mib = next_mib; - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } else { - /* check if there is a surrounding mib where to continue (point 2) (only possible if OID length > 1) */ - if (mib->base_oid_len > 1) { - mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1); - - if (mib == NULL) { - /* no surrounding mib, use next mib encountered above (point 3) */ - mib = next_mib; - - if (mib != NULL) { - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - } - /* else { start_oid stays the same because we want to continue from current offset in surrounding mib (point 2) } */ - } - } - } - } - - if (mib == NULL) { - /* loop is only left when mib == null (error) or mib_node != NULL (success) */ - return SNMP_ERR_ENDOFMIBVIEW; - } - - return SNMP_ERR_NOERROR; -} - -/** - * Searches tree for the supplied object identifier. - * - */ -const struct snmp_node * -snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len) -{ - const struct snmp_node* const* node = &mib->root_node; - u8_t oid_offset = mib->base_oid_len; - - while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE)) { - /* search for matching sub node */ - u32_t subnode_oid = *(oid + oid_offset); - - u32_t i = (*(const struct snmp_tree_node* const*)node)->subnode_count; - node = (*(const struct snmp_tree_node* const*)node)->subnodes; - while ((i > 0) && ((*node)->oid != subnode_oid)) { - node++; - i--; - } - - if (i == 0) { - /* no matching subnode found */ - return NULL; - } - - oid_offset++; - } - - if ((*node)->node_type != SNMP_NODE_TREE) { - /* we found a leaf node */ - *oid_instance_len = oid_len - oid_offset; - return (*node); - } - - return NULL; -} - -const struct snmp_node* -snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret) -{ - u8_t oid_offset = mib->base_oid_len; - const struct snmp_node* const* node; - const struct snmp_tree_node* node_stack[SNMP_MAX_OBJ_ID_LEN]; - s32_t nsi = 0; /* NodeStackIndex */ - u32_t subnode_oid; - - if (mib->root_node->node_type != SNMP_NODE_TREE) { - /* a next operation on a mib with only a leaf node will always return NULL because there is no other node */ - return NULL; - } - - /* first build node stack related to passed oid (as far as possible), then go backwards to determine the next node */ - node_stack[nsi] = (const struct snmp_tree_node*)(const void*)mib->root_node; - while (oid_offset < oid_len) { - /* search for matching sub node */ - u32_t i = node_stack[nsi]->subnode_count; - node = node_stack[nsi]->subnodes; - - subnode_oid = *(oid + oid_offset); - - while ((i > 0) && ((*node)->oid != subnode_oid)) { - node++; - i--; - } - - if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE)) { - /* no (matching) tree-subnode found */ - break; - } - nsi++; - node_stack[nsi] = (const struct snmp_tree_node*)(const void*)(*node); - - oid_offset++; - } - - - if (oid_offset >= oid_len) { - /* passed oid references a tree node -> return first useable sub node of it */ - subnode_oid = 0; - } else { - subnode_oid = *(oid + oid_offset) + 1; - } - - while (nsi >= 0) { - const struct snmp_node* subnode = NULL; - - /* find next node on current level */ - s32_t i = node_stack[nsi]->subnode_count; - node = node_stack[nsi]->subnodes; - while (i > 0) { - if ((*node)->oid == subnode_oid) { - subnode = *node; - break; - } else if (((*node)->oid > subnode_oid) && ((subnode == NULL) || ((*node)->oid < subnode->oid))) { - subnode = *node; - } - - node++; - i--; - } - - if (subnode == NULL) { - /* no further node found on this level, go one level up and start searching with index of current node*/ - subnode_oid = node_stack[nsi]->node.oid + 1; - nsi--; - } else { - if (subnode->node_type == SNMP_NODE_TREE) { - /* next is a tree node, go into it and start searching */ - nsi++; - node_stack[nsi] = (const struct snmp_tree_node*)(const void*)subnode; - subnode_oid = 0; - } else { - /* we found a leaf node -> fill oidret and return it */ - snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len); - i = 1; - while (i <= nsi) { - oidret->id[oidret->len] = node_stack[i]->node.oid; - oidret->len++; - i++; - } - - oidret->id[oidret->len] = subnode->oid; - oidret->len++; - - return subnode; - } - } - } - - return NULL; -} - -/** initialize struct next_oid_state using this function before passing it to next_oid_check */ -void -snmp_next_oid_init(struct snmp_next_oid_state *state, - const u32_t *start_oid, u8_t start_oid_len, - u32_t *next_oid_buf, u8_t next_oid_max_len) -{ - state->start_oid = start_oid; - state->start_oid_len = start_oid_len; - state->next_oid = next_oid_buf; - state->next_oid_len = 0; - state->next_oid_max_len = next_oid_max_len; - state->status = SNMP_NEXT_OID_STATUS_NO_MATCH; -} - -/** checks if the passed incomplete OID may be a possible candidate for snmp_next_oid_check(); -this methid is intended if the complete OID is not yet known but it is very expensive to build it up, -so it is possible to test the starting part before building up the complete oid and pass it to snmp_next_oid_check()*/ -u8_t -snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len) -{ - if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { - u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len; - - /* check passed OID is located behind start offset */ - if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0) { - /* check if new oid is located closer to start oid than current closest oid */ - if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || - (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { - return 1; - } - } - } - - return 0; -} - -/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */ -u8_t -snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference) -{ - /* do not overwrite a fail result */ - if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { - /* check passed OID is located behind start offset */ - if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0) { - /* check if new oid is located closer to start oid than current closest oid */ - if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || - (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { - if (oid_len <= state->next_oid_max_len) { - MEMCPY(state->next_oid, oid, oid_len * sizeof(u32_t)); - state->next_oid_len = oid_len; - state->status = SNMP_NEXT_OID_STATUS_SUCCESS; - state->reference = reference; - return 1; - } else { - state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL; - } - } - } - } - - return 0; -} - -u8_t -snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len) -{ - u8_t i; - - if (oid_len != oid_ranges_len) { - return 0; - } - - for (i = 0; i < oid_ranges_len; i++) { - if ((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) { - return 0; - } - } - - return 1; -} - -snmp_err_t -snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value) -{ - LWIP_UNUSED_ARG(instance); - LWIP_UNUSED_ARG(value_len); - LWIP_UNUSED_ARG(value); - - return SNMP_ERR_NOERROR; -} - -/** - * Decodes BITS pseudotype value from ASN.1 OctetString. - * - * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly - * be encoded/decoded by the agent. Instead call this function as required from - * get/test/set methods. - * - * @param buf points to a buffer holding the ASN1 octet string - * @param buf_len length of octet string - * @param bit_value decoded Bit value with Bit0 == LSB - * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit - */ -err_t -snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value) -{ - u8_t b; - u8_t bits_processed = 0; - *bit_value = 0; - - while (buf_len > 0) { - /* any bit set in this byte? */ - if (*buf != 0x00) { - if (bits_processed >= 32) { - /* accept more than 4 bytes, but only when no bits are set */ - return ERR_VAL; - } - - b = *buf; - do { - if (b & 0x80) { - *bit_value |= (1 << bits_processed); - } - bits_processed++; - b <<= 1; - } - while ((bits_processed & 0x07) != 0); /* &0x07 -> % 8 */ - } else { - bits_processed += 8; - } - - buf_len--; - buf++; - } - - return ERR_OK; -} - -err_t -snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value) -{ - /* defined by RFC1443: - TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - */ - - if ((asn1_value == NULL) || (bool_value == NULL)) { - return ERR_ARG; - } - - if (*asn1_value == 1) { - *bool_value = 1; - } else if (*asn1_value == 2) { - *bool_value = 0; - } else { - return ERR_VAL; - } - - return ERR_OK; -} - -/** - * Encodes BITS pseudotype value into ASN.1 OctetString. - * - * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly - * be encoded/decoded by the agent. Instead call this function as required from - * get/test/set methods. - * - * @param buf points to a buffer where the resulting ASN1 octet string is stored to - * @param buf_len max length of the bufffer - * @param bit_value Bit value to encode with Bit0 == LSB - * @param bit_count Number of possible bits for the bit value (according to rfc we have to send all bits independant from their truth value) - * @return number of bytes used from buffer to store the resulting OctetString - */ -u8_t -snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count) -{ - u8_t len = 0; - u8_t min_bytes = (bit_count + 7) >> 3; /* >>3 -> / 8 */ - - while ((buf_len > 0) && (bit_value != 0x00)) { - s8_t i = 7; - *buf = 0x00; - while (i >= 0) { - if (bit_value & 0x01) { - *buf |= 0x01; - } - - if (i > 0) { - *buf <<= 1; - } - - bit_value >>= 1; - i--; - } - - buf++; - buf_len--; - len++; - } - - if (len < min_bytes) { - buf += len; - buf_len -= len; - - while ((len < min_bytes) && (buf_len > 0)) { - *buf = 0x00; - buf++; - buf_len--; - len++; - } - } - - return len; -} - -u8_t -snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value) -{ - /* defined by RFC1443: - TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - */ - - if (asn1_value == NULL) { - return 0; - } - - if (bool_value) { - *asn1_value = 1; /* defined by RFC1443 */ - } else { - *asn1_value = 2; /* defined by RFC1443 */ - } - - return sizeof(s32_t); -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_core_priv.h b/components/net/lwip-2.0.2/src/apps/snmp/snmp_core_priv.h deleted file mode 100644 index 5552177d74..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_core_priv.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H -#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "snmp_asn1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* (outdated) SNMPv1 error codes - * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request - */ -#define SNMP_ERR_NOSUCHNAME 2 -#define SNMP_ERR_BADVALUE 3 -#define SNMP_ERR_READONLY 4 -/* error codes which are internal and shall not be used by MIBS - * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request - */ -#define SNMP_ERR_TOOBIG 1 -#define SNMP_ERR_AUTHORIZATIONERROR 16 -#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT -#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW - - -const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len); -const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret); - -typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*); - -u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance); -u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2.c deleted file mode 100644 index 9d8c43c108..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2.c +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -/** - * @defgroup snmp_mib2 MIB2 - * @ingroup snmp - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */ - -#if !LWIP_STATS -#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2) -#endif -#if !MIB2_STATS -#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2) -#endif - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_scalar.h" - -#if SNMP_USE_NETCONN -#include "lwip/tcpip.h" -#include "lwip/priv/tcpip_priv.h" -void -snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg) -{ -#if LWIP_TCPIP_CORE_LOCKING - LOCK_TCPIP_CORE(); - fn(arg); - UNLOCK_TCPIP_CORE(); -#else - tcpip_callback(fn, arg); -#endif -} - -struct snmp_threadsync_instance snmp_mib2_lwip_locks; -#endif - -/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ -/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ -/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ - -/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */ -extern const struct snmp_scalar_array_node snmp_mib2_snmp_root; -extern const struct snmp_tree_node snmp_mib2_udp_root; -extern const struct snmp_tree_node snmp_mib2_tcp_root; -extern const struct snmp_scalar_array_node snmp_mib2_icmp_root; -extern const struct snmp_tree_node snmp_mib2_interface_root; -extern const struct snmp_scalar_array_node snmp_mib2_system_node; -extern const struct snmp_tree_node snmp_mib2_at_root; -extern const struct snmp_tree_node snmp_mib2_ip_root; - -static const struct snmp_node* const mib2_nodes[] = { - &snmp_mib2_system_node.node.node, - &snmp_mib2_interface_root.node, -#if LWIP_ARP && LWIP_IPV4 - &snmp_mib2_at_root.node, -#endif /* LWIP_ARP && LWIP_IPV4 */ -#if LWIP_IPV4 - &snmp_mib2_ip_root.node, -#endif /* LWIP_IPV4 */ -#if LWIP_ICMP - &snmp_mib2_icmp_root.node.node, -#endif /* LWIP_ICMP */ -#if LWIP_TCP - &snmp_mib2_tcp_root.node, -#endif /* LWIP_TCP */ -#if LWIP_UDP - &snmp_mib2_udp_root.node, -#endif /* LWIP_UDP */ - &snmp_mib2_snmp_root.node.node -}; - -static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes); - -static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 }; -const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_icmp.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_icmp.c deleted file mode 100644 index 995bd320a5..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_icmp.c +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) ICMP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/icmp.h" -#include "lwip/stats.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */ - -static s16_t -icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - - switch (node->oid) { - case 1: /* icmpInMsgs */ - *uint_ptr = STATS_GET(mib2.icmpinmsgs); - return sizeof(*uint_ptr); - case 2: /* icmpInErrors */ - *uint_ptr = STATS_GET(mib2.icmpinerrors); - return sizeof(*uint_ptr); - case 3: /* icmpInDestUnreachs */ - *uint_ptr = STATS_GET(mib2.icmpindestunreachs); - return sizeof(*uint_ptr); - case 4: /* icmpInTimeExcds */ - *uint_ptr = STATS_GET(mib2.icmpintimeexcds); - return sizeof(*uint_ptr); - case 5: /* icmpInParmProbs */ - *uint_ptr = STATS_GET(mib2.icmpinparmprobs); - return sizeof(*uint_ptr); - case 6: /* icmpInSrcQuenchs */ - *uint_ptr = STATS_GET(mib2.icmpinsrcquenchs); - return sizeof(*uint_ptr); - case 7: /* icmpInRedirects */ - *uint_ptr = STATS_GET(mib2.icmpinredirects); - return sizeof(*uint_ptr); - case 8: /* icmpInEchos */ - *uint_ptr = STATS_GET(mib2.icmpinechos); - return sizeof(*uint_ptr); - case 9: /* icmpInEchoReps */ - *uint_ptr = STATS_GET(mib2.icmpinechoreps); - return sizeof(*uint_ptr); - case 10: /* icmpInTimestamps */ - *uint_ptr = STATS_GET(mib2.icmpintimestamps); - return sizeof(*uint_ptr); - case 11: /* icmpInTimestampReps */ - *uint_ptr = STATS_GET(mib2.icmpintimestampreps); - return sizeof(*uint_ptr); - case 12: /* icmpInAddrMasks */ - *uint_ptr = STATS_GET(mib2.icmpinaddrmasks); - return sizeof(*uint_ptr); - case 13: /* icmpInAddrMaskReps */ - *uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps); - return sizeof(*uint_ptr); - case 14: /* icmpOutMsgs */ - *uint_ptr = STATS_GET(mib2.icmpoutmsgs); - return sizeof(*uint_ptr); - case 15: /* icmpOutErrors */ - *uint_ptr = STATS_GET(mib2.icmpouterrors); - return sizeof(*uint_ptr); - case 16: /* icmpOutDestUnreachs */ - *uint_ptr = STATS_GET(mib2.icmpoutdestunreachs); - return sizeof(*uint_ptr); - case 17: /* icmpOutTimeExcds */ - *uint_ptr = STATS_GET(mib2.icmpouttimeexcds); - return sizeof(*uint_ptr); - case 18: /* icmpOutParmProbs: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 20: /* icmpOutRedirects: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 21: /* icmpOutEchos */ - *uint_ptr = STATS_GET(mib2.icmpoutechos); - return sizeof(*uint_ptr); - case 22: /* icmpOutEchoReps */ - *uint_ptr = STATS_GET(mib2.icmpoutechoreps); - return sizeof(*uint_ptr); - case 23: /* icmpOutTimestamps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 24: /* icmpOutTimestampReps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 25: /* icmpOutAddrMasks: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid)); - break; - } - - return 0; -} - - -static const struct snmp_scalar_array_node_def icmp_nodes[] = { - { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} -}; - -const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_interfaces.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_interfaces.c deleted file mode 100644 index 979b5073ea..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_interfaces.c +++ /dev/null @@ -1,375 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) INTERFACES objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/netif.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - - -/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ - -static s16_t -interfaces_get_value(struct snmp_node_instance* instance, void* value) -{ - if (instance->node->oid == 1) { - s32_t *sint_ptr = (s32_t*)value; - s32_t num_netifs = 0; - - struct netif *netif = netif_list; - while (netif != NULL) { - num_netifs++; - netif = netif->next; - } - - *sint_ptr = num_netifs; - return sizeof(*sint_ptr); - } - - return 0; -} - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range interfaces_Table_oid_ranges[] = { - { 1, 0xff } /* netif->num is u8_t */ -}; - -static const u8_t iftable_ifOutQLen = 0; - -static const u8_t iftable_ifOperStatus_up = 1; -static const u8_t iftable_ifOperStatus_down = 2; - -static const u8_t iftable_ifAdminStatus_up = 1; -static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7; -static const u8_t iftable_ifAdminStatus_down = 2; - -static snmp_err_t -interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance) -{ - u32_t ifIndex; - struct netif *netif; - - LWIP_UNUSED_ARG(column); - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get netif index from incoming OID */ - ifIndex = row_oid[0]; - - /* find netif with index */ - netif = netif_list; - while (netif != NULL) { - if (netif_to_num(netif) == ifIndex) { - /* store netif pointer for subsequent operations (get/test/set) */ - cell_instance->reference.ptr = netif; - return SNMP_ERR_NOERROR; - } - netif = netif->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; - - LWIP_UNUSED_ARG(column); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - netif = netif_list; - while (netif != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; - test_oid[0] = netif_to_num(netif); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); - - netif = netif->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* store netif pointer for subsequent operations (get/test/set) */ - cell_instance->reference.ptr = /* (struct netif*) */state.reference; - return SNMP_ERR_NOERROR; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static s16_t -interfaces_Table_get_value(struct snmp_node_instance* instance, void* value) -{ - struct netif *netif = (struct netif*)instance->reference.ptr; - u32_t* value_u32 = (u32_t*)value; - s32_t* value_s32 = (s32_t*)value; - u16_t value_len; - - switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) - { - case 1: /* ifIndex */ - *value_s32 = netif_to_num(netif); - value_len = sizeof(*value_s32); - break; - case 2: /* ifDescr */ - value_len = sizeof(netif->name); - MEMCPY(value, netif->name, value_len); - break; - case 3: /* ifType */ - *value_s32 = netif->link_type; - value_len = sizeof(*value_s32); - break; - case 4: /* ifMtu */ - *value_s32 = netif->mtu; - value_len = sizeof(*value_s32); - break; - case 5: /* ifSpeed */ - *value_u32 = netif->link_speed; - value_len = sizeof(*value_u32); - break; - case 6: /* ifPhysAddress */ - value_len = sizeof(netif->hwaddr); - MEMCPY(value, &netif->hwaddr, value_len); - break; - case 7: /* ifAdminStatus */ - if (netif_is_up(netif)) { - *value_s32 = iftable_ifOperStatus_up; - } else { - *value_s32 = iftable_ifOperStatus_down; - } - value_len = sizeof(*value_s32); - break; - case 8: /* ifOperStatus */ - if (netif_is_up(netif)) { - if (netif_is_link_up(netif)) { - *value_s32 = iftable_ifAdminStatus_up; - } else { - *value_s32 = iftable_ifAdminStatus_lowerLayerDown; - } - } else { - *value_s32 = iftable_ifAdminStatus_down; - } - value_len = sizeof(*value_s32); - break; - case 9: /* ifLastChange */ - *value_u32 = netif->ts; - value_len = sizeof(*value_u32); - break; - case 10: /* ifInOctets */ - *value_u32 = netif->mib2_counters.ifinoctets; - value_len = sizeof(*value_u32); - break; - case 11: /* ifInUcastPkts */ - *value_u32 = netif->mib2_counters.ifinucastpkts; - value_len = sizeof(*value_u32); - break; - case 12: /* ifInNUcastPkts */ - *value_u32 = netif->mib2_counters.ifinnucastpkts; - value_len = sizeof(*value_u32); - break; - case 13: /* ifInDiscards */ - *value_u32 = netif->mib2_counters.ifindiscards; - value_len = sizeof(*value_u32); - break; - case 14: /* ifInErrors */ - *value_u32 = netif->mib2_counters.ifinerrors; - value_len = sizeof(*value_u32); - break; - case 15: /* ifInUnkownProtos */ - *value_u32 = netif->mib2_counters.ifinunknownprotos; - value_len = sizeof(*value_u32); - break; - case 16: /* ifOutOctets */ - *value_u32 = netif->mib2_counters.ifoutoctets; - value_len = sizeof(*value_u32); - break; - case 17: /* ifOutUcastPkts */ - *value_u32 = netif->mib2_counters.ifoutucastpkts; - value_len = sizeof(*value_u32); - break; - case 18: /* ifOutNUcastPkts */ - *value_u32 = netif->mib2_counters.ifoutnucastpkts; - value_len = sizeof(*value_u32); - break; - case 19: /* ifOutDiscarts */ - *value_u32 = netif->mib2_counters.ifoutdiscards; - value_len = sizeof(*value_u32); - break; - case 20: /* ifOutErrors */ - *value_u32 = netif->mib2_counters.ifouterrors; - value_len = sizeof(*value_u32); - break; - case 21: /* ifOutQLen */ - *value_u32 = iftable_ifOutQLen; - value_len = sizeof(*value_u32); - break; - /** @note returning zeroDotZero (0.0) no media specific MIB support */ - case 22: /* ifSpecific */ - value_len = snmp_zero_dot_zero.len * sizeof(u32_t); - MEMCPY(value, snmp_zero_dot_zero.id, value_len); - break; - default: - return 0; - } - - return value_len; -} - -#if !SNMP_SAFE_REQUESTS - -static snmp_err_t -interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value) -{ - s32_t *sint_ptr = (s32_t*)value; - - /* stack should never call this method for another column, - because all other columns are set to readonly */ - LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); - LWIP_UNUSED_ARG(len); - - if (*sint_ptr == 1 || *sint_ptr == 2) { - return SNMP_ERR_NOERROR; - } - - return SNMP_ERR_WRONGVALUE; -} - -static snmp_err_t -interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value) -{ - struct netif *netif = (struct netif*)instance->reference.ptr; - s32_t *sint_ptr = (s32_t*)value; - - /* stack should never call this method for another column, - because all other columns are set to readonly */ - LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); - LWIP_UNUSED_ARG(len); - - if (*sint_ptr == 1) { - netif_set_up(netif); - } else if (*sint_ptr == 2) { - netif_set_down(netif); - } - - return SNMP_ERR_NOERROR; -} - -#endif /* SNMP_SAFE_REQUESTS */ - -static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value); - -static const struct snmp_table_col_def interfaces_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */ - { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */ - { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */ - { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */ - { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */ -#if !SNMP_SAFE_REQUESTS - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */ -#else - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */ -#endif - { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */ - { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */ - { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */ - { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */ - { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */ - { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */ - { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */ - { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */ - { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */ - { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */ - { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */ - { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */ - { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */ - { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */ - { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */ -}; - -#if !SNMP_SAFE_REQUESTS -static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, - interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); -#else -static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, - interfaces_Table_get_value, NULL, NULL); -#endif - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, interfaces_Number) -CREATE_LWIP_SYNC_NODE(2, interfaces_Table) - -static const struct snmp_node* const interface_nodes[] = { - &SYNC_NODE_NAME(interfaces_Number).node.node, - &SYNC_NODE_NAME(interfaces_Table).node.node -}; - -const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_ip.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_ip.c deleted file mode 100644 index 4f05180a39..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_ip.c +++ /dev/null @@ -1,743 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) IP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/stats.h" -#include "lwip/netif.h" -#include "lwip/ip.h" -#include "lwip/etharp.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -#if LWIP_IPV4 -/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ - -static s16_t -ip_get_value(struct snmp_node_instance* instance, void* value) -{ - s32_t* sint_ptr = (s32_t*)value; - u32_t* uint_ptr = (u32_t*)value; - - switch (instance->node->oid) { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - *sint_ptr = 1; -#else - /* not-forwarding */ - *sint_ptr = 2; -#endif - return sizeof(*sint_ptr); - case 2: /* ipDefaultTTL */ - *sint_ptr = IP_DEFAULT_TTL; - return sizeof(*sint_ptr); - case 3: /* ipInReceives */ - *uint_ptr = STATS_GET(mib2.ipinreceives); - return sizeof(*uint_ptr); - case 4: /* ipInHdrErrors */ - *uint_ptr = STATS_GET(mib2.ipinhdrerrors); - return sizeof(*uint_ptr); - case 5: /* ipInAddrErrors */ - *uint_ptr = STATS_GET(mib2.ipinaddrerrors); - return sizeof(*uint_ptr); - case 6: /* ipForwDatagrams */ - *uint_ptr = STATS_GET(mib2.ipforwdatagrams); - return sizeof(*uint_ptr); - case 7: /* ipInUnknownProtos */ - *uint_ptr = STATS_GET(mib2.ipinunknownprotos); - return sizeof(*uint_ptr); - case 8: /* ipInDiscards */ - *uint_ptr = STATS_GET(mib2.ipindiscards); - return sizeof(*uint_ptr); - case 9: /* ipInDelivers */ - *uint_ptr = STATS_GET(mib2.ipindelivers); - return sizeof(*uint_ptr); - case 10: /* ipOutRequests */ - *uint_ptr = STATS_GET(mib2.ipoutrequests); - return sizeof(*uint_ptr); - case 11: /* ipOutDiscards */ - *uint_ptr = STATS_GET(mib2.ipoutdiscards); - return sizeof(*uint_ptr); - case 12: /* ipOutNoRoutes */ - *uint_ptr = STATS_GET(mib2.ipoutnoroutes); - return sizeof(*uint_ptr); - case 13: /* ipReasmTimeout */ -#if IP_REASSEMBLY - *sint_ptr = IP_REASS_MAXAGE; -#else - *sint_ptr = 0; -#endif - return sizeof(*sint_ptr); - case 14: /* ipReasmReqds */ - *uint_ptr = STATS_GET(mib2.ipreasmreqds); - return sizeof(*uint_ptr); - case 15: /* ipReasmOKs */ - *uint_ptr = STATS_GET(mib2.ipreasmoks); - return sizeof(*uint_ptr); - case 16: /* ipReasmFails */ - *uint_ptr = STATS_GET(mib2.ipreasmfails); - return sizeof(*uint_ptr); - case 17: /* ipFragOKs */ - *uint_ptr = STATS_GET(mib2.ipfragoks); - return sizeof(*uint_ptr); - case 18: /* ipFragFails */ - *uint_ptr = STATS_GET(mib2.ipfragfails); - return sizeof(*uint_ptr); - case 19: /* ipFragCreates */ - *uint_ptr = STATS_GET(mib2.ipfragcreates); - return sizeof(*uint_ptr); - case 23: /* ipRoutingDiscards: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/** - * Test ip object value before setting. - * - * @param instance node instance - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value from. - * - * @note we allow set if the value matches the hardwired value, - * otherwise return badvalue. - */ -static snmp_err_t -ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - s32_t *sint_ptr = (s32_t*)value; - - LWIP_UNUSED_ARG(len); - switch (instance->node->oid) { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - if (*sint_ptr == 1) -#else - /* not-forwarding */ - if (*sint_ptr == 2) -#endif - { - ret = SNMP_ERR_NOERROR; - } - break; - case 2: /* ipDefaultTTL */ - if (*sint_ptr == IP_DEFAULT_TTL) { - ret = SNMP_ERR_NOERROR; - } - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return ret; -} - -static snmp_err_t -ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(instance); - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value); - /* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */ - return SNMP_ERR_NOERROR; -} - -/* --- ipAddrTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff } /* IP D */ -}; - -static snmp_err_t -ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - LWIP_UNUSED_ARG(value_len); - - switch (*column) { - case 1: /* ipAdEntAddr */ - value->u32 = netif_ip4_addr(netif)->addr; - break; - case 2: /* ipAdEntIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 3: /* ipAdEntNetMask */ - value->u32 = netif_ip4_netmask(netif)->addr; - break; - case 4: /* ipAdEntBcastAddr */ - /* lwIP oddity, there's no broadcast - address in the netif we can rely on */ - value->u32 = IPADDR_BROADCAST & 1; - break; - case 5: /* ipAdEntReasmMaxSize */ -#if IP_REASSEMBLY - /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, - * but only if receiving one fragmented packet at a time. - * The current solution is to calculate for 2 simultaneous packets... - */ - value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * - (PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN))); -#else - /** @todo returning MTU would be a bad thing and - returning a wild guess like '576' isn't good either */ - value->u32 = 0; -#endif - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_AddrTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t ip; - struct netif *netif; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ - - /* find netif with requested ip */ - netif = netif_list; - while (netif != NULL) { - if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) { - /* fill in object properties */ - return ip_AddrTable_get_cell_value_core(netif, column, value, value_len); - } - - netif = netif->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - netif = netif_list; - while (netif != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; - snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); - - netif = netif->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -/* --- ipRouteTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ -}; - -static snmp_err_t -ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - switch (*column) { - case 1: /* ipRouteDest */ - if (default_route) { - /* default rte has 0.0.0.0 dest */ - value->u32 = IP4_ADDR_ANY4->addr; - } else { - /* netifs have netaddress dest */ - ip4_addr_t tmp; - ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - value->u32 = tmp.addr; - } - break; - case 2: /* ipRouteIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 3: /* ipRouteMetric1 */ - if (default_route) { - value->s32 = 1; /* default */ - } else { - value->s32 = 0; /* normal */ - } - break; - case 4: /* ipRouteMetric2 */ - case 5: /* ipRouteMetric3 */ - case 6: /* ipRouteMetric4 */ - value->s32 = -1; /* none */ - break; - case 7: /* ipRouteNextHop */ - if (default_route) { - /* default rte: gateway */ - value->u32 = netif_ip4_gw(netif)->addr; - } else { - /* other rtes: netif ip_addr */ - value->u32 = netif_ip4_addr(netif)->addr; - } - break; - case 8: /* ipRouteType */ - if (default_route) { - /* default rte is indirect */ - value->u32 = 4; /* indirect */ - } else { - /* other rtes are direct */ - value->u32 = 3; /* direct */ - } - break; - case 9: /* ipRouteProto */ - /* locally defined routes */ - value->u32 = 2; /* local */ - break; - case 10: /* ipRouteAge */ - /* @todo (sysuptime - timestamp last change) / 100 */ - value->u32 = 0; - break; - case 11: /* ipRouteMask */ - if (default_route) { - /* default rte use 0.0.0.0 mask */ - value->u32 = IP4_ADDR_ANY4->addr; - } else { - /* other rtes use netmask */ - value->u32 = netif_ip4_netmask(netif)->addr; - } - break; - case 12: /* ipRouteMetric5 */ - value->s32 = -1; /* none */ - break; - case 13: /* ipRouteInfo */ - value->const_ptr = snmp_zero_dot_zero.id; - *value_len = snmp_zero_dot_zero.len * sizeof(u32_t); - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_RouteTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t test_ip; - struct netif *netif; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP and port from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */ - - /* default route is on default netif */ - if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) { - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len); - } - - /* find netif with requested route */ - netif = netif_list; - while (netif != NULL) { - ip4_addr_t dst; - ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - - if (ip4_addr_cmp(&dst, &test_ip)) { - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len); - } - - netif = netif->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; - u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)); - - /* check default route */ - if (netif_default != NULL) { - snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]); - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); - } - - /* iterate over all possible OIDs to find the next one */ - netif = netif_list; - while (netif != NULL) { - ip4_addr_t dst; - ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - - /* check generated OID: is it a candidate for the next one? */ - if (!ip4_addr_isany_val(dst)) { - snmp_ip4_to_oid(&dst, &test_oid[0]); - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); - } - - netif = netif->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - ip4_addr_t dst; - snmp_oid_to_ip4(&result_temp[0], &dst); - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -#if LWIP_ARP && LWIP_IPV4 -/* --- ipNetToMediaTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = { - { 1, 0xff }, /* IfIndex */ - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff } /* IP D */ -}; - -static snmp_err_t -ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t *ip; - struct netif *netif; - struct eth_addr *ethaddr; - - etharp_get_entry(arp_table_index, &ip, &netif, ðaddr); - - /* value */ - switch (*column) { - case 1: /* atIfIndex / ipNetToMediaIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 2: /* atPhysAddress / ipNetToMediaPhysAddress */ - value->ptr = ethaddr; - *value_len = sizeof(*ethaddr); - break; - case 3: /* atNetAddress / ipNetToMediaNetAddress */ - value->u32 = ip->addr; - break; - case 4: /* ipNetToMediaType */ - value->u32 = 3; /* dynamic*/ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_NetToMediaTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t ip_in; - u8_t netif_index; - u8_t i; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP from incoming OID */ - netif_index = (u8_t)row_oid[0]; - snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */ - - /* find requested entry */ - for (i=0; iid, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - for (i=0; i - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_scalar.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#define MIB2_AUTH_TRAPS_ENABLED 1 -#define MIB2_AUTH_TRAPS_DISABLED 2 - -/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */ -static s16_t -snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t*)value; - switch (node->oid) { - case 1: /* snmpInPkts */ - *uint_ptr = snmp_stats.inpkts; - break; - case 2: /* snmpOutPkts */ - *uint_ptr = snmp_stats.outpkts; - break; - case 3: /* snmpInBadVersions */ - *uint_ptr = snmp_stats.inbadversions; - break; - case 4: /* snmpInBadCommunityNames */ - *uint_ptr = snmp_stats.inbadcommunitynames; - break; - case 5: /* snmpInBadCommunityUses */ - *uint_ptr = snmp_stats.inbadcommunityuses; - break; - case 6: /* snmpInASNParseErrs */ - *uint_ptr = snmp_stats.inasnparseerrs; - break; - case 8: /* snmpInTooBigs */ - *uint_ptr = snmp_stats.intoobigs; - break; - case 9: /* snmpInNoSuchNames */ - *uint_ptr = snmp_stats.innosuchnames; - break; - case 10: /* snmpInBadValues */ - *uint_ptr = snmp_stats.inbadvalues; - break; - case 11: /* snmpInReadOnlys */ - *uint_ptr = snmp_stats.inreadonlys; - break; - case 12: /* snmpInGenErrs */ - *uint_ptr = snmp_stats.ingenerrs; - break; - case 13: /* snmpInTotalReqVars */ - *uint_ptr = snmp_stats.intotalreqvars; - break; - case 14: /* snmpInTotalSetVars */ - *uint_ptr = snmp_stats.intotalsetvars; - break; - case 15: /* snmpInGetRequests */ - *uint_ptr = snmp_stats.ingetrequests; - break; - case 16: /* snmpInGetNexts */ - *uint_ptr = snmp_stats.ingetnexts; - break; - case 17: /* snmpInSetRequests */ - *uint_ptr = snmp_stats.insetrequests; - break; - case 18: /* snmpInGetResponses */ - *uint_ptr = snmp_stats.ingetresponses; - break; - case 19: /* snmpInTraps */ - *uint_ptr = snmp_stats.intraps; - break; - case 20: /* snmpOutTooBigs */ - *uint_ptr = snmp_stats.outtoobigs; - break; - case 21: /* snmpOutNoSuchNames */ - *uint_ptr = snmp_stats.outnosuchnames; - break; - case 22: /* snmpOutBadValues */ - *uint_ptr = snmp_stats.outbadvalues; - break; - case 24: /* snmpOutGenErrs */ - *uint_ptr = snmp_stats.outgenerrs; - break; - case 25: /* snmpOutGetRequests */ - *uint_ptr = snmp_stats.outgetrequests; - break; - case 26: /* snmpOutGetNexts */ - *uint_ptr = snmp_stats.outgetnexts; - break; - case 27: /* snmpOutSetRequests */ - *uint_ptr = snmp_stats.outsetrequests; - break; - case 28: /* snmpOutGetResponses */ - *uint_ptr = snmp_stats.outgetresponses; - break; - case 29: /* snmpOutTraps */ - *uint_ptr = snmp_stats.outtraps; - break; - case 30: /* snmpEnableAuthenTraps */ - if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) { - *uint_ptr = MIB2_AUTH_TRAPS_DISABLED; - } else { - *uint_ptr = MIB2_AUTH_TRAPS_ENABLED; - } - break; - case 31: /* snmpSilentDrops */ - *uint_ptr = 0; /* not supported */ - break; - case 32: /* snmpProxyDrops */ - *uint_ptr = 0; /* not supported */ - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - return sizeof(*uint_ptr); -} - -static snmp_err_t -snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - LWIP_UNUSED_ARG(len); - - if (node->oid == 30) { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t*)value; - - /* we should have writable non-volatile mem here */ - if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) { - ret = SNMP_ERR_NOERROR; - } - } - return ret; -} - -static snmp_err_t -snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(len); - - if (node->oid == 30) { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t*)value; - if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) { - snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED); - } else { - snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED); - } - } - - return SNMP_ERR_NOERROR; -} - -/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ -static const struct snmp_scalar_array_node_def snmp_nodes[] = { - { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ - { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ - { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */ - { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */ - { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */ - { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */ - { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */ - { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */ - {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */ - {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */ - {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */ - {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */ - {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */ - {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */ - {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */ - {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */ - {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */ - {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */ - {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */ - {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */ - {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */ - {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */ - {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */ - {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */ - {27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */ - {28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */ - {29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */ - {30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */ - {31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */ - {32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */ -}; - -const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_system.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_system.c deleted file mode 100644 index 90e57805d2..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_system.c +++ /dev/null @@ -1,377 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) SYSTEM objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/sys.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ - -/** mib-2.system.sysDescr */ -static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; -static const u8_t* sysdescr = sysdescr_default; -static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */ - -/** mib-2.system.sysContact */ -static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; -static const u8_t* syscontact = syscontact_default; -static const u16_t* syscontact_len = NULL; /* use strlen for determining len */ -static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ -static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ -static u16_t syscontact_bufsize = 0; /* 0=not writable */ - -/** mib-2.system.sysName */ -static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; -static const u8_t* sysname = sysname_default; -static const u16_t* sysname_len = NULL; /* use strlen for determining len */ -static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ -static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ -static u16_t sysname_bufsize = 0; /* 0=not writable */ - -/** mib-2.system.sysLocation */ -static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; -static const u8_t* syslocation = syslocation_default; -static const u16_t* syslocation_len = NULL; /* use strlen for determining len */ -static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ -static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ -static u16_t syslocation_bufsize = 0; /* 0=not writable */ - -/** - * @ingroup snmp_mib2 - * Initializes sysDescr pointers. - * - * @param str if non-NULL then copy str pointer - * @param len points to string length, excluding zero terminator - */ -void -snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) -{ - if (str != NULL) { - sysdescr = str; - sysdescr_len = len; - } -} - -/** - * @ingroup snmp_mib2 - * Initializes sysContact pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - syscontact = ocstr; - syscontact_wr = ocstr; - syscontact_len = ocstrlen; - syscontact_wr_len = ocstrlen; - syscontact_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_syscontact but set pointer to readonly memory - */ -void -snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - syscontact = ocstr; - syscontact_len = ocstrlen; - syscontact_wr = NULL; - syscontact_wr_len = NULL; - syscontact_bufsize = 0; - } -} - - -/** - * @ingroup snmp_mib2 - * Initializes sysName pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - sysname = ocstr; - sysname_wr = ocstr; - sysname_len = ocstrlen; - sysname_wr_len = ocstrlen; - sysname_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_sysname but set pointer to readonly memory - */ -void -snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - sysname = ocstr; - sysname_len = ocstrlen; - sysname_wr = NULL; - sysname_wr_len = NULL; - sysname_bufsize = 0; - } -} - -/** - * @ingroup snmp_mib2 - * Initializes sysLocation pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - syslocation = ocstr; - syslocation_wr = ocstr; - syslocation_len = ocstrlen; - syslocation_wr_len = ocstrlen; - syslocation_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_syslocation but set pointer to readonly memory - */ -void -snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - syslocation = ocstr; - syslocation_len = ocstrlen; - syslocation_wr = NULL; - syslocation_wr_len = NULL; - syslocation_bufsize = 0; - } -} - - -static s16_t -system_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - const u8_t* var = NULL; - const s16_t* var_len; - u16_t result; - - switch (node->oid) { - case 1: /* sysDescr */ - var = sysdescr; - var_len = (const s16_t*)sysdescr_len; - break; - case 2: /* sysObjectID */ - { - const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid(); - MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); - return dev_enterprise_oid->len * sizeof(u32_t); - } - case 3: /* sysUpTime */ - MIB2_COPY_SYSUPTIME_TO((u32_t*)value); - return sizeof(u32_t); - case 4: /* sysContact */ - var = syscontact; - var_len = (const s16_t*)syscontact_len; - break; - case 5: /* sysName */ - var = sysname; - var_len = (const s16_t*)sysname_len; - break; - case 6: /* sysLocation */ - var = syslocation; - var_len = (const s16_t*)syslocation_len; - break; - case 7: /* sysServices */ - *(s32_t*)value = SNMP_SYSSERVICES; - return sizeof(s32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - /* handle string values (OID 1,4,5 and 6) */ - LWIP_ASSERT("", (value != NULL)); - if (var_len == NULL) { - result = (s16_t)strlen((const char*)var); - } else { - result = *var_len; - } - MEMCPY(value, var, result); - return result; -} - -static snmp_err_t -system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - const u16_t* var_bufsize = NULL; - const u16_t* var_wr_len; - - LWIP_UNUSED_ARG(value); - - switch (node->oid) { - case 4: /* sysContact */ - var_bufsize = &syscontact_bufsize; - var_wr_len = syscontact_wr_len; - break; - case 5: /* sysName */ - var_bufsize = &sysname_bufsize; - var_wr_len = sysname_wr_len; - break; - case 6: /* sysLocation */ - var_bufsize = &syslocation_bufsize; - var_wr_len = syslocation_wr_len; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid)); - return ret; - } - - /* check if value is writable at all */ - if (*var_bufsize > 0) { - if (var_wr_len == NULL) { - /* we have to take the terminating 0 into account */ - if (len < *var_bufsize) { - ret = SNMP_ERR_NOERROR; - } - } else { - if (len <= *var_bufsize) { - ret = SNMP_ERR_NOERROR; - } - } - } else { - ret = SNMP_ERR_NOTWRITABLE; - } - - return ret; -} - -static snmp_err_t -system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - u8_t* var_wr = NULL; - u16_t* var_wr_len; - - switch (node->oid) { - case 4: /* sysContact */ - var_wr = syscontact_wr; - var_wr_len = syscontact_wr_len; - break; - case 5: /* sysName */ - var_wr = sysname_wr; - var_wr_len = sysname_wr_len; - break; - case 6: /* sysLocation */ - var_wr = syslocation_wr; - var_wr_len = syslocation_wr_len; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid)); - return SNMP_ERR_GENERROR; - } - - /* no need to check size of target buffer, this was already done in set_test method */ - LWIP_ASSERT("", var_wr != NULL); - MEMCPY(var_wr, value, len); - - if (var_wr_len == NULL) { - /* add terminating 0 */ - var_wr[len] = 0; - } else { - *var_wr_len = len; - } - - return SNMP_ERR_NOERROR; -} - -static const struct snmp_scalar_array_node_def system_nodes[] = { - {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ - {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ - {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ - {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ - {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ - {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ - {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ -}; - -const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_tcp.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_tcp.c deleted file mode 100644 index 21f6965662..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_tcp.c +++ /dev/null @@ -1,594 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) TCP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ - -static s16_t -tcp_get_value(struct snmp_node_instance* instance, void* value) -{ - u32_t *uint_ptr = (u32_t*)value; - s32_t *sint_ptr = (s32_t*)value; - - switch (instance->node->oid) { - case 1: /* tcpRtoAlgorithm, vanj(4) */ - *sint_ptr = 4; - return sizeof(*sint_ptr); - case 2: /* tcpRtoMin */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 1000; - return sizeof(*sint_ptr); - case 3: /* tcpRtoMax */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 60000; - return sizeof(*sint_ptr); - case 4: /* tcpMaxConn */ - *sint_ptr = MEMP_NUM_TCP_PCB; - return sizeof(*sint_ptr); - case 5: /* tcpActiveOpens */ - *uint_ptr = STATS_GET(mib2.tcpactiveopens); - return sizeof(*uint_ptr); - case 6: /* tcpPassiveOpens */ - *uint_ptr = STATS_GET(mib2.tcppassiveopens); - return sizeof(*uint_ptr); - case 7: /* tcpAttemptFails */ - *uint_ptr = STATS_GET(mib2.tcpattemptfails); - return sizeof(*uint_ptr); - case 8: /* tcpEstabResets */ - *uint_ptr = STATS_GET(mib2.tcpestabresets); - return sizeof(*uint_ptr); - case 9: /* tcpCurrEstab */ - { - u16_t tcpcurrestab = 0; - struct tcp_pcb *pcb = tcp_active_pcbs; - while (pcb != NULL) { - if ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT)) { - tcpcurrestab++; - } - pcb = pcb->next; - } - *uint_ptr = tcpcurrestab; - } - return sizeof(*uint_ptr); - case 10: /* tcpInSegs */ - *uint_ptr = STATS_GET(mib2.tcpinsegs); - return sizeof(*uint_ptr); - case 11: /* tcpOutSegs */ - *uint_ptr = STATS_GET(mib2.tcpoutsegs); - return sizeof(*uint_ptr); - case 12: /* tcpRetransSegs */ - *uint_ptr = STATS_GET(mib2.tcpretranssegs); - return sizeof(*uint_ptr); - case 14: /* tcpInErrs */ - *uint_ptr = STATS_GET(mib2.tcpinerrs); - return sizeof(*uint_ptr); - case 15: /* tcpOutRsts */ - *uint_ptr = STATS_GET(mib2.tcpoutrsts); - return sizeof(*uint_ptr); - case 17: /* tcpHCInSegs */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - case 18: /* tcpHCOutSegs */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/* --- tcpConnTable --- */ - -#if LWIP_IPV4 - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 0, 0xffff }, /* Port */ - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 0, 0xffff } /* Port */ -}; - -static snmp_err_t -tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - LWIP_UNUSED_ARG(value_len); - - /* value */ - switch (*column) { - case 1: /* tcpConnState */ - value->u32 = pcb->state + 1; - break; - case 2: /* tcpConnLocalAddress */ - value->u32 = ip_2_ip4(&pcb->local_ip)->addr; - break; - case 3: /* tcpConnLocalPort */ - value->u32 = pcb->local_port; - break; - case 4: /* tcpConnRemAddress */ - if (pcb->state == LISTEN) { - value->u32 = IP4_ADDR_ANY4->addr; - } else { - value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; - } - break; - case 5: /* tcpConnRemPort */ - if (pcb->state == LISTEN) { - value->u32 = 0; - } else { - value->u32 = pcb->remote_port; - } - break; - default: - LWIP_ASSERT("invalid id", 0); - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - u8_t i; - ip4_addr_t local_ip; - ip4_addr_t remote_ip; - u16_t local_port; - u16_t remote_port; - struct tcp_pcb *pcb; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IPs and ports from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ - local_port = (u16_t)row_oid[4]; - snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ - remote_port = (u16_t)row_oid[9]; - - /* find tcp_pcb with requested ips and ports */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - pcb = *tcp_pcb_lists[i]; - - while (pcb != NULL) { - /* do local IP and local port match? */ - if (IP_IS_V4_VAL(pcb->local_ip) && - ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { - - /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ - if (pcb->state == LISTEN) { - if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); - } - } else { - if (IP_IS_V4_VAL(pcb->remote_ip) && - ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); - } - } - } - - pcb = pcb->next; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - u8_t i; - struct tcp_pcb *pcb; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - pcb = *tcp_pcb_lists[i]; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - - if (IP_IS_V4_VAL(pcb->local_ip)) { - snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); - test_oid[4] = pcb->local_port; - - /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ - if (pcb->state == LISTEN) { - snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); - test_oid[9] = 0; - } else { - if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ - continue; - } - snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); - test_oid[9] = pcb->remote_port; - } - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); - } - - pcb = pcb->next; - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -#endif /* LWIP_IPV4 */ - -/* --- tcpConnectionTable --- */ - -static snmp_err_t -tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) -{ - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ - switch (*column) { - case 7: /* tcpConnectionState */ - value->u32 = pcb->state + 1; - break; - case 8: /* tcpConnectionProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip_addr_t local_ip, remote_ip; - u16_t local_port, remote_port; - struct tcp_pcb *pcb; - u8_t idx = 0; - u8_t i; - struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; - - LWIP_UNUSED_ARG(value_len); - - /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find tcp_pcb with requested ip and port*/ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { - pcb = *tcp_pcb_nonlisten_lists[i]; - - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port) && - ip_addr_cmp(&remote_ip, &pcb->remote_ip) && - (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); - } - pcb = pcb->next; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct tcp_pcb *pcb; - struct snmp_next_oid_state state; - /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort - * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ - u32_t result_temp[38]; - u8_t i; - struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { - pcb = *tcp_pcb_nonlisten_lists[i]; - - while (pcb != NULL) { - u8_t idx = 0; - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - - /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ - idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, pcb); - - pcb = pcb->next; - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -/* --- tcpListenerTable --- */ - -static snmp_err_t -tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) -{ - /* all items except tcpListenerProcess are declared as not-accessible */ - switch (*column) { - case 4: /* tcpListenerProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip_addr_t local_ip; - u16_t local_port; - struct tcp_pcb_listen *pcb; - u8_t idx = 0; - - LWIP_UNUSED_ARG(value_len); - - /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find tcp_pcb with requested ip and port*/ - pcb = tcp_listen_pcbs.listen_pcbs; - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port)) { - /* fill in object properties */ - return tcp_ListenerTable_get_cell_value_core(column, value); - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct tcp_pcb_listen *pcb; - struct snmp_next_oid_state state; - /* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ - u32_t result_temp[19]; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - pcb = tcp_listen_pcbs.listen_pcbs; - while (pcb != NULL) { - u8_t idx = 0; - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - - /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, NULL); - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ListenerTable_get_cell_value_core(column, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); -static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); -static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); - -#if LWIP_IPV4 -static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ - { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ - { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ - { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ -}; - -static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ - { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ -}; - -static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); - - -static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { - /* all items except tcpListenerProcess are declared as not-accessible */ - { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ -}; - -static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) -CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) -CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) -CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) -CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) -CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) -CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) -CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) -CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) -CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) -CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) -CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) -#if LWIP_IPV4 -CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) -#endif /* LWIP_IPV4 */ -CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) -CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) -CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) -CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) -CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) -CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) - -static const struct snmp_node* const tcp_nodes[] = { - &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, - &SYNC_NODE_NAME(tcp_RtoMin).node.node, - &SYNC_NODE_NAME(tcp_RtoMax).node.node, - &SYNC_NODE_NAME(tcp_MaxConn).node.node, - &SYNC_NODE_NAME(tcp_ActiveOpens).node.node, - &SYNC_NODE_NAME(tcp_PassiveOpens).node.node, - &SYNC_NODE_NAME(tcp_AttemptFails).node.node, - &SYNC_NODE_NAME(tcp_EstabResets).node.node, - &SYNC_NODE_NAME(tcp_CurrEstab).node.node, - &SYNC_NODE_NAME(tcp_InSegs).node.node, - &SYNC_NODE_NAME(tcp_OutSegs).node.node, - &SYNC_NODE_NAME(tcp_RetransSegs).node.node, -#if LWIP_IPV4 - &SYNC_NODE_NAME(tcp_ConnTable).node.node, -#endif /* LWIP_IPV4 */ - &SYNC_NODE_NAME(tcp_InErrs).node.node, - &SYNC_NODE_NAME(tcp_OutRsts).node.node, - &SYNC_NODE_NAME(tcp_HCInSegs).node.node, - &SYNC_NODE_NAME(tcp_HCOutSegs).node.node, - &SYNC_NODE_NAME(tcp_ConnectionTable).node.node, - &SYNC_NODE_NAME(tcp_ListenerTable).node.node -}; - -const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_udp.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_udp.c deleted file mode 100644 index 6a983df20b..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_mib2_udp.c +++ /dev/null @@ -1,357 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) UDP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/udp.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ - -static s16_t -udp_get_value(struct snmp_node_instance* instance, void* value) -{ - u32_t *uint_ptr = (u32_t*)value; - - switch (instance->node->oid) { - case 1: /* udpInDatagrams */ - *uint_ptr = STATS_GET(mib2.udpindatagrams); - return sizeof(*uint_ptr); - case 2: /* udpNoPorts */ - *uint_ptr = STATS_GET(mib2.udpnoports); - return sizeof(*uint_ptr); - case 3: /* udpInErrors */ - *uint_ptr = STATS_GET(mib2.udpinerrors); - return sizeof(*uint_ptr); - case 4: /* udpOutDatagrams */ - *uint_ptr = STATS_GET(mib2.udpoutdatagrams); - return sizeof(*uint_ptr); - case 8: /* udpHCInDatagrams */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - case 9: /* udpHCOutDatagrams */ - memset(value, 0, 2*sizeof(u32_t)); /* not supported */ - return 2*sizeof(u32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/* --- udpEndpointTable --- */ - -static snmp_err_t -udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) -{ - /* all items except udpEndpointProcess are declared as not-accessible */ - switch (*column) { - case 8: /* udpEndpointProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip_addr_t local_ip, remote_ip; - u16_t local_port, remote_port; - struct udp_pcb *pcb; - u8_t idx = 0; - - LWIP_UNUSED_ARG(value_len); - - /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* udpEndpointInstance */ - if (row_oid_len < (idx+1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (row_oid[idx] != 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find udp_pcb with requested ip and port*/ - pcb = udp_pcbs; - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port) && - ip_addr_cmp(&remote_ip, &pcb->remote_ip) && - (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return udp_endpointTable_get_cell_value_core(column, value); - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct udp_pcb *pcb; - struct snmp_next_oid_state state; - /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + - * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + - * 1x udpEndpointInstance = 39 - */ - u32_t result_temp[39]; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - pcb = udp_pcbs; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - u8_t idx = 0; - - /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ - idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); - - test_oid[idx] = 0; /* udpEndpointInstance */ - idx++; - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, NULL); - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return udp_endpointTable_get_cell_value_core(column, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -/* --- udpTable --- */ - -#if LWIP_IPV4 - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range udp_Table_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 1, 0xffff } /* Port */ -}; - -static snmp_err_t -udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) -{ - LWIP_UNUSED_ARG(value_len); - - switch (*column) { - case 1: /* udpLocalAddress */ - /* set reference to PCB local IP and return a generic node that copies IP4 addresses */ - value->u32 = ip_2_ip4(&pcb->local_ip)->addr; - break; - case 2: /* udpLocalPort */ - /* set reference to PCB local port and return a generic node that copies u16_t values */ - value->u32 = pcb->local_port; - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -udp_Table_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) -{ - ip4_addr_t ip; - u16_t port; - struct udp_pcb *pcb; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP and port from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ - port = (u16_t)row_oid[4]; - - /* find udp_pcb with requested ip and port*/ - pcb = udp_pcbs; - while (pcb != NULL) { - if (IP_IS_V4_VAL(pcb->local_ip)) { - if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { - /* fill in object properties */ - return udp_Table_get_cell_value_core(pcb, column, value, value_len); - } - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) -{ - struct udp_pcb *pcb; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - pcb = udp_pcbs; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; - - if (IP_IS_V4_VAL(pcb->local_ip)) { - snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); - test_oid[4] = pcb->local_port; - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); - } - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -#endif /* LWIP_IPV4 */ - -static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); -static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); - -#if LWIP_IPV4 -static const struct snmp_table_simple_col_def udp_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ - { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ -}; -static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { - /* all items except udpEndpointProcess are declared as not-accessible */ - { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ -}; - -static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) -CREATE_LWIP_SYNC_NODE(2, udp_noPorts) -CREATE_LWIP_SYNC_NODE(3, udp_inErrors) -CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) -#if LWIP_IPV4 -CREATE_LWIP_SYNC_NODE(5, udp_Table) -#endif /* LWIP_IPV4 */ -CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) -CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) -CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) - -static const struct snmp_node* const udp_nodes[] = { - &SYNC_NODE_NAME(udp_inDatagrams).node.node, - &SYNC_NODE_NAME(udp_noPorts).node.node, - &SYNC_NODE_NAME(udp_inErrors).node.node, - &SYNC_NODE_NAME(udp_outDatagrams).node.node, -#if LWIP_IPV4 - &SYNC_NODE_NAME(udp_Table).node.node, -#endif /* LWIP_IPV4 */ - &SYNC_NODE_NAME(udp_endpointTable).node.node, - &SYNC_NODE_NAME(udp_HCInDatagrams).node.node, - &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node -}; - -const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.c deleted file mode 100644 index 0cb7ca997c..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.c +++ /dev/null @@ -1,1668 +0,0 @@ -/** - * @file - * SNMP message processing (RFC1157). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_msg.h" -#include "snmp_asn1.h" -#include "snmp_core_priv.h" -#include "lwip/ip_addr.h" -#include "lwip/stats.h" - -#if LWIP_SNMP_V3 -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#ifdef LWIP_SNMPV3_INCLUDE_ENGINE -#include LWIP_SNMPV3_INCLUDE_ENGINE -#endif -#endif - -#include - -/* public (non-static) constants */ -/** SNMP community string */ -const char *snmp_community = SNMP_COMMUNITY; -/** SNMP community string for write access */ -const char *snmp_community_write = SNMP_COMMUNITY_WRITE; -/** SNMP community string for sending traps */ -const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; - -snmp_write_callback_fct snmp_write_callback = NULL; -void* snmp_write_callback_arg = NULL; - -/** - * @ingroup snmp_core - * Returns current SNMP community string. - * @return current SNMP community string - */ -const char * -snmp_get_community(void) -{ - return snmp_community; -} - -/** - * @ingroup snmp_core - * Sets SNMP community string. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new community string - */ -void -snmp_set_community(const char * const community) -{ - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community = community; -} - -/** - * @ingroup snmp_core - * Returns current SNMP write-access community string. - * @return current SNMP write-access community string - */ -const char * -snmp_get_community_write(void) -{ - return snmp_community_write; -} - -/** - * @ingroup snmp_traps - * Returns current SNMP community string used for sending traps. - * @return current SNMP community string used for sending traps - */ -const char * -snmp_get_community_trap(void) -{ - return snmp_community_trap; -} - -/** - * @ingroup snmp_core - * Sets SNMP community string for write-access. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new write-access community string - */ -void -snmp_set_community_write(const char * const community) -{ - LWIP_ASSERT("community string must not be NULL", community != NULL); - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community_write = community; -} - -/** - * @ingroup snmp_traps - * Sets SNMP community string used for sending traps. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new trap community string - */ -void -snmp_set_community_trap(const char * const community) -{ - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community_trap = community; -} - -/** - * @ingroup snmp_core - * Callback fired on every successful write access - */ -void -snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg) -{ - snmp_write_callback = write_callback; - snmp_write_callback_arg = callback_arg; -} - -/* ----------------------------------------------------------------------- */ -/* forward declarations */ -/* ----------------------------------------------------------------------- */ - -static err_t snmp_process_get_request(struct snmp_request *request); -static err_t snmp_process_getnext_request(struct snmp_request *request); -static err_t snmp_process_getbulk_request(struct snmp_request *request); -static err_t snmp_process_set_request(struct snmp_request *request); - -static err_t snmp_parse_inbound_frame(struct snmp_request *request); -static err_t snmp_prepare_outbound_frame(struct snmp_request *request); -static err_t snmp_complete_outbound_frame(struct snmp_request *request); -static void snmp_execute_write_callbacks(struct snmp_request *request); - - -/* ----------------------------------------------------------------------- */ -/* implementation */ -/* ----------------------------------------------------------------------- */ - -void -snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) -{ - err_t err; - struct snmp_request request; - - memset(&request, 0, sizeof(request)); - request.handle = handle; - request.source_ip = source_ip; - request.source_port = port; - request.inbound_pbuf = p; - - snmp_stats.inpkts++; - - err = snmp_parse_inbound_frame(&request); - if (err == ERR_OK) { - err = snmp_prepare_outbound_frame(&request); - if (err == ERR_OK) { - - if (request.error_status == SNMP_ERR_NOERROR) { - /* only process frame if we do not already have an error to return (e.g. all readonly) */ - if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { - err = snmp_process_get_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { - err = snmp_process_getnext_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - err = snmp_process_getbulk_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - err = snmp_process_set_request(&request); - } - } - - if (err == ERR_OK) { - err = snmp_complete_outbound_frame(&request); - - if (err == ERR_OK) { - err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); - - if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) - && (request.error_status == SNMP_ERR_NOERROR) - && (snmp_write_callback != NULL)) { - /* raise write notification for all written objects */ - snmp_execute_write_callbacks(&request); - } - } - } - } - - if (request.outbound_pbuf != NULL) { - pbuf_free(request.outbound_pbuf); - } - } -} - -static u8_t -snmp_msg_getnext_validate_node_inst(struct snmp_node_instance* node_instance, void* validate_arg) -{ - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request*)validate_arg)->version == SNMP_VERSION_1)) { - /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static void -snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) -{ - err_t err; - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - - if (get_next) { - struct snmp_obj_id result_oid; - request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance); - - if (request->error_status == SNMP_ERR_NOERROR) { - snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); - } - } else { - request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); - - if (request->error_status == SNMP_ERR_NOERROR) { - /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ - request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); - - if (request->error_status != SNMP_ERR_NOERROR) { - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } - } - - if (request->error_status != SNMP_ERR_NOERROR) { - if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { - if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { - /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ - vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); - vb->value_len = 0; - - err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb); - if (err == ERR_OK) { - /* we stored the exception in varbind -> go on */ - request->error_status = SNMP_ERR_NOERROR; - } else if (err == ERR_BUF) { - request->error_status = SNMP_ERR_TOOBIG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - } else { - /* according to RFC 1157/1905, all other errors only return genError */ - request->error_status = SNMP_ERR_GENERROR; - } - } else { - s16_t len = node_instance.get_value(&node_instance, vb->value); - vb->type = node_instance.asn1_type; - - if(len >= 0) { - vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */ - - LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); - err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb); - - if (err == ERR_BUF) { - request->error_status = SNMP_ERR_TOOBIG; - } else if (err != ERR_OK) { - request->error_status = SNMP_ERR_GENERROR; - } - } else { - request->error_status = SNMP_ERR_GENERROR; - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } -} - - -/** - * Service an internal or external event for SNMP GET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_get_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n")); - - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { - snmp_process_varbind(request, &vb, 0); - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP GET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_getnext_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n")); - - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { - snmp_process_varbind(request, &vb, 1); - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP GETBULKT. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_getbulk_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - s32_t non_repeaters = request->non_repeaters; - s32_t repetitions; - u16_t repetition_offset = 0; - struct snmp_varbind_enumerator repetition_varbind_enumerator; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) { - repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS); - } else { - repetitions = request->max_repetitions; - } - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n")); - - /* process non repeaters and first repetition */ - while (request->error_status == SNMP_ERR_NOERROR) { - if (non_repeaters == 0) { - repetition_offset = request->outbound_pbuf_stream.offset; - - if (repetitions == 0) { - /* do not resolve repeaters when repetitions is set to 0 */ - break; - } - repetitions--; - } - - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) { - request->error_status = SNMP_ERR_GENERROR; - } else { - snmp_process_varbind(request, &vb, 1); - non_repeaters--; - } - } - - /* process repetitions > 1 */ - while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) { - - u8_t all_endofmibview = 1; - - snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset); - repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */ - - while (request->error_status == SNMP_ERR_NOERROR) { - vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */ - err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - vb.value = request->value_buffer; - snmp_process_varbind(request, &vb, 1); - - if (request->error_status != SNMP_ERR_NOERROR) { - /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */ - request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; - } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) { - all_endofmibview = 0; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else { - LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!")); - request->error_status = SNMP_ERR_GENERROR; - request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; - } - } - - if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) { - /* stop when all varbinds in a loop return EndOfMibView */ - break; - } - - repetitions--; - } - - if (request->error_status == SNMP_ERR_TOOBIG) { - /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */ - request->error_status = SNMP_ERR_NOERROR; - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP SET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_set_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n")); - - /* perform set test on all objects */ - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - - request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) { - if (node_instance.asn1_type != vb.type) { - request->error_status = SNMP_ERR_WRONGTYPE; - } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { - request->error_status = SNMP_ERR_NOTWRITABLE; - } else { - if (node_instance.set_test != NULL) { - request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value); - } - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { - request->error_status = SNMP_ERR_WRONGLENGTH; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - /* perform real set operation on all objects */ - if (request->error_status == SNMP_ERR_NOERROR) { - snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) { - if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { - if (request->inbound_varbind_enumerator.varbind_count == 1) { - request->error_status = SNMP_ERR_COMMITFAILED; - } else { - /* we cannot undo the set operations done so far */ - request->error_status = SNMP_ERR_UNDOFAILED; - } - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else { - /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */ - request->error_status = SNMP_ERR_GENERROR; - } - } - } - - return ERR_OK; -} - -#define PARSE_EXEC(code, retValue) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ - snmp_stats.inasnparseerrs++; \ - return retValue; \ - } - -#define PARSE_ASSERT(cond, retValue) \ - if (!(cond)) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ - snmp_stats.inasnparseerrs++; \ - return retValue; \ - } - -#define BUILD_EXEC(code, retValue) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ - return retValue; \ - } - -#define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG) -#define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG) - -/** - * Checks and decodes incoming SNMP message header, logs header errors. - * - * @param request points to the current message request state return - * @return - * - ERR_OK SNMP header is sane and accepted - * - ERR_VAL SNMP header is either malformed or rejected - */ -static err_t -snmp_parse_inbound_frame(struct snmp_request *request) -{ - struct snmp_pbuf_stream pbuf_stream; - struct snmp_asn1_tlv tlv; - s32_t parent_tlv_value_len; - s32_t s32_value; - err_t err; - - IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - - /* decode main container consisting of version, community and PDU */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length)); - parent_tlv_value_len = tlv.value_len; - - /* decode version */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - if ((s32_value != SNMP_VERSION_1) && - (s32_value != SNMP_VERSION_2c) -#if LWIP_SNMP_V3 - && (s32_value != SNMP_VERSION_3) -#endif - ) - { - /* unsupported SNMP version */ - snmp_stats.inbadversions++; - return ERR_ARG; - } - request->version = (u8_t)s32_value; - -#if LWIP_SNMP_V3 - if (request->version == SNMP_VERSION_3) { - u16_t u16_value; - u16_t inbound_msgAuthenticationParameters_offset; - - /* SNMPv3 doesn't use communities */ - /* @todo: Differentiate read/write access */ - strcpy((char*)request->community, snmp_community); - request->community_strlen = (u16_t)strlen(snmp_community); - - /* RFC3414 globalData */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* decode msgID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_id = s32_value; - - /* decode msgMaxSize */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_max_size = s32_value; - - /* decode msgFlags */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_flags = (u8_t)s32_value; - - /* decode msgSecurityModel */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_security_model = s32_value; - - /* RFC3414 msgSecurityParameters - * The User-based Security Model defines the contents of the OCTET - * STRING as a SEQUENCE. - * - * We skip the protective dummy OCTET STRING header - * to access the SEQUENCE header. - */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* msgSecurityParameters SEQUENCE header */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* decode msgAuthoritativeEngineID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->msg_authoritative_engine_id_len = (u8_t)u16_value; - - /* msgAuthoritativeEngineBoots */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots)); - - /* msgAuthoritativeEngineTime */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); - /* @todo: Implement time window checking */ - - /* msgUserName */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, - &u16_value, SNMP_V3_MAX_USER_LENGTH)); - request->msg_user_name_len = (u8_t)u16_value; - /* @todo: Implement unknown user error response */ - IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, NULL, NULL)); - - /* msgAuthenticationParameters */ - memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - /* Remember position */ - inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; - LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); - /* Read auth parameters */ - IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, - &u16_value, tlv.value_len)); - -#if LWIP_SNMP_V3_CRYPTO - if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; - u8_t key[20]; - u8_t algo; - u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; - struct snmp_pbuf_stream auth_stream; - - /* Rewind stream */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&pbuf_stream, inbound_msgAuthenticationParameters_offset)); - /* Set auth parameters to zero for verification */ - IF_PARSE_EXEC(snmp_asn1_enc_raw(&pbuf_stream, zero_arr, tlv.value_len)); - - /* Verify authentication */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - - IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); - IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, algo, hmac)); - /* @todo: Implement error response */ - IF_PARSE_EXEC(memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } -#else - /* Ungraceful exit if we encounter cryptography and don't support it. - * @todo: Implement error response - */ - IF_PARSE_ASSERT(!(request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG))); -#endif - - /* msgPrivacyParameters */ - memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, - &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); - -#if LWIP_SNMP_V3_CRYPTO - /* Decrypt message */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - u8_t key[20]; - u8_t algo; - - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); - IF_PARSE_EXEC(snmpv3_crypt(&pbuf_stream, tlv.value_len, key, - request->msg_privacy_parameters, request->msg_authoritative_engine_boots, - request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_DECRYPT)); - } -#endif - - /* Scoped PDU - * Encryption context - */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* contextEngineID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_engine_id_len = (u8_t)u16_value; - - /* contextName */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_name_len = (u8_t)u16_value; - } else -#endif - { - /* decode community */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); - if (err == ERR_MEM) { - /* community string does not fit in our buffer -> its too long -> its invalid */ - request->community_strlen = 0; - snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); - } else { - IF_PARSE_ASSERT(err == ERR_OK); - } - /* add zero terminator */ - request->community[request->community_strlen] = 0; - } - - /* decode PDU type (next container level) */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length); - request->inbound_padding_len = pbuf_stream.length - tlv.value_len; - parent_tlv_value_len = tlv.value_len; - - /* validate PDU type */ - switch(tlv.type) { - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ): - /* GetRequest PDU */ - snmp_stats.ingetrequests++; - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ): - /* GetNextRequest PDU */ - snmp_stats.ingetnexts++; - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ): - /* GetBulkRequest PDU */ - if (request->version < SNMP_VERSION_2c) { - /* RFC2089: invalid, drop packet */ - return ERR_ARG; - } - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ): - /* SetRequest PDU */ - snmp_stats.insetrequests++; - break; - default: - /* unsupported input PDU for this agent (no parse error) */ - LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \ - return ERR_ARG; - break; - } - request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; - - /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ - if (request->community_strlen == 0) { - /* community string was too long or really empty*/ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - if (snmp_community_write[0] == 0) { - /* our write community is empty, that means all our objects are readonly */ - request->error_status = SNMP_ERR_NOTWRITABLE; - request->error_index = 1; - } else if (strncmp(snmp_community_write, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { - /* community name does not match */ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } - } else { - if (strncmp(snmp_community, (const char*)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { - /* community name does not match */ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } - } - - /* decode request ID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id)); - - /* decode error status / non-repeaters */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters)); - if (request->non_repeaters < 0) { - /* RFC 1905, 4.2.3 */ - request->non_repeaters = 0; - } - } else { - /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */ - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR); - } - - /* decode error index / max-repetitions */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions)); - if (request->max_repetitions < 0) { - /* RFC 1905, 4.2.3 */ - request->max_repetitions = 0; - } - } else { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index)); - IF_PARSE_ASSERT(s32_value == 0); - } - - /* decode varbind-list type (next container level) */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length)); - - request->inbound_varbind_offset = pbuf_stream.offset; - request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len; - snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - - return ERR_OK; -} - -#define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) - -static err_t -snmp_prepare_outbound_frame(struct snmp_request *request) -{ - struct snmp_asn1_tlv tlv; - struct snmp_pbuf_stream* pbuf_stream = &(request->outbound_pbuf_stream); - - /* try allocating pbuf(s) for maximum response size */ - request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM); - if (request->outbound_pbuf == NULL) { - return ERR_MEM; - } - - snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len); - - /* 'Message' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* version */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) ); - -#if LWIP_SNMP_V3 - if (request->version < SNMP_VERSION_3) { -#endif - /* community */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) ); -#if LWIP_SNMP_V3 - } else { - const char* id; - - /* globalData */ - request->outbound_msg_global_data_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* msgID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id)); - - /* msgMaxSize */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size)); - - /* msgFlags */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1)); - - /* msgSecurityModel */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model)); - - /* end of msgGlobalData */ - request->outbound_msg_global_data_end = pbuf_stream->offset; - - /* msgSecurityParameters */ - request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* msgAuthoritativeEngineID */ - snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); - MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); - - request->msg_authoritative_engine_time = snmpv3_get_engine_time(); - request->msg_authoritative_engine_boots = snmpv3_get_engine_boots(); - - /* msgAuthoritativeEngineBoots */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots)); - - /* msgAuthoritativeEngineTime */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time)); - - /* msgUserName */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len)); - -#if LWIP_SNMP_V3_CRYPTO - /* msgAuthenticationParameters */ - if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } else -#endif - { - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - } - -#if LWIP_SNMP_V3_CRYPTO - /* msgPrivacyParameters */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - snmpv3_build_priv_param(request->msg_privacy_parameters); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); - } else -#endif - { - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - } - - /* End of msgSecurityParameters, so we can calculate the length of this sequence later */ - request->outbound_msg_security_parameters_end = pbuf_stream->offset; - -#if LWIP_SNMP_V3_CRYPTO - /* For encryption we have to encapsulate the payload in an octet string */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - request->outbound_scoped_pdu_string_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - } -#endif - /* Scoped PDU - * Encryption context - */ - request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* contextEngineID */ - snmpv3_get_engine_id(&id, &request->context_engine_id_len); - MEMCPY(request->context_engine_id, id, request->context_engine_id_len); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); - - /* contextName */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len)); - } -#endif - - /* 'PDU' sequence */ - request->outbound_pdu_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* request ID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) ); - - /* error status */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - request->outbound_error_status_offset = pbuf_stream->offset; - OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); - - /* error index */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - request->outbound_error_index_offset = pbuf_stream->offset; - OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); - - /* 'VarBindList' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - request->outbound_varbind_offset = pbuf_stream->offset; - - return ERR_OK; -} - -/** Calculate the length of a varbind list */ -err_t -snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len) -{ - /* calculate required lengths */ - snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len); - snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len); - - if (varbind->value_len == 0) { - len->value_value_len = 0; - } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { - len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA); - } else { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - if (varbind->value_len != sizeof (s32_t)) { - return ERR_VAL; - } - snmp_asn1_enc_s32t_cnt(*((s32_t*) varbind->value), &len->value_value_len); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - if (varbind->value_len != sizeof (u32_t)) { - return ERR_VAL; - } - snmp_asn1_enc_u32t_cnt(*((u32_t*) varbind->value), &len->value_value_len); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_IPADDR: - case SNMP_ASN1_TYPE_OPAQUE: - len->value_value_len = varbind->value_len; - break; - case SNMP_ASN1_TYPE_NULL: - if (varbind->value_len != 0) { - return ERR_VAL; - } - len->value_value_len = 0; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - if ((varbind->value_len & 0x03) != 0) { - return ERR_VAL; - } - snmp_asn1_enc_oid_cnt((u32_t*) varbind->value, varbind->value_len >> 2, &len->value_value_len); - break; - case SNMP_ASN1_TYPE_COUNTER64: - if (varbind->value_len != (2 * sizeof (u32_t))) { - return ERR_VAL; - } - snmp_asn1_enc_u64t_cnt((u32_t*) varbind->value, &len->value_value_len); - break; - default: - /* unsupported type */ - return ERR_VAL; - } - } - snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len); - - len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len; - snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len); - - return ERR_OK; -} - -#define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) - -err_t -snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind) -{ - struct snmp_asn1_tlv tlv; - struct snmp_varbind_len len; - err_t err; - - err = snmp_varbind_length(varbind, &len); - - if (err != ERR_OK) { - return err; - } - - /* check length already before adding first data because in case of GetBulk, - * data added so far is returned and therefore no partial data shall be added - */ - if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) { - return ERR_BUF; - } - - /* 'VarBind' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* VarBind OID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len)); - - /* VarBind value */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - if (len.value_value_len > 0) { - if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { - OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); - } else { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t*) varbind->value))); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t*) varbind->value))); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_IPADDR: - case SNMP_ASN1_TYPE_OPAQUE: - OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t*) varbind->value, len.value_value_len)); - len.value_value_len = varbind->value_len; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t*) varbind->value, varbind->value_len / sizeof (u32_t))); - break; - case SNMP_ASN1_TYPE_COUNTER64: - OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, (u32_t*) varbind->value)); - break; - default: - LWIP_ASSERT("Unknown variable type", 0); - break; - } - } - } - - return ERR_OK; -} - -static err_t -snmp_complete_outbound_frame(struct snmp_request *request) -{ - struct snmp_asn1_tlv tlv; - u16_t frame_size; - u8_t outbound_padding = 0; - - if (request->version == SNMP_VERSION_1) { - if (request->error_status != SNMP_ERR_NOERROR) { - /* map v2c error codes to v1 compliant error code (according to RFC 2089) */ - switch (request->error_status) { - /* mapping of implementation specific "virtual" error codes - * (during processing of frame we already stored them in error_status field, - * so no need to check all varbinds here for those exceptions as suggested by RFC) */ - case SNMP_ERR_NOSUCHINSTANCE: - case SNMP_ERR_NOSUCHOBJECT: - case SNMP_ERR_ENDOFMIBVIEW: - request->error_status = SNMP_ERR_NOSUCHNAME; - break; - /* mapping according to RFC */ - case SNMP_ERR_WRONGVALUE: - case SNMP_ERR_WRONGENCODING: - case SNMP_ERR_WRONGTYPE: - case SNMP_ERR_WRONGLENGTH: - case SNMP_ERR_INCONSISTENTVALUE: - request->error_status = SNMP_ERR_BADVALUE; - break; - case SNMP_ERR_NOACCESS: - case SNMP_ERR_NOTWRITABLE: - case SNMP_ERR_NOCREATION: - case SNMP_ERR_INCONSISTENTNAME: - case SNMP_ERR_AUTHORIZATIONERROR: - request->error_status = SNMP_ERR_NOSUCHNAME; - break; - case SNMP_ERR_RESOURCEUNAVAILABLE: - case SNMP_ERR_COMMITFAILED: - case SNMP_ERR_UNDOFAILED: - default: - request->error_status = SNMP_ERR_GENERROR; - break; - } - } - } else { - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ - switch (request->error_status) { - case SNMP_ERR_NOSUCHINSTANCE: - case SNMP_ERR_NOSUCHOBJECT: - case SNMP_ERR_ENDOFMIBVIEW: - request->error_status = SNMP_ERR_NOTWRITABLE; - break; - default: - break; - } - } - - if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { - /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); - return ERR_ARG; - } - } - - if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) { - /* all inbound vars are returned in response without any modification for error responses and successful set requests*/ - struct snmp_pbuf_stream inbound_stream; - OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) ); - OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) ); - snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0); - } - - frame_size = request->outbound_pbuf_stream.offset; - -#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO - /* Calculate padding for encryption */ - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { - u8_t i; - outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; - for (i = 0; i < outbound_padding; i++) { - snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0); - } - } -#endif - - /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) ); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - -#if LWIP_SNMP_V3 - if (request->version == SNMP_VERSION_3) { - /* complete missing length in 'globalData' sequence */ - /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end - - request->outbound_msg_global_data_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - /* complete missing length in 'msgSecurityParameters' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end - - request->outbound_msg_security_parameters_str_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end - - request->outbound_msg_security_parameters_seq_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - /* complete missing length in scoped PDU sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - } -#endif - - /* complete missing length in 'PDU' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP), 3, - frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - - /* process and encode final error status */ - if (request->error_status != 0) { - u16_t len; - snmp_asn1_enc_s32t_cnt(request->error_status, &len); - if (len != 1) { - /* error, we only reserved one byte for it */ - return ERR_ARG; - } - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) ); - - /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */ - switch (request->error_status) { - case SNMP_ERR_TOOBIG: - snmp_stats.outtoobigs++; - break; - case SNMP_ERR_NOSUCHNAME: - snmp_stats.outnosuchnames++; - break; - case SNMP_ERR_BADVALUE: - snmp_stats.outbadvalues++; - break; - case SNMP_ERR_GENERROR: - default: - snmp_stats.outgenerrs++; - break; - } - - if (request->error_status == SNMP_ERR_TOOBIG) { - request->error_index = 0; /* defined by RFC 1157 */ - } else if (request->error_index == 0) { - /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */ - request->error_index = request->inbound_varbind_enumerator.varbind_count; - } - } else { - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count; - } else { - snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count; - } - } - - /* encode final error index*/ - if (request->error_index != 0) { - u16_t len; - snmp_asn1_enc_s32t_cnt(request->error_index, &len); - if (len != 1) { - /* error, we only reserved one byte for it */ - return ERR_VAL; - } - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) ); - } - - /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset); - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - - /* Authenticate response */ -#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO - /* Encrypt response */ - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { - u8_t key[20]; - u8_t algo; - - /* complete missing length in PDU sequence */ - OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset)); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding - - request->outbound_scoped_pdu_string_offset - 1 - 3); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, NULL, NULL, &algo, key)); - - OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key, - request->msg_privacy_parameters, request->msg_authoritative_engine_boots, - request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT)); - } - - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) { - u8_t key[20]; - u8_t algo; - u8_t hmac[20]; - - OF_BUILD_EXEC(snmpv3_get_user((char*)request->msg_user_name, &algo, key, NULL, NULL)); - OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), - request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); - - MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, - request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, - request->outbound_msg_authentication_parameters_offset)); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream, - request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } -#endif - - pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding); - - snmp_stats.outgetresponses++; - snmp_stats.outpkts++; - - return ERR_OK; -} - -static void -snmp_execute_write_callbacks(struct snmp_request *request) -{ - struct snmp_varbind_enumerator inbound_varbind_enumerator; - struct snmp_varbind vb; - - snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ - - while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { - snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); - } -} - - -/* ----------------------------------------------------------------------- */ -/* VarBind enumerator methods */ -/* ----------------------------------------------------------------------- */ - -void -snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length) -{ - snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length); - enumerator->varbind_count = 0; -} - -#define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) -#define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) - -snmp_vb_enumerator_err_t -snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind) -{ - struct snmp_asn1_tlv tlv; - u16_t varbind_len; - err_t err; - - if (enumerator->pbuf_stream.length == 0) - { - return SNMP_VB_ENUMERATOR_ERR_EOVB; - } - enumerator->varbind_count++; - - /* decode varbind itself (parent container of a varbind) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length)); - varbind_len = tlv.value_len; - - /* decode varbind name (object id) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length)); - - VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN)); - varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv); - - /* decode varbind value (object id) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length)); - varbind->type = tlv.type; - - /* shall the value be decoded ? */ - if (varbind->value != NULL) { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t*)varbind->value)); - varbind->value_len = sizeof(s32_t*); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); - varbind->value_len = sizeof(u32_t*); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_OPAQUE: - err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE); - if (err == ERR_MEM) { - return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; - } - VB_PARSE_ASSERT(err == ERR_OK); - break; - case SNMP_ASN1_TYPE_NULL: - varbind->value_len = 0; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - /* misuse tlv.length_len as OID_length transporter */ - err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN); - if (err == ERR_MEM) { - return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; - } - VB_PARSE_ASSERT(err == ERR_OK); - varbind->value_len = tlv.length_len * sizeof(u32_t); - break; - case SNMP_ASN1_TYPE_IPADDR: - if (tlv.value_len == 4) { - /* must be exactly 4 octets! */ - VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t*)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE)); - } else { - VB_PARSE_ASSERT(0); - } - break; - case SNMP_ASN1_TYPE_COUNTER64: - VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t*)varbind->value)); - varbind->value_len = 2 * sizeof(u32_t*); - break; - default: - VB_PARSE_ASSERT(0); - break; - } - } else { - snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len); - varbind->value_len = tlv.value_len; - } - - return SNMP_VB_ENUMERATOR_ERR_OK; -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.h b/components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.h deleted file mode 100644 index 2d01ef36eb..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_msg.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @file - * SNMP Agent message handling structures (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_MSG_H -#define LWIP_HDR_APPS_SNMP_MSG_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_pbuf_stream.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#if LWIP_SNMP_V3 -#include "snmpv3_priv.h" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* The listen port of the SNMP agent. Clients have to make their requests to - this port. Most standard clients won't work if you change this! */ -#ifndef SNMP_IN_PORT -#define SNMP_IN_PORT 161 -#endif -/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't - work if you change this! */ -#ifndef SNMP_TRAP_PORT -#define SNMP_TRAP_PORT 162 -#endif - -/* version defines used in PDU */ -#define SNMP_VERSION_1 0 -#define SNMP_VERSION_2c 1 -#define SNMP_VERSION_3 3 - -struct snmp_varbind_enumerator -{ - struct snmp_pbuf_stream pbuf_stream; - u16_t varbind_count; -}; - -typedef enum { - SNMP_VB_ENUMERATOR_ERR_OK = 0, - SNMP_VB_ENUMERATOR_ERR_EOVB = 1, - SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2, - SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 -} snmp_vb_enumerator_err_t; - -void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length); -snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind); - -struct snmp_request -{ - /* Communication handle */ - void *handle; - /* source IP address */ - const ip_addr_t *source_ip; - /* source UDP port */ - u16_t source_port; - /* incoming snmp version */ - u8_t version; - /* community name (zero terminated) */ - u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1]; - /* community string length (exclusive zero term) */ - u16_t community_strlen; - /* request type */ - u8_t request_type; - /* request ID */ - s32_t request_id; - /* error status */ - s32_t error_status; - /* error index */ - s32_t error_index; - /* non-repeaters (getBulkRequest (SNMPv2c)) */ - s32_t non_repeaters; - /* max-repetitions (getBulkRequest (SNMPv2c)) */ - s32_t max_repetitions; - -#if LWIP_SNMP_V3 - s32_t msg_id; - s32_t msg_max_size; - u8_t msg_flags; - s32_t msg_security_model; - u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t msg_authoritative_engine_id_len; - s32_t msg_authoritative_engine_boots; - s32_t msg_authoritative_engine_time; - u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH]; - u8_t msg_user_name_len; - u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH]; - u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH]; - u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t context_engine_id_len; - u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t context_name_len; -#endif - - struct pbuf *inbound_pbuf; - struct snmp_varbind_enumerator inbound_varbind_enumerator; - u16_t inbound_varbind_offset; - u16_t inbound_varbind_len; - u16_t inbound_padding_len; - - struct pbuf *outbound_pbuf; - struct snmp_pbuf_stream outbound_pbuf_stream; - u16_t outbound_pdu_offset; - u16_t outbound_error_status_offset; - u16_t outbound_error_index_offset; - u16_t outbound_varbind_offset; -#if LWIP_SNMP_V3 - u16_t outbound_msg_global_data_offset; - u16_t outbound_msg_global_data_end; - u16_t outbound_msg_security_parameters_str_offset; - u16_t outbound_msg_security_parameters_seq_offset; - u16_t outbound_msg_security_parameters_end; - u16_t outbound_msg_authentication_parameters_offset; - u16_t outbound_scoped_pdu_seq_offset; - u16_t outbound_scoped_pdu_string_offset; -#endif - - u8_t value_buffer[SNMP_MAX_VALUE_SIZE]; -}; - -/** A helper struct keeping length information about varbinds */ -struct snmp_varbind_len -{ - u8_t vb_len_len; - u16_t vb_value_len; - u8_t oid_len_len; - u16_t oid_value_len; - u8_t value_len_len; - u16_t value_value_len; -}; - -/** Agent community string */ -extern const char *snmp_community; -/** Agent community string for write access */ -extern const char *snmp_community_write; -/** handle for sending traps */ -extern void* snmp_traps_handle; - -void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port); -err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port); -u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result); -err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len); -err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_MSG_H */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_netconn.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_netconn.c deleted file mode 100644 index 24c3e26531..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_netconn.c +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file - * SNMP netconn frontend. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && SNMP_USE_NETCONN - -#include -#include "lwip/api.h" -#include "lwip/ip.h" -#include "lwip/udp.h" -#include "snmp_msg.h" -#include "lwip/sys.h" - -/** SNMP netconn API worker thread */ -static void -snmp_netconn_thread(void *arg) -{ - struct netconn *conn; - struct netbuf *buf; - err_t err; - LWIP_UNUSED_ARG(arg); - - /* Bind to SNMP port with default IP address */ -#if LWIP_IPV6 - conn = netconn_new(NETCONN_UDP_IPV6); - netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT); -#else /* LWIP_IPV6 */ - conn = netconn_new(NETCONN_UDP); - netconn_bind(conn, IP4_ADDR_ANY, SNMP_IN_PORT); -#endif /* LWIP_IPV6 */ - LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); - - snmp_traps_handle = conn; - - do { - err = netconn_recv(conn, &buf); - - if (err == ERR_OK) { - snmp_receive(conn, buf->p, &buf->addr, buf->port); - } - - if (buf != NULL) { - netbuf_delete(buf); - } - } while(1); -} - -err_t -snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) -{ - err_t result; - struct netbuf buf; - - memset(&buf, 0, sizeof(buf)); - buf.p = p; - result = netconn_sendto((struct netconn*)handle, &buf, dst, port); - - return result; -} - -u8_t -snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) -{ - struct netconn* conn = (struct netconn*)handle; - struct netif *dst_if; - const ip_addr_t* dst_ip; - - LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */ - - ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip); - - if ((dst_if != NULL) && (dst_ip != NULL)) { - ip_addr_copy(*result, *dst_ip); - return 1; - } else { - return 0; - } -} - -/** - * Starts SNMP Agent. - */ -void -snmp_init(void) -{ - sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO); -} - -#endif /* LWIP_SNMP && SNMP_USE_NETCONN */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.c deleted file mode 100644 index 3c1217d710..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.c +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @file - * SNMP pbuf stream wrapper implementation (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_pbuf_stream.h" -#include "lwip/def.h" -#include - -err_t -snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length) -{ - pbuf_stream->offset = offset; - pbuf_stream->length = length; - pbuf_stream->pbuf = p; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data) -{ - if (pbuf_stream->length == 0) { - return ERR_BUF; - } - - if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { - return ERR_BUF; - } - - pbuf_stream->offset++; - pbuf_stream->length--; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data) -{ - return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); -} - -err_t -snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len) -{ - if (pbuf_stream->length < buf_len) { - return ERR_BUF; - } - - if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { - return ERR_BUF; - } - - pbuf_stream->offset += buf_len; - pbuf_stream->length -= buf_len; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len) -{ - - if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { - return ERR_ARG; - } - if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { - return ERR_ARG; - } - - if (len == 0) { - len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); - } - - while (len > 0) { - u16_t chunk_len; - err_t err; - u16_t target_offset; - struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); - - if ((pbuf == NULL) || (pbuf->len == 0)) { - return ERR_BUF; - } - - chunk_len = LWIP_MIN(len, pbuf->len); - err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len); - if (err != ERR_OK) { - return err; - } - - pbuf_stream->offset += chunk_len; - pbuf_stream->length -= chunk_len; - len -= chunk_len; - } - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset) -{ - if ((offset < 0) || (offset > pbuf_stream->length)) { - /* we cannot seek backwards or forward behind stream end */ - return ERR_ARG; - } - - pbuf_stream->offset += (u16_t)offset; - pbuf_stream->length -= (u16_t)offset; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset) -{ - s32_t rel_offset = offset - pbuf_stream->offset; - return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.h b/components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.h deleted file mode 100644 index 9778de774e..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_pbuf_stream.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file - * SNMP pbuf stream wrapper (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H -#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct snmp_pbuf_stream -{ - struct pbuf* pbuf; - u16_t offset; - u16_t length; -}; - -err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length); -err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data); -err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data); -err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len); -err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len); -err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset); -err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_raw.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_raw.c deleted file mode 100644 index 4a40864fc9..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_raw.c +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * SNMP RAW API frontend. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" -#include "lwip/ip_addr.h" - -#if LWIP_SNMP && SNMP_USE_RAW - -#include "lwip/udp.h" -#include "lwip/ip.h" -#include "snmp_msg.h" - -/* lwIP UDP receive callback function */ -static void -snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - LWIP_UNUSED_ARG(arg); - - snmp_receive(pcb, p, addr, port); - - pbuf_free(p); -} - -err_t -snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) -{ - return udp_sendto((struct udp_pcb*)handle, p, dst, port); -} - -u8_t -snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) -{ - struct udp_pcb* udp_pcb = (struct udp_pcb*)handle; - struct netif *dst_if; - const ip_addr_t* dst_ip; - - LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */ - - ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip); - - if ((dst_if != NULL) && (dst_ip != NULL)) { - ip_addr_copy(*result, *dst_ip); - return 1; - } else { - return 0; - } -} - -/** - * @ingroup snmp_core - * Starts SNMP Agent. - * Allocates UDP pcb and binds it to IP_ANY_TYPE port 161. - */ -void -snmp_init(void) -{ - err_t err; - - struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); - - snmp_traps_handle = snmp_pcb; - - udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT); - err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT); - LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); -} - -#endif /* LWIP_SNMP && SNMP_USE_RAW */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_scalar.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_scalar.c deleted file mode 100644 index 136c9eccd0..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_scalar.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file - * SNMP scalar node support implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_scalar.h" -#include "lwip/apps/snmp_core.h" - -static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value); -static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value); -static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value); - -snmp_err_t -snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* scalar only has one dedicated instance: .0 */ - if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->access = scalar_node->access; - instance->asn1_type = scalar_node->asn1_type; - instance->get_value = scalar_node->get_value; - instance->set_test = scalar_node->set_test; - instance->set_value = scalar_node->set_value; - return SNMP_ERR_NOERROR; -} - -snmp_err_t -snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - /* because our only instance is .0 we can only return a next instance if no instance oid is passed */ - if (instance->instance_oid.len == 0) { - instance->instance_oid.len = 1; - instance->instance_oid.id[0] = 0; - - return snmp_scalar_get_instance(root_oid, root_oid_len, instance); - } - - return SNMP_ERR_NOSUCHINSTANCE; -} - - -snmp_err_t -snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) { - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; - u32_t i = 0; - - while (i < array_node->array_node_count) { - if (array_node_def->oid == instance->instance_oid.id[0]) { - break; - } - - array_node_def++; - i++; - } - - if (i < array_node->array_node_count) { - instance->access = array_node_def->access; - instance->asn1_type = array_node_def->asn1_type; - instance->get_value = snmp_scalar_array_get_value; - instance->set_test = snmp_scalar_array_set_test; - instance->set_value = snmp_scalar_array_set_value; - instance->reference.const_ptr = array_node_def; - - return SNMP_ERR_NOERROR; - } - } - - return SNMP_ERR_NOSUCHINSTANCE; -} - -snmp_err_t -snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; - const struct snmp_scalar_array_node_def* result = NULL; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) { - /* return node with lowest OID */ - u16_t i = 0; - - result = array_node_def; - array_node_def++; - - for (i = 1; i < array_node->array_node_count; i++) { - if (array_node_def->oid < result->oid) { - result = array_node_def; - } - array_node_def++; - } - } else if (instance->instance_oid.len >= 1) { - if (instance->instance_oid.len == 1) { - /* if we have the requested OID we return its instance, otherwise we search for the next available */ - u16_t i = 0; - while (i < array_node->array_node_count) { - if (array_node_def->oid == instance->instance_oid.id[0]) { - result = array_node_def; - break; - } - - array_node_def++; - i++; - } - } - if (result == NULL) { - u32_t oid_dist = 0xFFFFFFFFUL; - u16_t i = 0; - array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */ - while (i < array_node->array_node_count) { - if ((array_node_def->oid > instance->instance_oid.id[0]) && - ((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) { - result = array_node_def; - oid_dist = array_node_def->oid - instance->instance_oid.id[0]; - } - - array_node_def++; - i++; - } - } - } - - if (result == NULL) { - /* nothing to return */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = result->oid; - instance->instance_oid.id[1] = 0; - - instance->access = result->access; - instance->asn1_type = result->asn1_type; - instance->get_value = snmp_scalar_array_get_value; - instance->set_test = snmp_scalar_array_set_test; - instance->set_value = snmp_scalar_array_set_value; - instance->reference.const_ptr = result; - - return SNMP_ERR_NOERROR; -} - -static s16_t -snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; - - return array_node->get_value(array_node_def, value); -} - -static snmp_err_t -snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; - - return array_node->set_test(array_node_def, value_len, value); -} - -static snmp_err_t -snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value) -{ - const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; - const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; - - return array_node->set_value(array_node_def, value_len, value); -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_table.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_table.c deleted file mode 100644 index 63ca595633..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_table.c +++ /dev/null @@ -1,343 +0,0 @@ -/** - * @file - * SNMP table support implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_table.h" -#include - -snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; - const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ - /* fixed row entry always has oid 1 */ - if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { - /* search column */ - const struct snmp_table_col_def* col_def = table_node->columns; - u16_t i = table_node->column_count; - while (i > 0) { - if (col_def->index == instance->instance_oid.id[1]) { - break; - } - - col_def++; - i--; - } - - if (i > 0) { - /* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */ - instance->asn1_type = col_def->asn1_type; - instance->access = col_def->access; - instance->get_value = table_node->get_value; - instance->set_test = table_node->set_test; - instance->set_value = table_node->set_value; - - ret = table_node->get_cell_instance( - &(instance->instance_oid.id[1]), - &(instance->instance_oid.id[2]), - instance->instance_oid.len-2, - instance); - } - } - - return ret; -} - -snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; - const struct snmp_table_col_def* col_def; - struct snmp_obj_id row_oid; - u32_t column = 0; - snmp_err_t result; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check that first part of id is 0 or 1, referencing fixed row entry */ - if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (instance->instance_oid.len > 1) { - column = instance->instance_oid.id[1]; - } - if (instance->instance_oid.len > 2) { - snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); - } else { - row_oid.len = 0; - } - - instance->get_value = table_node->get_value; - instance->set_test = table_node->set_test; - instance->set_value = table_node->set_value; - - /* resolve column and value */ - do { - u16_t i; - const struct snmp_table_col_def* next_col_def = NULL; - col_def = table_node->columns; - - for (i = 0; i < table_node->column_count; i++) { - if (col_def->index == column) { - next_col_def = col_def; - break; - } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { - next_col_def = col_def; - } - col_def++; - } - - if (next_col_def == NULL) { - /* no further column found */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->asn1_type = next_col_def->asn1_type; - instance->access = next_col_def->access; - - result = table_node->get_next_cell_instance( - &next_col_def->index, - &row_oid, - instance); - - if (result == SNMP_ERR_NOERROR) { - col_def = next_col_def; - break; - } - - row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ - column = next_col_def->index + 1; - } while (1); - - /* build resulting oid */ - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = 1; - instance->instance_oid.id[1] = col_def->index; - snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); - - return SNMP_ERR_NOERROR; -} - - -snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; - const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ - /* fixed row entry always has oid 1 */ - if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { - ret = table_node->get_cell_value( - &(instance->instance_oid.id[1]), - &(instance->instance_oid.id[2]), - instance->instance_oid.len-2, - &instance->reference, - &instance->reference_len); - - if (ret == SNMP_ERR_NOERROR) { - /* search column */ - const struct snmp_table_simple_col_def* col_def = table_node->columns; - u32_t i = table_node->column_count; - while (i > 0) { - if (col_def->index == instance->instance_oid.id[1]) { - break; - } - - col_def++; - i--; - } - - if (i > 0) { - instance->asn1_type = col_def->asn1_type; - instance->access = SNMP_NODE_INSTANCE_READ_ONLY; - instance->set_test = NULL; - instance->set_value = NULL; - - switch (col_def->data_type) { - case SNMP_VARIANT_VALUE_TYPE_U32: - instance->get_value = snmp_table_extract_value_from_u32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_S32: - instance->get_value = snmp_table_extract_value_from_s32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ - case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: - instance->get_value = snmp_table_extract_value_from_refconstptr; - break; - default: - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); - return SNMP_ERR_GENERROR; - } - - ret = SNMP_ERR_NOERROR; - } else { - ret = SNMP_ERR_NOSUCHINSTANCE; - } - } - } - - return ret; -} - -snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; - const struct snmp_table_simple_col_def* col_def; - struct snmp_obj_id row_oid; - u32_t column = 0; - snmp_err_t result; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check that first part of id is 0 or 1, referencing fixed row entry */ - if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (instance->instance_oid.len > 1) { - column = instance->instance_oid.id[1]; - } - if (instance->instance_oid.len > 2) { - snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); - } else { - row_oid.len = 0; - } - - /* resolve column and value */ - do { - u32_t i; - const struct snmp_table_simple_col_def* next_col_def = NULL; - col_def = table_node->columns; - - for (i = 0; i < table_node->column_count; i++) { - if (col_def->index == column) { - next_col_def = col_def; - break; - } else if ((col_def->index > column) && ((next_col_def == NULL) || - (col_def->index < next_col_def->index))) { - next_col_def = col_def; - } - col_def++; - } - - if (next_col_def == NULL) { - /* no further column found */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - result = table_node->get_next_cell_instance_and_value( - &next_col_def->index, - &row_oid, - &instance->reference, - &instance->reference_len); - - if (result == SNMP_ERR_NOERROR) { - col_def = next_col_def; - break; - } - - row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ - column = next_col_def->index + 1; - } - while (1); - - instance->asn1_type = col_def->asn1_type; - instance->access = SNMP_NODE_INSTANCE_READ_ONLY; - instance->set_test = NULL; - instance->set_value = NULL; - - switch (col_def->data_type) { - case SNMP_VARIANT_VALUE_TYPE_U32: - instance->get_value = snmp_table_extract_value_from_u32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_S32: - instance->get_value = snmp_table_extract_value_from_s32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ - case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: - instance->get_value = snmp_table_extract_value_from_refconstptr; - break; - default: - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); - return SNMP_ERR_GENERROR; - } - - /* build resulting oid */ - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = 1; - instance->instance_oid.id[1] = col_def->index; - snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); - - return SNMP_ERR_NOERROR; -} - - -s16_t -snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value) -{ - s32_t *dst = (s32_t*)value; - *dst = instance->reference.s32; - return sizeof(*dst); -} - -s16_t -snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value) -{ - u32_t *dst = (u32_t*)value; - *dst = instance->reference.u32; - return sizeof(*dst); -} - -s16_t -snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value) -{ - MEMCPY(value, instance->reference.const_ptr, instance->reference_len); - return (u16_t)instance->reference_len; -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_threadsync.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_threadsync.c deleted file mode 100644 index 204f265dc8..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_threadsync.c +++ /dev/null @@ -1,219 +0,0 @@ -/** - * @file - * SNMP thread synchronization implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_threadsync.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/sys.h" -#include - -static void -call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) -{ - sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); - call_data->threadsync_node->instance->sync_fn(fn, call_data); - sys_sem_wait(&call_data->threadsync_node->instance->sem); - sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); -} - -static void -threadsync_get_value_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static s16_t -threadsync_get_value(struct snmp_node_instance* instance, void* value) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - call_data->arg1.value = value; - call_synced_function(call_data, threadsync_get_value_synced); - - return call_data->retval.s16; -} - -static void -threadsync_set_test_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - call_data->arg1.value = value; - call_data->arg2.len = len; - call_synced_function(call_data, threadsync_set_test_synced); - - return call_data->retval.err; -} - -static void -threadsync_set_value_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - call_data->arg1.value = value; - call_data->arg2.len = len; - call_synced_function(call_data, threadsync_set_value_synced); - - return call_data->retval.err; -} - -static void -threadsync_release_instance_synced(void* ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - - call_data->proxy_instance.release_instance(&call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static void -threadsync_release_instance(struct snmp_node_instance *instance) -{ - struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; - - if (call_data->proxy_instance.release_instance != NULL) { - call_synced_function(call_data, threadsync_release_instance_synced); - } -} - -static void -get_instance_synced(void* ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; - - call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static void -get_next_instance_synced(void* ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data*)ctx; - const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; - - call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn) -{ - const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node; - struct threadsync_data *call_data = &threadsync_node->instance->data; - - if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { - LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); - return SNMP_ERR_NOSUCHINSTANCE; - } - - memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); - - instance->reference.ptr = call_data; - snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); - - call_data->proxy_instance.node = &threadsync_node->target->node; - call_data->threadsync_node = threadsync_node; - - call_data->arg1.root_oid = root_oid; - call_data->arg2.root_oid_len = root_oid_len; - call_synced_function(call_data, fn); - - if (call_data->retval.err == SNMP_ERR_NOERROR) { - instance->access = call_data->proxy_instance.access; - instance->asn1_type = call_data->proxy_instance.asn1_type; - instance->release_instance = threadsync_release_instance; - instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL; - instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL; - instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL; - snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); - } - - return call_data->retval.err; -} - -snmp_err_t -snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - return do_sync(root_oid, root_oid_len, instance, get_instance_synced); -} - -snmp_err_t -snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) -{ - return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); -} - -/** Initializes thread synchronization instance */ -void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) -{ - err_t err = sys_mutex_new(&instance->sem_usage_mutex); - LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); - err = sys_sem_new(&instance->sem, 0); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); - instance->sync_fn = sync_fn; -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmp_traps.c b/components/net/lwip-2.0.2/src/apps/snmp/snmp_traps.c deleted file mode 100644 index 0d2df64991..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmp_traps.c +++ /dev/null @@ -1,445 +0,0 @@ -/** - * @file - * SNMPv1 traps implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * Christiaan Simons - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/snmp.h" -#include "lwip/sys.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_msg.h" -#include "snmp_asn1.h" -#include "snmp_core_priv.h" - -struct snmp_msg_trap -{ - /* source enterprise ID (sysObjectID) */ - const struct snmp_obj_id *enterprise; - /* source IP address, raw network order format */ - ip_addr_t sip; - /* generic trap code */ - u32_t gen_trap; - /* specific trap code */ - u32_t spc_trap; - /* timestamp */ - u32_t ts; - /* snmp_version */ - u32_t snmp_version; - - /* output trap lengths used in ASN encoding */ - /* encoding pdu length */ - u16_t pdulen; - /* encoding community length */ - u16_t comlen; - /* encoding sequence length */ - u16_t seqlen; - /* encoding varbinds sequence length */ - u16_t vbseqlen; -}; - -static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); -static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); -static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); -static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); - -/** Agent community string for sending traps */ -extern const char *snmp_community_trap; - -void* snmp_traps_handle; - -struct snmp_trap_dst -{ - /* destination IP address in network order */ - ip_addr_t dip; - /* set to 0 when disabled, >0 when enabled */ - u8_t enable; -}; -static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; - -static u8_t snmp_auth_traps_enabled = 0; - -/** - * @ingroup snmp_traps - * Sets enable switch for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param enable switch if 0 destination is disabled >0 enabled. - */ -void -snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) -{ - if (dst_idx < SNMP_TRAP_DESTINATIONS) { - trap_dst[dst_idx].enable = enable; - } -} - -/** - * @ingroup snmp_traps - * Sets IPv4 address for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param dst IPv4 address in host order. - */ -void -snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) -{ - if (dst_idx < SNMP_TRAP_DESTINATIONS) { - ip_addr_set(&trap_dst[dst_idx].dip, dst); - } -} - -/** - * @ingroup snmp_traps - * Enable/disable authentication traps - */ -void -snmp_set_auth_traps_enabled(u8_t enable) -{ - snmp_auth_traps_enabled = enable; -} - -/** - * @ingroup snmp_traps - * Get authentication traps enabled state - */ -u8_t -snmp_get_auth_traps_enabled(void) -{ - return snmp_auth_traps_enabled; -} - - -/** - * @ingroup snmp_traps - * Sends a generic or enterprise specific trap message. - * - * @param eoid points to enterprise object identifier - * @param generic_trap is the trap code - * @param specific_trap used for enterprise traps when generic_trap == 6 - * @param varbinds linked list of varbinds to be sent - * @return ERR_OK when success, ERR_MEM if we're out of memory - * - * @note the use of the enterprise identifier field - * is per RFC1215. - * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps - * and .iso.org.dod.internet.private.enterprises.yourenterprise - * (sysObjectID) for specific traps. - */ -err_t -snmp_send_trap(const struct snmp_obj_id* eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) -{ - struct snmp_msg_trap trap_msg; - struct snmp_trap_dst *td; - struct pbuf *p; - u16_t i, tot_len; - err_t err = ERR_OK; - - trap_msg.snmp_version = 0; - - for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { - if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { - /* lookup current source address for this dst */ - if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { - if (eoid == NULL) { - trap_msg.enterprise = snmp_get_device_enterprise_oid(); - } else { - trap_msg.enterprise = eoid; - } - - trap_msg.gen_trap = generic_trap; - if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { - trap_msg.spc_trap = specific_trap; - } else { - trap_msg.spc_trap = 0; - } - - MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); - - /* pass 0, calculate length fields */ - tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); - tot_len = snmp_trap_header_sum(&trap_msg, tot_len); - - /* allocate pbuf(s) */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); - if (p != NULL) { - struct snmp_pbuf_stream pbuf_stream; - snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); - - /* pass 1, encode packet ino the pbuf(s) */ - snmp_trap_header_enc(&trap_msg, &pbuf_stream); - snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); - - snmp_stats.outtraps++; - snmp_stats.outpkts++; - - /** send to the TRAP destination */ - snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); - pbuf_free(p); - } else { - err = ERR_MEM; - } - } else { - /* routing error */ - err = ERR_RTE; - } - } - } - return err; -} - -/** - * @ingroup snmp_traps - * Send generic SNMP trap - */ -err_t -snmp_send_trap_generic(s32_t generic_trap) -{ - static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; - return snmp_send_trap(&oid, generic_trap, 0, NULL); -} - -/** - * @ingroup snmp_traps - * Send specific SNMP trap with variable bindings - */ -err_t -snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) -{ - return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); -} - -/** - * @ingroup snmp_traps - * Send coldstart trap - */ -void -snmp_coldstart_trap(void) -{ - snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); -} - -/** - * @ingroup snmp_traps - * Send authentication failure trap (used internally by agent) - */ -void -snmp_authfail_trap(void) -{ - if (snmp_auth_traps_enabled != 0) { - snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); - } -} - -static u16_t -snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) -{ - struct snmp_varbind *varbind; - u16_t tot_len; - u8_t tot_len_len; - - tot_len = 0; - varbind = varbinds; - while (varbind != NULL) { - struct snmp_varbind_len len; - - if (snmp_varbind_length(varbind, &len) == ERR_OK) { - tot_len += 1 + len.vb_len_len + len.vb_value_len; - } - - varbind = varbind->next; - } - - trap->vbseqlen = tot_len; - snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); - tot_len += 1 + tot_len_len; - - return tot_len; -} - -/** - * Sums trap header field lengths from tail to head and - * returns trap_header_lengths for second encoding pass. - * - * @param trap Trap message - * @param vb_len varbind-list length - * @return the required length for encoding the trap header - */ -static u16_t -snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) -{ - u16_t tot_len; - u16_t len; - u8_t lenlen; - - tot_len = vb_len; - - snmp_asn1_enc_u32t_cnt(trap->ts, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - if (IP_IS_V6_VAL(trap->sip)) { -#if LWIP_IPV6 - len = sizeof(ip_2_ip6(&trap->sip)->addr); -#endif - } else { -#if LWIP_IPV4 - len = sizeof(ip_2_ip4(&trap->sip)->addr); -#endif - } - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - trap->pdulen = tot_len; - snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); - tot_len += 1 + lenlen; - - trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); - snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); - tot_len += 1 + lenlen + trap->comlen; - - snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - trap->seqlen = tot_len; - snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); - tot_len += 1 + lenlen; - - return tot_len; -} - -static void -snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) -{ - struct snmp_asn1_tlv tlv; - struct snmp_varbind *varbind; - - varbind = varbinds; - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - - while (varbind != NULL) { - snmp_append_outbound_varbind(pbuf_stream, varbind); - - varbind = varbind->next; - } -} - -/** - * Encodes trap header from head to tail. - */ -static void -snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) -{ - struct snmp_asn1_tlv tlv; - - /* 'Message' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - - /* version */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version); - - /* community */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen); - - /* 'PDU' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - - /* object ID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); - snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len); - - /* IP addr */ - if (IP_IS_V6_VAL(trap->sip)) { -#if LWIP_IPV6 - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)); -#endif - } else { -#if LWIP_IPV4 - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)); -#endif - } - - /* trap length */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap); - - /* specific trap */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap); - - /* timestamp */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); - snmp_ans1_enc_tlv(pbuf_stream, &tlv); - snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts); -} - -#endif /* LWIP_SNMP */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3.c b/components/net/lwip-2.0.2/src/apps/snmp/snmpv3.c deleted file mode 100644 index 69fb3a0aaf..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#include "snmpv3_priv.h" -#include "lwip/apps/snmpv3.h" -#include "lwip/sys.h" -#include - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#ifdef LWIP_SNMPV3_INCLUDE_ENGINE -#include LWIP_SNMPV3_INCLUDE_ENGINE -#endif - -#define SNMP_MAX_TIME_BOOT 2147483647UL - -/** Call this if engine has been changed. Has to reset boots, see below */ -void -snmpv3_engine_id_changed(void) -{ - snmpv3_set_engine_boots(0); -} - -/** According to RFC3414 2.2.2. - * - * The number of times that the SNMP engine has - * (re-)initialized itself since snmpEngineID - * was last configured. - */ -u32_t -snmpv3_get_engine_boots_internal(void) -{ - if (snmpv3_get_engine_boots() == 0 || - snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) { - return snmpv3_get_engine_boots(); - } - - snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); - return snmpv3_get_engine_boots(); -} - -/** RFC3414 2.2.2. - * - * Once the timer reaches 2147483647 it gets reset to zero and the - * engine boot ups get incremented. - */ -u32_t -snmpv3_get_engine_time_internal(void) -{ - if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) { - snmpv3_reset_engine_time(); - - if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) { - snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1); - } else { - snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); - } - } - - return snmpv3_get_engine_time(); -} - -#if LWIP_SNMP_V3_CRYPTO - -/* This function ignores the byte order suggestion in RFC3414 - * since it simply doesn't influence the effectiveness of an IV. - * - * Implementing RFC3826 priv param algorithm if LWIP_RAND is available. - * - * @todo: This is a potential thread safety issue. - */ -err_t -snmpv3_build_priv_param(u8_t* priv_param) -{ -#ifdef LWIP_RAND /* Based on RFC3826 */ - static u8_t init; - static u32_t priv1, priv2; - - /* Lazy initialisation */ - if (init == 0) { - init = 1; - priv1 = LWIP_RAND(); - priv2 = LWIP_RAND(); - } - - SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); - SMEMCPY(&priv_param[4], &priv2, sizeof(priv2)); - - /* Emulate 64bit increment */ - priv1++; - if (!priv1) { /* Overflow */ - priv2++; - } -#else /* Based on RFC3414 */ - static u32_t ctr; - u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS(); - SMEMCPY(&priv_param[0], &boots, 4); - SMEMCPY(&priv_param[4], &ctr, 4); - ctr++; -#endif - return ERR_OK; -} -#endif /* LWIP_SNMP_V3_CRYPTO */ - -#endif diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_dummy.c b/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_dummy.c deleted file mode 100644 index bdfe844994..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_dummy.c +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file - * Dummy SNMPv3 functions. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - * Dirk Ziegelmeier - */ - -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#include -#include "lwip/err.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -/** - * @param username is a pointer to a string. - * @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found. - * @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found. - * @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found. - * @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found. - */ -err_t -snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key) -{ - const char* engine_id; - u8_t engine_id_len; - - if(strlen(username) == 0) { - return ERR_OK; - } - - if(memcmp(username, "lwip", 4) != 0) { - return ERR_VAL; - } - - snmpv3_get_engine_id(&engine_id, &engine_id_len); - - if(auth_key != NULL) { - snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, - (const u8_t*)engine_id, engine_id_len, - auth_key); - *auth_algo = SNMP_V3_AUTH_ALGO_SHA; - } - if(priv_key != NULL) { - snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, - (const u8_t*)engine_id, engine_id_len, - priv_key); - *priv_algo = SNMP_V3_PRIV_ALGO_DES; - } - return ERR_OK; -} - -/** - * Get engine ID from persistence - * @param id - * @param len - */ -void -snmpv3_get_engine_id(const char **id, u8_t *len) -{ - *id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"; - *len = 12; -} - -/** - * Store engine ID in persistence - * @param id - * @param len - */ -err_t -snmpv3_set_engine_id(const char *id, u8_t len) -{ - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(len); - return ERR_OK; -} - -/** - * Get engine boots from persistence. Must be increased on each boot. - * @return - */ -u32_t -snmpv3_get_engine_boots(void) -{ - return 0; -} - -/** - * Store engine boots in persistence - * @param boots - */ -void -snmpv3_set_engine_boots(u32_t boots) -{ - LWIP_UNUSED_ARG(boots); -} - -/** - * RFC3414 2.2.2. - * Once the timer reaches 2147483647 it gets reset to zero and the - * engine boot ups get incremented. - */ -u32_t -snmpv3_get_engine_time(void) -{ - return 0; -} - -/** - * Reset current engine time to 0 - */ -void -snmpv3_reset_engine_time(void) -{ -} - -#endif /* LWIP_SNMP && LWIP_SNMP_V3 */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_mbedtls.c b/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_mbedtls.c deleted file mode 100644 index 0b1eefb87e..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_mbedtls.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - * @file - * SNMPv3 crypto/auth functions implemented for ARM mbedtls. - */ - -/* - * Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - * Dirk Ziegelmeier - */ - -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#include "lwip/arch.h" -#include "snmp_msg.h" -#include "lwip/sys.h" -#include - -#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS - -#include "mbedtls/md.h" -#include "mbedtls/cipher.h" - -#include "mbedtls/md5.h" -#include "mbedtls/sha1.h" - -err_t -snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, - const u8_t* key, u8_t algo, u8_t* hmac_out) -{ - u32_t i; - u8_t key_len; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t ctx; - struct snmp_pbuf_stream read_stream; - snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); - - if (algo == SNMP_V3_AUTH_ALGO_MD5) { - md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); - key_len = SNMP_V3_MD5_LEN; - } else if (algo == SNMP_V3_AUTH_ALGO_SHA) { - md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - key_len = SNMP_V3_SHA_LEN; - } else { - return ERR_ARG; - } - - mbedtls_md_init(&ctx); - if(mbedtls_md_setup(&ctx, md_info, 1) != 0) { - return ERR_ARG; - } - - if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) { - goto free_md; - } - - for (i = 0; i < length; i++) { - u8_t byte; - - if (snmp_pbuf_stream_read(&read_stream, &byte)) { - goto free_md; - } - - if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) { - goto free_md; - } - } - - if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) { - goto free_md; - } - - mbedtls_md_free(&ctx); - return ERR_OK; - -free_md: - mbedtls_md_free(&ctx); - return ERR_ARG; -} - -#if LWIP_SNMP_V3_CRYPTO - -err_t -snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, - const u8_t* key, const u8_t* priv_param, const u32_t engine_boots, - const u32_t engine_time, u8_t algo, u8_t mode) -{ - size_t i; - mbedtls_cipher_context_t ctx; - const mbedtls_cipher_info_t *cipher_info; - - struct snmp_pbuf_stream read_stream; - struct snmp_pbuf_stream write_stream; - snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); - snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length); - mbedtls_cipher_init(&ctx); - - if (algo == SNMP_V3_PRIV_ALGO_DES) { - u8_t iv_local[8]; - u8_t out_bytes[8]; - size_t out_len; - - /* RFC 3414 mandates padding for DES */ - if ((length & 0x07) != 0) { - return ERR_ARG; - } - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); - if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - return ERR_ARG; - } - if(mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) { - return ERR_ARG; - } - if(mbedtls_cipher_setkey(&ctx, key, 8*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { - goto error; - } - - /* Prepare IV */ - for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) { - iv_local[i] = priv_param[i] ^ key[i + 8]; - } - if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { - goto error; - } - - for (i = 0; i < length; i += 8) { - size_t j; - u8_t in_bytes[8]; - out_len = LWIP_ARRAYSIZE(out_bytes) ; - - for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) { - snmp_pbuf_stream_read(&read_stream, &in_bytes[j]); - } - - if(mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) { - goto error; - } - - snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); - } - - out_len = LWIP_ARRAYSIZE(out_bytes); - if(mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) { - goto error; - } - snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); - } else if (algo == SNMP_V3_PRIV_ALGO_AES) { - u8_t iv_local[16]; - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128); - if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - return ERR_ARG; - } - if(mbedtls_cipher_setkey(&ctx, key, 16*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { - goto error; - } - - /* - * IV is the big endian concatenation of boots, - * uptime and priv param - see RFC3826. - */ - iv_local[0 + 0] = (engine_boots >> 24) & 0xFF; - iv_local[0 + 1] = (engine_boots >> 16) & 0xFF; - iv_local[0 + 2] = (engine_boots >> 8) & 0xFF; - iv_local[0 + 3] = (engine_boots >> 0) & 0xFF; - iv_local[4 + 0] = (engine_time >> 24) & 0xFF; - iv_local[4 + 1] = (engine_time >> 16) & 0xFF; - iv_local[4 + 2] = (engine_time >> 8) & 0xFF; - iv_local[4 + 3] = (engine_time >> 0) & 0xFF; - SMEMCPY(iv_local + 8, priv_param, 8); - if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { - goto error; - } - - for (i = 0; i < length; i++) { - u8_t in_byte; - u8_t out_byte; - size_t out_len = sizeof(out_byte); - - snmp_pbuf_stream_read(&read_stream, &in_byte); - if(mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) { - goto error; - } - snmp_pbuf_stream_write(&write_stream, out_byte); - } - } else { - return ERR_ARG; - } - - mbedtls_cipher_free(&ctx); - return ERR_OK; - -error: - mbedtls_cipher_free(&ctx); - return ERR_OK; -} - -#endif /* LWIP_SNMP_V3_CRYPTO */ - -/* A.2.1. Password to Key Sample Code for MD5 */ -void -snmpv3_password_to_key_md5( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength,/* IN - length of snmpEngineID */ - u8_t *key) /* OUT - pointer to caller 16-octet buffer */ -{ - mbedtls_md5_context MD; - u8_t *cp, password_buf[64]; - u32_t password_index = 0; - u8_t i; - u32_t count = 0; - - mbedtls_md5_init(&MD); /* initialize MD5 */ - mbedtls_md5_starts(&MD); - - /**********************************************/ - /* Use while loop until we've done 1 Megabyte */ - /**********************************************/ - while (count < 1048576) { - cp = password_buf; - for (i = 0; i < 64; i++) { - /*************************************************/ - /* Take the next octet of the password, wrapping */ - /* to the beginning of the password as necessary.*/ - /*************************************************/ - *cp++ = password[password_index++ % passwordlen]; - } - mbedtls_md5_update(&MD, password_buf, 64); - count += 64; - } - mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */ - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through MD5 to produce final key */ - /* May want to ensure that engineLength <= 32, */ - /* otherwise need to use a buffer larger than 64 */ - /*****************************************************/ - SMEMCPY(password_buf, key, 16); - MEMCPY(password_buf + 16, engineID, engineLength); - SMEMCPY(password_buf + 16 + engineLength, key, 16); - - mbedtls_md5_starts(&MD); - mbedtls_md5_update(&MD, password_buf, 32 + engineLength); - mbedtls_md5_finish(&MD, key); - - mbedtls_md5_free(&MD); - return; -} - -/* A.2.2. Password to Key Sample Code for SHA */ -void -snmpv3_password_to_key_sha( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength,/* IN - length of snmpEngineID */ - u8_t *key) /* OUT - pointer to caller 20-octet buffer */ -{ - mbedtls_sha1_context SH; - u8_t *cp, password_buf[72]; - u32_t password_index = 0; - u8_t i; - u32_t count = 0; - - mbedtls_sha1_init(&SH); /* initialize SHA */ - mbedtls_sha1_starts(&SH); - - /**********************************************/ - /* Use while loop until we've done 1 Megabyte */ - /**********************************************/ - while (count < 1048576) { - cp = password_buf; - for (i = 0; i < 64; i++) { - /*************************************************/ - /* Take the next octet of the password, wrapping */ - /* to the beginning of the password as necessary.*/ - /*************************************************/ - *cp++ = password[password_index++ % passwordlen]; - } - mbedtls_sha1_update(&SH, password_buf, 64); - count += 64; - } - mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */ - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through SHA to produce final key */ - /* May want to ensure that engineLength <= 32, */ - /* otherwise need to use a buffer larger than 72 */ - /*****************************************************/ - SMEMCPY(password_buf, key, 20); - MEMCPY(password_buf + 20, engineID, engineLength); - SMEMCPY(password_buf + 20 + engineLength, key, 20); - - mbedtls_sha1_starts(&SH); - mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); - mbedtls_sha1_finish(&SH, key); - - mbedtls_sha1_free(&SH); - return; -} - -#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */ diff --git a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_priv.h b/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_priv.h deleted file mode 100644 index b87666da99..0000000000 --- a/components/net/lwip-2.0.2/src/apps/snmp/snmpv3_priv.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H -#define LWIP_HDR_APPS_SNMP_V3_PRIV_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#include "snmp_pbuf_stream.h" - -/* According to RFC 3411 */ -#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32 -#define SNMP_V3_MAX_USER_LENGTH 32 - -#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12 -#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8 - -#define SNMP_V3_AUTH_FLAG 0x01 -#define SNMP_V3_PRIV_FLAG 0x02 - -#define SNMP_V3_MD5_LEN 16 -#define SNMP_V3_SHA_LEN 20 - -u32_t snmpv3_get_engine_boots_internal(void); -u32_t snmpv3_get_engine_time_internal(void); -err_t snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, u8_t algo, u8_t* hmac_out); -err_t snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, - const u8_t* priv_param, const u32_t engine_boots, const u32_t engine_time, u8_t algo, u8_t mode); -err_t snmpv3_build_priv_param(u8_t* priv_param); - -#endif - -#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/apps/sntp/sntp.c b/components/net/lwip-2.0.2/src/apps/sntp/sntp.c deleted file mode 100644 index 71b2abedb8..0000000000 --- a/components/net/lwip-2.0.2/src/apps/sntp/sntp.c +++ /dev/null @@ -1,727 +0,0 @@ -/** - * @file - * SNTP client module - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - */ - - -/** - * @defgroup sntp SNTP - * @ingroup apps - * - * This is simple "SNTP" client for the lwIP raw API. - * It is a minimal implementation of SNTPv4 as specified in RFC 4330. - * - * For a list of some public NTP servers, see this link : - * http://support.ntp.org/bin/view/Servers/NTPPoolServers - * - * @todo: - * - set/change servers at runtime - * - complete SNTP_CHECK_RESPONSE checks 3 and 4 - */ - -#include "lwip/apps/sntp.h" - -#include "lwip/opt.h" -#include "lwip/timeouts.h" -#include "lwip/udp.h" -#include "lwip/dns.h" -#include "lwip/ip_addr.h" -#include "lwip/pbuf.h" -#include "lwip/dhcp.h" - -#include -#include - -#if LWIP_UDP - -/* Handle support for more than one server via SNTP_MAX_SERVERS */ -#if SNTP_MAX_SERVERS > 1 -#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 -#else /* NTP_MAX_SERVERS > 1 */ -#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 -#endif /* NTP_MAX_SERVERS > 1 */ - -#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK) -#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!" -#endif - -/* Configure behaviour depending on microsecond or second precision */ -#ifdef SNTP_SET_SYSTEM_TIME_US -#define SNTP_CALC_TIME_US 1 -#define SNTP_RECEIVE_TIME_SIZE 2 -#else -#define SNTP_SET_SYSTEM_TIME_US(sec, us) -#define SNTP_CALC_TIME_US 0 -#define SNTP_RECEIVE_TIME_SIZE 1 -#endif - - -/* the various debug levels for this file */ -#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) -#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) -#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - -#define SNTP_ERR_KOD 1 - -/* SNTP protocol defines */ -#define SNTP_MSG_LEN 48 - -#define SNTP_OFFSET_LI_VN_MODE 0 -#define SNTP_LI_MASK 0xC0 -#define SNTP_LI_NO_WARNING 0x00 -#define SNTP_LI_LAST_MINUTE_61_SEC 0x01 -#define SNTP_LI_LAST_MINUTE_59_SEC 0x02 -#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */ - -#define SNTP_VERSION_MASK 0x38 -#define SNTP_VERSION (4/* NTP Version 4*/<<3) - -#define SNTP_MODE_MASK 0x07 -#define SNTP_MODE_CLIENT 0x03 -#define SNTP_MODE_SERVER 0x04 -#define SNTP_MODE_BROADCAST 0x05 - -#define SNTP_OFFSET_STRATUM 1 -#define SNTP_STRATUM_KOD 0x00 - -#define SNTP_OFFSET_ORIGINATE_TIME 24 -#define SNTP_OFFSET_RECEIVE_TIME 32 -#define SNTP_OFFSET_TRANSMIT_TIME 40 - -/* number of seconds between 1900 and 1970 (MSB=1)*/ -#define DIFF_SEC_1900_1970 (2208988800UL) -/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */ -#define DIFF_SEC_1970_2036 (2085978496UL) - -/** - * SNTP packet format (without optional fields) - * Timestamps are coded as 64 bits: - * - 32 bits seconds since Jan 01, 1970, 00:00 - * - 32 bits seconds fraction (0-padded) - * For future use, if the MSB in the seconds part is set, seconds are based - * on Feb 07, 2036, 06:28:16. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct sntp_msg { - PACK_STRUCT_FLD_8(u8_t li_vn_mode); - PACK_STRUCT_FLD_8(u8_t stratum); - PACK_STRUCT_FLD_8(u8_t poll); - PACK_STRUCT_FLD_8(u8_t precision); - PACK_STRUCT_FIELD(u32_t root_delay); - PACK_STRUCT_FIELD(u32_t root_dispersion); - PACK_STRUCT_FIELD(u32_t reference_identifier); - PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); - PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); - PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); - PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* function prototypes */ -static void sntp_request(void *arg); - -/** The operating mode */ -static u8_t sntp_opmode; - -/** The UDP pcb used by the SNTP client */ -static struct udp_pcb* sntp_pcb; -/** Names/Addresses of servers */ -struct sntp_server { -#if SNTP_SERVER_DNS - char* name; -#endif /* SNTP_SERVER_DNS */ - ip_addr_t addr; -}; -static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; - -#if SNTP_GET_SERVERS_FROM_DHCP -static u8_t sntp_set_servers_from_dhcp; -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ -#if SNTP_SUPPORT_MULTIPLE_SERVERS -/** The currently used server (initialized to 0) */ -static u8_t sntp_current_server; -#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ -#define sntp_current_server 0 -#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ - -#if SNTP_RETRY_TIMEOUT_EXP -#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT -/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ -static u32_t sntp_retry_timeout; -#else /* SNTP_RETRY_TIMEOUT_EXP */ -#define SNTP_RESET_RETRY_TIMEOUT() -#define sntp_retry_timeout SNTP_RETRY_TIMEOUT -#endif /* SNTP_RETRY_TIMEOUT_EXP */ - -#if SNTP_CHECK_RESPONSE >= 1 -/** Saves the last server address to compare with response */ -static ip_addr_t sntp_last_server_address; -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - -#if SNTP_CHECK_RESPONSE >= 2 -/** Saves the last timestamp sent (which is sent back by the server) - * to compare against in response */ -static u32_t sntp_last_timestamp_sent[2]; -#endif /* SNTP_CHECK_RESPONSE >= 2 */ - -/** - * SNTP processing of received timestamp - */ -static void -sntp_process(u32_t *receive_timestamp) -{ - /* convert SNTP time (1900-based) to unix GMT time (1970-based) - * if MSB is 0, SNTP time is 2036-based! - */ - u32_t rx_secs = lwip_ntohl(receive_timestamp[0]); - int is_1900_based = ((rx_secs & 0x80000000) != 0); - u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036); - time_t tim = t; - -#if SNTP_CALC_TIME_US - u32_t us = lwip_ntohl(receive_timestamp[1]) / 4295; - SNTP_SET_SYSTEM_TIME_US(t, us); - /* display local time from GMT time */ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us)); - -#else /* SNTP_CALC_TIME_US */ - - /* change system time and/or the update the RTC clock */ - SNTP_SET_SYSTEM_TIME(t); - /* display local time from GMT time */ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim))); -#endif /* SNTP_CALC_TIME_US */ - LWIP_UNUSED_ARG(tim); -} - -/** - * Initialize request struct to be sent to server. - */ -static void -sntp_initialize_request(struct sntp_msg *req) -{ - memset(req, 0, SNTP_MSG_LEN); - req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; - -#if SNTP_CHECK_RESPONSE >= 2 - { - u32_t sntp_time_sec, sntp_time_us; - /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ - SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); - sntp_last_timestamp_sent[0] = lwip_htonl(sntp_time_sec + DIFF_SEC_1900_1970); - req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; - /* we send/save us instead of fraction to be faster... */ - sntp_last_timestamp_sent[1] = lwip_htonl(sntp_time_us); - req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; - } -#endif /* SNTP_CHECK_RESPONSE >= 2 */ -} - -/** - * Retry: send a new request (and increase retry timeout). - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_retry(void* arg) -{ - LWIP_UNUSED_ARG(arg); - - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", - sntp_retry_timeout)); - - /* set up a timer to send a retry and increase the retry delay */ - sys_timeout(sntp_retry_timeout, sntp_request, NULL); - -#if SNTP_RETRY_TIMEOUT_EXP - { - u32_t new_retry_timeout; - /* increase the timeout for next retry */ - new_retry_timeout = sntp_retry_timeout << 1; - /* limit to maximum timeout and prevent overflow */ - if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && - (new_retry_timeout > sntp_retry_timeout)) { - sntp_retry_timeout = new_retry_timeout; - } - } -#endif /* SNTP_RETRY_TIMEOUT_EXP */ -} - -#if SNTP_SUPPORT_MULTIPLE_SERVERS -/** - * If Kiss-of-Death is received (or another packet parsing error), - * try the next server or retry the current server and increase the retry - * timeout if only one server is available. - * (implicitly, SNTP_MAX_SERVERS > 1) - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_try_next_server(void* arg) -{ - u8_t old_server, i; - LWIP_UNUSED_ARG(arg); - - old_server = sntp_current_server; - for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { - sntp_current_server++; - if (sntp_current_server >= SNTP_MAX_SERVERS) { - sntp_current_server = 0; - } - if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) -#if SNTP_SERVER_DNS - || (sntp_servers[sntp_current_server].name != NULL) -#endif - ) { - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", - (u16_t)sntp_current_server)); - /* new server: reset retry timeout */ - SNTP_RESET_RETRY_TIMEOUT(); - /* instantly send a request to the next server */ - sntp_request(NULL); - return; - } - } - /* no other valid server found */ - sntp_current_server = old_server; - sntp_retry(NULL); -} -#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ -/* Always retry on error if only one server is supported */ -#define sntp_try_next_server sntp_retry -#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ - -/** UDP recv callback for the sntp pcb */ -static void -sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u8_t mode; - u8_t stratum; - u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE]; - err_t err; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - - /* packet received: stop retry timeout */ - sys_untimeout(sntp_try_next_server, NULL); - sys_untimeout(sntp_request, NULL); - - err = ERR_ARG; -#if SNTP_CHECK_RESPONSE >= 1 - /* check server address and port */ - if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) && - (port == SNTP_PORT)) -#else /* SNTP_CHECK_RESPONSE >= 1 */ - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - { - /* process the response */ - if (p->tot_len == SNTP_MSG_LEN) { - pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE); - mode &= SNTP_MODE_MASK; - /* if this is a SNTP response... */ - if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) || - ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) { - pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM); - if (stratum == SNTP_STRATUM_KOD) { - /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ - err = SNTP_ERR_KOD; - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); - } else { -#if SNTP_CHECK_RESPONSE >= 2 - /* check originate_timetamp against sntp_last_timestamp_sent */ - u32_t originate_timestamp[2]; - pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME); - if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) || - (originate_timestamp[1] != sntp_last_timestamp_sent[1])) - { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n")); - } else -#endif /* SNTP_CHECK_RESPONSE >= 2 */ - /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ - { - /* correct answer */ - err = ERR_OK; - pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME); - } - } - } else { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); - /* wait for correct response */ - err = ERR_TIMEOUT; - } - } else { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); - } - } -#if SNTP_CHECK_RESPONSE >= 1 - else { - /* packet from wrong remote address or port, wait for correct response */ - err = ERR_TIMEOUT; - } -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - pbuf_free(p); - if (err == ERR_OK) { - sntp_process(receive_timestamp); - - /* Set up timeout for next request (only if poll response was received)*/ - if (sntp_opmode == SNTP_OPMODE_POLL) { - /* Correct response, reset retry timeout */ - SNTP_RESET_RETRY_TIMEOUT(); - - sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL); - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", - (u32_t)SNTP_UPDATE_DELAY)); - } - } else if (err != ERR_TIMEOUT) { - /* Errors are only processed in case of an explicit poll response */ - if (sntp_opmode == SNTP_OPMODE_POLL) { - if (err == SNTP_ERR_KOD) { - /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ - sntp_try_next_server(NULL); - } else { - /* another error, try the same server again */ - sntp_retry(NULL); - } - } - } -} - -/** Actually send an sntp request to a server. - * - * @param server_addr resolved IP address of the SNTP server - */ -static void -sntp_send_request(const ip_addr_t *server_addr) -{ - struct pbuf* p; - p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); - if (p != NULL) { - struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); - /* initialize request message */ - sntp_initialize_request(sntpmsg); - /* send request */ - udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); - /* free the pbuf after sending it */ - pbuf_free(p); - /* set up receive timeout: try next server or retry on timeout */ - sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); -#if SNTP_CHECK_RESPONSE >= 1 - /* save server address to verify it in sntp_recv */ - ip_addr_set(&sntp_last_server_address, server_addr); -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - } else { - LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", - (u32_t)SNTP_RETRY_TIMEOUT)); - /* out of memory: set up a timer to send a retry */ - sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); - } -} - -#if SNTP_SERVER_DNS -/** - * DNS found callback when using DNS names as server address. - */ -static void -sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) -{ - LWIP_UNUSED_ARG(hostname); - LWIP_UNUSED_ARG(arg); - - if (ipaddr != NULL) { - /* Address resolved, send request */ - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); - sntp_send_request(ipaddr); - } else { - /* DNS resolving failed -> try another server */ - LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); - sntp_try_next_server(NULL); - } -} -#endif /* SNTP_SERVER_DNS */ - -/** - * Send out an sntp request. - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_request(void *arg) -{ - ip_addr_t sntp_server_address; - err_t err; - - LWIP_UNUSED_ARG(arg); - - /* initialize SNTP server address */ -#if SNTP_SERVER_DNS - if (sntp_servers[sntp_current_server].name) { - /* always resolve the name and rely on dns-internal caching & timeout */ - ip_addr_set_zero(&sntp_servers[sntp_current_server].addr); - err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, - sntp_dns_found, NULL); - if (err == ERR_INPROGRESS) { - /* DNS request sent, wait for sntp_dns_found being called */ - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); - return; - } else if (err == ERR_OK) { - sntp_servers[sntp_current_server].addr = sntp_server_address; - } - } else -#endif /* SNTP_SERVER_DNS */ - { - sntp_server_address = sntp_servers[sntp_current_server].addr; - err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK; - } - - if (err == ERR_OK) { - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n", - ipaddr_ntoa(&sntp_server_address))); - sntp_send_request(&sntp_server_address); - } else { - /* address conversion failed, try another server */ - LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); - sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); - } -} - -/** - * @ingroup sntp - * Initialize this module. - * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). - */ -void -sntp_init(void) -{ -#ifdef SNTP_SERVER_ADDRESS -#if SNTP_SERVER_DNS - sntp_setservername(0, SNTP_SERVER_ADDRESS); -#else -#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 -#endif -#endif /* SNTP_SERVER_ADDRESS */ - - if (sntp_pcb == NULL) { - sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); - if (sntp_pcb != NULL) { - udp_recv(sntp_pcb, sntp_recv, NULL); - - if (sntp_opmode == SNTP_OPMODE_POLL) { - SNTP_RESET_RETRY_TIMEOUT(); -#if SNTP_STARTUP_DELAY - sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); -#else - sntp_request(NULL); -#endif - } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) { - ip_set_option(sntp_pcb, SOF_BROADCAST); - udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT); - } - } - } -} - -/** - * @ingroup sntp - * Stop this module. - */ -void -sntp_stop(void) -{ - if (sntp_pcb != NULL) { - sys_untimeout(sntp_request, NULL); - sys_untimeout(sntp_try_next_server, NULL); - udp_remove(sntp_pcb); - sntp_pcb = NULL; - } -} - -/** - * @ingroup sntp - * Get enabled state. - */ -u8_t sntp_enabled(void) -{ - return (sntp_pcb != NULL)? 1 : 0; -} - -/** - * @ingroup sntp - * Sets the operating mode. - * @param operating_mode one of the available operating modes - */ -void -sntp_setoperatingmode(u8_t operating_mode) -{ - LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY); - LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL); - sntp_opmode = operating_mode; -} - -/** - * @ingroup sntp - * Gets the operating mode. - */ -u8_t -sntp_getoperatingmode(void) -{ - return sntp_opmode; -} - -#if SNTP_GET_SERVERS_FROM_DHCP -/** - * Config SNTP server handling by IP address, name, or DHCP; clear table - * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp - */ -void -sntp_servermode_dhcp(int set_servers_from_dhcp) -{ - u8_t new_mode = set_servers_from_dhcp ? 1 : 0; - if (sntp_set_servers_from_dhcp != new_mode) { - sntp_set_servers_from_dhcp = new_mode; - } -} -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ - -/** - * @ingroup sntp - * Initialize one of the NTP servers by IP address - * - * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param server IP address of the NTP server to set - */ -void -sntp_setserver(u8_t idx, const ip_addr_t *server) -{ - if (idx < SNTP_MAX_SERVERS) { - if (server != NULL) { - sntp_servers[idx].addr = (*server); - } else { - ip_addr_set_zero(&sntp_servers[idx].addr); - } -#if SNTP_SERVER_DNS - sntp_servers[idx].name = NULL; -#endif - } -} - -#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP -/** - * Initialize one of the NTP servers by IP address, required by DHCP - * - * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param dnsserver IP address of the NTP server to set - */ -void -dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) -{ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", - (sntp_set_servers_from_dhcp ? "Got" : "Rejected"), - ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); - if (sntp_set_servers_from_dhcp && num) { - u8_t i; - for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { - ip_addr_t addr; - ip_addr_copy_from_ip4(addr, server[i]); - sntp_setserver(i, &addr); - } - for (i = num; i < SNTP_MAX_SERVERS; i++) { - sntp_setserver(i, NULL); - } - } -} -#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ - -/** - * @ingroup sntp - * Obtain one of the currently configured by IP address (or DHCP) NTP servers - * - * @param idx the index of the NTP server - * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP - * server has not been configured by address (or at all). - */ -const ip_addr_t* -sntp_getserver(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return &sntp_servers[idx].addr; - } - return IP_ADDR_ANY; -} - -#if SNTP_SERVER_DNS -/** - * Initialize one of the NTP servers by name - * - * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time - */ -void -sntp_setservername(u8_t idx, char *server) -{ - if (idx < SNTP_MAX_SERVERS) { - sntp_servers[idx].name = server; - } -} - -/** - * Obtain one of the currently configured by name NTP servers. - * - * @param numdns the index of the NTP server - * @return IP address of the indexed NTP server or NULL if the NTP - * server has not been configured by name (or at all) - */ -char * -sntp_getservername(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return sntp_servers[idx].name; - } - return NULL; -} -#endif /* SNTP_SERVER_DNS */ - -#endif /* LWIP_UDP */ diff --git a/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c b/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c deleted file mode 100644 index 38221ac580..0000000000 --- a/components/net/lwip-2.0.2/src/apps/tftp/tftp_port.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017-08-17 armink first version. - */ - - -#include -#include -#include -#include -#include - -static struct tftp_context ctx; - -static void* tftp_open(const char* fname, const char* mode, u8_t write) -{ - int fd = -1; - - if (!rt_strcmp(mode, "octet")) - { - if (write) - { - fd = open(fname, O_WRONLY | O_CREAT, 0); - } - else - { - fd = open(fname, O_RDONLY, 0); - } - } - else - { - rt_kprintf("tftp: No support this mode(%s).", mode); - } - - return (void *) fd; -} - -static int tftp_write(void* handle, struct pbuf* p) -{ - int fd = (int) handle; - - return write(fd, p->payload, p->len); -} - -#if defined(RT_USING_FINSH) -#include - -static void tftp_server(uint8_t argc, char **argv) -{ - ctx.open = tftp_open; - ctx.close = (void (*)(void *)) close; - ctx.read = (int (*)(void *, void *, int)) read; - ctx.write = tftp_write; - - if (tftp_init(&ctx) == ERR_OK) - { - rt_kprintf("TFTP server start successfully.\n"); - } - else - { - rt_kprintf("TFTP server start failed.\n"); - } -} -FINSH_FUNCTION_EXPORT(tftp_server, start tftp server.); - -MSH_CMD_EXPORT(tftp_server, start tftp server.); - -#endif /* defined(RT_USING_FINSH) */ diff --git a/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c b/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c deleted file mode 100644 index afaa3bb08d..0000000000 --- a/components/net/lwip-2.0.2/src/apps/tftp/tftp_server.c +++ /dev/null @@ -1,417 +0,0 @@ -/****************************************************************//** - * - * @file tftp_server.c - * - * @author Logan Gunthorpe - * Dirk Ziegelmeier - * - * @brief Trivial File Transfer Protocol (RFC 1350) - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - ********************************************************************/ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * Dirk Ziegelmeier - * - */ - -/** - * @defgroup tftp TFTP server - * @ingroup apps - * - * This is simple TFTP server for the lwIP raw API. - */ - -#include "lwip/apps/tftp_server.h" - -#if LWIP_UDP - -#include "lwip/udp.h" -#include "lwip/timeouts.h" -#include "lwip/debug.h" - -#define TFTP_MAX_PAYLOAD_SIZE 512 -#define TFTP_HEADER_LENGTH 4 - -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 - -enum tftp_error { - TFTP_ERROR_FILE_NOT_FOUND = 1, - TFTP_ERROR_ACCESS_VIOLATION = 2, - TFTP_ERROR_DISK_FULL = 3, - TFTP_ERROR_ILLEGAL_OPERATION = 4, - TFTP_ERROR_UNKNOWN_TRFR_ID = 5, - TFTP_ERROR_FILE_EXISTS = 6, - TFTP_ERROR_NO_SUCH_USER = 7 -}; - -#include - -struct tftp_state { - const struct tftp_context *ctx; - void *handle; - struct pbuf *last_data; - struct udp_pcb *upcb; - ip_addr_t addr; - u16_t port; - int timer; - int last_pkt; - u16_t blknum; - u8_t retries; - u8_t mode_write; -}; - -static struct tftp_state tftp_state; - -static void tftp_tmr(void* arg); - -static void -close_handle(void) -{ - tftp_state.port = 0; - ip_addr_set_any(0, &tftp_state.addr); - - if(tftp_state.last_data != NULL) { - pbuf_free(tftp_state.last_data); - tftp_state.last_data = NULL; - } - - sys_untimeout(tftp_tmr, NULL); - - if (tftp_state.handle) { - tftp_state.ctx->close(tftp_state.handle); - tftp_state.handle = NULL; - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); - } -} - -static void -send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) -{ - int str_length = strlen(str); - struct pbuf* p; - u16_t* payload; - - p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); - if(p == NULL) { - return; - } - - payload = (u16_t*) p->payload; - payload[0] = PP_HTONS(TFTP_ERROR); - payload[1] = lwip_htons(code); - MEMCPY(&payload[2], str, str_length + 1); - - udp_sendto(tftp_state.upcb, p, addr, port); - pbuf_free(p); -} - -static void -send_ack(u16_t blknum) -{ - struct pbuf* p; - u16_t* payload; - - p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); - if(p == NULL) { - return; - } - payload = (u16_t*) p->payload; - - payload[0] = PP_HTONS(TFTP_ACK); - payload[1] = lwip_htons(blknum); - udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); - pbuf_free(p); -} - -static void -resend_data(void) -{ - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); - if(p == NULL) { - return; - } - - if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) { - pbuf_free(p); - return; - } - - udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); - pbuf_free(p); -} - -static void -send_data(void) -{ - u16_t *payload; - int ret; - - if(tftp_state.last_data != NULL) { - pbuf_free(tftp_state.last_data); - } - - tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); - if(tftp_state.last_data == NULL) { - return; - } - - payload = (u16_t *) tftp_state.last_data->payload; - payload[0] = PP_HTONS(TFTP_DATA); - payload[1] = lwip_htons(tftp_state.blknum); - - ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); - if (ret < 0) { - send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); - close_handle(); - return; - } - - pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); - resend_data(); -} - -static void -recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u16_t *sbuf = (u16_t *) p->payload; - int opcode; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(upcb); - - if (((tftp_state.port != 0) && (port != tftp_state.port)) || - (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); - pbuf_free(p); - return; - } - - opcode = sbuf[0]; - - tftp_state.last_pkt = tftp_state.timer; - tftp_state.retries = 0; - - switch (opcode) { - case PP_HTONS(TFTP_RRQ): /* fall through */ - case PP_HTONS(TFTP_WRQ): - { - const char tftp_null = 0; - char filename[TFTP_MAX_FILENAME_LEN + 1] = { 0 }; - char mode[TFTP_MAX_MODE_LEN] = { 0 }; - u16_t filename_end_offset; - u16_t mode_end_offset; - - if(tftp_state.handle != NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); - break; - } - - sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); - - /* find \0 in pbuf -> end of filename string */ - filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); - if((u16_t)(filename_end_offset-2) > sizeof(filename)) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); - break; - } - pbuf_copy_partial(p, filename, filename_end_offset-2, 2); - - /* find \0 in pbuf -> end of mode string */ - mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1); - if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); - break; - } - pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1); - - tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); - tftp_state.blknum = 1; - - if (!tftp_state.handle) { - send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); - break; - } - - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); - ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); - - ip_addr_copy(tftp_state.addr, *addr); - tftp_state.port = port; - - if (opcode == PP_HTONS(TFTP_WRQ)) { - tftp_state.mode_write = 1; - send_ack(0); - } else { - tftp_state.mode_write = 0; - send_data(); - } - - break; - } - - case PP_HTONS(TFTP_DATA): - { - int ret; - u16_t blknum; - - if (tftp_state.handle == NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); - break; - } - - if (tftp_state.mode_write != 1) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); - break; - } - - blknum = lwip_ntohs(sbuf[1]); - pbuf_header(p, -TFTP_HEADER_LENGTH); - - ret = tftp_state.ctx->write(tftp_state.handle, p); - if (ret < 0) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); - close_handle(); - } else { - send_ack(blknum); - } - - if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { - close_handle(); - } - break; - } - - case PP_HTONS(TFTP_ACK): - { - u16_t blknum; - int lastpkt; - - if (tftp_state.handle == NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); - break; - } - - if (tftp_state.mode_write != 0) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); - break; - } - - blknum = lwip_ntohs(sbuf[1]); - if (blknum != tftp_state.blknum) { - send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); - break; - } - - lastpkt = 0; - - if (tftp_state.last_data != NULL) { - lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); - } - - if (!lastpkt) { - tftp_state.blknum++; - send_data(); - } else { - close_handle(); - } - - break; - } - - default: - send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); - break; - } - - pbuf_free(p); -} - -static void -tftp_tmr(void* arg) -{ - LWIP_UNUSED_ARG(arg); - - tftp_state.timer++; - - if (tftp_state.handle == NULL) { - return; - } - - sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); - - if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { - if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); - resend_data(); - tftp_state.retries++; - } else { - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); - close_handle(); - } - } -} - -/** @ingroup tftp - * Initialize TFTP server. - * @param ctx TFTP callback struct - */ -err_t -tftp_init(const struct tftp_context *ctx) -{ - err_t ret; - - struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (pcb == NULL) { - return ERR_MEM; - } - - ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); - if (ret != ERR_OK) { - udp_remove(pcb); - return ret; - } - - tftp_state.handle = NULL; - tftp_state.port = 0; - tftp_state.ctx = ctx; - tftp_state.timer = 0; - tftp_state.last_data = NULL; - tftp_state.upcb = pcb; - - udp_recv(pcb, recv, NULL); - - return ERR_OK; -} - -#endif /* LWIP_UDP */ diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/bpstruct.h b/components/net/lwip-2.0.2/src/arch/include/arch/bpstruct.h deleted file mode 100644 index 74ead358fa..0000000000 --- a/components/net/lwip-2.0.2/src/arch/include/arch/bpstruct.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#if defined(__ICCARM__) -#pragma pack(1) -#endif diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h b/components/net/lwip-2.0.2/src/arch/include/arch/cc.h deleted file mode 100644 index ea201be28a..0000000000 --- a/components/net/lwip-2.0.2/src/arch/include/arch/cc.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2001, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * $Id: cc.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $ - */ -#ifndef __ARCH_CC_H__ -#define __ARCH_CC_H__ - -#include -#include -#include - -#ifndef BYTE_ORDER -#ifdef RT_USING_BIG_ENDIAN -#define BYTE_ORDER BIG_ENDIAN -#else -#define BYTE_ORDER LITTLE_ENDIAN -#endif /* RT_USING_BIG_ENDIAN */ -#endif /* BYTE_ORDER */ - -#define U16_F "hu" -#define S16_F "hd" -#define X16_F "hx" -#define U32_F "lu" -#define S32_F "ld" -#define X32_F "lx" - -#include -/* some errno not defined in newlib */ -#ifndef ENSRNOTFOUND -#define ENSRNOTFOUND 163 /* Domain name not found */ -/* WARNING: ESHUTDOWN also not defined in newlib. We chose - 180 here because the number "108" which is used - in arch.h has been assigned to another error code. */ -#endif - -/* LWIP_TIMEVAL_PRIVATE: provided by */ -#include -#define LWIP_TIMEVAL_PRIVATE 0 - -#if defined(__CC_ARM) /* ARMCC compiler */ -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /*Arm Compiler 6*/ -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT __attribute__((packed)) -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END -#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */ -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_STRUCT -#define PACK_STRUCT_END -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_USE_INCLUDES -#elif defined(__GNUC__) /* GNU GCC Compiler */ -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT __attribute__((packed)) -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END -#elif defined(_MSC_VER) -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END -#endif - -void sys_arch_assert(const char* file, int line); -#define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) -#define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) - -#define SYS_ARCH_DECL_PROTECT(level) register rt_base_t level -#define SYS_ARCH_PROTECT(level) do {level = rt_hw_interrupt_disable();} while(0) -#define SYS_ARCH_UNPROTECT(level) do {rt_hw_interrupt_enable(level);} while(0) - -#endif /* __ARCH_CC_H__ */ diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/epstruct.h b/components/net/lwip-2.0.2/src/arch/include/arch/epstruct.h deleted file mode 100644 index f6390959ea..0000000000 --- a/components/net/lwip-2.0.2/src/arch/include/arch/epstruct.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#if defined(__ICCARM__) -#pragma pack() -#endif diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/perf.h b/components/net/lwip-2.0.2/src/arch/include/arch/perf.h deleted file mode 100644 index 675f1f65dc..0000000000 --- a/components/net/lwip-2.0.2/src/arch/include/arch/perf.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2001, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * $Id: perf.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $ - */ -#ifndef __ARCH_PERF_H__ -#define __ARCH_PERF_H__ - -//#include - -#define PERF_START /* null definition */ -#define PERF_STOP(x) /* null definition */ - -/* -void perf_print(unsigned long c1l, unsigned long c1h, - unsigned long c2l, unsigned long c2h, - char *key); - -void perf_print_times(struct tms *start, struct tms *end, char *key); - -void perf_init(char *fname); -*/ -#endif /* __ARCH_PERF_H__ */ diff --git a/components/net/lwip-2.0.2/src/arch/include/arch/sys_arch.h b/components/net/lwip-2.0.2/src/arch/include/arch/sys_arch.h deleted file mode 100644 index d065298bff..0000000000 --- a/components/net/lwip-2.0.2/src/arch/include/arch/sys_arch.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2001, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * $Id: sys_arch.h,v 1.3 2005/03/13 16:03:23 bear Exp $ - */ -#ifndef __ARCH_SYS_ARCH_H__ -#define __ARCH_SYS_ARCH_H__ - -#include "arch/cc.h" -#include - -#define SYS_MBOX_NULL RT_NULL -#define SYS_SEM_NULL RT_NULL - -typedef rt_uint32_t sys_prot_t; - -#define SYS_MBOX_SIZE 10 -#define SYS_LWIP_TIMER_NAME "timer" -#define SYS_LWIP_MBOX_NAME "mbox" -#define SYS_LWIP_SEM_NAME "sem" -#define SYS_LWIP_MUTEX_NAME "mu" - -typedef rt_sem_t sys_sem_t; -typedef rt_mutex_t sys_mutex_t; -typedef rt_mailbox_t sys_mbox_t; -typedef rt_thread_t sys_thread_t; - -#endif /* __ARCH_SYS_ARCH_H__ */ diff --git a/components/net/lwip-2.0.2/src/arch/sys_arch.c b/components/net/lwip-2.0.2/src/arch/sys_arch.c deleted file mode 100644 index b779264f96..0000000000 --- a/components/net/lwip-2.0.2/src/arch/sys_arch.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - * COPYRIGHT (C) 2006-2021, RT-Thread Development Team - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Change Logs: - * Date Author Notes - * 2012-12-8 Bernard add file header - * export bsd socket symbol for RT-Thread Application Module - * 2017-11-15 Bernard add lock for init_done callback. - */ - -#include -#include - -#include "lwip/sys.h" -#include "lwip/opt.h" -#include "lwip/stats.h" -#include "lwip/err.h" -#include "arch/sys_arch.h" -#include "lwip/debug.h" -#include "lwip/netif.h" -#include "lwip/netifapi.h" -#include "lwip/tcpip.h" -#include "netif/ethernetif.h" -#include "lwip/sio.h" -#include "lwip/init.h" -#include "lwip/dhcp.h" -#include "lwip/inet.h" - -#include - -/* - * Initialize the network interface device - * - * @return the operation status, ERR_OK on OK, ERR_IF on error - */ -static err_t netif_device_init(struct netif *netif) -{ - struct eth_device *ethif; - - ethif = (struct eth_device *)netif->state; - if (ethif != RT_NULL) - { - rt_device_t device; - - /* get device object */ - device = (rt_device_t) ethif; - if (rt_device_init(device) != RT_EOK) - { - return ERR_IF; - } - - /* copy device flags to netif flags */ - netif->flags = ethif->flags; - - return ERR_OK; - } - - return ERR_IF; -} -/* - * Initialize the ethernetif layer and set network interface device up - */ -static void tcpip_init_done_callback(void *arg) -{ - rt_device_t device; - struct eth_device *ethif; - ip4_addr_t ipaddr, netmask, gw; - struct rt_list_node* node; - struct rt_object* object; - struct rt_object_information *information; - - LWIP_ASSERT("invalid arg.\n",arg); - - IP4_ADDR(&gw, 0,0,0,0); - IP4_ADDR(&ipaddr, 0,0,0,0); - IP4_ADDR(&netmask, 0,0,0,0); - - /* enter critical */ - rt_enter_critical(); - - /* for each network interfaces */ - information = rt_object_get_information(RT_Object_Class_Device); - RT_ASSERT(information != RT_NULL); - for (node = information->object_list.next; - node != &(information->object_list); - node = node->next) - { - object = rt_list_entry(node, struct rt_object, list); - device = (rt_device_t)object; - if (device->type == RT_Device_Class_NetIf) - { - ethif = (struct eth_device *)device; - - /* leave critical */ - rt_exit_critical(); - LOCK_TCPIP_CORE(); - - netif_add(ethif->netif, &ipaddr, &netmask, &gw, - ethif, netif_device_init, tcpip_input); - - if (netif_default == RT_NULL) - netif_set_default(ethif->netif); - -#if LWIP_DHCP - /* set interface up */ - netif_set_up(ethif->netif); - /* if this interface uses DHCP, start the DHCP client */ - dhcp_start(ethif->netif); -#else - /* set interface up */ - netif_set_up(ethif->netif); -#endif - - if (ethif->flags & ETHIF_LINK_PHYUP) - { - netif_set_link_up(ethif->netif); - } - - UNLOCK_TCPIP_CORE(); - /* enter critical */ - rt_enter_critical(); - } - } - - /* leave critical */ - rt_exit_critical(); - rt_sem_release((rt_sem_t)arg); -} - -/** - * LwIP system initialization - */ -extern int eth_system_device_init_private(void); -int lwip_system_init(void) -{ - rt_err_t rc; - struct rt_semaphore done_sem; - static rt_bool_t init_ok = RT_FALSE; - - if (init_ok) - { - rt_kprintf("lwip system already init.\n"); - return 0; - } - - eth_system_device_init_private(); - - /* set default netif to NULL */ - netif_default = RT_NULL; - - rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO); - - if (rc != RT_EOK) - { - LWIP_ASSERT("Failed to create semaphore", 0); - - return -1; - } - - tcpip_init(tcpip_init_done_callback, (void *)&done_sem); - - /* waiting for initialization done */ - if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK) - { - rt_sem_detach(&done_sem); - - return -1; - } - rt_sem_detach(&done_sem); - - /* set default ip address */ -#if !LWIP_DHCP - if (netif_default != RT_NULL) - { - struct ip4_addr ipaddr, netmask, gw; - - ipaddr.addr = inet_addr(RT_LWIP_IPADDR); - gw.addr = inet_addr(RT_LWIP_GWADDR); - netmask.addr = inet_addr(RT_LWIP_MSKADDR); - - netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw); - } -#endif - rt_kprintf("lwIP-%d.%d.%d initialized!\n", LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, LWIP_VERSION_REVISION); - - init_ok = RT_TRUE; - - return 0; -} -INIT_PREV_EXPORT(lwip_system_init); - -void sys_init(void) -{ - /* nothing on RT-Thread porting */ -} - -void lwip_sys_init(void) -{ - lwip_system_init(); -} - -/* - * Create a new semaphore - * - * @return the operation status, ERR_OK on OK; others on error - */ -err_t sys_sem_new(sys_sem_t *sem, u8_t count) -{ - static unsigned short counter = 0; - char tname[RT_NAME_MAX]; - sys_sem_t tmpsem; - - RT_DEBUG_NOT_IN_INTERRUPT; - - rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter); - counter ++; - - tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO); - if (tmpsem == RT_NULL) - return ERR_MEM; - else - { - *sem = tmpsem; - - return ERR_OK; - } -} - -/* - * Deallocate a semaphore - */ -void sys_sem_free(sys_sem_t *sem) -{ - RT_DEBUG_NOT_IN_INTERRUPT; - rt_sem_delete(*sem); -} - -/* - * Signal a semaphore - */ -void sys_sem_signal(sys_sem_t *sem) -{ - rt_sem_release(*sem); -} - -/* - * Block the thread while waiting for the semaphore to be signaled - * - * @return If the timeout argument is non-zero, it will return the number of milliseconds - * spent waiting for the semaphore to be signaled; If the semaphore isn't signaled - * within the specified time, it will return SYS_ARCH_TIMEOUT; If the thread doesn't - * wait for the semaphore, it will return zero - */ -u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) -{ - rt_err_t ret; - s32_t t; - u32_t tick; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* get the begin tick */ - tick = rt_tick_get(); - if (timeout == 0) - t = RT_WAITING_FOREVER; - else - { - /* convert msecond to os tick */ - if (timeout < (1000/RT_TICK_PER_SECOND)) - t = 1; - else - t = timeout / (1000/RT_TICK_PER_SECOND); - } - - ret = rt_sem_take(*sem, t); - - if (ret == -RT_ETIMEOUT) - return SYS_ARCH_TIMEOUT; - else - { - if (ret == RT_EOK) - ret = 1; - } - - /* get elapse msecond */ - tick = rt_tick_get() - tick; - - /* convert tick to msecond */ - tick = tick * (1000 / RT_TICK_PER_SECOND); - if (tick == 0) - tick = 1; - - return tick; -} - -#ifndef sys_sem_valid -/** Check if a semaphore is valid/allocated: - * return 1 for valid, 0 for invalid - */ -int sys_sem_valid(sys_sem_t *sem) -{ - return (int)(*sem); -} -#endif - -#ifndef sys_sem_set_invalid -/** Set a semaphore invalid so that sys_sem_valid returns 0 - */ -void sys_sem_set_invalid(sys_sem_t *sem) -{ - *sem = RT_NULL; -} -#endif - -/* ====================== Mutex ====================== */ - -/** Create a new mutex - * @param mutex pointer to the mutex to create - * @return a new mutex - */ -err_t sys_mutex_new(sys_mutex_t *mutex) -{ - static unsigned short counter = 0; - char tname[RT_NAME_MAX]; - sys_mutex_t tmpmutex; - - RT_DEBUG_NOT_IN_INTERRUPT; - - rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MUTEX_NAME, counter); - counter ++; - - tmpmutex = rt_mutex_create(tname, RT_IPC_FLAG_PRIO); - if (tmpmutex == RT_NULL) - return ERR_MEM; - else - { - *mutex = tmpmutex; - - return ERR_OK; - } -} - -/** Lock a mutex - * @param mutex the mutex to lock - */ -void sys_mutex_lock(sys_mutex_t *mutex) -{ - RT_DEBUG_NOT_IN_INTERRUPT; - rt_mutex_take(*mutex, RT_WAITING_FOREVER); - - return; -} - -/** Unlock a mutex - * @param mutex the mutex to unlock - */ -void sys_mutex_unlock(sys_mutex_t *mutex) -{ - rt_mutex_release(*mutex); -} - -/** Delete a semaphore - * @param mutex the mutex to delete - */ -void sys_mutex_free(sys_mutex_t *mutex) -{ - RT_DEBUG_NOT_IN_INTERRUPT; - - rt_mutex_delete(*mutex); -} - -#ifndef sys_mutex_valid -/** Check if a mutex is valid/allocated: - * return 1 for valid, 0 for invalid - */ -int sys_mutex_valid(sys_mutex_t *mutex) -{ - return (int)(*mutex); -} -#endif - -#ifndef sys_mutex_set_invalid -/** Set a mutex invalid so that sys_mutex_valid returns 0 - */ -void sys_mutex_set_invalid(sys_mutex_t *mutex) -{ - *mutex = RT_NULL; -} -#endif - -/* ====================== Mailbox ====================== */ - -/* - * Create an empty mailbox for maximum "size" elements - * - * @return the operation status, ERR_OK on OK; others on error - */ -err_t sys_mbox_new(sys_mbox_t *mbox, int size) -{ - static unsigned short counter = 0; - char tname[RT_NAME_MAX]; - sys_mbox_t tmpmbox; - - RT_DEBUG_NOT_IN_INTERRUPT; - - rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter); - counter ++; - - tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO); - if (tmpmbox != RT_NULL) - { - *mbox = tmpmbox; - - return ERR_OK; - } - - return ERR_MEM; -} - -/* - * Deallocate a mailbox - */ -void sys_mbox_free(sys_mbox_t *mbox) -{ - RT_DEBUG_NOT_IN_INTERRUPT; - - rt_mb_delete(*mbox); - - return; -} - -/** Post a message to an mbox - may not fail - * -> blocks if full, only used from tasks not from ISR - * @param mbox mbox to posts the message - * @param msg message to post (ATTENTION: can be NULL) - */ -void sys_mbox_post(sys_mbox_t *mbox, void *msg) -{ - RT_DEBUG_NOT_IN_INTERRUPT; - - rt_mb_send_wait(*mbox, (rt_ubase_t)msg, RT_WAITING_FOREVER); - - return; -} - -/* - * Try to post the "msg" to the mailbox - * - * @return return ERR_OK if the "msg" is posted, ERR_MEM if the mailbox is full - */ -err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) -{ - if (rt_mb_send(*mbox, (rt_ubase_t)msg) == RT_EOK) - return ERR_OK; - - return ERR_MEM; -} - -/** Wait for a new message to arrive in the mbox - * @param mbox mbox to get a message from - * @param msg pointer where the message is stored - * @param timeout maximum time (in milliseconds) to wait for a message - * @return time (in milliseconds) waited for a message, may be 0 if not waited - or SYS_ARCH_TIMEOUT on timeout - * The returned time has to be accurate to prevent timer jitter! - */ -u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) -{ - rt_err_t ret; - s32_t t; - u32_t tick; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* get the begin tick */ - tick = rt_tick_get(); - - if(timeout == 0) - t = RT_WAITING_FOREVER; - else - { - /* convirt msecond to os tick */ - if (timeout < (1000/RT_TICK_PER_SECOND)) - t = 1; - else - t = timeout / (1000/RT_TICK_PER_SECOND); - } - - ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t); - if(ret != RT_EOK) - { - return SYS_ARCH_TIMEOUT; - } - - /* get elapse msecond */ - tick = rt_tick_get() - tick; - - /* convert tick to msecond */ - tick = tick * (1000 / RT_TICK_PER_SECOND); - if (tick == 0) - tick = 1; - - return tick; -} - -/** - * @ingroup sys_mbox - * This is similar to sys_arch_mbox_fetch, however if a message is not - * present in the mailbox, it immediately returns with the code - * SYS_MBOX_EMPTY. On success 0 is returned. - * To allow for efficient implementations, this can be defined as a - * function-like macro in sys_arch.h instead of a normal function. For - * example, a naive implementation could be: - * \#define sys_arch_mbox_tryfetch(mbox,msg) sys_arch_mbox_fetch(mbox,msg,1) - * although this would introduce unnecessary delays. - * - * @param mbox mbox to get a message from - * @param msg pointer where the message is stored - * @return 0 (milliseconds) if a message has been received - * or SYS_MBOX_EMPTY if the mailbox is empty - */ -u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) -{ - int ret; - - ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0); - - if(ret == -RT_ETIMEOUT) - return SYS_ARCH_TIMEOUT; - else - { - if (ret == RT_EOK) - ret = 0; - } - - return ret; -} - -#ifndef sys_mbox_valid -/** Check if an mbox is valid/allocated: - * return 1 for valid, 0 for invalid - */ -int sys_mbox_valid(sys_mbox_t *mbox) -{ - return (int)(*mbox); -} -#endif - -#ifndef sys_mbox_set_invalid -/** Set an mbox invalid so that sys_mbox_valid returns 0 - */ -void sys_mbox_set_invalid(sys_mbox_t *mbox) -{ - *mbox = RT_NULL; -} -#endif - -/* ====================== System ====================== */ - -/* - * Start a new thread named "name" with priority "prio" that will begin - * its execution in the function "thread()". The "arg" argument will be - * passed as an argument to the thread() function - */ -sys_thread_t sys_thread_new(const char *name, - lwip_thread_fn thread, - void *arg, - int stacksize, - int prio) -{ - rt_thread_t t; - - RT_DEBUG_NOT_IN_INTERRUPT; - - /* create thread */ - t = rt_thread_create(name, thread, arg, stacksize, prio, 20); - RT_ASSERT(t != RT_NULL); - - /* startup thread */ - rt_thread_startup(t); - - return t; -} - -sys_prot_t sys_arch_protect(void) -{ - rt_base_t level; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - return level; -} - -void sys_arch_unprotect(sys_prot_t pval) -{ - /* enable interrupt */ - rt_hw_interrupt_enable(pval); - - return; -} - -void sys_arch_assert(const char *file, int line) -{ - rt_kprintf("\nAssertion: %d in %s, thread %s\n", - line, file, rt_thread_self()->name); - RT_ASSERT(0); -} - -u32_t sys_jiffies(void) -{ - return rt_tick_get(); -} - -u32_t sys_now(void) -{ - return rt_tick_get_millisecond(); -} - - -RT_WEAK -void mem_init(void) -{ -} - -void *mem_calloc(mem_size_t count, mem_size_t size) -{ - return rt_calloc(count, size); -} - -void *mem_trim(void *mem, mem_size_t size) -{ - // return rt_realloc(mem, size); - /* not support trim yet */ - return mem; -} - -void *mem_malloc(mem_size_t size) -{ - return rt_malloc(size); -} - -void mem_free(void *mem) -{ - rt_free(mem); -} - -#ifdef RT_LWIP_PPP -u32_t sio_read(sio_fd_t fd, u8_t *buf, u32_t size) -{ - u32_t len; - - RT_ASSERT(fd != RT_NULL); - - len = rt_device_read((rt_device_t)fd, 0, buf, size); - if (len <= 0) - return 0; - - return len; -} - -u32_t sio_write(sio_fd_t fd, u8_t *buf, u32_t size) -{ - RT_ASSERT(fd != RT_NULL); - - return rt_device_write((rt_device_t)fd, 0, buf, size); -} - -void sio_read_abort(sio_fd_t fd) -{ - rt_kprintf("read_abort\n"); -} - -void ppp_trace(int level, const char *format, ...) -{ - va_list args; - rt_size_t length; - static char rt_log_buf[RT_CONSOLEBUF_SIZE]; - - va_start(args, format); - length = rt_vsprintf(rt_log_buf, format, args); - rt_device_write((rt_device_t)rt_console_get_device(), 0, rt_log_buf, length); - va_end(args); -} -#endif - -/* - * export bsd socket symbol for RT-Thread Application Module - */ -#if LWIP_SOCKET -#include -RTM_EXPORT(lwip_accept); -RTM_EXPORT(lwip_bind); -RTM_EXPORT(lwip_shutdown); -RTM_EXPORT(lwip_getpeername); -RTM_EXPORT(lwip_getsockname); -RTM_EXPORT(lwip_getsockopt); -RTM_EXPORT(lwip_setsockopt); -RTM_EXPORT(lwip_close); -RTM_EXPORT(lwip_connect); -RTM_EXPORT(lwip_listen); -RTM_EXPORT(lwip_recv); -RTM_EXPORT(lwip_read); -RTM_EXPORT(lwip_recvfrom); -RTM_EXPORT(lwip_send); -RTM_EXPORT(lwip_sendto); -RTM_EXPORT(lwip_socket); -RTM_EXPORT(lwip_write); -RTM_EXPORT(lwip_select); -RTM_EXPORT(lwip_ioctl); -RTM_EXPORT(lwip_fcntl); - -RTM_EXPORT(lwip_htons); -RTM_EXPORT(lwip_htonl); - -#if LWIP_DNS -#include -RTM_EXPORT(lwip_gethostbyname); -RTM_EXPORT(lwip_gethostbyname_r); -RTM_EXPORT(lwip_freeaddrinfo); -RTM_EXPORT(lwip_getaddrinfo); -#endif - -#endif - -#if LWIP_DHCP -#include -RTM_EXPORT(dhcp_start); -RTM_EXPORT(dhcp_renew); -RTM_EXPORT(dhcp_stop); -#endif - -#if LWIP_NETIF_API -#include -RTM_EXPORT(netifapi_netif_set_addr); -#endif - -#if LWIP_NETIF_LINK_CALLBACK -RTM_EXPORT(netif_set_link_callback); -#endif - -#if LWIP_NETIF_STATUS_CALLBACK -RTM_EXPORT(netif_set_status_callback); -#endif - -RTM_EXPORT(netif_find); -RTM_EXPORT(netif_set_addr); -RTM_EXPORT(netif_set_ipaddr); -RTM_EXPORT(netif_set_gw); -RTM_EXPORT(netif_set_netmask); diff --git a/components/net/lwip-2.0.2/src/core/def.c b/components/net/lwip-2.0.2/src/core/def.c deleted file mode 100644 index 8125313f41..0000000000 --- a/components/net/lwip-2.0.2/src/core/def.c +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @file - * Common functions used throughout the stack. - * - * These are reference implementations of the byte swapping functions. - * Again with the aim of being simple, correct and fully portable. - * Byte swapping is the second thing you would want to optimize. You will - * need to port it to your architecture and in your cc.h: - * - * \#define lwip_htons(x) your_htons - * \#define lwip_htonl(x) your_htonl - * - * Note lwip_ntohs() and lwip_ntohl() are merely references to the htonx counterparts. - * - * If you \#define them to htons() and htonl(), you should - * \#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from - * defining htonx/ntohx compatibility macros. - - * @defgroup sys_nonstandard Non-standard functions - * @ingroup sys_layer - * lwIP provides default implementations for non-standard functions. - * These can be mapped to OS functions to reduce code footprint if desired. - * All defines related to this section must not be placed in lwipopts.h, - * but in arch/cc.h! - * These options cannot be \#defined in lwipopts.h since they are not options - * of lwIP itself, but options of the lwIP port to your system. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ - -#include "lwip/opt.h" -#include "lwip/def.h" - -#include - -#if BYTE_ORDER == LITTLE_ENDIAN - -#if !defined(lwip_htons) -/** - * Convert an u16_t from host- to network byte order. - * - * @param n u16_t in host byte order - * @return n in network byte order - */ -u16_t -lwip_htons(u16_t n) -{ - return (u16_t)PP_HTONS(n); -} -#endif /* lwip_htons */ - -#if !defined(lwip_htonl) -/** - * Convert an u32_t from host- to network byte order. - * - * @param n u32_t in host byte order - * @return n in network byte order - */ -u32_t -lwip_htonl(u32_t n) -{ - return (u32_t)PP_HTONL(n); -} -#endif /* lwip_htonl */ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#ifndef lwip_strnstr -/** - * @ingroup sys_nonstandard - * lwIP default implementation for strnstr() non-standard function. - * This can be \#defined to strnstr() depending on your platform port. - */ -char* -lwip_strnstr(const char* buffer, const char* token, size_t n) -{ - const char* p; - size_t tokenlen = strlen(token); - if (tokenlen == 0) { - return LWIP_CONST_CAST(char *, buffer); - } - for (p = buffer; *p && (p + tokenlen <= buffer + n); p++) { - if ((*p == *token) && (strncmp(p, token, tokenlen) == 0)) { - return LWIP_CONST_CAST(char *, p); - } - } - return NULL; -} -#endif - -#ifndef lwip_stricmp -/** - * @ingroup sys_nonstandard - * lwIP default implementation for stricmp() non-standard function. - * This can be \#defined to stricmp() depending on your platform port. - */ -int -lwip_stricmp(const char* str1, const char* str2) -{ - char c1, c2; - - do { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) { - char c1_upc = c1 | 0x20; - if ((c1_upc >= 'a') && (c1_upc <= 'z')) { - /* characters are not equal an one is in the alphabet range: - downcase both chars and check again */ - char c2_upc = c2 | 0x20; - if (c1_upc != c2_upc) { - /* still not equal */ - /* don't care for < or > */ - return 1; - } - } else { - /* characters are not equal but none is in the alphabet range */ - return 1; - } - } - } while (c1 != 0); - return 0; -} -#endif - -#ifndef lwip_strnicmp -/** - * @ingroup sys_nonstandard - * lwIP default implementation for strnicmp() non-standard function. - * This can be \#defined to strnicmp() depending on your platform port. - */ -int -lwip_strnicmp(const char* str1, const char* str2, size_t len) -{ - char c1, c2; - - do { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) { - char c1_upc = c1 | 0x20; - if ((c1_upc >= 'a') && (c1_upc <= 'z')) { - /* characters are not equal an one is in the alphabet range: - downcase both chars and check again */ - char c2_upc = c2 | 0x20; - if (c1_upc != c2_upc) { - /* still not equal */ - /* don't care for < or > */ - return 1; - } - } else { - /* characters are not equal but none is in the alphabet range */ - return 1; - } - } - } while (len-- && c1 != 0); - return 0; -} -#endif - -#ifndef lwip_itoa -/** - * @ingroup sys_nonstandard - * lwIP default implementation for itoa() non-standard function. - * This can be \#defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform port. - */ -void -lwip_itoa(char* result, size_t bufsize, int number) -{ - const int base = 10; - char* ptr = result, *ptr1 = result, tmp_char; - int tmp_value; - LWIP_UNUSED_ARG(bufsize); - - do { - tmp_value = number; - number /= base; - *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - number * base)]; - } while(number); - - /* Apply negative sign */ - if (tmp_value < 0) { - *ptr++ = '-'; - } - *ptr-- = '\0'; - while(ptr1 < ptr) { - tmp_char = *ptr; - *ptr--= *ptr1; - *ptr1++ = tmp_char; - } -} -#endif diff --git a/components/net/lwip-2.0.2/src/core/dns.c b/components/net/lwip-2.0.2/src/core/dns.c deleted file mode 100644 index cd4de06229..0000000000 --- a/components/net/lwip-2.0.2/src/core/dns.c +++ /dev/null @@ -1,1587 +0,0 @@ -/** - * @file - * DNS - host name to IP address resolver. - * - * @defgroup dns DNS - * @ingroup callbackstyle_api - * - * Implements a DNS host name to IP address resolver. - * - * The lwIP DNS resolver functions are used to lookup a host name and - * map it to a numerical IP address. It maintains a list of resolved - * hostnames that can be queried with the dns_lookup() function. - * New hostnames can be resolved using the dns_query() function. - * - * The lwIP version of the resolver also adds a non-blocking version of - * gethostbyname() that will work with a raw API application. This function - * checks for an IP address string first and converts it if it is valid. - * gethostbyname() then does a dns_lookup() to see if the name is - * already in the table. If so, the IP is returned. If not, a query is - * issued and the function returns with a ERR_INPROGRESS status. The app - * using the dns client must then go into a waiting state. - * - * Once a hostname has been resolved (or found to be non-existent), - * the resolver code calls a specified callback function (which - * must be implemented by the module that uses the resolver). - * - * Multicast DNS queries are supported for names ending on ".local". - * However, only "One-Shot Multicast DNS Queries" are supported (RFC 6762 - * chapter 5.1), this is not a fully compliant implementation of continuous - * mDNS querying! - * - * All functions must be called from TCPIP thread. - * - * @see @ref netconn_common for thread-safe access. - */ - -/* - * Port to lwIP from uIP - * by Jim Pettinato April 2007 - * - * security fixes and more by Simon Goldschmidt - * - * uIP version Copyright (c) 2002-2003, Adam Dunkels. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/*----------------------------------------------------------------------------- - * RFC 1035 - Domain names - implementation and specification - * RFC 2181 - Clarifications to the DNS Specification - *----------------------------------------------------------------------------*/ - -/** @todo: define good default values (rfc compliance) */ -/** @todo: improve answer parsing, more checkings... */ -/** @todo: check RFC1035 - 7.3. Processing responses */ -/** @todo: one-shot mDNS: dual-stack fallback to another IP version */ - -/*----------------------------------------------------------------------------- - * Includes - *----------------------------------------------------------------------------*/ - -#include "lwip/opt.h" - -#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/udp.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/dns.h" -#include "lwip/prot/dns.h" - -#include - -#include - -/** Random generator function to create random TXIDs and source ports for queries */ -#ifndef DNS_RAND_TXID -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_XID) != 0) -#define DNS_RAND_TXID LWIP_RAND -#else -static u16_t dns_txid; -#define DNS_RAND_TXID() (++dns_txid) -#endif -#endif - -/** Limits the source port to be >= 1024 by default */ -#ifndef DNS_PORT_ALLOWED -#define DNS_PORT_ALLOWED(port) ((port) >= 1024) -#endif - -/** DNS maximum number of retries when asking for a name, before "timeout". */ -#ifndef DNS_MAX_RETRIES -#define DNS_MAX_RETRIES 4 -#endif - -/** DNS resource record max. TTL (one week as default) */ -#ifndef DNS_MAX_TTL -#define DNS_MAX_TTL 604800 -#elif DNS_MAX_TTL > 0x7FFFFFFF -#error DNS_MAX_TTL must be a positive 32-bit value -#endif - -#if DNS_TABLE_SIZE > 255 -#error DNS_TABLE_SIZE must fit into an u8_t -#endif -#if DNS_MAX_SERVERS > 255 -#error DNS_MAX_SERVERS must fit into an u8_t -#endif - -/* The number of parallel requests (i.e. calls to dns_gethostbyname - * that cannot be answered from the DNS table. - * This is set to the table size by default. - */ -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) -#ifndef DNS_MAX_REQUESTS -#define DNS_MAX_REQUESTS DNS_TABLE_SIZE -#else -#if DNS_MAX_REQUESTS > 255 -#error DNS_MAX_REQUESTS must fit into an u8_t -#endif -#endif -#else -/* In this configuration, both arrays have to have the same size and are used - * like one entry (used/free) */ -#define DNS_MAX_REQUESTS DNS_TABLE_SIZE -#endif - -/* The number of UDP source ports used in parallel */ -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) -#ifndef DNS_MAX_SOURCE_PORTS -#define DNS_MAX_SOURCE_PORTS DNS_MAX_REQUESTS -#else -#if DNS_MAX_SOURCE_PORTS > 255 -#error DNS_MAX_SOURCE_PORTS must fit into an u8_t -#endif -#endif -#else -#ifdef DNS_MAX_SOURCE_PORTS -#undef DNS_MAX_SOURCE_PORTS -#endif -#define DNS_MAX_SOURCE_PORTS 1 -#endif - -#if LWIP_IPV4 && LWIP_IPV6 -#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) (((t) == LWIP_DNS_ADDRTYPE_IPV6_IPV4) || ((t) == LWIP_DNS_ADDRTYPE_IPV6)) -#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) (IP_IS_V6_VAL(ip) ? LWIP_DNS_ADDRTYPE_IS_IPV6(t) : (!LWIP_DNS_ADDRTYPE_IS_IPV6(t))) -#define LWIP_DNS_ADDRTYPE_ARG(x) , x -#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) x -#define LWIP_DNS_SET_ADDRTYPE(x, y) do { x = y; } while(0) -#else -#if LWIP_IPV6 -#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 1 -#else -#define LWIP_DNS_ADDRTYPE_IS_IPV6(t) 0 -#endif -#define LWIP_DNS_ADDRTYPE_MATCH_IP(t, ip) 1 -#define LWIP_DNS_ADDRTYPE_ARG(x) -#define LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(x) 0 -#define LWIP_DNS_SET_ADDRTYPE(x, y) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES -#define LWIP_DNS_ISMDNS_ARG(x) , x -#else -#define LWIP_DNS_ISMDNS_ARG(x) -#endif - -/** DNS query message structure. - No packing needed: only used locally on the stack. */ -struct dns_query { - /* DNS query record starts with either a domain name or a pointer - to a name already present somewhere in the packet. */ - u16_t type; - u16_t cls; -}; -#define SIZEOF_DNS_QUERY 4 - -/** DNS answer message structure. - No packing needed: only used locally on the stack. */ -struct dns_answer { - /* DNS answer record starts with either a domain name or a pointer - to a name already present somewhere in the packet. */ - u16_t type; - u16_t cls; - u32_t ttl; - u16_t len; -}; -#define SIZEOF_DNS_ANSWER 10 -/* maximum allowed size for the struct due to non-packed */ -#define SIZEOF_DNS_ANSWER_ASSERT 12 - -/* DNS table entry states */ -typedef enum { - DNS_STATE_UNUSED = 0, - DNS_STATE_NEW = 1, - DNS_STATE_ASKING = 2, - DNS_STATE_DONE = 3 -} dns_state_enum_t; - -/** DNS table entry */ -struct dns_table_entry { - u32_t ttl; - ip_addr_t ipaddr; - u16_t txid; - u8_t state; - u8_t server_idx; - u8_t tmr; - u8_t retries; - u8_t seqno; -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - u8_t pcb_idx; -#endif - char name[DNS_MAX_NAME_LENGTH]; -#if LWIP_IPV4 && LWIP_IPV6 - u8_t reqaddrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - u8_t is_mdns; -#endif -}; - -/** DNS request table entry: used when dns_gehostbyname cannot answer the - * request from the DNS table */ -struct dns_req_entry { - /* pointer to callback on DNS query done */ - dns_found_callback found; - /* argument passed to the callback function */ - void *arg; -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - u8_t dns_table_idx; -#endif -#if LWIP_IPV4 && LWIP_IPV6 - u8_t reqaddrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -}; - -#if DNS_LOCAL_HOSTLIST - -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -/** Local host-list. For hostnames in this list, no - * external name resolution is performed */ -static struct local_hostlist_entry *local_hostlist_dynamic; -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -/** Defining this allows the local_hostlist_static to be placed in a different - * linker section (e.g. FLASH) */ -#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE -#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static -#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */ -/** Defining this allows the local_hostlist_static to be placed in a different - * linker section (e.g. FLASH) */ -#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST -#define DNS_LOCAL_HOSTLIST_STORAGE_POST -#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */ -DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[] - DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT; - -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -static void dns_init_local(void); -static err_t dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)); -#endif /* DNS_LOCAL_HOSTLIST */ - - -/* forward declarations */ -static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); -static void dns_check_entries(void); -static void dns_call_found(u8_t idx, ip_addr_t* addr); - -/*----------------------------------------------------------------------------- - * Globals - *----------------------------------------------------------------------------*/ - -/* DNS variables */ -static struct udp_pcb *dns_pcbs[DNS_MAX_SOURCE_PORTS]; -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) -static u8_t dns_last_pcb_idx; -#endif -static u8_t dns_seqno; -static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; -static struct dns_req_entry dns_requests[DNS_MAX_REQUESTS]; -static ip_addr_t dns_servers[DNS_MAX_SERVERS]; - -#if LWIP_IPV4 -const ip_addr_t dns_mquery_v4group = DNS_MQUERY_IPV4_GROUP_INIT; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 -const ip_addr_t dns_mquery_v6group = DNS_MQUERY_IPV6_GROUP_INIT; -#endif /* LWIP_IPV6 */ - -/** - * Initialize the resolver: set up the UDP pcb and configure the default server - * (if DNS_SERVER_ADDRESS is set). - */ -void -dns_init(void) -{ -#ifdef DNS_SERVER_ADDRESS - /* initialize default DNS server address */ - ip_addr_t dnsserver; - DNS_SERVER_ADDRESS(&dnsserver); - dns_setserver(0, &dnsserver); -#endif /* DNS_SERVER_ADDRESS */ - - LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY", - sizeof(struct dns_query) == SIZEOF_DNS_QUERY); - LWIP_ASSERT("sanity check SIZEOF_DNS_ANSWER", - sizeof(struct dns_answer) <= SIZEOF_DNS_ANSWER_ASSERT); - - LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); - - /* if dns client not yet initialized... */ -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) - if (dns_pcbs[0] == NULL) { - dns_pcbs[0] = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("dns_pcbs[0] != NULL", dns_pcbs[0] != NULL); - - /* initialize DNS table not needed (initialized to zero since it is a - * global variable) */ - LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0", - DNS_STATE_UNUSED == 0); - - /* initialize DNS client */ - udp_bind(dns_pcbs[0], IP_ANY_TYPE, 0); - udp_recv(dns_pcbs[0], dns_recv, NULL); - } -#endif - -#if DNS_LOCAL_HOSTLIST - dns_init_local(); -#endif -} - -/** - * @ingroup dns - * Initialize one of the DNS servers. - * - * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS - * @param dnsserver IP address of the DNS server to set - */ -void -dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) -{ - if (numdns < DNS_MAX_SERVERS) { - if (dnsserver != NULL) { - dns_servers[numdns] = (*dnsserver); - -#ifdef RT_USING_NETDEV - extern struct netif *netif_list; - extern struct netdev *netdev_get_by_name(const char *name); - extern void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server); - struct netif *netif = NULL; - - /* set network interface device DNS server address */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - netdev_low_level_set_dns_server(netdev_get_by_name(netif->name), numdns, dnsserver); - } -#endif /* RT_USING_NETDEV */ - } else { - dns_servers[numdns] = *IP_ADDR_ANY; - } - } -} - -/** - * @ingroup dns - * Obtain one of the currently configured DNS server. - * - * @param numdns the index of the DNS server - * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS - * server has not been configured. - */ -const ip_addr_t* -dns_getserver(u8_t numdns) -{ - if (numdns < DNS_MAX_SERVERS) { - return &dns_servers[numdns]; - } else { - return IP_ADDR_ANY; - } -} - -/** - * The DNS resolver client timer - handle retries and timeouts and should - * be called every DNS_TMR_INTERVAL milliseconds (every second by default). - */ -void -dns_tmr(void) -{ - LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n")); - dns_check_entries(); -} - -#if DNS_LOCAL_HOSTLIST -static void -dns_init_local(void) -{ -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) - size_t i; - struct local_hostlist_entry *entry; - /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */ - struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT; - size_t namelen; - for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_init); i++) { - struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; - LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); - namelen = strlen(init_entry->name); - LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); - entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); - LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); - if (entry != NULL) { - char* entry_name = (char*)entry + sizeof(struct local_hostlist_entry); - MEMCPY(entry_name, init_entry->name, namelen); - entry_name[namelen] = 0; - entry->name = entry_name; - entry->addr = init_entry->addr; - entry->next = local_hostlist_dynamic; - local_hostlist_dynamic = entry; - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */ -} - -/** - * @ingroup dns - * Iterate the local host-list for a hostname. - * - * @param iterator_fn a function that is called for every entry in the local host-list - * @param iterator_arg 3rd argument passed to iterator_fn - * @return the number of entries in the local host-list - */ -size_t -dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg) -{ - size_t i; -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC - struct local_hostlist_entry *entry = local_hostlist_dynamic; - i = 0; - while (entry != NULL) { - if (iterator_fn != NULL) { - iterator_fn(entry->name, &entry->addr, iterator_arg); - } - i++; - entry = entry->next; - } -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { - if (iterator_fn != NULL) { - iterator_fn(local_hostlist_static[i].name, &local_hostlist_static[i].addr, iterator_arg); - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - return i; -} - -/** - * @ingroup dns - * Scans the local host-list for a hostname. - * - * @param hostname Hostname to look for in the local host-list - * @param addr the first IP address for the hostname in the local host-list or - * IPADDR_NONE if not found. - * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 (ATTENTION: no fallback here!) - * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 (ATTENTION: no fallback here!) - * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only - * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only - * @return ERR_OK if found, ERR_ARG if not found - */ -err_t -dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype) -{ - LWIP_UNUSED_ARG(dns_addrtype); - return dns_lookup_local(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)); -} - -/* Internal implementation for dns_local_lookup and dns_lookup */ -static err_t -dns_lookup_local(const char *hostname, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) -{ -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC - struct local_hostlist_entry *entry = local_hostlist_dynamic; - while (entry != NULL) { - if ((lwip_stricmp(entry->name, hostname) == 0) && - LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, entry->addr)) { - if (addr) { - ip_addr_copy(*addr, entry->addr); - } - return ERR_OK; - } - entry = entry->next; - } -#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - size_t i; - for (i = 0; i < LWIP_ARRAYSIZE(local_hostlist_static); i++) { - if ((lwip_stricmp(local_hostlist_static[i].name, hostname) == 0) && - LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, local_hostlist_static[i].addr)) { - if (addr) { - ip_addr_copy(*addr, local_hostlist_static[i].addr); - } - return ERR_OK; - } - } -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - return ERR_ARG; -} - -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -/** - * @ingroup dns - * Remove all entries from the local host-list for a specific hostname - * and/or IP address - * - * @param hostname hostname for which entries shall be removed from the local - * host-list - * @param addr address for which entries shall be removed from the local host-list - * @return the number of removed entries - */ -int -dns_local_removehost(const char *hostname, const ip_addr_t *addr) -{ - int removed = 0; - struct local_hostlist_entry *entry = local_hostlist_dynamic; - struct local_hostlist_entry *last_entry = NULL; - while (entry != NULL) { - if (((hostname == NULL) || !lwip_stricmp(entry->name, hostname)) && - ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) { - struct local_hostlist_entry *free_entry; - if (last_entry != NULL) { - last_entry->next = entry->next; - } else { - local_hostlist_dynamic = entry->next; - } - free_entry = entry; - entry = entry->next; - memp_free(MEMP_LOCALHOSTLIST, free_entry); - removed++; - } else { - last_entry = entry; - entry = entry->next; - } - } - return removed; -} - -/** - * @ingroup dns - * Add a hostname/IP address pair to the local host-list. - * Duplicates are not checked. - * - * @param hostname hostname of the new entry - * @param addr IP address of the new entry - * @return ERR_OK if succeeded or ERR_MEM on memory error - */ -err_t -dns_local_addhost(const char *hostname, const ip_addr_t *addr) -{ - struct local_hostlist_entry *entry; - size_t namelen; - char* entry_name; - LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); - namelen = strlen(hostname); - LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); - entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); - if (entry == NULL) { - return ERR_MEM; - } - entry_name = (char*)entry + sizeof(struct local_hostlist_entry); - MEMCPY(entry_name, hostname, namelen); - entry_name[namelen] = 0; - entry->name = entry_name; - ip_addr_copy(entry->addr, *addr); - entry->next = local_hostlist_dynamic; - local_hostlist_dynamic = entry; - return ERR_OK; -} -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/ -#endif /* DNS_LOCAL_HOSTLIST */ - -/** - * @ingroup dns - * Look up a hostname in the array of known hostnames. - * - * @note This function only looks in the internal array of known - * hostnames, it does not send out a query for the hostname if none - * was found. The function dns_enqueue() can be used to send a query - * for a hostname. - * - * @param name the hostname to look up - * @param addr the hostname's IP address, as u32_t (instead of ip_addr_t to - * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname - * was not found in the cached dns_table. - * @return ERR_OK if found, ERR_ARG if not found - */ -static err_t -dns_lookup(const char *name, ip_addr_t *addr LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype)) -{ - u8_t i; -#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) -#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */ -#if DNS_LOCAL_HOSTLIST - if (dns_lookup_local(name, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { - return ERR_OK; - } -#endif /* DNS_LOCAL_HOSTLIST */ -#ifdef DNS_LOOKUP_LOCAL_EXTERN - if (DNS_LOOKUP_LOCAL_EXTERN(name, addr, LWIP_DNS_ADDRTYPE_ARG_OR_ZERO(dns_addrtype)) == ERR_OK) { - return ERR_OK; - } -#endif /* DNS_LOOKUP_LOCAL_EXTERN */ - - /* Walk through name list, return entry if found. If not, return NULL. */ - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - if ((dns_table[i].state == DNS_STATE_DONE) && - (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0) && - LWIP_DNS_ADDRTYPE_MATCH_IP(dns_addrtype, dns_table[i].ipaddr)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name)); - ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr)); - LWIP_DEBUGF(DNS_DEBUG, ("\n")); - if (addr) { - ip_addr_copy(*addr, dns_table[i].ipaddr); - } - return ERR_OK; - } - } - - return ERR_ARG; -} - -/** - * Compare the "dotted" name "query" with the encoded name "response" - * to make sure an answer from the DNS server matches the current dns_table - * entry (otherwise, answers might arrive late for hostname not on the list - * any more). - * - * @param query hostname (not encoded) from the dns_table - * @param p pbuf containing the encoded hostname in the DNS response - * @param start_offset offset into p where the name starts - * @return 0xFFFF: names differ, other: names equal -> offset behind name - */ -static u16_t -dns_compare_name(const char *query, struct pbuf* p, u16_t start_offset) -{ - int n; - u16_t response_offset = start_offset; - - do { - n = pbuf_try_get_at(p, response_offset++); - if (n < 0) { - return 0xFFFF; - } - /** @see RFC 1035 - 4.1.4. Message compression */ - if ((n & 0xc0) == 0xc0) { - /* Compressed name: cannot be equal since we don't send them */ - return 0xFFFF; - } else { - /* Not compressed name */ - while (n > 0) { - int c = pbuf_try_get_at(p, response_offset); - if (c < 0) { - return 0xFFFF; - } - if ((*query) != (u8_t)c) { - return 0xFFFF; - } - ++response_offset; - ++query; - --n; - } - ++query; - } - n = pbuf_try_get_at(p, response_offset); - if (n < 0) { - return 0xFFFF; - } - } while (n != 0); - - return response_offset + 1; -} - -/** - * Walk through a compact encoded DNS name and return the end of the name. - * - * @param p pbuf containing the name - * @param query_idx start index into p pointing to encoded DNS name in the DNS server response - * @return index to end of the name - */ -static u16_t -dns_skip_name(struct pbuf* p, u16_t query_idx) -{ - int n; - u16_t offset = query_idx; - - do { - n = pbuf_try_get_at(p, offset++); - if (n < 0) { - return 0xFFFF; - } - /** @see RFC 1035 - 4.1.4. Message compression */ - if ((n & 0xc0) == 0xc0) { - /* Compressed name: since we only want to skip it (not check it), stop here */ - break; - } else { - /* Not compressed name */ - if (offset + n >= p->tot_len) { - return 0xFFFF; - } - offset = (u16_t)(offset + n); - } - n = pbuf_try_get_at(p, offset); - if (n < 0) { - return 0xFFFF; - } - } while (n != 0); - - return offset + 1; -} - -/** - * Send a DNS query packet. - * - * @param idx the DNS table entry index for which to send a request - * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise - */ -static err_t -dns_send(u8_t idx) -{ - err_t err; - struct dns_hdr hdr; - struct dns_query qry; - struct pbuf *p; - u16_t query_idx, copy_len; - const char *hostname, *hostname_part; - u8_t n; - u8_t pcb_idx; - struct dns_table_entry* entry = &dns_table[idx]; - - LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", - (u16_t)(entry->server_idx), entry->name)); - LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS); - if (ip_addr_isany_val(dns_servers[entry->server_idx]) -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - && !entry->is_mdns -#endif - ) { - /* DNS server not valid anymore, e.g. PPP netif has been shut down */ - /* call specified callback function if provided */ - dns_call_found(idx, NULL); - /* flush this entry */ - entry->state = DNS_STATE_UNUSED; - return ERR_OK; - } - - /* if here, we have either a new query or a retry on a previous query to process */ - p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(SIZEOF_DNS_HDR + strlen(entry->name) + 2 + - SIZEOF_DNS_QUERY), PBUF_RAM); - if (p != NULL) { - const ip_addr_t* dst; - u16_t dst_port; - /* fill dns header */ - memset(&hdr, 0, SIZEOF_DNS_HDR); - hdr.id = lwip_htons(entry->txid); - hdr.flags1 = DNS_FLAG1_RD; - hdr.numquestions = PP_HTONS(1); - pbuf_take(p, &hdr, SIZEOF_DNS_HDR); - hostname = entry->name; - --hostname; - - /* convert hostname into suitable query format. */ - query_idx = SIZEOF_DNS_HDR; - do { - ++hostname; - hostname_part = hostname; - for (n = 0; *hostname != '.' && *hostname != 0; ++hostname) { - ++n; - } - copy_len = (u16_t)(hostname - hostname_part); - pbuf_put_at(p, query_idx, n); - pbuf_take_at(p, hostname_part, copy_len, query_idx + 1); - query_idx += n + 1; - } while (*hostname != 0); - pbuf_put_at(p, query_idx, 0); - query_idx++; - - /* fill dns query */ - if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) { - qry.type = PP_HTONS(DNS_RRTYPE_AAAA); - } else { - qry.type = PP_HTONS(DNS_RRTYPE_A); - } - qry.cls = PP_HTONS(DNS_RRCLASS_IN); - pbuf_take_at(p, &qry, SIZEOF_DNS_QUERY, query_idx); - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - pcb_idx = entry->pcb_idx; -#else - pcb_idx = 0; -#endif - /* send dns packet */ - LWIP_DEBUGF(DNS_DEBUG, ("sending DNS request ID %d for name \"%s\" to server %d\r\n", - entry->txid, entry->name, entry->server_idx)); -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - if (entry->is_mdns) { - dst_port = DNS_MQUERY_PORT; -#if LWIP_IPV6 - if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) - { - dst = &dns_mquery_v6group; - } -#endif -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif -#if LWIP_IPV4 - { - dst = &dns_mquery_v4group; - } -#endif - } else -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - { - dst_port = DNS_SERVER_PORT; - dst = &dns_servers[entry->server_idx]; - } - err = udp_sendto(dns_pcbs[pcb_idx], p, dst, dst_port); - - /* free pbuf */ - pbuf_free(p); - } else { - err = ERR_MEM; - } - - return err; -} - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) -static struct udp_pcb* -dns_alloc_random_port(void) -{ - err_t err; - struct udp_pcb* ret; - - ret = udp_new_ip_type(IPADDR_TYPE_ANY); - if (ret == NULL) { - /* out of memory, have to reuse an existing pcb */ - return NULL; - } - do { - u16_t port = (u16_t)DNS_RAND_TXID(); - if (!DNS_PORT_ALLOWED(port)) { - /* this port is not allowed, try again */ - err = ERR_USE; - continue; - } - err = udp_bind(ret, IP_ANY_TYPE, port); - } while (err == ERR_USE); - if (err != ERR_OK) { - udp_remove(ret); - return NULL; - } - udp_recv(ret, dns_recv, NULL); - return ret; -} - -/** - * dns_alloc_pcb() - allocates a new pcb (or reuses an existing one) to be used - * for sending a request - * - * @return an index into dns_pcbs - */ -static u8_t -dns_alloc_pcb(void) -{ - u8_t i; - u8_t idx; - - for (i = 0; i < DNS_MAX_SOURCE_PORTS; i++) { - if (dns_pcbs[i] == NULL) { - break; - } - } - if (i < DNS_MAX_SOURCE_PORTS) { - dns_pcbs[i] = dns_alloc_random_port(); - if (dns_pcbs[i] != NULL) { - /* succeeded */ - dns_last_pcb_idx = i; - return i; - } - } - /* if we come here, creating a new UDP pcb failed, so we have to use - an already existing one */ - for (i = 0, idx = dns_last_pcb_idx + 1; i < DNS_MAX_SOURCE_PORTS; i++, idx++) { - if (idx >= DNS_MAX_SOURCE_PORTS) { - idx = 0; - } - if (dns_pcbs[idx] != NULL) { - dns_last_pcb_idx = idx; - return idx; - } - } - return DNS_MAX_SOURCE_PORTS; -} -#endif /* ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) */ - -/** - * dns_call_found() - call the found callback and check if there are duplicate - * entries for the given hostname. If there are any, their found callback will - * be called and they will be removed. - * - * @param idx dns table index of the entry that is resolved or removed - * @param addr IP address for the hostname (or NULL on error or memory shortage) - */ -static void -dns_call_found(u8_t idx, ip_addr_t* addr) -{ -#if ((LWIP_DNS_SECURE & (LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT)) != 0) - u8_t i; -#endif - -#if LWIP_IPV4 && LWIP_IPV6 - if (addr != NULL) { - /* check that address type matches the request and adapt the table entry */ - if (IP_IS_V6_VAL(*addr)) { - LWIP_ASSERT("invalid response", LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); - dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; - } else { - LWIP_ASSERT("invalid response", !LWIP_DNS_ADDRTYPE_IS_IPV6(dns_table[idx].reqaddrtype)); - dns_table[idx].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; - } - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - for (i = 0; i < DNS_MAX_REQUESTS; i++) { - if (dns_requests[i].found && (dns_requests[i].dns_table_idx == idx)) { - (*dns_requests[i].found)(dns_table[idx].name, addr, dns_requests[i].arg); - /* flush this entry */ - dns_requests[i].found = NULL; - } - } -#else - if (dns_requests[idx].found) { - (*dns_requests[idx].found)(dns_table[idx].name, addr, dns_requests[idx].arg); - } - dns_requests[idx].found = NULL; -#endif -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - /* close the pcb used unless other request are using it */ - for (i = 0; i < DNS_MAX_REQUESTS; i++) { - if (i == idx) { - continue; /* only check other requests */ - } - if (dns_table[i].state == DNS_STATE_ASKING) { - if (dns_table[i].pcb_idx == dns_table[idx].pcb_idx) { - /* another request is still using the same pcb */ - dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; - break; - } - } - } - if (dns_table[idx].pcb_idx < DNS_MAX_SOURCE_PORTS) { - /* if we come here, the pcb is not used any more and can be removed */ - udp_remove(dns_pcbs[dns_table[idx].pcb_idx]); - dns_pcbs[dns_table[idx].pcb_idx] = NULL; - dns_table[idx].pcb_idx = DNS_MAX_SOURCE_PORTS; - } -#endif -} - -/* Create a query transmission ID that is unique for all outstanding queries */ -static u16_t -dns_create_txid(void) -{ - u16_t txid; - u8_t i; - -again: - txid = (u16_t)DNS_RAND_TXID(); - - /* check whether the ID is unique */ - for (i = 0; i < DNS_TABLE_SIZE; i++) { - if ((dns_table[i].state == DNS_STATE_ASKING) && - (dns_table[i].txid == txid)) { - /* ID already used by another pending query */ - goto again; - } - } - - return txid; -} - -/** - * dns_check_entry() - see if entry has not yet been queried and, if so, sends out a query. - * Check an entry in the dns_table: - * - send out query for new entries - * - retry old pending entries on timeout (also with different servers) - * - remove completed entries from the table if their TTL has expired - * - * @param i index of the dns_table entry to check - */ -static void -dns_check_entry(u8_t i) -{ - err_t err; - struct dns_table_entry *entry = &dns_table[i]; - - LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE); - - switch (entry->state) { - case DNS_STATE_NEW: - /* initialize new entry */ - entry->txid = dns_create_txid(); - entry->state = DNS_STATE_ASKING; - entry->server_idx = 0; - entry->tmr = 1; - entry->retries = 0; - - /* send DNS packet for this entry */ - err = dns_send(i); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("dns_send returned error: %s\n", lwip_strerr(err))); - } - break; - case DNS_STATE_ASKING: - if (--entry->tmr == 0) { - if (++entry->retries == DNS_MAX_RETRIES) { - if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1]) -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - && !entry->is_mdns -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - ) { - /* change of server */ - entry->server_idx++; - entry->tmr = 1; - entry->retries = 0; - } else { - LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", entry->name)); - /* call specified callback function if provided */ - dns_call_found(i, NULL); - /* flush this entry */ - entry->state = DNS_STATE_UNUSED; - break; - } - } else { - /* wait longer for the next retry */ - entry->tmr = entry->retries; - } - - /* send DNS packet for this entry */ - err = dns_send(i); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING, - ("dns_send returned error: %s\n", lwip_strerr(err))); - } - } - break; - case DNS_STATE_DONE: - /* if the time to live is nul */ - if ((entry->ttl == 0) || (--entry->ttl == 0)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", entry->name)); - /* flush this entry, there cannot be any related pending entries in this state */ - entry->state = DNS_STATE_UNUSED; - } - break; - case DNS_STATE_UNUSED: - /* nothing to do */ - break; - default: - LWIP_ASSERT("unknown dns_table entry state:", 0); - break; - } -} - -/** - * Call dns_check_entry for each entry in dns_table - check all entries. - */ -static void -dns_check_entries(void) -{ - u8_t i; - - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - dns_check_entry(i); - } -} - -/** - * Save TTL and call dns_call_found for correct response. - */ -static void -dns_correct_response(u8_t idx, u32_t ttl) -{ - struct dns_table_entry *entry = &dns_table[idx]; - - entry->state = DNS_STATE_DONE; - - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", entry->name)); - ip_addr_debug_print(DNS_DEBUG, (&(entry->ipaddr))); - LWIP_DEBUGF(DNS_DEBUG, ("\n")); - - /* read the answer resource record's TTL, and maximize it if needed */ - entry->ttl = ttl; - if (entry->ttl > DNS_MAX_TTL) { - entry->ttl = DNS_MAX_TTL; - } - dns_call_found(idx, &entry->ipaddr); - - if (entry->ttl == 0) { - /* RFC 883, page 29: "Zero values are - interpreted to mean that the RR can only be used for the - transaction in progress, and should not be cached." - -> flush this entry now */ - /* entry reused during callback? */ - if (entry->state == DNS_STATE_DONE) { - entry->state = DNS_STATE_UNUSED; - } - } -} -/** - * Receive input function for DNS response packets arriving for the dns UDP pcb. - */ -static void -dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u8_t i; - u16_t txid; - u16_t res_idx; - struct dns_hdr hdr; - struct dns_answer ans; - struct dns_query qry; - u16_t nquestions, nanswers; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(port); - - /* is the dns message big enough ? */ - if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY)) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); - /* free pbuf and return */ - goto memerr; - } - - /* copy dns payload inside static buffer for processing */ - if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, 0) == SIZEOF_DNS_HDR) { - /* Match the ID in the DNS header with the name table. */ - txid = lwip_htons(hdr.id); - for (i = 0; i < DNS_TABLE_SIZE; i++) { - const struct dns_table_entry *entry = &dns_table[i]; - if ((entry->state == DNS_STATE_ASKING) && - (entry->txid == txid)) { - - /* We only care about the question(s) and the answers. The authrr - and the extrarr are simply discarded. */ - nquestions = lwip_htons(hdr.numquestions); - nanswers = lwip_htons(hdr.numanswers); - - /* Check for correct response. */ - if ((hdr.flags1 & DNS_FLAG1_RESPONSE) == 0) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": not a response\n", entry->name)); - goto memerr; /* ignore this packet */ - } - if (nquestions != 1) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); - goto memerr; /* ignore this packet */ - } - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - if (!entry->is_mdns) -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - { - /* Check whether response comes from the same network address to which the - question was sent. (RFC 5452) */ - if (!ip_addr_cmp(addr, &dns_servers[entry->server_idx])) { - goto memerr; /* ignore this packet */ - } - } - - /* Check if the name in the "question" part match with the name in the entry and - skip it if equal. */ - res_idx = dns_compare_name(entry->name, p, SIZEOF_DNS_HDR); - if (res_idx == 0xFFFF) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); - goto memerr; /* ignore this packet */ - } - - /* check if "question" part matches the request */ - if (pbuf_copy_partial(p, &qry, SIZEOF_DNS_QUERY, res_idx) != SIZEOF_DNS_QUERY) { - goto memerr; /* ignore this packet */ - } - if ((qry.cls != PP_HTONS(DNS_RRCLASS_IN)) || - (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_AAAA))) || - (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype) && (qry.type != PP_HTONS(DNS_RRTYPE_A)))) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", entry->name)); - goto memerr; /* ignore this packet */ - } - /* skip the rest of the "question" part */ - res_idx += SIZEOF_DNS_QUERY; - - /* Check for error. If so, call callback to inform. */ - if (hdr.flags2 & DNS_FLAG2_ERR_MASK) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", entry->name)); - } else { - while ((nanswers > 0) && (res_idx < p->tot_len)) { - /* skip answer resource record's host name */ - res_idx = dns_skip_name(p, res_idx); - if (res_idx == 0xFFFF) { - goto memerr; /* ignore this packet */ - } - - /* Check for IP address type and Internet class. Others are discarded. */ - if (pbuf_copy_partial(p, &ans, SIZEOF_DNS_ANSWER, res_idx) != SIZEOF_DNS_ANSWER) { - goto memerr; /* ignore this packet */ - } - res_idx += SIZEOF_DNS_ANSWER; - - if (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) { -#if LWIP_IPV4 - if ((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.len == PP_HTONS(sizeof(ip4_addr_t)))) { -#if LWIP_IPV4 && LWIP_IPV6 - if (!LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - { - ip4_addr_t ip4addr; - /* read the IP address after answer resource record's header */ - if (pbuf_copy_partial(p, &ip4addr, sizeof(ip4_addr_t), res_idx) != sizeof(ip4_addr_t)) { - goto memerr; /* ignore this packet */ - } - ip_addr_copy_from_ip4(dns_table[i].ipaddr, ip4addr); - pbuf_free(p); - /* handle correct response */ - dns_correct_response(i, lwip_ntohl(ans.ttl)); - return; - } - } -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - if ((ans.type == PP_HTONS(DNS_RRTYPE_AAAA)) && (ans.len == PP_HTONS(sizeof(ip6_addr_t)))) { -#if LWIP_IPV4 && LWIP_IPV6 - if (LWIP_DNS_ADDRTYPE_IS_IPV6(entry->reqaddrtype)) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - { - ip6_addr_t ip6addr; - /* read the IP address after answer resource record's header */ - if (pbuf_copy_partial(p, &ip6addr, sizeof(ip6_addr_t), res_idx) != sizeof(ip6_addr_t)) { - goto memerr; /* ignore this packet */ - } - ip_addr_copy_from_ip6(dns_table[i].ipaddr, ip6addr); - pbuf_free(p); - /* handle correct response */ - dns_correct_response(i, lwip_ntohl(ans.ttl)); - return; - } - } -#endif /* LWIP_IPV6 */ - } - /* skip this answer */ - if ((int)(res_idx + lwip_htons(ans.len)) > 0xFFFF) { - goto memerr; /* ignore this packet */ - } - res_idx += lwip_htons(ans.len); - --nanswers; - } -#if LWIP_IPV4 && LWIP_IPV6 - if ((entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || - (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { - if (entry->reqaddrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { - /* IPv4 failed, try IPv6 */ - dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV6; - } else { - /* IPv6 failed, try IPv4 */ - dns_table[i].reqaddrtype = LWIP_DNS_ADDRTYPE_IPV4; - } - pbuf_free(p); - dns_table[i].state = DNS_STATE_NEW; - dns_check_entry(i); - return; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", entry->name)); - } - /* call callback to indicate error, clean up memory and return */ - pbuf_free(p); - dns_call_found(i, NULL); - dns_table[i].state = DNS_STATE_UNUSED; - return; - } - } - } - -memerr: - /* deallocate memory and return */ - pbuf_free(p); - return; -} - -/** - * Queues a new hostname to resolve and sends out a DNS query for that hostname - * - * @param name the hostname that is to be queried - * @param hostnamelen length of the hostname - * @param found a callback function to be called on success, failure or timeout - * @param callback_arg argument to pass to the callback function - * @return err_t return code. - */ -static err_t -dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, - void *callback_arg LWIP_DNS_ADDRTYPE_ARG(u8_t dns_addrtype) LWIP_DNS_ISMDNS_ARG(u8_t is_mdns)) -{ - u8_t i; - u8_t lseq, lseqi; - struct dns_table_entry *entry = NULL; - size_t namelen; - struct dns_req_entry* req; - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - u8_t r; - /* check for duplicate entries */ - for (i = 0; i < DNS_TABLE_SIZE; i++) { - if ((dns_table[i].state == DNS_STATE_ASKING) && - (lwip_strnicmp(name, dns_table[i].name, sizeof(dns_table[i].name)) == 0)) { -#if LWIP_IPV4 && LWIP_IPV6 - if (dns_table[i].reqaddrtype != dns_addrtype) { - /* requested address types don't match - this can lead to 2 concurrent requests, but mixing the address types - for the same host should not be that common */ - continue; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - /* this is a duplicate entry, find a free request entry */ - for (r = 0; r < DNS_MAX_REQUESTS; r++) { - if (dns_requests[r].found == 0) { - dns_requests[r].found = found; - dns_requests[r].arg = callback_arg; - dns_requests[r].dns_table_idx = i; - LWIP_DNS_SET_ADDRTYPE(dns_requests[r].reqaddrtype, dns_addrtype); - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": duplicate request\n", name)); - return ERR_INPROGRESS; - } - } - } - } - /* no duplicate entries found */ -#endif - - /* search an unused entry, or the oldest one */ - lseq = 0; - lseqi = DNS_TABLE_SIZE; - for (i = 0; i < DNS_TABLE_SIZE; ++i) { - entry = &dns_table[i]; - /* is it an unused entry ? */ - if (entry->state == DNS_STATE_UNUSED) { - break; - } - /* check if this is the oldest completed entry */ - if (entry->state == DNS_STATE_DONE) { - u8_t age = dns_seqno - entry->seqno; - if (age > lseq) { - lseq = age; - lseqi = i; - } - } - } - - /* if we don't have found an unused entry, use the oldest completed one */ - if (i == DNS_TABLE_SIZE) { - if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) { - /* no entry can be used now, table is full */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name)); - return ERR_MEM; - } else { - /* use the oldest completed one */ - i = lseqi; - entry = &dns_table[i]; - } - } - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING) != 0) - /* find a free request entry */ - req = NULL; - for (r = 0; r < DNS_MAX_REQUESTS; r++) { - if (dns_requests[r].found == NULL) { - req = &dns_requests[r]; - break; - } - } - if (req == NULL) { - /* no request entry can be used now, table is full */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS request entries table is full\n", name)); - return ERR_MEM; - } - req->dns_table_idx = i; -#else - /* in this configuration, the entry index is the same as the request index */ - req = &dns_requests[i]; -#endif - - /* use this entry */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); - - /* fill the entry */ - entry->state = DNS_STATE_NEW; - entry->seqno = dns_seqno; - LWIP_DNS_SET_ADDRTYPE(entry->reqaddrtype, dns_addrtype); - LWIP_DNS_SET_ADDRTYPE(req->reqaddrtype, dns_addrtype); - req->found = found; - req->arg = callback_arg; - namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); - MEMCPY(entry->name, name, namelen); - entry->name[namelen] = 0; - -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) != 0) - entry->pcb_idx = dns_alloc_pcb(); - if (entry->pcb_idx >= DNS_MAX_SOURCE_PORTS) { - /* failed to get a UDP pcb */ - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": failed to allocate a pcb\n", name)); - entry->state = DNS_STATE_UNUSED; - req->found = NULL; - return ERR_MEM; - } - LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS pcb %"U16_F"\n", name, (u16_t)(entry->pcb_idx))); -#endif - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - entry->is_mdns = is_mdns; -#endif - - dns_seqno++; - - /* force to send query without waiting timer */ - dns_check_entry(i); - - /* dns query is enqueued */ - return ERR_INPROGRESS; -} - -/** - * @ingroup dns - * Resolve a hostname (string) into an IP address. - * NON-BLOCKING callback version for use with raw API!!! - * - * Returns immediately with one of err_t return codes: - * - ERR_OK if hostname is a valid IP address string or the host - * name is already in the local names table. - * - ERR_INPROGRESS enqueue a request to be sent to the DNS server - * for resolution if no errors are present. - * - ERR_ARG: dns client not initialized or invalid hostname - * - * @param hostname the hostname that is to be queried - * @param addr pointer to a ip_addr_t where to store the address if it is already - * cached in the dns_table (only valid if ERR_OK is returned!) - * @param found a callback function to be called on success, failure or timeout (only if - * ERR_INPROGRESS is returned!) - * @param callback_arg argument to pass to the callback function - * @return a err_t return code. - */ -err_t -dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, - void *callback_arg) -{ - return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT); -} - -/** - * @ingroup dns - * Like dns_gethostbyname, but returned address type can be controlled: - * @param hostname the hostname that is to be queried - * @param addr pointer to a ip_addr_t where to store the address if it is already - * cached in the dns_table (only valid if ERR_OK is returned!) - * @param found a callback function to be called on success, failure or timeout (only if - * ERR_INPROGRESS is returned!) - * @param callback_arg argument to pass to the callback function - * @param dns_addrtype - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only - * - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only - * - LWIP_DNS_ADDRTYPE_IPV4: try to resolve IPv4 only - * - LWIP_DNS_ADDRTYPE_IPV6: try to resolve IPv6 only - */ -err_t -dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, - void *callback_arg, u8_t dns_addrtype) -{ - size_t hostnamelen; -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - u8_t is_mdns; -#endif - /* not initialized or no valid server yet, or invalid addr pointer - * or invalid hostname or invalid hostname length */ - if ((addr == NULL) || - (!hostname) || (!hostname[0])) { - return ERR_ARG; - } -#if ((LWIP_DNS_SECURE & LWIP_DNS_SECURE_RAND_SRC_PORT) == 0) - if (dns_pcbs[0] == NULL) { - return ERR_ARG; - } -#endif - hostnamelen = strlen(hostname); - if (hostnamelen >= DNS_MAX_NAME_LENGTH) { - LWIP_DEBUGF(DNS_DEBUG, ("dns_gethostbyname: name too long to resolve")); - return ERR_ARG; - } - - -#if LWIP_HAVE_LOOPIF - if (strcmp(hostname, "localhost") == 0) { - ip_addr_set_loopback(LWIP_DNS_ADDRTYPE_IS_IPV6(dns_addrtype), addr); - return ERR_OK; - } -#endif /* LWIP_HAVE_LOOPIF */ - - /* host name already in octet notation? set ip addr and return ERR_OK */ - if (ipaddr_aton(hostname, addr)) { -#if LWIP_IPV4 && LWIP_IPV6 - if ((IP_IS_V6(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV4)) || - (IP_IS_V4(addr) && (dns_addrtype != LWIP_DNS_ADDRTYPE_IPV6))) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - { - return ERR_OK; - } - } - /* already have this address cached? */ - if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(dns_addrtype)) == ERR_OK) { - return ERR_OK; - } -#if LWIP_IPV4 && LWIP_IPV6 - if ((dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) || (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV6_IPV4)) { - /* fallback to 2nd IP type and try again to lookup */ - u8_t fallback; - if (dns_addrtype == LWIP_DNS_ADDRTYPE_IPV4_IPV6) { - fallback = LWIP_DNS_ADDRTYPE_IPV6; - } else { - fallback = LWIP_DNS_ADDRTYPE_IPV4; - } - if (dns_lookup(hostname, addr LWIP_DNS_ADDRTYPE_ARG(fallback)) == ERR_OK) { - return ERR_OK; - } - } -#else /* LWIP_IPV4 && LWIP_IPV6 */ - LWIP_UNUSED_ARG(dns_addrtype); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if LWIP_DNS_SUPPORT_MDNS_QUERIES - if (strstr(hostname, ".local") == &hostname[hostnamelen] - 6) { - is_mdns = 1; - } else { - is_mdns = 0; - } - - if (!is_mdns) -#endif /* LWIP_DNS_SUPPORT_MDNS_QUERIES */ - { - /* prevent calling found callback if no server is set, return error instead */ - if (ip_addr_isany_val(dns_servers[0])) { - return ERR_VAL; - } - } - - /* queue query with specified callback */ - return dns_enqueue(hostname, hostnamelen, found, callback_arg LWIP_DNS_ADDRTYPE_ARG(dns_addrtype) - LWIP_DNS_ISMDNS_ARG(is_mdns)); -} - -#endif /* LWIP_DNS */ diff --git a/components/net/lwip-2.0.2/src/core/inet_chksum.c b/components/net/lwip-2.0.2/src/core/inet_chksum.c deleted file mode 100644 index 917f3e4f1a..0000000000 --- a/components/net/lwip-2.0.2/src/core/inet_chksum.c +++ /dev/null @@ -1,609 +0,0 @@ -/** - * @file - * Incluse internet checksum functions.\n - * - * These are some reference implementations of the checksum algorithm, with the - * aim of being simple, correct and fully portable. Checksumming is the - * first thing you would want to optimize for your platform. If you create - * your own version, link it in and in your cc.h put: - * - * \#define LWIP_CHKSUM your_checksum_routine - * - * Or you can select from the implementations below by defining - * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/inet_chksum.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" - -#include - -#ifndef LWIP_CHKSUM -# define LWIP_CHKSUM lwip_standard_chksum -# ifndef LWIP_CHKSUM_ALGORITHM -# define LWIP_CHKSUM_ALGORITHM 2 -# endif -u16_t lwip_standard_chksum(const void *dataptr, int len); -#endif -/* If none set: */ -#ifndef LWIP_CHKSUM_ALGORITHM -# define LWIP_CHKSUM_ALGORITHM 0 -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */ -/** - * lwip checksum - * - * @param dataptr points to start of data to be summed at any boundary - * @param len length of data to be summed - * @return host order (!) lwip checksum (non-inverted Internet sum) - * - * @note accumulator size limits summable length to 64k - * @note host endianess is irrelevant (p3 RFC1071) - */ -u16_t -lwip_standard_chksum(const void *dataptr, int len) -{ - u32_t acc; - u16_t src; - const u8_t *octetptr; - - acc = 0; - /* dataptr may be at odd or even addresses */ - octetptr = (const u8_t*)dataptr; - while (len > 1) { - /* declare first octet as most significant - thus assume network order, ignoring host order */ - src = (*octetptr) << 8; - octetptr++; - /* declare second octet as least significant */ - src |= (*octetptr); - octetptr++; - acc += src; - len -= 2; - } - if (len > 0) { - /* accumulate remaining octet */ - src = (*octetptr) << 8; - acc += src; - } - /* add deferred carry bits */ - acc = (acc >> 16) + (acc & 0x0000ffffUL); - if ((acc & 0xffff0000UL) != 0) { - acc = (acc >> 16) + (acc & 0x0000ffffUL); - } - /* This maybe a little confusing: reorder sum using lwip_htons() - instead of lwip_ntohs() since it has a little less call overhead. - The caller must invert bits for Internet sum ! */ - return lwip_htons((u16_t)acc); -} -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */ -/* - * Curt McDowell - * Broadcom Corp. - * csm@broadcom.com - * - * IP checksum two bytes at a time with support for - * unaligned buffer. - * Works for len up to and including 0x20000. - * by Curt McDowell, Broadcom Corp. 12/08/2005 - * - * @param dataptr points to start of data to be summed at any boundary - * @param len length of data to be summed - * @return host order (!) lwip checksum (non-inverted Internet sum) - */ -u16_t -lwip_standard_chksum(const void *dataptr, int len) -{ - const u8_t *pb = (const u8_t *)dataptr; - const u16_t *ps; - u16_t t = 0; - u32_t sum = 0; - int odd = ((mem_ptr_t)pb & 1); - - /* Get aligned to u16_t */ - if (odd && len > 0) { - ((u8_t *)&t)[1] = *pb++; - len--; - } - - /* Add the bulk of the data */ - ps = (const u16_t *)(const void *)pb; - while (len > 1) { - sum += *ps++; - len -= 2; - } - - /* Consume left-over byte, if any */ - if (len > 0) { - ((u8_t *)&t)[0] = *(const u8_t *)ps; - } - - /* Add end bytes */ - sum += t; - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - sum = FOLD_U32T(sum); - sum = FOLD_U32T(sum); - - /* Swap if alignment was odd */ - if (odd) { - sum = SWAP_BYTES_IN_WORD(sum); - } - - return (u16_t)sum; -} -#endif - -#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */ -/** - * An optimized checksum routine. Basically, it uses loop-unrolling on - * the checksum loop, treating the head and tail bytes specially, whereas - * the inner loop acts on 8 bytes at a time. - * - * @arg start of buffer to be checksummed. May be an odd byte address. - * @len number of bytes in the buffer to be checksummed. - * @return host order (!) lwip checksum (non-inverted Internet sum) - * - * by Curt McDowell, Broadcom Corp. December 8th, 2005 - */ -u16_t -lwip_standard_chksum(const void *dataptr, int len) -{ - const u8_t *pb = (const u8_t *)dataptr; - const u16_t *ps; - u16_t t = 0; - const u32_t *pl; - u32_t sum = 0, tmp; - /* starts at odd byte address? */ - int odd = ((mem_ptr_t)pb & 1); - - if (odd && len > 0) { - ((u8_t *)&t)[1] = *pb++; - len--; - } - - ps = (const u16_t *)(const void*)pb; - - if (((mem_ptr_t)ps & 3) && len > 1) { - sum += *ps++; - len -= 2; - } - - pl = (const u32_t *)(const void*)ps; - - while (len > 7) { - tmp = sum + *pl++; /* ping */ - if (tmp < sum) { - tmp++; /* add back carry */ - } - - sum = tmp + *pl++; /* pong */ - if (sum < tmp) { - sum++; /* add back carry */ - } - - len -= 8; - } - - /* make room in upper bits */ - sum = FOLD_U32T(sum); - - ps = (const u16_t *)pl; - - /* 16-bit aligned word remaining? */ - while (len > 1) { - sum += *ps++; - len -= 2; - } - - /* dangling tail byte remaining? */ - if (len > 0) { /* include odd byte */ - ((u8_t *)&t)[0] = *(const u8_t *)ps; - } - - sum += t; /* add end bytes */ - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - sum = FOLD_U32T(sum); - sum = FOLD_U32T(sum); - - if (odd) { - sum = SWAP_BYTES_IN_WORD(sum); - } - - return (u16_t)sum; -} -#endif - -/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ -static u16_t -inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc) -{ - struct pbuf *q; - u8_t swapped = 0; - - /* iterate through all pbuf in chain */ - for (q = p; q != NULL; q = q->next) { - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", - (void *)q, (void *)q->next)); - acc += LWIP_CHKSUM(q->payload, q->len); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ - /* just executing this next line is probably faster that the if statement needed - to check whether we really need to execute it, and does no harm */ - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - - acc += (u32_t)lwip_htons((u16_t)proto); - acc += (u32_t)lwip_htons(proto_len); - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); - return (u16_t)~(acc & 0xffffUL); -} - -#if LWIP_IPV4 -/* inet_chksum_pseudo: - * - * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip4_addr_t *src, const ip4_addr_t *dest) -{ - u32_t acc; - u32_t addr; - - addr = ip4_addr_get_u32(src); - acc = (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = ip4_addr_get_u32(dest); - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_base(p, proto, proto_len, acc); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. - * IPv6 addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param proto ipv6 protocol/next header (used for checksum of pseudo header) - * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) - * @param src source ipv6 address (used for checksum of pseudo header) - * @param dest destination ipv6 address (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip6_addr_t *src, const ip6_addr_t *dest) -{ - u32_t acc = 0; - u32_t addr; - u8_t addr_part; - - for (addr_part = 0; addr_part < 4; addr_part++) { - addr = src->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = dest->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - } - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_base(p, proto, proto_len, acc); -} -#endif /* LWIP_IPV6 */ - -/* ip_chksum_pseudo: - * - * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip_addr_t *src, const ip_addr_t *dest) -{ -#if LWIP_IPV6 - if (IP_IS_V6(dest)) { - return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest)); - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_IPV4 - { - return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); - } -#endif /* LWIP_IPV4 */ -} - -/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */ -static u16_t -inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, u32_t acc) -{ - struct pbuf *q; - u8_t swapped = 0; - u16_t chklen; - - /* iterate through all pbuf in chain */ - for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) { - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n", - (void *)q, (void *)q->next)); - chklen = q->len; - if (chklen > chksum_len) { - chklen = chksum_len; - } - acc += LWIP_CHKSUM(q->payload, chklen); - chksum_len -= chklen; - LWIP_ASSERT("delete me", chksum_len < 0x7fff); - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/ - /* fold the upper bit down */ - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/ - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - - acc += (u32_t)lwip_htons((u16_t)proto); - acc += (u32_t)lwip_htons(proto_len); - - /* Fold 32-bit sum to 16 bits - calling this twice is probably faster than if statements... */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc)); - return (u16_t)~(acc & 0xffffUL); -} - -#if LWIP_IPV4 -/* inet_chksum_pseudo_partial: - * - * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * IP addresses are expected to be in network byte order. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest) -{ - u32_t acc; - u32_t addr; - - addr = ip4_addr_get_u32(src); - acc = (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = ip4_addr_get_u32(dest); - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain. - * IPv6 addresses are expected to be in network byte order. Will only compute for a - * portion of the payload. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param proto ipv6 protocol/next header (used for checksum of pseudo header) - * @param proto_len length of the ipv6 payload (used for checksum of pseudo header) - * @param chksum_len number of payload bytes used to compute chksum - * @param src source ipv6 address (used for checksum of pseudo header) - * @param dest destination ipv6 address (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest) -{ - u32_t acc = 0; - u32_t addr; - u8_t addr_part; - - for (addr_part = 0; addr_part < 4; addr_part++) { - addr = src->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - addr = dest->addr[addr_part]; - acc += (addr & 0xffffUL); - acc += ((addr >> 16) & 0xffffUL); - } - /* fold down to 16 bits */ - acc = FOLD_U32T(acc); - acc = FOLD_U32T(acc); - - return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); -} -#endif /* LWIP_IPV6 */ - -/* ip_chksum_pseudo_partial: - * - * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. - * - * @param p chain of pbufs over that a checksum should be calculated (ip data part) - * @param src source ip address (used for checksum of pseudo header) - * @param dst destination ip address (used for checksum of pseudo header) - * @param proto ip protocol (used for checksum of pseudo header) - * @param proto_len length of the ip data part (used for checksum of pseudo header) - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest) -{ -#if LWIP_IPV6 - if (IP_IS_V6(dest)) { - return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest)); - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_IPV4 - { - return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); - } -#endif /* LWIP_IPV4 */ -} - -/* inet_chksum: - * - * Calculates the Internet checksum over a portion of memory. Used primarily for IP - * and ICMP. - * - * @param dataptr start of the buffer to calculate the checksum (no alignment needed) - * @param len length of the buffer to calculate the checksum - * @return checksum (as u16_t) to be saved directly in the protocol header - */ - -u16_t -inet_chksum(const void *dataptr, u16_t len) -{ - return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len); -} - -/** - * Calculate a checksum over a chain of pbufs (without pseudo-header, much like - * inet_chksum only pbufs are used). - * - * @param p pbuf chain over that the checksum should be calculated - * @return checksum (as u16_t) to be saved directly in the protocol header - */ -u16_t -inet_chksum_pbuf(struct pbuf *p) -{ - u32_t acc; - struct pbuf *q; - u8_t swapped; - - acc = 0; - swapped = 0; - for (q = p; q != NULL; q = q->next) { - acc += LWIP_CHKSUM(q->payload, q->len); - acc = FOLD_U32T(acc); - if (q->len % 2 != 0) { - swapped = 1 - swapped; - acc = SWAP_BYTES_IN_WORD(acc); - } - } - - if (swapped) { - acc = SWAP_BYTES_IN_WORD(acc); - } - return (u16_t)~(acc & 0xffffUL); -} - -/* These are some implementations for LWIP_CHKSUM_COPY, which copies data - * like MEMCPY but generates a checksum at the same time. Since this is a - * performance-sensitive function, you might want to create your own version - * in assembly targeted at your hardware by defining it in lwipopts.h: - * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len) - */ - -#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */ -/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM. - * For architectures with big caches, data might still be in cache when - * generating the checksum after copying. - */ -u16_t -lwip_chksum_copy(void *dst, const void *src, u16_t len) -{ - MEMCPY(dst, src, len); - return LWIP_CHKSUM(dst, len); -} -#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */ diff --git a/components/net/lwip-2.0.2/src/core/init.c b/components/net/lwip-2.0.2/src/core/init.c deleted file mode 100644 index 313146133d..0000000000 --- a/components/net/lwip-2.0.2/src/core/init.c +++ /dev/null @@ -1,385 +0,0 @@ -/** - * @file - * Modules initialization - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -#include "lwip/opt.h" - -#include "lwip/init.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/sockets.h" -#include "lwip/ip.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/timeouts.h" -#include "lwip/etharp.h" -#include "lwip/ip6.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/api.h" - -#include "netif/ppp/ppp_opts.h" -#include "netif/ppp/ppp_impl.h" - -#ifndef LWIP_SKIP_PACKING_CHECK - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct packed_struct_test -{ - PACK_STRUCT_FLD_8(u8_t dummy1); - PACK_STRUCT_FIELD(u32_t dummy2); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5 - -#endif - -/* Compile-time sanity checks for configuration errors. - * These can be done independently of LWIP_DEBUG, without penalty. - */ -#ifndef BYTE_ORDER - #error "BYTE_ORDER is not defined, you have to define it in your cc.h" -#endif -#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV) - #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_UDPLITE) - #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_DHCP) - #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS) - #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_DNS) - #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */ -#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0)) - #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h" -#endif -#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0)) - #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0)) - #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) - #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1)) - #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS) - #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h" -#endif -#if (LWIP_IGMP && !LWIP_IPV4) - #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h" -#endif -#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4) - #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h" -#endif -#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0)) - #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h" -#endif -/* There must be sufficient timeouts, taking into account requirements of the subsystems. */ -#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0))) - #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts" -#endif -#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS)) - #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!" -#endif -#endif /* !MEMP_MEM_MALLOC */ -#if LWIP_WND_SCALE -#if (LWIP_TCP && (TCP_WND > 0xffffffff)) - #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h" -#endif -#if (LWIP_TCP && (TCP_RCV_SCALE > 14)) - #error "The maximum valid window scale value is 14!" -#endif -#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE))) - #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!" -#endif -#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0)) - #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!" -#endif -#else /* LWIP_WND_SCALE */ -#if (LWIP_TCP && (TCP_WND > 0xffff)) - #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)" -#endif -#endif /* LWIP_WND_SCALE */ -#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) - #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" -#endif -#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) - #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" -#endif -#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) - #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" -#endif -#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))) - #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" -#endif -#if (LWIP_NETIF_API && (NO_SYS==1)) - #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1)) - #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if (LWIP_PPP_API && (NO_SYS==1)) - #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h" -#endif -#if (LWIP_PPP_API && (PPP_SUPPORT==0)) - #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h" -#endif -#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP) - #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h" -#endif -#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK) - #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h" -#endif -#if (!LWIP_ARP && LWIP_AUTOIP) - #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h" -#endif -#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API))) - #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h" -#endif -#if (MEM_LIBC_MALLOC && MEM_USE_POOLS) - #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h" -#endif -#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS) - #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h" -#endif -#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT) - #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf" -#endif -#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT))) - #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST" -#endif -#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT - #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on" -#endif -#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT - #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on" -#endif -#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4 - #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on" -#endif -#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6 - #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on" -#endif -#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT) - #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT" -#endif -#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING - #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too" -#endif -#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE - #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets" -#endif -#if LWIP_NETCONN && LWIP_TCP -#if NETCONN_COPY != TCP_WRITE_FLAG_COPY - #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY" -#endif -#if NETCONN_MORE != TCP_WRITE_FLAG_MORE - #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE" -#endif -#endif /* LWIP_NETCONN && LWIP_TCP */ -#if LWIP_SOCKET -/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */ -#if SO_REUSEADDR != SOF_REUSEADDR - #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR" -#endif -#if SO_KEEPALIVE != SOF_KEEPALIVE - #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE" -#endif -#if SO_BROADCAST != SOF_BROADCAST - #error "WARNING: SO_BROADCAST != SOF_BROADCAST" -#endif -#endif /* LWIP_SOCKET */ - - -/* Compile-time checks for deprecated options. - */ -#ifdef MEMP_NUM_TCPIP_MSG - #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef TCP_REXMIT_DEBUG - #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef RAW_STATS - #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef ETHARP_QUEUE_FIRST - #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h." -#endif -#ifdef ETHARP_ALWAYS_INSERT - #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h." -#endif -#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED) - #error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)" -#endif - -#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS -#define LWIP_DISABLE_TCP_SANITY_CHECKS 0 -#endif -#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS -#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0 -#endif - -/* MEMP sanity checks */ -#if MEMP_MEM_MALLOC -#if !LWIP_DISABLE_MEMP_SANITY_CHECKS -#if LWIP_NETCONN || LWIP_SOCKET -#if !MEMP_NUM_NETCONN && LWIP_SOCKET -#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!" -#endif -#else /* MEMP_MEM_MALLOC */ -#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB) -#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error." -#endif -#endif /* LWIP_NETCONN || LWIP_SOCKET */ -#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */ -#if MEM_USE_POOLS -#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time" -#endif -#ifdef LWIP_HOOK_MEMP_AVAILABLE -#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC" -#endif -#endif /* MEMP_MEM_MALLOC */ - -/* TCP sanity checks */ -#if !LWIP_DISABLE_TCP_SANITY_CHECKS -#if LWIP_TCP -#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN) - #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SND_BUF < (2 * TCP_MSS) - #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)) - #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SNDLOWAT >= TCP_SND_BUF - #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS)) - #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!" -#endif -#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN - #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)))) - #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#if TCP_WND < TCP_MSS - #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error." -#endif -#endif /* LWIP_TCP */ -#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */ - -/** - * @ingroup lwip_nosys - * Initialize all modules. - * Use this in NO_SYS mode. Use tcpip_init() otherwise. - */ -void -lwip_init(void) -{ -#ifndef LWIP_SKIP_CONST_CHECK - int a; - LWIP_UNUSED_ARG(a); - LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a); -#endif -#ifndef LWIP_SKIP_PACKING_CHECK - LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE); -#endif - - /* Modules initialization */ - stats_init(); -#if !NO_SYS - sys_init(); -#endif /* !NO_SYS */ - mem_init(); - memp_init(); - pbuf_init(); - netif_init(); -#if LWIP_IPV4 - ip_init(); -#if LWIP_ARP - etharp_init(); -#endif /* LWIP_ARP */ -#endif /* LWIP_IPV4 */ -#if LWIP_RAW - raw_init(); -#endif /* LWIP_RAW */ -#if LWIP_UDP - udp_init(); -#endif /* LWIP_UDP */ -#if LWIP_TCP - tcp_init(); -#endif /* LWIP_TCP */ -#if LWIP_IGMP - igmp_init(); -#endif /* LWIP_IGMP */ -#if LWIP_DNS - dns_init(); -#endif /* LWIP_DNS */ -#if PPP_SUPPORT - ppp_init(); -#endif - -#if LWIP_TIMERS - sys_timeouts_init(); -#endif /* LWIP_TIMERS */ -} diff --git a/components/net/lwip-2.0.2/src/core/ip.c b/components/net/lwip-2.0.2/src/core/ip.c deleted file mode 100644 index 2e0240851f..0000000000 --- a/components/net/lwip-2.0.2/src/core/ip.c +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @file - * Common IPv4 and IPv6 code - * - * @defgroup ip IP - * @ingroup callbackstyle_api - * - * @defgroup ip4 IPv4 - * @ingroup ip - * - * @defgroup ip6 IPv6 - * @ingroup ip - * - * @defgroup ipaddr IP address handling - * @ingroup infrastructure - * - * @defgroup ip4addr IPv4 only - * @ingroup ipaddr - * - * @defgroup ip6addr IPv6 only - * @ingroup ipaddr - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 || LWIP_IPV6 - -#include "lwip/ip_addr.h" -#include "lwip/ip.h" - -/** Global data for both IPv4 and IPv6 */ -struct ip_globals ip_data; - -#if LWIP_IPV4 && LWIP_IPV6 - -const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT; - -/** - * @ingroup ipaddr - * Convert IP address string (both versions) to numeric. - * The version is auto-detected from the string. - * - * @param cp IP address string to convert - * @param addr conversion result is stored here - * @return 1 on success, 0 on error - */ -int -ipaddr_aton(const char *cp, ip_addr_t *addr) -{ - if (cp != NULL) { - const char* c; - for (c = cp; *c != 0; c++) { - if (*c == ':') { - /* contains a colon: IPv6 address */ - if (addr) { - IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); - } - return ip6addr_aton(cp, ip_2_ip6(addr)); - } else if (*c == '.') { - /* contains a dot: IPv4 address */ - break; - } - } - /* call ip4addr_aton as fallback or if IPv4 was found */ - if (addr) { - IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); - } - return ip4addr_aton(cp, ip_2_ip4(addr)); - } - return 0; -} - -/** - * @ingroup lwip_nosys - * If both IP versions are enabled, this function can dispatch packets to the correct one. - * Don't call directly, pass to netif_add() and call netif->input(). - */ -err_t -ip_input(struct pbuf *p, struct netif *inp) -{ - if (p != NULL) { - if (IP_HDR_GET_VERSION(p->payload) == 6) { - return ip6_input(p, inp); - } - return ip4_input(p, inp); - } - return ERR_VAL; -} - -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#endif /* LWIP_IPV4 || LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/autoip.c b/components/net/lwip-2.0.2/src/core/ipv4/autoip.c deleted file mode 100644 index 10db8a3444..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/autoip.c +++ /dev/null @@ -1,527 +0,0 @@ -/** - * @file - * AutoIP Automatic LinkLocal IP Configuration - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - * @defgroup autoip AUTOIP - * @ingroup ip4 - * AUTOIP related functions - * USAGE: - * - * define @ref LWIP_AUTOIP 1 in your lwipopts.h - * Options: - * AUTOIP_TMR_INTERVAL msecs, - * I recommend a value of 100. The value must divide 1000 with a remainder almost 0. - * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 .... - * - * Without DHCP: - * - Call autoip_start() after netif_add(). - * - * With DHCP: - * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h. - * - Configure your DHCP Client. - * - * @see netifapi_autoip - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dominik Spies - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mem.h" -/* #include "lwip/udp.h" */ -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/autoip.h" -#include "lwip/etharp.h" -#include "lwip/prot/autoip.h" - -#include - -/** Pseudo random macro based on netif informations. - * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */ -#ifndef LWIP_AUTOIP_RAND -#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \ - ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \ - ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \ - ((u32_t)((netif->hwaddr[4]) & 0xff))) + \ - (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0)) -#endif /* LWIP_AUTOIP_RAND */ - -/** - * Macro that generates the initial IP address to be tried by AUTOIP. - * If you want to override this, define it to something else in lwipopts.h. - */ -#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR -#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \ - lwip_htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \ - ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8))) -#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */ - -/* static functions */ -static err_t autoip_arp_announce(struct netif *netif); -static void autoip_start_probing(struct netif *netif); - -/** - * @ingroup autoip - * Set a statically allocated struct autoip to work with. - * Using this prevents autoip_start to allocate it using mem_malloc. - * - * @param netif the netif for which to set the struct autoip - * @param autoip (uninitialised) autoip struct allocated by the application - */ -void -autoip_set_struct(struct netif *netif, struct autoip *autoip) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("autoip != NULL", autoip != NULL); - LWIP_ASSERT("netif already has a struct autoip set", - netif_autoip_data(netif) == NULL); - - /* clear data structure */ - memset(autoip, 0, sizeof(struct autoip)); - /* autoip->state = AUTOIP_STATE_OFF; */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); -} - -/** Restart AutoIP client and check the next address (conflict detected) - * - * @param netif The netif under AutoIP control - */ -static void -autoip_restart(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - autoip->tried_llipaddr++; - autoip_start(netif); -} - -/** - * Handle a IP address conflict after an ARP conflict detection - */ -static void -autoip_handle_arp_conflict(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where - a) means retreat on the first conflict and - b) allows to keep an already configured address when having only one - conflict in 10 seconds - We use option b) since it helps to improve the chance that one of the two - conflicting hosts may be able to retain its address. */ - - if (autoip->lastconflict > 0) { - /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n")); - - /* Active TCP sessions are aborted when removing the ip addresss */ - autoip_restart(netif); - } else { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n")); - autoip_arp_announce(netif); - autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } -} - -/** - * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255 - * - * @param netif network interface on which create the IP-Address - * @param ipaddr ip address to initialize - */ -static void -autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr) -{ - struct autoip* autoip = netif_autoip_data(netif); - - /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 - * compliant to RFC 3927 Section 2.1 - * We have 254 * 256 possibilities */ - - u32_t addr = lwip_ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif)); - addr += autoip->tried_llipaddr; - addr = AUTOIP_NET | (addr & 0xffff); - /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */ - - if (addr < AUTOIP_RANGE_START) { - addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; - } - if (addr > AUTOIP_RANGE_END) { - addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1; - } - LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) && - (addr <= AUTOIP_RANGE_END)); - ip4_addr_set_u32(ipaddr, lwip_htonl(addr)); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), - ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); -} - -/** - * Sends an ARP probe from a network interface - * - * @param netif network interface used to send the probe - */ -static err_t -autoip_arp_probe(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - /* this works because netif->ip_addr is ANY */ - return etharp_request(netif, &autoip->llipaddr); -} - -/** - * Sends an ARP announce from a network interface - * - * @param netif network interface used to send the announce - */ -static err_t -autoip_arp_announce(struct netif *netif) -{ - return etharp_gratuitous(netif); -} - -/** - * Configure interface for use with current LL IP-Address - * - * @param netif network interface to configure with current LL IP-Address - */ -static err_t -autoip_bind(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - ip4_addr_t sn_mask, gw_addr; - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - - IP4_ADDR(&sn_mask, 255, 255, 0, 0); - IP4_ADDR(&gw_addr, 0, 0, 0, 0); - - netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr); - /* interface is used by routing now that an address is set */ - - return ERR_OK; -} - -/** - * @ingroup autoip - * Start AutoIP client - * - * @param netif network interface on which start the AutoIP client - */ -err_t -autoip_start(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - err_t result = ERR_OK; - - LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); - - /* Set IP-Address, Netmask and Gateway to 0 to make sure that - * ARP Packets are formed correctly - */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], - netif->name[1], (u16_t)netif->num)); - if (autoip == NULL) { - /* no AutoIP client attached yet? */ - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_start(): starting new AUTOIP client\n")); - autoip = (struct autoip *)mem_malloc(sizeof(struct autoip)); - if (autoip == NULL) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_start(): could not allocate autoip\n")); - return ERR_MEM; - } - memset(autoip, 0, sizeof(struct autoip)); - /* store this AutoIP client in the netif */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); - } else { - autoip->state = AUTOIP_STATE_OFF; - autoip->ttw = 0; - autoip->sent_num = 0; - ip4_addr_set_zero(&autoip->llipaddr); - autoip->lastconflict = 0; - } - - autoip_create_addr(netif, &(autoip->llipaddr)); - autoip_start_probing(netif); - - return result; -} - -static void -autoip_start_probing(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - autoip->state = AUTOIP_STATE_PROBING; - autoip->sent_num = 0; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - - /* time to wait to first probe, this is randomly - * chosen out of 0 to PROBE_WAIT seconds. - * compliant to RFC 3927 Section 2.2.1 - */ - autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND)); - - /* - * if we tried more then MAX_CONFLICTS we must limit our rate for - * acquiring and probing address - * compliant to RFC 3927 Section 2.2.1 - */ - if (autoip->tried_llipaddr > MAX_CONFLICTS) { - autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND; - } -} - -/** - * Handle a possible change in the network configuration. - * - * If there is an AutoIP address configured, take the interface down - * and begin probing with the same address. - */ -void -autoip_network_changed(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - if (autoip && (autoip->state != AUTOIP_STATE_OFF)) { - autoip_start_probing(netif); - } -} - -/** - * @ingroup autoip - * Stop AutoIP client - * - * @param netif network interface on which stop the AutoIP client - */ -err_t -autoip_stop(struct netif *netif) -{ - struct autoip* autoip = netif_autoip_data(netif); - - if (autoip != NULL) { - autoip->state = AUTOIP_STATE_OFF; - if (ip4_addr_islinklocal(netif_ip4_addr(netif))) { - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - } - } - return ERR_OK; -} - -/** - * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds - */ -void -autoip_tmr(void) -{ - struct netif *netif = netif_list; - /* loop through netif's */ - while (netif != NULL) { - struct autoip* autoip = netif_autoip_data(netif); - /* only act on AutoIP configured interfaces */ - if (autoip != NULL) { - if (autoip->lastconflict > 0) { - autoip->lastconflict--; - } - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, - ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n", - (u16_t)(autoip->state), autoip->ttw)); - - if (autoip->ttw > 0) { - autoip->ttw--; - } - - switch(autoip->state) { - case AUTOIP_STATE_PROBING: - if (autoip->ttw == 0) { - if (autoip->sent_num >= PROBE_NUM) { - /* Switch to ANNOUNCING: now we can bind to an IP address and use it */ - autoip->state = AUTOIP_STATE_ANNOUNCING; - autoip_bind(netif); - /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP - which counts as an announcement */ - autoip->sent_num = 1; - autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - } else { - autoip_arp_probe(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n")); - autoip->sent_num++; - if (autoip->sent_num == PROBE_NUM) { - /* calculate time to wait to for announce */ - autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND; - } else { - /* calculate time to wait to next probe */ - autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) % - ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) + - PROBE_MIN * AUTOIP_TICKS_PER_SECOND); - } - } - } - break; - - case AUTOIP_STATE_ANNOUNCING: - if (autoip->ttw == 0) { - autoip_arp_announce(netif); - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n")); - autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND; - autoip->sent_num++; - - if (autoip->sent_num >= ANNOUNCE_NUM) { - autoip->state = AUTOIP_STATE_BOUND; - autoip->sent_num = 0; - autoip->ttw = 0; - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr), - ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr))); - } - } - break; - - default: - /* nothing to do in other states */ - break; - } - } - /* proceed to next network interface */ - netif = netif->next; - } -} - -/** - * Handles every incoming ARP Packet, called by etharp_input(). - * - * @param netif network interface to use for autoip processing - * @param hdr Incoming ARP packet - */ -void -autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) -{ - struct autoip* autoip = netif_autoip_data(netif); - - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n")); - if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) { - /* when ip.src == llipaddr && hw.src != netif->hwaddr - * - * when probing ip.dst == llipaddr && hw.src != netif->hwaddr - * we have a conflict and must solve it - */ - ip4_addr_t sipaddr, dipaddr; - struct eth_addr netifaddr; - ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); - - /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). - */ - IPADDR2_COPY(&sipaddr, &hdr->sipaddr); - IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - - if (autoip->state == AUTOIP_STATE_PROBING) { - /* RFC 3927 Section 2.2.1: - * from beginning to after ANNOUNCE_WAIT - * seconds we have a conflict if - * ip.src == llipaddr OR - * ip.dst == llipaddr && hw.src != own hwaddr - */ - if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) || - (ip4_addr_isany_val(sipaddr) && - ip4_addr_cmp(&dipaddr, &autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Probe Conflict detected\n")); - autoip_restart(netif); - } - } else { - /* RFC 3927 Section 2.5: - * in any state we have a conflict if - * ip.src == llipaddr && hw.src != own hwaddr - */ - if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) && - !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) { - LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("autoip_arp_reply(): Conflicting ARP-Packet detected\n")); - autoip_handle_arp_conflict(netif); - } - } - } -} - -/** check if AutoIP supplied netif->ip_addr - * - * @param netif the netif to check - * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING), - * 0 otherwise - */ -u8_t -autoip_supplied_address(const struct netif *netif) -{ - if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) { - struct autoip* autoip = netif_autoip_data(netif); - return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING); - } - return 0; -} - -u8_t -autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr) -{ - struct autoip* autoip = netif_autoip_data(netif); - return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr)); -} - -#endif /* LWIP_IPV4 && LWIP_AUTOIP */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/dhcp.c b/components/net/lwip-2.0.2/src/core/ipv4/dhcp.c deleted file mode 100644 index dd35471026..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/dhcp.c +++ /dev/null @@ -1,1950 +0,0 @@ -/** - * @file - * Dynamic Host Configuration Protocol client - * - * @defgroup dhcp4 DHCPv4 - * @ingroup ip4 - * DHCP (IPv4) related functions - * This is a DHCP client for the lwIP TCP/IP stack. It aims to conform - * with RFC 2131 and RFC 2132. - * - * @todo: - * - Support for interfaces other than Ethernet (SLIP, PPP, ...) - * - * Options: - * @ref DHCP_COARSE_TIMER_SECS (recommended 60 which is a minute) - * @ref DHCP_FINE_TIMER_MSECS (recommended 500 which equals TCP coarse timer) - * - * dhcp_start() starts a DHCP client instance which - * configures the interface by obtaining an IP address lease and maintaining it. - * - * Use dhcp_release() to end the lease and use dhcp_stop() - * to remove the DHCP client. - * - * @see netifapi_dhcp4 - */ - -/* - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. - * - * Author: Leon Woestenberg - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/def.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/dns.h" -#include "lwip/etharp.h" -#include "lwip/prot/dhcp.h" - -#include - -/** DHCP_CREATE_RAND_XID: if this is set to 1, the xid is created using - * LWIP_RAND() (this overrides DHCP_GLOBAL_XID) - */ -#ifndef DHCP_CREATE_RAND_XID -#define DHCP_CREATE_RAND_XID 1 -#endif - -/** Default for DHCP_GLOBAL_XID is 0xABCD0000 - * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. - * \#define DHCP_GLOBAL_XID_HEADER "stdlib.h" - * \#define DHCP_GLOBAL_XID rand() - */ -#ifdef DHCP_GLOBAL_XID_HEADER -#include DHCP_GLOBAL_XID_HEADER /* include optional starting XID generation prototypes */ -#endif - -/** DHCP_OPTION_MAX_MSG_SIZE is set to the MTU - * MTU is checked to be big enough in dhcp_start */ -#define DHCP_MAX_MSG_LEN(netif) (netif->mtu) -#define DHCP_MAX_MSG_LEN_MIN_REQUIRED 576 -/** Minimum length for reply before packet is parsed */ -#define DHCP_MIN_REPLY_LEN 44 - -#define REBOOT_TRIES 2 - -#if LWIP_DNS && LWIP_DHCP_MAX_DNS_SERVERS -#if DNS_MAX_SERVERS > LWIP_DHCP_MAX_DNS_SERVERS -#define LWIP_DHCP_PROVIDE_DNS_SERVERS LWIP_DHCP_MAX_DNS_SERVERS -#else -#define LWIP_DHCP_PROVIDE_DNS_SERVERS DNS_MAX_SERVERS -#endif -#else -#define LWIP_DHCP_PROVIDE_DNS_SERVERS 0 -#endif - -/** Option handling: options are parsed in dhcp_parse_reply - * and saved in an array where other functions can load them from. - * This might be moved into the struct dhcp (not necessarily since - * lwIP is single-threaded and the array is only used while in recv - * callback). */ -enum dhcp_option_idx { - DHCP_OPTION_IDX_OVERLOAD = 0, - DHCP_OPTION_IDX_MSG_TYPE, - DHCP_OPTION_IDX_SERVER_ID, - DHCP_OPTION_IDX_LEASE_TIME, - DHCP_OPTION_IDX_T1, - DHCP_OPTION_IDX_T2, - DHCP_OPTION_IDX_SUBNET_MASK, - DHCP_OPTION_IDX_ROUTER, -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - DHCP_OPTION_IDX_DNS_SERVER, - DHCP_OPTION_IDX_DNS_SERVER_LAST = DHCP_OPTION_IDX_DNS_SERVER + LWIP_DHCP_PROVIDE_DNS_SERVERS - 1, -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -#if LWIP_DHCP_GET_NTP_SRV - DHCP_OPTION_IDX_NTP_SERVER, - DHCP_OPTION_IDX_NTP_SERVER_LAST = DHCP_OPTION_IDX_NTP_SERVER + LWIP_DHCP_MAX_NTP_SERVERS - 1, -#endif /* LWIP_DHCP_GET_NTP_SRV */ - DHCP_OPTION_IDX_MAX -}; - -/** Holds the decoded option values, only valid while in dhcp_recv. - @todo: move this into struct dhcp? */ -u32_t dhcp_rx_options_val[DHCP_OPTION_IDX_MAX]; -/** Holds a flag which option was received and is contained in dhcp_rx_options_val, - only valid while in dhcp_recv. - @todo: move this into struct dhcp? */ -u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; - -static u8_t dhcp_discover_request_options[] = { - DHCP_OPTION_SUBNET_MASK, - DHCP_OPTION_ROUTER, - DHCP_OPTION_BROADCAST -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - , DHCP_OPTION_DNS_SERVER -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -#if LWIP_DHCP_GET_NTP_SRV - , DHCP_OPTION_NTP -#endif /* LWIP_DHCP_GET_NTP_SRV */ - }; - -#ifdef DHCP_GLOBAL_XID -static u32_t xid; -static u8_t xid_initialised; -#endif /* DHCP_GLOBAL_XID */ - -#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) -#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) -#define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) -#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) -#define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) -#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) - -static struct udp_pcb *dhcp_pcb; -static u8_t dhcp_pcb_refcount; - -/* DHCP client state machine functions */ -static err_t dhcp_discover(struct netif *netif); -static err_t dhcp_select(struct netif *netif); -static void dhcp_bind(struct netif *netif); -#if DHCP_DOES_ARP_CHECK -static err_t dhcp_decline(struct netif *netif); -#endif /* DHCP_DOES_ARP_CHECK */ -static err_t dhcp_rebind(struct netif *netif); -static err_t dhcp_reboot(struct netif *netif); -static void dhcp_set_state(struct dhcp *dhcp, u8_t new_state); - -/* receive, unfold, parse and free incoming messages */ -static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); - -/* set the DHCP timers */ -static void dhcp_timeout(struct netif *netif); -static void dhcp_t1_timeout(struct netif *netif); -static void dhcp_t2_timeout(struct netif *netif); - -/* build outgoing messages */ -/* create a DHCP message, fill in common headers */ -static err_t dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type); -/* free a DHCP request */ -static void dhcp_delete_msg(struct dhcp *dhcp); -/* add a DHCP option (type, then length in bytes) */ -static void dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len); -/* add option values */ -static void dhcp_option_byte(struct dhcp *dhcp, u8_t value); -static void dhcp_option_short(struct dhcp *dhcp, u16_t value); -static void dhcp_option_long(struct dhcp *dhcp, u32_t value); -#if LWIP_NETIF_HOSTNAME -static void dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif); -#endif /* LWIP_NETIF_HOSTNAME */ -/* always add the DHCP options trailer to end and pad */ -static void dhcp_option_trailer(struct dhcp *dhcp); - -/** Ensure DHCP PCB is allocated and bound */ -static err_t -dhcp_inc_pcb_refcount(void) -{ - if (dhcp_pcb_refcount == 0) { - LWIP_ASSERT("dhcp_inc_pcb_refcount(): memory leak", dhcp_pcb == NULL); - - /* allocate UDP PCB */ - dhcp_pcb = udp_new(); - - if (dhcp_pcb == NULL) { - return ERR_MEM; - } - - ip_set_option(dhcp_pcb, SOF_BROADCAST); - - /* set up local and remote port for the pcb -> listen on all interfaces on all src/dest IPs */ - udp_bind(dhcp_pcb, IP4_ADDR_ANY, DHCP_CLIENT_PORT); - udp_connect(dhcp_pcb, IP4_ADDR_ANY, DHCP_SERVER_PORT); - udp_recv(dhcp_pcb, dhcp_recv, NULL); - } - - dhcp_pcb_refcount++; - - return ERR_OK; -} - -/** Free DHCP PCB if the last netif stops using it */ -static void -dhcp_dec_pcb_refcount(void) -{ - LWIP_ASSERT("dhcp_pcb_refcount(): refcount error", (dhcp_pcb_refcount > 0)); - dhcp_pcb_refcount--; - - if (dhcp_pcb_refcount == 0) { - udp_remove(dhcp_pcb); - dhcp_pcb = NULL; - } -} - -/** - * Back-off the DHCP client (because of a received NAK response). - * - * Back-off the DHCP client because of a received NAK. Receiving a - * NAK means the client asked for something non-sensible, for - * example when it tries to renew a lease obtained on another network. - * - * We clear any existing set IP address and restart DHCP negotiation - * afresh (as per RFC2131 3.2.3). - * - * @param netif the netif under DHCP control - */ -static void -dhcp_handle_nak(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_nak(netif=%p) %c%c%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* Change to a defined state - set this before assigning the address - to ensure the callback can use dhcp_supplied_address() */ - dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); - /* remove IP address from interface (must no longer be used, as per RFC2131) */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - /* We can immediately restart discovery */ - dhcp_discover(netif); -} - -#if DHCP_DOES_ARP_CHECK -/** - * Checks if the offered IP address is already in use. - * - * It does so by sending an ARP request for the offered address and - * entering CHECKING state. If no ARP reply is received within a small - * interval, the address is assumed to be free for use by us. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_check(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_check(netif=%p) %c%c\n", (void *)netif, (s16_t)netif->name[0], - (s16_t)netif->name[1])); - dhcp_set_state(dhcp, DHCP_STATE_CHECKING); - /* create an ARP query for the offered IP address, expecting that no host - responds, as the IP address should not be in use. */ - result = etharp_query(netif, &dhcp->offered_ip_addr, NULL); - if (result != ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_check: could not perform ARP query\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = 500; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_check(): set request timeout %"U16_F" msecs\n", msecs)); -} -#endif /* DHCP_DOES_ARP_CHECK */ - -/** - * Remember the configuration offered by a DHCP server. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_handle_offer(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_handle_offer(netif=%p) %c%c%"U16_F"\n", - (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - /* obtain the server address */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SERVER_ID)) { - ip_addr_set_ip4_u32(&dhcp->server_ip_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SERVER_ID))); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): server 0x%08"X32_F"\n", - ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); - /* remember offered address */ - ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_handle_offer(): offer for 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_select(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_handle_offer(netif=%p) did not get server ID!\n", (void*)netif)); - } -} - -/** - * Select a DHCP server offer out of all offers. - * - * Simply select the first offer received. - * - * @param netif the netif under DHCP control - * @return lwIP specific error (see error.h) - */ -static err_t -dhcp_select(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_select(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - dhcp_set_state(dhcp, DHCP_STATE_REQUESTING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - /* MUST request the offered IP address */ - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&dhcp->server_ip_addr)))); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - dhcp_option_trailer(dhcp); - /* shrink the pbuf to the actual content length */ - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* send broadcast to any DHCP server */ - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_select: REQUESTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("dhcp_select: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_select(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * The DHCP timer that checks for lease renewal/rebind timeouts. - * Must be called once a minute (see @ref DHCP_COARSE_TIMER_SECS). - */ -void -dhcp_coarse_tmr(void) -{ - struct netif *netif = netif_list; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_coarse_tmr()\n")); - /* iterate through all network interfaces */ - while (netif != NULL) { - /* only act on DHCP configured interfaces */ - struct dhcp *dhcp = netif_dhcp_data(netif); - if ((dhcp != NULL) && (dhcp->state != DHCP_STATE_OFF)) { - /* compare lease time to expire timeout */ - if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t0 timeout\n")); - /* this clients' lease time has expired */ - dhcp_release(netif); - dhcp_discover(netif); - /* timer is active (non zero), and triggers (zeroes) now? */ - } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t2 timeout\n")); - /* this clients' rebind timeout triggered */ - dhcp_t2_timeout(netif); - /* timer is active (non zero), and triggers (zeroes) now */ - } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_coarse_tmr(): t1 timeout\n")); - /* this clients' renewal timeout triggered */ - dhcp_t1_timeout(netif); - } - } - /* proceed to next netif */ - netif = netif->next; - } -} - -/** - * DHCP transaction timeout handling (this function must be called every 500ms, - * see @ref DHCP_FINE_TIMER_MSECS). - * - * A DHCP server is expected to respond within a short period of time. - * This timer checks whether an outstanding DHCP request is timed out. - */ -void -dhcp_fine_tmr(void) -{ - struct netif *netif = netif_list; - /* loop through netif's */ - while (netif != NULL) { - struct dhcp *dhcp = netif_dhcp_data(netif); - /* only act on DHCP configured interfaces */ - if (dhcp != NULL) { - /* timer is active (non zero), and is about to trigger now */ - if (dhcp->request_timeout > 1) { - dhcp->request_timeout--; - } - else if (dhcp->request_timeout == 1) { - dhcp->request_timeout--; - /* { netif->dhcp->request_timeout == 0 } */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_fine_tmr(): request timeout\n")); - /* this client's request timeout triggered */ - dhcp_timeout(netif); - } - } - /* proceed to next network interface */ - netif = netif->next; - } -} - -/** - * A DHCP negotiation transaction, or ARP request, has timed out. - * - * The timer that was started with the DHCP or ARP request has - * timed out, indicating no response was received in time. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout()\n")); - /* back-off period has passed, or server selection timed out */ - if ((dhcp->state == DHCP_STATE_BACKING_OFF) || (dhcp->state == DHCP_STATE_SELECTING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_timeout(): restarting discovery\n")); - dhcp_discover(netif); - /* receiving the requested lease timed out */ - } else if (dhcp->state == DHCP_STATE_REQUESTING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, DHCP request timed out\n")); - if (dhcp->tries <= 5) { - dhcp_select(netif); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): REQUESTING, releasing, restarting\n")); - dhcp_release(netif); - dhcp_discover(netif); - } -#if DHCP_DOES_ARP_CHECK - /* received no ARP reply for the offered address (which is good) */ - } else if (dhcp->state == DHCP_STATE_CHECKING) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_timeout(): CHECKING, ARP request timed out\n")); - if (dhcp->tries <= 1) { - dhcp_check(netif); - /* no ARP replies on the offered address, - looks like the IP address is indeed free */ - } else { - /* bind the interface to the offered address */ - dhcp_bind(netif); - } -#endif /* DHCP_DOES_ARP_CHECK */ - } else if (dhcp->state == DHCP_STATE_REBOOTING) { - if (dhcp->tries < REBOOT_TRIES) { - dhcp_reboot(netif); - } else { - dhcp_discover(netif); - } - } -} - -/** - * The renewal period has timed out. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_t1_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_t1_timeout()\n")); - if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || - (dhcp->state == DHCP_STATE_RENEWING)) { - /* just retry to renew - note that the rebind timer (t2) will - * eventually time-out if renew tries fail. */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("dhcp_t1_timeout(): must renew\n")); - /* This slightly different to RFC2131: DHCPREQUEST will be sent from state - DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ - dhcp_renew(netif); - /* Calculate next timeout */ - if (((dhcp->t2_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) - { - dhcp->t1_renew_time = ((dhcp->t2_timeout - dhcp->lease_used) / 2); - } - } -} - -/** - * The rebind period has timed out. - * - * @param netif the netif under DHCP control - */ -static void -dhcp_t2_timeout(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_t2_timeout()\n")); - if ((dhcp->state == DHCP_STATE_REQUESTING) || (dhcp->state == DHCP_STATE_BOUND) || - (dhcp->state == DHCP_STATE_RENEWING) || (dhcp->state == DHCP_STATE_REBINDING)) { - /* just retry to rebind */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - ("dhcp_t2_timeout(): must rebind\n")); - /* This slightly different to RFC2131: DHCPREQUEST will be sent from state - DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ - dhcp_rebind(netif); - /* Calculate next timeout */ - if (((dhcp->t0_timeout - dhcp->lease_used) / 2) >= ((60 + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS)) - { - dhcp->t2_rebind_time = ((dhcp->t0_timeout - dhcp->lease_used) / 2); - } - } -} - -/** - * Handle a DHCP ACK packet - * - * @param netif the netif under DHCP control - */ -static void -dhcp_handle_ack(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - -#if LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV - u8_t n; -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS || LWIP_DHCP_GET_NTP_SRV */ -#if LWIP_DHCP_GET_NTP_SRV - ip4_addr_t ntp_server_addrs[LWIP_DHCP_MAX_NTP_SERVERS]; -#endif - - /* clear options we might not get from the ACK */ - ip4_addr_set_zero(&dhcp->offered_sn_mask); - ip4_addr_set_zero(&dhcp->offered_gw_addr); -#if LWIP_DHCP_BOOTP_FILE - ip4_addr_set_zero(&dhcp->offered_si_addr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* lease time given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_LEASE_TIME)) { - /* remember offered lease time */ - dhcp->offered_t0_lease = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_LEASE_TIME); - } - /* renewal period given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T1)) { - /* remember given renewal period */ - dhcp->offered_t1_renew = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T1); - } else { - /* calculate safe periods for renewal */ - dhcp->offered_t1_renew = dhcp->offered_t0_lease / 2; - } - - /* renewal period given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_T2)) { - /* remember given rebind period */ - dhcp->offered_t2_rebind = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_T2); - } else { - /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ - dhcp->offered_t2_rebind = (dhcp->offered_t0_lease * 7U) / 8U; - } - - /* (y)our internet address */ - ip4_addr_copy(dhcp->offered_ip_addr, dhcp->msg_in->yiaddr); - -#if LWIP_DHCP_BOOTP_FILE - /* copy boot server address, - boot file name copied in dhcp_parse_reply if not overloaded */ - ip4_addr_copy(dhcp->offered_si_addr, dhcp->msg_in->siaddr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* subnet mask given? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_SUBNET_MASK)) { - /* remember given subnet mask */ - ip4_addr_set_u32(&dhcp->offered_sn_mask, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_SUBNET_MASK))); - dhcp->subnet_mask_given = 1; - } else { - dhcp->subnet_mask_given = 0; - } - - /* gateway router */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_ROUTER)) { - ip4_addr_set_u32(&dhcp->offered_gw_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_ROUTER))); - } - -#if LWIP_DHCP_GET_NTP_SRV - /* NTP servers */ - for (n = 0; (n < LWIP_DHCP_MAX_NTP_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n); n++) { - ip4_addr_set_u32(&ntp_server_addrs[n], lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_NTP_SERVER + n))); - } - dhcp_set_ntp_servers(n, ntp_server_addrs); -#endif /* LWIP_DHCP_GET_NTP_SRV */ - -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - /* DNS servers */ - for (n = 0; (n < LWIP_DHCP_PROVIDE_DNS_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) { - ip_addr_t dns_addr; - ip_addr_set_ip4_u32(&dns_addr, lwip_htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n))); - dns_setserver(n, &dns_addr); - } -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ -} - -/** - * @ingroup dhcp4 - * Set a statically allocated struct dhcp to work with. - * Using this prevents dhcp_start to allocate it using mem_malloc. - * - * @param netif the netif for which to set the struct dhcp - * @param dhcp (uninitialised) dhcp struct allocated by the application - */ -void -dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("dhcp != NULL", dhcp != NULL); - LWIP_ASSERT("netif already has a struct dhcp set", netif_dhcp_data(netif) == NULL); - - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); -} - -/** - * @ingroup dhcp4 - * Removes a struct dhcp from a netif. - * - * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the - * struct dhcp since the memory is passed back to the heap. - * - * @param netif the netif from which to remove the struct dhcp - */ -void dhcp_cleanup(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", netif != NULL); - - if (netif_dhcp_data(netif) != NULL) { - mem_free(netif_dhcp_data(netif)); - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL); - } -} - -/** - * @ingroup dhcp4 - * Start DHCP negotiation for a network interface. - * - * If no DHCP client instance was attached to this interface, - * a new client is created first. If a DHCP client instance - * was already present, it restarts negotiation. - * - * @param netif The lwIP network interface - * @return lwIP error code - * - ERR_OK - No error - * - ERR_MEM - Out of memory - */ -err_t -dhcp_start(struct netif *netif) -{ - struct dhcp *dhcp; - err_t result; - - LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); - LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;); - dhcp = netif_dhcp_data(netif); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - - /* check MTU of the netif */ - if (netif->mtu < DHCP_MAX_MSG_LEN_MIN_REQUIRED) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): Cannot use this netif with DHCP: MTU is too small\n")); - return ERR_MEM; - } - - /* no DHCP client attached yet? */ - if (dhcp == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n")); - dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp)); - if (dhcp == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n")); - return ERR_MEM; - } - - /* store this dhcp client in the netif */ - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): allocated dhcp")); - /* already has DHCP client attached */ - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(): restarting DHCP configuration\n")); - LWIP_ASSERT("pbuf p_out wasn't freed", dhcp->p_out == NULL); - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL ); - - if (dhcp->pcb_allocated != 0) { - dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ - } - /* dhcp is cleared below, no need to reset flag*/ - } - - /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); - /* dhcp_set_state(&dhcp, DHCP_STATE_OFF); */ - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting DHCP configuration\n")); - - if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ - return ERR_MEM; - } - dhcp->pcb_allocated = 1; - -#if LWIP_DHCP_CHECK_LINK_UP - if (!netif_is_link_up(netif)) { - /* set state INIT and wait for dhcp_network_changed() to call dhcp_discover() */ - dhcp_set_state(dhcp, DHCP_STATE_INIT); - return ERR_OK; - } -#endif /* LWIP_DHCP_CHECK_LINK_UP */ - - - /* (re)start the DHCP negotiation */ - result = dhcp_discover(netif); - if (result != ERR_OK) { - /* free resources allocated above */ - dhcp_stop(netif); - return ERR_MEM; - } - return result; -} - -/** - * @ingroup dhcp4 - * Inform a DHCP server of our manual configuration. - * - * This informs DHCP servers of our fixed IP address configuration - * by sending an INFORM message. It does not involve DHCP address - * configuration, it is just here to be nice to the network. - * - * @param netif The lwIP network interface - */ -void -dhcp_inform(struct netif *netif) -{ - struct dhcp dhcp; - err_t result = ERR_OK; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - if (dhcp_inc_pcb_refcount() != ERR_OK) { /* ensure DHCP PCB is allocated */ - return; - } - - memset(&dhcp, 0, sizeof(struct dhcp)); - dhcp_set_state(&dhcp, DHCP_STATE_INFORMING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, &dhcp, DHCP_INFORM); - if (result == ERR_OK) { - dhcp_option(&dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(&dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option_trailer(&dhcp); - - pbuf_realloc(dhcp.p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp.options_out_len); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_inform: INFORMING\n")); - - udp_sendto_if(dhcp_pcb, dhcp.p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - - dhcp_delete_msg(&dhcp); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_inform: could not allocate DHCP request\n")); - } - - dhcp_dec_pcb_refcount(); /* delete DHCP PCB if not needed any more */ -} - -/** Handle a possible change in the network configuration. - * - * This enters the REBOOTING state to verify that the currently bound - * address is still valid. - */ -void -dhcp_network_changed(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - - if (!dhcp) - return; - switch (dhcp->state) { - case DHCP_STATE_REBINDING: - case DHCP_STATE_RENEWING: - case DHCP_STATE_BOUND: - case DHCP_STATE_REBOOTING: - dhcp->tries = 0; - dhcp_reboot(netif); - break; - case DHCP_STATE_OFF: - /* stay off */ - break; - default: - /* INIT/REQUESTING/CHECKING/BACKING_OFF restart with new 'rid' because the - state changes, SELECTING: continue with current 'rid' as we stay in the - same state */ -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - /* ensure we start with short timeouts, even if already discovering */ - dhcp->tries = 0; - dhcp_discover(netif); - break; - } -} - -#if DHCP_DOES_ARP_CHECK -/** - * Match an ARP reply with the offered IP address: - * check whether the offered IP address is not in use using ARP - * - * @param netif the network interface on which the reply was received - * @param addr The IP address we received a reply from - */ -void -dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr) -{ - struct dhcp *dhcp; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - dhcp = netif_dhcp_data(netif); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_arp_reply()\n")); - /* is a DHCP client doing an ARP check? */ - if ((dhcp != NULL) && (dhcp->state == DHCP_STATE_CHECKING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_arp_reply(): CHECKING, arp reply for 0x%08"X32_F"\n", - ip4_addr_get_u32(addr))); - /* did a host respond with the address we - were offered by the DHCP server? */ - if (ip4_addr_cmp(addr, &dhcp->offered_ip_addr)) { - /* we will not accept the offered address */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING, - ("dhcp_arp_reply(): arp reply matched with offered address, declining\n")); - dhcp_decline(netif); - } - } -} - -/** - * Decline an offered lease. - * - * Tell the DHCP server we do not accept the offered address. - * One reason to decline the lease is when we find out the address - * is already in use by another host (through ARP). - * - * @param netif the netif under DHCP control - */ -static err_t -dhcp_decline(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result = ERR_OK; - u16_t msecs; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline()\n")); - dhcp_set_state(dhcp, DHCP_STATE_BACKING_OFF); - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_DECLINE); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option_trailer(dhcp); - /* resize pbuf to reflect true size of options */ - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* per section 4.4.4, broadcast DECLINE messages */ - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_decline: BACKING OFF\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_decline: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = 10*1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_decline(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} -#endif /* DHCP_DOES_ARP_CHECK */ - - -/** - * Start the DHCP process, discover a DHCP server. - * - * @param netif the netif under DHCP control - */ -static err_t -dhcp_discover(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result = ERR_OK; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover()\n")); - ip4_addr_set_any(&dhcp->offered_ip_addr); - dhcp_set_state(dhcp, DHCP_STATE_SELECTING); - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_DISCOVER); - if (result == ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: making request\n")); - - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - dhcp_option_trailer(dhcp); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: realloc()ing\n")); - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT)\n")); - udp_sendto_if_src(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif, IP4_ADDR_ANY); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_discover: deleting()ing\n")); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover: SELECTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_discover: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->tries >= LWIP_DHCP_AUTOIP_COOP_TRIES && dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_OFF) { - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_ON; - autoip_start(netif); - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - msecs = (dhcp->tries < 6 ? 1 << dhcp->tries : 60) * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_discover(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - - -/** - * Bind the interface to the offered IP address. - * - * @param netif network interface to bind to the offered address - */ -static void -dhcp_bind(struct netif *netif) -{ - u32_t timeout; - struct dhcp *dhcp; - ip4_addr_t sn_mask, gw_addr; - LWIP_ERROR("dhcp_bind: netif != NULL", (netif != NULL), return;); - dhcp = netif_dhcp_data(netif); - LWIP_ERROR("dhcp_bind: dhcp != NULL", (dhcp != NULL), return;); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); - - /* reset time used of lease */ - dhcp->lease_used = 0; - - if (dhcp->offered_t0_lease != 0xffffffffUL) { - /* set renewal period timer */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t0 renewal timer %"U32_F" secs\n", dhcp->offered_t0_lease)); - timeout = (dhcp->offered_t0_lease + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if (timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t0_timeout = (u16_t)timeout; - if (dhcp->t0_timeout == 0) { - dhcp->t0_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t0_lease*1000)); - } - - /* temporary DHCP lease? */ - if (dhcp->offered_t1_renew != 0xffffffffUL) { - /* set renewal period timer */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t1 renewal timer %"U32_F" secs\n", dhcp->offered_t1_renew)); - timeout = (dhcp->offered_t1_renew + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if (timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t1_timeout = (u16_t)timeout; - if (dhcp->t1_timeout == 0) { - dhcp->t1_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t1_renew*1000)); - dhcp->t1_renew_time = dhcp->t1_timeout; - } - /* set renewal period timer */ - if (dhcp->offered_t2_rebind != 0xffffffffUL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_bind(): t2 rebind timer %"U32_F" secs\n", dhcp->offered_t2_rebind)); - timeout = (dhcp->offered_t2_rebind + DHCP_COARSE_TIMER_SECS / 2) / DHCP_COARSE_TIMER_SECS; - if (timeout > 0xffff) { - timeout = 0xffff; - } - dhcp->t2_timeout = (u16_t)timeout; - if (dhcp->t2_timeout == 0) { - dhcp->t2_timeout = 1; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_bind(): set request timeout %"U32_F" msecs\n", dhcp->offered_t2_rebind*1000)); - dhcp->t2_rebind_time = dhcp->t2_timeout; - } - - /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ - if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { - dhcp->t1_timeout = 0; - } - - if (dhcp->subnet_mask_given) { - /* copy offered network mask */ - ip4_addr_copy(sn_mask, dhcp->offered_sn_mask); - } else { - /* subnet mask not given, choose a safe subnet mask given the network class */ - u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); - if (first_octet <= 127) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); - } else if (first_octet >= 192) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); - } else { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); - } - } - - ip4_addr_copy(gw_addr, dhcp->offered_gw_addr); - /* gateway address not given? */ - if (ip4_addr_isany_val(gw_addr)) { - /* copy network address */ - ip4_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); - /* use first host address on network as gateway */ - ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); - } - -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F" SN: 0x%08"X32_F" GW: 0x%08"X32_F"\n", - ip4_addr_get_u32(&dhcp->offered_ip_addr), ip4_addr_get_u32(&sn_mask), ip4_addr_get_u32(&gw_addr))); - /* netif is now bound to DHCP leased address - set this before assigning the address - to ensure the callback can use dhcp_supplied_address() */ - dhcp_set_state(dhcp, DHCP_STATE_BOUND); - - netif_set_addr(netif, &dhcp->offered_ip_addr, &sn_mask, &gw_addr); - /* interface is used by routing now that an address is set */ -} - -/** - * @ingroup dhcp4 - * Renew an existing DHCP lease at the involved DHCP server. - * - * @param netif network interface which must renew its lease - */ -err_t -dhcp_renew(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_renew()\n")); - dhcp_set_state(dhcp, DHCP_STATE_RENEWING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - /* append DHCP message trailer */ - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - udp_sendto_if(dhcp_pcb, dhcp->p_out, &dhcp->server_ip_addr, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew: RENEWING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_renew: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - /* back-off on retries, but to a maximum of 20 seconds */ - msecs = dhcp->tries < 10 ? dhcp->tries * 2000 : 20 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_renew(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * Rebind with a DHCP server for an existing DHCP lease. - * - * @param netif network interface which must rebind with a DHCP server - */ -static err_t -dhcp_rebind(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind()\n")); - dhcp_set_state(dhcp, DHCP_STATE_REBINDING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - -#if LWIP_NETIF_HOSTNAME - dhcp_option_hostname(dhcp, netif); -#endif /* LWIP_NETIF_HOSTNAME */ - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* broadcast to server */ - udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind: REBINDING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_rebind: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_rebind(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - -/** - * Enter REBOOTING state to verify an existing lease - * - * @param netif network interface which must reboot - */ -static err_t -dhcp_reboot(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - u16_t msecs; - u8_t i; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot()\n")); - dhcp_set_state(dhcp, DHCP_STATE_REBOOTING); - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_REQUEST); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); - dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN_MIN_REQUIRED); - - dhcp_option(dhcp, DHCP_OPTION_REQUESTED_IP, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(&dhcp->offered_ip_addr))); - - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, LWIP_ARRAYSIZE(dhcp_discover_request_options)); - for (i = 0; i < LWIP_ARRAYSIZE(dhcp_discover_request_options); i++) { - dhcp_option_byte(dhcp, dhcp_discover_request_options[i]); - } - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - /* broadcast to server */ - udp_sendto_if(dhcp_pcb, dhcp->p_out, IP_ADDR_BROADCAST, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot: REBOOTING\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_reboot: could not allocate DHCP request\n")); - } - if (dhcp->tries < 255) { - dhcp->tries++; - } - msecs = dhcp->tries < 10 ? dhcp->tries * 1000 : 10 * 1000; - dhcp->request_timeout = (msecs + DHCP_FINE_TIMER_MSECS - 1) / DHCP_FINE_TIMER_MSECS; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_reboot(): set request timeout %"U16_F" msecs\n", msecs)); - return result; -} - - -/** - * @ingroup dhcp4 - * Release a DHCP lease (usually called before @ref dhcp_stop). - * - * @param netif network interface which must release its lease - */ -err_t -dhcp_release(struct netif *netif) -{ - struct dhcp *dhcp = netif_dhcp_data(netif); - err_t result; - ip_addr_t server_ip_addr; - u8_t is_dhcp_supplied_address; - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_release()\n")); - if (dhcp == NULL) { - return ERR_ARG; - } - ip_addr_copy(server_ip_addr, dhcp->server_ip_addr); - - is_dhcp_supplied_address = dhcp_supplied_address(netif); - - /* idle DHCP client */ - dhcp_set_state(dhcp, DHCP_STATE_OFF); - /* clean old DHCP offer */ - ip_addr_set_zero_ip4(&dhcp->server_ip_addr); - ip4_addr_set_zero(&dhcp->offered_ip_addr); - ip4_addr_set_zero(&dhcp->offered_sn_mask); - ip4_addr_set_zero(&dhcp->offered_gw_addr); -#if LWIP_DHCP_BOOTP_FILE - ip4_addr_set_zero(&dhcp->offered_si_addr); -#endif /* LWIP_DHCP_BOOTP_FILE */ - dhcp->offered_t0_lease = dhcp->offered_t1_renew = dhcp->offered_t2_rebind = 0; - dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; - - if (!is_dhcp_supplied_address) { - /* don't issue release message when address is not dhcp-assigned */ - return ERR_OK; - } - - /* create and initialize the DHCP message header */ - result = dhcp_create_msg(netif, dhcp, DHCP_RELEASE); - if (result == ERR_OK) { - dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); - dhcp_option_long(dhcp, lwip_ntohl(ip4_addr_get_u32(ip_2_ip4(&server_ip_addr)))); - - dhcp_option_trailer(dhcp); - - pbuf_realloc(dhcp->p_out, sizeof(struct dhcp_msg) - DHCP_OPTIONS_LEN + dhcp->options_out_len); - - udp_sendto_if(dhcp_pcb, dhcp->p_out, &server_ip_addr, DHCP_SERVER_PORT, netif); - dhcp_delete_msg(dhcp); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_release: RELEASED, DHCP_STATE_OFF\n")); - } else { - /* sending release failed, but that's not a problem since the correct behaviour of dhcp does not rely on release */ - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("dhcp_release: could not allocate DHCP request\n")); - } - /* remove IP address from interface (prevents routing from selecting this interface) */ - netif_set_addr(netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - - return result; -} - -/** - * @ingroup dhcp4 - * Remove the DHCP client from the interface. - * - * @param netif The network interface to stop DHCP on - */ -void -dhcp_stop(struct netif *netif) -{ - struct dhcp *dhcp; - LWIP_ERROR("dhcp_stop: netif != NULL", (netif != NULL), return;); - dhcp = netif_dhcp_data(netif); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); - /* netif is DHCP configured? */ - if (dhcp != NULL) { -#if LWIP_DHCP_AUTOIP_COOP - if (dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { - autoip_stop(netif); - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; - } -#endif /* LWIP_DHCP_AUTOIP_COOP */ - - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); - dhcp_set_state(dhcp, DHCP_STATE_OFF); - - if (dhcp->pcb_allocated != 0) { - dhcp_dec_pcb_refcount(); /* free DHCP PCB if not needed any more */ - dhcp->pcb_allocated = 0; - } - } -} - -/* - * Set the DHCP state of a DHCP client. - * - * If the state changed, reset the number of tries. - */ -static void -dhcp_set_state(struct dhcp *dhcp, u8_t new_state) -{ - if (new_state != dhcp->state) { - dhcp->state = new_state; - dhcp->tries = 0; - dhcp->request_timeout = 0; - } -} - -/* - * Concatenate an option type and length field to the outgoing - * DHCP message. - * - */ -static void -dhcp_option(struct dhcp *dhcp, u8_t option_type, u8_t option_len) -{ - LWIP_ASSERT("dhcp_option: dhcp->options_out_len + 2 + option_len <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U + option_len <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = option_type; - dhcp->msg_out->options[dhcp->options_out_len++] = option_len; -} -/* - * Concatenate a single byte to the outgoing DHCP message. - * - */ -static void -dhcp_option_byte(struct dhcp *dhcp, u8_t value) -{ - LWIP_ASSERT("dhcp_option_byte: dhcp->options_out_len < DHCP_OPTIONS_LEN", dhcp->options_out_len < DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = value; -} - -static void -dhcp_option_short(struct dhcp *dhcp, u16_t value) -{ - LWIP_ASSERT("dhcp_option_short: dhcp->options_out_len + 2 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 2U <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff00U) >> 8); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t) (value & 0x00ffU); -} - -static void -dhcp_option_long(struct dhcp *dhcp, u32_t value) -{ - LWIP_ASSERT("dhcp_option_long: dhcp->options_out_len + 4 <= DHCP_OPTIONS_LEN", dhcp->options_out_len + 4U <= DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0xff000000UL) >> 24); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x00ff0000UL) >> 16); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x0000ff00UL) >> 8); - dhcp->msg_out->options[dhcp->options_out_len++] = (u8_t)((value & 0x000000ffUL)); -} - -#if LWIP_NETIF_HOSTNAME -static void -dhcp_option_hostname(struct dhcp *dhcp, struct netif *netif) -{ - if (netif->hostname != NULL) { - size_t namelen = strlen(netif->hostname); - if (namelen > 0) { - size_t len; - const char *p = netif->hostname; - /* Shrink len to available bytes (need 2 bytes for OPTION_HOSTNAME - and 1 byte for trailer) */ - size_t available = DHCP_OPTIONS_LEN - dhcp->options_out_len - 3; - LWIP_ASSERT("DHCP: hostname is too long!", namelen <= available); - len = LWIP_MIN(namelen, available); - LWIP_ASSERT("DHCP: hostname is too long!", len <= 0xFF); - dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, (u8_t)len); - while (len--) { - dhcp_option_byte(dhcp, *p++); - } - } - } -} -#endif /* LWIP_NETIF_HOSTNAME */ - -/** - * Extract the DHCP message and the DHCP options. - * - * Extract the DHCP message and the DHCP options, each into a contiguous - * piece of memory. As a DHCP message is variable sized by its options, - * and also allows overriding some fields for options, the easy approach - * is to first unfold the options into a contiguous piece of memory, and - * use that further on. - * - */ -static err_t -dhcp_parse_reply(struct dhcp *dhcp, struct pbuf *p) -{ - u8_t *options; - u16_t offset; - u16_t offset_max; - u16_t options_idx; - u16_t options_idx_max; - struct pbuf *q; - int parse_file_as_options = 0; - int parse_sname_as_options = 0; - - /* clear received options */ - dhcp_clear_all_options(dhcp); - /* check that beginning of dhcp_msg (up to and including chaddr) is in first pbuf */ - if (p->len < DHCP_SNAME_OFS) { - return ERR_BUF; - } - dhcp->msg_in = (struct dhcp_msg *)p->payload; -#if LWIP_DHCP_BOOTP_FILE - /* clear boot file name */ - dhcp->boot_file_name[0] = 0; -#endif /* LWIP_DHCP_BOOTP_FILE */ - - /* parse options */ - - /* start with options field */ - options_idx = DHCP_OPTIONS_OFS; - /* parse options to the end of the received packet */ - options_idx_max = p->tot_len; -again: - q = p; - while ((q != NULL) && (options_idx >= q->len)) { - options_idx -= q->len; - options_idx_max -= q->len; - q = q->next; - } - if (q == NULL) { - return ERR_BUF; - } - offset = options_idx; - offset_max = options_idx_max; - options = (u8_t*)q->payload; - /* at least 1 byte to read and no end marker, then at least 3 bytes to read? */ - while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) { - u8_t op = options[offset]; - u8_t len; - u8_t decode_len = 0; - int decode_idx = -1; - u16_t val_offset = offset + 2; - /* len byte might be in the next pbuf */ - if ((offset + 1) < q->len) { - len = options[offset + 1]; - } else { - len = (q->next != NULL ? ((u8_t*)q->next->payload)[0] : 0); - } - /* LWIP_DEBUGF(DHCP_DEBUG, ("msg_offset=%"U16_F", q->len=%"U16_F, msg_offset, q->len)); */ - decode_len = len; - switch(op) { - /* case(DHCP_OPTION_END): handled above */ - case(DHCP_OPTION_PAD): - /* special option: no len encoded */ - decode_len = len = 0; - /* will be increased below */ - offset--; - break; - case(DHCP_OPTION_SUBNET_MASK): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_SUBNET_MASK; - break; - case(DHCP_OPTION_ROUTER): - decode_len = 4; /* only copy the first given router */ - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_ROUTER; - break; -#if LWIP_DHCP_PROVIDE_DNS_SERVERS - case(DHCP_OPTION_DNS_SERVER): - /* special case: there might be more than one server */ - LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); - /* limit number of DNS servers */ - decode_len = LWIP_MIN(len, 4 * DNS_MAX_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_DNS_SERVER; - break; -#endif /* LWIP_DHCP_PROVIDE_DNS_SERVERS */ - case(DHCP_OPTION_LEASE_TIME): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_LEASE_TIME; - break; -#if LWIP_DHCP_GET_NTP_SRV - case(DHCP_OPTION_NTP): - /* special case: there might be more than one server */ - LWIP_ERROR("len %% 4 == 0", len % 4 == 0, return ERR_VAL;); - /* limit number of NTP servers */ - decode_len = LWIP_MIN(len, 4 * LWIP_DHCP_MAX_NTP_SERVERS); - LWIP_ERROR("len >= decode_len", len >= decode_len, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_NTP_SERVER; - break; -#endif /* LWIP_DHCP_GET_NTP_SRV*/ - case(DHCP_OPTION_OVERLOAD): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); - /* decode overload only in options, not in file/sname: invalid packet */ - LWIP_ERROR("overload in file/sname", options_idx == DHCP_OPTIONS_OFS, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_OVERLOAD; - break; - case(DHCP_OPTION_MESSAGE_TYPE): - LWIP_ERROR("len == 1", len == 1, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_MSG_TYPE; - break; - case(DHCP_OPTION_SERVER_ID): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_SERVER_ID; - break; - case(DHCP_OPTION_T1): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_T1; - break; - case(DHCP_OPTION_T2): - LWIP_ERROR("len == 4", len == 4, return ERR_VAL;); - decode_idx = DHCP_OPTION_IDX_T2; - break; - default: - decode_len = 0; - LWIP_DEBUGF(DHCP_DEBUG, ("skipping option %"U16_F" in options\n", (u16_t)op)); - break; - } - offset += len + 2; - if (decode_len > 0) { - u32_t value = 0; - u16_t copy_len; -decode_next: - LWIP_ASSERT("check decode_idx", decode_idx >= 0 && decode_idx < DHCP_OPTION_IDX_MAX); - if (!dhcp_option_given(dhcp, decode_idx)) { - copy_len = LWIP_MIN(decode_len, 4); - if (pbuf_copy_partial(q, &value, copy_len, val_offset) != copy_len) { - return ERR_BUF; - } - if (decode_len > 4) { - /* decode more than one u32_t */ - LWIP_ERROR("decode_len %% 4 == 0", decode_len % 4 == 0, return ERR_VAL;); - dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, lwip_htonl(value)); - decode_len -= 4; - val_offset += 4; - decode_idx++; - goto decode_next; - } else if (decode_len == 4) { - value = lwip_ntohl(value); - } else { - LWIP_ERROR("invalid decode_len", decode_len == 1, return ERR_VAL;); - value = ((u8_t*)&value)[0]; - } - dhcp_got_option(dhcp, decode_idx); - dhcp_set_option_value(dhcp, decode_idx, value); - } - } - if (offset >= q->len) { - offset -= q->len; - offset_max -= q->len; - if ((offset < offset_max) && offset_max) { - q = q->next; - LWIP_ASSERT("next pbuf was null", q); - options = (u8_t*)q->payload; - } else { - /* We've run out of bytes, probably no end marker. Don't proceed. */ - break; - } - } - } - /* is this an overloaded message? */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_OVERLOAD)) { - u32_t overload = dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_OVERLOAD); - dhcp_clear_option(dhcp, DHCP_OPTION_IDX_OVERLOAD); - if (overload == DHCP_OVERLOAD_FILE) { - parse_file_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded file field\n")); - } else if (overload == DHCP_OVERLOAD_SNAME) { - parse_sname_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname field\n")); - } else if (overload == DHCP_OVERLOAD_SNAME_FILE) { - parse_sname_as_options = 1; - parse_file_as_options = 1; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("overloaded sname and file field\n")); - } else { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("invalid overload option: %d\n", (int)overload)); - } -#if LWIP_DHCP_BOOTP_FILE - if (!parse_file_as_options) { - /* only do this for ACK messages */ - if (dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE) && - (dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE) == DHCP_ACK)) - /* copy bootp file name, don't care for sname (server hostname) */ - if (pbuf_copy_partial(p, dhcp->boot_file_name, DHCP_FILE_LEN-1, DHCP_FILE_OFS) != (DHCP_FILE_LEN-1)) { - return ERR_BUF; - } - /* make sure the string is really NULL-terminated */ - dhcp->boot_file_name[DHCP_FILE_LEN-1] = 0; - } -#endif /* LWIP_DHCP_BOOTP_FILE */ - } - if (parse_file_as_options) { - /* if both are overloaded, parse file first and then sname (RFC 2131 ch. 4.1) */ - parse_file_as_options = 0; - options_idx = DHCP_FILE_OFS; - options_idx_max = DHCP_FILE_OFS + DHCP_FILE_LEN; - goto again; - } else if (parse_sname_as_options) { - parse_sname_as_options = 0; - options_idx = DHCP_SNAME_OFS; - options_idx_max = DHCP_SNAME_OFS + DHCP_SNAME_LEN; - goto again; - } - return ERR_OK; -} - -/** - * If an incoming DHCP message is in response to us, then trigger the state machine - */ -static void -dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - struct netif *netif = ip_current_input_netif(); - struct dhcp *dhcp = netif_dhcp_data(netif); - struct dhcp_msg *reply_msg = (struct dhcp_msg *)p->payload; - u8_t msg_type; - u8_t i; - - LWIP_UNUSED_ARG(arg); - - /* Caught DHCP message from netif that does not have DHCP enabled? -> not interested */ - if ((dhcp == NULL) || (dhcp->pcb_allocated == 0)) { - goto free_pbuf_and_return; - } - - LWIP_ASSERT("invalid server address type", IP_IS_V4(addr)); - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_recv(pbuf = %p) from DHCP server %"U16_F".%"U16_F".%"U16_F".%"U16_F" port %"U16_F"\n", (void*)p, - ip4_addr1_16(ip_2_ip4(addr)), ip4_addr2_16(ip_2_ip4(addr)), ip4_addr3_16(ip_2_ip4(addr)), ip4_addr4_16(ip_2_ip4(addr)), port)); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->len = %"U16_F"\n", p->len)); - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("pbuf->tot_len = %"U16_F"\n", p->tot_len)); - /* prevent warnings about unused arguments */ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); - - LWIP_ASSERT("reply wasn't freed", dhcp->msg_in == NULL); - - if (p->len < DHCP_MIN_REPLY_LEN) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n")); - goto free_pbuf_and_return; - } - - if (reply_msg->op != DHCP_BOOTREPLY) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op)); - goto free_pbuf_and_return; - } - /* iterate through hardware address and match against DHCP message */ - for (i = 0; i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN && i < DHCP_CHADDR_LEN; i++) { - if (netif->hwaddr[i] != reply_msg->chaddr[i]) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n", - (u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i])); - goto free_pbuf_and_return; - } - } - /* match transaction ID against what we expected */ - if (lwip_ntohl(reply_msg->xid) != dhcp->xid) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",lwip_ntohl(reply_msg->xid),dhcp->xid)); - goto free_pbuf_and_return; - } - /* option fields could be unfold? */ - if (dhcp_parse_reply(dhcp, p) != ERR_OK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("problem unfolding DHCP message - too short on memory?\n")); - goto free_pbuf_and_return; - } - - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n")); - /* obtain pointer to DHCP message type */ - if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n")); - goto free_pbuf_and_return; - } - - /* read DHCP message type */ - msg_type = (u8_t)dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_MSG_TYPE); - /* message type is DHCP ACK? */ - if (msg_type == DHCP_ACK) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_ACK received\n")); - /* in requesting state? */ - if (dhcp->state == DHCP_STATE_REQUESTING) { - dhcp_handle_ack(netif); -#if DHCP_DOES_ARP_CHECK - if ((netif->flags & NETIF_FLAG_ETHARP) != 0) { - /* check if the acknowledged lease address is already in use */ - dhcp_check(netif); - } else { - /* bind interface to the acknowledged lease address */ - dhcp_bind(netif); - } -#else - /* bind interface to the acknowledged lease address */ - dhcp_bind(netif); -#endif - } - /* already bound to the given lease address? */ - else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || - (dhcp->state == DHCP_STATE_RENEWING)) { - dhcp_handle_ack(netif); - dhcp_bind(netif); - } - } - /* received a DHCP_NAK in appropriate state? */ - else if ((msg_type == DHCP_NAK) && - ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REQUESTING) || - (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING ))) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_NAK received\n")); - dhcp_handle_nak(netif); - } - /* received a DHCP_OFFER in DHCP_STATE_SELECTING state? */ - else if ((msg_type == DHCP_OFFER) && (dhcp->state == DHCP_STATE_SELECTING)) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("DHCP_OFFER received in DHCP_STATE_SELECTING state\n")); - dhcp->request_timeout = 0; - /* remember offered lease */ - dhcp_handle_offer(netif); - } - -free_pbuf_and_return: - if (dhcp != NULL) { - dhcp->msg_in = NULL; - } - pbuf_free(p); -} - -/** - * Create a DHCP request, fill in common headers - * - * @param netif the netif under DHCP control - * @param dhcp dhcp control struct - * @param message_type message type of the request - */ -static err_t -dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type) -{ - u16_t i; -#ifndef DHCP_GLOBAL_XID - /** default global transaction identifier starting value (easy to match - * with a packet analyser). We simply increment for each new request. - * Predefine DHCP_GLOBAL_XID to a better value or a function call to generate one - * at runtime, any supporting function prototypes can be defined in DHCP_GLOBAL_XID_HEADER */ -#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - static u32_t xid; -#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - static u32_t xid = 0xABCD0000; -#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ -#else - if (!xid_initialised) { - xid = DHCP_GLOBAL_XID; - xid_initialised = !xid_initialised; - } -#endif - LWIP_ERROR("dhcp_create_msg: netif != NULL", (netif != NULL), return ERR_ARG;); - LWIP_ERROR("dhcp_create_msg: dhcp != NULL", (dhcp != NULL), return ERR_VAL;); - LWIP_ASSERT("dhcp_create_msg: dhcp->p_out == NULL", dhcp->p_out == NULL); - LWIP_ASSERT("dhcp_create_msg: dhcp->msg_out == NULL", dhcp->msg_out == NULL); - dhcp->p_out = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcp_msg), PBUF_RAM); - if (dhcp->p_out == NULL) { - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("dhcp_create_msg(): could not allocate pbuf\n")); - return ERR_MEM; - } - LWIP_ASSERT("dhcp_create_msg: check that first pbuf can hold struct dhcp_msg", - (dhcp->p_out->len >= sizeof(struct dhcp_msg))); - - /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ - if (message_type != DHCP_REQUEST) { - /* reuse transaction identifier in retransmissions */ - if (dhcp->tries == 0) { -#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND) - xid = LWIP_RAND(); -#else /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - xid++; -#endif /* DHCP_CREATE_RAND_XID && defined(LWIP_RAND) */ - } - dhcp->xid = xid; - } - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, - ("transaction id xid(%"X32_F")\n", xid)); - - dhcp->msg_out = (struct dhcp_msg *)dhcp->p_out->payload; - - dhcp->msg_out->op = DHCP_BOOTREQUEST; - /* @todo: make link layer independent */ - dhcp->msg_out->htype = DHCP_HTYPE_ETH; - dhcp->msg_out->hlen = netif->hwaddr_len; - dhcp->msg_out->hops = 0; - dhcp->msg_out->xid = lwip_htonl(dhcp->xid); - dhcp->msg_out->secs = 0; - /* we don't need the broadcast flag since we can receive unicast traffic - before being fully configured! */ - dhcp->msg_out->flags = 0; - ip4_addr_set_zero(&dhcp->msg_out->ciaddr); - /* set ciaddr to netif->ip_addr based on message_type and state */ - if ((message_type == DHCP_INFORM) || (message_type == DHCP_DECLINE) || (message_type == DHCP_RELEASE) || - ((message_type == DHCP_REQUEST) && /* DHCP_STATE_BOUND not used for sending! */ - ((dhcp->state== DHCP_STATE_RENEWING) || dhcp->state== DHCP_STATE_REBINDING))) { - ip4_addr_copy(dhcp->msg_out->ciaddr, *netif_ip4_addr(netif)); - } - ip4_addr_set_zero(&dhcp->msg_out->yiaddr); - ip4_addr_set_zero(&dhcp->msg_out->siaddr); - ip4_addr_set_zero(&dhcp->msg_out->giaddr); - for (i = 0; i < DHCP_CHADDR_LEN; i++) { - /* copy netif hardware address, pad with zeroes */ - dhcp->msg_out->chaddr[i] = (i < netif->hwaddr_len && i < NETIF_MAX_HWADDR_LEN) ? netif->hwaddr[i] : 0/* pad byte*/; - } - for (i = 0; i < DHCP_SNAME_LEN; i++) { - dhcp->msg_out->sname[i] = 0; - } - for (i = 0; i < DHCP_FILE_LEN; i++) { - dhcp->msg_out->file[i] = 0; - } - dhcp->msg_out->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); - dhcp->options_out_len = 0; - /* fill options field with an incrementing array (for debugging purposes) */ - for (i = 0; i < DHCP_OPTIONS_LEN; i++) { - dhcp->msg_out->options[i] = (u8_t)i; /* for debugging only, no matter if truncated */ - } - /* Add option MESSAGE_TYPE */ - dhcp_option(dhcp, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN); - dhcp_option_byte(dhcp, message_type); - return ERR_OK; -} - -/** - * Free previously allocated memory used to send a DHCP request. - * - * @param dhcp the dhcp struct to free the request from - */ -static void -dhcp_delete_msg(struct dhcp *dhcp) -{ - LWIP_ERROR("dhcp_delete_msg: dhcp != NULL", (dhcp != NULL), return;); - LWIP_ASSERT("dhcp_delete_msg: dhcp->p_out != NULL", dhcp->p_out != NULL); - LWIP_ASSERT("dhcp_delete_msg: dhcp->msg_out != NULL", dhcp->msg_out != NULL); - if (dhcp->p_out != NULL) { - pbuf_free(dhcp->p_out); - } - dhcp->p_out = NULL; - dhcp->msg_out = NULL; -} - -/** - * Add a DHCP message trailer - * - * Adds the END option to the DHCP message, and if - * necessary, up to three padding bytes. - * - * @param dhcp DHCP state structure - */ -static void -dhcp_option_trailer(struct dhcp *dhcp) -{ - LWIP_ERROR("dhcp_option_trailer: dhcp != NULL", (dhcp != NULL), return;); - LWIP_ASSERT("dhcp_option_trailer: dhcp->msg_out != NULL\n", dhcp->msg_out != NULL); - LWIP_ASSERT("dhcp_option_trailer: dhcp->options_out_len < DHCP_OPTIONS_LEN\n", dhcp->options_out_len < DHCP_OPTIONS_LEN); - dhcp->msg_out->options[dhcp->options_out_len++] = DHCP_OPTION_END; - /* packet is too small, or not 4 byte aligned? */ - while (((dhcp->options_out_len < DHCP_MIN_OPTIONS_LEN) || (dhcp->options_out_len & 3)) && - (dhcp->options_out_len < DHCP_OPTIONS_LEN)) { - /* add a fill/padding byte */ - dhcp->msg_out->options[dhcp->options_out_len++] = 0; - } -} - -/** check if DHCP supplied netif->ip_addr - * - * @param netif the netif to check - * @return 1 if DHCP supplied netif->ip_addr (states BOUND or RENEWING), - * 0 otherwise - */ -u8_t -dhcp_supplied_address(const struct netif *netif) -{ - if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) { - struct dhcp* dhcp = netif_dhcp_data(netif); - return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING); - } - return 0; -} - -#endif /* LWIP_IPV4 && LWIP_DHCP */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/etharp.c b/components/net/lwip-2.0.2/src/core/ipv4/etharp.c deleted file mode 100644 index 3f48a9975f..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/etharp.c +++ /dev/null @@ -1,1206 +0,0 @@ -/** - * @file - * Address Resolution Protocol module for IP over Ethernet - * - * Functionally, ARP is divided into two parts. The first maps an IP address - * to a physical address when sending a packet, and the second part answers - * requests from other machines for our physical address. - * - * This implementation complies with RFC 826 (Ethernet ARP). It supports - * Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6 - * if an interface calls etharp_gratuitous(our_netif) upon address change. - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET - -#include "lwip/etharp.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "netif/ethernet.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ - -/** Re-request a used ARP entry 1 minute before it would expire to prevent - * breaking a steadily used connection because the ARP entry timed out. */ -#define ARP_AGE_REREQUEST_USED_UNICAST (ARP_MAXAGE - 30) -#define ARP_AGE_REREQUEST_USED_BROADCAST (ARP_MAXAGE - 15) - -/** the time an ARP entry stays pending after first request, - * for ARP_TMR_INTERVAL = 1000, this is - * 10 seconds. - * - * @internal Keep this number at least 2, otherwise it might - * run out instantly if the timeout occurs directly after a request. - */ -#define ARP_MAXPENDING 5 - -/** ARP states */ -enum etharp_state { - ETHARP_STATE_EMPTY = 0, - ETHARP_STATE_PENDING, - ETHARP_STATE_STABLE, - ETHARP_STATE_STABLE_REREQUESTING_1, - ETHARP_STATE_STABLE_REREQUESTING_2 -#if ETHARP_SUPPORT_STATIC_ENTRIES - ,ETHARP_STATE_STATIC -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ -}; - -struct etharp_entry { -#if ARP_QUEUEING - /** Pointer to queue of pending outgoing packets on this ARP entry. */ - struct etharp_q_entry *q; -#else /* ARP_QUEUEING */ - /** Pointer to a single pending outgoing packet on this ARP entry. */ - struct pbuf *q; -#endif /* ARP_QUEUEING */ - ip4_addr_t ipaddr; - struct netif *netif; - struct eth_addr ethaddr; - u16_t ctime; - u8_t state; -}; - -static struct etharp_entry arp_table[ARP_TABLE_SIZE]; - -#if !LWIP_NETIF_HWADDRHINT -static u8_t etharp_cached_entry; -#endif /* !LWIP_NETIF_HWADDRHINT */ - -/** Try hard to create a new entry - we want the IP address to appear in - the cache (even if this means removing an active entry or so). */ -#define ETHARP_FLAG_TRY_HARD 1 -#define ETHARP_FLAG_FIND_ONLY 2 -#if ETHARP_SUPPORT_STATIC_ENTRIES -#define ETHARP_FLAG_STATIC_ENTRY 4 -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -#if LWIP_NETIF_HWADDRHINT -#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ - *((netif)->addr_hint) = (hint); -#else /* LWIP_NETIF_HWADDRHINT */ -#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) -#endif /* LWIP_NETIF_HWADDRHINT */ - - -/* Some checks, instead of etharp_init(): */ -#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) - #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" -#endif - - -static err_t etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr); -static err_t etharp_raw(struct netif *netif, - const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, - const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, - const u16_t opcode); - -#if ARP_QUEUEING -/** - * Free a complete queue of etharp entries - * - * @param q a qeueue of etharp_q_entry's to free - */ -static void -free_etharp_q(struct etharp_q_entry *q) -{ - struct etharp_q_entry *r; - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("q->p != NULL", q->p != NULL); - while (q) { - r = q; - q = q->next; - LWIP_ASSERT("r->p != NULL", (r->p != NULL)); - pbuf_free(r->p); - memp_free(MEMP_ARP_QUEUE, r); - } -} -#else /* ARP_QUEUEING */ - -/** Compatibility define: free the queued pbuf */ -#define free_etharp_q(q) pbuf_free(q) - -#endif /* ARP_QUEUEING */ - -/** Clean up ARP table entries */ -static void -etharp_free_entry(int i) -{ - /* remove from SNMP ARP index tree */ - mib2_remove_arp_entry(arp_table[i].netif, &arp_table[i].ipaddr); - /* and empty packet queue */ - if (arp_table[i].q != NULL) { - /* remove all queued packets */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_free_entry: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; - } - /* recycle entry for re-use */ - arp_table[i].state = ETHARP_STATE_EMPTY; -#ifdef LWIP_DEBUG - /* for debugging, clean out the complete entry */ - arp_table[i].ctime = 0; - arp_table[i].netif = NULL; - ip4_addr_set_zero(&arp_table[i].ipaddr); - arp_table[i].ethaddr = ethzero; -#endif /* LWIP_DEBUG */ -} - -/** - * Clears expired entries in the ARP table. - * - * This function should be called every ARP_TMR_INTERVAL milliseconds (1 second), - * in order to expire entries in the ARP table. - */ -void -etharp_tmr(void) -{ - u8_t i; - - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); - /* remove expired entries from the ARP table */ - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - if (state != ETHARP_STATE_EMPTY -#if ETHARP_SUPPORT_STATIC_ENTRIES - && (state != ETHARP_STATE_STATIC) -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - ) { - arp_table[i].ctime++; - if ((arp_table[i].ctime >= ARP_MAXAGE) || - ((arp_table[i].state == ETHARP_STATE_PENDING) && - (arp_table[i].ctime >= ARP_MAXPENDING))) { - /* pending or stable entry has become old! */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); - /* clean up entries that have just been expired */ - etharp_free_entry(i); - } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_1) { - /* Don't send more than one request every 2 seconds. */ - arp_table[i].state = ETHARP_STATE_STABLE_REREQUESTING_2; - } else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING_2) { - /* Reset state to stable, so that the next transmitted packet will - re-send an ARP request. */ - arp_table[i].state = ETHARP_STATE_STABLE; - } else if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* still pending, resend an ARP query */ - etharp_request(arp_table[i].netif, &arp_table[i].ipaddr); - } - } - } -} - -/** - * Search the ARP table for a matching or new entry. - * - * If an IP address is given, return a pending or stable ARP entry that matches - * the address. If no match is found, create a new entry with this address set, - * but in state ETHARP_EMPTY. The caller must check and possibly change the - * state of the returned entry. - * - * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. - * - * In all cases, attempt to create new entries from an empty entry. If no - * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle - * old entries. Heuristic choose the least important entry for recycling. - * - * @param ipaddr IP address to find in ARP cache, or to add if not found. - * @param flags See @ref etharp_state - * @param netif netif related to this address (used for NETIF_HWADDRHINT) - * - * @return The ARP entry index that matched or is created, ERR_MEM if no - * entry is found or could be recycled. - */ -static s8_t -etharp_find_entry(const ip4_addr_t *ipaddr, u8_t flags, struct netif* netif) -{ - s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; - s8_t empty = ARP_TABLE_SIZE; - u8_t i = 0; - /* oldest entry with packets on queue */ - s8_t old_queue = ARP_TABLE_SIZE; - /* its age */ - u16_t age_queue = 0, age_pending = 0, age_stable = 0; - - LWIP_UNUSED_ARG(netif); - - /** - * a) do a search through the cache, remember candidates - * b) select candidate entry - * c) create new entry - */ - - /* a) in a single search sweep, do all of this - * 1) remember the first empty entry (if any) - * 2) remember the oldest stable entry (if any) - * 3) remember the oldest pending entry without queued packets (if any) - * 4) remember the oldest pending entry with queued packets (if any) - * 5) search for a matching IP entry, either pending or stable - * until 5 matches, or all entries are searched for. - */ - - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - /* no empty entry found yet and now we do find one? */ - if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_find_entry: found empty entry %"U16_F"\n", (u16_t)i)); - /* remember first empty entry */ - empty = i; - } else if (state != ETHARP_STATE_EMPTY) { - LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", - state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); - /* if given, does IP address match IP address in ARP entry? */ - if (ipaddr && ip4_addr_cmp(ipaddr, &arp_table[i].ipaddr) -#if ETHARP_TABLE_MATCH_NETIF - && ((netif == NULL) || (netif == arp_table[i].netif)) -#endif /* ETHARP_TABLE_MATCH_NETIF */ - ) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: found matching entry %"U16_F"\n", (u16_t)i)); - /* found exact IP address match, simply bail out */ - return i; - } - /* pending entry? */ - if (state == ETHARP_STATE_PENDING) { - /* pending with queued packets? */ - if (arp_table[i].q != NULL) { - if (arp_table[i].ctime >= age_queue) { - old_queue = i; - age_queue = arp_table[i].ctime; - } - } else - /* pending without queued packets? */ - { - if (arp_table[i].ctime >= age_pending) { - old_pending = i; - age_pending = arp_table[i].ctime; - } - } - /* stable entry? */ - } else if (state >= ETHARP_STATE_STABLE) { -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* don't record old_stable for static entries since they never expire */ - if (state < ETHARP_STATE_STATIC) -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - { - /* remember entry with oldest stable entry in oldest, its age in maxtime */ - if (arp_table[i].ctime >= age_stable) { - old_stable = i; - age_stable = arp_table[i].ctime; - } - } - } - } - } - /* { we have no match } => try to create a new entry */ - - /* don't create new entry, only search? */ - if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || - /* or no empty entry found and not allowed to recycle? */ - ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty entry found and not allowed to recycle\n")); - return (s8_t)ERR_MEM; - } - - /* b) choose the least destructive entry to recycle: - * 1) empty entry - * 2) oldest stable entry - * 3) oldest pending entry without queued packets - * 4) oldest pending entry with queued packets - * - * { ETHARP_FLAG_TRY_HARD is set at this point } - */ - - /* 1) empty entry available? */ - if (empty < ARP_TABLE_SIZE) { - i = empty; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); - } else { - /* 2) found recyclable stable entry? */ - if (old_stable < ARP_TABLE_SIZE) { - /* recycle oldest stable*/ - i = old_stable; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); - /* no queued packets should exist on stable entries */ - LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); - /* 3) found recyclable pending entry without queued packets? */ - } else if (old_pending < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_pending; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); - /* 4) found recyclable pending entry with queued packets? */ - } else if (old_queue < ARP_TABLE_SIZE) { - /* recycle oldest pending (queued packets are free in etharp_free_entry) */ - i = old_queue; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); - /* no empty or recyclable entries found */ - } else { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_find_entry: no empty or recyclable entries found\n")); - return (s8_t)ERR_MEM; - } - - /* { empty or recyclable entry found } */ - LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - etharp_free_entry(i); - } - - LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", - arp_table[i].state == ETHARP_STATE_EMPTY); - - /* IP address given? */ - if (ipaddr != NULL) { - /* set IP address */ - ip4_addr_copy(arp_table[i].ipaddr, *ipaddr); - } - arp_table[i].ctime = 0; -#if ETHARP_TABLE_MATCH_NETIF - arp_table[i].netif = netif; -#endif /* ETHARP_TABLE_MATCH_NETIF*/ - return (err_t)i; -} - -/** - * Update (or insert) a IP/MAC address pair in the ARP cache. - * - * If a pending entry is resolved, any queued packets will be sent - * at this point. - * - * @param netif netif related to this entry (used for NETIF_ADDRHINT) - * @param ipaddr IP address of the inserted ARP entry. - * @param ethaddr Ethernet address of the inserted ARP entry. - * @param flags See @ref etharp_state - * - * @return - * - ERR_OK Successfully updated ARP cache. - * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - * @see pbuf_free() - */ -static err_t -etharp_update_arp_entry(struct netif *netif, const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) -{ - s8_t i; - LWIP_ASSERT("netif->hwaddr_len == ETH_HWADDR_LEN", netif->hwaddr_len == ETH_HWADDR_LEN); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), - (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], - (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); - /* non-unicast address? */ - if (ip4_addr_isany(ipaddr) || - ip4_addr_isbroadcast(ipaddr, netif) || - ip4_addr_ismulticast(ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: will not add non-unicast IP address to ARP cache\n")); - return ERR_ARG; - } - /* find or create ARP entry */ - i = etharp_find_entry(ipaddr, flags, netif); - /* bail out if no entry could be found */ - if (i < 0) { - return (err_t)i; - } - -#if ETHARP_SUPPORT_STATIC_ENTRIES - if (flags & ETHARP_FLAG_STATIC_ENTRY) { - /* record static type */ - arp_table[i].state = ETHARP_STATE_STATIC; - } else if (arp_table[i].state == ETHARP_STATE_STATIC) { - /* found entry is a static type, don't overwrite it */ - return ERR_VAL; - } else -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - { - /* mark it stable */ - arp_table[i].state = ETHARP_STATE_STABLE; - } - - /* record network interface */ - arp_table[i].netif = netif; - /* insert in SNMP ARP index tree */ - mib2_add_arp_entry(netif, &arp_table[i].ipaddr); - - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); - /* update address */ - ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); - /* reset time stamp */ - arp_table[i].ctime = 0; - /* this is where we will send out queued packets! */ -#if ARP_QUEUEING - while (arp_table[i].q != NULL) { - struct pbuf *p; - /* remember remainder of queue */ - struct etharp_q_entry *q = arp_table[i].q; - /* pop first item off the queue */ - arp_table[i].q = q->next; - /* get the packet pointer */ - p = q->p; - /* now queue entry can be freed */ - memp_free(MEMP_ARP_QUEUE, q); -#else /* ARP_QUEUEING */ - if (arp_table[i].q != NULL) { - struct pbuf *p = arp_table[i].q; - arp_table[i].q = NULL; -#endif /* ARP_QUEUEING */ - /* send the queued IP packet */ - ethernet_output(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr, ETHTYPE_IP); - /* free the queued IP packet */ - pbuf_free(p); - } - return ERR_OK; -} - -#if ETHARP_SUPPORT_STATIC_ENTRIES -/** Add a new static entry to the ARP table. If an entry exists for the - * specified IP address, this entry is overwritten. - * If packets are queued for the specified IP address, they are sent out. - * - * @param ipaddr IP address for the new static entry - * @param ethaddr ethernet address for the new static entry - * @return See return values of etharp_add_static_entry - */ -err_t -etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr) -{ - struct netif *netif; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), - (u16_t)ethaddr->addr[0], (u16_t)ethaddr->addr[1], (u16_t)ethaddr->addr[2], - (u16_t)ethaddr->addr[3], (u16_t)ethaddr->addr[4], (u16_t)ethaddr->addr[5])); - - netif = ip4_route(ipaddr); - if (netif == NULL) { - return ERR_RTE; - } - - return etharp_update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); -} - -/** Remove a static entry from the ARP table previously added with a call to - * etharp_add_static_entry. - * - * @param ipaddr IP address of the static entry to remove - * @return ERR_OK: entry removed - * ERR_MEM: entry wasn't found - * ERR_ARG: entry wasn't a static entry but a dynamic one - */ -err_t -etharp_remove_static_entry(const ip4_addr_t *ipaddr) -{ - s8_t i; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); - - /* find or create ARP entry */ - i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, NULL); - /* bail out if no entry could be found */ - if (i < 0) { - return (err_t)i; - } - - if (arp_table[i].state != ETHARP_STATE_STATIC) { - /* entry wasn't a static entry, cannot remove it */ - return ERR_ARG; - } - /* entry found, free it */ - etharp_free_entry(i); - return ERR_OK; -} -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -/** - * Remove all ARP table entries of the specified netif. - * - * @param netif points to a network interface - */ -void -etharp_cleanup_netif(struct netif *netif) -{ - u8_t i; - - for (i = 0; i < ARP_TABLE_SIZE; ++i) { - u8_t state = arp_table[i].state; - if ((state != ETHARP_STATE_EMPTY) && (arp_table[i].netif == netif)) { - etharp_free_entry(i); - } - } -} - -/** - * Finds (stable) ethernet/IP address pair from ARP table - * using interface and IP address index. - * @note the addresses in the ARP table are in network order! - * - * @param netif points to interface index - * @param ipaddr points to the (network order) IP address index - * @param eth_ret points to return pointer - * @param ip_ret points to return pointer - * @return table index if found, -1 otherwise - */ -s8_t -etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, - struct eth_addr **eth_ret, const ip4_addr_t **ip_ret) -{ - s8_t i; - - LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", - eth_ret != NULL && ip_ret != NULL); - - LWIP_UNUSED_ARG(netif); - - i = etharp_find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY, netif); - if ((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { - *eth_ret = &arp_table[i].ethaddr; - *ip_ret = &arp_table[i].ipaddr; - return i; - } - return -1; -} - -/** - * Possibility to iterate over stable ARP table entries - * - * @param i entry number, 0 to ARP_TABLE_SIZE - * @param ipaddr return value: IP address - * @param netif return value: points to interface - * @param eth_ret return value: ETH address - * @return 1 on valid index, 0 otherwise - */ -u8_t -etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret) -{ - LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("eth_ret != NULL", eth_ret != NULL); - - if((i < ARP_TABLE_SIZE) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { - *ipaddr = &arp_table[i].ipaddr; - *netif = arp_table[i].netif; - *eth_ret = &arp_table[i].ethaddr; - return 1; - } else { - return 0; - } -} - -/** - * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache - * send out queued IP packets. Updates cache with snooped address pairs. - * - * Should be called for incoming ARP packets. The pbuf in the argument - * is freed by this function. - * - * @param p The ARP packet that arrived on netif. Is freed by this function. - * @param netif The lwIP network interface on which the ARP packet pbuf arrived. - * - * @see pbuf_free() - */ -void -etharp_input(struct pbuf *p, struct netif *netif) -{ - struct etharp_hdr *hdr; - /* these are aligned properly, whereas the ARP header fields might not be */ - ip4_addr_t sipaddr, dipaddr; - u8_t for_us; - - LWIP_ERROR("netif != NULL", (netif != NULL), return;); - - hdr = (struct etharp_hdr *)p->payload; - - /* RFC 826 "Packet Reception": */ - if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || - (hdr->hwlen != ETH_HWADDR_LEN) || - (hdr->protolen != sizeof(ip4_addr_t)) || - (hdr->proto != PP_HTONS(ETHTYPE_IP))) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", - hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen)); - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - pbuf_free(p); - return; - } - ETHARP_STATS_INC(etharp.recv); - -#if LWIP_AUTOIP - /* We have to check if a host already has configured our random - * created link local address and continuously check if there is - * a host with this IP-address so we can detect collisions */ - autoip_arp_reply(netif, hdr); -#endif /* LWIP_AUTOIP */ - - /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without - * structure packing (not using structure copy which breaks strict-aliasing rules). */ - IPADDR2_COPY(&sipaddr, &hdr->sipaddr); - IPADDR2_COPY(&dipaddr, &hdr->dipaddr); - - /* this interface is not configured? */ - if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { - for_us = 0; - } else { - /* ARP packet directed to us? */ - for_us = (u8_t)ip4_addr_cmp(&dipaddr, netif_ip4_addr(netif)); - } - - /* ARP message directed to us? - -> add IP address in ARP cache; assume requester wants to talk to us, - can result in directly sending the queued packets for this host. - ARP message not directed to us? - -> update the source IP address in the cache, if present */ - etharp_update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), - for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); - - /* now act on the message itself */ - switch (hdr->opcode) { - /* ARP request? */ - case PP_HTONS(ARP_REQUEST): - /* ARP request. If it asked for our address, we send out a - * reply. In any case, we time-stamp any existing ARP entry, - * and possibly send out an IP packet that was queued on it. */ - - LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP request\n")); - /* ARP request for our address? */ - if (for_us) { - /* send ARP response */ - etharp_raw(netif, - (struct eth_addr *)netif->hwaddr, &hdr->shwaddr, - (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), - &hdr->shwaddr, &sipaddr, - ARP_REPLY); - /* we are not configured? */ - } else if (ip4_addr_isany_val(*netif_ip4_addr(netif))) { - /* { for_us == 0 and netif->ip_addr.addr == 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: we are unconfigured, ARP request ignored.\n")); - /* request was not directed to us */ - } else { - /* { for_us == 0 and netif->ip_addr.addr != 0 } */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP request was not for us.\n")); - } - break; - case PP_HTONS(ARP_REPLY): - /* ARP reply. We already updated the ARP cache earlier. */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: incoming ARP reply\n")); -#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) - /* DHCP wants to know about ARP replies from any host with an - * IP address also offered to us by the DHCP server. We do not - * want to take a duplicate IP address on a single network. - * @todo How should we handle redundant (fail-over) interfaces? */ - dhcp_arp_reply(netif, &sipaddr); -#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ - break; - default: - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_input: ARP unknown opcode type %"S16_F"\n", lwip_htons(hdr->opcode))); - ETHARP_STATS_INC(etharp.err); - break; - } - /* free ARP packet */ - pbuf_free(p); -} - -/** Just a small helper function that sends a pbuf to an ethernet address - * in the arp_table specified by the index 'arp_idx'. - */ -static err_t -etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) -{ - LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", - arp_table[arp_idx].state >= ETHARP_STATE_STABLE); - /* if arp table entry is about to expire: re-request it, - but only if its state is ETHARP_STATE_STABLE to prevent flooding the - network with ARP requests if this address is used frequently. */ - if (arp_table[arp_idx].state == ETHARP_STATE_STABLE) { - if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_BROADCAST) { - /* issue a standard request using broadcast */ - if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { - arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; - } - } else if (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED_UNICAST) { - /* issue a unicast request (for 15 seconds) to prevent unnecessary broadcast */ - if (etharp_request_dst(netif, &arp_table[arp_idx].ipaddr, &arp_table[arp_idx].ethaddr) == ERR_OK) { - arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING_1; - } - } - } - - return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &arp_table[arp_idx].ethaddr, ETHTYPE_IP); -} - -/** - * Resolve and fill-in Ethernet address header for outgoing IP packet. - * - * For IP multicast and broadcast, corresponding Ethernet addresses - * are selected and the packet is transmitted on the link. - * - * For unicast addresses, the packet is submitted to etharp_query(). In - * case the IP address is outside the local network, the IP address of - * the gateway is used. - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ipaddr The IP address of the packet destination. - * - * @return - * - ERR_RTE No route to destination (no gateway to external networks), - * or the return type of either etharp_query() or ethernet_output(). - */ -err_t -etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) -{ - const struct eth_addr *dest; - struct eth_addr mcastaddr; - const ip4_addr_t *dst_addr = ipaddr; - - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); - - /* Determine on destination hardware address. Broadcasts and multicasts - * are special, other IP addresses are looked up in the ARP table. */ - - /* broadcast destination IP address? */ - if (ip4_addr_isbroadcast(ipaddr, netif)) { - /* broadcast on Ethernet also */ - dest = (const struct eth_addr *)ðbroadcast; - /* multicast destination IP address? */ - } else if (ip4_addr_ismulticast(ipaddr)) { - /* Hash IP multicast address to MAC address.*/ - mcastaddr.addr[0] = LL_IP4_MULTICAST_ADDR_0; - mcastaddr.addr[1] = LL_IP4_MULTICAST_ADDR_1; - mcastaddr.addr[2] = LL_IP4_MULTICAST_ADDR_2; - mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f; - mcastaddr.addr[4] = ip4_addr3(ipaddr); - mcastaddr.addr[5] = ip4_addr4(ipaddr); - /* destination Ethernet address is multicast */ - dest = &mcastaddr; - /* unicast destination IP address? */ - } else { - s8_t i; - /* outside local network? if so, this can neither be a global broadcast nor - a subnet broadcast. */ - if (!ip4_addr_netcmp(ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) && - !ip4_addr_islinklocal(ipaddr)) { -#if LWIP_AUTOIP - struct ip_hdr *iphdr = LWIP_ALIGNMENT_CAST(struct ip_hdr*, q->payload); - /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with - a link-local source address must always be "directly to its destination - on the same physical link. The host MUST NOT send the packet to any - router for forwarding". */ - if (!ip4_addr_islinklocal(&iphdr->src)) -#endif /* LWIP_AUTOIP */ - { -#ifdef LWIP_HOOK_ETHARP_GET_GW - /* For advanced routing, a single default gateway might not be enough, so get - the IP address of the gateway to handle the current destination address. */ - dst_addr = LWIP_HOOK_ETHARP_GET_GW(netif, ipaddr); - if (dst_addr == NULL) -#endif /* LWIP_HOOK_ETHARP_GET_GW */ - { - /* interface has default gateway? */ - if (!ip4_addr_isany_val(*netif_ip4_gw(netif))) { - /* send to hardware address of default gateway IP address */ - dst_addr = netif_ip4_gw(netif); - /* no default gateway available */ - } else { - /* no route to destination error (default gateway missing) */ - return ERR_RTE; - } - } - } - } -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - u8_t etharp_cached_entry = *(netif->addr_hint); - if (etharp_cached_entry < ARP_TABLE_SIZE) { -#endif /* LWIP_NETIF_HWADDRHINT */ - if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && -#if ETHARP_TABLE_MATCH_NETIF - (arp_table[etharp_cached_entry].netif == netif) && -#endif - (ip4_addr_cmp(dst_addr, &arp_table[etharp_cached_entry].ipaddr))) { - /* the per-pcb-cached entry is stable and the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return etharp_output_to_arp_index(netif, q, etharp_cached_entry); - } -#if LWIP_NETIF_HWADDRHINT - } - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* find stable entry: do this here since this is a critical path for - throughput and etharp_find_entry() is kind of slow */ - for (i = 0; i < ARP_TABLE_SIZE; i++) { - if ((arp_table[i].state >= ETHARP_STATE_STABLE) && -#if ETHARP_TABLE_MATCH_NETIF - (arp_table[i].netif == netif) && -#endif - (ip4_addr_cmp(dst_addr, &arp_table[i].ipaddr))) { - /* found an existing, stable entry */ - ETHARP_SET_HINT(netif, i); - return etharp_output_to_arp_index(netif, q, i); - } - } - /* no stable entry found, use the (slower) query function: - queue on destination Ethernet address belonging to ipaddr */ - return etharp_query(netif, dst_addr, q); - } - - /* continuation for multicast/broadcast destinations */ - /* obtain source Ethernet address of the given interface */ - /* send packet directly on the link */ - return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), dest, ETHTYPE_IP); -} - -/** - * Send an ARP request for the given IP address and/or queue a packet. - * - * If the IP address was not yet in the cache, a pending ARP cache entry - * is added and an ARP request is sent for the given address. The packet - * is queued on this entry. - * - * If the IP address was already pending in the cache, a new ARP request - * is sent for the given address. The packet is queued on this entry. - * - * If the IP address was already stable in the cache, and a packet is - * given, it is directly sent and no ARP request is sent out. - * - * If the IP address was already stable in the cache, and no packet is - * given, an ARP request is sent out. - * - * @param netif The lwIP network interface on which ipaddr - * must be queried for. - * @param ipaddr The IP address to be resolved. - * @param q If non-NULL, a pbuf that must be delivered to the IP address. - * q is not freed by this function. - * - * @note q must only be ONE packet, not a packet queue! - * - * @return - * - ERR_BUF Could not make room for Ethernet header. - * - ERR_MEM Hardware address unknown, and no more ARP entries available - * to query for address or queue the packet. - * - ERR_MEM Could not queue packet due to memory shortage. - * - ERR_RTE No route to destination (no gateway to external networks). - * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. - * - */ -err_t -etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) -{ - struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; - err_t result = ERR_MEM; - int is_new_entry = 0; - s8_t i; /* ARP entry index */ - - /* non-unicast address? */ - if (ip4_addr_isbroadcast(ipaddr, netif) || - ip4_addr_ismulticast(ipaddr) || - ip4_addr_isany(ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n")); - return ERR_ARG; - } - - /* find entry in ARP cache, ask to create entry if queueing packet */ - i = etharp_find_entry(ipaddr, ETHARP_FLAG_TRY_HARD, netif); - - /* could not find or create entry? */ - if (i < 0) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n")); - if (q) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n")); - ETHARP_STATS_INC(etharp.memerr); - } - return (err_t)i; - } - - /* mark a fresh entry as pending (we just sent a request) */ - if (arp_table[i].state == ETHARP_STATE_EMPTY) { - is_new_entry = 1; - arp_table[i].state = ETHARP_STATE_PENDING; - /* record network interface for re-sending arp request in etharp_tmr */ - arp_table[i].netif = netif; - } - - /* { i is either a STABLE or (new or existing) PENDING entry } */ - LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", - ((arp_table[i].state == ETHARP_STATE_PENDING) || - (arp_table[i].state >= ETHARP_STATE_STABLE))); - - /* do we have a new entry? or an implicit query request? */ - if (is_new_entry || (q == NULL)) { - /* try to resolve it; send out ARP request */ - result = etharp_request(netif, ipaddr); - if (result != ERR_OK) { - /* ARP request couldn't be sent */ - /* We don't re-send arp request in etharp_tmr, but we still queue packets, - since this failure could be temporary, and the next packet calling - etharp_query again could lead to sending the queued packets. */ - } - if (q == NULL) { - return result; - } - } - - /* packet given? */ - LWIP_ASSERT("q != NULL", q != NULL); - /* stable entry? */ - if (arp_table[i].state >= ETHARP_STATE_STABLE) { - /* we have a valid IP->Ethernet address mapping */ - ETHARP_SET_HINT(netif, i); - /* send the packet */ - result = ethernet_output(netif, q, srcaddr, &(arp_table[i].ethaddr), ETHTYPE_IP); - /* pending entry? (either just created or already pending */ - } else if (arp_table[i].state == ETHARP_STATE_PENDING) { - /* entry is still pending, queue the given packet 'q' */ - struct pbuf *p; - int copy_needed = 0; - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); - if (p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; - } - if (copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - if (p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet could be taken over? */ - if (p != NULL) { - /* queue packet ... */ -#if ARP_QUEUEING - struct etharp_q_entry *new_entry; - /* allocate a new arp queue entry */ - new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); - if (new_entry != NULL) { - unsigned int qlen = 0; - new_entry->next = 0; - new_entry->p = p; - if (arp_table[i].q != NULL) { - /* queue was already existent, append the new entry to the end */ - struct etharp_q_entry *r; - r = arp_table[i].q; - qlen++; - while (r->next != NULL) { - r = r->next; - qlen++; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - arp_table[i].q = new_entry; - } -#if ARP_QUEUE_LEN - if (qlen >= ARP_QUEUE_LEN) { - struct etharp_q_entry *old; - old = arp_table[i].q; - arp_table[i].q = arp_table[i].q->next; - pbuf_free(old->p); - memp_free(MEMP_ARP_QUEUE, old); - } -#endif - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - result = ERR_OK; - } else { - /* the pool MEMP_ARP_QUEUE is empty */ - pbuf_free(p); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - result = ERR_MEM; - } -#else /* ARP_QUEUEING */ - /* always queue one packet per ARP request only, freeing a previously queued packet */ - if (arp_table[i].q != NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - pbuf_free(arp_table[i].q); - } - arp_table[i].q = p; - result = ERR_OK; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); -#endif /* ARP_QUEUEING */ - } else { - ETHARP_STATS_INC(etharp.memerr); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - result = ERR_MEM; - } - } - return result; -} - -/** - * Send a raw ARP packet (opcode and all addresses can be modified) - * - * @param netif the lwip network interface on which to send the ARP packet - * @param ethsrc_addr the source MAC address for the ethernet header - * @param ethdst_addr the destination MAC address for the ethernet header - * @param hwsrc_addr the source MAC address for the ARP protocol header - * @param ipsrc_addr the source IP address for the ARP protocol header - * @param hwdst_addr the destination MAC address for the ARP protocol header - * @param ipdst_addr the destination IP address for the ARP protocol header - * @param opcode the type of the ARP packet - * @return ERR_OK if the ARP packet has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -static err_t -etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, - const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const ip4_addr_t *ipsrc_addr, - const struct eth_addr *hwdst_addr, const ip4_addr_t *ipdst_addr, - const u16_t opcode) -{ - struct pbuf *p; - err_t result = ERR_OK; - struct etharp_hdr *hdr; - - LWIP_ASSERT("netif != NULL", netif != NULL); - - /* allocate a pbuf for the outgoing ARP request packet */ - p = pbuf_alloc(PBUF_LINK, SIZEOF_ETHARP_HDR, PBUF_RAM); - /* could allocate a pbuf for an ARP request? */ - if (p == NULL) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("etharp_raw: could not allocate pbuf for ARP request.\n")); - ETHARP_STATS_INC(etharp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", - (p->len >= SIZEOF_ETHARP_HDR)); - - hdr = (struct etharp_hdr *)p->payload; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); - hdr->opcode = lwip_htons(opcode); - - LWIP_ASSERT("netif->hwaddr_len must be the same as ETH_HWADDR_LEN for etharp!", - (netif->hwaddr_len == ETH_HWADDR_LEN)); - - /* Write the ARP MAC-Addresses */ - ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); - ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); - /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without - * structure packing. */ - IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); - IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); - - hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); - hdr->proto = PP_HTONS(ETHTYPE_IP); - /* set hwlen and protolen */ - hdr->hwlen = ETH_HWADDR_LEN; - hdr->protolen = sizeof(ip4_addr_t); - - /* send ARP query */ -#if LWIP_AUTOIP - /* If we are using Link-Local, all ARP packets that contain a Link-Local - * 'sender IP address' MUST be sent using link-layer broadcast instead of - * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ - if(ip4_addr_islinklocal(ipsrc_addr)) { - ethernet_output(netif, p, ethsrc_addr, ðbroadcast, ETHTYPE_ARP); - } else -#endif /* LWIP_AUTOIP */ - { - ethernet_output(netif, p, ethsrc_addr, ethdst_addr, ETHTYPE_ARP); - } - - ETHARP_STATS_INC(etharp.xmit); - /* free ARP query packet */ - pbuf_free(p); - p = NULL; - /* could not allocate pbuf for ARP request */ - - return result; -} - -/** - * Send an ARP request packet asking for ipaddr to a specific eth address. - * Used to send unicast request to refresh the ARP table just before an entry - * times out - * - * @param netif the lwip network interface on which to send the request - * @param ipaddr the IP address for which to ask - * @param hw_dst_addr the ethernet address to send this packet to - * @return ERR_OK if the request has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -static err_t -etharp_request_dst(struct netif *netif, const ip4_addr_t *ipaddr, const struct eth_addr* hw_dst_addr) -{ - return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, hw_dst_addr, - (struct eth_addr *)netif->hwaddr, netif_ip4_addr(netif), ðzero, - ipaddr, ARP_REQUEST); -} - -/** - * Send an ARP request packet asking for ipaddr. - * - * @param netif the lwip network interface on which to send the request - * @param ipaddr the IP address for which to ask - * @return ERR_OK if the request has been sent - * ERR_MEM if the ARP packet couldn't be allocated - * any other err_t on failure - */ -err_t -etharp_request(struct netif *netif, const ip4_addr_t *ipaddr) -{ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); - return etharp_request_dst(netif, ipaddr, ðbroadcast); -} -#endif /* LWIP_IPV4 && LWIP_ARP */ - -#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/icmp.c b/components/net/lwip-2.0.2/src/core/ipv4/icmp.c deleted file mode 100644 index 5ee24eedfa..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/icmp.c +++ /dev/null @@ -1,397 +0,0 @@ -/** - * @file - * ICMP - Internet Control Message Protocol - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* Some ICMP messages should be passed to the transport protocols. This - is not implemented. */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip.h" -#include "lwip/def.h" -#include "lwip/stats.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be - * used to modify and send a response packet (and to 1 if this is not the case, - * e.g. when link header is stripped of when receiving) */ -#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN -#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1 -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ - -/* The amount of data from the original packet to return in a dest-unreachable */ -#define ICMP_DEST_UNREACH_DATASIZE 8 - -static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code); - -/** - * Processes ICMP input packets, called from ip_input(). - * - * Currently only processes icmp echo requests and sends - * out the echo response. - * - * @param p the icmp echo request packet, p->payload pointing to the icmp header - * @param inp the netif on which this packet was received - */ -void -icmp_input(struct pbuf *p, struct netif *inp) -{ - u8_t type; -#ifdef LWIP_DEBUG - u8_t code; -#endif /* LWIP_DEBUG */ - struct icmp_echo_hdr *iecho; - const struct ip_hdr *iphdr_in; - u16_t hlen; - const ip4_addr_t* src; - - ICMP_STATS_INC(icmp.recv); - MIB2_STATS_INC(mib2.icmpinmsgs); - - iphdr_in = ip4_current_header(); - hlen = IPH_HL(iphdr_in) * 4; - if (hlen < IP_HLEN) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short IP header (%"S16_F" bytes) received\n", hlen)); - goto lenerr; - } - if (p->len < sizeof(u16_t)*2) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len)); - goto lenerr; - } - - type = *((u8_t *)p->payload); -#ifdef LWIP_DEBUG - code = *(((u8_t *)p->payload)+1); -#endif /* LWIP_DEBUG */ - switch (type) { - case ICMP_ER: - /* This is OK, echo reply might have been parsed by a raw PCB - (as obviously, an echo request has been sent, too). */ - MIB2_STATS_INC(mib2.icmpinechoreps); - break; - case ICMP_ECHO: - MIB2_STATS_INC(mib2.icmpinechos); - src = ip4_current_dest_addr(); - /* multicast destination address? */ - if (ip4_addr_ismulticast(ip4_current_dest_addr())) { -#if LWIP_MULTICAST_PING - /* For multicast, use address of receiving interface as source address */ - src = netif_ip4_addr(inp); -#else /* LWIP_MULTICAST_PING */ - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast pings\n")); - goto icmperr; -#endif /* LWIP_MULTICAST_PING */ - } - /* broadcast destination address? */ - if (ip4_addr_isbroadcast(ip4_current_dest_addr(), ip_current_netif())) { -#if LWIP_BROADCAST_PING - /* For broadcast, use address of receiving interface as source address */ - src = netif_ip4_addr(inp); -#else /* LWIP_BROADCAST_PING */ - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to broadcast pings\n")); - goto icmperr; -#endif /* LWIP_BROADCAST_PING */ - } - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n")); - if (p->tot_len < sizeof(struct icmp_echo_hdr)) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n")); - goto lenerr; - } -#if CHECKSUM_CHECK_ICMP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) { - if (inet_chksum_pbuf(p) != 0) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n")); - pbuf_free(p); - ICMP_STATS_INC(icmp.chkerr); - MIB2_STATS_INC(mib2.icmpinerrors); - return; - } - } -#endif -#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { - /* p is not big enough to contain link headers - * allocate a new one and copy p into it - */ - struct pbuf *r; - /* allocate new packet buffer with space for link headers */ - r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM); - if (r == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); - goto icmperr; - } - if (r->len < hlen + sizeof(struct icmp_echo_hdr)) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("first pbuf cannot hold the ICMP header")); - pbuf_free(r); - goto icmperr; - } - /* copy the ip header */ - MEMCPY(r->payload, iphdr_in, hlen); - /* switch r->payload back to icmp header (cannot fail) */ - if (pbuf_header(r, (s16_t)-hlen)) { - LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); - pbuf_free(r); - goto icmperr; - } - /* copy the rest of the packet without ip header */ - if (pbuf_copy(r, p) != ERR_OK) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("icmp_input: copying to new pbuf failed")); - pbuf_free(r); - goto icmperr; - } - /* free the original p */ - pbuf_free(p); - /* we now have an identical copy of p that has room for link headers */ - p = r; - } else { - /* restore p->payload to point to icmp header (cannot fail) */ - if (pbuf_header(p, -(s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { - LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); - goto icmperr; - } - } -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */ - /* At this point, all checks are OK. */ - /* We generate an answer by switching the dest and src ip addresses, - * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ - iecho = (struct icmp_echo_hdr *)p->payload; - if (pbuf_header(p, (s16_t)hlen)) { - LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet")); - } else { - err_t ret; - struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; - ip4_addr_copy(iphdr->src, *src); - ip4_addr_copy(iphdr->dest, *ip4_current_src_addr()); - ICMPH_TYPE_SET(iecho, ICMP_ER); -#if CHECKSUM_GEN_ICMP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) { - /* adjust the checksum */ - if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { - iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; - } else { - iecho->chksum += PP_HTONS(ICMP_ECHO << 8); - } - } -#if LWIP_CHECKSUM_CTRL_PER_NETIF - else { - iecho->chksum = 0; - } -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#else /* CHECKSUM_GEN_ICMP */ - iecho->chksum = 0; -#endif /* CHECKSUM_GEN_ICMP */ - - /* Set the correct TTL and recalculate the header checksum. */ - IPH_TTL_SET(iphdr, ICMP_TTL); - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen)); - } -#endif /* CHECKSUM_GEN_IP */ - - ICMP_STATS_INC(icmp.xmit); - /* increase number of messages attempted to send */ - MIB2_STATS_INC(mib2.icmpoutmsgs); - /* increase number of echo replies attempted to send */ - MIB2_STATS_INC(mib2.icmpoutechoreps); - - /* send an ICMP packet */ - ret = ip4_output_if(p, src, LWIP_IP_HDRINCL, - ICMP_TTL, 0, IP_PROTO_ICMP, inp); - if (ret != ERR_OK) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret))); - } - } - break; - default: - if (type == ICMP_DUR) { - MIB2_STATS_INC(mib2.icmpindestunreachs); - } else if (type == ICMP_TE) { - MIB2_STATS_INC(mib2.icmpintimeexcds); - } else if (type == ICMP_PP) { - MIB2_STATS_INC(mib2.icmpinparmprobs); - } else if (type == ICMP_SQ) { - MIB2_STATS_INC(mib2.icmpinsrcquenchs); - } else if (type == ICMP_RD) { - MIB2_STATS_INC(mib2.icmpinredirects); - } else if (type == ICMP_TS) { - MIB2_STATS_INC(mib2.icmpintimestamps); - } else if (type == ICMP_TSR) { - MIB2_STATS_INC(mib2.icmpintimestampreps); - } else if (type == ICMP_AM) { - MIB2_STATS_INC(mib2.icmpinaddrmasks); - } else if (type == ICMP_AMR) { - MIB2_STATS_INC(mib2.icmpinaddrmaskreps); - } - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", - (s16_t)type, (s16_t)code)); - ICMP_STATS_INC(icmp.proterr); - ICMP_STATS_INC(icmp.drop); - } - pbuf_free(p); - return; -lenerr: - pbuf_free(p); - ICMP_STATS_INC(icmp.lenerr); - MIB2_STATS_INC(mib2.icmpinerrors); - return; -#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING -icmperr: - pbuf_free(p); - ICMP_STATS_INC(icmp.err); - MIB2_STATS_INC(mib2.icmpinerrors); - return; -#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING */ -} - -/** - * Send an icmp 'destination unreachable' packet, called from ip_input() if - * the transport layer protocol is unknown and from udp_input() if the local - * port is not bound. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IP header - * @param t type of the 'unreachable' packet - */ -void -icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t) -{ - MIB2_STATS_INC(mib2.icmpoutdestunreachs); - icmp_send_response(p, ICMP_DUR, t); -} - -#if IP_FORWARD || IP_REASSEMBLY -/** - * Send a 'time exceeded' packet, called from ip_forward() if TTL is 0. - * - * @param p the input packet for which the 'time exceeded' should be sent, - * p->payload pointing to the IP header - * @param t type of the 'time exceeded' packet - */ -void -icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t) -{ - MIB2_STATS_INC(mib2.icmpouttimeexcds); - icmp_send_response(p, ICMP_TE, t); -} - -#endif /* IP_FORWARD || IP_REASSEMBLY */ - -/** - * Send an icmp packet in response to an incoming packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IP header - * @param type Type of the ICMP header - * @param code Code of the ICMP header - */ -static void -icmp_send_response(struct pbuf *p, u8_t type, u8_t code) -{ - struct pbuf *q; - struct ip_hdr *iphdr; - /* we can use the echo header here */ - struct icmp_echo_hdr *icmphdr; - ip4_addr_t iphdr_src; - struct netif *netif; - - /* increase number of messages attempted to send */ - MIB2_STATS_INC(mib2.icmpoutmsgs); - - /* ICMP header + IP header + 8 bytes of data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n")); - MIB2_STATS_INC(mib2.icmpouterrors); - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp message", - (q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE))); - - iphdr = (struct ip_hdr *)p->payload; - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from ")); - ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->src); - LWIP_DEBUGF(ICMP_DEBUG, (" to ")); - ip4_addr_debug_print_val(ICMP_DEBUG, iphdr->dest); - LWIP_DEBUGF(ICMP_DEBUG, ("\n")); - - icmphdr = (struct icmp_echo_hdr *)q->payload; - icmphdr->type = type; - icmphdr->code = code; - icmphdr->id = 0; - icmphdr->seqno = 0; - - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload, - IP_HLEN + ICMP_DEST_UNREACH_DATASIZE); - - ip4_addr_copy(iphdr_src, iphdr->src); -#ifdef LWIP_HOOK_IP4_ROUTE_SRC - { - ip4_addr_t iphdr_dst; - ip4_addr_copy(iphdr_dst, iphdr->dest); - netif = ip4_route_src(&iphdr_src, &iphdr_dst); - } -#else - netif = ip4_route(&iphdr_src); -#endif - if (netif != NULL) { - /* calculate checksum */ - icmphdr->chksum = 0; -#if CHECKSUM_GEN_ICMP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) { - icmphdr->chksum = inet_chksum(icmphdr, q->len); - } -#endif - ICMP_STATS_INC(icmp.xmit); - ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif); - } - pbuf_free(q); -} - -#endif /* LWIP_IPV4 && LWIP_ICMP */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/igmp.c b/components/net/lwip-2.0.2/src/core/ipv4/igmp.c deleted file mode 100644 index 74a6c37731..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/igmp.c +++ /dev/null @@ -1,800 +0,0 @@ -/** - * @file - * IGMP - Internet Group Management Protocol - * - * @defgroup igmp IGMP - * @ingroup ip4 - * To be called from TCPIP thread - */ - -/* - * Copyright (c) 2002 CITEL Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is a contribution to the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. -*/ - -/*------------------------------------------------------------- -Note 1) -Although the rfc requires V1 AND V2 capability -we will only support v2 since now V1 is very old (August 1989) -V1 can be added if required - -a debug print and statistic have been implemented to -show this up. -------------------------------------------------------------- -------------------------------------------------------------- -Note 2) -A query for a specific group address (as opposed to ALLHOSTS) -has now been implemented as I am unsure if it is required - -a debug print and statistic have been implemented to -show this up. -------------------------------------------------------------- -------------------------------------------------------------- -Note 3) -The router alert rfc 2113 is implemented in outgoing packets -but not checked rigorously incoming -------------------------------------------------------------- -Steve Reynolds -------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - * RFC 988 - Host extensions for IP multicasting - V0 - * RFC 1054 - Host extensions for IP multicasting - - * RFC 1112 - Host extensions for IP multicasting - V1 - * RFC 2236 - Internet Group Management Protocol, Version 2 - V2 <- this code is based on this RFC (it's the "de facto" standard) - * RFC 3376 - Internet Group Management Protocol, Version 3 - V3 - * RFC 4604 - Using Internet Group Management Protocol Version 3... - V3+ - * RFC 2113 - IP Router Alert Option - - *----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- - * Includes - *----------------------------------------------------------------------------*/ - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/igmp.h" -#include "lwip/debug.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/ip.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/stats.h" -#include "lwip/prot/igmp.h" - -#include "string.h" - -static struct igmp_group *igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr); -static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group); -static void igmp_timeout(struct netif *netif, struct igmp_group *group); -static void igmp_start_timer(struct igmp_group *group, u8_t max_time); -static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp); -static err_t igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif); -static void igmp_send(struct netif *netif, struct igmp_group *group, u8_t type); - -static ip4_addr_t allsystems; -static ip4_addr_t allrouters; - -/** - * Initialize the IGMP module - */ -void -igmp_init(void) -{ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n")); - - IP4_ADDR(&allsystems, 224, 0, 0, 1); - IP4_ADDR(&allrouters, 224, 0, 0, 2); -} - -/** - * Start IGMP processing on interface - * - * @param netif network interface on which start IGMP processing - */ -err_t -igmp_start(struct netif *netif) -{ - struct igmp_group* group; - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", (void*)netif)); - - group = igmp_lookup_group(netif, &allsystems); - - if (group != NULL) { - group->group_state = IGMP_GROUP_IDLE_MEMBER; - group->use++; - - /* Allow the igmp messages at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD ")); - ip4_addr_debug_print_val(IGMP_DEBUG, allsystems); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, &allsystems, NETIF_ADD_MAC_FILTER); - } - - return ERR_OK; - } - - return ERR_MEM; -} - -/** - * Stop IGMP processing on interface - * - * @param netif network interface on which stop IGMP processing - */ -err_t -igmp_stop(struct netif *netif) -{ - struct igmp_group *group = netif_igmp_data(netif); - - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, NULL); - - while (group != NULL) { - struct igmp_group *next = group->next; /* avoid use-after-free below */ - - /* disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL ")); - ip4_addr_debug_print(IGMP_DEBUG, &group->group_address); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); - } - - /* free group */ - memp_free(MEMP_IGMP_GROUP, group); - - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report IGMP memberships for this interface - * - * @param netif network interface on which report IGMP memberships - */ -void -igmp_report_groups(struct netif *netif) -{ - struct igmp_group *group = netif_igmp_data(netif); - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); - - /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ - if(group != NULL) { - group = group->next; - } - - while (group != NULL) { - igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - group = group->next; - } -} - -/** - * Search for a group in the global igmp_group_list - * - * @param ifp the network interface for which to look - * @param addr the group ip address to search for - * @return a struct igmp_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct igmp_group * -igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) -{ - struct igmp_group *group = netif_igmp_data(ifp); - - while (group != NULL) { - if (ip4_addr_cmp(&(group->group_address), addr)) { - return group; - } - group = group->next; - } - - /* to be clearer, we return NULL here instead of - * 'group' (which is also NULL at this point). - */ - return NULL; -} - -/** - * Search for a specific igmp group and create a new one if not found- - * - * @param ifp the network interface for which to look - * @param addr the group ip address to search - * @return a struct igmp_group*, - * NULL on memory error. - */ -static struct igmp_group * -igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) -{ - struct igmp_group *group; - struct igmp_group *list_head = netif_igmp_data(ifp); - - /* Search if the group already exists */ - group = igmp_lookfor_group(ifp, addr); - if (group != NULL) { - /* Group already exists. */ - return group; - } - - /* Group doesn't exist yet, create a new one */ - group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); - if (group != NULL) { - ip4_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = IGMP_GROUP_NON_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - - /* Ensure allsystems group is always first in list */ - if (list_head == NULL) { - /* this is the first entry in linked list */ - LWIP_ASSERT("igmp_lookup_group: first group must be allsystems", - (ip4_addr_cmp(addr, &allsystems) != 0)); - group->next = NULL; - netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); - } else { - /* append _after_ first entry */ - LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems", - (ip4_addr_cmp(addr, &allsystems) == 0)); - group->next = list_head->next; - list_head->next = group; - } - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); - ip4_addr_debug_print(IGMP_DEBUG, addr); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)ifp)); - - return group; -} - -/** - * Remove a group in the global igmp_group_list, but don't free it yet - * - * @param group the group to remove from the global igmp_group_list - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t -igmp_remove_group(struct netif* netif, struct igmp_group *group) -{ - err_t err = ERR_OK; - struct igmp_group *tmp_group; - - /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ - for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) { - if (tmp_group->next == group) { - tmp_group->next = group->next; - break; - } - } - /* Group not found in the global igmp_group_list */ - if (tmp_group == NULL) { - err = ERR_ARG; - } - - return err; -} - -/** - * Called from ip_input() if a new IGMP packet is received. - * - * @param p received igmp packet, p->payload pointing to the igmp header - * @param inp network interface on which the packet was received - * @param dest destination ip address of the igmp packet - */ -void -igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) -{ - struct igmp_msg* igmp; - struct igmp_group* group; - struct igmp_group* groupref; - - IGMP_STATS_INC(igmp.recv); - - /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ - if (p->len < IGMP_MINLEN) { - pbuf_free(p); - IGMP_STATS_INC(igmp.lenerr); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n")); - return; - } - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from ")); - ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->src)); - LWIP_DEBUGF(IGMP_DEBUG, (" to address ")); - ip4_addr_debug_print(IGMP_DEBUG, &(ip4_current_header()->dest)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)inp)); - - /* Now calculate and check the checksum */ - igmp = (struct igmp_msg *)p->payload; - if (inet_chksum(igmp, p->len)) { - pbuf_free(p); - IGMP_STATS_INC(igmp.chkerr); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n")); - return; - } - - /* Packet is ok so find an existing group */ - group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */ - - /* If group can be found or create... */ - if (!group) { - pbuf_free(p); - IGMP_STATS_INC(igmp.drop); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n")); - return; - } - - /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ - switch (igmp->igmp_msgtype) { - case IGMP_MEMB_QUERY: - /* IGMP_MEMB_QUERY to the "all systems" address ? */ - if ((ip4_addr_cmp(dest, &allsystems)) && ip4_addr_isany(&igmp->igmp_group_address)) { - /* THIS IS THE GENERAL QUERY */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - - if (igmp->igmp_maxresp == 0) { - IGMP_STATS_INC(igmp.rx_v1); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n")); - igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR; - } else { - IGMP_STATS_INC(igmp.rx_general); - } - - groupref = netif_igmp_data(inp); - - /* Do not send messages on the all systems group address! */ - /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ - if(groupref != NULL) { - groupref = groupref->next; - } - - while (groupref) { - igmp_delaying_member(groupref, igmp->igmp_maxresp); - groupref = groupref->next; - } - } else { - /* IGMP_MEMB_QUERY to a specific group ? */ - if (!ip4_addr_isany(&igmp->igmp_group_address)) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group ")); - ip4_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address); - if (ip4_addr_cmp(dest, &allsystems)) { - ip4_addr_t groupaddr; - LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - /* we first need to re-look for the group since we used dest last time */ - ip4_addr_copy(groupaddr, igmp->igmp_group_address); - group = igmp_lookfor_group(inp, &groupaddr); - } else { - LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp))); - } - - if (group != NULL) { - IGMP_STATS_INC(igmp.rx_group); - igmp_delaying_member(group, igmp->igmp_maxresp); - } else { - IGMP_STATS_INC(igmp.drop); - } - } else { - IGMP_STATS_INC(igmp.proterr); - } - } - break; - case IGMP_V2_MEMB_REPORT: - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n")); - IGMP_STATS_INC(igmp.rx_report); - if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) { - /* This is on a specific group we have already looked up */ - group->timer = 0; /* stopped */ - group->group_state = IGMP_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - break; - default: - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n", - igmp->igmp_msgtype, group->group_state, (void*)&group, (void*)inp)); - IGMP_STATS_INC(igmp.proterr); - break; - } - - pbuf_free(p); - return; -} - -/** - * @ingroup igmp - * Join a group on one network interface. - * - * @param ifaddr ip address of the network interface which should join a new group - * @param groupaddr the ip address of the group which to join - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t -igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we join this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { - err = igmp_joingroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Return an error even if some network interfaces are joined */ - /** @todo undo any other netif already joined */ - return err; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup igmp - * Join a group on one network interface. - * - * @param netif the network interface which should join a new group - * @param groupaddr the ip address of the group which to join - * @return ERR_OK if group was joined on the netif, an err_t otherwise - */ -err_t -igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) -{ - struct igmp_group *group; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_joingroup_netif: attempt to join non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_joingroup_netif: attempt to join allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* make sure it is an igmp-enabled netif */ - LWIP_ERROR("igmp_joingroup_netif: attempt to join on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); - - /* find group or create a new one if not found */ - group = igmp_lookup_group(netif, groupaddr); - - if (group != NULL) { - /* This should create a new group, check the state to make sure */ - if (group->group_state != IGMP_GROUP_NON_MEMBER) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to group not in state IGMP_GROUP_NON_MEMBER\n")); - } else { - /* OK - it was new group */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: join to new group: ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* If first use of the group, allow the group at the MAC level */ - if ((group->use==0) && (netif->igmp_mac_filter != NULL)) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: igmp_mac_filter(ADD ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); - } - - IGMP_STATS_INC(igmp.tx_join); - igmp_send(netif, group, IGMP_V2_MEMB_REPORT); - - igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - - /* Need to work out where this timer comes from */ - group->group_state = IGMP_GROUP_DELAYING_MEMBER; - } - /* Increment group use */ - group->use++; - /* Join on this interface */ - return ERR_OK; - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup_netif: Not enough memory to join to group\n")); - return ERR_MEM; - } -} - -/** - * @ingroup igmp - * Leave a group on one network interface. - * - * @param ifaddr ip address of the network interface which should leave a group - * @param groupaddr the ip address of the group which to leave - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t -igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we leave this interface ? */ - if ((netif->flags & NETIF_FLAG_IGMP) && ((ip4_addr_isany(ifaddr) || ip4_addr_cmp(netif_ip4_addr(netif), ifaddr)))) { - err_t res = igmp_leavegroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Store this result if we have not yet gotten a success */ - err = res; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup igmp - * Leave a group on one network interface. - * - * @param netif the network interface which should leave a group - * @param groupaddr the ip address of the group which to leave - * @return ERR_OK if group was left on the netif, an err_t otherwise - */ -err_t -igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr) -{ - struct igmp_group *group; - - /* make sure it is multicast address */ - LWIP_ERROR("igmp_leavegroup_netif: attempt to leave non-multicast address", ip4_addr_ismulticast(groupaddr), return ERR_VAL;); - LWIP_ERROR("igmp_leavegroup_netif: attempt to leave allsystems address", (!ip4_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;); - - /* make sure it is an igmp-enabled netif */ - LWIP_ERROR("igmp_leavegroup_netif: attempt to leave on non-IGMP netif", netif->flags & NETIF_FLAG_IGMP, return ERR_VAL;); - - /* find group */ - group = igmp_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Only send a leave if the flag is set according to the state diagram */ - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: Leaving group: ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, ("\n")); - - /* If there is no other use of the group */ - if (group->use <= 1) { - /* Remove the group from the list */ - igmp_remove_group(netif, group); - - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: sending leaving group\n")); - IGMP_STATS_INC(igmp.tx_leave); - igmp_send(netif, group, IGMP_LEAVE_GROUP); - } - - /* Disable the group at the MAC level */ - if (netif->igmp_mac_filter != NULL) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: igmp_mac_filter(DEL ")); - ip4_addr_debug_print(IGMP_DEBUG, groupaddr); - LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", (void*)netif)); - netif->igmp_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); - } - - /* Free group struct */ - memp_free(MEMP_IGMP_GROUP, group); - } else { - /* Decrement group use */ - group->use--; - } - return ERR_OK; - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup_netif: not member of group\n")); - return ERR_VAL; - } -} - -/** - * The igmp timer function (both for NO_SYS=1 and =0) - * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). - */ -void -igmp_tmr(void) -{ - struct netif *netif = netif_list; - - while (netif != NULL) { - struct igmp_group *group = netif_igmp_data(netif); - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - igmp_timeout(netif, group); - } - } - group = group->next; - } - netif = netif->next; - } -} - -/** - * Called if a timeout for one group is reached. - * Sends a report for this group. - * - * @param group an igmp_group for which a timeout is reached - */ -static void -igmp_timeout(struct netif *netif, struct igmp_group *group) -{ - /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group - (unless it is the allsystems group) */ - if ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && - (!(ip4_addr_cmp(&(group->group_address), &allsystems)))) { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address ")); - ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); - LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif)); - - group->group_state = IGMP_GROUP_IDLE_MEMBER; - - IGMP_STATS_INC(igmp.tx_report); - igmp_send(netif, group, IGMP_V2_MEMB_REPORT); - } -} - -/** - * Start a timer for an igmp group - * - * @param group the igmp_group for which to start a timer - * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with - * every call to igmp_tmr()) - */ -static void -igmp_start_timer(struct igmp_group *group, u8_t max_time) -{ -#ifdef LWIP_RAND - group->timer = max_time > 2 ? (LWIP_RAND() % max_time) : 1; -#else /* LWIP_RAND */ - /* ATTENTION: use this only if absolutely necessary! */ - group->timer = max_time / 2; -#endif /* LWIP_RAND */ - - if (group->timer == 0) { - group->timer = 1; - } -} - -/** - * Delaying membership report for a group if necessary - * - * @param group the igmp_group for which "delaying" membership report - * @param maxresp query delay - */ -static void -igmp_delaying_member(struct igmp_group *group, u8_t maxresp) -{ - if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || - ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - igmp_start_timer(group, maxresp); - group->group_state = IGMP_GROUP_DELAYING_MEMBER; - } -} - - -/** - * Sends an IP packet on a network interface. This function constructs the IP header - * and calculates the IP header checksum. If the source IP address is NULL, - * the IP address of the outgoing network interface is filled in as source address. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IP/LINK headers - * returns errors returned by netif->output - */ -static err_t -igmp_ip_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, struct netif *netif) -{ - /* This is the "router alert" option */ - u16_t ra[2]; - ra[0] = PP_HTONS(ROUTER_ALERT); - ra[1] = 0x0000; /* Router shall examine packet */ - IGMP_STATS_INC(igmp.xmit); - return ip4_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN); -} - -/** - * Send an igmp packet to a specific group. - * - * @param group the group to which to send the packet - * @param type the type of igmp packet to send - */ -static void -igmp_send(struct netif *netif, struct igmp_group *group, u8_t type) -{ - struct pbuf* p = NULL; - struct igmp_msg* igmp = NULL; - ip4_addr_t src = *IP4_ADDR_ANY4; - ip4_addr_t* dest = NULL; - - /* IP header + "router alert" option + IGMP header */ - p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); - - if (p) { - igmp = (struct igmp_msg *)p->payload; - LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg", - (p->len >= sizeof(struct igmp_msg))); - ip4_addr_copy(src, *netif_ip4_addr(netif)); - - if (type == IGMP_V2_MEMB_REPORT) { - dest = &(group->group_address); - ip4_addr_copy(igmp->igmp_group_address, group->group_address); - group->last_reporter_flag = 1; /* Remember we were the last to report */ - } else { - if (type == IGMP_LEAVE_GROUP) { - dest = &allrouters; - ip4_addr_copy(igmp->igmp_group_address, group->group_address); - } - } - - if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) { - igmp->igmp_msgtype = type; - igmp->igmp_maxresp = 0; - igmp->igmp_checksum = 0; - igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN); - - igmp_ip_output_if(p, &src, dest, netif); - } - - pbuf_free(p); - } else { - LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n")); - IGMP_STATS_INC(igmp.memerr); - } -} - -#endif /* LWIP_IPV4 && LWIP_IGMP */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/ip4.c b/components/net/lwip-2.0.2/src/core/ipv4/ip4.c deleted file mode 100644 index 4e4eb61146..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/ip4.c +++ /dev/null @@ -1,1086 +0,0 @@ -/** - * @file - * This is the IPv4 layer implementation for incoming and outgoing IP traffic. - * - * @see ip_frag.c - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/ip4_frag.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/igmp.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/autoip.h" -#include "lwip/stats.h" -#include "lwip/prot/dhcp.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -/** Set this to 0 in the rare case of wanting to call an extra function to - * generate the IP checksum (in contrast to calculating it on-the-fly). */ -#ifndef LWIP_INLINE_IP_CHKSUM -#if LWIP_CHECKSUM_CTRL_PER_NETIF -#define LWIP_INLINE_IP_CHKSUM 0 -#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#define LWIP_INLINE_IP_CHKSUM 1 -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#endif - -#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP -#define CHECKSUM_GEN_IP_INLINE 1 -#else -#define CHECKSUM_GEN_IP_INLINE 0 -#endif - -#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) -#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 - -/** Some defines for DHCP to let link-layer-addressed packets through while the - * netif is down. - * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port) - * to return 1 if the port is accepted and 0 if the port is not accepted. - */ -#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) -/* accept DHCP client port and custom port */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \ - || (LWIP_IP_ACCEPT_UDP_PORT(port))) -#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ -/* accept custom port only */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) -#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ -/* accept DHCP client port only */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT)) -#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ - -#else /* LWIP_DHCP */ -#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 -#endif /* LWIP_DHCP */ - -/** The IP header ID of the next outgoing IP packet */ -static u16_t ip_id; - -#if LWIP_MULTICAST_TX_OPTIONS -/** The default netif used for multicast */ -static struct netif* ip4_default_multicast_netif; - -/** - * @ingroup ip4 - * Set a default netif for IPv4 multicast. */ -void -ip4_set_default_multicast_netif(struct netif* default_multicast_netif) -{ - ip4_default_multicast_netif = default_multicast_netif; -} -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#ifdef LWIP_HOOK_IP4_ROUTE_SRC -/** - * Source based IPv4 routing must be fully implemented in - * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides he parameters. - */ -struct netif * -ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src) -{ - if (src != NULL) { - /* when src==NULL, the hook is called from ip4_route(dest) */ - struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, src); - if (netif != NULL) { - return netif; - } - } - return ip4_route(dest); -} -#endif /* LWIP_HOOK_IP4_ROUTE_SRC */ - -/** - * Finds the appropriate network interface for a given IP address. It - * searches the list of network interfaces linearly. A match is found - * if the masked IP address of the network interface equals the masked - * IP address given to the function. - * - * @param dest the destination IP address for which to find the route - * @return the netif on which to send to reach dest - */ -struct netif * -ip4_route(const ip4_addr_t *dest) -{ - struct netif *netif; - -#if LWIP_MULTICAST_TX_OPTIONS - /* Use administratively selected interface for multicast by default */ - if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { - return ip4_default_multicast_netif; - } -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - - /* iterate through netifs */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - /* is the netif up, does it have a link and a valid address? */ - if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { - /* network mask matches? */ - if (ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))) { - /* return netif on which to forward IP packet */ - return netif; - } - /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ - if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && ip4_addr_cmp(dest, netif_ip4_gw(netif))) { - /* return netif on which to forward IP packet */ - return netif; - } - } - } - -#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - /* loopif is disabled, looopback traffic is passed through any netif */ - if (ip4_addr_isloopback(dest)) { - /* don't check for link on loopback traffic */ - if (netif_default != NULL && netif_is_up(netif_default)) { - return netif_default; - } - /* default netif is not up, just use any netif for loopback traffic */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (netif_is_up(netif)) { - return netif; - } - } - return NULL; - } -#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ - -#ifdef LWIP_HOOK_IP4_ROUTE_SRC - netif = LWIP_HOOK_IP4_ROUTE_SRC(dest, NULL); - if (netif != NULL) { - return netif; - } -#elif defined(LWIP_HOOK_IP4_ROUTE) - netif = LWIP_HOOK_IP4_ROUTE(dest); - if (netif != NULL) { - return netif; - } -#endif - - if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || - ip4_addr_isany_val(*netif_ip4_addr(netif_default))) { - /* No matching netif found and default netif is not usable. - If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - MIB2_STATS_INC(mib2.ipoutnoroutes); - return NULL; - } - - return netif_default; -} - -#if IP_FORWARD -/** - * Determine whether an IP address is in a reserved set of addresses - * that may not be forwarded, or whether datagrams to that destination - * may be forwarded. - * @param p the packet to forward - * @return 1: can forward 0: discard - */ -static int -ip4_canforward(struct pbuf *p) -{ - u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr())); - - if (p->flags & PBUF_FLAG_LLBCAST) { - /* don't route link-layer broadcasts */ - return 0; - } - if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) { - /* don't route link-layer multicasts unless the destination address is an IP - multicast address */ - return 0; - } - if (IP_EXPERIMENTAL(addr)) { - return 0; - } - if (IP_CLASSA(addr)) { - u32_t net = addr & IP_CLASSA_NET; - if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { - /* don't route loopback packets */ - return 0; - } - } - return 1; -} - -/** - * Forwards an IP packet. It finds an appropriate route for the - * packet, decrements the TTL value of the packet, adjusts the - * checksum and outputs the packet on the appropriate interface. - * - * @param p the packet to forward (p->payload points to IP header) - * @param iphdr the IP header of the input packet - * @param inp the netif on which this packet was received - */ -static void -ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) -{ - struct netif *netif; - - PERF_START; - LWIP_UNUSED_ARG(inp); - - if (!ip4_canforward(p)) { - goto return_noroute; - } - - /* RFC3927 2.7: do not forward link-local addresses */ - if (ip4_addr_islinklocal(ip4_current_dest_addr())) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), - ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); - goto return_noroute; - } - - /* Find network interface where to forward this IP packet to. */ - netif = ip4_route_src(ip4_current_dest_addr(), ip4_current_src_addr()); - if (netif == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", - ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), - ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); - /* @todo: send ICMP_DUR_NET? */ - goto return_noroute; - } -#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF - /* Do not forward packets onto the same network interface on which - * they arrived. */ - if (netif == inp) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: not bouncing packets back on incoming interface.\n")); - goto return_noroute; - } -#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ - - /* decrement TTL */ - IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); - /* send ICMP if TTL == 0 */ - if (IPH_TTL(iphdr) == 0) { - MIB2_STATS_INC(mib2.ipinhdrerrors); -#if LWIP_ICMP - /* Don't send ICMP messages in response to ICMP messages */ - if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { - icmp_time_exceeded(p, ICMP_TE_TTL); - } -#endif /* LWIP_ICMP */ - return; - } - - /* Incrementally update the IP checksum. */ - if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { - IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); - } else { - IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); - } - - LWIP_DEBUGF(IP_DEBUG, ("ip4_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(ip4_current_dest_addr()), ip4_addr2_16(ip4_current_dest_addr()), - ip4_addr3_16(ip4_current_dest_addr()), ip4_addr4_16(ip4_current_dest_addr()))); - - IP_STATS_INC(ip.fw); - MIB2_STATS_INC(mib2.ipforwdatagrams); - IP_STATS_INC(ip.xmit); - - PERF_STOP("ip4_forward"); - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > netif->mtu)) { - if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) { -#if IP_FRAG - ip4_frag(p, netif, ip4_current_dest_addr()); -#else /* IP_FRAG */ - /* @todo: send ICMP Destination Unreachable code 13 "Communication administratively prohibited"? */ -#endif /* IP_FRAG */ - } else { -#if LWIP_ICMP - /* send ICMP Destination Unreachable code 4: "Fragmentation Needed and DF Set" */ - icmp_dest_unreach(p, ICMP_DUR_FRAG); -#endif /* LWIP_ICMP */ - } - return; - } - /* transmit pbuf on chosen interface */ - netif->output(netif, p, ip4_current_dest_addr()); - return; -return_noroute: - MIB2_STATS_INC(mib2.ipoutnoroutes); -} -#endif /* IP_FORWARD */ - -/** - * This function is called by the network interface device driver when - * an IP packet is received. The function does the basic checks of the - * IP header such as packet size being at least larger than the header - * size etc. If the packet was not destined for us, the packet is - * forwarded (using ip_forward). The IP checksum is always checked. - * - * Finally, the packet is sent to the upper layer protocol input function. - * - * @param p the received IP packet (p->payload points to IP header) - * @param inp the netif on which this packet was received - * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't - * processed, but currently always returns ERR_OK) - */ -err_t -ip4_input(struct pbuf *p, struct netif *inp) -{ - struct ip_hdr *iphdr; - struct netif *netif; - u16_t iphdr_hlen; - u16_t iphdr_len; -#if IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP - int check_ip_src = 1; -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING || LWIP_IGMP */ - - IP_STATS_INC(ip.recv); - MIB2_STATS_INC(mib2.ipinreceives); - - /* identify the IP header */ - iphdr = (struct ip_hdr *)p->payload; - if (IPH_V(iphdr) != 4) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", (u16_t)IPH_V(iphdr))); - ip4_debug_print(p); - pbuf_free(p); - IP_STATS_INC(ip.err); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinhdrerrors); - return ERR_OK; - } - -#ifdef LWIP_HOOK_IP4_INPUT - if (LWIP_HOOK_IP4_INPUT(p, inp)) { - /* the packet has been eaten */ - return ERR_OK; - } -#endif - - /* obtain IP header length in number of 32-bit words */ - iphdr_hlen = IPH_HL(iphdr); - /* calculate IP header length in bytes */ - iphdr_hlen *= 4; - /* obtain ip length in bytes */ - iphdr_len = lwip_ntohs(IPH_LEN(iphdr)); - - /* Trim pbuf. This is especially required for packets < 60 bytes. */ - if (iphdr_len < p->tot_len) { - pbuf_realloc(p, iphdr_len); - } - - /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ - if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len) || (iphdr_hlen < IP_HLEN)) { - if (iphdr_hlen < IP_HLEN) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("ip4_input: short IP header (%"U16_F" bytes) received, IP packet dropped\n", iphdr_hlen)); - } - if (iphdr_hlen > p->len) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", - iphdr_hlen, p->len)); - } - if (iphdr_len > p->tot_len) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", - iphdr_len, p->tot_len)); - } - /* free (drop) packet pbufs */ - pbuf_free(p); - IP_STATS_INC(ip.lenerr); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipindiscards); - return ERR_OK; - } - - /* verify checksum */ -#if CHECKSUM_CHECK_IP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) { - if (inet_chksum(iphdr, iphdr_hlen) != 0) { - - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); - ip4_debug_print(p); - pbuf_free(p); - IP_STATS_INC(ip.chkerr); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinhdrerrors); - return ERR_OK; - } - } -#endif - - /* copy IP addresses to aligned ip_addr_t */ - ip_addr_copy_from_ip4(ip_data.current_iphdr_dest, iphdr->dest); - ip_addr_copy_from_ip4(ip_data.current_iphdr_src, iphdr->src); - - /* match packet against an interface, i.e. is this packet for us? */ - if (ip4_addr_ismulticast(ip4_current_dest_addr())) { -#if LWIP_IGMP - if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ip4_current_dest_addr()))) { - /* IGMP snooping switches need 0.0.0.0 to be allowed as source address (RFC 4541) */ - ip4_addr_t allsystems; - IP4_ADDR(&allsystems, 224, 0, 0, 1); - if (ip4_addr_cmp(ip4_current_dest_addr(), &allsystems) && - ip4_addr_isany(ip4_current_src_addr())) { - check_ip_src = 0; - } - netif = inp; - } else { - netif = NULL; - } -#else /* LWIP_IGMP */ - if ((netif_is_up(inp)) && (!ip4_addr_isany_val(*netif_ip4_addr(inp)))) { - netif = inp; - } else { - netif = NULL; - } -#endif /* LWIP_IGMP */ - } else { - /* start trying with inp. if that's not acceptable, start walking the - list of configured netifs. - 'first' is used as a boolean to mark whether we started walking the list */ - int first = 1; - netif = inp; - do { - LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", - ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(netif_ip4_addr(netif)), - ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(netif_ip4_netmask(netif)), - ip4_addr_get_u32(netif_ip4_addr(netif)) & ip4_addr_get_u32(netif_ip4_netmask(netif)), - ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(netif_ip4_netmask(netif)))); - - /* interface is up and configured? */ - if ((netif_is_up(netif)) && (!ip4_addr_isany_val(*netif_ip4_addr(netif)))) { - /* unicast to this interface address? */ - if (ip4_addr_cmp(ip4_current_dest_addr(), netif_ip4_addr(netif)) || - /* or broadcast on this interface network address? */ - ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) -#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - || (ip4_addr_get_u32(ip4_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK)) -#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ - ) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; - } -#if LWIP_AUTOIP - /* connections to link-local addresses must persist after changing - the netif's address (RFC3927 ch. 1.9) */ - if (autoip_accept_packet(netif, ip4_current_dest_addr())) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: LLA packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - /* break out of for loop */ - break; - } -#endif /* LWIP_AUTOIP */ - } - if (first) { -#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF - /* Packets sent to the loopback address must not be accepted on an - * interface that does not have the loopback address assigned to it, - * unless a non-loopback interface is used for loopback traffic. */ - if (ip4_addr_isloopback(ip4_current_dest_addr())) { - netif = NULL; - break; - } -#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ - first = 0; - netif = netif_list; - } else { - netif = netif->next; - } - if (netif == inp) { - netif = netif->next; - } - } while (netif != NULL); - } - -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed - * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. - * According to RFC 1542 section 3.1.1, referred by RFC 2131). - * - * If you want to accept private broadcast communication while a netif is down, - * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.: - * - * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345)) - */ - if (netif == NULL) { - /* remote port is DHCP server? */ - if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { - struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", - lwip_ntohs(udphdr->dest))); - if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); - netif = inp; - check_ip_src = 0; - } - } - } -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ -#if LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING - if (check_ip_src -#if IP_ACCEPT_LINK_LAYER_ADDRESSING - /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ - && !ip4_addr_isany_val(*ip4_current_src_addr()) -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - ) -#endif /* LWIP_IGMP || IP_ACCEPT_LINK_LAYER_ADDRESSING */ - { - if ((ip4_addr_isbroadcast(ip4_current_src_addr(), inp)) || - (ip4_addr_ismulticast(ip4_current_src_addr()))) { - /* packet source is not valid */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip4_input: packet source is not valid.\n")); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinaddrerrors); - MIB2_STATS_INC(mib2.ipindiscards); - return ERR_OK; - } - } - - /* packet not for us? */ - if (netif == NULL) { - /* packet not for us, route or discard */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: packet not for us.\n")); -#if IP_FORWARD - /* non-broadcast packet? */ - if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), inp)) { - /* try to forward IP packet on (other) interfaces */ - ip4_forward(p, iphdr, inp); - } else -#endif /* IP_FORWARD */ - { - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinaddrerrors); - MIB2_STATS_INC(mib2.ipindiscards); - } - pbuf_free(p); - return ERR_OK; - } - /* packet consists of multiple fragments? */ - if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { -#if IP_REASSEMBLY /* packet fragment reassembly code present? */ - LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", - lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); - /* reassemble the packet*/ - p = ip4_reass(p); - /* packet not fully reassembled yet? */ - if (p == NULL) { - return ERR_OK; - } - iphdr = (struct ip_hdr *)p->payload; -#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ - pbuf_free(p); - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", - lwip_ntohs(IPH_OFFSET(iphdr)))); - IP_STATS_INC(ip.opterr); - IP_STATS_INC(ip.drop); - /* unsupported protocol feature */ - MIB2_STATS_INC(mib2.ipinunknownprotos); - return ERR_OK; -#endif /* IP_REASSEMBLY */ - } - -#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ - -#if LWIP_IGMP - /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ - if ((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { -#else - if (iphdr_hlen > IP_HLEN) { -#endif /* LWIP_IGMP */ - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); - pbuf_free(p); - IP_STATS_INC(ip.opterr); - IP_STATS_INC(ip.drop); - /* unsupported protocol feature */ - MIB2_STATS_INC(mib2.ipinunknownprotos); - return ERR_OK; - } -#endif /* IP_OPTIONS_ALLOWED == 0 */ - - /* send to upper layers */ - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: \n")); - ip4_debug_print(p); - LWIP_DEBUGF(IP_DEBUG, ("ip4_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); - - ip_data.current_netif = netif; - ip_data.current_input_netif = inp; - ip_data.current_ip4_header = iphdr; - ip_data.current_ip_header_tot_len = IPH_HL(iphdr) * 4; - -#if LWIP_RAW - /* raw input did not eat the packet? */ - if (raw_input(p, inp) == 0) -#endif /* LWIP_RAW */ - { - pbuf_header(p, -(s16_t)iphdr_hlen); /* Move to payload, no check necessary. */ - - switch (IPH_PROTO(iphdr)) { -#if LWIP_UDP - case IP_PROTO_UDP: -#if LWIP_UDPLITE - case IP_PROTO_UDPLITE: -#endif /* LWIP_UDPLITE */ - MIB2_STATS_INC(mib2.ipindelivers); - udp_input(p, inp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case IP_PROTO_TCP: - MIB2_STATS_INC(mib2.ipindelivers); - tcp_input(p, inp); - break; -#endif /* LWIP_TCP */ -#if LWIP_ICMP - case IP_PROTO_ICMP: - MIB2_STATS_INC(mib2.ipindelivers); - icmp_input(p, inp); - break; -#endif /* LWIP_ICMP */ -#if LWIP_IGMP - case IP_PROTO_IGMP: - igmp_input(p, inp, ip4_current_dest_addr()); - break; -#endif /* LWIP_IGMP */ - default: -#if LWIP_ICMP - /* send ICMP destination protocol unreachable unless is was a broadcast */ - if (!ip4_addr_isbroadcast(ip4_current_dest_addr(), netif) && - !ip4_addr_ismulticast(ip4_current_dest_addr())) { - pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */ - p->payload = iphdr; - icmp_dest_unreach(p, ICMP_DUR_PROTO); - } -#endif /* LWIP_ICMP */ - pbuf_free(p); - - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", (u16_t)IPH_PROTO(iphdr))); - - IP_STATS_INC(ip.proterr); - IP_STATS_INC(ip.drop); - MIB2_STATS_INC(mib2.ipinunknownprotos); - } - } - - /* @todo: this is not really necessary... */ - ip_data.current_netif = NULL; - ip_data.current_input_netif = NULL; - ip_data.current_ip4_header = NULL; - ip_data.current_ip_header_tot_len = 0; - ip4_addr_set_any(ip4_current_src_addr()); - ip4_addr_set_any(ip4_current_dest_addr()); - - return ERR_OK; -} - -/** - * Sends an IP packet on a network interface. This function constructs - * the IP header and calculates the IP header checksum. If the source - * IP address is NULL, the IP address of the outgoing network - * interface is filled in as source address. - * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already - * include an IP header and p->payload points to it instead of the data. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IP/LINK headers - * returns errors returned by netif->output - * - * @note ip_id: RFC791 "some host may be able to simply use - * unique identifiers independent of destination" - */ -err_t -ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, - u8_t proto, struct netif *netif) -{ -#if IP_OPTIONS_SEND - return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); -} - -/** - * Same as ip_output_if() but with the possibility to include IP options: - * - * @ param ip_options pointer to the IP options, copied into the IP header - * @ param optlen length of ip_options - */ -err_t -ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen) -{ -#endif /* IP_OPTIONS_SEND */ - const ip4_addr_t *src_used = src; - if (dest != LWIP_IP_HDRINCL) { - if (ip4_addr_isany(src)) { - src_used = netif_ip4_addr(netif); - } - } - -#if IP_OPTIONS_SEND - return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif, - ip_options, optlen); -#else /* IP_OPTIONS_SEND */ - return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif); -#endif /* IP_OPTIONS_SEND */ -} - -/** - * Same as ip_output_if() but 'src' address is not replaced by netif address - * when it is 'any'. - */ -err_t -ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, - u8_t proto, struct netif *netif) -{ -#if IP_OPTIONS_SEND - return ip4_output_if_opt_src(p, src, dest, ttl, tos, proto, netif, NULL, 0); -} - -/** - * Same as ip_output_if_opt() but 'src' address is not replaced by netif address - * when it is 'any'. - */ -err_t -ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen) -{ -#endif /* IP_OPTIONS_SEND */ - struct ip_hdr *iphdr; - ip4_addr_t dest_addr; -#if CHECKSUM_GEN_IP_INLINE - u32_t chk_sum = 0; -#endif /* CHECKSUM_GEN_IP_INLINE */ - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - MIB2_STATS_INC(mib2.ipoutrequests); - - /* Should the IP header be generated or is it already included in p? */ - if (dest != LWIP_IP_HDRINCL) { - u16_t ip_hlen = IP_HLEN; -#if IP_OPTIONS_SEND - u16_t optlen_aligned = 0; - if (optlen != 0) { -#if CHECKSUM_GEN_IP_INLINE - int i; -#endif /* CHECKSUM_GEN_IP_INLINE */ - /* round up to a multiple of 4 */ - optlen_aligned = ((optlen + 3) & ~3); - ip_hlen += optlen_aligned; - /* First write in the IP options */ - if (pbuf_header(p, optlen_aligned)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output_if_opt: not enough room for IP options in pbuf\n")); - IP_STATS_INC(ip.err); - MIB2_STATS_INC(mib2.ipoutdiscards); - return ERR_BUF; - } - MEMCPY(p->payload, ip_options, optlen); - if (optlen < optlen_aligned) { - /* zero the remaining bytes */ - memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); - } -#if CHECKSUM_GEN_IP_INLINE - for (i = 0; i < optlen_aligned/2; i++) { - chk_sum += ((u16_t*)p->payload)[i]; - } -#endif /* CHECKSUM_GEN_IP_INLINE */ - } -#endif /* IP_OPTIONS_SEND */ - /* generate IP header */ - if (pbuf_header(p, IP_HLEN)) { - LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_output: not enough room for IP header in pbuf\n")); - - IP_STATS_INC(ip.err); - MIB2_STATS_INC(mib2.ipoutdiscards); - return ERR_BUF; - } - - iphdr = (struct ip_hdr *)p->payload; - LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", - (p->len >= sizeof(struct ip_hdr))); - - IPH_TTL_SET(iphdr, ttl); - IPH_PROTO_SET(iphdr, proto); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += PP_NTOHS(proto | (ttl << 8)); -#endif /* CHECKSUM_GEN_IP_INLINE */ - - /* dest cannot be NULL here */ - ip4_addr_copy(iphdr->dest, *dest); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF; - chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16; -#endif /* CHECKSUM_GEN_IP_INLINE */ - - IPH_VHL_SET(iphdr, 4, ip_hlen / 4); - IPH_TOS_SET(iphdr, tos); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8)); -#endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += iphdr->_len; -#endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_OFFSET_SET(iphdr, 0); - IPH_ID_SET(iphdr, lwip_htons(ip_id)); -#if CHECKSUM_GEN_IP_INLINE - chk_sum += iphdr->_id; -#endif /* CHECKSUM_GEN_IP_INLINE */ - ++ip_id; - - if (src == NULL) { - ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4); - } else { - /* src cannot be NULL here */ - ip4_addr_copy(iphdr->src, *src); - } - -#if CHECKSUM_GEN_IP_INLINE - chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF; - chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16; - chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF); - chk_sum = (chk_sum >> 16) + chk_sum; - chk_sum = ~chk_sum; - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - iphdr->_chksum = (u16_t)chk_sum; /* network order */ - } -#if LWIP_CHECKSUM_CTRL_PER_NETIF - else { - IPH_CHKSUM_SET(iphdr, 0); - } -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ -#else /* CHECKSUM_GEN_IP_INLINE */ - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); - } -#endif /* CHECKSUM_GEN_IP */ -#endif /* CHECKSUM_GEN_IP_INLINE */ - } else { - /* IP header already included in p */ - iphdr = (struct ip_hdr *)p->payload; - ip4_addr_copy(dest_addr, iphdr->dest); - dest = &dest_addr; - } - - IP_STATS_INC(ip.xmit); - - LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); - ip4_debug_print(p); - -#if ENABLE_LOOPBACK - if (ip4_addr_cmp(dest, netif_ip4_addr(netif)) -#if !LWIP_HAVE_LOOPIF - || ip4_addr_isloopback(dest) -#endif /* !LWIP_HAVE_LOOPIF */ - ) { - /* Packet to self, enqueue it for loopback */ - LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); - return netif_loop_output(netif, p); - } -#if LWIP_MULTICAST_TX_OPTIONS - if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { - netif_loop_output(netif, p); - } -#endif /* LWIP_MULTICAST_TX_OPTIONS */ -#endif /* ENABLE_LOOPBACK */ -#if IP_FRAG - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > netif->mtu)) { - return ip4_frag(p, netif, dest); - } -#endif /* IP_FRAG */ - - LWIP_DEBUGF(IP_DEBUG, ("ip4_output_if: call netif->output()\n")); - return netif->output(netif, p, dest); -} - -/** - * Simple interface to ip_output_if. It finds the outgoing network - * interface and calls upon ip_output_if to do the actual work. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto) -{ - struct netif *netif; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if ((netif = ip4_route_src(dest, src)) == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - return ERR_RTE; - } - - return ip4_output_if(p, src, dest, ttl, tos, proto, netif); -} - -#if LWIP_NETIF_HWADDRHINT -/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint - * before calling ip_output_if. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IP header and p->payload points to that IP header) - * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the - * IP address of the netif used to send is used as source address) - * @param dest the destination IP address to send the packet to - * @param ttl the TTL value to be set in the IP header - * @param tos the TOS value to be set in the IP header - * @param proto the PROTOCOL to be set in the IP header - * @param addr_hint address hint pointer set to netif->addr_hint before - * calling ip_output_if() - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) -{ - struct netif *netif; - err_t err; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if ((netif = ip4_route_src(dest, src)) == NULL) { - LWIP_DEBUGF(IP_DEBUG, ("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); - IP_STATS_INC(ip.rterr); - return ERR_RTE; - } - - NETIF_SET_HWADDRHINT(netif, addr_hint); - err = ip4_output_if(p, src, dest, ttl, tos, proto, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - return err; -} -#endif /* LWIP_NETIF_HWADDRHINT*/ - -#if IP_DEBUG -/* Print an IP header by using LWIP_DEBUGF - * @param p an IP packet, p->payload pointing to the IP header - */ -void -ip4_debug_print(struct pbuf *p) -{ - struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; - - LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", - (u16_t)IPH_V(iphdr), - (u16_t)IPH_HL(iphdr), - (u16_t)IPH_TOS(iphdr), - lwip_ntohs(IPH_LEN(iphdr)))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", - lwip_ntohs(IPH_ID(iphdr)), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), - (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", - (u16_t)IPH_TTL(iphdr), - (u16_t)IPH_PROTO(iphdr), - lwip_ntohs(IPH_CHKSUM(iphdr)))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", - ip4_addr1_16(&iphdr->src), - ip4_addr2_16(&iphdr->src), - ip4_addr3_16(&iphdr->src), - ip4_addr4_16(&iphdr->src))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", - ip4_addr1_16(&iphdr->dest), - ip4_addr2_16(&iphdr->dest), - ip4_addr3_16(&iphdr->dest), - ip4_addr4_16(&iphdr->dest))); - LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); -} -#endif /* IP_DEBUG */ - -#endif /* LWIP_IPV4 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/ip4_addr.c b/components/net/lwip-2.0.2/src/core/ipv4/ip4_addr.c deleted file mode 100644 index 2d479923bd..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/ip4_addr.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - * @file - * This is the IPv4 address tools implementation. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip_addr.h" -#include "lwip/netif.h" - -/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ -const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); -const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); - -/** - * Determine if an address is a broadcast address on a network interface - * - * @param addr address to be checked - * @param netif the network interface against which the address is checked - * @return returns non-zero if the address is a broadcast address - */ -u8_t -ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif) -{ - ip4_addr_t ipaddr; - ip4_addr_set_u32(&ipaddr, addr); - - /* all ones (broadcast) or all zeroes (old skool broadcast) */ - if ((~addr == IPADDR_ANY) || - (addr == IPADDR_ANY)) { - return 1; - /* no broadcast support on this network interface? */ - } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) { - /* the given address cannot be a broadcast address - * nor can we check against any broadcast addresses */ - return 0; - /* address matches network interface address exactly? => no broadcast */ - } else if (addr == ip4_addr_get_u32(netif_ip4_addr(netif))) { - return 0; - /* on the same (sub) network... */ - } else if (ip4_addr_netcmp(&ipaddr, netif_ip4_addr(netif), netif_ip4_netmask(netif)) - /* ...and host identifier bits are all ones? =>... */ - && ((addr & ~ip4_addr_get_u32(netif_ip4_netmask(netif))) == - (IPADDR_BROADCAST & ~ip4_addr_get_u32(netif_ip4_netmask(netif))))) { - /* => network broadcast address */ - return 1; - } else { - return 0; - } -} - -/** Checks if a netmask is valid (starting with ones, then only zeros) - * - * @param netmask the IPv4 netmask to check (in network byte order!) - * @return 1 if the netmask is valid, 0 if it is not - */ -u8_t -ip4_addr_netmask_valid(u32_t netmask) -{ - u32_t mask; - u32_t nm_hostorder = lwip_htonl(netmask); - - /* first, check for the first zero */ - for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { - if ((nm_hostorder & mask) == 0) { - break; - } - } - /* then check that there is no one */ - for (; mask != 0; mask >>= 1) { - if ((nm_hostorder & mask) != 0) { - /* there is a one after the first zero -> invalid */ - return 0; - } - } - /* no one after the first zero -> valid */ - return 1; -} - -/* Here for now until needed in other places in lwIP */ -#ifndef isprint -#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) -#define isprint(c) in_range(c, 0x20, 0x7f) -#define isdigit(c) in_range(c, '0', '9') -#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) -#define islower(c) in_range(c, 'a', 'z') -#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') -#endif - -/** - * Ascii internet address interpretation routine. - * The value returned is in network order. - * - * @param cp IP address in ascii representation (e.g. "127.0.0.1") - * @return ip address in network order - */ -u32_t -ipaddr_addr(const char *cp) -{ - ip4_addr_t val; - - if (ip4addr_aton(cp, &val)) { - return ip4_addr_get_u32(&val); - } - return (IPADDR_NONE); -} - -/** - * Check whether "cp" is a valid ascii representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - * - * @param cp IP address in ascii representation (e.g. "127.0.0.1") - * @param addr pointer to which to save the ip address in network order - * @return 1 if cp could be converted to addr, 0 on failure - */ -int -ip4addr_aton(const char *cp, ip4_addr_t *addr) -{ - u32_t val; - u8_t base; - char c; - u32_t parts[4]; - u32_t *pp = parts; - - c = *cp; - for (;;) { - /* - * Collect number up to ``.''. - * Values are specified as for C: - * 0x=hex, 0=octal, 1-9=decimal. - */ - if (!isdigit(c)) { - return 0; - } - val = 0; - base = 10; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') { - base = 16; - c = *++cp; - } else { - base = 8; - } - } - for (;;) { - if (isdigit(c)) { - val = (val * base) + (u32_t)(c - '0'); - c = *++cp; - } else if (base == 16 && isxdigit(c)) { - val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A')); - c = *++cp; - } else { - break; - } - } - if (c == '.') { - /* - * Internet format: - * a.b.c.d - * a.b.c (with c treated as 16 bits) - * a.b (with b treated as 24 bits) - */ - if (pp >= parts + 3) { - return 0; - } - *pp++ = val; - c = *++cp; - } else { - break; - } - } - /* - * Check for trailing characters. - */ - if (c != '\0' && !isspace(c)) { - return 0; - } - /* - * Concoct the address according to - * the number of parts specified. - */ - switch (pp - parts + 1) { - - case 0: - return 0; /* initial nondigit */ - - case 1: /* a -- 32 bits */ - break; - - case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffffUL) { - return 0; - } - if (parts[0] > 0xff) { - return 0; - } - val |= parts[0] << 24; - break; - - case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) { - return 0; - } - if ((parts[0] > 0xff) || (parts[1] > 0xff)) { - return 0; - } - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) { - return 0; - } - if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) { - return 0; - } - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - default: - LWIP_ASSERT("unhandled", 0); - break; - } - if (addr) { - ip4_addr_set_u32(addr, lwip_htonl(val)); - } - return 1; -} - -/** - * Convert numeric IP address into decimal dotted ASCII representation. - * returns ptr to static buffer; not reentrant! - * - * @param addr ip address in network order to convert - * @return pointer to a global static (!) buffer that holds the ASCII - * representation of addr - */ -char* -ip4addr_ntoa(const ip4_addr_t *addr) -{ - static char str[IP4ADDR_STRLEN_MAX]; - return ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX); -} - -/** - * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. - * - * @param addr ip address in network order to convert - * @param buf target buffer where the string is stored - * @param buflen length of buf - * @return either pointer to buf which now holds the ASCII - * representation of addr or NULL if buf was too small - */ -char* -ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) -{ - u32_t s_addr; - char inv[3]; - char *rp; - u8_t *ap; - u8_t rem; - u8_t n; - u8_t i; - int len = 0; - - s_addr = ip4_addr_get_u32(addr); - - rp = buf; - ap = (u8_t *)&s_addr; - for (n = 0; n < 4; n++) { - i = 0; - do { - rem = *ap % (u8_t)10; - *ap /= (u8_t)10; - inv[i++] = (char)('0' + rem); - } while (*ap); - while (i--) { - if (len++ >= buflen) { - return NULL; - } - *rp++ = inv[i]; - } - if (len++ >= buflen) { - return NULL; - } - *rp++ = '.'; - ap++; - } - *--rp = 0; - return buf; -} - -#endif /* LWIP_IPV4 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv4/ip4_frag.c b/components/net/lwip-2.0.2/src/core/ipv4/ip4_frag.c deleted file mode 100644 index 57fb44cbb3..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv4/ip4_frag.c +++ /dev/null @@ -1,831 +0,0 @@ -/** - * @file - * This is the IPv4 packet segmentation and reassembly implementation. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jani Monoses - * Simon Goldschmidt - * original reassembly code by Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/ip4_frag.h" -#include "lwip/def.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/stats.h" -#include "lwip/icmp.h" - -#include - -#if IP_REASSEMBLY -/** - * The IP reassembly code currently has the following limitations: - * - IP header options are not supported - * - fragments must not overlap (e.g. due to different routes), - * currently, overlapping or duplicate fragments are thrown away - * if IP_REASS_CHECK_OVERLAP=1 (the default)! - * - * @todo: work with IP header options - */ - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IP header, since it replaces - * the IP header in memory in incoming fragments (after copying it) to keep - * track of the various fragments. (-> If the IP header doesn't need packing, - * this struct doesn't need packing, too.) - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ - (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ - ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ - IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 - -/* global variables */ -static struct ip_reassdata *reassdatagrams; -static u16_t ip_reass_pbufcount; - -/* function prototypes */ -static void ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); -static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev); - -/** - * Reassembly timer base function - * for both NO_SYS == 0 and 1 (!). - * - * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). - */ -void -ip_reass_tmr(void) -{ - struct ip_reassdata *r, *prev = NULL; - - r = reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)r->timer)); - prev = r; - r = r->next; - } else { - /* reassembly timed out */ - struct ip_reassdata *tmp; - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer timed out\n")); - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip_reass_free_complete_datagram(tmp, prev); - } - } -} - -/** - * Free a datagram (struct ip_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip_reass_pbufcount), - * SNMP counters and sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - * @param prev the previous datagram in the linked list - * @return the number of pbufs freed - */ -static int -ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - u16_t pbufs_freed = 0; - u16_t clen; - struct pbuf *p; - struct ip_reass_helper *iprh; - - LWIP_ASSERT("prev != ipr", prev != ipr); - if (prev != NULL) { - LWIP_ASSERT("prev->next == ipr", prev->next == ipr); - } - - MIB2_STATS_INC(mib2.ipreasmfails); -#if LWIP_ICMP - iprh = (struct ip_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, copy the original header into it. */ - SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN); - icmp_time_exceeded(p, ICMP_TE_FRAG); - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - /* Then, unchain the struct ip_reassdata from the list and free it. */ - ip_reass_dequeue_datagram(ipr, prev); - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed); - ip_reass_pbufcount -= pbufs_freed; - - return pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram 'fraghdr' belongs to is not freed! - * - * @param fraghdr IP header of the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - * @return the number of pbufs freed - */ -static int -ip_reass_remove_oldest_datagram(struct ip_hdr *fraghdr, int pbufs_needed) -{ - /* @todo Can't we simply remove the last datagram in the - * linked list behind reassdatagrams? - */ - struct ip_reassdata *r, *oldest, *prev, *oldest_prev; - int pbufs_freed = 0, pbufs_freed_current; - int other_datagrams; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the datagram that 'fraghdr' belongs to! */ - do { - oldest = NULL; - prev = NULL; - oldest_prev = NULL; - other_datagrams = 0; - r = reassdatagrams; - while (r != NULL) { - if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { - /* Not the same datagram as fraghdr */ - other_datagrams++; - if (oldest == NULL) { - oldest = r; - oldest_prev = prev; - } else if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - oldest_prev = prev; - } - } - if (r->next != NULL) { - prev = r; - } - r = r->next; - } - if (oldest != NULL) { - pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); - pbufs_freed += pbufs_freed_current; - } - } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); - return pbufs_freed; -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Enqueues a new fragment into the fragment queue - * @param fraghdr points to the new fragments IP hdr - * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) - * @return A pointer to the queue location into which the fragment was enqueued - */ -static struct ip_reassdata* -ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) -{ - struct ip_reassdata* ipr; -#if ! IP_REASS_FREE_OLDEST - LWIP_UNUSED_ARG(clen); -#endif - - /* No matching previous fragment found, allocate a new reassdata struct */ - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { - ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA); - } - if (ipr == NULL) -#endif /* IP_REASS_FREE_OLDEST */ - { - IPFRAG_STATS_INC(ip_frag.memerr); - LWIP_DEBUGF(IP_REASS_DEBUG,("Failed to alloc reassdata struct\n")); - return NULL; - } - } - memset(ipr, 0, sizeof(struct ip_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = reassdatagrams; - reassdatagrams = ipr; - /* copy the ip header for later tests and input */ - /* @todo: no ip options supported? */ - SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN); - return ipr; -} - -/** - * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. - * @param ipr points to the queue entry to dequeue - */ -static void -ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) -{ - /* dequeue the reass struct */ - if (reassdatagrams == ipr) { - /* it was the first in the list */ - reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", prev != NULL); - prev->next = ipr->next; - } - - /* now we can free the ip_reassdata struct */ - memp_free(MEMP_REASSDATA, ipr); -} - -/** - * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list - * will grow over time as new pbufs are rx. - * Also checks that the datagram passes basic continuity checks (if the last - * fragment was received at least once). - * @param ipr points to the reassembly state - * @param new_p points to the pbuf for the current fragment - * @return 0 if invalid, >0 otherwise - */ -static int -ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p) -{ - struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct pbuf *q; - u16_t offset, len; - struct ip_hdr *fraghdr; - int valid = 1; - - /* Extract length and fragment offset from current fragment */ - fraghdr = (struct ip_hdr*)new_p->payload; - len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - - /* overwrite the fragment's ip header from the pbuf with our helper struct, - * and setup the embedded helper structure. */ - /* make sure the struct ip_reass_helper fits into the IP header */ - LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", - sizeof(struct ip_reass_helper) <= IP_HLEN); - iprh = (struct ip_reass_helper*)new_p->payload; - iprh->next_pbuf = NULL; - iprh->start = offset; - iprh->end = offset + len; - - /* Iterate through until we either get to the end of the list (append), - * or we find one with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ -#if IP_REASS_CHECK_OVERLAP - if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { - /* fragment overlaps with previous or following, throw away */ - goto freepbuf; - } -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - } else { - /* fragment with the lowest offset */ - ipr->p = new_p; - } - break; - } else if (iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - goto freepbuf; -#if IP_REASS_CHECK_OVERLAP - } else if (iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - goto freepbuf; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no holes. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = new_p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = new_p; - } - } - - /* At this point, the validation part begins: */ - /* If we already received the last fragment */ - if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) { - /* and had no holes so far */ - if (valid) { - /* then check if the rest of the fragments is here */ - /* Check if the queue starts with the first datagram */ - if ((ipr->p == NULL) || (((struct ip_reass_helper*)ipr->p->payload)->start != 0)) { - valid = 0; - } else { - /* and check that there are no holes after this datagram */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while (q != NULL) { - iprh = (struct ip_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - /* if still valid, all fragments are received - * (because to the MF==0 already arrived */ - if (valid) { - LWIP_ASSERT("sanity check", ipr->p != NULL); - LWIP_ASSERT("sanity check", - ((struct ip_reass_helper*)ipr->p->payload) != iprh); - LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", - iprh->next_pbuf == NULL); - LWIP_ASSERT("validate_datagram:datagram end!=datagram len", - iprh->end == ipr->datagram_len); - } - } - } - /* If valid is 0 here, there are some fragments missing in the middle - * (since MF == 0 has already arrived). Such datagrams simply time out if - * no more fragments are received... */ - return valid; - } - /* If we come here, not all fragments were received, yet! */ - return 0; /* not yet valid! */ -#if IP_REASS_CHECK_OVERLAP -freepbuf: - ip_reass_pbufcount -= pbuf_clen(new_p); - pbuf_free(new_p); - return 0; -#endif /* IP_REASS_CHECK_OVERLAP */ -} - -/** - * Reassembles incoming IP fragments into an IP datagram. - * - * @param p points to a pbuf chain of the fragment - * @return NULL if reassembly is incomplete, ? otherwise - */ -struct pbuf * -ip4_reass(struct pbuf *p) -{ - struct pbuf *r; - struct ip_hdr *fraghdr; - struct ip_reassdata *ipr; - struct ip_reass_helper *iprh; - u16_t offset, len, clen; - - IPFRAG_STATS_INC(ip_frag.recv); - MIB2_STATS_INC(mib2.ipreasmreqds); - - fraghdr = (struct ip_hdr*)p->payload; - - if ((IPH_HL(fraghdr) * 4) != IP_HLEN) { - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n")); - IPFRAG_STATS_INC(ip_frag.err); - goto nullreturn; - } - - offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - - /* Check if we are allowed to enqueue more datagrams. */ - clen = pbuf_clen(p); - if ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || - ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) -#endif /* IP_REASS_FREE_OLDEST */ - { - /* No datagram could be freed and still too many pbufs enqueued */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", - ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); - IPFRAG_STATS_INC(ip_frag.memerr); - /* @todo: send ICMP time exceeded here? */ - /* drop this pbuf */ - goto nullreturn; - } - } - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { - LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", - lwip_ntohs(IPH_ID(fraghdr)))); - IPFRAG_STATS_INC(ip_frag.cachehit); - break; - } - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = ip_reass_enqueue_new_datagram(fraghdr, clen); - /* Bail if unable to enqueue */ - if (ipr == NULL) { - goto nullreturn; - } - } else { - if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && - ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { - /* ipr->iphdr is not the header from the first fragment, but fraghdr is - * -> copy fraghdr into ipr->iphdr since we want to have the header - * of the first fragment (for ICMP time exceeded and later, for copying - * all options, if supported)*/ - SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN); - } - } - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time */ - ip_reass_pbufcount += clen; - - /* At this point, we have either created a new entry or pointing - * to an existing one */ - - /* check for 'no more fragments', and update queue entry*/ - if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) { - ipr->flags |= IP_REASS_FLAG_LASTFRAG; - ipr->datagram_len = offset + len; - LWIP_DEBUGF(IP_REASS_DEBUG, - ("ip4_reass: last fragment seen, total len %"S16_F"\n", - ipr->datagram_len)); - } - /* find the right place to insert this pbuf */ - /* @todo: trim pbufs if fragments are overlapping */ - if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) { - struct ip_reassdata *ipr_prev; - /* the totally last fragment (flag more fragments = 0) was received at least - * once AND all fragments are received */ - ipr->datagram_len += IP_HLEN; - - /* save the second pbuf before copying the header over the pointer */ - r = ((struct ip_reass_helper*)ipr->p->payload)->next_pbuf; - - /* copy the original ip header back to the first pbuf */ - fraghdr = (struct ip_hdr*)(ipr->p->payload); - SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); - IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len)); - IPH_OFFSET_SET(fraghdr, 0); - IPH_CHKSUM_SET(fraghdr, 0); - /* @todo: do we need to set/calculate the correct checksum? */ -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); - } -#endif /* CHECKSUM_GEN_IP */ - - p = ipr->p; - - /* chain together the pbufs contained within the reass_data list. */ - while (r != NULL) { - iprh = (struct ip_reass_helper*)r->payload; - - /* hide the ip header for every succeeding fragment */ - pbuf_header(r, -IP_HLEN); - pbuf_cat(p, r); - r = iprh->next_pbuf; - } - - /* find the previous entry in the linked list */ - if (ipr == reassdatagrams) { - ipr_prev = NULL; - } else { - for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } - - /* release the sources allocate for the fragment queue entry */ - ip_reass_dequeue_datagram(ipr, ipr_prev); - - /* and adjust the number of pbufs currently queued for reassembly. */ - ip_reass_pbufcount -= pbuf_clen(p); - - MIB2_STATS_INC(mib2.ipreasmoks); - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass_pbufcount: %d out\n", ip_reass_pbufcount)); - return NULL; - -nullreturn: - LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n")); - IPFRAG_STATS_INC(ip_frag.drop); - pbuf_free(p); - return NULL; -} -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if !LWIP_NETIF_TX_SINGLE_PBUF -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* -ip_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void -ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void -ipfrag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip_frag_free_pbuf_custom_ref(pcr); -} -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ - -/** - * Fragment an IP datagram if too large for the netif. - * - * Chop the datagram in MTU sized chunks and send them in order - * by pointing PBUF_REFs into p. - * - * @param p ip packet to send - * @param netif the netif on which to send - * @param dest destination ip address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t -ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) -{ - struct pbuf *rambuf; -#if !LWIP_NETIF_TX_SINGLE_PBUF - struct pbuf *newpbuf; - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif - struct ip_hdr *original_iphdr; - struct ip_hdr *iphdr; - const u16_t nfb = (netif->mtu - IP_HLEN) / 8; - u16_t left, fragsize; - u16_t ofo; - int last; - u16_t poff = IP_HLEN; - u16_t tmp; - - original_iphdr = (struct ip_hdr *)p->payload; - iphdr = original_iphdr; - LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL); - - /* Save original offset */ - tmp = lwip_ntohs(IPH_OFFSET(iphdr)); - ofo = tmp & IP_OFFMASK; - LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL); - - left = p->tot_len - IP_HLEN; - - while (left) { - /* Fill this fragment */ - fragsize = LWIP_MIN(left, nfb * 8); - -#if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM); - if (rambuf == NULL) { - goto memerr; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); - /* make room for the IP header */ - if (pbuf_header(rambuf, IP_HLEN)) { - pbuf_free(rambuf); - goto memerr; - } - /* fill in the IP header */ - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr*)rambuf->payload; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link and IP header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM); - if (rambuf == NULL) { - goto memerr; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP_HLEN))); - SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); - iphdr = (struct ip_hdr *)rambuf->payload; - - left_to_copy = fragsize; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - u16_t plen = p->len - poff; - newpbuflen = LWIP_MIN(left_to_copy, plen); - /* Is this pbuf already empty? */ - if (!newpbuflen) { - poff = 0; - p = p->next; - continue; - } - pcr = ip_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - goto memerr; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, - (u8_t*)p->payload + poff, newpbuflen); - if (newpbuf == NULL) { - ip_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - goto memerr; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ipfrag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - poff = 0; - p = p->next; - } - } - poff += newpbuflen; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - /* Correct header */ - last = (left <= netif->mtu - IP_HLEN); - - /* Set new offset and MF flag */ - tmp = (IP_OFFMASK & (ofo)); - if (!last) { - tmp = tmp | IP_MF; - } - IPH_OFFSET_SET(iphdr, lwip_htons(tmp)); - IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN)); - IPH_CHKSUM_SET(iphdr, 0); -#if CHECKSUM_GEN_IP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); - } -#endif /* CHECKSUM_GEN_IP */ - - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - netif->output(netif, rambuf, dest); - IPFRAG_STATS_INC(ip_frag.xmit); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); - left -= fragsize; - ofo += nfb; - } - MIB2_STATS_INC(mib2.ipfragoks); - return ERR_OK; -memerr: - MIB2_STATS_INC(mib2.ipfragfails); - return ERR_MEM; -} -#endif /* IP_FRAG */ - -#endif /* LWIP_IPV4 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/dhcp6.c b/components/net/lwip-2.0.2/src/core/ipv6/dhcp6.c deleted file mode 100644 index f27a725e3a..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/dhcp6.c +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file - * - * DHCPv6. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/def.h" - - -#endif /* LWIP_IPV6 && LWIP_IPV6_DHCP6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/ethip6.c b/components/net/lwip-2.0.2/src/core/ipv6/ethip6.c deleted file mode 100644 index 8f9a91b5f7..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/ethip6.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * - * Ethernet output for IPv6. Uses ND tables for link-layer addressing. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_ETHERNET - -#include "lwip/ethip6.h" -#include "lwip/nd6.h" -#include "lwip/pbuf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp6.h" -#include "lwip/prot/ethernet.h" -#include "netif/ethernet.h" - -#include - -/** - * Resolve and fill-in Ethernet address header for outgoing IPv6 packet. - * - * For IPv6 multicast, corresponding Ethernet addresses - * are selected and the packet is transmitted on the link. - * - * For unicast addresses, ask the ND6 module what to do. It will either let us - * send the the packet right away, or queue the packet for later itself, unless - * an error occurs. - * - * @todo anycast addresses - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The IP address of the packet destination. - * - * @return - * - ERR_OK or the return value of @ref nd6_get_next_hop_addr_or_queue. - */ -err_t -ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) -{ - struct eth_addr dest; - const u8_t *hwaddr; - err_t result; - - /* multicast destination IP address? */ - if (ip6_addr_ismulticast(ip6addr)) { - /* Hash IP multicast address to MAC address.*/ - dest.addr[0] = 0x33; - dest.addr[1] = 0x33; - dest.addr[2] = ((const u8_t *)(&(ip6addr->addr[3])))[0]; - dest.addr[3] = ((const u8_t *)(&(ip6addr->addr[3])))[1]; - dest.addr[4] = ((const u8_t *)(&(ip6addr->addr[3])))[2]; - dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; - - /* Send out. */ - return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); - } - - /* We have a unicast destination IP address */ - /* @todo anycast? */ - - /* Ask ND6 what to do with the packet. */ - result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); - if (result != ERR_OK) { - return result; - } - - /* If no hardware address is returned, nd6 has queued the packet for later. */ - if (hwaddr == NULL) { - return ERR_OK; - } - - /* Send out the packet using the returned hardware address. */ - SMEMCPY(dest.addr, hwaddr, 6); - return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); -} - -#endif /* LWIP_IPV6 && LWIP_ETHERNET */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/icmp6.c b/components/net/lwip-2.0.2/src/core/ipv6/icmp6.c deleted file mode 100644 index 323b69a2ab..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/icmp6.c +++ /dev/null @@ -1,350 +0,0 @@ -/** - * @file - * - * IPv6 version of ICMP, as per RFC 4443. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp6.h" -#include "lwip/prot/icmp6.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/ip.h" -#include "lwip/stats.h" - -#include - -#ifndef LWIP_ICMP6_DATASIZE -#define LWIP_ICMP6_DATASIZE 8 -#endif -#if LWIP_ICMP6_DATASIZE == 0 -#define LWIP_ICMP6_DATASIZE 8 -#endif - -/* Forward declarations */ -static void icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type); - - -/** - * Process an input ICMPv6 message. Called by ip6_input. - * - * Will generate a reply for echo requests. Other messages are forwarded - * to nd6_input, or mld6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -icmp6_input(struct pbuf *p, struct netif *inp) -{ - struct icmp6_hdr *icmp6hdr; - struct pbuf *r; - const ip6_addr_t *reply_src; - - ICMP6_STATS_INC(icmp6.recv); - - /* Check that ICMPv6 header fits in payload */ - if (p->len < sizeof(struct icmp6_hdr)) { - /* drop short packets */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.lenerr); - ICMP6_STATS_INC(icmp6.drop); - return; - } - - icmp6hdr = (struct icmp6_hdr *)p->payload; - -#if CHECKSUM_CHECK_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { - if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(), - ip6_current_dest_addr()) != 0) { - /* Checksum failed */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.chkerr); - ICMP6_STATS_INC(icmp6.drop); - return; - } - } -#endif /* CHECKSUM_CHECK_ICMP6 */ - - switch (icmp6hdr->type) { - case ICMP6_TYPE_NA: /* Neighbor advertisement */ - case ICMP6_TYPE_NS: /* Neighbor solicitation */ - case ICMP6_TYPE_RA: /* Router advertisement */ - case ICMP6_TYPE_RD: /* Redirect */ - case ICMP6_TYPE_PTB: /* Packet too big */ - nd6_input(p, inp); - return; - break; - case ICMP6_TYPE_RS: -#if LWIP_IPV6_FORWARD - /* @todo implement router functionality */ -#endif - break; -#if LWIP_IPV6_MLD - case ICMP6_TYPE_MLQ: - case ICMP6_TYPE_MLR: - case ICMP6_TYPE_MLD: - mld6_input(p, inp); - return; - break; -#endif - case ICMP6_TYPE_EREQ: -#if !LWIP_MULTICAST_PING - /* multicast destination address? */ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* drop */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.drop); - return; - } -#endif /* LWIP_MULTICAST_PING */ - - /* Allocate reply. */ - r = pbuf_alloc(PBUF_IP, p->tot_len, PBUF_RAM); - if (r == NULL) { - /* drop */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.memerr); - return; - } - - /* Copy echo request. */ - if (pbuf_copy(r, p) != ERR_OK) { - /* drop */ - pbuf_free(p); - pbuf_free(r); - ICMP6_STATS_INC(icmp6.err); - return; - } - - /* Determine reply source IPv6 address. */ -#if LWIP_MULTICAST_PING - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - reply_src = ip_2_ip6(ip6_select_source_address(inp, ip6_current_src_addr())); - if (reply_src == NULL) { - /* drop */ - pbuf_free(p); - pbuf_free(r); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - else -#endif /* LWIP_MULTICAST_PING */ - { - reply_src = ip6_current_dest_addr(); - } - - /* Set fields in reply. */ - ((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP; - ((struct icmp6_echo_hdr *)(r->payload))->chksum = 0; -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) { - ((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r, - IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr()); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send reply. */ - ICMP6_STATS_INC(icmp6.xmit); - ip6_output_if(r, reply_src, ip6_current_src_addr(), - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, inp); - pbuf_free(r); - - break; - default: - ICMP6_STATS_INC(icmp6.proterr); - ICMP6_STATS_INC(icmp6.drop); - break; - } - - pbuf_free(p); -} - - -/** - * Send an icmpv6 'destination unreachable' packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IPv6 header - * @param c ICMPv6 code for the unreachable type - */ -void -icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c) -{ - icmp6_send_response(p, c, 0, ICMP6_TYPE_DUR); -} - -/** - * Send an icmpv6 'packet too big' packet. - * - * @param p the input packet for which the 'packet too big' should be sent, - * p->payload pointing to the IPv6 header - * @param mtu the maximum mtu that we can accept - */ -void -icmp6_packet_too_big(struct pbuf *p, u32_t mtu) -{ - icmp6_send_response(p, 0, mtu, ICMP6_TYPE_PTB); -} - -/** - * Send an icmpv6 'time exceeded' packet. - * - * @param p the input packet for which the 'unreachable' should be sent, - * p->payload pointing to the IPv6 header - * @param c ICMPv6 code for the time exceeded type - */ -void -icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c) -{ - icmp6_send_response(p, c, 0, ICMP6_TYPE_TE); -} - -/** - * Send an icmpv6 'parameter problem' packet. - * - * @param p the input packet for which the 'param problem' should be sent, - * p->payload pointing to the IP header - * @param c ICMPv6 code for the param problem type - * @param pointer the pointer to the byte where the parameter is found - */ -void -icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer) -{ - icmp6_send_response(p, c, pointer, ICMP6_TYPE_PP); -} - -/** - * Send an ICMPv6 packet in response to an incoming packet. - * - * @param p the input packet for which the response should be sent, - * p->payload pointing to the IPv6 header - * @param code Code of the ICMPv6 header - * @param data Additional 32-bit parameter in the ICMPv6 header - * @param type Type of the ICMPv6 header - */ -static void -icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type) -{ - struct pbuf *q; - struct icmp6_hdr *icmp6hdr; - const ip6_addr_t *reply_src; - ip6_addr_t *reply_dest; - ip6_addr_t reply_src_local, reply_dest_local; - struct ip6_hdr *ip6hdr; - struct netif *netif; - - /* ICMPv6 header + IPv6 header + data */ - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); - ICMP6_STATS_INC(icmp6.memerr); - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", - (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); - - icmp6hdr = (struct icmp6_hdr *)q->payload; - icmp6hdr->type = type; - icmp6hdr->code = code; - icmp6hdr->data = data; - - /* copy fields from original packet */ - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); - - /* Get the destination address and netif for this ICMP message. */ - if ((ip_current_netif() == NULL) || - ((code == ICMP6_TE_FRAG) && (type == ICMP6_TYPE_TE))) { - /* Special case, as ip6_current_xxx is either NULL, or points - * to a different packet than the one that expired. - * We must use the addresses that are stored in the expired packet. */ - ip6hdr = (struct ip6_hdr *)p->payload; - /* copy from packed address to aligned address */ - ip6_addr_copy(reply_dest_local, ip6hdr->src); - ip6_addr_copy(reply_src_local, ip6hdr->dest); - reply_dest = &reply_dest_local; - reply_src = &reply_src_local; - netif = ip6_route(reply_src, reply_dest); - if (netif == NULL) { - /* drop */ - pbuf_free(q); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - else { - netif = ip_current_netif(); - reply_dest = ip6_current_src_addr(); - - /* Select an address to use as source. */ - reply_src = ip_2_ip6(ip6_select_source_address(netif, reply_dest)); - if (reply_src == NULL) { - /* drop */ - pbuf_free(q); - ICMP6_STATS_INC(icmp6.rterr); - return; - } - } - - /* calculate checksum */ - icmp6hdr->chksum = 0; -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len, - reply_src, reply_dest); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - ICMP6_STATS_INC(icmp6.xmit); - ip6_output_if(q, reply_src, reply_dest, LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(q); -} - -#endif /* LWIP_ICMP6 && LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/inet6.c b/components/net/lwip-2.0.2/src/core/ipv6/inet6.c deleted file mode 100644 index d9a992c22a..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/inet6.c +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file - * - * INET v6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/inet.h" - -/** This variable is initialized by the system to contain the wildcard IPv6 address. - */ -const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; - -#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/ip6.c b/components/net/lwip-2.0.2/src/core/ipv6/ip6.c deleted file mode 100644 index f14e33424f..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/ip6.c +++ /dev/null @@ -1,1122 +0,0 @@ -/** - * @file - * - * IPv6 layer. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/ip.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip6_frag.h" -#include "lwip/icmp6.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/dhcp6.h" -#include "lwip/nd6.h" -#include "lwip/mld6.h" -#include "lwip/debug.h" -#include "lwip/stats.h" - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -/** - * Finds the appropriate network interface for a given IPv6 address. It tries to select - * a netif following a sequence of heuristics: - * 1) if there is only 1 netif, return it - * 2) if the destination is a link-local address, try to match the src address to a netif. - * this is a tricky case because with multiple netifs, link-local addresses only have - * meaning within a particular subnet/link. - * 3) tries to match the destination subnet to a configured address - * 4) tries to find a router - * 5) tries to match the source address to the netif - * 6) returns the default netif, if configured - * - * @param src the source IPv6 address, if known - * @param dest the destination IPv6 address for which to find the route - * @return the netif on which to send to reach dest - */ -struct netif * -ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) -{ - struct netif *netif; - s8_t i; - - /* If single netif configuration, fast return. */ - if ((netif_list != NULL) && (netif_list->next == NULL)) { - if (!netif_is_up(netif_list) || !netif_is_link_up(netif_list)) { - return NULL; - } - return netif_list; - } - - /* Special processing for link-local addresses. */ - if (ip6_addr_islinklocal(dest)) { - if (ip6_addr_isany(src)) { - /* Use default netif, if Up. */ - if (netif_default == NULL || !netif_is_up(netif_default) || - !netif_is_link_up(netif_default)) { - return NULL; - } - return netif_default; - } - - /* Try to find the netif for the source address, checking that link is up. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (!netif_is_up(netif) || !netif_is_link_up(netif)) { - continue; - } - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - - /* netif not found, use default netif, if up */ - if (netif_default == NULL || !netif_is_up(netif_default) || - !netif_is_link_up(netif_default)) { - return NULL; - } - return netif_default; - } - - /* we come here for non-link-local addresses */ -#ifdef LWIP_HOOK_IP6_ROUTE - netif = LWIP_HOOK_IP6_ROUTE(src, dest); - if (netif != NULL) { - return netif; - } -#endif - - /* See if the destination subnet matches a configured address. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (!netif_is_up(netif) || !netif_is_link_up(netif)) { - continue; - } - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - - /* Get the netif for a suitable router. */ - netif = nd6_find_route(dest); - if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) { - return netif; - } - - /* try with the netif that matches the source address. */ - if (!ip6_addr_isany(src)) { - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (!netif_is_up(netif) || !netif_is_link_up(netif)) { - continue; - } - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(src, netif_ip6_addr(netif, i))) { - return netif; - } - } - } - } - -#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF - /* loopif is disabled, loopback traffic is passed through any netif */ - if (ip6_addr_isloopback(dest)) { - /* don't check for link on loopback traffic */ - if (netif_default != NULL && netif_is_up(netif_default)) { - return netif_default; - } - /* default netif is not up, just use any netif for loopback traffic */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (netif_is_up(netif)) { - return netif; - } - } - return NULL; - } -#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ - - /* no matching netif found, use default netif, if up */ - if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { - return NULL; - } - return netif_default; -} - -/** - * @ingroup ip6 - * Select the best IPv6 source address for a given destination - * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior - * is assumed. - * - * @param netif the netif on which to send a packet - * @param dest the destination we are trying to reach - * @return the most suitable source address to use, or NULL if no suitable - * source address is found - */ -const ip_addr_t * -ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest) -{ - const ip_addr_t *src = NULL; - u8_t i; - - /* If dest is link-local, choose a link-local source. */ - if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - } - - /* Choose a site-local with matching prefix. */ - if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - } - - /* Choose a unique-local with matching prefix. */ - if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - } - - /* Choose a global with best matching prefix. */ - if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_isglobal(netif_ip6_addr(netif, i))) { - if (src == NULL) { - src = netif_ip_addr6(netif, i); - } - else { - /* Replace src only if we find a prefix match. */ - /* @todo find longest matching prefix. */ - if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && - ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { - src = netif_ip_addr6(netif, i); - } - } - } - } - if (src != NULL) { - return src; - } - } - - /* Last resort: see if arbitrary prefix matches. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { - return netif_ip_addr6(netif, i); - } - } - - return NULL; -} - -#if LWIP_IPV6_FORWARD -/** - * Forwards an IPv6 packet. It finds an appropriate route for the - * packet, decrements the HL value of the packet, and outputs - * the packet on the appropriate interface. - * - * @param p the packet to forward (p->payload points to IP header) - * @param iphdr the IPv6 header of the input packet - * @param inp the netif on which this packet was received - */ -static void -ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) -{ - struct netif *netif; - - /* do not forward link-local or loopback addresses */ - if (ip6_addr_islinklocal(ip6_current_dest_addr()) || - ip6_addr_isloopback(ip6_current_dest_addr())) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - - /* Find network interface where to forward this IP packet to. */ - netif = ip6_route(IP6_ADDR_ANY6, ip6_current_dest_addr()); - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(ip6_current_dest_addr()), - IP6_ADDR_BLOCK2(ip6_current_dest_addr()), - IP6_ADDR_BLOCK3(ip6_current_dest_addr()), - IP6_ADDR_BLOCK4(ip6_current_dest_addr()), - IP6_ADDR_BLOCK5(ip6_current_dest_addr()), - IP6_ADDR_BLOCK6(ip6_current_dest_addr()), - IP6_ADDR_BLOCK7(ip6_current_dest_addr()), - IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_dest_unreach(p, ICMP6_DUR_NO_ROUTE); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - /* Do not forward packets onto the same network interface on which - * they arrived. */ - if (netif == inp) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not bouncing packets back on incoming interface.\n")); - IP6_STATS_INC(ip6.rterr); - IP6_STATS_INC(ip6.drop); - return; - } - - /* decrement HL */ - IP6H_HOPLIM_SET(iphdr, IP6H_HOPLIM(iphdr) - 1); - /* send ICMP6 if HL == 0 */ - if (IP6H_HOPLIM(iphdr) == 0) { -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_time_exceeded(p, ICMP6_TE_HL); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.drop); - return; - } - - if (netif->mtu && (p->tot_len > netif->mtu)) { -#if LWIP_ICMP6 - /* Don't send ICMP messages in response to ICMP messages */ - if (IP6H_NEXTH(iphdr) != IP6_NEXTH_ICMP6) { - icmp6_packet_too_big(p, netif->mtu); - } -#endif /* LWIP_ICMP6 */ - IP6_STATS_INC(ip6.drop); - return; - } - - LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: forwarding packet to %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(ip6_current_dest_addr()), - IP6_ADDR_BLOCK2(ip6_current_dest_addr()), - IP6_ADDR_BLOCK3(ip6_current_dest_addr()), - IP6_ADDR_BLOCK4(ip6_current_dest_addr()), - IP6_ADDR_BLOCK5(ip6_current_dest_addr()), - IP6_ADDR_BLOCK6(ip6_current_dest_addr()), - IP6_ADDR_BLOCK7(ip6_current_dest_addr()), - IP6_ADDR_BLOCK8(ip6_current_dest_addr()))); - - /* transmit pbuf on chosen interface */ - netif->output_ip6(netif, p, ip6_current_dest_addr()); - IP6_STATS_INC(ip6.fw); - IP6_STATS_INC(ip6.xmit); - return; -} -#endif /* LWIP_IPV6_FORWARD */ - -/** - * This function is called by the network interface device driver when - * an IPv6 packet is received. The function does the basic checks of the - * IP header such as packet size being at least larger than the header - * size etc. If the packet was not destined for us, the packet is - * forwarded (using ip6_forward). - * - * Finally, the packet is sent to the upper layer protocol input function. - * - * @param p the received IPv6 packet (p->payload points to IPv6 header) - * @param inp the netif on which this packet was received - * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't - * processed, but currently always returns ERR_OK) - */ -err_t -ip6_input(struct pbuf *p, struct netif *inp) -{ - struct ip6_hdr *ip6hdr; - struct netif *netif; - u8_t nexth; - u16_t hlen; /* the current header length */ - u8_t i; -#if 0 /*IP_ACCEPT_LINK_LAYER_ADDRESSING*/ - @todo - int check_ip_src=1; -#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */ - - IP6_STATS_INC(ip6.recv); - - /* identify the IP header */ - ip6hdr = (struct ip6_hdr *)p->payload; - if (IP6H_V(ip6hdr) != 6) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IPv6 packet dropped due to bad version number %"U32_F"\n", - IP6H_V(ip6hdr))); - pbuf_free(p); - IP6_STATS_INC(ip6.err); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - -#ifdef LWIP_HOOK_IP6_INPUT - if (LWIP_HOOK_IP6_INPUT(p, inp)) { - /* the packet has been eaten */ - return ERR_OK; - } -#endif - - /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ - if ((IP6_HLEN > p->len) || ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len)) { - if (IP6_HLEN > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", - (u16_t)IP6_HLEN, p->len)); - } - if ((IP6H_PLEN(ip6hdr) + IP6_HLEN) > p->tot_len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 (plen %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", - (u16_t)(IP6H_PLEN(ip6hdr) + IP6_HLEN), p->tot_len)); - } - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - - /* Trim pbuf. This should have been done at the netif layer, - * but we'll do it anyway just to be sure that its done. */ - pbuf_realloc(p, IP6_HLEN + IP6H_PLEN(ip6hdr)); - - /* copy IP addresses to aligned ip6_addr_t */ - ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); - ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); - - /* Don't accept virtual IPv4 mapped IPv6 addresses. - * Don't accept multicast source addresses. */ - if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || - ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || - ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { - IP6_STATS_INC(ip6.err); - IP6_STATS_INC(ip6.drop); - return ERR_OK; - } - - /* current header pointer. */ - ip_data.current_ip6_header = ip6hdr; - - /* In netif, used in case we need to send ICMPv6 packets back. */ - ip_data.current_netif = inp; - ip_data.current_input_netif = inp; - - /* match packet against an interface, i.e. is this packet for us? */ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* Always joined to multicast if-local and link-local all-nodes group. */ - if (ip6_addr_isallnodes_iflocal(ip6_current_dest_addr()) || - ip6_addr_isallnodes_linklocal(ip6_current_dest_addr())) { - netif = inp; - } -#if LWIP_IPV6_MLD - else if (mld6_lookfor_group(inp, ip6_current_dest_addr())) { - netif = inp; - } -#else /* LWIP_IPV6_MLD */ - else if (ip6_addr_issolicitednode(ip6_current_dest_addr())) { - /* Filter solicited node packets when MLD is not enabled - * (for Neighbor discovery). */ - netif = NULL; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp_solicitednode(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { - netif = inp; - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: solicited node packet accepted on interface %c%c\n", - netif->name[0], netif->name[1])); - break; - } - } - } -#endif /* LWIP_IPV6_MLD */ - else { - netif = NULL; - } - } else { - /* start trying with inp. if that's not acceptable, start walking the - list of configured netifs. - 'first' is used as a boolean to mark whether we started walking the list */ - int first = 1; - netif = inp; - do { - /* interface is up? */ - if (netif_is_up(netif)) { - /* unicast to this interface address? address configured? */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(netif, i))) { - /* exit outer loop */ - goto netif_found; - } - } - } - if (first) { - if (ip6_addr_islinklocal(ip6_current_dest_addr()) -#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF - || ip6_addr_isloopback(ip6_current_dest_addr()) -#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ - ) { - /* Do not match link-local addresses to other netifs. The loopback - * address is to be considered link-local and packets to it should be - * dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This - * requirement cannot be implemented in the case that loopback - * traffic is sent across a non-loopback interface, however. - */ - netif = NULL; - break; - } - first = 0; - netif = netif_list; - } else { - netif = netif->next; - } - if (netif == inp) { - netif = netif->next; - } - } while (netif != NULL); -netif_found: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet accepted on interface %c%c\n", - netif ? netif->name[0] : 'X', netif? netif->name[1] : 'X')); - } - - /* "::" packet source address? (used in duplicate address detection) */ - if (ip6_addr_isany(ip6_current_src_addr()) && - (!ip6_addr_issolicitednode(ip6_current_dest_addr()))) { - /* packet source is not valid */ - /* free (drop) packet pbufs */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with src ANY_ADDRESS dropped\n")); - pbuf_free(p); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - /* packet not for us? */ - if (netif == NULL) { - /* packet not for us, route or discard */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_TRACE, ("ip6_input: packet not for us.\n")); -#if LWIP_IPV6_FORWARD - /* non-multicast packet? */ - if (!ip6_addr_ismulticast(ip6_current_dest_addr())) { - /* try to forward IP packet on (other) interfaces */ - ip6_forward(p, ip6hdr, inp); - } -#endif /* LWIP_IPV6_FORWARD */ - pbuf_free(p); - goto ip6_input_cleanup; - } - - /* current netif pointer. */ - ip_data.current_netif = netif; - - /* Save next header type. */ - nexth = IP6H_NEXTH(ip6hdr); - - /* Init header length. */ - hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; - - /* Move to payload. */ - pbuf_header(p, -IP6_HLEN); - - /* Process known option extension headers, if present. */ - while (nexth != IP6_NEXTH_NONE) - { - switch (nexth) { - case IP6_NEXTH_HOPBYHOP: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Hop-by-Hop options header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -(s16_t)hlen); - break; - case IP6_NEXTH_DESTOPTS: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Destination options header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -(s16_t)hlen); - break; - case IP6_NEXTH_ROUTING: - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Routing header\n")); - /* Get next header type. */ - nexth = *((u8_t *)p->payload); - - /* Get the header length. */ - hlen = 8 * (1 + *((u8_t *)p->payload + 1)); - ip_data.current_ip_header_tot_len += hlen; - - /* Skip over this header. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_STATS_INC(ip6.lenerr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; - } - - pbuf_header(p, -(s16_t)hlen); - break; - - case IP6_NEXTH_FRAGMENT: - { - struct ip6_frag_hdr *frag_hdr; - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header\n")); - - frag_hdr = (struct ip6_frag_hdr *)p->payload; - - /* Get next header type. */ - nexth = frag_hdr->_nexth; - - /* Fragment Header length. */ - hlen = 8; - ip_data.current_ip_header_tot_len += hlen; - - /* Make sure this header fits in current pbuf. */ - if (hlen > p->len) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("IPv6 options header (hlen %"U16_F") does not fit in first pbuf (len %"U16_F"), IPv6 packet dropped.\n", - hlen, p->len)); - /* free (drop) packet pbufs */ - pbuf_free(p); - IP6_FRAG_STATS_INC(ip6_frag.lenerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto ip6_input_cleanup; - } - - /* Offset == 0 and more_fragments == 0? */ - if ((frag_hdr->_fragment_offset & - PP_HTONS(IP6_FRAG_OFFSET_MASK | IP6_FRAG_MORE_FLAG)) == 0) { - /* This is a 1-fragment packet, usually a packet that we have - * already reassembled. Skip this header anc continue. */ - pbuf_header(p, -(s16_t)hlen); - } else { -#if LWIP_IPV6_REASS - - /* reassemble the packet */ - p = ip6_reass(p); - /* packet not fully reassembled yet? */ - if (p == NULL) { - goto ip6_input_cleanup; - } - - /* Returned p point to IPv6 header. - * Update all our variables and pointers and continue. */ - ip6hdr = (struct ip6_hdr *)p->payload; - nexth = IP6H_NEXTH(ip6hdr); - hlen = ip_data.current_ip_header_tot_len = IP6_HLEN; - pbuf_header(p, -IP6_HLEN); - -#else /* LWIP_IPV6_REASS */ - /* free (drop) packet pbufs */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: packet with Fragment header dropped (with LWIP_IPV6_REASS==0)\n")); - pbuf_free(p); - IP6_STATS_INC(ip6.opterr); - IP6_STATS_INC(ip6.drop); - goto ip6_input_cleanup; -#endif /* LWIP_IPV6_REASS */ - } - break; - } - default: - goto options_done; - break; - } - } -options_done: - - /* p points to IPv6 header again. */ - pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len); - - /* send to upper layers */ - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); - ip6_debug_print(p); - LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); - -#if LWIP_RAW - /* raw input did not eat the packet? */ - if (raw_input(p, inp) == 0) -#endif /* LWIP_RAW */ - { - switch (nexth) { - case IP6_NEXTH_NONE: - pbuf_free(p); - break; -#if LWIP_UDP - case IP6_NEXTH_UDP: -#if LWIP_UDPLITE - case IP6_NEXTH_UDPLITE: -#endif /* LWIP_UDPLITE */ - /* Point to payload. */ - pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); - udp_input(p, inp); - break; -#endif /* LWIP_UDP */ -#if LWIP_TCP - case IP6_NEXTH_TCP: - /* Point to payload. */ - pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); - tcp_input(p, inp); - break; -#endif /* LWIP_TCP */ -#if LWIP_ICMP6 - case IP6_NEXTH_ICMP6: - /* Point to payload. */ - pbuf_header(p, -(s16_t)ip_data.current_ip_header_tot_len); - icmp6_input(p, inp); - break; -#endif /* LWIP_ICMP */ - default: -#if LWIP_ICMP6 - /* send ICMP parameter problem unless it was a multicast or ICMPv6 */ - if ((!ip6_addr_ismulticast(ip6_current_dest_addr())) && - (IP6H_NEXTH(ip6hdr) != IP6_NEXTH_ICMP6)) { - icmp6_param_problem(p, ICMP6_PP_HEADER, ip_data.current_ip_header_tot_len - hlen); - } -#endif /* LWIP_ICMP */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_input: Unsupported transport protocol %"U16_F"\n", (u16_t)IP6H_NEXTH(ip6hdr))); - pbuf_free(p); - IP6_STATS_INC(ip6.proterr); - IP6_STATS_INC(ip6.drop); - break; - } - } - -ip6_input_cleanup: - ip_data.current_netif = NULL; - ip_data.current_input_netif = NULL; - ip_data.current_ip6_header = NULL; - ip_data.current_ip_header_tot_len = 0; - ip6_addr_set_zero(ip6_current_src_addr()); - ip6_addr_set_zero(ip6_current_dest_addr()); - - return ERR_OK; -} - - -/** - * Sends an IPv6 packet on a network interface. This function constructs - * the IPv6 header. If the source IPv6 address is NULL, the IPv6 "ANY" address is - * used as source (usually during network startup). If the source IPv6 address it - * IP6_ADDR_ANY, the most appropriate IPv6 address of the outgoing network - * interface is filled in as source address. If the destination IPv6 address is - * LWIP_IP_HDRINCL, p is assumed to already include an IPv6 header and - * p->payload points to it instead of the data. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * @param netif the netif on which to send this packet - * @return ERR_OK if the packet was sent OK - * ERR_BUF if p doesn't have enough space for IPv6/LINK headers - * returns errors returned by netif->output - */ -err_t -ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, - u8_t nexth, struct netif *netif) -{ - const ip6_addr_t *src_used = src; - if (dest != LWIP_IP_HDRINCL) { - if (src != NULL && ip6_addr_isany(src)) { - src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); - if ((src_used == NULL) || ip6_addr_isany(src_used)) { - /* No appropriate source address was found for this packet. */ - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - } - } - return ip6_output_if_src(p, src_used, dest, hl, tc, nexth, netif); -} - -/** - * Same as ip6_output_if() but 'src' address is not replaced by netif address - * when it is 'any'. - */ -err_t -ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, - u8_t nexth, struct netif *netif) -{ - struct ip6_hdr *ip6hdr; - ip6_addr_t dest_addr; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - /* Should the IPv6 header be generated or is it already included in p? */ - if (dest != LWIP_IP_HDRINCL) { - /* generate IPv6 header */ - if (pbuf_header(p, IP6_HLEN)) { - LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: not enough room for IPv6 header in pbuf\n")); - IP6_STATS_INC(ip6.err); - return ERR_BUF; - } - - ip6hdr = (struct ip6_hdr *)p->payload; - LWIP_ASSERT("check that first pbuf can hold struct ip6_hdr", - (p->len >= sizeof(struct ip6_hdr))); - - IP6H_HOPLIM_SET(ip6hdr, hl); - IP6H_NEXTH_SET(ip6hdr, nexth); - - /* dest cannot be NULL here */ - ip6_addr_copy(ip6hdr->dest, *dest); - - IP6H_VTCFL_SET(ip6hdr, 6, tc, 0); - IP6H_PLEN_SET(ip6hdr, p->tot_len - IP6_HLEN); - - if (src == NULL) { - src = IP6_ADDR_ANY6; - } - /* src cannot be NULL here */ - ip6_addr_copy(ip6hdr->src, *src); - - } else { - /* IP header already included in p */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(dest_addr, ip6hdr->dest); - dest = &dest_addr; - } - - IP6_STATS_INC(ip6.xmit); - - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); - ip6_debug_print(p); - -#if ENABLE_LOOPBACK - { - int i; -#if !LWIP_HAVE_LOOPIF - if (ip6_addr_isloopback(dest)) { - return netif_loop_output(netif, p); - } -#endif /* !LWIP_HAVE_LOOPIF */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(dest, netif_ip6_addr(netif, i))) { - /* Packet to self, enqueue it for loopback */ - LWIP_DEBUGF(IP6_DEBUG, ("netif_loop_output()\n")); - return netif_loop_output(netif, p); - } - } - } -#endif /* ENABLE_LOOPBACK */ -#if LWIP_IPV6_FRAG - /* don't fragment if interface has mtu set to 0 [loopif] */ - if (netif->mtu && (p->tot_len > nd6_get_destination_mtu(dest, netif))) { - return ip6_frag(p, netif, dest); - } -#endif /* LWIP_IPV6_FRAG */ - - LWIP_DEBUGF(IP6_DEBUG, ("netif->output_ip6()\n")); - return netif->output_ip6(netif, p, dest); -} - -/** - * Simple interface to ip6_output_if. It finds the outgoing network - * interface and calls upon ip6_output_if to do the actual work. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth) -{ - struct netif *netif; - struct ip6_hdr *ip6hdr; - ip6_addr_t src_addr, dest_addr; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if (dest != LWIP_IP_HDRINCL) { - netif = ip6_route(src, dest); - } else { - /* IP header included in p, read addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(src_addr, ip6hdr->src); - ip6_addr_copy(dest_addr, ip6hdr->dest); - netif = ip6_route(&src_addr, &dest_addr); - } - - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(dest), - IP6_ADDR_BLOCK2(dest), - IP6_ADDR_BLOCK3(dest), - IP6_ADDR_BLOCK4(dest), - IP6_ADDR_BLOCK5(dest), - IP6_ADDR_BLOCK6(dest), - IP6_ADDR_BLOCK7(dest), - IP6_ADDR_BLOCK8(dest))); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - - return ip6_output_if(p, src, dest, hl, tc, nexth, netif); -} - - -#if LWIP_NETIF_HWADDRHINT -/** Like ip6_output, but takes and addr_hint pointer that is passed on to netif->addr_hint - * before calling ip6_output_if. - * - * @param p the packet to send (p->payload points to the data, e.g. next - protocol header; if dest == LWIP_IP_HDRINCL, p already includes an - IPv6 header and p->payload points to that IPv6 header) - * @param src the source IPv6 address to send from (if src == IP6_ADDR_ANY, an - * IP address of the netif is selected and used as source address. - * if src == NULL, IP6_ADDR_ANY is used as source) - * @param dest the destination IPv6 address to send the packet to - * @param hl the Hop Limit value to be set in the IPv6 header - * @param tc the Traffic Class value to be set in the IPv6 header - * @param nexth the Next Header to be set in the IPv6 header - * @param addr_hint address hint pointer set to netif->addr_hint before - * calling ip_output_if() - * - * @return ERR_RTE if no route is found - * see ip_output_if() for more return values - */ -err_t -ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint) -{ - struct netif *netif; - struct ip6_hdr *ip6hdr; - ip6_addr_t src_addr, dest_addr; - err_t err; - - LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); - - if (dest != LWIP_IP_HDRINCL) { - netif = ip6_route(src, dest); - } else { - /* IP header included in p, read addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip6_addr_copy(src_addr, ip6hdr->src); - ip6_addr_copy(dest_addr, ip6hdr->dest); - netif = ip6_route(&src_addr, &dest_addr); - } - - if (netif == NULL) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_output: no route for %"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F":%"X16_F"\n", - IP6_ADDR_BLOCK1(dest), - IP6_ADDR_BLOCK2(dest), - IP6_ADDR_BLOCK3(dest), - IP6_ADDR_BLOCK4(dest), - IP6_ADDR_BLOCK5(dest), - IP6_ADDR_BLOCK6(dest), - IP6_ADDR_BLOCK7(dest), - IP6_ADDR_BLOCK8(dest))); - IP6_STATS_INC(ip6.rterr); - return ERR_RTE; - } - - NETIF_SET_HWADDRHINT(netif, addr_hint); - err = ip6_output_if(p, src, dest, hl, tc, nexth, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - return err; -} -#endif /* LWIP_NETIF_HWADDRHINT*/ - -#if LWIP_IPV6_MLD -/** - * Add a hop-by-hop options header with a router alert option and padding. - * - * Used by MLD when sending a Multicast listener report/done message. - * - * @param p the packet to which we will prepend the options header - * @param nexth the next header protocol number (e.g. IP6_NEXTH_ICMP6) - * @param value the value of the router alert option data (e.g. IP6_ROUTER_ALERT_VALUE_MLD) - * @return ERR_OK if hop-by-hop header was added, ERR_* otherwise - */ -err_t -ip6_options_add_hbh_ra(struct pbuf *p, u8_t nexth, u8_t value) -{ - struct ip6_hbh_hdr *hbh_hdr; - - /* Move pointer to make room for hop-by-hop options header. */ - if (pbuf_header(p, sizeof(struct ip6_hbh_hdr))) { - LWIP_DEBUGF(IP6_DEBUG, ("ip6_options: no space for options header\n")); - IP6_STATS_INC(ip6.err); - return ERR_BUF; - } - - hbh_hdr = (struct ip6_hbh_hdr *)p->payload; - - /* Set fields. */ - hbh_hdr->_nexth = nexth; - hbh_hdr->_hlen = 0; - hbh_hdr->_ra_opt_type = IP6_ROUTER_ALERT_OPTION; - hbh_hdr->_ra_opt_dlen = 2; - hbh_hdr->_ra_opt_data = value; - hbh_hdr->_padn_opt_type = IP6_PADN_ALERT_OPTION; - hbh_hdr->_padn_opt_dlen = 0; - - return ERR_OK; -} -#endif /* LWIP_IPV6_MLD */ - -#if IP6_DEBUG -/* Print an IPv6 header by using LWIP_DEBUGF - * @param p an IPv6 packet, p->payload pointing to the IPv6 header - */ -void -ip6_debug_print(struct pbuf *p) -{ - struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; - - LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n")); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n", - IP6H_V(ip6hdr), - IP6H_TC(ip6hdr), - IP6H_FL(ip6hdr))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %5"U16_F" | %3"U16_F" | %3"U16_F" | (plen, nexth, hopl)\n", - IP6H_PLEN(ip6hdr), - IP6H_NEXTH(ip6hdr), - IP6H_HOPLIM(ip6hdr))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (src)\n", - IP6_ADDR_BLOCK1(&(ip6hdr->src)), - IP6_ADDR_BLOCK2(&(ip6hdr->src)), - IP6_ADDR_BLOCK3(&(ip6hdr->src)), - IP6_ADDR_BLOCK4(&(ip6hdr->src)))); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", - IP6_ADDR_BLOCK5(&(ip6hdr->src)), - IP6_ADDR_BLOCK6(&(ip6hdr->src)), - IP6_ADDR_BLOCK7(&(ip6hdr->src)), - IP6_ADDR_BLOCK8(&(ip6hdr->src)))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" | (dest)\n", - IP6_ADDR_BLOCK1(&(ip6hdr->dest)), - IP6_ADDR_BLOCK2(&(ip6hdr->dest)), - IP6_ADDR_BLOCK3(&(ip6hdr->dest)), - IP6_ADDR_BLOCK4(&(ip6hdr->dest)))); - LWIP_DEBUGF(IP6_DEBUG, ("| %4"X32_F" | %4"X32_F" | %4"X32_F" | %4"X32_F" |\n", - IP6_ADDR_BLOCK5(&(ip6hdr->dest)), - IP6_ADDR_BLOCK6(&(ip6hdr->dest)), - IP6_ADDR_BLOCK7(&(ip6hdr->dest)), - IP6_ADDR_BLOCK8(&(ip6hdr->dest)))); - LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n")); -} -#endif /* IP6_DEBUG */ - -#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/ip6_addr.c b/components/net/lwip-2.0.2/src/core/ipv6/ip6_addr.c deleted file mode 100644 index aa06659a02..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/ip6_addr.c +++ /dev/null @@ -1,292 +0,0 @@ -/** - * @file - * - * IPv6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * Functions for handling IPv6 addresses. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip_addr.h" -#include "lwip/def.h" - -/* used by IP6_ADDR_ANY(6) in ip6_addr.h */ -const ip_addr_t ip6_addr_any = IPADDR6_INIT(0ul, 0ul, 0ul, 0ul); - -#ifndef isprint -#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up) -#define isprint(c) in_range(c, 0x20, 0x7f) -#define isdigit(c) in_range(c, '0', '9') -#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) -#define islower(c) in_range(c, 'a', 'z') -#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') -#define xchar(i) ((i) < 10 ? '0' + (i) : 'A' + (i) - 10) -#endif - -/** - * Check whether "cp" is a valid ascii representation - * of an IPv6 address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * - * @param cp IPv6 address in ascii representation (e.g. "FF01::1") - * @param addr pointer to which to save the ip address in network order - * @return 1 if cp could be converted to addr, 0 on failure - */ -int -ip6addr_aton(const char *cp, ip6_addr_t *addr) -{ - u32_t addr_index, zero_blocks, current_block_index, current_block_value; - const char *s; - - /* Count the number of colons, to count the number of blocks in a "::" sequence - zero_blocks may be 1 even if there are no :: sequences */ - zero_blocks = 8; - for (s = cp; *s != 0; s++) { - if (*s == ':') { - zero_blocks--; - } else if (!isxdigit(*s)) { - break; - } - } - - /* parse each block */ - addr_index = 0; - current_block_index = 0; - current_block_value = 0; - for (s = cp; *s != 0; s++) { - if (*s == ':') { - if (addr) { - if (current_block_index & 0x1) { - addr->addr[addr_index++] |= current_block_value; - } - else { - addr->addr[addr_index] = current_block_value << 16; - } - } - current_block_index++; - current_block_value = 0; - if (current_block_index > 7) { - /* address too long! */ - return 0; - } - if (s[1] == ':') { - if (s[2] == ':') { - /* invalid format: three successive colons */ - return 0; - } - s++; - /* "::" found, set zeros */ - while (zero_blocks > 0) { - zero_blocks--; - if (current_block_index & 0x1) { - addr_index++; - } else { - if (addr) { - addr->addr[addr_index] = 0; - } - } - current_block_index++; - if (current_block_index > 7) { - /* address too long! */ - return 0; - } - } - } - } else if (isxdigit(*s)) { - /* add current digit */ - current_block_value = (current_block_value << 4) + - (isdigit(*s) ? (u32_t)(*s - '0') : - (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); - } else { - /* unexpected digit, space? CRLF? */ - break; - } - } - - if (addr) { - if (current_block_index & 0x1) { - addr->addr[addr_index++] |= current_block_value; - } - else { - addr->addr[addr_index] = current_block_value << 16; - } - } - - /* convert to network byte order. */ - if (addr) { - for (addr_index = 0; addr_index < 4; addr_index++) { - addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); - } - } - - if (current_block_index != 7) { - return 0; - } - - return 1; -} - -/** - * Convert numeric IPv6 address into ASCII representation. - * returns ptr to static buffer; not reentrant! - * - * @param addr ip6 address in network order to convert - * @return pointer to a global static (!) buffer that holds the ASCII - * representation of addr - */ -char * -ip6addr_ntoa(const ip6_addr_t *addr) -{ - static char str[40]; - return ip6addr_ntoa_r(addr, str, 40); -} - -/** - * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used. - * - * @param addr ip6 address in network order to convert - * @param buf target buffer where the string is stored - * @param buflen length of buf - * @return either pointer to buf which now holds the ASCII - * representation of addr or NULL if buf was too small - */ -char * -ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) -{ - u32_t current_block_index, current_block_value, next_block_value; - s32_t i; - u8_t zero_flag, empty_block_flag; - - i = 0; - empty_block_flag = 0; /* used to indicate a zero chain for "::' */ - - for (current_block_index = 0; current_block_index < 8; current_block_index++) { - /* get the current 16-bit block */ - current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); - if ((current_block_index & 0x1) == 0) { - current_block_value = current_block_value >> 16; - } - current_block_value &= 0xffff; - - /* Check for empty block. */ - if (current_block_value == 0) { - if (current_block_index == 7 && empty_block_flag == 1) { - /* special case, we must render a ':' for the last block. */ - buf[i++] = ':'; - if (i >= buflen) { - return NULL; - } - break; - } - if (empty_block_flag == 0) { - /* generate empty block "::", but only if more than one contiguous zero block, - * according to current formatting suggestions RFC 5952. */ - next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); - if ((current_block_index & 0x1) == 0x01) { - next_block_value = next_block_value >> 16; - } - next_block_value &= 0xffff; - if (next_block_value == 0) { - empty_block_flag = 1; - buf[i++] = ':'; - if (i >= buflen) { - return NULL; - } - continue; /* move on to next block. */ - } - } else if (empty_block_flag == 1) { - /* move on to next block. */ - continue; - } - } else if (empty_block_flag == 1) { - /* Set this flag value so we don't produce multiple empty blocks. */ - empty_block_flag = 2; - } - - if (current_block_index > 0) { - buf[i++] = ':'; - if (i >= buflen) { - return NULL; - } - } - - if ((current_block_value & 0xf000) == 0) { - zero_flag = 1; - } else { - buf[i++] = xchar(((current_block_value & 0xf000) >> 12)); - zero_flag = 0; - if (i >= buflen) { - return NULL; - } - } - - if (((current_block_value & 0xf00) == 0) && (zero_flag)) { - /* do nothing */ - } else { - buf[i++] = xchar(((current_block_value & 0xf00) >> 8)); - zero_flag = 0; - if (i >= buflen) { - return NULL; - } - } - - if (((current_block_value & 0xf0) == 0) && (zero_flag)) { - /* do nothing */ - } - else { - buf[i++] = xchar(((current_block_value & 0xf0) >> 4)); - zero_flag = 0; - if (i >= buflen) { - return NULL; - } - } - - buf[i++] = xchar((current_block_value & 0xf)); - if (i >= buflen) { - return NULL; - } - } - - buf[i] = 0; - - return buf; -} - -#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/ip6_frag.c b/components/net/lwip-2.0.2/src/core/ipv6/ip6_frag.c deleted file mode 100644 index ff07f71cd2..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/ip6_frag.c +++ /dev/null @@ -1,805 +0,0 @@ -/** - * @file - * - * IPv6 fragmentation and reassembly. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" -#include "lwip/ip6_frag.h" -#include "lwip/ip6.h" -#include "lwip/icmp6.h" -#include "lwip/nd6.h" -#include "lwip/ip.h" - -#include "lwip/pbuf.h" -#include "lwip/memp.h" -#include "lwip/stats.h" - -#include - -#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ - - -/** Setting this to 0, you can turn off checking the fragments for overlapping - * regions. The code gets a little smaller. Only use this if you know that - * overlapping won't occur on your network! */ -#ifndef IP_REASS_CHECK_OVERLAP -#define IP_REASS_CHECK_OVERLAP 1 -#endif /* IP_REASS_CHECK_OVERLAP */ - -/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is - * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. - * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA - * is set to 1, so one datagram can be reassembled at a time, only. */ -#ifndef IP_REASS_FREE_OLDEST -#define IP_REASS_FREE_OLDEST 1 -#endif /* IP_REASS_FREE_OLDEST */ - -#if IPV6_FRAG_COPYHEADER -#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN)) -#endif - -#define IP_REASS_FLAG_LASTFRAG 0x01 - -/** This is a helper struct which holds the starting - * offset and the ending offset of this fragment to - * easily chain the fragments. - * It has the same packing requirements as the IPv6 header, since it replaces - * the Fragment Header in memory in incoming fragments to keep - * track of the various fragments. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_reass_helper { - PACK_STRUCT_FIELD(struct pbuf *next_pbuf); - PACK_STRUCT_FIELD(u16_t start); - PACK_STRUCT_FIELD(u16_t end); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* static variables */ -static struct ip6_reassdata *reassdatagrams; -static u16_t ip6_reass_pbufcount; - -/* Forward declarations. */ -static void ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr); -#if IP_REASS_FREE_OLDEST -static void ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed); -#endif /* IP_REASS_FREE_OLDEST */ - -void -ip6_reass_tmr(void) -{ - struct ip6_reassdata *r, *tmp; - -#if !IPV6_FRAG_COPYHEADER - LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", - sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); -#endif /* !IPV6_FRAG_COPYHEADER */ - - r = reassdatagrams; - while (r != NULL) { - /* Decrement the timer. Once it reaches 0, - * clean up the incomplete fragment assembly */ - if (r->timer > 0) { - r->timer--; - r = r->next; - } else { - /* reassembly timed out */ - tmp = r; - /* get the next pointer before freeing */ - r = r->next; - /* free the helper struct and all enqueued pbufs */ - ip6_reass_free_complete_datagram(tmp); - } - } -} - -/** - * Free a datagram (struct ip6_reassdata) and all its pbufs. - * Updates the total count of enqueued pbufs (ip6_reass_pbufcount), - * sends an ICMP time exceeded packet. - * - * @param ipr datagram to free - */ -static void -ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) -{ - struct ip6_reassdata *prev; - u16_t pbufs_freed = 0; - u16_t clen; - struct pbuf *p; - struct ip6_reass_helper *iprh; - -#if LWIP_ICMP6 - iprh = (struct ip6_reass_helper *)ipr->p->payload; - if (iprh->start == 0) { - /* The first fragment was received, send ICMP time exceeded. */ - /* First, de-queue the first pbuf from r->p. */ - p = ipr->p; - ipr->p = iprh->next_pbuf; - /* Then, move back to the original ipv6 header (we are now pointing to Fragment header). - This cannot fail since we already checked when receiving this fragment. */ - if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)IPV6_FRAG_HDRREF(ipr->iphdr)))) { - LWIP_ASSERT("ip6_reass_free: moving p->payload to ip6 header failed\n", 0); - } - else { - icmp6_time_exceeded(p, ICMP6_TE_FRAG); - } - clen = pbuf_clen(p); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(p); - } -#endif /* LWIP_ICMP6 */ - - /* First, free all received pbufs. The individual pbufs need to be released - separately as they have not yet been chained */ - p = ipr->p; - while (p != NULL) { - struct pbuf *pcur; - iprh = (struct ip6_reass_helper *)p->payload; - pcur = p; - /* get the next pointer before freeing */ - p = iprh->next_pbuf; - clen = pbuf_clen(pcur); - LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); - pbufs_freed += clen; - pbuf_free(pcur); - } - - /* Then, unchain the struct ip6_reassdata from the list and free it. */ - if (ipr == reassdatagrams) { - reassdatagrams = ipr->next; - } else { - prev = reassdatagrams; - while (prev != NULL) { - if (prev->next == ipr) { - break; - } - prev = prev->next; - } - if (prev != NULL) { - prev->next = ipr->next; - } - } - memp_free(MEMP_IP6_REASSDATA, ipr); - - /* Finally, update number of pbufs in reassembly queue */ - LWIP_ASSERT("ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed); - ip6_reass_pbufcount -= pbufs_freed; -} - -#if IP_REASS_FREE_OLDEST -/** - * Free the oldest datagram to make room for enqueueing new fragments. - * The datagram ipr is not freed! - * - * @param ipr ip6_reassdata for the current fragment - * @param pbufs_needed number of pbufs needed to enqueue - * (used for freeing other datagrams if not enough space) - */ -static void -ip6_reass_remove_oldest_datagram(struct ip6_reassdata *ipr, int pbufs_needed) -{ - struct ip6_reassdata *r, *oldest; - - /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, - * but don't free the current datagram! */ - do { - r = oldest = reassdatagrams; - while (r != NULL) { - if (r != ipr) { - if (r->timer <= oldest->timer) { - /* older than the previous oldest */ - oldest = r; - } - } - r = r->next; - } - if (oldest == ipr) { - /* nothing to free, ipr is the only element on the list */ - return; - } - if (oldest != NULL) { - ip6_reass_free_complete_datagram(oldest); - } - } while (((ip6_reass_pbufcount + pbufs_needed) > IP_REASS_MAX_PBUFS) && (reassdatagrams != NULL)); -} -#endif /* IP_REASS_FREE_OLDEST */ - -/** - * Reassembles incoming IPv6 fragments into an IPv6 datagram. - * - * @param p points to the IPv6 Fragment Header - * @return NULL if reassembly is incomplete, pbuf pointing to - * IPv6 Header if reassembly is complete - */ -struct pbuf * -ip6_reass(struct pbuf *p) -{ - struct ip6_reassdata *ipr, *ipr_prev; - struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; - struct ip6_frag_hdr *frag_hdr; - u16_t offset, len; - u16_t clen; - u8_t valid = 1; - struct pbuf *q; - - IP6_FRAG_STATS_INC(ip6_frag.recv); - - if ((const void*)ip6_current_header() != ((u8_t*)p->payload) - IP6_HLEN) { - /* ip6_frag_hdr must be in the first pbuf, not chained */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - - frag_hdr = (struct ip6_frag_hdr *) p->payload; - - clen = pbuf_clen(p); - - offset = lwip_ntohs(frag_hdr->_fragment_offset); - - /* Calculate fragment length from IPv6 payload length. - * Adjust for headers before Fragment Header. - * And finally adjust by Fragment Header length. */ - len = lwip_ntohs(ip6_current_header()->_plen); - len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); - len -= IP6_FRAG_HLEN; - - /* Look for the datagram the fragment belongs to in the current datagram queue, - * remembering the previous in the queue for later dequeueing. */ - for (ipr = reassdatagrams, ipr_prev = NULL; ipr != NULL; ipr = ipr->next) { - /* Check if the incoming fragment matches the one currently present - in the reassembly buffer. If so, we proceed with copying the - fragment into the buffer. */ - if ((frag_hdr->_identification == ipr->identification) && - ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) && - ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) { - IP6_FRAG_STATS_INC(ip6_frag.cachehit); - break; - } - ipr_prev = ipr; - } - - if (ipr == NULL) { - /* Enqueue a new datagram into the datagram queue */ - ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); - if (ipr == NULL) { -#if IP_REASS_FREE_OLDEST - /* Make room and try again. */ - ip6_reass_remove_oldest_datagram(ipr, clen); - ipr = (struct ip6_reassdata *)memp_malloc(MEMP_IP6_REASSDATA); - if (ipr != NULL) { - /* re-search ipr_prev since it might have been removed */ - for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } else -#endif /* IP_REASS_FREE_OLDEST */ - { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } - - memset(ipr, 0, sizeof(struct ip6_reassdata)); - ipr->timer = IP_REASS_MAXAGE; - - /* enqueue the new structure to the front of the list */ - ipr->next = reassdatagrams; - reassdatagrams = ipr; - - /* Use the current IPv6 header for src/dest address reference. - * Eventually, we will replace it when we get the first fragment - * (it might be this one, in any case, it is done later). */ -#if IPV6_FRAG_COPYHEADER - MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); -#else /* IPV6_FRAG_COPYHEADER */ - /* need to use the none-const pointer here: */ - ipr->iphdr = ip_data.current_ip6_header; -#endif /* IPV6_FRAG_COPYHEADER */ - - /* copy the fragmented packet id. */ - ipr->identification = frag_hdr->_identification; - - /* copy the nexth field */ - ipr->nexth = frag_hdr->_nexth; - } - - /* Check if we are allowed to enqueue more datagrams. */ - if ((ip6_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) { -#if IP_REASS_FREE_OLDEST - ip6_reass_remove_oldest_datagram(ipr, clen); - if ((ip6_reass_pbufcount + clen) <= IP_REASS_MAX_PBUFS) { - /* re-search ipr_prev since it might have been removed */ - for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { - if (ipr_prev->next == ipr) { - break; - } - } - } else -#endif /* IP_REASS_FREE_OLDEST */ - { - /* @todo: send ICMPv6 time exceeded here? */ - /* drop this pbuf */ - IP6_FRAG_STATS_INC(ip6_frag.memerr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } - - /* Overwrite Fragment Header with our own helper struct. */ -#if IPV6_FRAG_COPYHEADER - if (IPV6_FRAG_REQROOM > 0) { - /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). - This cannot fail since we already checked when receiving this fragment. */ - u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); - LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); - } -#else /* IPV6_FRAG_COPYHEADER */ - LWIP_ASSERT("sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1", - sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN); -#endif /* IPV6_FRAG_COPYHEADER */ - iprh = (struct ip6_reass_helper *)p->payload; - iprh->next_pbuf = NULL; - iprh->start = (offset & IP6_FRAG_OFFSET_MASK); - iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len; - - /* find the right place to insert this pbuf */ - /* Iterate through until we either get to the end of the list (append), - * or we find on with a larger offset (insert). */ - for (q = ipr->p; q != NULL;) { - iprh_tmp = (struct ip6_reass_helper*)q->payload; - if (iprh->start < iprh_tmp->start) { -#if IP_REASS_CHECK_OVERLAP - if (iprh->end > iprh_tmp->start) { - /* fragment overlaps with following, throw away */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - if (iprh_prev != NULL) { - if (iprh->start < iprh_prev->end) { - /* fragment overlaps with previous, throw away */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; - } - } -#endif /* IP_REASS_CHECK_OVERLAP */ - /* the new pbuf should be inserted before this */ - iprh->next_pbuf = q; - if (iprh_prev != NULL) { - /* not the fragment with the lowest offset */ - iprh_prev->next_pbuf = p; - } else { - /* fragment with the lowest offset */ - ipr->p = p; - } - break; - } else if (iprh->start == iprh_tmp->start) { - /* received the same datagram twice: no need to keep the datagram */ - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; -#if IP_REASS_CHECK_OVERLAP - } else if (iprh->start < iprh_tmp->end) { - /* overlap: no need to keep the new datagram */ - IP6_FRAG_STATS_INC(ip6_frag.proterr); - IP6_FRAG_STATS_INC(ip6_frag.drop); - goto nullreturn; -#endif /* IP_REASS_CHECK_OVERLAP */ - } else { - /* Check if the fragments received so far have no gaps. */ - if (iprh_prev != NULL) { - if (iprh_prev->end != iprh_tmp->start) { - /* There is a fragment missing between the current - * and the previous fragment */ - valid = 0; - } - } - } - q = iprh_tmp->next_pbuf; - iprh_prev = iprh_tmp; - } - - /* If q is NULL, then we made it to the end of the list. Determine what to do now */ - if (q == NULL) { - if (iprh_prev != NULL) { - /* this is (for now), the fragment with the highest offset: - * chain it to the last fragment */ -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); -#endif /* IP_REASS_CHECK_OVERLAP */ - iprh_prev->next_pbuf = p; - if (iprh_prev->end != iprh->start) { - valid = 0; - } - } else { -#if IP_REASS_CHECK_OVERLAP - LWIP_ASSERT("no previous fragment, this must be the first fragment!", - ipr->p == NULL); -#endif /* IP_REASS_CHECK_OVERLAP */ - /* this is the first fragment we ever received for this ip datagram */ - ipr->p = p; - } - } - - /* Track the current number of pbufs current 'in-flight', in order to limit - the number of fragments that may be enqueued at any one time */ - ip6_reass_pbufcount += clen; - - /* Remember IPv6 header if this is the first fragment. */ - if (iprh->start == 0) { -#if IPV6_FRAG_COPYHEADER - if (iprh->next_pbuf != NULL) { - MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN); - } -#else /* IPV6_FRAG_COPYHEADER */ - /* need to use the none-const pointer here: */ - ipr->iphdr = ip_data.current_ip6_header; -#endif /* IPV6_FRAG_COPYHEADER */ - } - - /* If this is the last fragment, calculate total packet length. */ - if ((offset & IP6_FRAG_MORE_FLAG) == 0) { - ipr->datagram_len = iprh->end; - } - - /* Additional validity tests: we have received first and last fragment. */ - iprh_tmp = (struct ip6_reass_helper*)ipr->p->payload; - if (iprh_tmp->start != 0) { - valid = 0; - } - if (ipr->datagram_len == 0) { - valid = 0; - } - - /* Final validity test: no gaps between current and last fragment. */ - iprh_prev = iprh; - q = iprh->next_pbuf; - while ((q != NULL) && valid) { - iprh = (struct ip6_reass_helper*)q->payload; - if (iprh_prev->end != iprh->start) { - valid = 0; - break; - } - iprh_prev = iprh; - q = iprh->next_pbuf; - } - - if (valid) { - /* All fragments have been received */ - struct ip6_hdr* iphdr_ptr; - - /* chain together the pbufs contained within the ip6_reassdata list. */ - iprh = (struct ip6_reass_helper*) ipr->p->payload; - while (iprh != NULL) { - struct pbuf* next_pbuf = iprh->next_pbuf; - if (next_pbuf != NULL) { - /* Save next helper struct (will be hidden in next step). */ - iprh_tmp = (struct ip6_reass_helper*)next_pbuf->payload; - - /* hide the fragment header for every succeeding fragment */ - pbuf_header(next_pbuf, -IP6_FRAG_HLEN); -#if IPV6_FRAG_COPYHEADER - if (IPV6_FRAG_REQROOM > 0) { - /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ - u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); - LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); - } -#endif - pbuf_cat(ipr->p, next_pbuf); - } - else { - iprh_tmp = NULL; - } - - iprh = iprh_tmp; - } - -#if IPV6_FRAG_COPYHEADER - if (IPV6_FRAG_REQROOM > 0) { - /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ - u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); - LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); - } - iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); - MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN); -#else - iphdr_ptr = ipr->iphdr; -#endif - - /* Adjust datagram length by adding header lengths. */ - ipr->datagram_len += (u16_t)(((u8_t*)ipr->p->payload - (u8_t*)iphdr_ptr) - + IP6_FRAG_HLEN - - IP6_HLEN); - - /* Set payload length in ip header. */ - iphdr_ptr->_plen = lwip_htons(ipr->datagram_len); - - /* Get the first pbuf. */ - p = ipr->p; - - /* Restore Fragment Header in first pbuf. Mark as "single fragment" - * packet. Restore nexth. */ - frag_hdr = (struct ip6_frag_hdr *) p->payload; - frag_hdr->_nexth = ipr->nexth; - frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = 0; - frag_hdr->_identification = 0; - - /* release the sources allocate for the fragment queue entry */ - if (reassdatagrams == ipr) { - /* it was the first in the list */ - reassdatagrams = ipr->next; - } else { - /* it wasn't the first, so it must have a valid 'prev' */ - LWIP_ASSERT("sanity check linked list", ipr_prev != NULL); - ipr_prev->next = ipr->next; - } - memp_free(MEMP_IP6_REASSDATA, ipr); - - /* adjust the number of pbufs currently queued for reassembly. */ - ip6_reass_pbufcount -= pbuf_clen(p); - - /* Move pbuf back to IPv6 header. - This cannot fail since we already checked when receiving this fragment. */ - if (pbuf_header_force(p, (s16_t)((u8_t*)p->payload - (u8_t*)iphdr_ptr))) { - LWIP_ASSERT("ip6_reass: moving p->payload to ip6 header failed\n", 0); - pbuf_free(p); - return NULL; - } - - /* Return the pbuf chain */ - return p; - } - /* the datagram is not (yet?) reassembled completely */ - return NULL; - -nullreturn: - pbuf_free(p); - return NULL; -} - -#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_FRAG - -#if !LWIP_NETIF_TX_SINGLE_PBUF -/** Allocate a new struct pbuf_custom_ref */ -static struct pbuf_custom_ref* -ip6_frag_alloc_pbuf_custom_ref(void) -{ - return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF); -} - -/** Free a struct pbuf_custom_ref */ -static void -ip6_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p) -{ - LWIP_ASSERT("p != NULL", p != NULL); - memp_free(MEMP_FRAG_PBUF, p); -} - -/** Free-callback function to free a 'struct pbuf_custom_ref', called by - * pbuf_free. */ -static void -ip6_frag_free_pbuf_custom(struct pbuf *p) -{ - struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p; - LWIP_ASSERT("pcr != NULL", pcr != NULL); - LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p); - if (pcr->original != NULL) { - pbuf_free(pcr->original); - } - ip6_frag_free_pbuf_custom_ref(pcr); -} -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ - -/** - * Fragment an IPv6 datagram if too large for the netif or path MTU. - * - * Chop the datagram in MTU sized chunks and send them in order - * by pointing PBUF_REFs into p - * - * @param p ipv6 packet to send - * @param netif the netif on which to send - * @param dest destination ipv6 address to which to send - * - * @return ERR_OK if sent successfully, err_t otherwise - */ -err_t -ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) -{ - struct ip6_hdr *original_ip6hdr; - struct ip6_hdr *ip6hdr; - struct ip6_frag_hdr *frag_hdr; - struct pbuf *rambuf; -#if !LWIP_NETIF_TX_SINGLE_PBUF - struct pbuf *newpbuf; - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif - static u32_t identification; - u16_t nfb; - u16_t left, cop; - u16_t mtu; - u16_t fragment_offset = 0; - u16_t last; - u16_t poff = IP6_HLEN; - - identification++; - - original_ip6hdr = (struct ip6_hdr *)p->payload; - - mtu = nd6_get_destination_mtu(dest, netif); - - /* @todo we assume there are no options in the unfragmentable part (IPv6 header). */ - left = p->tot_len - IP6_HLEN; - - nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK; - - while (left) { - last = (left <= nfb); - - /* Fill this fragment */ - cop = last ? left : nfb; - -#if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM); - if (rambuf == NULL) { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); - poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff); - /* make room for the IP header */ - if (pbuf_header(rambuf, IP6_HLEN)) { - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - /* fill in the IP header */ - SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); - ip6hdr = (struct ip6_hdr *)rambuf->payload; - frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); -#else - /* When not using a static buffer, create a chain of pbufs. - * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. - * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, - * but limited to the size of an mtu. - */ - rambuf = pbuf_alloc(PBUF_LINK, IP6_HLEN + IP6_FRAG_HLEN, PBUF_RAM); - if (rambuf == NULL) { - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP6_HLEN))); - SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); - ip6hdr = (struct ip6_hdr *)rambuf->payload; - frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); - - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - p->tot_len -= poff; - - left_to_copy = cop; - while (left_to_copy) { - struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; - /* Is this pbuf already empty? */ - if (!newpbuflen) { - p = p->next; - continue; - } - pcr = ip6_frag_alloc_pbuf_custom_ref(); - if (pcr == NULL) { - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); - if (newpbuf == NULL) { - ip6_frag_free_pbuf_custom_ref(pcr); - pbuf_free(rambuf); - IP6_FRAG_STATS_INC(ip6_frag.memerr); - return ERR_MEM; - } - pbuf_ref(p); - pcr->original = p; - pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom; - - /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain - * so that it is removed when pbuf_dechain is later called on rambuf. - */ - pbuf_cat(rambuf, newpbuf); - left_to_copy -= newpbuflen; - if (left_to_copy) { - p = p->next; - } - } - poff = newpbuflen; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - /* Set headers */ - frag_hdr->_nexth = original_ip6hdr->_nexth; - frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); - frag_hdr->_identification = lwip_htonl(identification); - - IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); - IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); - - /* No need for separate header pbuf - we allowed room for it in rambuf - * when allocated. - */ - IP6_FRAG_STATS_INC(ip6_frag.xmit); - netif->output_ip6(netif, rambuf, dest); - - /* Unfortunately we can't reuse rambuf - the hardware may still be - * using the buffer. Instead we free it (and the ensuing chain) and - * recreate it next time round the loop. If we're lucky the hardware - * will have already sent the packet, the free will really free, and - * there will be zero memory penalty. - */ - - pbuf_free(rambuf); - left -= cop; - fragment_offset += cop; - } - return ERR_OK; -} - -#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/mld6.c b/components/net/lwip-2.0.2/src/core/ipv6/mld6.c deleted file mode 100644 index 9acb82fe24..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/mld6.c +++ /dev/null @@ -1,588 +0,0 @@ -/** - * @file - * Multicast listener discovery - * - * @defgroup mld6 MLD6 - * @ingroup ip6 - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2.\n - * To be called from TCPIP thread - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -/* Based on igmp.c implementation of igmp v2 protocol */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mld6.h" -#include "lwip/prot/mld6.h" -#include "lwip/icmp6.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip.h" -#include "lwip/inet_chksum.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/memp.h" -#include "lwip/stats.h" - -#include - - -/* - * MLD constants - */ -#define MLD6_HL 1 -#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) - -#define MLD6_GROUP_NON_MEMBER 0 -#define MLD6_GROUP_DELAYING_MEMBER 1 -#define MLD6_GROUP_IDLE_MEMBER 2 - -/* Forward declarations. */ -static struct mld_group *mld6_new_group(struct netif *ifp, const ip6_addr_t *addr); -static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); -static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); -static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); - - -/** - * Stop MLD processing on interface - * - * @param netif network interface on which stop MLD processing - */ -err_t -mld6_stop(struct netif *netif) -{ - struct mld_group *group = netif_mld6_data(netif); - - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); - - while (group != NULL) { - struct mld_group *next = group->next; /* avoid use-after-free below */ - - /* disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, &(group->group_address), NETIF_DEL_MAC_FILTER); - } - - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); - - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report MLD memberships for this interface - * - * @param netif network interface on which report MLD memberships - */ -void -mld6_report_groups(struct netif *netif) -{ - struct mld_group *group = netif_mld6_data(netif); - - while (group != NULL) { - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - group = group->next; - } -} - -/** - * Search for a group that is joined on a netif - * - * @param ifp the network interface for which to look - * @param addr the group ipv6 address to search for - * @return a struct mld_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct mld_group * -mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr) -{ - struct mld_group *group = netif_mld6_data(ifp); - - while (group != NULL) { - if (ip6_addr_cmp(&(group->group_address), addr)) { - return group; - } - group = group->next; - } - - return NULL; -} - - -/** - * create a new group - * - * @param ifp the network interface for which to create - * @param addr the new group ipv6 - * @return a struct mld_group*, - * NULL on memory error. - */ -static struct mld_group * -mld6_new_group(struct netif *ifp, const ip6_addr_t *addr) -{ - struct mld_group *group; - - group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); - if (group != NULL) { - ip6_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - group->next = netif_mld6_data(ifp); - - netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); - } - - return group; -} - -/** - * Remove a group from the mld_group_list, but do not free it yet - * - * @param group the group to remove - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t -mld6_remove_group(struct netif *netif, struct mld_group *group) -{ - err_t err = ERR_OK; - - /* Is it the first group? */ - if (netif_mld6_data(netif) == group) { - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group->next); - } else { - /* look for group further down the list */ - struct mld_group *tmpGroup; - for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { - if (tmpGroup->next == group) { - tmpGroup->next = group->next; - break; - } - } - /* Group not find group */ - if (tmpGroup == NULL) { - err = ERR_ARG; - } - } - - return err; -} - - -/** - * Process an input MLD message. Called by icmp6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -mld6_input(struct pbuf *p, struct netif *inp) -{ - struct mld_header *mld_hdr; - struct mld_group *group; - - MLD6_STATS_INC(mld6.recv); - - /* Check that mld header fits in packet. */ - if (p->len < sizeof(struct mld_header)) { - /* @todo debug message */ - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - MLD6_STATS_INC(mld6.drop); - return; - } - - mld_hdr = (struct mld_header *)p->payload; - - switch (mld_hdr->type) { - case ICMP6_TYPE_MLQ: /* Multicast listener query. */ - /* Is it a general query? */ - if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && - ip6_addr_isany(&(mld_hdr->multicast_address))) { - MLD6_STATS_INC(mld6.rx_general); - /* Report all groups, except all nodes group, and if-local groups. */ - group = netif_mld6_data(inp); - while (group != NULL) { - if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && - (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - group = group->next; - } - } else { - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_group); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* Schedule a report. */ - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - } - break; /* ICMP6_TYPE_MLQ */ - case ICMP6_TYPE_MLR: /* Multicast listener report. */ - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_report); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* If we are waiting to report, cancel it. */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - group->timer = 0; /* stopped */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - } - break; /* ICMP6_TYPE_MLR */ - case ICMP6_TYPE_MLD: /* Multicast listener done. */ - /* Do nothing, router will query us. */ - break; /* ICMP6_TYPE_MLD */ - default: - MLD6_STATS_INC(mld6.proterr); - MLD6_STATS_INC(mld6.drop); - break; - } - - pbuf_free(p); -} - -/** - * @ingroup mld6 - * Join a group on a network interface. - * - * @param srcaddr ipv6 address of the network interface which should - * join a new group. If IP6_ADDR_ANY, join on all netifs - * @param groupaddr the ipv6 address of the group to join - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t -mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we join this interface ? */ - if (ip6_addr_isany(srcaddr) || - netif_get_ip6_addr_match(netif, srcaddr) >= 0) { - err = mld6_joingroup_netif(netif, groupaddr); - if (err != ERR_OK) { - return err; - } - } - - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup mld6 - * Join a group on a network interface. - * - * @param netif the network interface which should join a new group. - * @param groupaddr the ipv6 address of the group to join - * @return ERR_OK if group was joined on the netif, an err_t otherwise - */ -err_t -mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) -{ - struct mld_group *group; - - /* find group or create a new one if not found */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group == NULL) { - /* Joining a new group. Create a new group entry. */ - group = mld6_new_group(netif, groupaddr); - if (group == NULL) { - return ERR_MEM; - } - - /* Activate this address on the MAC layer. */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); - } - - /* Report our membership. */ - MLD6_STATS_INC(mld6.tx_report); - mld6_send(netif, group, ICMP6_TYPE_MLR); - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - } - - /* Increment group use */ - group->use++; - return ERR_OK; -} - -/** - * @ingroup mld6 - * Leave a group on a network interface. - * - * @param srcaddr ipv6 address of the network interface which should - * leave the group. If IP6_ISANY, leave on all netifs - * @param groupaddr the ipv6 address of the group to leave - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t -mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) -{ - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - /* loop through netif's */ - netif = netif_list; - while (netif != NULL) { - /* Should we leave this interface ? */ - if (ip6_addr_isany(srcaddr) || - netif_get_ip6_addr_match(netif, srcaddr) >= 0) { - err_t res = mld6_leavegroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Store this result if we have not yet gotten a success */ - err = res; - } - } - /* proceed to next network interface */ - netif = netif->next; - } - - return err; -} - -/** - * @ingroup mld6 - * Leave a group on a network interface. - * - * @param netif the network interface which should leave the group. - * @param groupaddr the ipv6 address of the group to leave - * @return ERR_OK if group was left on the netif, an err_t otherwise - */ -err_t -mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) -{ - struct mld_group *group; - - /* find group */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Leave if there is no other use of the group */ - if (group->use <= 1) { - /* Remove the group from the list */ - mld6_remove_group(netif, group); - - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - MLD6_STATS_INC(mld6.tx_leave); - mld6_send(netif, group, ICMP6_TYPE_MLD); - } - - /* Disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); - } - - /* free group struct */ - memp_free(MEMP_MLD6_GROUP, group); - } else { - /* Decrement group use */ - group->use--; - } - - /* Left group */ - return ERR_OK; - } - - /* Group not found */ - return ERR_VAL; -} - - -/** - * Periodic timer for mld processing. Must be called every - * MLD6_TMR_INTERVAL milliseconds (100). - * - * When a delaying member expires, a membership report is sent. - */ -void -mld6_tmr(void) -{ - struct netif *netif = netif_list; - - while (netif != NULL) { - struct mld_group *group = netif_mld6_data(netif); - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report for this group */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - MLD6_STATS_INC(mld6.tx_report); - mld6_send(netif, group, ICMP6_TYPE_MLR); - group->group_state = MLD6_GROUP_IDLE_MEMBER; - } - } - } - group = group->next; - } - netif = netif->next; - } -} - -/** - * Schedule a delayed membership report for a group - * - * @param group the mld_group for which "delaying" membership report - * should be sent - * @param maxresp the max resp delay provided in the query - */ -static void -mld6_delayed_report(struct mld_group *group, u16_t maxresp) -{ - /* Convert maxresp from milliseconds to tmr ticks */ - maxresp = maxresp / MLD6_TMR_INTERVAL; - if (maxresp == 0) { - maxresp = 1; - } - -#ifdef LWIP_RAND - /* Randomize maxresp. (if LWIP_RAND is supported) */ - maxresp = LWIP_RAND() % maxresp; - if (maxresp == 0) { - maxresp = 1; - } -#endif /* LWIP_RAND */ - - /* Apply timer value if no report has been scheduled already. */ - if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || - ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - group->timer = maxresp; - group->group_state = MLD6_GROUP_DELAYING_MEMBER; - } -} - -/** - * Send a MLD message (report or done). - * - * An IPv6 hop-by-hop options header with a router alert option - * is prepended. - * - * @param group the group to report or quit - * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) - */ -static void -mld6_send(struct netif *netif, struct mld_group *group, u8_t type) -{ - struct mld_header *mld_hdr; - struct pbuf *p; - const ip6_addr_t *src_addr; - - /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + sizeof(struct ip6_hbh_hdr), PBUF_RAM); - if (p == NULL) { - MLD6_STATS_INC(mld6.memerr); - return; - } - - /* Move to make room for Hop-by-hop options header. */ - if (pbuf_header(p, -IP6_HBH_HLEN)) { - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - return; - } - - /* Select our source address. */ - if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { - /* This is a special case, when we are performing duplicate address detection. - * We must join the multicast group, but we don't have a valid address yet. */ - src_addr = IP6_ADDR_ANY6; - } else { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); - } - - /* MLD message header pointer. */ - mld_hdr = (struct mld_header *)p->payload; - - /* Set fields. */ - mld_hdr->type = type; - mld_hdr->code = 0; - mld_hdr->chksum = 0; - mld_hdr->max_resp_delay = 0; - mld_hdr->reserved = 0; - ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, - src_addr, &(group->group_address)); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Add hop-by-hop headers options: router alert with MLD value. */ - ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); - - if (type == ICMP6_TYPE_MLR) { - /* Remember we were the last to report */ - group->last_reporter_flag = 1; - } - - /* Send the packet out. */ - MLD6_STATS_INC(mld6.xmit); - ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), - MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); - pbuf_free(p); -} - -#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/ipv6/nd6.c b/components/net/lwip-2.0.2/src/core/ipv6/nd6.c deleted file mode 100644 index 0b367181b2..0000000000 --- a/components/net/lwip-2.0.2/src/core/ipv6/nd6.c +++ /dev/null @@ -1,2102 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/nd6.h" -#include "lwip/priv/nd6_priv.h" -#include "lwip/prot/nd6.h" -#include "lwip/prot/icmp6.h" -#include "lwip/pbuf.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" -#include "lwip/netif.h" -#include "lwip/icmp6.h" -#include "lwip/mld6.h" -#include "lwip/ip.h" -#include "lwip/stats.h" -#include "lwip/dns.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK -#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK -#endif - -/* Router tables. */ -struct nd6_neighbor_cache_entry neighbor_cache[LWIP_ND6_NUM_NEIGHBORS]; -struct nd6_destination_cache_entry destination_cache[LWIP_ND6_NUM_DESTINATIONS]; -struct nd6_prefix_list_entry prefix_list[LWIP_ND6_NUM_PREFIXES]; -struct nd6_router_list_entry default_router_list[LWIP_ND6_NUM_ROUTERS]; - -/* Default values, can be updated by a RA message. */ -u32_t reachable_time = LWIP_ND6_REACHABLE_TIME; -u32_t retrans_timer = LWIP_ND6_RETRANS_TIMER; /* @todo implement this value in timer */ - -/* Index for cache entries. */ -static u8_t nd6_cached_neighbor_index; -static u8_t nd6_cached_destination_index; - -/* Multicast address holder. */ -static ip6_addr_t multicast_address; - -/* Static buffer to parse RA packet options (size of a prefix option, biggest option) */ -static u8_t nd6_ra_buffer[sizeof(struct prefix_option)]; - -/* Forward declarations. */ -static s8_t nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr); -static s8_t nd6_new_neighbor_cache_entry(void); -static void nd6_free_neighbor_cache_entry(s8_t i); -static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); -static s8_t nd6_new_destination_cache_entry(void); -static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); -static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); -static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); -static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); -static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); -static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); -static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); -static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); - -#define ND6_SEND_FLAG_MULTICAST_DEST 0x01 -#define ND6_SEND_FLAG_ALLNODES_DEST 0x02 -static void nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); -static void nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags); -static void nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags); -#if LWIP_IPV6_SEND_ROUTER_SOLICIT -static err_t nd6_send_rs(struct netif *netif); -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -#if LWIP_ND6_QUEUEING -static void nd6_free_q(struct nd6_q_entry *q); -#else /* LWIP_ND6_QUEUEING */ -#define nd6_free_q(q) pbuf_free(q) -#endif /* LWIP_ND6_QUEUEING */ -static void nd6_send_q(s8_t i); - - -/** - * Process an incoming neighbor discovery message - * - * @param p the nd packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void -nd6_input(struct pbuf *p, struct netif *inp) -{ - u8_t msg_type; - s8_t i; - - ND6_STATS_INC(nd6.recv); - - msg_type = *((u8_t *)p->payload); - switch (msg_type) { - case ICMP6_TYPE_NA: /* Neighbor Advertisement. */ - { - struct na_header *na_hdr; - struct lladdr_option *lladdr_opt; - - /* Check that na header fits in packet. */ - if (p->len < (sizeof(struct na_header))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - na_hdr = (struct na_header *)p->payload; - - /* Unsolicited NA?*/ - if (ip6_addr_ismulticast(ip6_current_dest_addr())) { - ip6_addr_t target_address; - - /* This is an unsolicited NA. - * link-layer changed? - * part of DAD mechanism? */ - - /* Create an aligned copy. */ - ip6_addr_set(&target_address, &(na_hdr->target_address)); - -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS - /* If the target address matches this netif, it is a DAD response. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { - /* We are using a duplicate address. */ - netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); - -#if LWIP_IPV6_AUTOCONFIG - /* Check to see if this address was autoconfigured. */ - if (!ip6_addr_islinklocal(&target_address)) { - i = nd6_get_onlink_prefix(&target_address, inp); - if (i >= 0) { - /* Mark this prefix as duplicate, so that we don't use it - * to generate this address again. */ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE; - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - - pbuf_free(p); - return; - } - } -#endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ - - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + 2)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - /* This is an unsolicited NA, most likely there was a LLADDR change. */ - i = nd6_find_neighbor_cache_entry(&target_address); - if (i >= 0) { - if (na_hdr->flags & ND6_FLAG_OVERRIDE) { - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - } - } - } else { - ip6_addr_t target_address; - - /* This is a solicited NA. - * neighbor address resolution response? - * neighbor unreachability detection response? */ - - /* Create an aligned copy. */ - ip6_addr_set(&target_address, &(na_hdr->target_address)); - - /* Find the cache entry corresponding to this na. */ - i = nd6_find_neighbor_cache_entry(&target_address); - if (i < 0) { - /* We no longer care about this target address. drop it. */ - pbuf_free(p); - return; - } - - /* Update cache entry. */ - if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || - (neighbor_cache[i].state == ND6_INCOMPLETE)) { - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + 2)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - } - - neighbor_cache[i].netif = inp; - neighbor_cache[i].state = ND6_REACHABLE; - neighbor_cache[i].counter.reachable_time = reachable_time; - - /* Send queued packets, if any. */ - if (neighbor_cache[i].q != NULL) { - nd6_send_q(i); - } - } - - break; /* ICMP6_TYPE_NA */ - } - case ICMP6_TYPE_NS: /* Neighbor solicitation. */ - { - struct ns_header *ns_hdr; - struct lladdr_option *lladdr_opt; - u8_t accepted; - - /* Check that ns header fits in packet. */ - if (p->len < sizeof(struct ns_header)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - ns_hdr = (struct ns_header *)p->payload; - - /* Check if there is a link-layer address provided. Only point to it if in this buffer. */ - if (p->len >= (sizeof(struct ns_header) + 2)) { - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); - if (p->len < (sizeof(struct ns_header) + (lladdr_opt->length << 3))) { - lladdr_opt = NULL; - } - } else { - lladdr_opt = NULL; - } - - /* Check if the target address is configured on the receiving netif. */ - accepted = 0; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) || - (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) && - ip6_addr_isany(ip6_current_src_addr()))) && - ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { - accepted = 1; - break; - } - } - - /* NS not for us? */ - if (!accepted) { - pbuf_free(p); - return; - } - - /* Check for ANY address in src (DAD algorithm). */ - if (ip6_addr_isany(ip6_current_src_addr())) { - /* Sender is validating this address. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) { - /* Send a NA back so that the sender does not use this address. */ - nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST); - if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) { - /* We shouldn't use this address either. */ - netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); - } - } - } - } else { - ip6_addr_t target_address; - - /* Sender is trying to resolve our address. */ - /* Verify that they included their own link-layer address. */ - if (lladdr_opt == NULL) { - /* Not a valid message. */ - pbuf_free(p); - ND6_STATS_INC(nd6.proterr); - ND6_STATS_INC(nd6.drop); - return; - } - - i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); - if (i>= 0) { - /* We already have a record for the solicitor. */ - if (neighbor_cache[i].state == ND6_INCOMPLETE) { - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - - /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - } else { - /* Add their IPv6 address and link-layer address to neighbor cache. - * We will need it at least to send a unicast NA message, but most - * likely we will also be communicating with this node soon. */ - i = nd6_new_neighbor_cache_entry(); - if (i < 0) { - /* We couldn't assign a cache entry for this neighbor. - * we won't be able to reply. drop it. */ - pbuf_free(p); - ND6_STATS_INC(nd6.memerr); - return; - } - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); - - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - - /* Create an aligned copy. */ - ip6_addr_set(&target_address, &(ns_hdr->target_address)); - - /* Send back a NA for us. Allocate the reply pbuf. */ - nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); - } - - break; /* ICMP6_TYPE_NS */ - } - case ICMP6_TYPE_RA: /* Router Advertisement. */ - { - struct ra_header *ra_hdr; - u8_t *buffer; /* Used to copy options. */ - u16_t offset; -#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS - /* There can by multiple RDNSS options per RA */ - u8_t rdnss_server_idx = 0; -#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ - - /* Check that RA header fits in packet. */ - if (p->len < sizeof(struct ra_header)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - ra_hdr = (struct ra_header *)p->payload; - - /* If we are sending RS messages, stop. */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* ensure at least one solicitation is sent */ - if ((inp->rs_count < LWIP_ND6_MAX_MULTICAST_SOLICIT) || - (nd6_send_rs(inp) == ERR_OK)) { - inp->rs_count = 0; - } -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - - /* Get the matching default router entry. */ - i = nd6_get_router(ip6_current_src_addr(), inp); - if (i < 0) { - /* Create a new router entry. */ - i = nd6_new_router(ip6_current_src_addr(), inp); - } - - if (i < 0) { - /* Could not create a new router entry. */ - pbuf_free(p); - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Re-set invalidation timer. */ - default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); - - /* Re-set default timer values. */ -#if LWIP_ND6_ALLOW_RA_UPDATES - if (ra_hdr->retrans_timer > 0) { - retrans_timer = lwip_htonl(ra_hdr->retrans_timer); - } - if (ra_hdr->reachable_time > 0) { - reachable_time = lwip_htonl(ra_hdr->reachable_time); - } -#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ - - /* @todo set default hop limit... */ - /* ra_hdr->current_hop_limit;*/ - - /* Update flags in local entry (incl. preference). */ - default_router_list[i].flags = ra_hdr->flags; - - /* Offset to options. */ - offset = sizeof(struct ra_header); - - /* Process each option. */ - while ((p->tot_len - offset) > 0) { - if (p->len == p->tot_len) { - /* no need to copy from contiguous pbuf */ - buffer = &((u8_t*)p->payload)[offset]; - } else { - buffer = nd6_ra_buffer; - if (pbuf_copy_partial(p, buffer, sizeof(struct prefix_option), offset) != sizeof(struct prefix_option)) { - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - } - if (buffer[1] == 0) { - /* zero-length extension. drop packet */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - switch (buffer[0]) { - case ND6_OPTION_TYPE_SOURCE_LLADDR: - { - struct lladdr_option *lladdr_opt; - lladdr_opt = (struct lladdr_option *)buffer; - if ((default_router_list[i].neighbor_entry != NULL) && - (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) { - SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->hwaddr_len); - default_router_list[i].neighbor_entry->state = ND6_REACHABLE; - default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time; - } - break; - } - case ND6_OPTION_TYPE_MTU: - { - struct mtu_option *mtu_opt; - mtu_opt = (struct mtu_option *)buffer; - if (lwip_htonl(mtu_opt->mtu) >= 1280) { -#if LWIP_ND6_ALLOW_RA_UPDATES - inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); -#endif /* LWIP_ND6_ALLOW_RA_UPDATES */ - } - break; - } - case ND6_OPTION_TYPE_PREFIX_INFO: - { - struct prefix_option *prefix_opt; - prefix_opt = (struct prefix_option *)buffer; - - if ((prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) && - (prefix_opt->prefix_length == 64) && - !ip6_addr_islinklocal(&(prefix_opt->prefix))) { - /* Add to on-link prefix list. */ - s8_t prefix; - ip6_addr_t prefix_addr; - - /* Get a memory-aligned copy of the prefix. */ - ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); - - /* find cache entry for this prefix. */ - prefix = nd6_get_onlink_prefix(&prefix_addr, inp); - if (prefix < 0) { - /* Create a new cache entry. */ - prefix = nd6_new_onlink_prefix(&prefix_addr, inp); - } - if (prefix >= 0) { - prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); - -#if LWIP_IPV6_AUTOCONFIG - if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { - /* Mark prefix as autonomous, so that address autoconfiguration can take place. - * Only OR flag, so that we don't over-write other flags (such as ADDRESS_DUPLICATE)*/ - prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS; - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - } - } - - break; - } - case ND6_OPTION_TYPE_ROUTE_INFO: - /* @todo implement preferred routes. - struct route_option * route_opt; - route_opt = (struct route_option *)buffer;*/ - - break; -#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS - case ND6_OPTION_TYPE_RDNSS: - { - u8_t num, n; - struct rdnss_option * rdnss_opt; - - rdnss_opt = (struct rdnss_option *)buffer; - num = (rdnss_opt->length - 1) / 2; - for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { - ip_addr_t rdnss_address; - - /* Get a memory-aligned copy of the prefix. */ - ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); - - if (htonl(rdnss_opt->lifetime) > 0) { - /* TODO implement Lifetime > 0 */ - dns_setserver(rdnss_server_idx++, &rdnss_address); - } else { - /* TODO implement DNS removal in dns.c */ - u8_t s; - for (s = 0; s < DNS_MAX_SERVERS; s++) { - const ip_addr_t *addr = dns_getserver(s); - if(ip_addr_cmp(addr, &rdnss_address)) { - dns_setserver(s, NULL); - } - } - } - } - break; - } -#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ - default: - /* Unrecognized option, abort. */ - ND6_STATS_INC(nd6.proterr); - break; - } - /* option length is checked earlier to be non-zero to make sure loop ends */ - offset += 8 * ((u16_t)buffer[1]); - } - - break; /* ICMP6_TYPE_RA */ - } - case ICMP6_TYPE_RD: /* Redirect */ - { - struct redirect_header *redir_hdr; - struct lladdr_option *lladdr_opt; - ip6_addr_t tmp; - - /* Check that Redir header fits in packet. */ - if (p->len < sizeof(struct redirect_header)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - redir_hdr = (struct redirect_header *)p->payload; - - if (p->len >= (sizeof(struct redirect_header) + 2)) { - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct redirect_header)); - if (p->len < (sizeof(struct redirect_header) + (lladdr_opt->length << 3))) { - lladdr_opt = NULL; - } - } else { - lladdr_opt = NULL; - } - - /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(&tmp, &(redir_hdr->destination_address)); - - /* Find dest address in cache */ - i = nd6_find_destination_cache_entry(&tmp); - if (i < 0) { - /* Destination not in cache, drop packet. */ - pbuf_free(p); - return; - } - - /* Set the new target address. */ - ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address)); - - /* If Link-layer address of other router is given, try to add to neighbor cache. */ - if (lladdr_opt != NULL) { - if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { - /* Copy target address to current source address, to have an aligned copy. */ - ip6_addr_set(&tmp, &(redir_hdr->target_address)); - - i = nd6_find_neighbor_cache_entry(&tmp); - if (i < 0) { - i = nd6_new_neighbor_cache_entry(); - if (i >= 0) { - neighbor_cache[i].netif = inp; - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp); - - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - } - if (i >= 0) { - if (neighbor_cache[i].state == ND6_INCOMPLETE) { - MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - /* Receiving a message does not prove reachability: only in one direction. - * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - } - } - } - break; /* ICMP6_TYPE_RD */ - } - case ICMP6_TYPE_PTB: /* Packet too big */ - { - struct icmp6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ - u32_t pmtu; - ip6_addr_t tmp; - - /* Check that ICMPv6 header + IPv6 header fit in payload */ - if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { - /* drop short packets */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - icmp6hdr = (struct icmp6_hdr *)p->payload; - ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); - - /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(&tmp, &(ip6hdr->dest)); - - /* Look for entry in destination cache. */ - i = nd6_find_destination_cache_entry(&tmp); - if (i < 0) { - /* Destination not in cache, drop packet. */ - pbuf_free(p); - return; - } - - /* Change the Path MTU. */ - pmtu = lwip_htonl(icmp6hdr->data); - destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); - - break; /* ICMP6_TYPE_PTB */ - } - - default: - ND6_STATS_INC(nd6.proterr); - ND6_STATS_INC(nd6.drop); - break; /* default */ - } - - pbuf_free(p); -} - - -/** - * Periodic timer for Neighbor discovery functions: - * - * - Update neighbor reachability states - * - Update destination cache entries age - * - Update invalidation timers of default routers and on-link prefixes - * - Perform duplicate address detection (DAD) for our addresses - * - Send router solicitations - */ -void -nd6_tmr(void) -{ - s8_t i; - struct netif *netif; - - /* Process neighbor entries. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - switch (neighbor_cache[i].state) { - case ND6_INCOMPLETE: - if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && - (!neighbor_cache[i].isrouter)) { - /* Retries exceeded. */ - nd6_free_neighbor_cache_entry(i); - } else { - /* Send a NS for this entry. */ - neighbor_cache[i].counter.probes_sent++; - nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); - } - break; - case ND6_REACHABLE: - /* Send queued packets, if any are left. Should have been sent already. */ - if (neighbor_cache[i].q != NULL) { - nd6_send_q(i); - } - if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) { - /* Change to stale state. */ - neighbor_cache[i].state = ND6_STALE; - neighbor_cache[i].counter.stale_time = 0; - } else { - neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL; - } - break; - case ND6_STALE: - neighbor_cache[i].counter.stale_time++; - break; - case ND6_DELAY: - if (neighbor_cache[i].counter.delay_time <= 1) { - /* Change to PROBE state. */ - neighbor_cache[i].state = ND6_PROBE; - neighbor_cache[i].counter.probes_sent = 0; - } else { - neighbor_cache[i].counter.delay_time--; - } - break; - case ND6_PROBE: - if ((neighbor_cache[i].counter.probes_sent >= LWIP_ND6_MAX_MULTICAST_SOLICIT) && - (!neighbor_cache[i].isrouter)) { - /* Retries exceeded. */ - nd6_free_neighbor_cache_entry(i); - } else { - /* Send a NS for this entry. */ - neighbor_cache[i].counter.probes_sent++; - nd6_send_neighbor_cache_probe(&neighbor_cache[i], 0); - } - break; - case ND6_NO_ENTRY: - default: - /* Do nothing. */ - break; - } - } - - /* Process destination entries. */ - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - destination_cache[i].age++; - } - - /* Process router entries. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (default_router_list[i].neighbor_entry != NULL) { - /* Active entry. */ - if (default_router_list[i].invalidation_timer > 0) { - default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - } - if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - /* Less than 1 second remaining. Clear this entry. */ - default_router_list[i].neighbor_entry->isrouter = 0; - default_router_list[i].neighbor_entry = NULL; - default_router_list[i].invalidation_timer = 0; - default_router_list[i].flags = 0; - } - } - } - - /* Process prefix entries. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if (prefix_list[i].netif != NULL) { - if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) { - /* Entry timed out, remove it */ - prefix_list[i].invalidation_timer = 0; - -#if LWIP_IPV6_AUTOCONFIG - /* If any addresses were configured with this prefix, remove them */ - if (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED) { - s8_t j; - - for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { - if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) && - ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) { - netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID); - prefix_list[i].flags = 0; - - /* Exit loop. */ - break; - } - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - - prefix_list[i].netif = NULL; - prefix_list[i].flags = 0; - } else { - prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000; - -#if LWIP_IPV6_AUTOCONFIG - /* Initiate address autoconfiguration for this prefix, if conditions are met. */ - if (prefix_list[i].netif->ip6_autoconfig_enabled && - (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) && - !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) { - s8_t j; - /* Try to get an address on this netif that is invalid. - * Skip 0 index (link-local address) */ - for (j = 1; j < LWIP_IPV6_NUM_ADDRESSES; j++) { - if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) { - /* Generate an address using this prefix and interface ID from link-local address. */ - netif_ip6_addr_set_parts(prefix_list[i].netif, j, - prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1], - netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]); - - /* Mark it as tentative (DAD will be performed if configured). */ - netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE); - - /* Mark this prefix with ADDRESS_GENERATED, so that we don't try again. */ - prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED; - - /* Exit loop. */ - break; - } - } - } -#endif /* LWIP_IPV6_AUTOCONFIG */ - } - } - } - - - /* Process our own addresses, if DAD configured. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; ++i) { - u8_t addr_state = netif_ip6_addr_state(netif, i); - if (ip6_addr_istentative(addr_state)) { - if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) >= LWIP_IPV6_DUP_DETECT_ATTEMPTS) { - /* No NA received in response. Mark address as valid. */ - netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); - /* @todo implement preferred and valid lifetimes. */ - } else if (netif->flags & NETIF_FLAG_UP) { - /* Send a NS for this address. */ - nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); - /* tentative: set next state by increasing by one */ - netif_ip6_addr_set_state(netif, i, addr_state + 1); - /* @todo send max 1 NS per tmr call? enable return*/ - /*return;*/ - } - } - } - } - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* Send router solicitation messages, if necessary. */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - if ((netif->rs_count > 0) && (netif->flags & NETIF_FLAG_UP) && - (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) { - if (nd6_send_rs(netif) == ERR_OK) { - netif->rs_count--; - } - } - } -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -} - -/** Send a neighbor solicitation message for a specific neighbor cache entry - * - * @param entry the neightbor cache entry for wich to send the message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_neighbor_cache_probe(struct nd6_neighbor_cache_entry *entry, u8_t flags) -{ - nd6_send_ns(entry->netif, &entry->next_hop_address, flags); -} - -/** - * Send a neighbor solicitation message - * - * @param netif the netif on which to send the message - * @param target_addr the IPv6 target address for the ND message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_ns(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) -{ - struct ns_header *ns_hdr; - struct pbuf *p; - const ip6_addr_t *src_addr; - u16_t lladdr_opt_len; - - if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); - /* calculate option length (in 8-byte-blocks) */ - lladdr_opt_len = ((netif->hwaddr_len + 2) + 7) >> 3; - } else { - src_addr = IP6_ADDR_ANY6; - /* Option "MUST NOT be included when the source IP address is the unspecified address." */ - lladdr_opt_len = 0; - } - - /* Allocate a packet. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct ns_header) + (lladdr_opt_len << 3), PBUF_RAM); - if (p == NULL) { - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - ns_hdr = (struct ns_header *)p->payload; - - ns_hdr->type = ICMP6_TYPE_NS; - ns_hdr->code = 0; - ns_hdr->chksum = 0; - ns_hdr->reserved = 0; - ip6_addr_set(&(ns_hdr->target_address), target_addr); - - if (lladdr_opt_len != 0) { - struct lladdr_option *lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct ns_header)); - lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; - lladdr_opt->length = (u8_t)lladdr_opt_len; - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - } - - /* Generate the solicited node address for the target address. */ - if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { - ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); - target_addr = &multicast_address; - } - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - target_addr); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, target_addr, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} - -/** - * Send a neighbor advertisement message - * - * @param netif the netif on which to send the message - * @param target_addr the IPv6 target address for the ND message - * @param flags one of ND6_SEND_FLAG_* - */ -static void -nd6_send_na(struct netif *netif, const ip6_addr_t *target_addr, u8_t flags) -{ - struct na_header *na_hdr; - struct lladdr_option *lladdr_opt; - struct pbuf *p; - const ip6_addr_t *src_addr; - const ip6_addr_t *dest_addr; - u16_t lladdr_opt_len; - - /* Use link-local address as source address. */ - /* src_addr = netif_ip6_addr(netif, 0); */ - /* Use target address as source address. */ - src_addr = target_addr; - - /* Allocate a packet. */ - lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - p = pbuf_alloc(PBUF_IP, sizeof(struct na_header) + (lladdr_opt_len << 3), PBUF_RAM); - if (p == NULL) { - ND6_STATS_INC(nd6.memerr); - return; - } - - /* Set fields. */ - na_hdr = (struct na_header *)p->payload; - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - na_hdr->type = ICMP6_TYPE_NA; - na_hdr->code = 0; - na_hdr->chksum = 0; - na_hdr->flags = flags & 0xf0; - na_hdr->reserved[0] = 0; - na_hdr->reserved[1] = 0; - na_hdr->reserved[2] = 0; - ip6_addr_set(&(na_hdr->target_address), target_addr); - - lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR; - lladdr_opt->length = (u8_t)lladdr_opt_len; - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - - /* Generate the solicited node address for the target address. */ - if (flags & ND6_SEND_FLAG_MULTICAST_DEST) { - ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]); - dest_addr = &multicast_address; - } else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) { - ip6_addr_set_allnodes_linklocal(&multicast_address); - dest_addr = &multicast_address; - } else { - dest_addr = ip6_current_src_addr(); - } - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - dest_addr); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - ip6_output_if(p, src_addr, dest_addr, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); -} - -#if LWIP_IPV6_SEND_ROUTER_SOLICIT -/** - * Send a router solicitation message - * - * @param netif the netif on which to send the message - */ -static err_t -nd6_send_rs(struct netif *netif) -{ - struct rs_header *rs_hdr; - struct lladdr_option *lladdr_opt; - struct pbuf *p; - const ip6_addr_t *src_addr; - err_t err; - u16_t lladdr_opt_len = 0; - - /* Link-local source address, or unspecified address? */ - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { - src_addr = netif_ip6_addr(netif, 0); - } else { - src_addr = IP6_ADDR_ANY6; - } - - /* Generate the all routers target address. */ - ip6_addr_set_allrouters_linklocal(&multicast_address); - - /* Allocate a packet. */ - if (src_addr != IP6_ADDR_ANY6) { - lladdr_opt_len = ((netif->hwaddr_len + 2) >> 3) + (((netif->hwaddr_len + 2) & 0x07) ? 1 : 0); - } - p = pbuf_alloc(PBUF_IP, sizeof(struct rs_header) + (lladdr_opt_len << 3), PBUF_RAM); - if (p == NULL) { - ND6_STATS_INC(nd6.memerr); - return ERR_BUF; - } - - /* Set fields. */ - rs_hdr = (struct rs_header *)p->payload; - - rs_hdr->type = ICMP6_TYPE_RS; - rs_hdr->code = 0; - rs_hdr->chksum = 0; - rs_hdr->reserved = 0; - - if (src_addr != IP6_ADDR_ANY6) { - /* Include our hw address. */ - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct rs_header)); - lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR; - lladdr_opt->length = (u8_t)lladdr_opt_len; - SMEMCPY(lladdr_opt->addr, netif->hwaddr, netif->hwaddr_len); - } - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - &multicast_address); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Send the packet out. */ - ND6_STATS_INC(nd6.xmit); - - err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ? NULL : src_addr, &multicast_address, - LWIP_ICMP6_HL, 0, IP6_NEXTH_ICMP6, netif); - pbuf_free(p); - - return err; -} -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - -/** - * Search for a neighbor cache entry - * - * @param ip6addr the IPv6 address of the neighbor - * @return The neighbor cache entry index that matched, -1 if no - * entry is found - */ -static s8_t -nd6_find_neighbor_cache_entry(const ip6_addr_t *ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) { - return i; - } - } - return -1; -} - -/** - * Create a new neighbor cache entry. - * - * If no unused entry is found, will try to recycle an old entry - * according to ad-hoc "age" heuristic. - * - * @return The neighbor cache entry index that was created, -1 if no - * entry could be created - */ -static s8_t -nd6_new_neighbor_cache_entry(void) -{ - s8_t i; - s8_t j; - u32_t time; - - - /* First, try to find an empty entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (neighbor_cache[i].state == ND6_NO_ENTRY) { - return i; - } - } - - /* We need to recycle an entry. in general, do not recycle if it is a router. */ - - /* Next, try to find a Stale entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_STALE) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find a Probe entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_PROBE) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find a Delayed entry. */ - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_DELAY) && - (!neighbor_cache[i].isrouter)) { - nd6_free_neighbor_cache_entry(i); - return i; - } - } - - /* Next, try to find the oldest reachable entry. */ - time = 0xfffffffful; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_REACHABLE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.reachable_time < time) { - j = i; - time = neighbor_cache[i].counter.reachable_time; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* Next, find oldest incomplete entry without queued packets. */ - time = 0; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ( - (neighbor_cache[i].q == NULL) && - (neighbor_cache[i].state == ND6_INCOMPLETE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.probes_sent >= time) { - j = i; - time = neighbor_cache[i].counter.probes_sent; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* Next, find oldest incomplete entry with queued packets. */ - time = 0; - j = -1; - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if ((neighbor_cache[i].state == ND6_INCOMPLETE) && - (!neighbor_cache[i].isrouter)) { - if (neighbor_cache[i].counter.probes_sent >= time) { - j = i; - time = neighbor_cache[i].counter.probes_sent; - } - } - } - if (j >= 0) { - nd6_free_neighbor_cache_entry(j); - return j; - } - - /* No more entries to try. */ - return -1; -} - -/** - * Will free any resources associated with a neighbor cache - * entry, and will mark it as unused. - * - * @param i the neighbor cache entry index to free - */ -static void -nd6_free_neighbor_cache_entry(s8_t i) -{ - if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { - return; - } - if (neighbor_cache[i].isrouter) { - /* isrouter needs to be cleared before deleting a neighbor cache entry */ - return; - } - - /* Free any queued packets. */ - if (neighbor_cache[i].q != NULL) { - nd6_free_q(neighbor_cache[i].q); - neighbor_cache[i].q = NULL; - } - - neighbor_cache[i].state = ND6_NO_ENTRY; - neighbor_cache[i].isrouter = 0; - neighbor_cache[i].netif = NULL; - neighbor_cache[i].counter.reachable_time = 0; - ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address)); -} - -/** - * Search for a destination cache entry - * - * @param ip6addr the IPv6 address of the destination - * @return The destination cache entry index that matched, -1 if no - * entry is found - */ -static s8_t -nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) { - return i; - } - } - return -1; -} - -/** - * Create a new destination cache entry. If no unused entry is found, - * will recycle oldest entry. - * - * @return The destination cache entry index that was created, -1 if no - * entry was created - */ -static s8_t -nd6_new_destination_cache_entry(void) -{ - s8_t i, j; - u32_t age; - - /* Find an empty entry. */ - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (ip6_addr_isany(&(destination_cache[i].destination_addr))) { - return i; - } - } - - /* Find oldest entry. */ - age = 0; - j = LWIP_ND6_NUM_DESTINATIONS - 1; - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - if (destination_cache[i].age > age) { - j = i; - } - } - - return j; -} - -/** - * Clear the destination cache. - * - * This operation may be necessary for consistency in the light of changing - * local addresses and/or use of the gateway hook. - */ -void -nd6_clear_destination_cache(void) -{ - int i; - - for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { - ip6_addr_set_any(&destination_cache[i].destination_addr); - } -} - -/** - * Determine whether an address matches an on-link prefix. - * - * @param ip6addr the IPv6 address to match - * @return 1 if the address is on-link, 0 otherwise - */ -static s8_t -nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) -{ - s8_t i; - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if ((prefix_list[i].netif == netif) && - (prefix_list[i].invalidation_timer > 0) && - ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) { - return 1; - } - } - /* Check to see if address prefix matches a (manually?) configured address. */ - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) { - return 1; - } - } - return 0; -} - -/** - * Select a default router for a destination. - * - * @param ip6addr the destination address - * @param netif the netif for the outgoing packet, if known - * @return the default router entry index, or -1 if no suitable - * router is found - */ -static s8_t -nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) -{ - s8_t i; - /* last_router is used for round-robin router selection (as recommended - * in RFC). This is more robust in case one router is not reachable, - * we are not stuck trying to resolve it. */ - static s8_t last_router; - (void)ip6addr; /* @todo match preferred routes!! (must implement ND6_OPTION_TYPE_ROUTE_INFO) */ - - /* @todo: implement default router preference */ - - /* Look for reachable routers. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if ((default_router_list[i].neighbor_entry != NULL) && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && - (default_router_list[i].invalidation_timer > 0) && - (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) { - return i; - } - } - - /* Look for router in other reachability states, but still valid according to timer. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if ((default_router_list[i].neighbor_entry != NULL) && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) && - (default_router_list[i].invalidation_timer > 0)) { - return i; - } - } - - /* Look for any router for which we have any information at all. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if (++last_router >= LWIP_ND6_NUM_ROUTERS) { - last_router = 0; - } - if (default_router_list[i].neighbor_entry != NULL && - (netif != NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) { - return i; - } - } - - /* no suitable router found. */ - return -1; -} - -/** - * Find a router-announced route to the given destination. - * - * The caller is responsible for checking whether the returned netif, if any, - * is in a suitable state (up, link up) to be used for packet transmission. - * - * @param ip6addr the destination IPv6 address - * @return the netif to use for the destination, or NULL if none found - */ -struct netif * -nd6_find_route(const ip6_addr_t *ip6addr) -{ - s8_t i; - - i = nd6_select_router(ip6addr, NULL); - if (i >= 0) { - if (default_router_list[i].neighbor_entry != NULL) { - return default_router_list[i].neighbor_entry->netif; /* may be NULL */ - } - } - - return NULL; -} - -/** - * Find an entry for a default router. - * - * @param router_addr the IPv6 address of the router - * @param netif the netif on which the router is found, if known - * @return the index of the router entry, or -1 if not found - */ -static s8_t -nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif) -{ - s8_t i; - - /* Look for router. */ - for (i = 0; i < LWIP_ND6_NUM_ROUTERS; i++) { - if ((default_router_list[i].neighbor_entry != NULL) && - ((netif != NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) && - ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) { - return i; - } - } - - /* router not found. */ - return -1; -} - -/** - * Create a new entry for a default router. - * - * @param router_addr the IPv6 address of the router - * @param netif the netif on which the router is connected, if known - * @return the index on the router table, or -1 if could not be created - */ -static s8_t -nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) -{ - s8_t router_index; - s8_t free_router_index; - s8_t neighbor_index; - - /* Do we have a neighbor entry for this router? */ - neighbor_index = nd6_find_neighbor_cache_entry(router_addr); - if (neighbor_index < 0) { - /* Create a neighbor entry for this router. */ - neighbor_index = nd6_new_neighbor_cache_entry(); - if (neighbor_index < 0) { - /* Could not create neighbor entry for this router. */ - return -1; - } - ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr); - neighbor_cache[neighbor_index].netif = netif; - neighbor_cache[neighbor_index].q = NULL; - neighbor_cache[neighbor_index].state = ND6_INCOMPLETE; - neighbor_cache[neighbor_index].counter.probes_sent = 1; - nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST); - } - - /* Mark neighbor as router. */ - neighbor_cache[neighbor_index].isrouter = 1; - - /* Look for empty entry. */ - free_router_index = LWIP_ND6_NUM_ROUTERS; - for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { - /* check if router already exists (this is a special case for 2 netifs on the same subnet - - e.g. wifi and cable) */ - if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ - return router_index; - } - if (default_router_list[router_index].neighbor_entry == NULL) { - /* remember lowest free index to create a new entry */ - free_router_index = router_index; - } - } - if (free_router_index < LWIP_ND6_NUM_ROUTERS) { - default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); - return free_router_index; - } - - /* Could not create a router entry. */ - - /* Mark neighbor entry as not-router. Entry might be useful as neighbor still. */ - neighbor_cache[neighbor_index].isrouter = 0; - - /* router not found. */ - return -1; -} - -/** - * Find the cached entry for an on-link prefix. - * - * @param prefix the IPv6 prefix that is on-link - * @param netif the netif on which the prefix is on-link - * @return the index on the prefix table, or -1 if not found - */ -static s8_t -nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) -{ - s8_t i; - - /* Look for prefix in list. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) && - (prefix_list[i].netif == netif)) { - return i; - } - } - - /* Entry not available. */ - return -1; -} - -/** - * Creates a new entry for an on-link prefix. - * - * @param prefix the IPv6 prefix that is on-link - * @param netif the netif on which the prefix is on-link - * @return the index on the prefix table, or -1 if not created - */ -static s8_t -nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) -{ - s8_t i; - - /* Create new entry. */ - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; ++i) { - if ((prefix_list[i].netif == NULL) || - (prefix_list[i].invalidation_timer == 0)) { - /* Found empty prefix entry. */ - prefix_list[i].netif = netif; - ip6_addr_set(&(prefix_list[i].prefix), prefix); -#if LWIP_IPV6_AUTOCONFIG - prefix_list[i].flags = 0; -#endif /* LWIP_IPV6_AUTOCONFIG */ - return i; - } - } - - /* Entry not available. */ - return -1; -} - -/** - * Determine the next hop for a destination. Will determine if the - * destination is on-link, else a suitable on-link router is selected. - * - * The last entry index is cached for fast entry search. - * - * @param ip6addr the destination address - * @param netif the netif on which the packet will be sent - * @return the neighbor cache entry for the next hop, ERR_RTE if no - * suitable next hop was found, ERR_MEM if no cache entry - * could be created - */ -static s8_t -nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) -{ -#ifdef LWIP_HOOK_ND6_GET_GW - const ip6_addr_t *next_hop_addr; -#endif /* LWIP_HOOK_ND6_GET_GW */ - s8_t i; - -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - u8_t addr_hint = *(netif->addr_hint); - if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) { - nd6_cached_destination_index = addr_hint; - } - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* Look for ip6addr in destination cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { - /* the cached entry index is the right one! */ - /* do nothing. */ - ND6_STATS_INC(nd6.cachehit); - } else { - /* Search destination cache. */ - i = nd6_find_destination_cache_entry(ip6addr); - if (i >= 0) { - /* found destination entry. make it our new cached index. */ - nd6_cached_destination_index = i; - } else { - /* Not found. Create a new destination entry. */ - i = nd6_new_destination_cache_entry(); - if (i >= 0) { - /* got new destination entry. make it our new cached index. */ - nd6_cached_destination_index = i; - } else { - /* Could not create a destination cache entry. */ - return ERR_MEM; - } - - /* Copy dest address to destination cache. */ - ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr); - - /* Now find the next hop. is it a neighbor? */ - if (ip6_addr_islinklocal(ip6addr) || - nd6_is_prefix_in_netif(ip6addr, netif)) { - /* Destination in local link. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); -#ifdef LWIP_HOOK_ND6_GET_GW - } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { - /* Next hop for destination provided by hook function. */ - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; - ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); -#endif /* LWIP_HOOK_ND6_GET_GW */ - } else { - /* We need to select a router. */ - i = nd6_select_router(ip6addr, netif); - if (i < 0) { - /* No router found. */ - ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr)); - return ERR_RTE; - } - destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; /* Start with netif mtu, correct through ICMPv6 if necessary */ - ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address); - } - } - } - -#if LWIP_NETIF_HWADDRHINT - if (netif->addr_hint != NULL) { - /* per-pcb cached entry was given */ - *(netif->addr_hint) = nd6_cached_destination_index; - } -#endif /* LWIP_NETIF_HWADDRHINT */ - - /* Look in neighbor cache for the next-hop address. */ - if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr), - &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - /* Cache hit. */ - /* Do nothing. */ - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr)); - if (i >= 0) { - /* Found a matching record, make it new cached entry. */ - nd6_cached_neighbor_index = i; - } else { - /* Neighbor not in cache. Make a new entry. */ - i = nd6_new_neighbor_cache_entry(); - if (i >= 0) { - /* got new neighbor entry. make it our new cached index. */ - nd6_cached_neighbor_index = i; - } else { - /* Could not create a neighbor cache entry. */ - return ERR_MEM; - } - - /* Initialize fields. */ - ip6_addr_copy(neighbor_cache[i].next_hop_address, - destination_cache[nd6_cached_destination_index].next_hop_addr); - neighbor_cache[i].isrouter = 0; - neighbor_cache[i].netif = netif; - neighbor_cache[i].state = ND6_INCOMPLETE; - neighbor_cache[i].counter.probes_sent = 1; - nd6_send_neighbor_cache_probe(&neighbor_cache[i], ND6_SEND_FLAG_MULTICAST_DEST); - } - } - - /* Reset this destination's age. */ - destination_cache[nd6_cached_destination_index].age = 0; - - return nd6_cached_neighbor_index; -} - -/** - * Queue a packet for a neighbor. - * - * @param neighbor_index the index in the neighbor cache table - * @param q packet to be queued - * @return ERR_OK if succeeded, ERR_MEM if out of memory - */ -static err_t -nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) -{ - err_t result = ERR_MEM; - struct pbuf *p; - int copy_needed = 0; -#if LWIP_ND6_QUEUEING - struct nd6_q_entry *new_entry, *r; -#endif /* LWIP_ND6_QUEUEING */ - - if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) { - return ERR_ARG; - } - - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - if (p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; - } - if (copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); - while ((p == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { - /* Free oldest packet (as per RFC recommendation) */ -#if LWIP_ND6_QUEUEING - r = neighbor_cache[neighbor_index].q; - neighbor_cache[neighbor_index].q = r->next; - r->next = NULL; - nd6_free_q(r); -#else /* LWIP_ND6_QUEUEING */ - pbuf_free(neighbor_cache[neighbor_index].q); - neighbor_cache[neighbor_index].q = NULL; -#endif /* LWIP_ND6_QUEUEING */ - p = pbuf_alloc(PBUF_LINK, q->tot_len, PBUF_RAM); - } - if (p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet was copied/ref'd? */ - if (p != NULL) { - /* queue packet ... */ -#if LWIP_ND6_QUEUEING - /* allocate a new nd6 queue entry */ - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); - if ((new_entry == NULL) && (neighbor_cache[neighbor_index].q != NULL)) { - /* Free oldest packet (as per RFC recommendation) */ - r = neighbor_cache[neighbor_index].q; - neighbor_cache[neighbor_index].q = r->next; - r->next = NULL; - nd6_free_q(r); - new_entry = (struct nd6_q_entry *)memp_malloc(MEMP_ND6_QUEUE); - } - if (new_entry != NULL) { - new_entry->next = NULL; - new_entry->p = p; - if (neighbor_cache[neighbor_index].q != NULL) { - /* queue was already existent, append the new entry to the end */ - r = neighbor_cache[neighbor_index].q; - while (r->next != NULL) { - r = r->next; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - neighbor_cache[neighbor_index].q = new_entry; - } - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); - result = ERR_OK; - } else { - /* the pool MEMP_ND6_QUEUE is empty */ - pbuf_free(p); - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)p)); - /* { result == ERR_MEM } through initialization */ - } -#else /* LWIP_ND6_QUEUEING */ - /* Queue a single packet. If an older packet is already queued, free it as per RFC. */ - if (neighbor_cache[neighbor_index].q != NULL) { - pbuf_free(neighbor_cache[neighbor_index].q); - } - neighbor_cache[neighbor_index].q = p; - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: queued packet %p on neighbor entry %"S16_F"\n", (void *)p, (s16_t)neighbor_index)); - result = ERR_OK; -#endif /* LWIP_ND6_QUEUEING */ - } else { - LWIP_DEBUGF(LWIP_DBG_TRACE, ("ipv6: could not queue a copy of packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ - } - - return result; -} - -#if LWIP_ND6_QUEUEING -/** - * Free a complete queue of nd6 q entries - * - * @param q a queue of nd6_q_entry to free - */ -static void -nd6_free_q(struct nd6_q_entry *q) -{ - struct nd6_q_entry *r; - LWIP_ASSERT("q != NULL", q != NULL); - LWIP_ASSERT("q->p != NULL", q->p != NULL); - while (q) { - r = q; - q = q->next; - LWIP_ASSERT("r->p != NULL", (r->p != NULL)); - pbuf_free(r->p); - memp_free(MEMP_ND6_QUEUE, r); - } -} -#endif /* LWIP_ND6_QUEUEING */ - -/** - * Send queued packets for a neighbor - * - * @param i the neighbor to send packets to - */ -static void -nd6_send_q(s8_t i) -{ - struct ip6_hdr *ip6hdr; - ip6_addr_t dest; -#if LWIP_ND6_QUEUEING - struct nd6_q_entry *q; -#endif /* LWIP_ND6_QUEUEING */ - - if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) { - return; - } - -#if LWIP_ND6_QUEUEING - while (neighbor_cache[i].q != NULL) { - /* remember first in queue */ - q = neighbor_cache[i].q; - /* pop first item off the queue */ - neighbor_cache[i].q = q->next; - /* Get ipv6 header. */ - ip6hdr = (struct ip6_hdr *)(q->p->payload); - /* Create an aligned copy. */ - ip6_addr_set(&dest, &(ip6hdr->dest)); - /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); - /* free the queued IP packet */ - pbuf_free(q->p); - /* now queue entry can be freed */ - memp_free(MEMP_ND6_QUEUE, q); - } -#else /* LWIP_ND6_QUEUEING */ - if (neighbor_cache[i].q != NULL) { - /* Get ipv6 header. */ - ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); - /* Create an aligned copy. */ - ip6_addr_set(&dest, &(ip6hdr->dest)); - /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); - /* free the queued IP packet */ - pbuf_free(neighbor_cache[i].q); - neighbor_cache[i].q = NULL; - } -#endif /* LWIP_ND6_QUEUEING */ -} - -/** - * A packet is to be transmitted to a specific IPv6 destination on a specific - * interface. Check if we can find the hardware address of the next hop to use - * for the packet. If so, give the hardware address to the caller, which should - * use it to send the packet right away. Otherwise, enqueue the packet for - * later transmission while looking up the hardware address, if possible. - * - * As such, this function returns one of three different possible results: - * - * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. - * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. - * - not ERR_OK: something went wrong; forward the error upward in the stack. - * - * @param netif The lwIP network interface on which the IP packet will be sent. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The destination IPv6 address of the packet. - * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning - * the packet has been queued). - * @return - * - ERR_OK on success, ERR_RTE if no route was found for the packet, - * or ERR_MEM if low memory conditions prohibit sending the packet at all. - */ -err_t -nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) -{ - s8_t i; - - /* Get next hop record. */ - i = nd6_get_next_hop_entry(ip6addr, netif); - if (i < 0) { - /* failed to get a next hop neighbor record. */ - return i; - } - - /* Now that we have a destination record, send or queue the packet. */ - if (neighbor_cache[i].state == ND6_STALE) { - /* Switch to delay state. */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; - } - /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ - if ((neighbor_cache[i].state == ND6_REACHABLE) || - (neighbor_cache[i].state == ND6_DELAY) || - (neighbor_cache[i].state == ND6_PROBE)) { - - /* Tell the caller to send out the packet now. */ - *hwaddrp = neighbor_cache[i].lladdr; - return ERR_OK; - } - - /* We should queue packet on this interface. */ - *hwaddrp = NULL; - return nd6_queue_packet(i, q); -} - - -/** - * Get the Path MTU for a destination. - * - * @param ip6addr the destination address - * @param netif the netif on which the packet will be sent - * @return the Path MTU, if known, or the netif default MTU - */ -u16_t -nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif) -{ - s8_t i; - - i = nd6_find_destination_cache_entry(ip6addr); - if (i >= 0) { - if (destination_cache[i].pmtu > 0) { - return destination_cache[i].pmtu; - } - } - - if (netif != NULL) { - return netif->mtu; - } - - return 1280; /* Minimum MTU */ -} - - -#if LWIP_ND6_TCP_REACHABILITY_HINTS -/** - * Provide the Neighbor discovery process with a hint that a - * destination is reachable. Called by tcp_receive when ACKs are - * received or sent (as per RFC). This is useful to avoid sending - * NS messages every 30 seconds. - * - * @param ip6addr the destination address which is know to be reachable - * by an upper layer protocol (TCP) - */ -void -nd6_reachability_hint(const ip6_addr_t *ip6addr) -{ - s8_t i; - - /* Find destination in cache. */ - if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) { - i = nd6_cached_destination_index; - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_destination_cache_entry(ip6addr); - } - if (i < 0) { - return; - } - - /* Find next hop neighbor in cache. */ - if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) { - i = nd6_cached_neighbor_index; - ND6_STATS_INC(nd6.cachehit); - } else { - i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr)); - } - if (i < 0) { - return; - } - - /* For safety: don't set as reachable if we don't have a LL address yet. Misuse protection. */ - if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) { - return; - } - - /* Set reachability state. */ - neighbor_cache[i].state = ND6_REACHABLE; - neighbor_cache[i].counter.reachable_time = reachable_time; -} -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ - -/** - * Remove all prefix, neighbor_cache and router entries of the specified netif. - * - * @param netif points to a network interface - */ -void -nd6_cleanup_netif(struct netif *netif) -{ - u8_t i; - s8_t router_index; - for (i = 0; i < LWIP_ND6_NUM_PREFIXES; i++) { - if (prefix_list[i].netif == netif) { - prefix_list[i].netif = NULL; - prefix_list[i].flags = 0; - } - } - for (i = 0; i < LWIP_ND6_NUM_NEIGHBORS; i++) { - if (neighbor_cache[i].netif == netif) { - for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { - if (default_router_list[router_index].neighbor_entry == &neighbor_cache[i]) { - default_router_list[router_index].neighbor_entry = NULL; - default_router_list[router_index].flags = 0; - } - } - neighbor_cache[i].isrouter = 0; - nd6_free_neighbor_cache_entry(i); - } - } -} - -#if LWIP_IPV6_MLD -/** - * The state of a local IPv6 address entry is about to change. If needed, join - * or leave the solicited-node multicast group for the address. - * - * @param netif The netif that owns the address. - * @param addr_idx The index of the address. - * @param new_state The new (IP6_ADDR_) state for the address. - */ -void -nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) -{ - u8_t old_state, old_member, new_member; - - old_state = netif_ip6_addr_state(netif, addr_idx); - - /* Determine whether we were, and should be, a member of the solicited-node - * multicast group for this address. For tentative addresses, the group is - * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ - old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE); - new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE); - - if (old_member != new_member) { - ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); - - if (new_member) { - mld6_joingroup_netif(netif, &multicast_address); - } else { - mld6_leavegroup_netif(netif, &multicast_address); - } - } -} -#endif /* LWIP_IPV6_MLD */ - -#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/mem.c b/components/net/lwip-2.0.2/src/core/mem.c deleted file mode 100644 index db3b7cc54e..0000000000 --- a/components/net/lwip-2.0.2/src/core/mem.c +++ /dev/null @@ -1,777 +0,0 @@ -/** - * @file - * Dynamic memory manager - * - * This is a lightweight replacement for the standard C library malloc(). - * - * If you want to use the standard C library malloc() instead, define - * MEM_LIBC_MALLOC to 1 in your lwipopts.h - * - * To let mem_malloc() use pools (prevents fragmentation and is much faster than - * a heap but might waste some memory), define MEM_USE_POOLS to 1, define - * MEMP_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list - * of pools like this (more pools can be added between _START and _END): - * - * Define three pools with sizes 256, 512, and 1512 bytes - * LWIP_MALLOC_MEMPOOL_START - * LWIP_MALLOC_MEMPOOL(20, 256) - * LWIP_MALLOC_MEMPOOL(10, 512) - * LWIP_MALLOC_MEMPOOL(5, 1512) - * LWIP_MALLOC_MEMPOOL_END - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" -#include "lwip/mem.h" -#include "lwip/def.h" -#include "lwip/sys.h" -#include "lwip/stats.h" -#include "lwip/err.h" - -#include - -#if MEM_LIBC_MALLOC -#include /* for malloc()/free() */ -#endif - -#if MEM_LIBC_MALLOC || MEM_USE_POOLS - -/** mem_init is not used when using pools instead of a heap or using - * C library malloc(). - */ -void -mem_init(void) -{ -} - -/** mem_trim is not used when using pools instead of a heap or using - * C library malloc(): we can't free part of a pool element and the stack - * support mem_trim() to return a different pointer - */ -void* -mem_trim(void *mem, mem_size_t size) -{ - LWIP_UNUSED_ARG(size); - return mem; -} -#endif /* MEM_LIBC_MALLOC || MEM_USE_POOLS */ - -#if MEM_LIBC_MALLOC -/* lwIP heap implemented using C library malloc() */ - -/* in case C library malloc() needs extra protection, - * allow these defines to be overridden. - */ -#ifndef mem_clib_free -#define mem_clib_free free -#endif -#ifndef mem_clib_malloc -#define mem_clib_malloc malloc -#endif -#ifndef mem_clib_calloc -#define mem_clib_calloc calloc -#endif - -#if LWIP_STATS && MEM_STATS -#define MEM_LIBC_STATSHELPER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(mem_size_t)) -#else -#define MEM_LIBC_STATSHELPER_SIZE 0 -#endif - -/** - * Allocate a block of memory with a minimum of 'size' bytes. - * - * @param size is the minimum size of the requested block in bytes. - * @return pointer to allocated memory or NULL if no free memory was found. - * - * Note that the returned value must always be aligned (as defined by MEM_ALIGNMENT). - */ -void * -mem_malloc(mem_size_t size) -{ - void* ret = mem_clib_malloc(size + MEM_LIBC_STATSHELPER_SIZE); - if (ret == NULL) { - MEM_STATS_INC(err); - } else { - LWIP_ASSERT("malloc() must return aligned memory", LWIP_MEM_ALIGN(ret) == ret); -#if LWIP_STATS && MEM_STATS - *(mem_size_t*)ret = size; - ret = (u8_t*)ret + MEM_LIBC_STATSHELPER_SIZE; - MEM_STATS_INC_USED(used, size); -#endif - } - return ret; -} - -/** Put memory back on the heap - * - * @param rmem is the pointer as returned by a previous call to mem_malloc() - */ -void -mem_free(void *rmem) -{ - LWIP_ASSERT("rmem != NULL", (rmem != NULL)); - LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); -#if LWIP_STATS && MEM_STATS - rmem = (u8_t*)rmem - MEM_LIBC_STATSHELPER_SIZE; - MEM_STATS_DEC_USED(used, *(mem_size_t*)rmem); -#endif - mem_clib_free(rmem); -} - -#elif MEM_USE_POOLS - -/* lwIP heap implemented with different sized pools */ - -/** - * Allocate memory: determine the smallest pool that is big enough - * to contain an element of 'size' and get an element from that pool. - * - * @param size the size in bytes of the memory needed - * @return a pointer to the allocated memory or NULL if the pool is empty - */ -void * -mem_malloc(mem_size_t size) -{ - void *ret; - struct memp_malloc_helper *element = NULL; - memp_t poolnr; - mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); - - for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) { - /* is this pool big enough to hold an element of the required size - plus a struct memp_malloc_helper that saves the pool this element came from? */ - if (required_size <= memp_pools[poolnr]->size) { - element = (struct memp_malloc_helper*)memp_malloc(poolnr); - if (element == NULL) { - /* No need to DEBUGF or ASSERT: This error is already taken care of in memp.c */ -#if MEM_USE_POOLS_TRY_BIGGER_POOL - /** Try a bigger pool if this one is empty! */ - if (poolnr < MEMP_POOL_LAST) { - continue; - } -#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */ - MEM_STATS_INC(err); - return NULL; - } - break; - } - } - if (poolnr > MEMP_POOL_LAST) { - LWIP_ASSERT("mem_malloc(): no pool is that big!", 0); - MEM_STATS_INC(err); - return NULL; - } - - /* save the pool number this element came from */ - element->poolnr = poolnr; - /* and return a pointer to the memory directly after the struct memp_malloc_helper */ - ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); - -#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) - /* truncating to u16_t is safe because struct memp_desc::size is u16_t */ - element->size = (u16_t)size; - MEM_STATS_INC_USED(used, element->size); -#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ -#if MEMP_OVERFLOW_CHECK - /* initialize unused memory (diff between requested size and selected pool's size) */ - memset((u8_t*)ret + size, 0xcd, memp_pools[poolnr]->size - size); -#endif /* MEMP_OVERFLOW_CHECK */ - return ret; -} - -/** - * Free memory previously allocated by mem_malloc. Loads the pool number - * and calls memp_free with that pool number to put the element back into - * its pool - * - * @param rmem the memory element to free - */ -void -mem_free(void *rmem) -{ - struct memp_malloc_helper *hmem; - - LWIP_ASSERT("rmem != NULL", (rmem != NULL)); - LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem))); - - /* get the original struct memp_malloc_helper */ - /* cast through void* to get rid of alignment warnings */ - hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))); - - LWIP_ASSERT("hmem != NULL", (hmem != NULL)); - LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem))); - LWIP_ASSERT("hmem->poolnr < MEMP_MAX", (hmem->poolnr < MEMP_MAX)); - - MEM_STATS_DEC_USED(used, hmem->size); -#if MEMP_OVERFLOW_CHECK - { - u16_t i; - LWIP_ASSERT("MEM_USE_POOLS: invalid chunk size", - hmem->size <= memp_pools[hmem->poolnr]->size); - /* check that unused memory remained untouched (diff between requested size and selected pool's size) */ - for (i = hmem->size; i < memp_pools[hmem->poolnr]->size; i++) { - u8_t data = *((u8_t*)rmem + i); - LWIP_ASSERT("MEM_USE_POOLS: mem overflow detected", data == 0xcd); - } - } -#endif /* MEMP_OVERFLOW_CHECK */ - - /* and put it in the pool we saved earlier */ - memp_free(hmem->poolnr, hmem); -} - -#else /* MEM_USE_POOLS */ -/* lwIP replacement for your libc malloc() */ - -/** - * The heap is made up as a list of structs of this type. - * This does not have to be aligned since for getting its size, - * we only use the macro SIZEOF_STRUCT_MEM, which automatically aligns. - */ -struct mem { - /** index (-> ram[next]) of the next struct */ - mem_size_t next; - /** index (-> ram[prev]) of the previous struct */ - mem_size_t prev; - /** 1: this area is used; 0: this area is unused */ - u8_t used; -}; - -/** All allocated blocks will be MIN_SIZE bytes big, at least! - * MIN_SIZE can be overridden to suit your needs. Smaller values save space, - * larger values could prevent too small blocks to fragment the RAM too much. */ -#ifndef MIN_SIZE -#define MIN_SIZE 12 -#endif /* MIN_SIZE */ -/* some alignment macros: we define them here for better source code layout */ -#define MIN_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MIN_SIZE) -#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) -#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) - -/** If you want to relocate the heap to external memory, simply define - * LWIP_RAM_HEAP_POINTER as a void-pointer to that location. - * If so, make sure the memory at that location is big enough (see below on - * how that space is calculated). */ -#ifndef LWIP_RAM_HEAP_POINTER -/** the heap. we need one struct mem at the end and some room for alignment */ -LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)); -#define LWIP_RAM_HEAP_POINTER ram_heap -#endif /* LWIP_RAM_HEAP_POINTER */ - -/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */ -static u8_t *ram; -/** the last entry, always unused! */ -static struct mem *ram_end; -/** pointer to the lowest free block, this is used for faster search */ -static struct mem *lfree; - -/** concurrent access protection */ -#if !NO_SYS -static sys_mutex_t mem_mutex; -#endif - -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - -static volatile u8_t mem_free_count; - -/* Allow mem_free from other (e.g. interrupt) context */ -#define LWIP_MEM_FREE_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_free) -#define LWIP_MEM_FREE_PROTECT() SYS_ARCH_PROTECT(lev_free) -#define LWIP_MEM_FREE_UNPROTECT() SYS_ARCH_UNPROTECT(lev_free) -#define LWIP_MEM_ALLOC_DECL_PROTECT() SYS_ARCH_DECL_PROTECT(lev_alloc) -#define LWIP_MEM_ALLOC_PROTECT() SYS_ARCH_PROTECT(lev_alloc) -#define LWIP_MEM_ALLOC_UNPROTECT() SYS_ARCH_UNPROTECT(lev_alloc) - -#else /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - -/* Protect the heap only by using a semaphore */ -#define LWIP_MEM_FREE_DECL_PROTECT() -#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) -#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) -/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ -#define LWIP_MEM_ALLOC_DECL_PROTECT() -#define LWIP_MEM_ALLOC_PROTECT() -#define LWIP_MEM_ALLOC_UNPROTECT() - -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - -/** - * "Plug holes" by combining adjacent empty struct mems. - * After this function is through, there should not exist - * one empty struct mem pointing to another empty struct mem. - * - * @param mem this points to a struct mem which just has been freed - * @internal this function is only called by mem_free() and mem_trim() - * - * This assumes access to the heap is protected by the calling function - * already. - */ -static void -plug_holes(struct mem *mem) -{ - struct mem *nmem; - struct mem *pmem; - - LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram); - LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end); - LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0); - - /* plug hole forward */ - LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED); - - nmem = (struct mem *)(void *)&ram[mem->next]; - if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) { - /* if mem->next is unused and not end of ram, combine mem and mem->next */ - if (lfree == nmem) { - lfree = mem; - } - mem->next = nmem->next; - ((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram); - } - - /* plug hole backward */ - pmem = (struct mem *)(void *)&ram[mem->prev]; - if (pmem != mem && pmem->used == 0) { - /* if mem->prev is unused, combine mem and mem->prev */ - if (lfree == mem) { - lfree = pmem; - } - pmem->next = mem->next; - ((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram); - } -} - -/** - * Zero the heap and initialize start, end and lowest-free - */ -void -mem_init(void) -{ - struct mem *mem; - - LWIP_ASSERT("Sanity check alignment", - (SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0); - - /* align the heap */ - ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER); - /* initialize the start of the heap */ - mem = (struct mem *)(void *)ram; - mem->next = MEM_SIZE_ALIGNED; - mem->prev = 0; - mem->used = 0; - /* initialize the end of the heap */ - ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED]; - ram_end->used = 1; - ram_end->next = MEM_SIZE_ALIGNED; - ram_end->prev = MEM_SIZE_ALIGNED; - - /* initialize the lowest-free pointer to the start of the heap */ - lfree = (struct mem *)(void *)ram; - - MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED); - - if (sys_mutex_new(&mem_mutex) != ERR_OK) { - LWIP_ASSERT("failed to create mem_mutex", 0); - } -} - -/** - * Put a struct mem back on the heap - * - * @param rmem is the data portion of a struct mem as returned by a previous - * call to mem_malloc() - */ -void -mem_free(void *rmem) -{ - struct mem *mem; - LWIP_MEM_FREE_DECL_PROTECT(); - - if (rmem == NULL) { - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n")); - return; - } - LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0); - - LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram && - (u8_t *)rmem < (u8_t *)ram_end); - - if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { - SYS_ARCH_DECL_PROTECT(lev); - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n")); - /* protect mem stats from concurrent access */ - SYS_ARCH_PROTECT(lev); - MEM_STATS_INC(illegal); - SYS_ARCH_UNPROTECT(lev); - return; - } - /* protect the heap from concurrent access */ - LWIP_MEM_FREE_PROTECT(); - /* Get the corresponding struct mem ... */ - /* cast through void* to get rid of alignment warnings */ - mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); - /* ... which has to be in a used state ... */ - LWIP_ASSERT("mem_free: mem->used", mem->used); - /* ... and is now unused. */ - mem->used = 0; - - if (mem < lfree) { - /* the newly freed struct is now the lowest */ - lfree = mem; - } - - MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram))); - - /* finally, see if prev or next are free also */ - plug_holes(mem); -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 1; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_FREE_UNPROTECT(); -} - -/** - * Shrink memory returned by mem_malloc(). - * - * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked - * @param newsize required size after shrinking (needs to be smaller than or - * equal to the previous size) - * @return for compatibility reasons: is always == rmem, at the moment - * or NULL if newsize is > old size, in which case rmem is NOT touched - * or freed! - */ -void * -mem_trim(void *rmem, mem_size_t newsize) -{ - mem_size_t size; - mem_size_t ptr, ptr2; - struct mem *mem, *mem2; - /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */ - LWIP_MEM_FREE_DECL_PROTECT(); - - /* Expand the size of the allocated memory region so that we can - adjust for alignment. */ - newsize = LWIP_MEM_ALIGN_SIZE(newsize); - - if (newsize < MIN_SIZE_ALIGNED) { - /* every data block must be at least MIN_SIZE_ALIGNED long */ - newsize = MIN_SIZE_ALIGNED; - } - - if (newsize > MEM_SIZE_ALIGNED) { - return NULL; - } - - LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram && - (u8_t *)rmem < (u8_t *)ram_end); - - if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) { - SYS_ARCH_DECL_PROTECT(lev); - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n")); - /* protect mem stats from concurrent access */ - SYS_ARCH_PROTECT(lev); - MEM_STATS_INC(illegal); - SYS_ARCH_UNPROTECT(lev); - return rmem; - } - /* Get the corresponding struct mem ... */ - /* cast through void* to get rid of alignment warnings */ - mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM); - /* ... and its offset pointer */ - ptr = (mem_size_t)((u8_t *)mem - ram); - - size = mem->next - ptr - SIZEOF_STRUCT_MEM; - LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size); - if (newsize > size) { - /* not supported */ - return NULL; - } - if (newsize == size) { - /* No change in size, simply return */ - return rmem; - } - - /* protect the heap from concurrent access */ - LWIP_MEM_FREE_PROTECT(); - - mem2 = (struct mem *)(void *)&ram[mem->next]; - if (mem2->used == 0) { - /* The next struct is unused, we can simply move it at little */ - mem_size_t next; - /* remember the old next pointer */ - next = mem2->next; - /* create new struct mem which is moved directly after the shrinked mem */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - if (lfree == mem2) { - lfree = (struct mem *)(void *)&ram[ptr2]; - } - mem2 = (struct mem *)(void *)&ram[ptr2]; - mem2->used = 0; - /* restore the next pointer */ - mem2->next = next; - /* link it back to mem */ - mem2->prev = ptr; - /* link mem to it */ - mem->next = ptr2; - /* last thing to restore linked list: as we have moved mem2, - * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not - * the end of the heap */ - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_DEC_USED(used, (size - newsize)); - /* no need to plug holes, we've already done that */ - } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) { - /* Next struct is used but there's room for another struct mem with - * at least MIN_SIZE_ALIGNED of data. - * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem - * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED'). - * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty - * region that couldn't hold data, but when mem->next gets freed, - * the 2 regions would be combined, resulting in more free memory */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; - mem2 = (struct mem *)(void *)&ram[ptr2]; - if (mem2 < lfree) { - lfree = mem2; - } - mem2->used = 0; - mem2->next = mem->next; - mem2->prev = ptr; - mem->next = ptr2; - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_DEC_USED(used, (size - newsize)); - /* the original mem->next is used, so no need to plug holes! */ - } - /* else { - next struct mem is used but size between mem and mem2 is not big enough - to create another struct mem - -> don't do anyhting. - -> the remaining space stays unused since it is too small - } */ -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 1; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_FREE_UNPROTECT(); - return rmem; -} - -/** - * Allocate a block of memory with a minimum of 'size' bytes. - * - * @param size is the minimum size of the requested block in bytes. - * @return pointer to allocated memory or NULL if no free memory was found. - * - * Note that the returned value will always be aligned (as defined by MEM_ALIGNMENT). - */ -void * -mem_malloc(mem_size_t size) -{ - mem_size_t ptr, ptr2; - struct mem *mem, *mem2; -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - u8_t local_mem_free_count = 0; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_MEM_ALLOC_DECL_PROTECT(); - - if (size == 0) { - return NULL; - } - - /* Expand the size of the allocated memory region so that we can - adjust for alignment. */ - size = LWIP_MEM_ALIGN_SIZE(size); - - if (size < MIN_SIZE_ALIGNED) { - /* every data block must be at least MIN_SIZE_ALIGNED long */ - size = MIN_SIZE_ALIGNED; - } - - if (size > MEM_SIZE_ALIGNED) { - return NULL; - } - - /* protect the heap from concurrent access */ - sys_mutex_lock(&mem_mutex); - LWIP_MEM_ALLOC_PROTECT(); -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - /* run as long as a mem_free disturbed mem_malloc or mem_trim */ - do { - local_mem_free_count = 0; -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - /* Scan through the heap searching for a free block that is big enough, - * beginning with the lowest free block. - */ - for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size; - ptr = ((struct mem *)(void *)&ram[ptr])->next) { - mem = (struct mem *)(void *)&ram[ptr]; -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 0; - LWIP_MEM_ALLOC_UNPROTECT(); - /* allow mem_free or mem_trim to run */ - LWIP_MEM_ALLOC_PROTECT(); - if (mem_free_count != 0) { - /* If mem_free or mem_trim have run, we have to restart since they - could have altered our current struct mem. */ - local_mem_free_count = 1; - break; - } -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - - if ((!mem->used) && - (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { - /* mem is not used and at least perfect fit is possible: - * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ - - if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { - /* (in addition to the above, we test if another struct mem (SIZEOF_STRUCT_MEM) containing - * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') - * -> split large block, create empty remainder, - * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if - * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, - * struct mem would fit in but no data between mem2 and mem2->next - * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty - * region that couldn't hold data, but when mem->next gets freed, - * the 2 regions would be combined, resulting in more free memory - */ - ptr2 = ptr + SIZEOF_STRUCT_MEM + size; - /* create mem2 struct */ - mem2 = (struct mem *)(void *)&ram[ptr2]; - mem2->used = 0; - mem2->next = mem->next; - mem2->prev = ptr; - /* and insert it between mem and mem->next */ - mem->next = ptr2; - mem->used = 1; - - if (mem2->next != MEM_SIZE_ALIGNED) { - ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2; - } - MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM)); - } else { - /* (a mem2 struct does no fit into the user data space of mem and mem->next will always - * be used at this point: if not we have 2 unused structs in a row, plug_holes should have - * take care of this). - * -> near fit or exact fit: do not split, no mem2 creation - * also can't move mem->next directly behind mem, since mem->next - * will always be used at this point! - */ - mem->used = 1; - MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram)); - } -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT -mem_malloc_adjust_lfree: -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - if (mem == lfree) { - struct mem *cur = lfree; - /* Find next free block after mem and update lowest free pointer */ - while (cur->used && cur != ram_end) { -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - mem_free_count = 0; - LWIP_MEM_ALLOC_UNPROTECT(); - /* prevent high interrupt latency... */ - LWIP_MEM_ALLOC_PROTECT(); - if (mem_free_count != 0) { - /* If mem_free or mem_trim have run, we have to restart since they - could have altered our current struct mem or lfree. */ - goto mem_malloc_adjust_lfree; - } -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - cur = (struct mem *)(void *)&ram[cur->next]; - } - lfree = cur; - LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); - } - LWIP_MEM_ALLOC_UNPROTECT(); - sys_mutex_unlock(&mem_mutex); - LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", - (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); - LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", - ((mem_ptr_t)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0); - LWIP_ASSERT("mem_malloc: sanity check alignment", - (((mem_ptr_t)mem) & (MEM_ALIGNMENT-1)) == 0); - - return (u8_t *)mem + SIZEOF_STRUCT_MEM; - } - } -#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT - /* if we got interrupted by a mem_free, try again */ - } while (local_mem_free_count != 0); -#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */ - LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); - MEM_STATS_INC(err); - LWIP_MEM_ALLOC_UNPROTECT(); - sys_mutex_unlock(&mem_mutex); - return NULL; -} - -#endif /* MEM_USE_POOLS */ - -#if MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) -void * -mem_calloc(mem_size_t count, mem_size_t size) -{ - return mem_clib_calloc(count, size); -} - -#else /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ -/** - * Contiguously allocates enough space for count objects that are size bytes - * of memory each and returns a pointer to the allocated memory. - * - * The allocated memory is filled with bytes of value zero. - * - * @param count number of objects to allocate - * @param size size of the objects to allocate - * @return pointer to allocated memory / NULL pointer if there is an error - */ -void * -mem_calloc(mem_size_t count, mem_size_t size) -{ - void *p; - - /* allocate 'count' objects of size 'size' */ - p = mem_malloc(count * size); - if (p) { - /* zero the memory */ - memset(p, 0, (size_t)count * (size_t)size); - } - return p; -} -#endif /* MEM_LIBC_MALLOC && (!LWIP_STATS || !MEM_STATS) */ diff --git a/components/net/lwip-2.0.2/src/core/memp.c b/components/net/lwip-2.0.2/src/core/memp.c deleted file mode 100644 index 58fab1a20a..0000000000 --- a/components/net/lwip-2.0.2/src/core/memp.c +++ /dev/null @@ -1,496 +0,0 @@ -/** - * @file - * Dynamic pool memory manager - * - * lwIP has dedicated pools for many structures (netconn, protocol control blocks, - * packet buffers, ...). All these pools are managed here. - * - * @defgroup mempool Memory pools - * @ingroup infrastructure - * Custom memory pools - - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/memp.h" -#include "lwip/sys.h" -#include "lwip/stats.h" - -#include - -/* Make sure we include everything we need for size calculation required by memp_std.h */ -#include "lwip/pbuf.h" -#include "lwip/raw.h" -#include "lwip/udp.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/ip4_frag.h" -#include "lwip/netbuf.h" -#include "lwip/api.h" -#include "lwip/priv/tcpip_priv.h" -#include "lwip/priv/api_msg.h" -#include "lwip/sockets.h" -#include "lwip/netifapi.h" -#include "lwip/etharp.h" -#include "lwip/igmp.h" -#include "lwip/timeouts.h" -/* needed by default MEMP_NUM_SYS_TIMEOUT */ -#include "netif/ppp/ppp_opts.h" -#include "lwip/netdb.h" -#include "lwip/dns.h" -#include "lwip/priv/nd6_priv.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" - -#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) -#include "lwip/priv/memp_std.h" - -const struct memp_desc* const memp_pools[MEMP_MAX] = { -#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, -#include "lwip/priv/memp_std.h" -}; - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 -#undef MEMP_OVERFLOW_CHECK -/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ -#define MEMP_OVERFLOW_CHECK 1 -#endif - -#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC -/** - * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". - */ -static int -memp_sanity(const struct memp_desc *desc) -{ - struct memp *t, *h; - - t = *desc->tab; - if (t != NULL) { - for (h = t->next; (t != NULL) && (h != NULL); t = t->next, - h = ((h->next != NULL) ? h->next->next : NULL)) { - if (t == h) { - return 0; - } - } - } - - return 1; -} -#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */ - -#if MEMP_OVERFLOW_CHECK -/** - * Check if a memp element was victim of an overflow - * (e.g. the restricted area after it has been altered) - * - * @param p the memp element to check - * @param desc the pool p comes from - */ -static void -memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) -{ -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - u16_t k; - u8_t *m; - m = (u8_t*)p + MEMP_SIZE + desc->size; - for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { - if (m[k] != 0xcd) { - char errstr[128] = "detected memp overflow in pool "; - strcat(errstr, desc->desc); - LWIP_ASSERT(errstr, 0); - } - } -#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(desc); -#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ -} - -/** - * Check if a memp element was victim of an underflow - * (e.g. the restricted area before it has been altered) - * - * @param p the memp element to check - * @param desc the pool p comes from - */ -static void -memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) -{ -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - u16_t k; - u8_t *m; - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { - if (m[k] != 0xcd) { - char errstr[128] = "detected memp underflow in pool "; - strcat(errstr, desc->desc); - LWIP_ASSERT(errstr, 0); - } - } -#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(desc); -#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ -} - -/** - * Initialize the restricted area of on memp element. - */ -static void -memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) -{ -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - u8_t *m; -#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); -#endif -#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 - m = (u8_t*)p + MEMP_SIZE + desc->size; - memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); -#endif -#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(desc); -#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ -} - -#if MEMP_OVERFLOW_CHECK >= 2 -/** - * Do an overflow check for all elements in every pool. - * - * @see memp_overflow_check_element for a description of the check - */ -static void -memp_overflow_check_all(void) -{ - u16_t i, j; - struct memp *p; - SYS_ARCH_DECL_PROTECT(old_level); - SYS_ARCH_PROTECT(old_level); - - for (i = 0; i < MEMP_MAX; ++i) { - p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); - for (j = 0; j < memp_pools[i]->num; ++j) { - memp_overflow_check_element_overflow(p, memp_pools[i]); - memp_overflow_check_element_underflow(p, memp_pools[i]); - p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED)); - } - } - SYS_ARCH_UNPROTECT(old_level); -} -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ -#endif /* MEMP_OVERFLOW_CHECK */ - -/** - * Initialize custom memory pool. - * Related functions: memp_malloc_pool, memp_free_pool - * - * @param desc pool to initialize - */ -void -memp_init_pool(const struct memp_desc *desc) -{ -#if MEMP_MEM_MALLOC - LWIP_UNUSED_ARG(desc); -#else - int i; - struct memp *memp; - - *desc->tab = NULL; - memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); - /* create a linked list of memp elements */ - for (i = 0; i < desc->num; ++i) { - memp->next = *desc->tab; - *desc->tab = memp; -#if MEMP_OVERFLOW_CHECK - memp_overflow_init_element(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ - /* cast through void* to get rid of alignment warnings */ - memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size -#if MEMP_OVERFLOW_CHECK - + MEMP_SANITY_REGION_AFTER_ALIGNED -#endif - ); - } -#if MEMP_STATS - desc->stats->avail = desc->num; -#endif /* MEMP_STATS */ -#endif /* !MEMP_MEM_MALLOC */ - -#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) - desc->stats->name = desc->desc; -#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ -} - -/** - * Initializes lwIP built-in pools. - * Related functions: memp_malloc, memp_free - * - * Carves out memp_memory into linked lists for each pool-type. - */ -void -memp_init(void) -{ - u16_t i; - - /* for every pool: */ - for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) { - memp_init_pool(memp_pools[i]); - -#if LWIP_STATS && MEMP_STATS - lwip_stats.memp[i] = memp_pools[i]->stats; -#endif - } - -#if MEMP_OVERFLOW_CHECK >= 2 - /* check everything a first time to see if it worked */ - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ -} - -static void* -#if !MEMP_OVERFLOW_CHECK -do_memp_malloc_pool(const struct memp_desc *desc) -#else -do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) -#endif -{ - struct memp *memp; - SYS_ARCH_DECL_PROTECT(old_level); - -#if MEMP_MEM_MALLOC - memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size)); - SYS_ARCH_PROTECT(old_level); -#else /* MEMP_MEM_MALLOC */ - SYS_ARCH_PROTECT(old_level); - - memp = *desc->tab; -#endif /* MEMP_MEM_MALLOC */ - - if (memp != NULL) { -#if !MEMP_MEM_MALLOC -#if MEMP_OVERFLOW_CHECK == 1 - memp_overflow_check_element_overflow(memp, desc); - memp_overflow_check_element_underflow(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ - - *desc->tab = memp->next; -#if MEMP_OVERFLOW_CHECK - memp->next = NULL; -#endif /* MEMP_OVERFLOW_CHECK */ -#endif /* !MEMP_MEM_MALLOC */ -#if MEMP_OVERFLOW_CHECK - memp->file = file; - memp->line = line; -#if MEMP_MEM_MALLOC - memp_overflow_init_element(memp, desc); -#endif /* MEMP_MEM_MALLOC */ -#endif /* MEMP_OVERFLOW_CHECK */ - LWIP_ASSERT("memp_malloc: memp properly aligned", - ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); -#if MEMP_STATS - desc->stats->used++; - if (desc->stats->used > desc->stats->max) { - desc->stats->max = desc->stats->used; - } -#endif - SYS_ARCH_UNPROTECT(old_level); - /* cast through u8_t* to get rid of alignment warnings */ - return ((u8_t*)memp + MEMP_SIZE); - } else { - LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc)); -#if MEMP_STATS - desc->stats->err++; -#endif - } - - SYS_ARCH_UNPROTECT(old_level); - return NULL; -} - -/** - * Get an element from a custom pool. - * - * @param desc the pool to get an element from - * - * @return a pointer to the allocated memory or a NULL pointer on error - */ -void * -#if !MEMP_OVERFLOW_CHECK -memp_malloc_pool(const struct memp_desc *desc) -#else -memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) -#endif -{ - LWIP_ASSERT("invalid pool desc", desc != NULL); - if (desc == NULL) { - return NULL; - } - -#if !MEMP_OVERFLOW_CHECK - return do_memp_malloc_pool(desc); -#else - return do_memp_malloc_pool_fn(desc, file, line); -#endif -} - -/** - * Get an element from a specific pool. - * - * @param type the pool to get an element from - * - * @return a pointer to the allocated memory or a NULL pointer on error - */ -void * -#if !MEMP_OVERFLOW_CHECK -memp_malloc(memp_t type) -#else -memp_malloc_fn(memp_t type, const char* file, const int line) -#endif -{ - void *memp; - LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); - -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ - -#if !MEMP_OVERFLOW_CHECK - memp = do_memp_malloc_pool(memp_pools[type]); -#else - memp = do_memp_malloc_pool_fn(memp_pools[type], file, line); -#endif - - return memp; -} - -static void -do_memp_free_pool(const struct memp_desc* desc, void *mem) -{ - struct memp *memp; - SYS_ARCH_DECL_PROTECT(old_level); - - LWIP_ASSERT("memp_free: mem properly aligned", - ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); - - /* cast through void* to get rid of alignment warnings */ - memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); - - SYS_ARCH_PROTECT(old_level); - -#if MEMP_OVERFLOW_CHECK == 1 - memp_overflow_check_element_overflow(memp, desc); - memp_overflow_check_element_underflow(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ - -#if MEMP_STATS - desc->stats->used--; -#endif - -#if MEMP_MEM_MALLOC - LWIP_UNUSED_ARG(desc); - SYS_ARCH_UNPROTECT(old_level); - mem_free(memp); -#else /* MEMP_MEM_MALLOC */ - memp->next = *desc->tab; - *desc->tab = memp; - -#if MEMP_SANITY_CHECK - LWIP_ASSERT("memp sanity", memp_sanity(desc)); -#endif /* MEMP_SANITY_CHECK */ - - SYS_ARCH_UNPROTECT(old_level); -#endif /* !MEMP_MEM_MALLOC */ -} - -/** - * Put a custom pool element back into its pool. - * - * @param desc the pool where to put mem - * @param mem the memp element to free - */ -void -memp_free_pool(const struct memp_desc* desc, void *mem) -{ - LWIP_ASSERT("invalid pool desc", desc != NULL); - if ((desc == NULL) || (mem == NULL)) { - return; - } - - do_memp_free_pool(desc, mem); -} - -/** - * Put an element back into its pool. - * - * @param type the pool where to put mem - * @param mem the memp element to free - */ -void -memp_free(memp_t type, void *mem) -{ -#ifdef LWIP_HOOK_MEMP_AVAILABLE - struct memp *old_first; -#endif - - LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); - - if (mem == NULL) { - return; - } - -#if MEMP_OVERFLOW_CHECK >= 2 - memp_overflow_check_all(); -#endif /* MEMP_OVERFLOW_CHECK >= 2 */ - -#ifdef LWIP_HOOK_MEMP_AVAILABLE - old_first = *memp_pools[type]->tab; -#endif - - do_memp_free_pool(memp_pools[type], mem); - -#ifdef LWIP_HOOK_MEMP_AVAILABLE - if (old_first == NULL) { - LWIP_HOOK_MEMP_AVAILABLE(type); - } -#endif -} diff --git a/components/net/lwip-2.0.2/src/core/netif.c b/components/net/lwip-2.0.2/src/core/netif.c deleted file mode 100644 index ee57bb9a9d..0000000000 --- a/components/net/lwip-2.0.2/src/core/netif.c +++ /dev/null @@ -1,1316 +0,0 @@ -/** - * @file - * lwIP network interface abstraction - * - * @defgroup netif Network interface (NETIF) - * @ingroup callbackstyle_api - * - * @defgroup netif_ip4 IPv4 address handling - * @ingroup netif - * - * @defgroup netif_ip6 IPv6 address handling - * @ingroup netif - * - * @defgroup netif_cd Client data handling - * Store data (void*) on a netif for application usage. - * @see @ref LWIP_NUM_NETIF_CLIENT_DATA - * @ingroup netif - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -#include "lwip/opt.h" - -#include - -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/udp.h" -#include "lwip/raw.h" -#include "lwip/snmp.h" -#include "lwip/igmp.h" -#include "lwip/etharp.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/ip.h" -#if ENABLE_LOOPBACK -#if LWIP_NETIF_LOOPBACK_MULTITHREADING -#include "lwip/tcpip.h" -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -#include "netif/ethernet.h" - -#if LWIP_AUTOIP -#include "lwip/autoip.h" -#endif /* LWIP_AUTOIP */ -#if LWIP_DHCP -#include "lwip/dhcp.h" -#endif /* LWIP_DHCP */ -#if LWIP_IPV6_DHCP6 -#include "lwip/dhcp6.h" -#endif /* LWIP_IPV6_DHCP6 */ -#if LWIP_IPV6_MLD -#include "lwip/mld6.h" -#endif /* LWIP_IPV6_MLD */ -#if LWIP_IPV6 -#include "lwip/nd6.h" -#endif - -#include - -#ifdef RT_USING_NETDEV -#include "lwip/netdb.h" -#include -#endif /* RT_USING_NETDEV */ - -#if LWIP_NETIF_STATUS_CALLBACK -#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) -#else -#define NETIF_STATUS_CALLBACK(n) -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -#if LWIP_NETIF_LINK_CALLBACK -#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) -#else -#define NETIF_LINK_CALLBACK(n) -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -struct netif *netif_list; -struct netif *netif_default; - -static u8_t netif_num; - -#if LWIP_NUM_NETIF_CLIENT_DATA > 0 -static u8_t netif_client_id; -#endif - -#define NETIF_REPORT_TYPE_IPV4 0x01 -#define NETIF_REPORT_TYPE_IPV6 0x02 -static void netif_issue_reports(struct netif* netif, u8_t report_type); - -#if LWIP_IPV6 -static err_t netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr); -#endif /* LWIP_IPV6 */ - -#if LWIP_HAVE_LOOPIF -#if LWIP_IPV4 -static err_t netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr); -#endif -#if LWIP_IPV6 -static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr); -#endif - - -static struct netif loop_netif; - -/** - * Initialize a lwip network interface structure for a loopback interface - * - * @param netif the lwip network interface structure for this loopif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - */ -static err_t -netif_loopif_init(struct netif *netif) -{ - /* initialize the snmp variables and counters inside the struct netif - * ifSpeed: no assumption can be made! - */ - MIB2_INIT_NETIF(netif, snmp_ifType_softwareLoopback, 0); - - netif->name[0] = 'l'; - netif->name[1] = 'o'; -#if LWIP_IPV4 - netif->output = netif_loop_output_ipv4; -#endif -#if LWIP_IPV6 - netif->output_ip6 = netif_loop_output_ipv6; -#endif -#if LWIP_LOOPIF_MULTICAST - netif->flags |= NETIF_FLAG_IGMP; -#endif - return ERR_OK; -} -#endif /* LWIP_HAVE_LOOPIF */ - -void -netif_init(void) -{ -#if LWIP_HAVE_LOOPIF -#if LWIP_IPV4 -#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw, - ip4_addr_t loop_ipaddr, loop_netmask, loop_gw; - IP4_ADDR(&loop_gw, 127,0,0,1); - IP4_ADDR(&loop_ipaddr, 127,0,0,1); - IP4_ADDR(&loop_netmask, 255,0,0,0); -#else /* LWIP_IPV4 */ -#define LOOPIF_ADDRINIT -#endif /* LWIP_IPV4 */ - -#if NO_SYS - netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input); -#else /* NO_SYS */ - netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input); -#endif /* NO_SYS */ - -#if LWIP_IPV6 - IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL); - loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID; -#endif /* LWIP_IPV6 */ - - netif_set_link_up(&loop_netif); - netif_set_up(&loop_netif); - -#endif /* LWIP_HAVE_LOOPIF */ -} - -/** - * @ingroup lwip_nosys - * Forwards a received packet for input processing with - * ethernet_input() or ip_input() depending on netif flags. - * Don't call directly, pass to netif_add() and call - * netif->input(). - * Only works if the netif driver correctly sets - * NETIF_FLAG_ETHARP and/or NETIF_FLAG_ETHERNET flag! - */ -err_t -netif_input(struct pbuf *p, struct netif *inp) -{ -#if LWIP_ETHERNET - if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { - return ethernet_input(p, inp); - } else -#endif /* LWIP_ETHERNET */ - return ip_input(p, inp); -} - -/** - * @ingroup netif - * Add a network interface to the list of lwIP netifs. - * - * @param netif a pre-allocated netif structure - * @param ipaddr IP address for the new netif - * @param netmask network mask for the new netif - * @param gw default gateway IP address for the new netif - * @param state opaque data passed to the new netif - * @param init callback function that initializes the interface - * @param input callback function that is called to pass - * ingress packets up in the protocol layer stack.\n - * It is recommended to use a function that passes the input directly - * to the stack (netif_input(), NO_SYS=1 mode) or via sending a - * message to TCPIP thread (tcpip_input(), NO_SYS=0 mode).\n - * These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET - * to decide whether to forward to ethernet_input() or ip_input(). - * In other words, the functions only work when the netif - * driver is implemented correctly!\n - * Most members of struct netif should be be initialized by the - * netif init function = netif driver (init parameter of this function).\n - * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after - * setting the MAC address in struct netif.hwaddr - * (IPv6 requires a link-local address). - * - * @return netif, or NULL if failed. - */ -struct netif * -netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input) -{ -#if LWIP_IPV6 - s8_t i; -#endif - - LWIP_ASSERT("No init function given", init != NULL); - - /* reset new interface configuration state */ -#if LWIP_IPV4 - ip_addr_set_zero_ip4(&netif->ip_addr); - ip_addr_set_zero_ip4(&netif->netmask); - ip_addr_set_zero_ip4(&netif->gw); -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - ip_addr_set_zero_ip6(&netif->ip6_addr[i]); - netif->ip6_addr_state[i] = IP6_ADDR_INVALID; - } - netif->output_ip6 = netif_null_output_ip6; -#endif /* LWIP_IPV6 */ - NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); - netif->flags = 0; -#ifdef netif_get_client_data - memset(netif->client_data, 0, sizeof(netif->client_data)); -#endif /* LWIP_NUM_NETIF_CLIENT_DATA */ -#if LWIP_IPV6_AUTOCONFIG - /* IPv6 address autoconfiguration not enabled by default */ - netif->ip6_autoconfig_enabled = 0; -#endif /* LWIP_IPV6_AUTOCONFIG */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_NETIF_STATUS_CALLBACK - netif->status_callback = NULL; -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK - netif->link_callback = NULL; -#endif /* LWIP_NETIF_LINK_CALLBACK */ -#if LWIP_IGMP - netif->igmp_mac_filter = NULL; -#endif /* LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - netif->mld_mac_filter = NULL; -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ -#if ENABLE_LOOPBACK - netif->loop_first = NULL; - netif->loop_last = NULL; -#endif /* ENABLE_LOOPBACK */ - - /* remember netif specific state information data */ - netif->state = state; - netif->num = netif_num++; - netif->input = input; - - NETIF_SET_HWADDRHINT(netif, NULL); -#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS - netif->loop_cnt_current = 0; -#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ - -#if LWIP_IPV4 - netif_set_addr(netif, ipaddr, netmask, gw); -#endif /* LWIP_IPV4 */ - - /* call user specified initialization function for netif */ - if (init(netif) != ERR_OK) { - return NULL; - } - - /* add this netif to the list */ - netif->next = netif_list; - netif_list = netif; - mib2_netif_added(netif); - -#if LWIP_IGMP - /* start IGMP processing */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_start(netif); - } -#endif /* LWIP_IGMP */ - - LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", - netif->name[0], netif->name[1])); -#if LWIP_IPV4 - LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); - ip4_addr_debug_print(NETIF_DEBUG, ipaddr); - LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); - ip4_addr_debug_print(NETIF_DEBUG, netmask); - LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); - ip4_addr_debug_print(NETIF_DEBUG, gw); -#endif /* LWIP_IPV4 */ - LWIP_DEBUGF(NETIF_DEBUG, ("\n")); - return netif; -} - -#if LWIP_IPV4 -/** - * @ingroup netif_ip4 - * Change IP address configuration for a network interface (including netmask - * and default gateway). - * - * @param netif the network interface to change - * @param ipaddr the new IP address - * @param netmask the new netmask - * @param gw the new default gateway - */ -void -netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, - const ip4_addr_t *gw) -{ - if (ip4_addr_isany(ipaddr)) { - /* when removing an address, we have to remove it *before* changing netmask/gw - to ensure that tcp RST segment can be sent correctly */ - netif_set_ipaddr(netif, ipaddr); - netif_set_netmask(netif, netmask); - netif_set_gw(netif, gw); - } else { - netif_set_netmask(netif, netmask); - netif_set_gw(netif, gw); - /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ - netif_set_ipaddr(netif, ipaddr); - } -} -#endif /* LWIP_IPV4*/ - -/** - * @ingroup netif - * Remove a network interface from the list of lwIP netifs. - * - * @param netif the network interface to remove - */ -void -netif_remove(struct netif *netif) -{ -#if LWIP_IPV6 - int i; -#endif - - if (netif == NULL) { - return; - } - -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); -#endif /* LWIP_RAW */ - } - -#if LWIP_IGMP - /* stop IGMP processing */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_stop(netif); - } -#endif /* LWIP_IGMP */ -#endif /* LWIP_IPV4*/ - -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); -#endif /* LWIP_RAW */ - } - } -#if LWIP_IPV6_MLD - /* stop MLD processing */ - mld6_stop(netif); -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ - if (netif_is_up(netif)) { - /* set netif down before removing (call callback function) */ - netif_set_down(netif); - } - - mib2_remove_ip4(netif); - - /* this netif is default? */ - if (netif_default == netif) { - /* reset default netif */ - netif_set_default(NULL); - } - /* is it the first netif? */ - if (netif_list == netif) { - netif_list = netif->next; - } else { - /* look for netif further down the list */ - struct netif * tmp_netif; - for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { - if (tmp_netif->next == netif) { - tmp_netif->next = netif->next; - break; - } - } - if (tmp_netif == NULL) { - return; /* netif is not on the list */ - } - } - mib2_netif_removed(netif); -#if LWIP_NETIF_REMOVE_CALLBACK - if (netif->remove_callback) { - netif->remove_callback(netif); - } -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); -} - -/** - * @ingroup netif - * Find a network interface by searching for its name - * - * @param name the name of the netif (like netif->name) plus concatenated number - * in ascii representation (e.g. 'en0') - */ -struct netif * -netif_find(const char *name) -{ - struct netif *netif; - u8_t num; - - if (name == NULL) { - return NULL; - } - - num = (u8_t)(name[2] - '0'); - - for (netif = netif_list; netif != NULL; netif = netif->next) { - if (num == netif->num && - name[0] == netif->name[0] && - name[1] == netif->name[1]) { - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); - return netif; - } - } - LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); - return NULL; -} - -#if LWIP_IPV4 -/** - * @ingroup netif_ip4 - * Change the IP address of a network interface - * - * @param netif the network interface to change - * @param ipaddr the new IP address - * - * @note call netif_set_addr() if you also want to change netmask and - * default gateway - */ -void -netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr) -{ - ip_addr_t new_addr; - *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4); - IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4); - - /* address is actually being changed? */ - if (ip4_addr_cmp(ip_2_ip4(&new_addr), netif_ip4_addr(netif)) == 0) { - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr); -#endif /* LWIP_RAW */ - - mib2_remove_ip4(netif); - mib2_remove_route_ip4(0, netif); - /* set new IP address to netif */ - ip4_addr_set(ip_2_ip4(&netif->ip_addr), ipaddr); - IP_SET_TYPE_VAL(netif->ip_addr, IPADDR_TYPE_V4); - mib2_add_ip4(netif); - mib2_add_route_ip4(0, netif); - - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4); - - NETIF_STATUS_CALLBACK(netif); - -#ifdef RT_USING_NETDEV - /* rt-thread sal network interface device set IP address operations */ - netdev_low_level_set_ipaddr(netdev_get_by_name(netif->name), &netif->ip_addr); -#endif /* RT_USING_NETDEV */ - } - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(netif_ip4_addr(netif)), - ip4_addr2_16(netif_ip4_addr(netif)), - ip4_addr3_16(netif_ip4_addr(netif)), - ip4_addr4_16(netif_ip4_addr(netif)))); -} - -/** - * @ingroup netif_ip4 - * Change the default gateway for a network interface - * - * @param netif the network interface to change - * @param gw the new default gateway - * - * @note call netif_set_addr() if you also want to change ip address and netmask - */ -void -netif_set_gw(struct netif *netif, const ip4_addr_t *gw) -{ - ip4_addr_set(ip_2_ip4(&netif->gw), gw); - IP_SET_TYPE_VAL(netif->gw, IPADDR_TYPE_V4); - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(netif_ip4_gw(netif)), - ip4_addr2_16(netif_ip4_gw(netif)), - ip4_addr3_16(netif_ip4_gw(netif)), - ip4_addr4_16(netif_ip4_gw(netif)))); - -#ifdef RT_USING_NETDEV - /* rt_thread network interface device set gateway address */ - netdev_low_level_set_gw(netdev_get_by_name(netif->name), &netif->gw); -#endif /* RT_USING_NETDEV */ -} - -/** - * @ingroup netif_ip4 - * Change the netmask of a network interface - * - * @param netif the network interface to change - * @param netmask the new netmask - * - * @note call netif_set_addr() if you also want to change ip address and - * default gateway - */ -void -netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask) -{ - mib2_remove_route_ip4(0, netif); - /* set new netmask to netif */ - ip4_addr_set(ip_2_ip4(&netif->netmask), netmask); - IP_SET_TYPE_VAL(netif->netmask, IPADDR_TYPE_V4); - mib2_add_route_ip4(0, netif); - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", - netif->name[0], netif->name[1], - ip4_addr1_16(netif_ip4_netmask(netif)), - ip4_addr2_16(netif_ip4_netmask(netif)), - ip4_addr3_16(netif_ip4_netmask(netif)), - ip4_addr4_16(netif_ip4_netmask(netif)))); - -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set netmask address */ - netdev_low_level_set_netmask(netdev_get_by_name(netif->name), &netif->netmask); -#endif /* RT_USING_NETDEV */ -} -#endif /* LWIP_IPV4 */ - -/** - * @ingroup netif - * Set a network interface as the default network interface - * (used to output all packets for which no specific route is found) - * - * @param netif the default network interface - */ -void -netif_set_default(struct netif *netif) -{ - if (netif == NULL) { - /* remove default route */ - mib2_remove_route_ip4(1, netif); - } else { - /* install default route */ - mib2_add_route_ip4(1, netif); - } - netif_default = netif; - LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", - netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); -} - -/** - * @ingroup netif - * Bring an interface up, available for processing - * traffic. - */ -void -netif_set_up(struct netif *netif) -{ - if (!(netif->flags & NETIF_FLAG_UP)) { - netif->flags |= NETIF_FLAG_UP; - - MIB2_COPY_SYSUPTIME_TO(&netif->ts); - - NETIF_STATUS_CALLBACK(netif); - - if (netif->flags & NETIF_FLAG_LINK_UP) { - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); - } - -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set up status */ - netdev_low_level_set_status(netdev_get_by_name(netif->name), RT_TRUE); -#endif /* RT_USING_NETDEV */ - } -} - -/** Send ARP/IGMP/MLD/RS events, e.g. on link-up/netif-up or addr-change - */ -static void -netif_issue_reports(struct netif* netif, u8_t report_type) -{ -#if LWIP_IPV4 - if ((report_type & NETIF_REPORT_TYPE_IPV4) && - !ip4_addr_isany_val(*netif_ip4_addr(netif))) { -#if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ - if (netif->flags & (NETIF_FLAG_ETHARP)) { - etharp_gratuitous(netif); - } -#endif /* LWIP_ARP */ - -#if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups(netif); - } -#endif /* LWIP_IGMP */ - } -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 - if (report_type & NETIF_REPORT_TYPE_IPV6) { -#if LWIP_IPV6_MLD - /* send mld memberships */ - mld6_report_groups(netif); -#endif /* LWIP_IPV6_MLD */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /* Send Router Solicitation messages. */ - netif->rs_count = LWIP_ND6_MAX_MULTICAST_SOLICIT; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ - } -#endif /* LWIP_IPV6 */ -} - -/** - * @ingroup netif - * Bring an interface down, disabling any traffic processing. - */ -void -netif_set_down(struct netif *netif) -{ - if (netif->flags & NETIF_FLAG_UP) { - netif->flags &= ~NETIF_FLAG_UP; - MIB2_COPY_SYSUPTIME_TO(&netif->ts); - -#if LWIP_IPV4 && LWIP_ARP - if (netif->flags & NETIF_FLAG_ETHARP) { - etharp_cleanup_netif(netif); - } -#endif /* LWIP_IPV4 && LWIP_ARP */ - -#if LWIP_IPV6 - nd6_cleanup_netif(netif); -#endif /* LWIP_IPV6 */ - - NETIF_STATUS_CALLBACK(netif); - -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set down status */ - netdev_low_level_set_status(netdev_get_by_name(netif->name), RT_FALSE); -#endif /* RT_USING_NETDEV */ - } -} - -#if LWIP_NETIF_STATUS_CALLBACK -/** - * @ingroup netif - * Set callback to be called when interface is brought up/down or address is changed while up - */ -void -netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) -{ - if (netif) { - netif->status_callback = status_callback; - } -} -#endif /* LWIP_NETIF_STATUS_CALLBACK */ - -#if LWIP_NETIF_REMOVE_CALLBACK -/** - * @ingroup netif - * Set callback to be called when the interface has been removed - */ -void -netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback) -{ - if (netif) { - netif->remove_callback = remove_callback; - } -} -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - -/** - * @ingroup netif - * Called by a driver when its link goes up - */ -void -netif_set_link_up(struct netif *netif) -{ - if (!(netif->flags & NETIF_FLAG_LINK_UP)) { - netif->flags |= NETIF_FLAG_LINK_UP; - -#if LWIP_DHCP - dhcp_network_changed(netif); -#endif /* LWIP_DHCP */ - -#if LWIP_AUTOIP - autoip_network_changed(netif); -#endif /* LWIP_AUTOIP */ - - if (netif->flags & NETIF_FLAG_UP) { - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4|NETIF_REPORT_TYPE_IPV6); - } - NETIF_LINK_CALLBACK(netif); - -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set link up status */ - netdev_low_level_set_link_status(netdev_get_by_name(netif->name), RT_TRUE); -#endif /* RT_USING_NETDEV */ - } -} - -/** - * @ingroup netif - * Called by a driver when its link goes down - */ -void -netif_set_link_down(struct netif *netif ) -{ - if (netif->flags & NETIF_FLAG_LINK_UP) { - netif->flags &= ~NETIF_FLAG_LINK_UP; - NETIF_LINK_CALLBACK(netif); - -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set link down status */ - netdev_low_level_set_link_status(netdev_get_by_name(netif->name), RT_FALSE); -#endif /* RT_USING_NETDEV */ - } -} - -#if LWIP_NETIF_LINK_CALLBACK -/** - * @ingroup netif - * Set callback to be called when link is brought up/down - */ -void -netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) -{ - if (netif) { - netif->link_callback = link_callback; - } -} -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#if ENABLE_LOOPBACK -/** - * @ingroup netif - * Send an IP packet to be received on the same netif (loopif-like). - * The pbuf is simply copied and handed back to netif->input. - * In multithreaded mode, this is done directly since netif->input must put - * the packet on a queue. - * In callback mode, the packet is put on an internal queue and is fed to - * netif->input by netif_poll(). - * - * @param netif the lwip network interface structure - * @param p the (IP) packet to 'send' - * @return ERR_OK if the packet has been sent - * ERR_MEM if the pbuf used to copy the packet couldn't be allocated - */ -err_t -netif_loop_output(struct netif *netif, struct pbuf *p) -{ - struct pbuf *r; - err_t err; - struct pbuf *last; -#if LWIP_LOOPBACK_MAX_PBUFS - u16_t clen = 0; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - /* If we have a loopif, SNMP counters are adjusted for it, - * if not they are adjusted for 'netif'. */ -#if MIB2_STATS -#if LWIP_HAVE_LOOPIF - struct netif *stats_if = &loop_netif; -#else /* LWIP_HAVE_LOOPIF */ - struct netif *stats_if = netif; -#endif /* LWIP_HAVE_LOOPIF */ -#endif /* MIB2_STATS */ - SYS_ARCH_DECL_PROTECT(lev); - - /* Allocate a new pbuf */ - r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - if (r == NULL) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); - return ERR_MEM; - } -#if LWIP_LOOPBACK_MAX_PBUFS - clen = pbuf_clen(r); - /* check for overflow or too many pbuf on queue */ - if (((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || - ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { - pbuf_free(r); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); - return ERR_MEM; - } - netif->loop_cnt_current += clen; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - /* Copy the whole pbuf queue p into the single pbuf r */ - if ((err = pbuf_copy(r, p)) != ERR_OK) { - pbuf_free(r); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(stats_if, ifoutdiscards); - return err; - } - - /* Put the packet on a linked list which gets emptied through calling - netif_poll(). */ - - /* let last point to the last pbuf in chain r */ - for (last = r; last->next != NULL; last = last->next); - - SYS_ARCH_PROTECT(lev); - if (netif->loop_first != NULL) { - LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); - netif->loop_last->next = r; - netif->loop_last = last; - } else { - netif->loop_first = r; - netif->loop_last = last; - } - SYS_ARCH_UNPROTECT(lev); - - LINK_STATS_INC(link.xmit); - MIB2_STATS_NETIF_ADD(stats_if, ifoutoctets, p->tot_len); - MIB2_STATS_NETIF_INC(stats_if, ifoutucastpkts); - -#if LWIP_NETIF_LOOPBACK_MULTITHREADING - /* For multithreading environment, schedule a call to netif_poll */ - tcpip_callback_with_block((tcpip_callback_fn)netif_poll, netif, 0); -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ - - return ERR_OK; -} - -#if LWIP_HAVE_LOOPIF -#if LWIP_IPV4 -static err_t -netif_loop_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t* addr) -{ - LWIP_UNUSED_ARG(addr); - return netif_loop_output(netif, p); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -static err_t -netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* addr) -{ - LWIP_UNUSED_ARG(addr); - return netif_loop_output(netif, p); -} -#endif /* LWIP_IPV6 */ -#endif /* LWIP_HAVE_LOOPIF */ - - -/** - * Call netif_poll() in the main loop of your application. This is to prevent - * reentering non-reentrant functions like tcp_input(). Packets passed to - * netif_loop_output() are put on a list that is passed to netif->input() by - * netif_poll(). - */ -void -netif_poll(struct netif *netif) -{ - /* If we have a loopif, SNMP counters are adjusted for it, - * if not they are adjusted for 'netif'. */ -#if MIB2_STATS -#if LWIP_HAVE_LOOPIF - struct netif *stats_if = &loop_netif; -#else /* LWIP_HAVE_LOOPIF */ - struct netif *stats_if = netif; -#endif /* LWIP_HAVE_LOOPIF */ -#endif /* MIB2_STATS */ - SYS_ARCH_DECL_PROTECT(lev); - - /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ - SYS_ARCH_PROTECT(lev); - while (netif->loop_first != NULL) { - struct pbuf *in, *in_end; -#if LWIP_LOOPBACK_MAX_PBUFS - u8_t clen = 1; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - in = in_end = netif->loop_first; - while (in_end->len != in_end->tot_len) { - LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); - in_end = in_end->next; -#if LWIP_LOOPBACK_MAX_PBUFS - clen++; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - } -#if LWIP_LOOPBACK_MAX_PBUFS - /* adjust the number of pbufs on queue */ - LWIP_ASSERT("netif->loop_cnt_current underflow", - ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); - netif->loop_cnt_current -= clen; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ - - /* 'in_end' now points to the last pbuf from 'in' */ - if (in_end == netif->loop_last) { - /* this was the last pbuf in the list */ - netif->loop_first = netif->loop_last = NULL; - } else { - /* pop the pbuf off the list */ - netif->loop_first = in_end->next; - LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); - } - /* De-queue the pbuf from its successors on the 'loop_' list. */ - in_end->next = NULL; - SYS_ARCH_UNPROTECT(lev); - - LINK_STATS_INC(link.recv); - MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); - MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); - /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { - pbuf_free(in); - } - SYS_ARCH_PROTECT(lev); - } - SYS_ARCH_UNPROTECT(lev); -} - -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING -/** - * Calls netif_poll() for every netif on the netif_list. - */ -void -netif_poll_all(void) -{ - struct netif *netif = netif_list; - /* loop through netifs */ - while (netif != NULL) { - netif_poll(netif); - /* proceed to next network interface */ - netif = netif->next; - } -} -#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -#if LWIP_NUM_NETIF_CLIENT_DATA > 0 -/** - * @ingroup netif_cd - * Allocate an index to store data in client_data member of struct netif. - * Returned value is an index in mentioned array. - * @see LWIP_NUM_NETIF_CLIENT_DATA - */ -u8_t -netif_alloc_client_data_id(void) -{ - u8_t result = netif_client_id; - netif_client_id++; - - LWIP_ASSERT("Increase LWIP_NUM_NETIF_CLIENT_DATA in lwipopts.h", result < LWIP_NUM_NETIF_CLIENT_DATA); - return result + LWIP_NETIF_CLIENT_DATA_INDEX_MAX; -} -#endif - -#if LWIP_IPV6 -/** - * @ingroup netif_ip6 - * Change an IPv6 address of a network interface - * - * @param netif the network interface to change - * @param addr_idx index of the IPv6 address - * @param addr6 the new IPv6 address - * - * @note call netif_ip6_addr_set_state() to set the address valid/temptative - */ -void -netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6) -{ - LWIP_ASSERT("addr6 != NULL", addr6 != NULL); - netif_ip6_addr_set_parts(netif, addr_idx, addr6->addr[0], addr6->addr[1], - addr6->addr[2], addr6->addr[3]); -} - -/* - * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) - * - * @param netif the network interface to change - * @param addr_idx index of the IPv6 address - * @param i0 word0 of the new IPv6 address - * @param i1 word1 of the new IPv6 address - * @param i2 word2 of the new IPv6 address - * @param i3 word3 of the new IPv6 address - */ -void -netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) -{ - const ip6_addr_t *old_addr; - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); - - old_addr = netif_ip6_addr(netif, addr_idx); - /* address is actually being changed? */ - if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || - (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); - - if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { -#if LWIP_TCP || LWIP_UDP - ip_addr_t new_ipaddr; - IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); -#endif /* LWIP_TCP || LWIP_UDP */ -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); -#endif /* LWIP_RAW */ - } - /* @todo: remove/readd mib2 ip6 entries? */ - - IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); - IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); - - if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); - NETIF_STATUS_CALLBACK(netif); - } - } - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", - addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), - netif_ip6_addr_state(netif, addr_idx))); -} - -/** - * @ingroup netif_ip6 - * Change the state of an IPv6 address of a network interface - * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE - * includes the number of checks done, see ip6_addr.h) - * - * @param netif the network interface to change - * @param addr_idx index of the IPv6 address - * @param state the new IPv6 address state - */ -void -netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) -{ - u8_t old_state; - LWIP_ASSERT("netif != NULL", netif != NULL); - LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); - - old_state = netif_ip6_addr_state(netif, addr_idx); - /* state is actually being changed? */ - if (old_state != state) { - u8_t old_valid = old_state & IP6_ADDR_VALID; - u8_t new_valid = state & IP6_ADDR_VALID; - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); - -#if LWIP_IPV6_MLD - /* Reevaluate solicited-node multicast group membership. */ - if (netif->flags & NETIF_FLAG_MLD6) { - nd6_adjust_mld_membership(netif, addr_idx, state); - } -#endif /* LWIP_IPV6_MLD */ - - if (old_valid && !new_valid) { - /* address about to be removed by setting invalid */ -#if LWIP_TCP - tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); -#endif /* LWIP_TCP */ -#if LWIP_UDP - udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); -#endif /* LWIP_UDP */ -#if LWIP_RAW - raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); -#endif /* LWIP_RAW */ - /* @todo: remove mib2 ip6 entries? */ - } - netif->ip6_addr_state[addr_idx] = state; - - if (!old_valid && new_valid) { - /* address added by setting valid */ - /* @todo: add mib2 ip6 entries? */ - netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); - } - if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { - /* address state has changed (valid flag changed or switched between - preferred and deprecated) -> call the callback function */ - NETIF_STATUS_CALLBACK(netif); - } - } - - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", - addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), - netif_ip6_addr_state(netif, addr_idx))); -} - -/** - * Checks if a specific address is assigned to the netif and returns its - * index. - * - * @param netif the netif to check - * @param ip6addr the IPv6 address to find - * @return >= 0: address found, this is its index - * -1: address not found on this netif - */ -s8_t -netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr) -{ - s8_t i; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)) && - ip6_addr_cmp(netif_ip6_addr(netif, i), ip6addr)) { - return i; - } - } - return -1; -} - -/** - * @ingroup netif_ip6 - * Create a link-local IPv6 address on a netif (stored in slot 0) - * - * @param netif the netif to create the address on - * @param from_mac_48bit if != 0, assume hwadr is a 48-bit MAC address (std conversion) - * if == 0, use hwaddr directly as interface ID - */ -void -netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit) -{ - u8_t i, addr_index; - - /* Link-local prefix. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[0] = PP_HTONL(0xfe800000ul); - ip_2_ip6(&netif->ip6_addr[0])->addr[1] = 0; - - /* Generate interface ID. */ - if (from_mac_48bit) { - /* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) | - ((u32_t)(netif->hwaddr[1]) << 16) | - ((u32_t)(netif->hwaddr[2]) << 8) | - (0xff)); - ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) | - ((u32_t)(netif->hwaddr[3]) << 16) | - ((u32_t)(netif->hwaddr[4]) << 8) | - (netif->hwaddr[5])); - } else { - /* Use hwaddr directly as interface ID. */ - ip_2_ip6(&netif->ip6_addr[0])->addr[2] = 0; - ip_2_ip6(&netif->ip6_addr[0])->addr[3] = 0; - - addr_index = 3; - for (i = 0; (i < 8) && (i < netif->hwaddr_len); i++) { - if (i == 4) { - addr_index--; - } - ip_2_ip6(&netif->ip6_addr[0])->addr[addr_index] |= ((u32_t)(netif->hwaddr[netif->hwaddr_len - i - 1])) << (8 * (i & 0x03)); - } - } - -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set ipv6 address */ - ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[0], netif->ip6_addr[0]); -#endif /* RT_USING_NETDEV */ - - /* Set address state. */ -#if LWIP_IPV6_DUP_DETECT_ATTEMPTS - /* Will perform duplicate address detection (DAD). */ - netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE); -#else - /* Consider address valid. */ - netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED); -#endif /* LWIP_IPV6_AUTOCONFIG */ -} - -/** - * @ingroup netif_ip6 - * This function allows for the easy addition of a new IPv6 address to an interface. - * It takes care of finding an empty slot and then sets the address tentative - * (to make sure that all the subsequent processing happens). - * - * @param netif netif to add the address on - * @param ip6addr address to add - * @param chosen_idx if != NULL, the chosen IPv6 address index will be stored here - */ -err_t -netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx) -{ - s8_t i; - - i = netif_get_ip6_addr_match(netif, ip6addr); - if (i >= 0) { - /* Address already added */ - if (chosen_idx != NULL) { - *chosen_idx = i; - } - return ERR_OK; - } - - /* Find a free slot -- musn't be the first one (reserved for link local) */ - for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) { - ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr); -#ifdef RT_USING_NETDEV - /* rt-thread network interface device set ipv6 address */ - ip_addr_copy(netdev_get_by_name(netif->name)->ip6_addr[i], netif->ip6_addr[i]); -#endif /* RT_USING_NETDEV */ - netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE); - if (chosen_idx != NULL) { - *chosen_idx = i; - } - return ERR_OK; - } - } - - if (chosen_idx != NULL) { - *chosen_idx = -1; - } - return ERR_VAL; -} - -/** Dummy IPv6 output function for netifs not supporting IPv6 - */ -static err_t -netif_null_output_ip6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(netif); - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(ipaddr); - - return ERR_IF; -} -#endif /* LWIP_IPV6 */ diff --git a/components/net/lwip-2.0.2/src/core/pbuf.c b/components/net/lwip-2.0.2/src/core/pbuf.c deleted file mode 100644 index 059f83a571..0000000000 --- a/components/net/lwip-2.0.2/src/core/pbuf.c +++ /dev/null @@ -1,1442 +0,0 @@ -/** - * @file - * Packet buffer management - */ - -/** - * @defgroup pbuf Packet buffers (PBUF) - * @ingroup infrastructure - * - * Packets are built from the pbuf data structure. It supports dynamic - * memory allocation for packet contents or can reference externally - * managed packet contents both in RAM and ROM. Quick allocation for - * incoming packets is provided through pools with fixed sized pbufs. - * - * A packet may span over multiple pbufs, chained as a singly linked - * list. This is called a "pbuf chain". - * - * Multiple packets may be queued, also using this singly linked list. - * This is called a "packet queue". - * - * So, a packet queue consists of one or more pbuf chains, each of - * which consist of one or more pbufs. CURRENTLY, PACKET QUEUES ARE - * NOT SUPPORTED!!! Use helper structs to queue multiple packets. - * - * The differences between a pbuf chain and a packet queue are very - * precise but subtle. - * - * The last pbuf of a packet has a ->tot_len field that equals the - * ->len field. It can be found by traversing the list. If the last - * pbuf of a packet has a ->next field other than NULL, more packets - * are on the queue. - * - * Therefore, looping through a pbuf of a single packet, has an - * loop end condition (tot_len == p->len), NOT (next == NULL). - * - * Example of custom pbuf usage for zero-copy RX: - @code{.c} -typedef struct my_custom_pbuf -{ - struct pbuf_custom p; - void* dma_descriptor; -} my_custom_pbuf_t; - -LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool"); - -void my_pbuf_free_custom(void* p) -{ - my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p; - - LOCK_INTERRUPTS(); - free_rx_dma_descriptor(my_pbuf->dma_descriptor); - LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf); - UNLOCK_INTERRUPTS(); -} - -void eth_rx_irq() -{ - dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet(); - my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL); - - my_pbuf->p.custom_free_function = my_pbuf_free_custom; - my_pbuf->dma_descriptor = dma_desc; - - invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length); - - struct pbuf* p = pbuf_alloced_custom(PBUF_RAW, - dma_desc->rx_length, - PBUF_REF, - &my_pbuf->p, - dma_desc->rx_data, - dma_desc->max_buffer_size); - - if(netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } -} - @endcode - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/stats.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" -#if LWIP_TCP && TCP_QUEUE_OOSEQ -#include "lwip/priv/tcp_priv.h" -#endif -#if LWIP_CHECKSUM_ON_COPY -#include "lwip/inet_chksum.h" -#endif - -#include - -#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) -/* Since the pool is created in memp, PBUF_POOL_BUFSIZE will be automatically - aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ -#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - -#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ -#define PBUF_POOL_IS_EMPTY() -#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ - -#if !NO_SYS -#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL -#include "lwip/tcpip.h" -#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \ - if (tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \ - SYS_ARCH_PROTECT(old_level); \ - pbuf_free_ooseq_pending = 0; \ - SYS_ARCH_UNPROTECT(old_level); \ - } } while(0) -#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ -#endif /* !NO_SYS */ - -volatile u8_t pbuf_free_ooseq_pending; -#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty() - -/** - * Attempt to reclaim some memory from queued out-of-sequence TCP segments - * if we run out of pool pbufs. It's better to give priority to new packets - * if we're running out. - * - * This must be done in the correct thread context therefore this function - * can only be used with NO_SYS=0 and through tcpip_callback. - */ -#if !NO_SYS -static -#endif /* !NO_SYS */ -void -pbuf_free_ooseq(void) -{ - struct tcp_pcb* pcb; - SYS_ARCH_SET(pbuf_free_ooseq_pending, 0); - - for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) { - if (NULL != pcb->ooseq) { - /** Free the ooseq pbufs of one PCB only */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n")); - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; - return; - } - } -} - -#if !NO_SYS -/** - * Just a callback function for tcpip_callback() that calls pbuf_free_ooseq(). - */ -static void -pbuf_free_ooseq_callback(void *arg) -{ - LWIP_UNUSED_ARG(arg); - pbuf_free_ooseq(); -} -#endif /* !NO_SYS */ - -/** Queue a call to pbuf_free_ooseq if not already queued. */ -static void -pbuf_pool_is_empty(void) -{ -#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL - SYS_ARCH_SET(pbuf_free_ooseq_pending, 1); -#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ - u8_t queued; - SYS_ARCH_DECL_PROTECT(old_level); - SYS_ARCH_PROTECT(old_level); - queued = pbuf_free_ooseq_pending; - pbuf_free_ooseq_pending = 1; - SYS_ARCH_UNPROTECT(old_level); - - if (!queued) { - /* queue a call to pbuf_free_ooseq if not already queued */ - PBUF_POOL_FREE_OOSEQ_QUEUE_CALL(); - } -#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */ -} -#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */ - -/** - * @ingroup pbuf - * Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type). - * - * The actual memory allocated for the pbuf is determined by the - * layer at which the pbuf is allocated and the requested size - * (from the size parameter). - * - * @param layer flag to define header size - * @param length size of the pbuf's payload - * @param type this parameter decides how and where the pbuf - * should be allocated as follows: - * - * - PBUF_RAM: buffer memory for pbuf is allocated as one large - * chunk. This includes protocol headers as well. - * - PBUF_ROM: no buffer memory is allocated for the pbuf, even for - * protocol headers. Additional headers must be prepended - * by allocating another pbuf and chain in to the front of - * the ROM pbuf. It is assumed that the memory used is really - * similar to ROM in that it is immutable and will not be - * changed. Memory which is dynamic should generally not - * be attached to PBUF_ROM pbufs. Use PBUF_REF instead. - * - PBUF_REF: no buffer memory is allocated for the pbuf, even for - * protocol headers. It is assumed that the pbuf is only - * being used in a single thread. If the pbuf gets queued, - * then pbuf_take should be called to copy the buffer. - * - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from - * the pbuf pool that is allocated during pbuf_init(). - * - * @return the allocated pbuf. If multiple pbufs where allocated, this - * is the first pbuf of a pbuf chain. - */ -struct pbuf * -pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) -{ - struct pbuf *p, *q, *r; - u16_t offset; - s32_t rem_len; /* remaining length */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length)); - - /* determine header offset */ - switch (layer) { - case PBUF_TRANSPORT: - /* add room for transport (often TCP) layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; - break; - case PBUF_IP: - /* add room for IP layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; - break; - case PBUF_LINK: - /* add room for link layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; - break; - case PBUF_RAW_TX: - /* add room for encapsulating link layer headers (e.g. 802.11) */ - offset = PBUF_LINK_ENCAPSULATION_HLEN; - break; - case PBUF_RAW: - /* no offset (e.g. RX buffers or chain successors) */ - offset = 0; - break; - default: - LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0); - return NULL; - } - - switch (type) { - case PBUF_POOL: - /* allocate head of pbuf chain into p */ - p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p)); - if (p == NULL) { - PBUF_POOL_IS_EMPTY(); - return NULL; - } - p->type = type; - p->next = NULL; - - /* make the payload pointer point 'offset' bytes into pbuf data memory */ - p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + (SIZEOF_STRUCT_PBUF + offset))); - LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned", - ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); - /* the total length of the pbuf chain is the requested size */ - p->tot_len = length; - /* set the length of the first pbuf in the chain */ - p->len = LWIP_MIN(length, PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)); - LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", - ((u8_t*)p->payload + p->len <= - (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); - LWIP_ASSERT("PBUF_POOL_BUFSIZE must be bigger than MEM_ALIGNMENT", - (PBUF_POOL_BUFSIZE_ALIGNED - LWIP_MEM_ALIGN_SIZE(offset)) > 0 ); - /* set reference count (needed here in case we fail) */ - p->ref = 1; - - /* now allocate the tail of the pbuf chain */ - - /* remember first pbuf for linkage in next iteration */ - r = p; - /* remaining length to be allocated */ - rem_len = length - p->len; - /* any remaining pbufs to be allocated? */ - while (rem_len > 0) { - q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL); - if (q == NULL) { - PBUF_POOL_IS_EMPTY(); - /* free chain so far allocated */ - pbuf_free(p); - /* bail out unsuccessfully */ - return NULL; - } - q->type = type; - q->flags = 0; - q->next = NULL; - /* make previous pbuf point to this pbuf */ - r->next = q; - /* set total length of this pbuf and next in chain */ - LWIP_ASSERT("rem_len < max_u16_t", rem_len < 0xffff); - q->tot_len = (u16_t)rem_len; - /* this pbuf length is pool size, unless smaller sized tail */ - q->len = LWIP_MIN((u16_t)rem_len, PBUF_POOL_BUFSIZE_ALIGNED); - q->payload = (void *)((u8_t *)q + SIZEOF_STRUCT_PBUF); - LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned", - ((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0); - LWIP_ASSERT("check p->payload + p->len does not overflow pbuf", - ((u8_t*)p->payload + p->len <= - (u8_t*)p + SIZEOF_STRUCT_PBUF + PBUF_POOL_BUFSIZE_ALIGNED)); - q->ref = 1; - /* calculate remaining length to be allocated */ - rem_len -= q->len; - /* remember this pbuf for linkage in next iteration */ - r = q; - } - /* end of chain */ - /*r->next = NULL;*/ - - break; - case PBUF_RAM: - { - mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length); - - /* bug #50040: Check for integer overflow when calculating alloc_len */ - if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) { - return NULL; - } - - /* If pbuf is to be allocated in RAM, allocate memory for it. */ - p = (struct pbuf*)mem_malloc(alloc_len); - } - - if (p == NULL) { - return NULL; - } - /* Set up internal structure of the pbuf. */ - p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); - p->len = p->tot_len = length; - p->next = NULL; - p->type = type; - - LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", - ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); - break; - /* pbuf references existing (non-volatile static constant) ROM payload? */ - case PBUF_ROM: - /* pbuf references existing (externally allocated) RAM payload? */ - case PBUF_REF: - /* only allocate memory for the pbuf structure */ - p = (struct pbuf *)memp_malloc(MEMP_PBUF); - if (p == NULL) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", - (type == PBUF_ROM) ? "ROM" : "REF")); - return NULL; - } - /* caller must set this field properly, afterwards */ - p->payload = NULL; - p->len = p->tot_len = length; - p->next = NULL; - p->type = type; - break; - default: - LWIP_ASSERT("pbuf_alloc: erroneous type", 0); - return NULL; - } - /* set reference count */ - p->ref = 1; - /* set flags */ - p->flags = 0; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); - return p; -} - -#if LWIP_SUPPORT_CUSTOM_PBUF -/** - * @ingroup pbuf - * Initialize a custom pbuf (already allocated). - * - * @param l flag to define header size - * @param length size of the pbuf's payload - * @param type type of the pbuf (only used to treat the pbuf accordingly, as - * this function allocates no memory) - * @param p pointer to the custom pbuf to initialize (already allocated) - * @param payload_mem pointer to the buffer that is used for payload and headers, - * must be at least big enough to hold 'length' plus the header size, - * may be NULL if set later. - * ATTENTION: The caller is responsible for correct alignment of this buffer!! - * @param payload_mem_len the size of the 'payload_mem' buffer, must be at least - * big enough to hold 'length' plus the header size - */ -struct pbuf* -pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p, - void *payload_mem, u16_t payload_mem_len) -{ - u16_t offset; - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length)); - - /* determine header offset */ - switch (l) { - case PBUF_TRANSPORT: - /* add room for transport (often TCP) layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN; - break; - case PBUF_IP: - /* add room for IP layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN; - break; - case PBUF_LINK: - /* add room for link layer header */ - offset = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; - break; - case PBUF_RAW_TX: - /* add room for encapsulating link layer headers (e.g. 802.11) */ - offset = PBUF_LINK_ENCAPSULATION_HLEN; - break; - case PBUF_RAW: - offset = 0; - break; - default: - LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0); - return NULL; - } - - if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length)); - return NULL; - } - - p->pbuf.next = NULL; - if (payload_mem != NULL) { - p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset); - } else { - p->pbuf.payload = NULL; - } - p->pbuf.flags = PBUF_FLAG_IS_CUSTOM; - p->pbuf.len = p->pbuf.tot_len = length; - p->pbuf.type = type; - p->pbuf.ref = 1; - return &p->pbuf; -} -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - -/** - * @ingroup pbuf - * Shrink a pbuf chain to a desired length. - * - * @param p pbuf to shrink. - * @param new_len desired new length of pbuf chain - * - * Depending on the desired length, the first few pbufs in a chain might - * be skipped and left unchanged. The new last pbuf in the chain will be - * resized, and any remaining pbufs will be freed. - * - * @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted. - * @note May not be called on a packet queue. - * - * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). - */ -void -pbuf_realloc(struct pbuf *p, u16_t new_len) -{ - struct pbuf *q; - u16_t rem_len; /* remaining length */ - s32_t grow; - - LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); - LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_POOL || - p->type == PBUF_ROM || - p->type == PBUF_RAM || - p->type == PBUF_REF); - - /* desired length larger than current length? */ - if (new_len >= p->tot_len) { - /* enlarging not yet supported */ - return; - } - - /* the pbuf chain grows by (new_len - p->tot_len) bytes - * (which may be negative in case of shrinking) */ - grow = new_len - p->tot_len; - - /* first, step over any pbufs that should remain in the chain */ - rem_len = new_len; - q = p; - /* should this pbuf be kept? */ - while (rem_len > q->len) { - /* decrease remaining length by pbuf length */ - rem_len -= q->len; - /* decrease total length indicator */ - LWIP_ASSERT("grow < max_u16_t", grow < 0xffff); - q->tot_len += (u16_t)grow; - /* proceed to next pbuf in chain */ - q = q->next; - LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); - } - /* we have now reached the new last pbuf (in q) */ - /* rem_len == desired length for pbuf q */ - - /* shrink allocated memory for PBUF_RAM */ - /* (other types merely adjust their length fields */ - if ((q->type == PBUF_RAM) && (rem_len != q->len) -#if LWIP_SUPPORT_CUSTOM_PBUF - && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - ) { - /* reallocate and adjust the length of the pbuf that will be split */ - q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len); - LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); - } - /* adjust length fields for new last pbuf */ - q->len = rem_len; - q->tot_len = q->len; - - /* any remaining pbufs in chain? */ - if (q->next != NULL) { - /* free remaining pbufs in chain */ - pbuf_free(q->next); - } - /* q is last packet in chain */ - q->next = NULL; - -} - -/** - * Adjusts the payload pointer to hide or reveal headers in the payload. - * @see pbuf_header. - * - * @param p pbuf to change the header size. - * @param header_size_increment Number of bytes to increment header size. - * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types - * - * @return non-zero on failure, zero on success. - * - */ -static u8_t -pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force) -{ - u16_t type; - void *payload; - u16_t increment_magnitude; - - LWIP_ASSERT("p != NULL", p != NULL); - if ((header_size_increment == 0) || (p == NULL)) { - return 0; - } - - if (header_size_increment < 0) { - increment_magnitude = (u16_t)-header_size_increment; - /* Check that we aren't going to move off the end of the pbuf */ - LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;); - } else { - increment_magnitude = (u16_t)header_size_increment; -#if 0 - /* Can't assert these as some callers speculatively call - pbuf_header() to see if it's OK. Will return 1 below instead. */ - /* Check that we've got the correct type of pbuf to work with */ - LWIP_ASSERT("p->type == PBUF_RAM || p->type == PBUF_POOL", - p->type == PBUF_RAM || p->type == PBUF_POOL); - /* Check that we aren't going to move off the beginning of the pbuf */ - LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", - (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); -#endif - } - - type = p->type; - /* remember current payload pointer */ - payload = p->payload; - - /* pbuf types containing payloads? */ - if (type == PBUF_RAM || type == PBUF_POOL) { - /* set new payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - /* boundary check fails? */ - if ((u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF) { - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, - ("pbuf_header: failed as %p < %p (not enough space for new header size)\n", - (void *)p->payload, (void *)((u8_t *)p + SIZEOF_STRUCT_PBUF))); - /* restore old payload pointer */ - p->payload = payload; - /* bail out unsuccessfully */ - return 1; - } - /* pbuf types referring to external payloads? */ - } else if (type == PBUF_REF || type == PBUF_ROM) { - /* hide a header in the payload? */ - if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { - /* increase payload pointer */ - p->payload = (u8_t *)p->payload - header_size_increment; - } else if ((header_size_increment > 0) && force) { - p->payload = (u8_t *)p->payload - header_size_increment; - } else { - /* cannot expand payload to front (yet!) - * bail out unsuccessfully */ - return 1; - } - } else { - /* Unknown type */ - LWIP_ASSERT("bad pbuf type", 0); - return 1; - } - /* modify pbuf length fields */ - p->len += header_size_increment; - p->tot_len += header_size_increment; - - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_header: old %p new %p (%"S16_F")\n", - (void *)payload, (void *)p->payload, header_size_increment)); - - return 0; -} - -/** - * Adjusts the payload pointer to hide or reveal headers in the payload. - * - * Adjusts the ->payload pointer so that space for a header - * (dis)appears in the pbuf payload. - * - * The ->payload, ->tot_len and ->len fields are adjusted. - * - * @param p pbuf to change the header size. - * @param header_size_increment Number of bytes to increment header size which - * increases the size of the pbuf. New space is on the front. - * (Using a negative value decreases the header size.) - * If hdr_size_inc is 0, this function does nothing and returns successful. - * - * PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so - * the call will fail. A check is made that the increase in header size does - * not move the payload pointer in front of the start of the buffer. - * @return non-zero on failure, zero on success. - * - */ -u8_t -pbuf_header(struct pbuf *p, s16_t header_size_increment) -{ - return pbuf_header_impl(p, header_size_increment, 0); -} - -/** - * Same as pbuf_header but does not check if 'header_size > 0' is allowed. - * This is used internally only, to allow PBUF_REF for RX. - */ -u8_t -pbuf_header_force(struct pbuf *p, s16_t header_size_increment) -{ - return pbuf_header_impl(p, header_size_increment, 1); -} - -/** - * @ingroup pbuf - * Dereference a pbuf chain or queue and deallocate any no-longer-used - * pbufs at the head of this chain or queue. - * - * Decrements the pbuf reference count. If it reaches zero, the pbuf is - * deallocated. - * - * For a pbuf chain, this is repeated for each pbuf in the chain, - * up to the first pbuf which has a non-zero reference count after - * decrementing. So, when all reference counts are one, the whole - * chain is free'd. - * - * @param p The pbuf (chain) to be dereferenced. - * - * @return the number of pbufs that were de-allocated - * from the head of the chain. - * - * @note MUST NOT be called on a packet queue (Not verified to work yet). - * @note the reference counter of a pbuf equals the number of pointers - * that refer to the pbuf (or into the pbuf). - * - * @internal examples: - * - * Assuming existing chains a->b->c with the following reference - * counts, calling pbuf_free(a) results in: - * - * 1->2->3 becomes ...1->3 - * 3->3->3 becomes 2->3->3 - * 1->1->2 becomes ......1 - * 2->1->1 becomes 1->1->1 - * 1->1->1 becomes ....... - * - */ -u8_t -pbuf_free(struct pbuf *p) -{ - u16_t type; - struct pbuf *q; - u8_t count; - - if (p == NULL) { - LWIP_ASSERT("p != NULL", p != NULL); - /* if assertions are disabled, proceed with debug output */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("pbuf_free(p == NULL) was called.\n")); - return 0; - } - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p)); - - PERF_START; - - LWIP_ASSERT("pbuf_free: sane type", - p->type == PBUF_RAM || p->type == PBUF_ROM || - p->type == PBUF_REF || p->type == PBUF_POOL); - - count = 0; - /* de-allocate all consecutive pbufs from the head of the chain that - * obtain a zero reference count after decrementing*/ - while (p != NULL) { - u16_t ref; - SYS_ARCH_DECL_PROTECT(old_level); - /* Since decrementing ref cannot be guaranteed to be a single machine operation - * we must protect it. We put the new ref into a local variable to prevent - * further protection. */ - SYS_ARCH_PROTECT(old_level); - /* all pbufs in a chain are referenced at least once */ - LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0); - /* decrease reference count (number of pointers to pbuf) */ - ref = --(p->ref); - SYS_ARCH_UNPROTECT(old_level); - /* this pbuf is no longer referenced to? */ - if (ref == 0) { - /* remember next pbuf in chain for next iteration */ - q = p->next; - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p)); - type = p->type; -#if LWIP_SUPPORT_CUSTOM_PBUF - /* is this a custom pbuf? */ - if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) { - struct pbuf_custom *pc = (struct pbuf_custom*)p; - LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL); - pc->custom_free_function(p); - } else -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - { - /* is this a pbuf from the pool? */ - if (type == PBUF_POOL) { - memp_free(MEMP_PBUF_POOL, p); - /* is this a ROM or RAM referencing pbuf? */ - } else if (type == PBUF_ROM || type == PBUF_REF) { - memp_free(MEMP_PBUF, p); - /* type == PBUF_RAM */ - } else { - mem_free(p); - } - } - count++; - /* proceed to next pbuf */ - p = q; - /* p->ref > 0, this pbuf is still referenced to */ - /* (and so the remaining pbufs in chain as well) */ - } else { - LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, ref)); - /* stop walking through the chain */ - p = NULL; - } - } - PERF_STOP("pbuf_free"); - /* return number of de-allocated pbufs */ - return count; -} - -/** - * Count number of pbufs in a chain - * - * @param p first pbuf of chain - * @return the number of pbufs in a chain - */ -u16_t -pbuf_clen(const struct pbuf *p) -{ - u16_t len; - - len = 0; - while (p != NULL) { - ++len; - p = p->next; - } - return len; -} - -/** - * @ingroup pbuf - * Increment the reference count of the pbuf. - * - * @param p pbuf to increase reference counter of - * - */ -void -pbuf_ref(struct pbuf *p) -{ - /* pbuf given? */ - if (p != NULL) { - SYS_ARCH_INC(p->ref, 1); - LWIP_ASSERT("pbuf ref overflow", p->ref > 0); - } -} - -/** - * @ingroup pbuf - * Concatenate two pbufs (each may be a pbuf chain) and take over - * the caller's reference of the tail pbuf. - * - * @note The caller MAY NOT reference the tail pbuf afterwards. - * Use pbuf_chain() for that purpose. - * - * @see pbuf_chain() - */ -void -pbuf_cat(struct pbuf *h, struct pbuf *t) -{ - struct pbuf *p; - - LWIP_ERROR("(h != NULL) && (t != NULL) (programmer violates API)", - ((h != NULL) && (t != NULL)), return;); - - /* proceed to last pbuf of chain */ - for (p = h; p->next != NULL; p = p->next) { - /* add total length of second chain to all totals of first chain */ - p->tot_len += t->tot_len; - } - /* { p is last pbuf of first h chain, p->next == NULL } */ - LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len); - LWIP_ASSERT("p->next == NULL", p->next == NULL); - /* add total length of second chain to last pbuf total of first chain */ - p->tot_len += t->tot_len; - /* chain last pbuf of head (p) with first of tail (t) */ - p->next = t; - /* p->next now references t, but the caller will drop its reference to t, - * so netto there is no change to the reference count of t. - */ -} - -/** - * @ingroup pbuf - * Chain two pbufs (or pbuf chains) together. - * - * The caller MUST call pbuf_free(t) once it has stopped - * using it. Use pbuf_cat() instead if you no longer use t. - * - * @param h head pbuf (chain) - * @param t tail pbuf (chain) - * @note The pbufs MUST belong to the same packet. - * @note MAY NOT be called on a packet queue. - * - * The ->tot_len fields of all pbufs of the head chain are adjusted. - * The ->next field of the last pbuf of the head chain is adjusted. - * The ->ref field of the first pbuf of the tail chain is adjusted. - * - */ -void -pbuf_chain(struct pbuf *h, struct pbuf *t) -{ - pbuf_cat(h, t); - /* t is now referenced by h */ - pbuf_ref(t); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t)); -} - -/** - * Dechains the first pbuf from its succeeding pbufs in the chain. - * - * Makes p->tot_len field equal to p->len. - * @param p pbuf to dechain - * @return remainder of the pbuf chain, or NULL if it was de-allocated. - * @note May not be called on a packet queue. - */ -struct pbuf * -pbuf_dechain(struct pbuf *p) -{ - struct pbuf *q; - u8_t tail_gone = 1; - /* tail */ - q = p->next; - /* pbuf has successor in chain? */ - if (q != NULL) { - /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ - LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len); - /* enforce invariant if assertion is disabled */ - q->tot_len = p->tot_len - p->len; - /* decouple pbuf from remainder */ - p->next = NULL; - /* total length of pbuf p is its own length only */ - p->tot_len = p->len; - /* q is no longer referenced by p, free it */ - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_dechain: unreferencing %p\n", (void *)q)); - tail_gone = pbuf_free(q); - if (tail_gone > 0) { - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, - ("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q)); - } - /* return remaining tail or NULL if deallocated */ - } - /* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */ - LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len); - return ((tail_gone > 0) ? NULL : q); -} - -/** - * @ingroup pbuf - * Create PBUF_RAM copies of pbufs. - * - * Used to queue packets on behalf of the lwIP stack, such as - * ARP based queueing. - * - * @note You MUST explicitly use p = pbuf_take(p); - * - * @note Only one packet is copied, no packet queue! - * - * @param p_to pbuf destination of the copy - * @param p_from pbuf source of the copy - * - * @return ERR_OK if pbuf was copied - * ERR_ARG if one of the pbufs is NULL or p_to is not big - * enough to hold p_from - */ -err_t -pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from) -{ - u16_t offset_to=0, offset_from=0, len; - - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n", - (const void*)p_to, (const void*)p_from)); - - /* is the target big enough to hold the source? */ - LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) && - (p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;); - - /* iterate through pbuf chain */ - do - { - /* copy one part of the original chain */ - if ((p_to->len - offset_to) >= (p_from->len - offset_from)) { - /* complete current p_from fits into current p_to */ - len = p_from->len - offset_from; - } else { - /* current p_from does not fit into current p_to */ - len = p_to->len - offset_to; - } - MEMCPY((u8_t*)p_to->payload + offset_to, (u8_t*)p_from->payload + offset_from, len); - offset_to += len; - offset_from += len; - LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len); - LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len); - if (offset_from >= p_from->len) { - /* on to next p_from (if any) */ - offset_from = 0; - p_from = p_from->next; - } - if (offset_to == p_to->len) { - /* on to next p_to (if any) */ - offset_to = 0; - p_to = p_to->next; - LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;); - } - - if ((p_from != NULL) && (p_from->len == p_from->tot_len)) { - /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!", - (p_from->next == NULL), return ERR_VAL;); - } - if ((p_to != NULL) && (p_to->len == p_to->tot_len)) { - /* don't copy more than one packet! */ - LWIP_ERROR("pbuf_copy() does not allow packet queues!", - (p_to->next == NULL), return ERR_VAL;); - } - } while (p_from); - LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n")); - return ERR_OK; -} - -/** - * @ingroup pbuf - * Copy (part of) the contents of a packet buffer - * to an application supplied buffer. - * - * @param buf the pbuf from which to copy data - * @param dataptr the application supplied buffer - * @param len length of data to copy (dataptr must be big enough). No more - * than buf->tot_len will be copied, irrespective of len - * @param offset offset into the packet buffer from where to begin copying len bytes - * @return the number of bytes copied, or 0 on failure - */ -u16_t -pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) -{ - const struct pbuf *p; - u16_t left; - u16_t buf_copy_len; - u16_t copied_total = 0; - - LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); - LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); - - left = 0; - - if ((buf == NULL) || (dataptr == NULL)) { - return 0; - } - - /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ - for (p = buf; len != 0 && p != NULL; p = p->next) { - if ((offset != 0) && (offset >= p->len)) { - /* don't copy from this buffer -> on to the next */ - offset -= p->len; - } else { - /* copy from this buffer. maybe only partially. */ - buf_copy_len = p->len - offset; - if (buf_copy_len > len) { - buf_copy_len = len; - } - /* copy the necessary parts of the buffer */ - MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); - copied_total += buf_copy_len; - left += buf_copy_len; - len -= buf_copy_len; - offset = 0; - } - } - return copied_total; -} - -#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE -/** - * This method modifies a 'pbuf chain', so that its total length is - * smaller than 64K. The remainder of the original pbuf chain is stored - * in *rest. - * This function never creates new pbufs, but splits an existing chain - * in two parts. The tot_len of the modified packet queue will likely be - * smaller than 64K. - * 'packet queues' are not supported by this function. - * - * @param p the pbuf queue to be split - * @param rest pointer to store the remainder (after the first 64K) - */ -void pbuf_split_64k(struct pbuf *p, struct pbuf **rest) -{ - *rest = NULL; - if ((p != NULL) && (p->next != NULL)) { - u16_t tot_len_front = p->len; - struct pbuf *i = p; - struct pbuf *r = p->next; - - /* continue until the total length (summed up as u16_t) overflows */ - while ((r != NULL) && ((u16_t)(tot_len_front + r->len) > tot_len_front)) { - tot_len_front += r->len; - i = r; - r = r->next; - } - /* i now points to last packet of the first segment. Set next - pointer to NULL */ - i->next = NULL; - - if (r != NULL) { - /* Update the tot_len field in the first part */ - for (i = p; i != NULL; i = i->next) { - i->tot_len -= r->tot_len; - LWIP_ASSERT("tot_len/len mismatch in last pbuf", - (i->next != NULL) || (i->tot_len == i->len)); - } - if (p->flags & PBUF_FLAG_TCP_FIN) { - r->flags |= PBUF_FLAG_TCP_FIN; - } - - /* tot_len field in rest does not need modifications */ - /* reference counters do not need modifications */ - *rest = r; - } - } -} -#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - -/* Actual implementation of pbuf_skip() but returning const pointer... */ -static const struct pbuf* -pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset) -{ - u16_t offset_left = in_offset; - const struct pbuf* q = in; - - /* get the correct pbuf */ - while ((q != NULL) && (q->len <= offset_left)) { - offset_left -= q->len; - q = q->next; - } - if (out_offset != NULL) { - *out_offset = offset_left; - } - return q; -} - -/** - * @ingroup pbuf - * Skip a number of bytes at the start of a pbuf - * - * @param in input pbuf - * @param in_offset offset to skip - * @param out_offset resulting offset in the returned pbuf - * @return the pbuf in the queue where the offset is - */ -struct pbuf* -pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) -{ - const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset); - return LWIP_CONST_CAST(struct pbuf*, out); -} - -/** - * @ingroup pbuf - * Copy application supplied data into a pbuf. - * This function can only be used to copy the equivalent of buf->tot_len data. - * - * @param buf pbuf to fill with data - * @param dataptr application supplied data buffer - * @param len length of the application supplied data buffer - * - * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough - */ -err_t -pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) -{ - struct pbuf *p; - u16_t buf_copy_len; - u16_t total_copy_len = len; - u16_t copied_total = 0; - - LWIP_ERROR("pbuf_take: invalid buf", (buf != NULL), return ERR_ARG;); - LWIP_ERROR("pbuf_take: invalid dataptr", (dataptr != NULL), return ERR_ARG;); - LWIP_ERROR("pbuf_take: buf not large enough", (buf->tot_len >= len), return ERR_MEM;); - - if ((buf == NULL) || (dataptr == NULL) || (buf->tot_len < len)) { - return ERR_ARG; - } - - /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ - for (p = buf; total_copy_len != 0; p = p->next) { - LWIP_ASSERT("pbuf_take: invalid pbuf", p != NULL); - buf_copy_len = total_copy_len; - if (buf_copy_len > p->len) { - /* this pbuf cannot hold all remaining data */ - buf_copy_len = p->len; - } - /* copy the necessary parts of the buffer */ - MEMCPY(p->payload, &((const char*)dataptr)[copied_total], buf_copy_len); - total_copy_len -= buf_copy_len; - copied_total += buf_copy_len; - } - LWIP_ASSERT("did not copy all data", total_copy_len == 0 && copied_total == len); - return ERR_OK; -} - -/** - * @ingroup pbuf - * Same as pbuf_take() but puts data at an offset - * - * @param buf pbuf to fill with data - * @param dataptr application supplied data buffer - * @param len length of the application supplied data buffer - * @param offset offset in pbuf where to copy dataptr to - * - * @return ERR_OK if successful, ERR_MEM if the pbuf is not big enough - */ -err_t -pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) -{ - u16_t target_offset; - struct pbuf* q = pbuf_skip(buf, offset, &target_offset); - - /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->tot_len >= target_offset + len)) { - u16_t remaining_len = len; - const u8_t* src_ptr = (const u8_t*)dataptr; - /* copy the part that goes into the first pbuf */ - u16_t first_copy_len = LWIP_MIN(q->len - target_offset, len); - MEMCPY(((u8_t*)q->payload) + target_offset, dataptr, first_copy_len); - remaining_len -= first_copy_len; - src_ptr += first_copy_len; - if (remaining_len > 0) { - return pbuf_take(q->next, src_ptr, remaining_len); - } - return ERR_OK; - } - return ERR_MEM; -} - -/** - * @ingroup pbuf - * Creates a single pbuf out of a queue of pbufs. - * - * @remark: Either the source pbuf 'p' is freed by this function or the original - * pbuf 'p' is returned, therefore the caller has to check the result! - * - * @param p the source pbuf - * @param layer pbuf_layer of the new pbuf - * - * @return a new, single pbuf (p->next is NULL) - * or the old pbuf if allocation fails - */ -struct pbuf* -pbuf_coalesce(struct pbuf *p, pbuf_layer layer) -{ - struct pbuf *q; - err_t err; - if (p->next == NULL) { - return p; - } - q = pbuf_alloc(layer, p->tot_len, PBUF_RAM); - if (q == NULL) { - /* @todo: what do we do now? */ - return p; - } - err = pbuf_copy(q, p); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("pbuf_copy failed", err == ERR_OK); - pbuf_free(p); - return q; -} - -#if LWIP_CHECKSUM_ON_COPY -/** - * Copies data into a single pbuf (*not* into a pbuf queue!) and updates - * the checksum while copying - * - * @param p the pbuf to copy data into - * @param start_offset offset of p->payload where to copy the data to - * @param dataptr data to copy into the pbuf - * @param len length of data to copy into the pbuf - * @param chksum pointer to the checksum which is updated - * @return ERR_OK if successful, another error if the data does not fit - * within the (first) pbuf (no pbuf queues!) - */ -err_t -pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, - u16_t len, u16_t *chksum) -{ - u32_t acc; - u16_t copy_chksum; - char *dst_ptr; - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("dataptr != NULL", dataptr != NULL); - LWIP_ASSERT("chksum != NULL", chksum != NULL); - LWIP_ASSERT("len != 0", len != 0); - - if ((start_offset >= p->len) || (start_offset + len > p->len)) { - return ERR_ARG; - } - - dst_ptr = ((char*)p->payload) + start_offset; - copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len); - if ((start_offset & 1) != 0) { - copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum); - } - acc = *chksum; - acc += copy_chksum; - *chksum = FOLD_U32T(acc); - return ERR_OK; -} -#endif /* LWIP_CHECKSUM_ON_COPY */ - -/** - * @ingroup pbuf - * Get one byte from the specified position in a pbuf - * WARNING: returns zero for offset >= p->tot_len - * - * @param p pbuf to parse - * @param offset offset into p of the byte to return - * @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len - */ -u8_t -pbuf_get_at(const struct pbuf* p, u16_t offset) -{ - int ret = pbuf_try_get_at(p, offset); - if (ret >= 0) { - return (u8_t)ret; - } - return 0; -} - -/** - * @ingroup pbuf - * Get one byte from the specified position in a pbuf - * - * @param p pbuf to parse - * @param offset offset into p of the byte to return - * @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len - */ -int -pbuf_try_get_at(const struct pbuf* p, u16_t offset) -{ - u16_t q_idx; - const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx); - - /* return requested data if pbuf is OK */ - if ((q != NULL) && (q->len > q_idx)) { - return ((u8_t*)q->payload)[q_idx]; - } - return -1; -} - -/** - * @ingroup pbuf - * Put one byte to the specified position in a pbuf - * WARNING: silently ignores offset >= p->tot_len - * - * @param p pbuf to fill - * @param offset offset into p of the byte to write - * @param data byte to write at an offset into p - */ -void -pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) -{ - u16_t q_idx; - struct pbuf* q = pbuf_skip(p, offset, &q_idx); - - /* write requested data if pbuf is OK */ - if ((q != NULL) && (q->len > q_idx)) { - ((u8_t*)q->payload)[q_idx] = data; - } -} - -/** - * @ingroup pbuf - * Compare pbuf contents at specified offset with memory s2, both of length n - * - * @param p pbuf to compare - * @param offset offset into p at which to start comparing - * @param s2 buffer to compare - * @param n length of buffer to compare - * @return zero if equal, nonzero otherwise - * (0xffff if p is too short, diffoffset+1 otherwise) - */ -u16_t -pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n) -{ - u16_t start = offset; - const struct pbuf* q = p; - u16_t i; - - /* pbuf long enough to perform check? */ - if(p->tot_len < (offset + n)) { - return 0xffff; - } - - /* get the correct pbuf from chain. We know it succeeds because of p->tot_len check above. */ - while ((q != NULL) && (q->len <= start)) { - start -= q->len; - q = q->next; - } - - /* return requested data if pbuf is OK */ - for (i = 0; i < n; i++) { - /* We know pbuf_get_at() succeeds because of p->tot_len check above. */ - u8_t a = pbuf_get_at(q, start + i); - u8_t b = ((const u8_t*)s2)[i]; - if (a != b) { - return i+1; - } - } - return 0; -} - -/** - * @ingroup pbuf - * Find occurrence of mem (with length mem_len) in pbuf p, starting at offset - * start_offset. - * - * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as - * return value 'not found' - * @param mem search for the contents of this buffer - * @param mem_len length of 'mem' - * @param start_offset offset into p at which to start searching - * @return 0xFFFF if substr was not found in p or the index where it was found - */ -u16_t -pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset) -{ - u16_t i; - u16_t max = p->tot_len - mem_len; - if (p->tot_len >= mem_len + start_offset) { - for (i = start_offset; i <= max; i++) { - u16_t plus = pbuf_memcmp(p, i, mem, mem_len); - if (plus == 0) { - return i; - } - } - } - return 0xFFFF; -} - -/** - * Find occurrence of substr with length substr_len in pbuf p, start at offset - * start_offset - * WARNING: in contrast to strstr(), this one does not stop at the first \0 in - * the pbuf/source string! - * - * @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as - * return value 'not found' - * @param substr string to search for in p, maximum length is 0xFFFE - * @return 0xFFFF if substr was not found in p or the index where it was found - */ -u16_t -pbuf_strstr(const struct pbuf* p, const char* substr) -{ - size_t substr_len; - if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { - return 0xFFFF; - } - substr_len = strlen(substr); - if (substr_len >= 0xFFFF) { - return 0xFFFF; - } - return pbuf_memfind(p, substr, (u16_t)substr_len, 0); -} diff --git a/components/net/lwip-2.0.2/src/core/raw.c b/components/net/lwip-2.0.2/src/core/raw.c deleted file mode 100644 index 80cf9ec64b..0000000000 --- a/components/net/lwip-2.0.2/src/core/raw.c +++ /dev/null @@ -1,521 +0,0 @@ -/** - * @file - * Implementation of raw protocol PCBs for low-level handling of - * different types of protocols besides (or overriding) those - * already available in lwIP.\n - * See also @ref raw_raw - * - * @defgroup raw_raw RAW - * @ingroup callbackstyle_api - * Implementation of raw protocol PCBs for low-level handling of - * different types of protocols besides (or overriding) those - * already available in lwIP.\n - * @see @ref raw_api - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/raw.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/inet_chksum.h" - -#include - -/** The list of RAW PCBs */ -static struct raw_pcb *raw_pcbs; - -static u8_t -raw_input_match(struct raw_pcb *pcb, u8_t broadcast) -{ - LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ - -#if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -#if IP_SOF_BROADCAST_RECV - if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { - return 0; - } -#endif /* IP_SOF_BROADCAST_RECV */ - return 1; - } -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - - /* Only need to check PCB if incoming IP version matches PCB IP version */ - if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { -#if LWIP_IPV4 - /* Special case: IPv4 broadcast: receive all broadcasts - * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ - if (broadcast != 0) { -#if IP_SOF_BROADCAST_RECV - if (ip_get_option(pcb, SOF_BROADCAST)) -#endif /* IP_SOF_BROADCAST_RECV */ - { - if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip))) { - return 1; - } - } - } else -#endif /* LWIP_IPV4 */ - /* Handle IPv4 and IPv6: catch all or exact match */ - if (ip_addr_isany(&pcb->local_ip) || - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - return 1; - } - } - - return 0; -} - -/** - * Determine if in incoming IP packet is covered by a RAW PCB - * and if so, pass it to a user-provided receive callback function. - * - * Given an incoming IP datagram (as a chain of pbufs) this function - * finds a corresponding RAW PCB and calls the corresponding receive - * callback function. - * - * @param p pbuf to be demultiplexed to a RAW PCB. - * @param inp network interface on which the datagram was received. - * @return - 1 if the packet has been eaten by a RAW PCB receive - * callback function. The caller MAY NOT not reference the - * packet any longer, and MAY NOT call pbuf_free(). - * @return - 0 if packet is not eaten (pbuf is still referenced by the - * caller). - * - */ -u8_t -raw_input(struct pbuf *p, struct netif *inp) -{ - struct raw_pcb *pcb, *prev; - s16_t proto; - u8_t eaten = 0; - u8_t broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); - - LWIP_UNUSED_ARG(inp); - -#if LWIP_IPV6 -#if LWIP_IPV4 - if (IP_HDR_GET_VERSION(p->payload) == 6) -#endif /* LWIP_IPV4 */ - { - struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload; - proto = IP6H_NEXTH(ip6hdr); - } -#if LWIP_IPV4 - else -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - { - proto = IPH_PROTO((struct ip_hdr *)p->payload); - } -#endif /* LWIP_IPV4 */ - - prev = NULL; - pcb = raw_pcbs; - /* loop through all raw pcbs until the packet is eaten by one */ - /* this allows multiple pcbs to match against the packet by design */ - while ((eaten == 0) && (pcb != NULL)) { - if ((pcb->protocol == proto) && raw_input_match(pcb, broadcast)) { - /* receive callback function available? */ - if (pcb->recv != NULL) { -#ifndef LWIP_NOASSERT - void* old_payload = p->payload; -#endif - /* the receive callback function did not eat the packet? */ - eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()); - if (eaten != 0) { - /* receive function ate the packet */ - p = NULL; - eaten = 1; - if (prev != NULL) { - /* move the pcb to the front of raw_pcbs so that is - found faster next time */ - prev->next = pcb->next; - pcb->next = raw_pcbs; - raw_pcbs = pcb; - } - } else { - /* sanity-check that the receive callback did not alter the pbuf */ - LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet", - p->payload == old_payload); - } - } - /* no receive callback function was set for this raw PCB */ - } - /* drop the packet */ - prev = pcb; - pcb = pcb->next; - } - return eaten; -} - -/** - * @ingroup raw_raw - * Bind a RAW PCB. - * - * @param pcb RAW PCB to be bound with a local address ipaddr. - * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to - * bind to all local interfaces. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occurred. - * - ERR_USE. The specified IP address is already bound to by - * another RAW PCB. - * - * @see raw_disconnect() - */ -err_t -raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) -{ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); - return ERR_OK; -} - -/** - * @ingroup raw_raw - * Connect an RAW PCB. This function is required by upper layers - * of lwip. Using the raw api you could use raw_sendto() instead - * - * This will associate the RAW PCB with the remote address. - * - * @param pcb RAW PCB to be connected with remote address ipaddr and port. - * @param ipaddr remote IP address to connect with. - * - * @return lwIP error code - * - * @see raw_disconnect() and raw_sendto() - */ -err_t -raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) -{ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); - return ERR_OK; -} - -/** - * @ingroup raw_raw - * Set the callback function for received packets that match the - * raw PCB's protocol and binding. - * - * The callback function MUST either - * - eat the packet by calling pbuf_free() and returning non-zero. The - * packet will not be passed to other raw PCBs or other protocol layers. - * - not free the packet, and return zero. The packet will be matched - * against further PCBs and/or forwarded to another protocol layers. - */ -void -raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) -{ - /* remember recv() callback and user data */ - pcb->recv = recv; - pcb->recv_arg = recv_arg; -} - -/** - * @ingroup raw_raw - * Send the raw IP packet to the given address. Note that actually you cannot - * modify the IP headers (this is inconsistent with the receive callback where - * you actually get the IP headers), you can only specify the IP payload here. - * It requires some more changes in lwIP. (there will be a raw_send() function - * then.) - * - * @param pcb the raw pcb which to send - * @param p the IP payload to send - * @param ipaddr the destination address of the IP packet - * - */ -err_t -raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) -{ - err_t err; - struct netif *netif; - const ip_addr_t *src_ip; - struct pbuf *q; /* q will be sent down the stack */ - s16_t header_size; - - if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) { - return ERR_VAL; - } - - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n")); - - header_size = ( -#if LWIP_IPV4 && LWIP_IPV6 - IP_IS_V6(ipaddr) ? IP6_HLEN : IP_HLEN); -#elif LWIP_IPV4 - IP_HLEN); -#else - IP6_HLEN); -#endif - - /* not enough space to add an IP header to first pbuf in given p chain? */ - if (pbuf_header(p, header_size)) { - /* allocate header in new pbuf */ - q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM); - /* new header pbuf could not be allocated? */ - if (q == NULL) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); - return ERR_MEM; - } - if (p->tot_len != 0) { - /* chain header q in front of given pbuf p */ - pbuf_chain(q, p); - } - /* { first pbuf q points to header pbuf } */ - LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); - } else { - /* first pbuf q equals given pbuf */ - q = p; - if (pbuf_header(q, -header_size)) { - LWIP_ASSERT("Can't restore header we just removed!", 0); - return ERR_MEM; - } - } - - if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - /* Don't call ip_route() with IP_ANY_TYPE */ - netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr); - } else { - netif = ip_route(&pcb->local_ip, ipaddr); - } - - if (netif == NULL) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to ")); - ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr); - /* free any temporary header pbuf allocated by pbuf_header() */ - if (q != p) { - pbuf_free(q); - } - return ERR_RTE; - } - -#if IP_SOF_BROADCAST - if (IP_IS_V4(ipaddr)) - { - /* broadcast filter? */ - if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); - /* free any temporary header pbuf allocated by pbuf_header() */ - if (q != p) { - pbuf_free(q); - } - return ERR_VAL; - } - } -#endif /* IP_SOF_BROADCAST */ - - if (ip_addr_isany(&pcb->local_ip)) { - /* use outgoing network interface IP address as source address */ - src_ip = ip_netif_get_local_ip(netif, ipaddr); -#if LWIP_IPV6 - if (src_ip == NULL) { - if (q != p) { - pbuf_free(q); - } - return ERR_RTE; - } -#endif /* LWIP_IPV6 */ - } else { - /* use RAW PCB local IP address as source address */ - src_ip = &pcb->local_ip; - } - -#if LWIP_IPV6 - /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542, - compute the checksum and update the checksum in the payload. */ - if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) { - u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr)); - LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2)); - SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t)); - } -#endif - - NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); - err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - /* did we chain a header earlier? */ - if (q != p) { - /* free the header */ - pbuf_free(q); - } - return err; -} - -/** - * @ingroup raw_raw - * Send the raw IP packet to the address given by raw_connect() - * - * @param pcb the raw pcb which to send - * @param p the IP payload to send - * - */ -err_t -raw_send(struct raw_pcb *pcb, struct pbuf *p) -{ - return raw_sendto(pcb, p, &pcb->remote_ip); -} - -/** - * @ingroup raw_raw - * Remove an RAW PCB. - * - * @param pcb RAW PCB to be removed. The PCB is removed from the list of - * RAW PCB's and the data structure is freed from memory. - * - * @see raw_new() - */ -void -raw_remove(struct raw_pcb *pcb) -{ - struct raw_pcb *pcb2; - /* pcb to be removed is first in list? */ - if (raw_pcbs == pcb) { - /* make list start at 2nd pcb */ - raw_pcbs = raw_pcbs->next; - /* pcb not 1st in list */ - } else { - for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { - /* find pcb in raw_pcbs list */ - if (pcb2->next != NULL && pcb2->next == pcb) { - /* remove pcb from list */ - pcb2->next = pcb->next; - break; - } - } - } - memp_free(MEMP_RAW_PCB, pcb); -} - -/** - * @ingroup raw_raw - * Create a RAW PCB. - * - * @return The RAW PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) - * - * @see raw_remove() - */ -struct raw_pcb * -raw_new(u8_t proto) -{ - struct raw_pcb *pcb; - - LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n")); - - pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); - /* could allocate RAW PCB? */ - if (pcb != NULL) { - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); - pcb->protocol = proto; - pcb->ttl = RAW_TTL; - pcb->next = raw_pcbs; - raw_pcbs = pcb; - } - return pcb; -} - -/** - * @ingroup raw_raw - * Create a RAW PCB for specific IP type. - * - * @return The RAW PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @param type IP address type, see @ref lwip_ip_addr_type definitions. - * If you want to listen to IPv4 and IPv6 (dual-stack) packets, - * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. - * @param proto the protocol number (next header) of the IPv6 packet payload - * (e.g. IP6_NEXTH_ICMP6) - * - * @see raw_remove() - */ -struct raw_pcb * -raw_new_ip_type(u8_t type, u8_t proto) -{ - struct raw_pcb *pcb; - pcb = raw_new(proto); -#if LWIP_IPV4 && LWIP_IPV6 - if (pcb != NULL) { - IP_SET_TYPE_VAL(pcb->local_ip, type); - IP_SET_TYPE_VAL(pcb->remote_ip, type); - } -#else /* LWIP_IPV4 && LWIP_IPV6 */ - LWIP_UNUSED_ARG(type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - return pcb; -} - -/** This function is called from netif.c when address is changed - * - * @param old_addr IP address of the netif before change - * @param new_addr IP address of the netif after change - */ -void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) -{ - struct raw_pcb* rpcb; - - if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { - for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&rpcb->local_ip, old_addr)) { - /* The PCB is bound to the old ipaddr and - * is set to bound to the new one instead */ - ip_addr_copy(rpcb->local_ip, *new_addr); - } - } - } -} - -#endif /* LWIP_RAW */ diff --git a/components/net/lwip-2.0.2/src/core/stats.c b/components/net/lwip-2.0.2/src/core/stats.c deleted file mode 100644 index 893d199c04..0000000000 --- a/components/net/lwip-2.0.2/src/core/stats.c +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file - * Statistics module - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_STATS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/debug.h" - -#include - -struct stats_ lwip_stats; - -void -stats_init(void) -{ -#ifdef LWIP_DEBUG -#if MEM_STATS - lwip_stats.mem.name = "MEM"; -#endif /* MEM_STATS */ -#endif /* LWIP_DEBUG */ -} - -#if LWIP_STATS_DISPLAY -void -stats_display_proto(struct stats_proto *proto, const char *name) -{ - LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit)); - LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", proto->recv)); - LWIP_PLATFORM_DIAG(("fw: %"STAT_COUNTER_F"\n\t", proto->fw)); - LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", proto->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", proto->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", proto->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", proto->memerr)); - LWIP_PLATFORM_DIAG(("rterr: %"STAT_COUNTER_F"\n\t", proto->rterr)); - LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", proto->proterr)); - LWIP_PLATFORM_DIAG(("opterr: %"STAT_COUNTER_F"\n\t", proto->opterr)); - LWIP_PLATFORM_DIAG(("err: %"STAT_COUNTER_F"\n\t", proto->err)); - LWIP_PLATFORM_DIAG(("cachehit: %"STAT_COUNTER_F"\n", proto->cachehit)); -} - -#if IGMP_STATS || MLD6_STATS -void -stats_display_igmp(struct stats_igmp *igmp, const char *name) -{ - LWIP_PLATFORM_DIAG(("\n%s\n\t", name)); - LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit)); - LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv)); - LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop)); - LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr)); - LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr)); - LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr)); - LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr)); - LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1)); - LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n\t", igmp->rx_group)); - LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n\t", igmp->rx_general)); - LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report)); - LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join)); - LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave)); - LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report)); -} -#endif /* IGMP_STATS || MLD6_STATS */ - -#if MEM_STATS || MEMP_STATS -void -stats_display_mem(struct stats_mem *mem, const char *name) -{ - LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name)); - LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail)); - LWIP_PLATFORM_DIAG(("used: %"U32_F"\n\t", (u32_t)mem->used)); - LWIP_PLATFORM_DIAG(("max: %"U32_F"\n\t", (u32_t)mem->max)); - LWIP_PLATFORM_DIAG(("err: %"U32_F"\n", (u32_t)mem->err)); -} - -#if MEMP_STATS -void -stats_display_memp(struct stats_mem *mem, int index) -{ - if (index < MEMP_MAX) { - stats_display_mem(mem, mem->name); - } -} -#endif /* MEMP_STATS */ -#endif /* MEM_STATS || MEMP_STATS */ - -#if SYS_STATS -void -stats_display_sys(struct stats_sys *sys) -{ - LWIP_PLATFORM_DIAG(("\nSYS\n\t")); - LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used)); - LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max)); - LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err)); - LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used)); - LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max)); - LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err)); - LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used)); - LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max)); - LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err)); -} -#endif /* SYS_STATS */ - -void -stats_display(void) -{ - s16_t i; - - LINK_STATS_DISPLAY(); - ETHARP_STATS_DISPLAY(); - IPFRAG_STATS_DISPLAY(); - IP6_FRAG_STATS_DISPLAY(); - IP_STATS_DISPLAY(); - ND6_STATS_DISPLAY(); - IP6_STATS_DISPLAY(); - IGMP_STATS_DISPLAY(); - MLD6_STATS_DISPLAY(); - ICMP_STATS_DISPLAY(); - ICMP6_STATS_DISPLAY(); - UDP_STATS_DISPLAY(); - TCP_STATS_DISPLAY(); - MEM_STATS_DISPLAY(); - for (i = 0; i < MEMP_MAX; i++) { - MEMP_STATS_DISPLAY(i); - } - SYS_STATS_DISPLAY(); -} -#endif /* LWIP_STATS_DISPLAY */ - -#endif /* LWIP_STATS */ - diff --git a/components/net/lwip-2.0.2/src/core/sys.c b/components/net/lwip-2.0.2/src/core/sys.c deleted file mode 100644 index 7059b4de5b..0000000000 --- a/components/net/lwip-2.0.2/src/core/sys.c +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file - * lwIP Operating System abstraction - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/** - * @defgroup sys_layer Porting (system abstraction layer) - * @ingroup lwip - * @verbinclude "sys_arch.txt" - * - * @defgroup sys_os OS abstraction layer - * @ingroup sys_layer - * No need to implement functions in this section in NO_SYS mode. - * - * @defgroup sys_sem Semaphores - * @ingroup sys_os - * - * @defgroup sys_mutex Mutexes - * @ingroup sys_os - * Mutexes are recommended to correctly handle priority inversion, - * especially if you use LWIP_CORE_LOCKING . - * - * @defgroup sys_mbox Mailboxes - * @ingroup sys_os - * - * @defgroup sys_time Time - * @ingroup sys_layer - * - * @defgroup sys_prot Critical sections - * @ingroup sys_layer - * Used to protect short regions of code against concurrent access. - * - Your system is a bare-metal system (probably with an RTOS) - * and interrupts are under your control: - * Implement this as LockInterrupts() / UnlockInterrupts() - * - Your system uses an RTOS with deferred interrupt handling from a - * worker thread: Implement as a global mutex or lock/unlock scheduler - * - Your system uses a high-level OS with e.g. POSIX signals: - * Implement as a global mutex - * - * @defgroup sys_misc Misc - * @ingroup sys_os - */ - -#include "lwip/opt.h" - -#include "lwip/sys.h" - -/* Most of the functions defined in sys.h must be implemented in the - * architecture-dependent file sys_arch.c */ - -#if !NO_SYS - -#ifndef sys_msleep -/** - * Sleep for some ms. Timeouts are NOT processed while sleeping. - * - * @param ms number of milliseconds to sleep - */ -void -sys_msleep(u32_t ms) -{ - if (ms > 0) { - sys_sem_t delaysem; - err_t err = sys_sem_new(&delaysem, 0); - if (err == ERR_OK) { - sys_arch_sem_wait(&delaysem, ms); - sys_sem_free(&delaysem); - } - } -} -#endif /* sys_msleep */ - -#endif /* !NO_SYS */ diff --git a/components/net/lwip-2.0.2/src/core/tcp.c b/components/net/lwip-2.0.2/src/core/tcp.c deleted file mode 100644 index ec2e1f92ce..0000000000 --- a/components/net/lwip-2.0.2/src/core/tcp.c +++ /dev/null @@ -1,2164 +0,0 @@ -/** - * @file - * Transmission Control Protocol for IP - * See also @ref tcp_raw - * - * @defgroup tcp_raw TCP - * @ingroup callbackstyle_api - * Transmission Control Protocol for IP\n - * @see @ref raw_api and @ref netconn - * - * Common functions for the TCP implementation, such as functinos - * for manipulating the data structures and the TCP timer functions. TCP functions - * related to input and output is found in tcp_in.c and tcp_out.c respectively.\n - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/nd6.h" - -#include - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -#ifndef TCP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define TCP_LOCAL_PORT_RANGE_START 0xc000 -#define TCP_LOCAL_PORT_RANGE_END 0xffff -#define TCP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~TCP_LOCAL_PORT_RANGE_START) + TCP_LOCAL_PORT_RANGE_START)) -#endif - -#if LWIP_TCP_KEEPALIVE -#define TCP_KEEP_DUR(pcb) ((pcb)->keep_cnt * (pcb)->keep_intvl) -#define TCP_KEEP_INTVL(pcb) ((pcb)->keep_intvl) -#else /* LWIP_TCP_KEEPALIVE */ -#define TCP_KEEP_DUR(pcb) TCP_MAXIDLE -#define TCP_KEEP_INTVL(pcb) TCP_KEEPINTVL_DEFAULT -#endif /* LWIP_TCP_KEEPALIVE */ - -/* As initial send MSS, we use TCP_MSS but limit it to 536. */ -#if TCP_MSS > 536 -#define INITIAL_MSS 536 -#else -#define INITIAL_MSS TCP_MSS -#endif - -static const char * const tcp_state_str[] = { - "CLOSED", - "LISTEN", - "SYN_SENT", - "SYN_RCVD", - "ESTABLISHED", - "FIN_WAIT_1", - "FIN_WAIT_2", - "CLOSE_WAIT", - "CLOSING", - "LAST_ACK", - "TIME_WAIT" -}; - -/* last local TCP port */ -static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START; - -/* Incremented every coarse grained timer shot (typically every 500 ms). */ -u32_t tcp_ticks; -static const u8_t tcp_backoff[13] = - { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; - /* Times per slowtmr hits */ -static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; - -/* The TCP PCB lists. */ - -/** List of all TCP PCBs bound but not yet (connected || listening) */ -struct tcp_pcb *tcp_bound_pcbs; -/** List of all TCP PCBs in LISTEN state */ -union tcp_listen_pcbs_t tcp_listen_pcbs; -/** List of all TCP PCBs that are in a state in which - * they accept or send data. */ -struct tcp_pcb *tcp_active_pcbs; -/** List of all TCP PCBs in TIME-WAIT state */ -struct tcp_pcb *tcp_tw_pcbs; - -/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ -struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, - &tcp_active_pcbs, &tcp_tw_pcbs}; - -u8_t tcp_active_pcbs_changed; - -/** Timer counter to handle calling slow-timer from tcp_tmr() */ -static u8_t tcp_timer; -static u8_t tcp_timer_ctr; -static u16_t tcp_new_port(void); - -static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb); - -/** - * Initialize this module. - */ -void -tcp_init(void) -{ -#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) - tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); -#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ -} - -/** - * Called periodically to dispatch TCP timers. - */ -void -tcp_tmr(void) -{ - /* Call tcp_fasttmr() every 250 ms */ - tcp_fasttmr(); - - if (++tcp_timer & 1) { - /* Call tcp_slowtmr() every 500 ms, i.e., every other timer - tcp_tmr() is called. */ - tcp_slowtmr(); - } -} - -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG -/** Called when a listen pcb is closed. Iterates one pcb list and removes the - * closed listener pcb from pcb->listener if matching. - */ -static void -tcp_remove_listener(struct tcp_pcb *list, struct tcp_pcb_listen *lpcb) -{ - struct tcp_pcb *pcb; - for (pcb = list; pcb != NULL; pcb = pcb->next) { - if (pcb->listener == lpcb) { - pcb->listener = NULL; - } - } -} -#endif - -/** Called when a listen pcb is closed. Iterates all pcb lists and removes the - * closed listener pcb from pcb->listener if matching. - */ -static void -tcp_listen_closed(struct tcp_pcb *pcb) -{ -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG - size_t i; - LWIP_ASSERT("pcb != NULL", pcb != NULL); - LWIP_ASSERT("pcb->state == LISTEN", pcb->state == LISTEN); - for (i = 1; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - tcp_remove_listener(*tcp_pcb_lists[i], (struct tcp_pcb_listen*)pcb); - } -#endif - LWIP_UNUSED_ARG(pcb); -} - -#if TCP_LISTEN_BACKLOG -/** @ingroup tcp_raw - * Delay accepting a connection in respect to the listen backlog: - * the number of outstanding connections is increased until - * tcp_backlog_accepted() is called. - * - * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() - * or else the backlog feature will get out of sync! - * - * @param pcb the connection pcb which is not fully accepted yet - */ -void -tcp_backlog_delayed(struct tcp_pcb* pcb) -{ - LWIP_ASSERT("pcb != NULL", pcb != NULL); - if ((pcb->flags & TF_BACKLOGPEND) == 0) { - if (pcb->listener != NULL) { - pcb->listener->accepts_pending++; - LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); - pcb->flags |= TF_BACKLOGPEND; - } - } -} - -/** @ingroup tcp_raw - * A delayed-accept a connection is accepted (or closed/aborted): decreases - * the number of outstanding connections after calling tcp_backlog_delayed(). - * - * ATTENTION: the caller is responsible for calling tcp_backlog_accepted() - * or else the backlog feature will get out of sync! - * - * @param pcb the connection pcb which is now fully accepted (or closed/aborted) - */ -void -tcp_backlog_accepted(struct tcp_pcb* pcb) -{ - LWIP_ASSERT("pcb != NULL", pcb != NULL); - if ((pcb->flags & TF_BACKLOGPEND) != 0) { - if (pcb->listener != NULL) { - LWIP_ASSERT("accepts_pending != 0", pcb->listener->accepts_pending != 0); - pcb->listener->accepts_pending--; - pcb->flags &= ~TF_BACKLOGPEND; - } - } -} -#endif /* TCP_LISTEN_BACKLOG */ - -/** - * Closes the TX side of a connection held by the PCB. - * For tcp_close(), a RST is sent if the application didn't receive all data - * (tcp_recved() not called for all data passed to recv callback). - * - * Listening pcbs are freed and may not be referenced any more. - * Connection pcbs are freed if not yet connected and may not be referenced - * any more. If a connection is established (at least SYN received or in - * a closing state), the connection is closed, and put in a closing state. - * The pcb is then automatically freed in tcp_slowtmr(). It is therefore - * unsafe to reference it. - * - * @param pcb the tcp_pcb to close - * @return ERR_OK if connection has been closed - * another err_t if closing failed and pcb is not freed - */ -static err_t -tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) -{ - if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) { - if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) { - /* Not all data received by application, send RST to tell the remote - side about this. */ - LWIP_ASSERT("pcb->flags & TF_RXCLOSED", pcb->flags & TF_RXCLOSED); - - /* don't call tcp_abort here: we must not deallocate the pcb since - that might not be expected when calling tcp_close */ - tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, - pcb->local_port, pcb->remote_port); - - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - if (pcb->state == ESTABLISHED) { - /* move to TIME_WAIT since we close actively */ - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } else { - /* CLOSE_WAIT: deallocate the pcb since we already sent a RST for it */ - if (tcp_input_pcb == pcb) { - /* prevent using a deallocated pcb: free it from tcp_input later */ - tcp_trigger_input_pcb_close(); - } else { - memp_free(MEMP_TCP_PCB, pcb); - } - } - return ERR_OK; - } - } - - /* - states which free the pcb are handled here, - - states which send FIN and change state are handled in tcp_close_shutdown_fin() */ - switch (pcb->state) { - case CLOSED: - /* Closing a pcb in the CLOSED state might seem erroneous, - * however, it is in this state once allocated and as yet unused - * and the user needs some way to free it should the need arise. - * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) - * or for a pcb that has been used and then entered the CLOSED state - * is erroneous, but this should never happen as the pcb has in those cases - * been freed, and so any remaining handles are bogus. */ - if (pcb->local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - memp_free(MEMP_TCP_PCB, pcb); - break; - case LISTEN: - tcp_listen_closed(pcb); - tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); - memp_free(MEMP_TCP_PCB_LISTEN, pcb); - break; - case SYN_SENT: - TCP_PCB_REMOVE_ACTIVE(pcb); - memp_free(MEMP_TCP_PCB, pcb); - MIB2_STATS_INC(mib2.tcpattemptfails); - break; - default: - return tcp_close_shutdown_fin(pcb); - } - return ERR_OK; -} - -static err_t -tcp_close_shutdown_fin(struct tcp_pcb *pcb) -{ - err_t err; - LWIP_ASSERT("pcb != NULL", pcb != NULL); - - switch (pcb->state) { - case SYN_RCVD: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - tcp_backlog_accepted(pcb); - MIB2_STATS_INC(mib2.tcpattemptfails); - pcb->state = FIN_WAIT_1; - } - break; - case ESTABLISHED: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - MIB2_STATS_INC(mib2.tcpestabresets); - pcb->state = FIN_WAIT_1; - } - break; - case CLOSE_WAIT: - err = tcp_send_fin(pcb); - if (err == ERR_OK) { - MIB2_STATS_INC(mib2.tcpestabresets); - pcb->state = LAST_ACK; - } - break; - default: - /* Has already been closed, do nothing. */ - return ERR_OK; - break; - } - - if (err == ERR_OK) { - /* To ensure all data has been sent when tcp_close returns, we have - to make sure tcp_output doesn't fail. - Since we don't really have to ensure all data has been sent when tcp_close - returns (unsent data is sent from tcp timer functions, also), we don't care - for the return value of tcp_output for now. */ - tcp_output(pcb); - } else if (err == ERR_MEM) { - /* Mark this pcb for closing. Closing is retried from tcp_tmr. */ - pcb->flags |= TF_CLOSEPEND; - } - return err; -} - -/** - * @ingroup tcp_raw - * Closes the connection held by the PCB. - * - * Listening pcbs are freed and may not be referenced any more. - * Connection pcbs are freed if not yet connected and may not be referenced - * any more. If a connection is established (at least SYN received or in - * a closing state), the connection is closed, and put in a closing state. - * The pcb is then automatically freed in tcp_slowtmr(). It is therefore - * unsafe to reference it (unless an error is returned). - * - * @param pcb the tcp_pcb to close - * @return ERR_OK if connection has been closed - * another err_t if closing failed and pcb is not freed - */ -err_t -tcp_close(struct tcp_pcb *pcb) -{ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); - tcp_debug_print_state(pcb->state); - - if (pcb->state != LISTEN) { - /* Set a flag not to receive any more data... */ - pcb->flags |= TF_RXCLOSED; - } - /* ... and close */ - return tcp_close_shutdown(pcb, 1); -} - -/** - * @ingroup tcp_raw - * Causes all or part of a full-duplex connection of this PCB to be shut down. - * This doesn't deallocate the PCB unless shutting down both sides! - * Shutting down both sides is the same as calling tcp_close, so if it succeds, - * the PCB should not be referenced any more. - * - * @param pcb PCB to shutdown - * @param shut_rx shut down receive side if this is != 0 - * @param shut_tx shut down send side if this is != 0 - * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) - * another err_t on error. - */ -err_t -tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) -{ - if (pcb->state == LISTEN) { - return ERR_CONN; - } - if (shut_rx) { - /* shut down the receive side: set a flag not to receive any more data... */ - pcb->flags |= TF_RXCLOSED; - if (shut_tx) { - /* shutting down the tx AND rx side is the same as closing for the raw API */ - return tcp_close_shutdown(pcb, 1); - } - /* ... and free buffered data */ - if (pcb->refused_data != NULL) { - pbuf_free(pcb->refused_data); - pcb->refused_data = NULL; - } - } - if (shut_tx) { - /* This can't happen twice since if it succeeds, the pcb's state is changed. - Only close in these states as the others directly deallocate the PCB */ - switch (pcb->state) { - case SYN_RCVD: - case ESTABLISHED: - case CLOSE_WAIT: - return tcp_close_shutdown(pcb, (u8_t)shut_rx); - default: - /* Not (yet?) connected, cannot shutdown the TX side as that would bring us - into CLOSED state, where the PCB is deallocated. */ - return ERR_CONN; - } - } - return ERR_OK; -} - -/** - * Abandons a connection and optionally sends a RST to the remote - * host. Deletes the local protocol control block. This is done when - * a connection is killed because of shortage of memory. - * - * @param pcb the tcp_pcb to abort - * @param reset boolean to indicate whether a reset should be sent - */ -void -tcp_abandon(struct tcp_pcb *pcb, int reset) -{ - u32_t seqno, ackno; -#if LWIP_CALLBACK_API - tcp_err_fn errf; -#endif /* LWIP_CALLBACK_API */ - void *errf_arg; - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_abort/tcp_abandon for listen-pcbs", - pcb->state != LISTEN); - /* Figure out on which TCP PCB list we are, and remove us. If we - are in an active state, call the receive function associated with - the PCB with a NULL argument, and send an RST to the remote end. */ - if (pcb->state == TIME_WAIT) { - tcp_pcb_remove(&tcp_tw_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else { - int send_rst = 0; - u16_t local_port = 0; - enum tcp_state last_state; - seqno = pcb->snd_nxt; - ackno = pcb->rcv_nxt; -#if LWIP_CALLBACK_API - errf = pcb->errf; -#endif /* LWIP_CALLBACK_API */ - errf_arg = pcb->callback_arg; - if (pcb->state == CLOSED) { - if (pcb->local_port != 0) { - /* bound, not yet opened */ - TCP_RMV(&tcp_bound_pcbs, pcb); - } - } else { - send_rst = reset; - local_port = pcb->local_port; - TCP_PCB_REMOVE_ACTIVE(pcb); - } - if (pcb->unacked != NULL) { - tcp_segs_free(pcb->unacked); - } - if (pcb->unsent != NULL) { - tcp_segs_free(pcb->unsent); - } -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL) { - tcp_segs_free(pcb->ooseq); - } -#endif /* TCP_QUEUE_OOSEQ */ - tcp_backlog_accepted(pcb); - if (send_rst) { - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); - tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port); - } - last_state = pcb->state; - memp_free(MEMP_TCP_PCB, pcb); - TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT); - } -} - -/** - * @ingroup tcp_raw - * Aborts the connection by sending a RST (reset) segment to the remote - * host. The pcb is deallocated. This function never fails. - * - * ATTENTION: When calling this from one of the TCP callbacks, make - * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise - * or you will risk accessing deallocated memory or memory leaks! - * - * @param pcb the tcp pcb to abort - */ -void -tcp_abort(struct tcp_pcb *pcb) -{ - tcp_abandon(pcb, 1); -} - -/** - * @ingroup tcp_raw - * Binds the connection to a local port number and IP address. If the - * IP address is not given (i.e., ipaddr == NULL), the IP address of - * the outgoing network interface is used instead. - * - * @param pcb the tcp_pcb to bind (no check is done whether this pcb is - * already bound!) - * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind - * to any local address - * @param port the local port to bind to - * @return ERR_USE if the port is already in use - * ERR_VAL if bind failed because the PCB is not in a valid state - * ERR_OK if bound - */ -err_t -tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) -{ - int i; - int max_pcb_list = NUM_TCP_PCB_LISTS; - struct tcp_pcb *cpcb; - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - /* still need to check for ipaddr == NULL in IPv6 only case */ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); - -#if SO_REUSE - /* Unless the REUSEADDR flag is set, - we have to check the pcbs in TIME-WAIT state, also. - We do not dump TIME_WAIT pcb's; they can still be matched by incoming - packets using both local and remote IP addresses and ports to distinguish. - */ - if (ip_get_option(pcb, SOF_REUSEADDR)) { - max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; - } -#endif /* SO_REUSE */ - - if (port == 0) { - port = tcp_new_port(); - if (port == 0) { - return ERR_BUF; - } - } else { - /* Check if the address already is in use (on all lists) */ - for (i = 0; i < max_pcb_list; i++) { - for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { - if (cpcb->local_port == port) { -#if SO_REUSE - /* Omit checking for the same port if both pcbs have REUSEADDR set. - For SO_REUSEADDR, the duplicate-check for a 5-tuple is done in - tcp_connect. */ - if (!ip_get_option(pcb, SOF_REUSEADDR) || - !ip_get_option(cpcb, SOF_REUSEADDR)) -#endif /* SO_REUSE */ - { - /* @todo: check accept_any_ip_version */ - if ((IP_IS_V6(ipaddr) == IP_IS_V6_VAL(cpcb->local_ip)) && - (ip_addr_isany(&cpcb->local_ip) || - ip_addr_isany(ipaddr) || - ip_addr_cmp(&cpcb->local_ip, ipaddr))) { - return ERR_USE; - } - } - } - } - } - } - - if (!ip_addr_isany(ipaddr)) { - ip_addr_set(&pcb->local_ip, ipaddr); - } - pcb->local_port = port; - TCP_REG(&tcp_bound_pcbs, pcb); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: bind to port %"U16_F"\n", port)); - return ERR_OK; -} -#if LWIP_CALLBACK_API -/** - * Default accept callback if no accept callback is specified by the user. - */ -static err_t -tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err) -{ - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(err); - - tcp_abort(pcb); - - return ERR_ABRT; -} -#endif /* LWIP_CALLBACK_API */ - -/** - * @ingroup tcp_raw - * Set the state of the connection to be LISTEN, which means that it - * is able to accept incoming connections. The protocol control block - * is reallocated in order to consume less memory. Setting the - * connection to LISTEN is an irreversible process. - * - * @param pcb the original tcp_pcb - * @param backlog the incoming connections queue limit - * @return tcp_pcb used for listening, consumes less memory. - * - * @note The original tcp_pcb is freed. This function therefore has to be - * called like this: - * tpcb = tcp_listen_with_backlog(tpcb, backlog); - */ -struct tcp_pcb * -tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) -{ - return tcp_listen_with_backlog_and_err(pcb, backlog, NULL); -} - -/** - * @ingroup tcp_raw - * Set the state of the connection to be LISTEN, which means that it - * is able to accept incoming connections. The protocol control block - * is reallocated in order to consume less memory. Setting the - * connection to LISTEN is an irreversible process. - * - * @param pcb the original tcp_pcb - * @param backlog the incoming connections queue limit - * @param err when NULL is returned, this contains the error reason - * @return tcp_pcb used for listening, consumes less memory. - * - * @note The original tcp_pcb is freed. This function therefore has to be - * called like this: - * tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err); - */ -struct tcp_pcb * -tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) -{ - struct tcp_pcb_listen *lpcb = NULL; - err_t res; - - LWIP_UNUSED_ARG(backlog); - LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done); - - /* already listening? */ - if (pcb->state == LISTEN) { - lpcb = (struct tcp_pcb_listen*)pcb; - res = ERR_ALREADY; - goto done; - } -#if SO_REUSE - if (ip_get_option(pcb, SOF_REUSEADDR)) { - /* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage - is declared (listen-/connection-pcb), we have to make sure now that - this port is only used once for every local IP. */ - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if ((lpcb->local_port == pcb->local_port) && - ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) { - /* this address/port is already used */ - lpcb = NULL; - res = ERR_USE; - goto done; - } - } - } -#endif /* SO_REUSE */ - lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN); - if (lpcb == NULL) { - res = ERR_MEM; - goto done; - } - lpcb->callback_arg = pcb->callback_arg; - lpcb->local_port = pcb->local_port; - lpcb->state = LISTEN; - lpcb->prio = pcb->prio; - lpcb->so_options = pcb->so_options; - lpcb->ttl = pcb->ttl; - lpcb->tos = pcb->tos; -#if LWIP_IPV4 && LWIP_IPV6 - IP_SET_TYPE_VAL(lpcb->remote_ip, pcb->local_ip.type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - ip_addr_copy(lpcb->local_ip, pcb->local_ip); - if (pcb->local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - memp_free(MEMP_TCP_PCB, pcb); -#if LWIP_CALLBACK_API - lpcb->accept = tcp_accept_null; -#endif /* LWIP_CALLBACK_API */ -#if TCP_LISTEN_BACKLOG - lpcb->accepts_pending = 0; - tcp_backlog_set(lpcb, backlog); -#endif /* TCP_LISTEN_BACKLOG */ - TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb); - res = ERR_OK; -done: - if (err != NULL) { - *err = res; - } - return (struct tcp_pcb *)lpcb; -} - -/** - * Update the state that tracks the available window space to advertise. - * - * Returns how much extra window would be advertised if we sent an - * update now. - */ -u32_t -tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) -{ - u32_t new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; - - if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { - /* we can advertise more window */ - pcb->rcv_ann_wnd = pcb->rcv_wnd; - return new_right_edge - pcb->rcv_ann_right_edge; - } else { - if (TCP_SEQ_GT(pcb->rcv_nxt, pcb->rcv_ann_right_edge)) { - /* Can happen due to other end sending out of advertised window, - * but within actual available (but not yet advertised) window */ - pcb->rcv_ann_wnd = 0; - } else { - /* keep the right edge of window constant */ - u32_t new_rcv_ann_wnd = pcb->rcv_ann_right_edge - pcb->rcv_nxt; -#if !LWIP_WND_SCALE - LWIP_ASSERT("new_rcv_ann_wnd <= 0xffff", new_rcv_ann_wnd <= 0xffff); -#endif - pcb->rcv_ann_wnd = (tcpwnd_size_t)new_rcv_ann_wnd; - } - return 0; - } -} - -/** - * @ingroup tcp_raw - * This function should be called by the application when it has - * processed the data. The purpose is to advertise a larger window - * when the data has been processed. - * - * @param pcb the tcp_pcb for which data is read - * @param len the amount of bytes that have been read by the application - */ -void -tcp_recved(struct tcp_pcb *pcb, u16_t len) -{ - int wnd_inflation; - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_recved for listen-pcbs", - pcb->state != LISTEN); - - pcb->rcv_wnd += len; - if (pcb->rcv_wnd > TCP_WND_MAX(pcb)) { - pcb->rcv_wnd = TCP_WND_MAX(pcb); - } else if (pcb->rcv_wnd == 0) { - /* rcv_wnd overflowed */ - if ((pcb->state == CLOSE_WAIT) || (pcb->state == LAST_ACK)) { - /* In passive close, we allow this, since the FIN bit is added to rcv_wnd - by the stack itself, since it is not mandatory for an application - to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ - pcb->rcv_wnd = TCP_WND_MAX(pcb); - } else { - LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0); - } - } - - wnd_inflation = tcp_update_rcv_ann_wnd(pcb); - - /* If the change in the right edge of window is significant (default - * watermark is TCP_WND/4), then send an explicit update now. - * Otherwise wait for a packet to be sent in the normal course of - * events (or more window to be available later) */ - if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { - tcp_ack_now(pcb); - tcp_output(pcb); - } - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: received %"U16_F" bytes, wnd %"TCPWNDSIZE_F" (%"TCPWNDSIZE_F").\n", - len, pcb->rcv_wnd, (u16_t)(TCP_WND_MAX(pcb) - pcb->rcv_wnd))); -} - -/** - * Allocate a new local TCP port. - * - * @return a new (free) local TCP port number - */ -static u16_t -tcp_new_port(void) -{ - u8_t i; - u16_t n = 0; - struct tcp_pcb *pcb; - -again: - if (tcp_port++ == TCP_LOCAL_PORT_RANGE_END) { - tcp_port = TCP_LOCAL_PORT_RANGE_START; - } - /* Check all PCB lists. */ - for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { - for (pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { - if (pcb->local_port == tcp_port) { - if (++n > (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START)) { - return 0; - } - goto again; - } - } - } - return tcp_port; -} - -/** - * @ingroup tcp_raw - * Connects to another host. The function given as the "connected" - * argument will be called when the connection has been established. - * - * @param pcb the tcp_pcb used to establish the connection - * @param ipaddr the remote ip address to connect to - * @param port the remote tcp port to connect to - * @param connected callback function to call when connected (on error, - the err calback will be called) - * @return ERR_VAL if invalid arguments are given - * ERR_OK if connect request has been sent - * other err_t values if connect request couldn't be sent - */ -err_t -tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, - tcp_connected_fn connected) -{ - err_t ret; - u32_t iss; - u16_t old_local_port; - - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); - ip_addr_set(&pcb->remote_ip, ipaddr); - pcb->remote_port = port; - - /* check if we have a route to the remote host */ - if (ip_addr_isany(&pcb->local_ip)) { - /* no local IP address set, yet. */ - struct netif *netif; - const ip_addr_t *local_ip; - ip_route_get_local_ip(&pcb->local_ip, &pcb->remote_ip, netif, local_ip); - if ((netif == NULL) || (local_ip == NULL)) { - /* Don't even try to send a SYN packet if we have no route - since that will fail. */ - return ERR_RTE; - } - /* Use the address as local address of the pcb. */ - ip_addr_copy(pcb->local_ip, *local_ip); - } - - old_local_port = pcb->local_port; - if (pcb->local_port == 0) { - pcb->local_port = tcp_new_port(); - if (pcb->local_port == 0) { - return ERR_BUF; - } - } else { -#if SO_REUSE - if (ip_get_option(pcb, SOF_REUSEADDR)) { - /* Since SOF_REUSEADDR allows reusing a local address, we have to make sure - now that the 5-tuple is unique. */ - struct tcp_pcb *cpcb; - int i; - /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ - for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { - for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { - if ((cpcb->local_port == pcb->local_port) && - (cpcb->remote_port == port) && - ip_addr_cmp(&cpcb->local_ip, &pcb->local_ip) && - ip_addr_cmp(&cpcb->remote_ip, ipaddr)) { - /* linux returns EISCONN here, but ERR_USE should be OK for us */ - return ERR_USE; - } - } - } - } -#endif /* SO_REUSE */ - } - - iss = tcp_next_iss(pcb); - pcb->rcv_nxt = 0; - pcb->snd_nxt = iss; - pcb->lastack = iss - 1; - pcb->snd_wl2 = iss - 1; - pcb->snd_lbb = iss - 1; - /* Start with a window that does not need scaling. When window scaling is - enabled and used, the window is enlarged when both sides agree on scaling. */ - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); - pcb->rcv_ann_right_edge = pcb->rcv_nxt; - pcb->snd_wnd = TCP_WND; - /* As initial send MSS, we use TCP_MSS but limit it to 536. - The send MSS is updated when an MSS option is received. */ - pcb->mss = INITIAL_MSS; -#if TCP_CALCULATE_EFF_SEND_MSS - pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - pcb->cwnd = 1; -#if LWIP_CALLBACK_API - pcb->connected = connected; -#else /* LWIP_CALLBACK_API */ - LWIP_UNUSED_ARG(connected); -#endif /* LWIP_CALLBACK_API */ - - /* Send a SYN together with the MSS option. */ - ret = tcp_enqueue_flags(pcb, TCP_SYN); - if (ret == ERR_OK) { - /* SYN segment was enqueued, changed the pcbs state now */ - pcb->state = SYN_SENT; - if (old_local_port != 0) { - TCP_RMV(&tcp_bound_pcbs, pcb); - } - TCP_REG_ACTIVE(pcb); - MIB2_STATS_INC(mib2.tcpactiveopens); - - tcp_output(pcb); - } - return ret; -} - -/** - * Called every 500 ms and implements the retransmission timer and the timer that - * removes PCBs that have been in TIME-WAIT for enough time. It also increments - * various timers such as the inactivity timer in each PCB. - * - * Automatically called from tcp_tmr(). - */ -void -tcp_slowtmr(void) -{ - struct tcp_pcb *pcb, *prev; - tcpwnd_size_t eff_wnd; - u8_t pcb_remove; /* flag if a PCB should be removed */ - u8_t pcb_reset; /* flag if a RST should be sent when removing */ - err_t err; - - err = ERR_OK; - - ++tcp_ticks; - ++tcp_timer_ctr; - -tcp_slowtmr_start: - /* Steps through all of the active PCBs. */ - prev = NULL; - pcb = tcp_active_pcbs; - if (pcb == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); - } - while (pcb != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); - LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); - if (pcb->last_timer == tcp_timer_ctr) { - /* skip this pcb, we have already processed it */ - pcb = pcb->next; - continue; - } - pcb->last_timer = tcp_timer_ctr; - - pcb_remove = 0; - pcb_reset = 0; - - if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); - } - else if (pcb->nrtx >= TCP_MAXRTX) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); - } else { - if (pcb->persist_backoff > 0) { - /* If snd_wnd is zero, use persist timer to send 1 byte probes - * instead of using the standard retransmission mechanism. */ - u8_t backoff_cnt = tcp_persist_backoff[pcb->persist_backoff-1]; - if (pcb->persist_cnt < backoff_cnt) { - pcb->persist_cnt++; - } - if (pcb->persist_cnt >= backoff_cnt) { - if (tcp_zero_window_probe(pcb) == ERR_OK) { - pcb->persist_cnt = 0; - if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { - pcb->persist_backoff++; - } - } - } - } else { - /* Increase the retransmission timer if it is running */ - if (pcb->rtime >= 0) { - ++pcb->rtime; - } - - if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) { - /* Time for a retransmission. */ - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F - " pcb->rto %"S16_F"\n", - pcb->rtime, pcb->rto)); - - /* Double retransmission time-out unless we are trying to - * connect to somebody (i.e., we are in SYN_SENT). */ - if (pcb->state != SYN_SENT) { - u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1); - pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx]; - } - - /* Reset the retransmission timer. */ - pcb->rtime = 0; - - /* Reduce congestion window and ssthresh. */ - eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd); - pcb->ssthresh = eff_wnd >> 1; - if (pcb->ssthresh < (tcpwnd_size_t)(pcb->mss << 1)) { - pcb->ssthresh = (pcb->mss << 1); - } - pcb->cwnd = pcb->mss; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"TCPWNDSIZE_F - " ssthresh %"TCPWNDSIZE_F"\n", - pcb->cwnd, pcb->ssthresh)); - - /* The following needs to be called AFTER cwnd is set to one - mss - STJ */ - tcp_rexmit_rto(pcb); - } - } - } - /* Check if this PCB has stayed too long in FIN-WAIT-2 */ - if (pcb->state == FIN_WAIT_2) { - /* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */ - if (pcb->flags & TF_RXCLOSED) { - /* PCB was fully closed (either through close() or SHUT_RDWR): - normal FIN-WAIT timeout handling. */ - if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n")); - } - } - } - - /* Check if KEEPALIVE should be sent */ - if (ip_get_option(pcb, SOF_KEEPALIVE) && - ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT))) { - if ((u32_t)(tcp_ticks - pcb->tmr) > - (pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL) - { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to ")); - ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - ++pcb_remove; - ++pcb_reset; - } else if ((u32_t)(tcp_ticks - pcb->tmr) > - (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb)) - / TCP_SLOW_INTERVAL) - { - err = tcp_keepalive(pcb); - if (err == ERR_OK) { - pcb->keep_cnt_sent++; - } - } - } - - /* If this PCB has queued out of sequence data, but has been - inactive for too long, will drop the data (it will eventually - be retransmitted). */ -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL && - (u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) { - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: dropping OOSEQ queued data\n")); - } -#endif /* TCP_QUEUE_OOSEQ */ - - /* Check if this PCB has stayed too long in SYN-RCVD */ - if (pcb->state == SYN_RCVD) { - if ((u32_t)(tcp_ticks - pcb->tmr) > - TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in SYN-RCVD\n")); - } - } - - /* Check if this PCB has stayed too long in LAST-ACK */ - if (pcb->state == LAST_ACK) { - if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { - ++pcb_remove; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in LAST-ACK\n")); - } - } - - /* If the PCB should be removed, do it. */ - if (pcb_remove) { - struct tcp_pcb *pcb2; -#if LWIP_CALLBACK_API - tcp_err_fn err_fn = pcb->errf; -#endif /* LWIP_CALLBACK_API */ - void *err_arg; - enum tcp_state last_state; - tcp_pcb_purge(pcb); - /* Remove PCB from tcp_active_pcbs list. */ - if (prev != NULL) { - LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); - prev->next = pcb->next; - } else { - /* This PCB was the first. */ - LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); - tcp_active_pcbs = pcb->next; - } - - if (pcb_reset) { - tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, - pcb->local_port, pcb->remote_port); - } - - err_arg = pcb->callback_arg; - last_state = pcb->state; - pcb2 = pcb; - pcb = pcb->next; - memp_free(MEMP_TCP_PCB, pcb2); - - tcp_active_pcbs_changed = 0; - TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT); - if (tcp_active_pcbs_changed) { - goto tcp_slowtmr_start; - } - } else { - /* get the 'next' element now and work with 'prev' below (in case of abort) */ - prev = pcb; - pcb = pcb->next; - - /* We check if we should poll the connection. */ - ++prev->polltmr; - if (prev->polltmr >= prev->pollinterval) { - prev->polltmr = 0; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); - tcp_active_pcbs_changed = 0; - TCP_EVENT_POLL(prev, err); - if (tcp_active_pcbs_changed) { - goto tcp_slowtmr_start; - } - /* if err == ERR_ABRT, 'prev' is already deallocated */ - if (err == ERR_OK) { - tcp_output(prev); - } - } - } - } - - - /* Steps through all of the TIME-WAIT PCBs. */ - prev = NULL; - pcb = tcp_tw_pcbs; - while (pcb != NULL) { - LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - pcb_remove = 0; - - /* Check if this PCB has stayed long enough in TIME-WAIT */ - if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) { - ++pcb_remove; - } - - /* If the PCB should be removed, do it. */ - if (pcb_remove) { - struct tcp_pcb *pcb2; - tcp_pcb_purge(pcb); - /* Remove PCB from tcp_tw_pcbs list. */ - if (prev != NULL) { - LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs); - prev->next = pcb->next; - } else { - /* This PCB was the first. */ - LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); - tcp_tw_pcbs = pcb->next; - } - pcb2 = pcb; - pcb = pcb->next; - memp_free(MEMP_TCP_PCB, pcb2); - } else { - prev = pcb; - pcb = pcb->next; - } - } -} - -/** - * Is called every TCP_FAST_INTERVAL (250 ms) and process data previously - * "refused" by upper layer (application) and sends delayed ACKs. - * - * Automatically called from tcp_tmr(). - */ -void -tcp_fasttmr(void) -{ - struct tcp_pcb *pcb; - - ++tcp_timer_ctr; - -tcp_fasttmr_start: - pcb = tcp_active_pcbs; - - while (pcb != NULL) { - if (pcb->last_timer != tcp_timer_ctr) { - struct tcp_pcb *next; - pcb->last_timer = tcp_timer_ctr; - /* send delayed ACKs */ - if (pcb->flags & TF_ACK_DELAY) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); - tcp_ack_now(pcb); - tcp_output(pcb); - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - /* send pending FIN */ - if (pcb->flags & TF_CLOSEPEND) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n")); - pcb->flags &= ~(TF_CLOSEPEND); - tcp_close_shutdown_fin(pcb); - } - - next = pcb->next; - - /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) { - tcp_active_pcbs_changed = 0; - tcp_process_refused_data(pcb); - if (tcp_active_pcbs_changed) { - /* application callback has changed the pcb list: restart the loop */ - goto tcp_fasttmr_start; - } - } - pcb = next; - } else { - pcb = pcb->next; - } - } -} - -/** Call tcp_output for all active pcbs that have TF_NAGLEMEMERR set */ -void -tcp_txnow(void) -{ - struct tcp_pcb *pcb; - - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->flags & TF_NAGLEMEMERR) { - tcp_output(pcb); - } - } -} - -/** Pass pcb->refused_data to the recv callback */ -err_t -tcp_process_refused_data(struct tcp_pcb *pcb) -{ -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - struct pbuf *rest; - while (pcb->refused_data != NULL) -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - { - err_t err; - u8_t refused_flags = pcb->refused_data->flags; - /* set pcb->refused_data to NULL in case the callback frees it and then - closes the pcb */ - struct pbuf *refused_data = pcb->refused_data; -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - pbuf_split_64k(refused_data, &rest); - pcb->refused_data = rest; -#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - pcb->refused_data = NULL; -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - /* Notify again application with data previously received. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); - TCP_EVENT_RECV(pcb, refused_data, ERR_OK, err); - if (err == ERR_OK) { - /* did refused_data include a FIN? */ - if (refused_flags & PBUF_FLAG_TCP_FIN -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - && (rest == NULL) -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - ) { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { - pcb->rcv_wnd++; - } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - return ERR_ABRT; - } - } - } else if (err == ERR_ABRT) { - /* if err == ERR_ABRT, 'pcb' is already deallocated */ - /* Drop incoming packets because pcb is "full" (only if the incoming - segment contains data). */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); - return ERR_ABRT; - } else { - /* data is still refused, pbuf is still valid (go on for ACK-only packets) */ -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_cat(refused_data, rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - pcb->refused_data = refused_data; - return ERR_INPROGRESS; - } - } - return ERR_OK; -} - -/** - * Deallocates a list of TCP segments (tcp_seg structures). - * - * @param seg tcp_seg list of TCP segments to free - */ -void -tcp_segs_free(struct tcp_seg *seg) -{ - while (seg != NULL) { - struct tcp_seg *next = seg->next; - tcp_seg_free(seg); - seg = next; - } -} - -/** - * Frees a TCP segment (tcp_seg structure). - * - * @param seg single tcp_seg to free - */ -void -tcp_seg_free(struct tcp_seg *seg) -{ - if (seg != NULL) { - if (seg->p != NULL) { - pbuf_free(seg->p); -#if TCP_DEBUG - seg->p = NULL; -#endif /* TCP_DEBUG */ - } - memp_free(MEMP_TCP_SEG, seg); - } -} - -/** - * Sets the priority of a connection. - * - * @param pcb the tcp_pcb to manipulate - * @param prio new priority - */ -void -tcp_setprio(struct tcp_pcb *pcb, u8_t prio) -{ - pcb->prio = prio; -} - -#if TCP_QUEUE_OOSEQ -/** - * Returns a copy of the given TCP segment. - * The pbuf and data are not copied, only the pointers - * - * @param seg the old tcp_seg - * @return a copy of seg - */ -struct tcp_seg * -tcp_seg_copy(struct tcp_seg *seg) -{ - struct tcp_seg *cseg; - - cseg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG); - if (cseg == NULL) { - return NULL; - } - SMEMCPY((u8_t *)cseg, (const u8_t *)seg, sizeof(struct tcp_seg)); - pbuf_ref(cseg->p); - return cseg; -} -#endif /* TCP_QUEUE_OOSEQ */ - -#if LWIP_CALLBACK_API -/** - * Default receive callback that is called if the user didn't register - * a recv callback for the pcb. - */ -err_t -tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - LWIP_UNUSED_ARG(arg); - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); - } else if (err == ERR_OK) { - return tcp_close(pcb); - } - return ERR_OK; -} -#endif /* LWIP_CALLBACK_API */ - -/** - * Kills the oldest active connection that has the same or lower priority than - * 'prio'. - * - * @param prio minimum priority - */ -static void -tcp_kill_prio(u8_t prio) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - u8_t mprio; - - mprio = LWIP_MIN(TCP_PRIO_MAX, prio); - - /* We kill the oldest active connection that has lower priority than prio. */ - inactivity = 0; - inactive = NULL; - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->prio <= mprio && - (u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - mprio = pcb->prio; - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", - (void *)inactive, inactivity)); - tcp_abort(inactive); - } -} - -/** - * Kills the oldest connection that is in specific state. - * Called from tcp_alloc() for LAST_ACK and CLOSING if no more connections are available. - */ -static void -tcp_kill_state(enum tcp_state state) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - LWIP_ASSERT("invalid state", (state == CLOSING) || (state == LAST_ACK)); - - inactivity = 0; - inactive = NULL; - /* Go through the list of active pcbs and get the oldest pcb that is in state - CLOSING/LAST_ACK. */ - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->state == state) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_closing: killing oldest %s PCB %p (%"S32_F")\n", - tcp_state_str[state], (void *)inactive, inactivity)); - /* Don't send a RST, since no data is lost. */ - tcp_abandon(inactive, 0); - } -} - -/** - * Kills the oldest connection that is in TIME_WAIT state. - * Called from tcp_alloc() if no more connections are available. - */ -static void -tcp_kill_timewait(void) -{ - struct tcp_pcb *pcb, *inactive; - u32_t inactivity; - - inactivity = 0; - inactive = NULL; - /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - if ((u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { - inactivity = tcp_ticks - pcb->tmr; - inactive = pcb; - } - } - if (inactive != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_timewait: killing oldest TIME-WAIT PCB %p (%"S32_F")\n", - (void *)inactive, inactivity)); - tcp_abort(inactive); - } -} - -/** - * Allocate a new tcp_pcb structure. - * - * @param prio priority for the new pcb - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * -tcp_alloc(u8_t prio) -{ - struct tcp_pcb *pcb; - - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in TIME-WAIT. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest TIME-WAIT connection\n")); - tcp_kill_timewait(); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in LAST-ACK (these wouldn't go to TIME-WAIT). */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest LAST-ACK connection\n")); - tcp_kill_state(LAST_ACK); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing oldest connection in CLOSING. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing off oldest CLOSING connection\n")); - tcp_kill_state(CLOSING); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb == NULL) { - /* Try killing active connections with lower priority than the new one. */ - LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: killing connection with prio lower than %d\n", prio)); - tcp_kill_prio(prio); - /* Try to allocate a tcp_pcb again. */ - pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB); - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed multiple times before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed multiple times before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed multiple times before */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* adjust err stats: memp_malloc failed above */ - MEMP_STATS_DEC(err, MEMP_TCP_PCB); - } - } - if (pcb != NULL) { - /* zero out the whole pcb, so there is no need to initialize members to zero */ - memset(pcb, 0, sizeof(struct tcp_pcb)); - pcb->prio = prio; - pcb->snd_buf = TCP_SND_BUF; - /* Start with a window that does not need scaling. When window scaling is - enabled and used, the window is enlarged when both sides agree on scaling. */ - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); - pcb->ttl = TCP_TTL; - /* As initial send MSS, we use TCP_MSS but limit it to 536. - The send MSS is updated when an MSS option is received. */ - pcb->mss = INITIAL_MSS; - pcb->rto = 3000 / TCP_SLOW_INTERVAL; - pcb->sv = 3000 / TCP_SLOW_INTERVAL; - pcb->rtime = -1; - pcb->cwnd = 1; - pcb->tmr = tcp_ticks; - pcb->last_timer = tcp_timer_ctr; - - /* RFC 5681 recommends setting ssthresh abritrarily high and gives an example - of using the largest advertised receive window. We've seen complications with - receiving TCPs that use window scaling and/or window auto-tuning where the - initial advertised window is very small and then grows rapidly once the - connection is established. To avoid these complications, we set ssthresh to the - largest effective cwnd (amount of in-flight data) that the sender can have. */ - pcb->ssthresh = TCP_SND_BUF; - -#if LWIP_CALLBACK_API - pcb->recv = tcp_recv_null; -#endif /* LWIP_CALLBACK_API */ - - /* Init KEEPALIVE timer */ - pcb->keep_idle = TCP_KEEPIDLE_DEFAULT; - -#if LWIP_TCP_KEEPALIVE - pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT; - pcb->keep_cnt = TCP_KEEPCNT_DEFAULT; -#endif /* LWIP_TCP_KEEPALIVE */ - } - return pcb; -} - -/** - * @ingroup tcp_raw - * Creates a new TCP protocol control block but doesn't place it on - * any of the TCP PCB lists. - * The pcb is not put on any list until binding using tcp_bind(). - * - * @internal: Maybe there should be a idle TCP PCB list where these - * PCBs are put on. Port reservation using tcp_bind() is implemented but - * allocated pcbs that are not bound can't be killed automatically if wanting - * to allocate a pcb with higher prio (@see tcp_kill_prio()) - * - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * -tcp_new(void) -{ - return tcp_alloc(TCP_PRIO_NORMAL); -} - -/** - * @ingroup tcp_raw - * Creates a new TCP protocol control block but doesn't - * place it on any of the TCP PCB lists. - * The pcb is not put on any list until binding using tcp_bind(). - * - * @param type IP address type, see @ref lwip_ip_addr_type definitions. - * If you want to listen to IPv4 and IPv6 (dual-stack) connections, - * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. - * @return a new tcp_pcb that initially is in state CLOSED - */ -struct tcp_pcb * -tcp_new_ip_type(u8_t type) -{ - struct tcp_pcb * pcb; - pcb = tcp_alloc(TCP_PRIO_NORMAL); -#if LWIP_IPV4 && LWIP_IPV6 - if (pcb != NULL) { - IP_SET_TYPE_VAL(pcb->local_ip, type); - IP_SET_TYPE_VAL(pcb->remote_ip, type); - } -#else - LWIP_UNUSED_ARG(type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - return pcb; -} - -/** - * @ingroup tcp_raw - * Used to specify the argument that should be passed callback - * functions. - * - * @param pcb tcp_pcb to set the callback argument - * @param arg void pointer argument to pass to callback functions - */ -void -tcp_arg(struct tcp_pcb *pcb, void *arg) -{ - /* This function is allowed to be called for both listen pcbs and - connection pcbs. */ - if (pcb != NULL) { - pcb->callback_arg = arg; - } -} -#if LWIP_CALLBACK_API - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called when a TCP - * connection receives data. - * - * @param pcb tcp_pcb to set the recv callback - * @param recv callback function to call for this pcb when data is received - */ -void -tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv) -{ - if (pcb != NULL) { - LWIP_ASSERT("invalid socket state for recv callback", pcb->state != LISTEN); - pcb->recv = recv; - } -} - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called when TCP data - * has been successfully delivered to the remote host. - * - * @param pcb tcp_pcb to set the sent callback - * @param sent callback function to call for this pcb when data is successfully sent - */ -void -tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) -{ - if (pcb != NULL) { - LWIP_ASSERT("invalid socket state for sent callback", pcb->state != LISTEN); - pcb->sent = sent; - } -} - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called when a fatal error - * has occurred on the connection. - * - * @note The corresponding pcb is already freed when this callback is called! - * - * @param pcb tcp_pcb to set the err callback - * @param err callback function to call for this pcb when a fatal error - * has occurred on the connection - */ -void -tcp_err(struct tcp_pcb *pcb, tcp_err_fn err) -{ - if (pcb != NULL) { - LWIP_ASSERT("invalid socket state for err callback", pcb->state != LISTEN); - pcb->errf = err; - } -} - -/** - * @ingroup tcp_raw - * Used for specifying the function that should be called when a - * LISTENing connection has been connected to another host. - * - * @param pcb tcp_pcb to set the accept callback - * @param accept callback function to call for this pcb when LISTENing - * connection has been connected to another host - */ -void -tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) -{ - if ((pcb != NULL) && (pcb->state == LISTEN)) { - struct tcp_pcb_listen *lpcb = (struct tcp_pcb_listen*)pcb; - lpcb->accept = accept; - } -} -#endif /* LWIP_CALLBACK_API */ - - -/** - * @ingroup tcp_raw - * Used to specify the function that should be called periodically - * from TCP. The interval is specified in terms of the TCP coarse - * timer interval, which is called twice a second. - * - */ -void -tcp_poll(struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) -{ - LWIP_ASSERT("invalid socket state for poll", pcb->state != LISTEN); -#if LWIP_CALLBACK_API - pcb->poll = poll; -#else /* LWIP_CALLBACK_API */ - LWIP_UNUSED_ARG(poll); -#endif /* LWIP_CALLBACK_API */ - pcb->pollinterval = interval; -} - -/** - * Purges a TCP PCB. Removes any buffered data and frees the buffer memory - * (pcb->ooseq, pcb->unsent and pcb->unacked are freed). - * - * @param pcb tcp_pcb to purge. The pcb itself is not deallocated! - */ -void -tcp_pcb_purge(struct tcp_pcb *pcb) -{ - if (pcb->state != CLOSED && - pcb->state != TIME_WAIT && - pcb->state != LISTEN) { - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge\n")); - - tcp_backlog_accepted(pcb); - - if (pcb->refused_data != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->refused_data\n")); - pbuf_free(pcb->refused_data); - pcb->refused_data = NULL; - } - if (pcb->unsent != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: not all data sent\n")); - } - if (pcb->unacked != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->unacked\n")); - } -#if TCP_QUEUE_OOSEQ - if (pcb->ooseq != NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_pcb_purge: data left on ->ooseq\n")); - } - tcp_segs_free(pcb->ooseq); - pcb->ooseq = NULL; -#endif /* TCP_QUEUE_OOSEQ */ - - /* Stop the retransmission timer as it will expect data on unacked - queue if it fires */ - pcb->rtime = -1; - - tcp_segs_free(pcb->unsent); - tcp_segs_free(pcb->unacked); - pcb->unacked = pcb->unsent = NULL; -#if TCP_OVERSIZE - pcb->unsent_oversize = 0; -#endif /* TCP_OVERSIZE */ - } -} - -/** - * Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first. - * - * @param pcblist PCB list to purge. - * @param pcb tcp_pcb to purge. The pcb itself is NOT deallocated! - */ -void -tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) -{ - TCP_RMV(pcblist, pcb); - - tcp_pcb_purge(pcb); - - /* if there is an outstanding delayed ACKs, send it */ - if (pcb->state != TIME_WAIT && - pcb->state != LISTEN && - pcb->flags & TF_ACK_DELAY) { - pcb->flags |= TF_ACK_NOW; - tcp_output(pcb); - } - - if (pcb->state != LISTEN) { - LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); - LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); -#if TCP_QUEUE_OOSEQ - LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); -#endif /* TCP_QUEUE_OOSEQ */ - } - - pcb->state = CLOSED; - /* reset the local port to prevent the pcb from being 'bound' */ - pcb->local_port = 0; - - LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); -} - -/** - * Calculates a new initial sequence number for new connections. - * - * @return u32_t pseudo random sequence number - */ -u32_t -tcp_next_iss(struct tcp_pcb *pcb) -{ -#ifdef LWIP_HOOK_TCP_ISN - return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port); -#else /* LWIP_HOOK_TCP_ISN */ - static u32_t iss = 6510; - - LWIP_UNUSED_ARG(pcb); - - iss += tcp_ticks; /* XXX */ - return iss; -#endif /* LWIP_HOOK_TCP_ISN */ -} - -#if TCP_CALCULATE_EFF_SEND_MSS -/** - * Calculates the effective send mss that can be used for a specific IP address - * by using ip_route to determine the netif used to send to the address and - * calculating the minimum of TCP_MSS and that netif's mtu (if set). - */ -u16_t -tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest -#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING - , const ip_addr_t *src -#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ - ) -{ - u16_t mss_s; - struct netif *outif; - s16_t mtu; - - outif = ip_route(src, dest); -#if LWIP_IPV6 -#if LWIP_IPV4 - if (IP_IS_V6(dest)) -#endif /* LWIP_IPV4 */ - { - /* First look in destination cache, to see if there is a Path MTU. */ - mtu = nd6_get_destination_mtu(ip_2_ip6(dest), outif); - } -#if LWIP_IPV4 - else -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - { - if (outif == NULL) { - return sendmss; - } - mtu = outif->mtu; - } -#endif /* LWIP_IPV4 */ - - if (mtu != 0) { -#if LWIP_IPV6 -#if LWIP_IPV4 - if (IP_IS_V6(dest)) -#endif /* LWIP_IPV4 */ - { - mss_s = mtu - IP6_HLEN - TCP_HLEN; - } -#if LWIP_IPV4 - else -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - { - mss_s = mtu - IP_HLEN - TCP_HLEN; - } -#endif /* LWIP_IPV4 */ - /* RFC 1122, chap 4.2.2.6: - * Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize - * We correct for TCP options in tcp_write(), and don't support IP options. - */ - sendmss = LWIP_MIN(sendmss, mss_s); - } - return sendmss; -} -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - -/** Helper function for tcp_netif_ip_addr_changed() that iterates a pcb list */ -static void -tcp_netif_ip_addr_changed_pcblist(const ip_addr_t* old_addr, struct tcp_pcb* pcb_list) -{ - struct tcp_pcb *pcb; - pcb = pcb_list; - while (pcb != NULL) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&pcb->local_ip, old_addr) -#if LWIP_AUTOIP - /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ - && (!IP_IS_V4_VAL(pcb->local_ip) || !ip4_addr_islinklocal(ip_2_ip4(&pcb->local_ip))) -#endif /* LWIP_AUTOIP */ - ) { - /* this connection must be aborted */ - struct tcp_pcb *next = pcb->next; - LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); - tcp_abort(pcb); - pcb = next; - } else { - pcb = pcb->next; - } - } -} - -/** This function is called from netif.c when address is changed or netif is removed - * - * @param old_addr IP address of the netif before change - * @param new_addr IP address of the netif after change or NULL if netif has been removed - */ -void -tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) -{ - struct tcp_pcb_listen *lpcb, *next; - - if (!ip_addr_isany(old_addr)) { - tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_active_pcbs); - tcp_netif_ip_addr_changed_pcblist(old_addr, tcp_bound_pcbs); - - if (!ip_addr_isany(new_addr)) { - /* PCB bound to current local interface address? */ - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = next) { - next = lpcb->next; - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&lpcb->local_ip, old_addr)) { - /* The PCB is listening to the old ipaddr and - * is set to listen to the new one instead */ - ip_addr_copy(lpcb->local_ip, *new_addr); - } - } - } - } -} - -const char* -tcp_debug_state_str(enum tcp_state s) -{ - return tcp_state_str[s]; -} - -#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG -/** - * Print a tcp header for debugging purposes. - * - * @param tcphdr pointer to a struct tcp_hdr - */ -void -tcp_debug_print(struct tcp_hdr *tcphdr) -{ - LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n")); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n", - lwip_ntohl(tcphdr->seqno))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n", - lwip_ntohl(tcphdr->ackno))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (", - TCPH_HDRLEN(tcphdr), - (u16_t)(TCPH_FLAGS(tcphdr) >> 5 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 4 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 3 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1), - (u16_t)(TCPH_FLAGS(tcphdr) & 1), - lwip_ntohs(tcphdr->wnd))); - tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); - LWIP_DEBUGF(TCP_DEBUG, ("), win)\n")); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n", - lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp))); - LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n")); -} - -/** - * Print a tcp state for debugging purposes. - * - * @param s enum tcp_state to print - */ -void -tcp_debug_print_state(enum tcp_state s) -{ - LWIP_DEBUGF(TCP_DEBUG, ("State: %s\n", tcp_state_str[s])); -} - -/** - * Print tcp flags for debugging purposes. - * - * @param flags tcp flags, all active flags are printed - */ -void -tcp_debug_print_flags(u8_t flags) -{ - if (flags & TCP_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("FIN ")); - } - if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("SYN ")); - } - if (flags & TCP_RST) { - LWIP_DEBUGF(TCP_DEBUG, ("RST ")); - } - if (flags & TCP_PSH) { - LWIP_DEBUGF(TCP_DEBUG, ("PSH ")); - } - if (flags & TCP_ACK) { - LWIP_DEBUGF(TCP_DEBUG, ("ACK ")); - } - if (flags & TCP_URG) { - LWIP_DEBUGF(TCP_DEBUG, ("URG ")); - } - if (flags & TCP_ECE) { - LWIP_DEBUGF(TCP_DEBUG, ("ECE ")); - } - if (flags & TCP_CWR) { - LWIP_DEBUGF(TCP_DEBUG, ("CWR ")); - } - LWIP_DEBUGF(TCP_DEBUG, ("\n")); -} - -/** - * Print all tcp_pcbs in every list for debugging purposes. - */ -void -tcp_debug_print_pcbs(void) -{ - struct tcp_pcb *pcb; - struct tcp_pcb_listen *pcbl; - - LWIP_DEBUGF(TCP_DEBUG, ("Active PCB states:\n")); - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } - - LWIP_DEBUGF(TCP_DEBUG, ("Listen PCB states:\n")); - for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F" ", pcbl->local_port)); - tcp_debug_print_state(pcbl->state); - } - - LWIP_DEBUGF(TCP_DEBUG, ("TIME-WAIT PCB states:\n")); - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_DEBUGF(TCP_DEBUG, ("Local port %"U16_F", foreign port %"U16_F" snd_nxt %"U32_F" rcv_nxt %"U32_F" ", - pcb->local_port, pcb->remote_port, - pcb->snd_nxt, pcb->rcv_nxt)); - tcp_debug_print_state(pcb->state); - } -} - -/** - * Check state consistency of the tcp_pcb lists. - */ -s16_t -tcp_pcbs_sane(void) -{ - struct tcp_pcb *pcb; - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != CLOSED", pcb->state != CLOSED); - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != LISTEN", pcb->state != LISTEN); - LWIP_ASSERT("tcp_pcbs_sane: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); - } - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_pcbs_sane: tw pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - } - return 1; -} -#endif /* TCP_DEBUG */ - -#endif /* LWIP_TCP */ diff --git a/components/net/lwip-2.0.2/src/core/tcp_in.c b/components/net/lwip-2.0.2/src/core/tcp_in.c deleted file mode 100644 index ba879284f2..0000000000 --- a/components/net/lwip-2.0.2/src/core/tcp_in.c +++ /dev/null @@ -1,1818 +0,0 @@ -/** - * @file - * Transmission Control Protocol, incoming traffic - * - * The input processing functions of the TCP layer. - * - * These functions are generally called in the order (ip_input() ->) - * tcp_input() -> * tcp_process() -> tcp_receive() (-> application). - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/tcp_priv.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#if LWIP_ND6_TCP_REACHABILITY_HINTS -#include "lwip/nd6.h" -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ - -/** Initial CWND calculation as defined RFC 2581 */ -#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U)); - -/* These variables are global to all functions involved in the input - processing of TCP segments. They are set by the tcp_input() - function. */ -static struct tcp_seg inseg; -static struct tcp_hdr *tcphdr; -static u16_t tcphdr_optlen; -static u16_t tcphdr_opt1len; -static u8_t* tcphdr_opt2; -static u16_t tcp_optidx; -static u32_t seqno, ackno; -static tcpwnd_size_t recv_acked; -static u16_t tcplen; -static u8_t flags; - -static u8_t recv_flags; -static struct pbuf *recv_data; - -struct tcp_pcb *tcp_input_pcb; - -/* Forward declarations. */ -static err_t tcp_process(struct tcp_pcb *pcb); -static void tcp_receive(struct tcp_pcb *pcb); -static void tcp_parseopt(struct tcp_pcb *pcb); - -static void tcp_listen_input(struct tcp_pcb_listen *pcb); -static void tcp_timewait_input(struct tcp_pcb *pcb); - -/** - * The initial input processing of TCP. It verifies the TCP header, demultiplexes - * the segment between the PCBs and passes it on to tcp_process(), which implements - * the TCP finite state machine. This function is called by the IP layer (in - * ip_input()). - * - * @param p received TCP segment to process (p->payload pointing to the TCP header) - * @param inp network interface on which this segment was received - */ -void -tcp_input(struct pbuf *p, struct netif *inp) -{ - struct tcp_pcb *pcb, *prev; - struct tcp_pcb_listen *lpcb; -#if SO_REUSE - struct tcp_pcb *lpcb_prev = NULL; - struct tcp_pcb_listen *lpcb_any = NULL; -#endif /* SO_REUSE */ - u8_t hdrlen_bytes; - err_t err; - - LWIP_UNUSED_ARG(inp); - - PERF_START; - - TCP_STATS_INC(tcp.recv); - MIB2_STATS_INC(mib2.tcpinsegs); - - tcphdr = (struct tcp_hdr *)p->payload; - -#if TCP_INPUT_DEBUG - tcp_debug_print(tcphdr); -#endif - - /* Check that TCP header fits in payload */ - if (p->len < TCP_HLEN) { - /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* Don't even process incoming broadcasts/multicasts. */ - if (ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()) || - ip_addr_ismulticast(ip_current_dest_addr())) { - TCP_STATS_INC(tcp.proterr); - goto dropped; - } - -#if CHECKSUM_CHECK_TCP - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) { - /* Verify TCP checksum. */ - u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - ip_current_src_addr(), ip_current_dest_addr()); - if (chksum != 0) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n", - chksum)); - tcp_debug_print(tcphdr); - TCP_STATS_INC(tcp.chkerr); - goto dropped; - } - } -#endif /* CHECKSUM_CHECK_TCP */ - - /* sanity-check header length */ - hdrlen_bytes = TCPH_HDRLEN(tcphdr) * 4; - if ((hdrlen_bytes < TCP_HLEN) || (hdrlen_bytes > p->tot_len)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: invalid header length (%"U16_F")\n", (u16_t)hdrlen_bytes)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* Move the payload pointer in the pbuf so that it points to the - TCP data instead of the TCP header. */ - tcphdr_optlen = hdrlen_bytes - TCP_HLEN; - tcphdr_opt2 = NULL; - if (p->len >= hdrlen_bytes) { - /* all options are in the first pbuf */ - tcphdr_opt1len = tcphdr_optlen; - pbuf_header(p, -(s16_t)hdrlen_bytes); /* cannot fail */ - } else { - u16_t opt2len; - /* TCP header fits into first pbuf, options don't - data is in the next pbuf */ - /* there must be a next pbuf, due to hdrlen_bytes sanity check above */ - LWIP_ASSERT("p->next != NULL", p->next != NULL); - - /* advance over the TCP header (cannot fail) */ - pbuf_header(p, -TCP_HLEN); - - /* determine how long the first and second parts of the options are */ - tcphdr_opt1len = p->len; - opt2len = tcphdr_optlen - tcphdr_opt1len; - - /* options continue in the next pbuf: set p to zero length and hide the - options in the next pbuf (adjusting p->tot_len) */ - pbuf_header(p, -(s16_t)tcphdr_opt1len); - - /* check that the options fit in the second pbuf */ - if (opt2len > p->next->len) { - /* drop short packets */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: options overflow second pbuf (%"U16_F" bytes)\n", p->next->len)); - TCP_STATS_INC(tcp.lenerr); - goto dropped; - } - - /* remember the pointer to the second part of the options */ - tcphdr_opt2 = (u8_t*)p->next->payload; - - /* advance p->next to point after the options, and manually - adjust p->tot_len to keep it consistent with the changed p->next */ - pbuf_header(p->next, -(s16_t)opt2len); - p->tot_len -= opt2len; - - LWIP_ASSERT("p->len == 0", p->len == 0); - LWIP_ASSERT("p->tot_len == p->next->tot_len", p->tot_len == p->next->tot_len); - } - - /* Convert fields in TCP header to host byte order. */ - tcphdr->src = lwip_ntohs(tcphdr->src); - tcphdr->dest = lwip_ntohs(tcphdr->dest); - seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno); - ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno); - tcphdr->wnd = lwip_ntohs(tcphdr->wnd); - - flags = TCPH_FLAGS(tcphdr); - tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); - - /* Demultiplex an incoming segment. First, we check if it is destined - for an active connection. */ - prev = NULL; - - for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); - LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); - LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); - if (pcb->remote_port == tcphdr->src && - pcb->local_port == tcphdr->dest && - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - /* Move this PCB to the front of the list so that subsequent - lookups will be faster (we exploit locality in TCP segment - arrivals). */ - LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); - if (prev != NULL) { - prev->next = pcb->next; - pcb->next = tcp_active_pcbs; - tcp_active_pcbs = pcb; - } else { - TCP_STATS_INC(tcp.cachehit); - } - LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); - break; - } - prev = pcb; - } - - if (pcb == NULL) { - /* If it did not go to an active connection, we check the connections - in the TIME-WAIT state. */ - for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { - LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); - if (pcb->remote_port == tcphdr->src && - pcb->local_port == tcphdr->dest && - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()) && - ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - /* We don't really care enough to move this PCB to the front - of the list since we are not very likely to receive that - many segments for connections in TIME-WAIT. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); - tcp_timewait_input(pcb); - pbuf_free(p); - return; - } - } - - /* Finally, if we still did not get a match, we check all PCBs that - are LISTENing for incoming connections. */ - prev = NULL; - for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { - if (lpcb->local_port == tcphdr->dest) { - if (IP_IS_ANY_TYPE_VAL(lpcb->local_ip)) { - /* found an ANY TYPE (IPv4/IPv6) match */ -#if SO_REUSE - lpcb_any = lpcb; - lpcb_prev = prev; -#else /* SO_REUSE */ - break; -#endif /* SO_REUSE */ - } else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) { - if (ip_addr_cmp(&lpcb->local_ip, ip_current_dest_addr())) { - /* found an exact match */ - break; - } else if (ip_addr_isany(&lpcb->local_ip)) { - /* found an ANY-match */ -#if SO_REUSE - lpcb_any = lpcb; - lpcb_prev = prev; -#else /* SO_REUSE */ - break; - #endif /* SO_REUSE */ - } - } - } - prev = (struct tcp_pcb *)lpcb; - } -#if SO_REUSE - /* first try specific local IP */ - if (lpcb == NULL) { - /* only pass to ANY if no specific local IP has been found */ - lpcb = lpcb_any; - prev = lpcb_prev; - } -#endif /* SO_REUSE */ - if (lpcb != NULL) { - /* Move this PCB to the front of the list so that subsequent - lookups will be faster (we exploit locality in TCP segment - arrivals). */ - if (prev != NULL) { - ((struct tcp_pcb_listen *)prev)->next = lpcb->next; - /* our successor is the remainder of the listening list */ - lpcb->next = tcp_listen_pcbs.listen_pcbs; - /* put this listening pcb at the head of the listening list */ - tcp_listen_pcbs.listen_pcbs = lpcb; - } else { - TCP_STATS_INC(tcp.cachehit); - } - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); - tcp_listen_input(lpcb); - pbuf_free(p); - return; - } - } - -#if TCP_INPUT_DEBUG - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("+-+-+-+-+-+-+-+-+-+-+-+-+-+- tcp_input: flags ")); - tcp_debug_print_flags(TCPH_FLAGS(tcphdr)); - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n")); -#endif /* TCP_INPUT_DEBUG */ - - - if (pcb != NULL) { - /* The incoming segment belongs to a connection. */ -#if TCP_INPUT_DEBUG - tcp_debug_print_state(pcb->state); -#endif /* TCP_INPUT_DEBUG */ - - /* Set up a tcp_seg structure. */ - inseg.next = NULL; - inseg.len = p->tot_len; - inseg.p = p; - inseg.tcphdr = tcphdr; - - recv_data = NULL; - recv_flags = 0; - recv_acked = 0; - - if (flags & TCP_PSH) { - p->flags |= PBUF_FLAG_PUSH; - } - - /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) { - if ((tcp_process_refused_data(pcb) == ERR_ABRT) || - ((pcb->refused_data != NULL) && (tcplen > 0))) { - /* pcb has been aborted or refused data is still refused and the new - segment contains data */ - if (pcb->rcv_ann_wnd == 0) { - /* this is a zero-window probe, we respond to it with current RCV.NXT - and drop the data segment */ - tcp_send_empty_ack(pcb); - } - TCP_STATS_INC(tcp.drop); - MIB2_STATS_INC(mib2.tcpinerrs); - goto aborted; - } - } - tcp_input_pcb = pcb; - err = tcp_process(pcb); - /* A return value of ERR_ABRT means that tcp_abort() was called - and that the pcb has been freed. If so, we don't do anything. */ - if (err != ERR_ABRT) { - if (recv_flags & TF_RESET) { - /* TF_RESET means that the connection was reset by the other - end. We then call the error callback to inform the - application that the connection is dead before we - deallocate the PCB. */ - TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST); - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - } else { - err = ERR_OK; - /* If the application has registered a "sent" function to be - called when new send buffer space is available, we call it - now. */ - if (recv_acked > 0) { - u16_t acked16; -#if LWIP_WND_SCALE - /* recv_acked is u32_t but the sent callback only takes a u16_t, - so we might have to call it multiple times. */ - u32_t acked = recv_acked; - while (acked > 0) { - acked16 = (u16_t)LWIP_MIN(acked, 0xffffu); - acked -= acked16; -#else - { - acked16 = recv_acked; -#endif - TCP_EVENT_SENT(pcb, (u16_t)acked16, err); - if (err == ERR_ABRT) { - goto aborted; - } - } - recv_acked = 0; - } - if (recv_flags & TF_CLOSED) { - /* The connection has been closed and we will deallocate the - PCB. */ - if (!(pcb->flags & TF_RXCLOSED)) { - /* Connection closed although the application has only shut down the - tx side: call the PCB's err callback and indicate the closure to - ensure the application doesn't continue using the PCB. */ - TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD); - } - tcp_pcb_remove(&tcp_active_pcbs, pcb); - memp_free(MEMP_TCP_PCB, pcb); - goto aborted; - } -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - while (recv_data != NULL) { - struct pbuf *rest = NULL; - pbuf_split_64k(recv_data, &rest); -#else /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - if (recv_data != NULL) { -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - - LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); - if (pcb->flags & TF_RXCLOSED) { - /* received data although already closed -> abort (send RST) to - notify the remote host that not all data has been processed */ - pbuf_free(recv_data); -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_free(rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - tcp_abort(pcb); - goto aborted; - } - - /* Notify application that data has been received. */ - TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); - if (err == ERR_ABRT) { -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_free(rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - goto aborted; - } - - /* If the upper layer can't receive this data, store it */ - if (err != ERR_OK) { -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - if (rest != NULL) { - pbuf_cat(recv_data, rest); - } -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - pcb->refused_data = recv_data; - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); -#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE - break; - } else { - /* Upper layer received the data, go on with the rest if > 64K */ - recv_data = rest; -#endif /* TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - } - } - - /* If a FIN segment was received, we call the callback - function with a NULL buffer to indicate EOF. */ - if (recv_flags & TF_GOT_FIN) { - if (pcb->refused_data != NULL) { - /* Delay this if we have refused data. */ - pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN; - } else { - /* correct rcv_wnd as the application won't call tcp_recved() - for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND_MAX(pcb)) { - pcb->rcv_wnd++; - } - TCP_EVENT_CLOSED(pcb, err); - if (err == ERR_ABRT) { - goto aborted; - } - } - } - - tcp_input_pcb = NULL; - /* Try to send something out. */ - tcp_output(pcb); -#if TCP_INPUT_DEBUG -#if TCP_DEBUG - tcp_debug_print_state(pcb->state); -#endif /* TCP_DEBUG */ -#endif /* TCP_INPUT_DEBUG */ - } - } - /* Jump target if pcb has been aborted in a callback (by calling tcp_abort()). - Below this line, 'pcb' may not be dereferenced! */ -aborted: - tcp_input_pcb = NULL; - recv_data = NULL; - - /* give up our reference to inseg.p */ - if (inseg.p != NULL) - { - pbuf_free(inseg.p); - inseg.p = NULL; - } - } else { - - /* If no matching PCB was found, send a TCP RST (reset) to the - sender. */ - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); - if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { - TCP_STATS_INC(tcp.proterr); - TCP_STATS_INC(tcp.drop); - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } - pbuf_free(p); - } - - LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane()); - PERF_STOP("tcp_input"); - return; -dropped: - TCP_STATS_INC(tcp.drop); - MIB2_STATS_INC(mib2.tcpinerrs); - pbuf_free(p); -} - -/** - * Called by tcp_input() when a segment arrives for a listening - * connection (from tcp_input()). - * - * @param pcb the tcp_pcb_listen for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static void -tcp_listen_input(struct tcp_pcb_listen *pcb) -{ - struct tcp_pcb *npcb; - u32_t iss; - err_t rc; - - if (flags & TCP_RST) { - /* An incoming RST should be ignored. Return. */ - return; - } - - /* In the LISTEN state, we check for incoming SYN segments, - creates a new PCB, and responds with a SYN|ACK. */ - if (flags & TCP_ACK) { - /* For incoming segments with the ACK flag set, respond with a - RST. */ - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n")); - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } else if (flags & TCP_SYN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); -#if TCP_LISTEN_BACKLOG - if (pcb->accepts_pending >= pcb->backlog) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest)); - return; - } -#endif /* TCP_LISTEN_BACKLOG */ - npcb = tcp_alloc(pcb->prio); - /* If a new PCB could not be created (probably due to lack of memory), - we don't do anything, but rely on the sender will retransmit the - SYN at a time when we have more memory available. */ - if (npcb == NULL) { - err_t err; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); - TCP_STATS_INC(tcp.memerr); - TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err); - LWIP_UNUSED_ARG(err); /* err not useful here */ - return; - } -#if TCP_LISTEN_BACKLOG - pcb->accepts_pending++; - npcb->flags |= TF_BACKLOGPEND; -#endif /* TCP_LISTEN_BACKLOG */ - /* Set up the new PCB. */ - ip_addr_copy(npcb->local_ip, *ip_current_dest_addr()); - ip_addr_copy(npcb->remote_ip, *ip_current_src_addr()); - npcb->local_port = pcb->local_port; - npcb->remote_port = tcphdr->src; - npcb->state = SYN_RCVD; - npcb->rcv_nxt = seqno + 1; - npcb->rcv_ann_right_edge = npcb->rcv_nxt; - iss = tcp_next_iss(npcb); - npcb->snd_wl2 = iss; - npcb->snd_nxt = iss; - npcb->lastack = iss; - npcb->snd_lbb = iss; - npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ - npcb->callback_arg = pcb->callback_arg; -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG - npcb->listener = pcb; -#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ - /* inherit socket options */ - npcb->so_options = pcb->so_options & SOF_INHERITED; - /* Register the new PCB so that we can begin receiving segments - for it. */ - TCP_REG_ACTIVE(npcb); - - /* Parse any options in the SYN. */ - tcp_parseopt(npcb); - npcb->snd_wnd = tcphdr->wnd; - npcb->snd_wnd_max = npcb->snd_wnd; - -#if TCP_CALCULATE_EFF_SEND_MSS - npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - - MIB2_STATS_INC(mib2.tcppassiveopens); - - /* Send a SYN|ACK together with the MSS option. */ - rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); - if (rc != ERR_OK) { - tcp_abandon(npcb, 0); - return; - } - tcp_output(npcb); - } - return; -} - -/** - * Called by tcp_input() when a segment arrives for a connection in - * TIME_WAIT. - * - * @param pcb the tcp_pcb for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static void -tcp_timewait_input(struct tcp_pcb *pcb) -{ - /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments */ - /* RFC 793 3.9 Event Processing - Segment Arrives: - * - first check sequence number - we skip that one in TIME_WAIT (always - * acceptable since we only send ACKs) - * - second check the RST bit (... return) */ - if (flags & TCP_RST) { - return; - } - /* - fourth, check the SYN bit, */ - if (flags & TCP_SYN) { - /* If an incoming segment is not acceptable, an acknowledgment - should be sent in reply */ - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) { - /* If the SYN is in the window it is an error, send a reset */ - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - return; - } - } else if (flags & TCP_FIN) { - /* - eighth, check the FIN bit: Remain in the TIME-WAIT state. - Restart the 2 MSL time-wait timeout.*/ - pcb->tmr = tcp_ticks; - } - - if ((tcplen > 0)) { - /* Acknowledge data, FIN or out-of-window SYN */ - pcb->flags |= TF_ACK_NOW; - tcp_output(pcb); - } - return; -} - -/** - * Implements the TCP state machine. Called by tcp_input. In some - * states tcp_receive() is called to receive data. The tcp_seg - * argument will be freed by the caller (tcp_input()) unless the - * recv_data pointer in the pcb is set. - * - * @param pcb the tcp_pcb for which a segment arrived - * - * @note the segment which arrived is saved in global variables, therefore only the pcb - * involved is passed as a parameter to this function - */ -static err_t -tcp_process(struct tcp_pcb *pcb) -{ - struct tcp_seg *rseg; - u8_t acceptable = 0; - err_t err; - - err = ERR_OK; - - /* Process incoming RST segments. */ - if (flags & TCP_RST) { - /* First, determine if the reset is acceptable. */ - if (pcb->state == SYN_SENT) { - /* "In the SYN-SENT state (a RST received in response to an initial SYN), - the RST is acceptable if the ACK field acknowledges the SYN." */ - if (ackno == pcb->snd_nxt) { - acceptable = 1; - } - } else { - /* "In all states except SYN-SENT, all reset (RST) segments are validated - by checking their SEQ-fields." */ - if (seqno == pcb->rcv_nxt) { - acceptable = 1; - } else if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt + pcb->rcv_wnd)) { - /* If the sequence number is inside the window, we only send an ACK - and wait for a re-send with matching sequence number. - This violates RFC 793, but is required to protection against - CVE-2004-0230 (RST spoofing attack). */ - tcp_ack_now(pcb); - } - } - - if (acceptable) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: Connection RESET\n")); - LWIP_ASSERT("tcp_input: pcb->state != CLOSED", pcb->state != CLOSED); - recv_flags |= TF_RESET; - pcb->flags &= ~TF_ACK_DELAY; - return ERR_RST; - } else { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", - seqno, pcb->rcv_nxt)); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_process: unacceptable reset seqno %"U32_F" rcv_nxt %"U32_F"\n", - seqno, pcb->rcv_nxt)); - return ERR_OK; - } - } - - if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { - /* Cope with new connection attempt after remote end crashed */ - tcp_ack_now(pcb); - return ERR_OK; - } - - if ((pcb->flags & TF_RXCLOSED) == 0) { - /* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */ - pcb->tmr = tcp_ticks; - } - pcb->keep_cnt_sent = 0; - - tcp_parseopt(pcb); - - /* Do different things depending on the TCP state. */ - switch (pcb->state) { - case SYN_SENT: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno, - pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno))); - /* received SYN ACK with expected sequence number? */ - if ((flags & TCP_ACK) && (flags & TCP_SYN) - && (ackno == pcb->lastack + 1)) { - pcb->rcv_nxt = seqno + 1; - pcb->rcv_ann_right_edge = pcb->rcv_nxt; - pcb->lastack = ackno; - pcb->snd_wnd = tcphdr->wnd; - pcb->snd_wnd_max = pcb->snd_wnd; - pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ - pcb->state = ESTABLISHED; - -#if TCP_CALCULATE_EFF_SEND_MSS - pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - - pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F - " ssthresh %"TCPWNDSIZE_F"\n", - pcb->cwnd, pcb->ssthresh)); - LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); - --pcb->snd_queuelen; - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); - rseg = pcb->unacked; - if (rseg == NULL) { - /* might happen if tcp_output fails in tcp_rexmit_rto() - in which case the segment is on the unsent list */ - rseg = pcb->unsent; - LWIP_ASSERT("no segment to free", rseg != NULL); - pcb->unsent = rseg->next; - } else { - pcb->unacked = rseg->next; - } - tcp_seg_free(rseg); - - /* If there's nothing left to acknowledge, stop the retransmit - timer, otherwise reset it to start again */ - if (pcb->unacked == NULL) { - pcb->rtime = -1; - } else { - pcb->rtime = 0; - pcb->nrtx = 0; - } - - /* Call the user specified function to call when successfully - * connected. */ - TCP_EVENT_CONNECTED(pcb, ERR_OK, err); - if (err == ERR_ABRT) { - return ERR_ABRT; - } - tcp_ack_now(pcb); - } - /* received ACK? possibly a half-open connection */ - else if (flags & TCP_ACK) { - /* send a RST to bring the other side in a non-synchronized state. */ - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - /* Resend SYN immediately (don't wait for rto timeout) to establish - connection faster, but do not send more SYNs than we otherwise would - have, or we might get caught in a loop on loopback interfaces. */ - if (pcb->nrtx < TCP_SYNMAXRTX) { - pcb->rtime = 0; - tcp_rexmit_rto(pcb); - } - } - break; - case SYN_RCVD: - if (flags & TCP_ACK) { - /* expected ACK number? */ - if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { - pcb->state = ESTABLISHED; - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG -#if LWIP_CALLBACK_API - LWIP_ASSERT("pcb->listener->accept != NULL", - (pcb->listener == NULL) || (pcb->listener->accept != NULL)); -#endif - if (pcb->listener == NULL) { - /* listen pcb might be closed by now */ - err = ERR_VAL; - } else -#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ - { - tcp_backlog_accepted(pcb); - /* Call the accept function. */ - TCP_EVENT_ACCEPT(pcb->listener, pcb, pcb->callback_arg, ERR_OK, err); - } - if (err != ERR_OK) { - /* If the accept function returns with an error, we abort - * the connection. */ - /* Already aborted? */ - if (err != ERR_ABRT) { - tcp_abort(pcb); - } - return ERR_ABRT; - } - /* If there was any data contained within this ACK, - * we'd better pass it on to the application as well. */ - tcp_receive(pcb); - - /* Prevent ACK for SYN to generate a sent event */ - if (recv_acked != 0) { - recv_acked--; - } - - pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss); - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SYN_RCVD): cwnd %"TCPWNDSIZE_F - " ssthresh %"TCPWNDSIZE_F"\n", - pcb->cwnd, pcb->ssthresh)); - - if (recv_flags & TF_GOT_FIN) { - tcp_ack_now(pcb); - pcb->state = CLOSE_WAIT; - } - } else { - /* incorrect ACK number, send RST */ - tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), - ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } - } else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) { - /* Looks like another copy of the SYN - retransmit our SYN-ACK */ - tcp_rexmit(pcb); - } - break; - case CLOSE_WAIT: - /* FALLTHROUGH */ - case ESTABLISHED: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { /* passive close */ - tcp_ack_now(pcb); - pcb->state = CLOSE_WAIT; - } - break; - case FIN_WAIT_1: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { - if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && - pcb->unsent == NULL) { - LWIP_DEBUGF(TCP_DEBUG, - ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } else { - tcp_ack_now(pcb); - pcb->state = CLOSING; - } - } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) && - pcb->unsent == NULL) { - pcb->state = FIN_WAIT_2; - } - break; - case FIN_WAIT_2: - tcp_receive(pcb); - if (recv_flags & TF_GOT_FIN) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_ack_now(pcb); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } - break; - case CLOSING: - tcp_receive(pcb); - if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - tcp_pcb_purge(pcb); - TCP_RMV_ACTIVE(pcb); - pcb->state = TIME_WAIT; - TCP_REG(&tcp_tw_pcbs, pcb); - } - break; - case LAST_ACK: - tcp_receive(pcb); - if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ - recv_flags |= TF_CLOSED; - } - break; - default: - break; - } - return ERR_OK; -} - -#if TCP_QUEUE_OOSEQ -/** - * Insert segment into the list (segments covered with new one will be deleted) - * - * Called from tcp_receive() - */ -static void -tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next) -{ - struct tcp_seg *old_seg; - - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - /* received segment overlaps all following segments */ - tcp_segs_free(next); - next = NULL; - } else { - /* delete some following segments - oos queue may have segments with FIN flag */ - while (next && - TCP_SEQ_GEQ((seqno + cseg->len), - (next->tcphdr->seqno + next->len))) { - /* cseg with FIN already processed */ - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { - TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN); - } - old_seg = next; - next = next->next; - tcp_seg_free(old_seg); - } - if (next && - TCP_SEQ_GT(seqno + cseg->len, next->tcphdr->seqno)) { - /* We need to trim the incoming segment. */ - cseg->len = (u16_t)(next->tcphdr->seqno - seqno); - pbuf_realloc(cseg->p, cseg->len); - } - } - cseg->next = next; -} -#endif /* TCP_QUEUE_OOSEQ */ - -/** - * Called by tcp_process. Checks if the given segment is an ACK for outstanding - * data, and if so frees the memory of the buffered data. Next, it places the - * segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment - * is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until - * it has been removed from the buffer. - * - * If the incoming segment constitutes an ACK for a segment that was used for RTT - * estimation, the RTT is estimated here as well. - * - * Called from tcp_process(). - */ -static void -tcp_receive(struct tcp_pcb *pcb) -{ - struct tcp_seg *next; -#if TCP_QUEUE_OOSEQ - struct tcp_seg *prev, *cseg; -#endif /* TCP_QUEUE_OOSEQ */ - s32_t off; - s16_t m; - u32_t right_wnd_edge; - u16_t new_tot_len; - int found_dupack = 0; -#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS - u32_t ooseq_blen; - u16_t ooseq_qlen; -#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ - - LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED); - - if (flags & TCP_ACK) { - right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; - - /* Update window. */ - if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || - (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || - (pcb->snd_wl2 == ackno && (u32_t)SND_WND_SCALE(pcb, tcphdr->wnd) > pcb->snd_wnd)) { - pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd); - /* keep track of the biggest window announced by the remote host to calculate - the maximum segment size */ - if (pcb->snd_wnd_max < pcb->snd_wnd) { - pcb->snd_wnd_max = pcb->snd_wnd; - } - pcb->snd_wl1 = seqno; - pcb->snd_wl2 = ackno; - if (pcb->snd_wnd == 0) { - if (pcb->persist_backoff == 0) { - /* start persist timer */ - pcb->persist_cnt = 0; - pcb->persist_backoff = 1; - } - } else if (pcb->persist_backoff > 0) { - /* stop persist timer */ - pcb->persist_backoff = 0; - } - LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"TCPWNDSIZE_F"\n", pcb->snd_wnd)); -#if TCP_WND_DEBUG - } else { - if (pcb->snd_wnd != (tcpwnd_size_t)SND_WND_SCALE(pcb, tcphdr->wnd)) { - LWIP_DEBUGF(TCP_WND_DEBUG, - ("tcp_receive: no window update lastack %"U32_F" ackno %" - U32_F" wl1 %"U32_F" seqno %"U32_F" wl2 %"U32_F"\n", - pcb->lastack, ackno, pcb->snd_wl1, seqno, pcb->snd_wl2)); - } -#endif /* TCP_WND_DEBUG */ - } - - /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a - * duplicate ack if: - * 1) It doesn't ACK new data - * 2) length of received packet is zero (i.e. no payload) - * 3) the advertised window hasn't changed - * 4) There is outstanding unacknowledged data (retransmission timer running) - * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) - * - * If it passes all five, should process as a dupack: - * a) dupacks < 3: do nothing - * b) dupacks == 3: fast retransmit - * c) dupacks > 3: increase cwnd - * - * If it only passes 1-3, should reset dupack counter (and add to - * stats, which we don't do in lwIP) - * - * If it only passes 1, should reset dupack counter - * - */ - - /* Clause 1 */ - if (TCP_SEQ_LEQ(ackno, pcb->lastack)) { - /* Clause 2 */ - if (tcplen == 0) { - /* Clause 3 */ - if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) { - /* Clause 4 */ - if (pcb->rtime >= 0) { - /* Clause 5 */ - if (pcb->lastack == ackno) { - found_dupack = 1; - if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) { - ++pcb->dupacks; - } - if (pcb->dupacks > 3) { - /* Inflate the congestion window, but not if it means that - the value overflows. */ - if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - } else if (pcb->dupacks == 3) { - /* Do fast retransmit */ - tcp_rexmit_fast(pcb); - } - } - } - } - } - /* If Clause (1) or more is true, but not a duplicate ack, reset - * count of consecutive duplicate acks */ - if (!found_dupack) { - pcb->dupacks = 0; - } - } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { - /* We come here when the ACK acknowledges new data. */ - - /* Reset the "IN Fast Retransmit" flag, since we are no longer - in fast retransmit. Also reset the congestion window to the - slow start threshold. */ - if (pcb->flags & TF_INFR) { - pcb->flags &= ~TF_INFR; - pcb->cwnd = pcb->ssthresh; - } - - /* Reset the number of retransmissions. */ - pcb->nrtx = 0; - - /* Reset the retransmission time-out. */ - pcb->rto = (pcb->sa >> 3) + pcb->sv; - - /* Reset the fast retransmit variables. */ - pcb->dupacks = 0; - pcb->lastack = ackno; - - /* Update the congestion control variables (cwnd and - ssthresh). */ - if (pcb->state >= ESTABLISHED) { - if (pcb->cwnd < pcb->ssthresh) { - if ((tcpwnd_size_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { - pcb->cwnd += pcb->mss; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: slow start cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); - } else { - tcpwnd_size_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd); - if (new_cwnd > pcb->cwnd) { - pcb->cwnd = new_cwnd; - } - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_receive: congestion avoidance cwnd %"TCPWNDSIZE_F"\n", pcb->cwnd)); - } - } - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n", - ackno, - pcb->unacked != NULL? - lwip_ntohl(pcb->unacked->tcphdr->seqno): 0, - pcb->unacked != NULL? - lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0)); - - /* Remove segment from the unacknowledged list if the incoming - ACK acknowledges them. */ - while (pcb->unacked != NULL && - TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked), ackno)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n", - lwip_ntohl(pcb->unacked->tcphdr->seqno), - lwip_ntohl(pcb->unacked->tcphdr->seqno) + - TCP_TCPLEN(pcb->unacked))); - - next = pcb->unacked; - pcb->unacked = pcb->unacked->next; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); - LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); - - pcb->snd_queuelen -= pbuf_clen(next->p); - recv_acked += next->len; - tcp_seg_free(next); - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unacked)\n", (tcpwnd_size_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - } - - /* If there's nothing left to acknowledge, stop the retransmit - timer, otherwise reset it to start again */ - if (pcb->unacked == NULL) { - pcb->rtime = -1; - } else { - pcb->rtime = 0; - } - - pcb->polltmr = 0; - -#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS - if (ip_current_is_v6()) { - /* Inform neighbor reachability of forward progress. */ - nd6_reachability_hint(ip6_current_src_addr()); - } -#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ - } else { - /* Out of sequence ACK, didn't really ack anything */ - tcp_send_empty_ack(pcb); - } - - /* We go through the ->unsent list to see if any of the segments - on the list are acknowledged by the ACK. This may seem - strange since an "unsent" segment shouldn't be acked. The - rationale is that lwIP puts all outstanding segments on the - ->unsent list after a retransmission, so these segments may - in fact have been sent once. */ - while (pcb->unsent != NULL && - TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n", - lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) + - TCP_TCPLEN(pcb->unsent))); - - next = pcb->unsent; - pcb->unsent = pcb->unsent->next; -#if TCP_OVERSIZE - if (pcb->unsent == NULL) { - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"TCPWNDSIZE_F" ... ", (tcpwnd_size_t)pcb->snd_queuelen)); - LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); - /* Prevent ACK for FIN to generate a sent event */ - pcb->snd_queuelen -= pbuf_clen(next->p); - recv_acked += next->len; - tcp_seg_free(next); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"TCPWNDSIZE_F" (after freeing unsent)\n", (tcpwnd_size_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_receive: valid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - } - pcb->snd_buf += recv_acked; - /* End of ACK for new data processing. */ - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: pcb->rttest %"U32_F" rtseq %"U32_F" ackno %"U32_F"\n", - pcb->rttest, pcb->rtseq, ackno)); - - /* RTT estimation calculations. This is done by checking if the - incoming segment acknowledges the segment we use to take a - round-trip time measurement. */ - if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) { - /* diff between this shouldn't exceed 32K since this are tcp timer ticks - and a round-trip shouldn't be that long... */ - m = (s16_t)(tcp_ticks - pcb->rttest); - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", - m, (u16_t)(m * TCP_SLOW_INTERVAL))); - - /* This is taken directly from VJs original code in his paper */ - m = m - (pcb->sa >> 3); - pcb->sa += m; - if (m < 0) { - m = -m; - } - m = m - (pcb->sv >> 2); - pcb->sv += m; - pcb->rto = (pcb->sa >> 3) + pcb->sv; - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: RTO %"U16_F" (%"U16_F" milliseconds)\n", - pcb->rto, (u16_t)(pcb->rto * TCP_SLOW_INTERVAL))); - - pcb->rttest = 0; - } - } - - /* If the incoming segment contains data, we must process it - further unless the pcb already received a FIN. - (RFC 793, chapter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING, - LAST-ACK and TIME-WAIT: "Ignore the segment text.") */ - if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) { - /* This code basically does three things: - - +) If the incoming segment contains data that is the next - in-sequence data, this data is passed to the application. This - might involve trimming the first edge of the data. The rcv_nxt - variable and the advertised window are adjusted. - - +) If the incoming segment has data that is above the next - sequence number expected (->rcv_nxt), the segment is placed on - the ->ooseq queue. This is done by finding the appropriate - place in the ->ooseq queue (which is ordered by sequence - number) and trim the segment in both ends if needed. An - immediate ACK is sent to indicate that we received an - out-of-sequence segment. - - +) Finally, we check if the first segment on the ->ooseq queue - now is in sequence (i.e., if rcv_nxt >= ooseq->seqno). If - rcv_nxt > ooseq->seqno, we must trim the first edge of the - segment on ->ooseq before we adjust rcv_nxt. The data in the - segments that are now on sequence are chained onto the - incoming segment so that we only need to call the application - once. - */ - - /* First, we check if we must trim the first edge. We have to do - this if the sequence number of the incoming segment is less - than rcv_nxt, and the sequence number plus the length of the - segment is larger than rcv_nxt. */ - /* if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { - if (TCP_SEQ_LT(pcb->rcv_nxt, seqno + tcplen)) {*/ - if (TCP_SEQ_BETWEEN(pcb->rcv_nxt, seqno + 1, seqno + tcplen - 1)) { - /* Trimming the first edge is done by pushing the payload - pointer in the pbuf downwards. This is somewhat tricky since - we do not want to discard the full contents of the pbuf up to - the new starting point of the data since we have to keep the - TCP header which is present in the first pbuf in the chain. - - What is done is really quite a nasty hack: the first pbuf in - the pbuf chain is pointed to by inseg.p. Since we need to be - able to deallocate the whole pbuf, we cannot change this - inseg.p pointer to point to any of the later pbufs in the - chain. Instead, we point the ->payload pointer in the first - pbuf to data in one of the later pbufs. We also set the - inseg.data pointer to point to the right place. This way, the - ->p pointer will still point to the first pbuf, but the - ->p->payload pointer will point to data in another pbuf. - - After we are done with adjusting the pbuf pointers we must - adjust the ->data pointer in the seg and the segment - length.*/ - - struct pbuf *p = inseg.p; - off = pcb->rcv_nxt - seqno; - LWIP_ASSERT("inseg.p != NULL", inseg.p); - LWIP_ASSERT("insane offset!", (off < 0x7fff)); - if (inseg.p->len < off) { - LWIP_ASSERT("pbuf too short!", (((s32_t)inseg.p->tot_len) >= off)); - new_tot_len = (u16_t)(inseg.p->tot_len - off); - while (p->len < off) { - off -= p->len; - /* KJM following line changed (with addition of new_tot_len var) - to fix bug #9076 - inseg.p->tot_len -= p->len; */ - p->tot_len = new_tot_len; - p->len = 0; - p = p->next; - } - if (pbuf_header(p, (s16_t)-off)) { - /* Do we need to cope with this failing? Assert for now */ - LWIP_ASSERT("pbuf_header failed", 0); - } - } else { - if (pbuf_header(inseg.p, (s16_t)-off)) { - /* Do we need to cope with this failing? Assert for now */ - LWIP_ASSERT("pbuf_header failed", 0); - } - } - inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); - inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; - } - else { - if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)) { - /* the whole segment is < rcv_nxt */ - /* must be a duplicate of a packet that has already been correctly handled */ - - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); - tcp_ack_now(pcb); - } - } - - /* The sequence number must be within the window (above rcv_nxt - and below rcv_nxt + rcv_wnd) in order to be further - processed. */ - if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt + pcb->rcv_wnd - 1)) { - if (pcb->rcv_nxt == seqno) { - /* The incoming segment is the next in sequence. We check if - we have to trim the end of the segment and update rcv_nxt - and pass the data to the application. */ - tcplen = TCP_TCPLEN(&inseg); - - if (tcplen > pcb->rcv_wnd) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: other end overran receive window" - "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", - seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - /* Must remove the FIN from the header as we're trimming - * that byte of sequence-space from the packet */ - TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS(inseg.tcphdr) & ~(unsigned int)TCP_FIN); - } - /* Adjust length of segment to fit in the window. */ - TCPWND_CHECK16(pcb->rcv_wnd); - inseg.len = (u16_t)pcb->rcv_wnd; - if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { - inseg.len -= 1; - } - pbuf_realloc(inseg.p, inseg.len); - tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", - (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); - } -#if TCP_QUEUE_OOSEQ - /* Received in-sequence data, adjust ooseq data if: - - FIN has been received or - - inseq overlaps with ooseq */ - if (pcb->ooseq != NULL) { - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: received in-order FIN, binning ooseq queue\n")); - /* Received in-order FIN means anything that was received - * out of order must now have been received in-order, so - * bin the ooseq queue */ - while (pcb->ooseq != NULL) { - struct tcp_seg *old_ooseq = pcb->ooseq; - pcb->ooseq = pcb->ooseq->next; - tcp_seg_free(old_ooseq); - } - } else { - next = pcb->ooseq; - /* Remove all segments on ooseq that are covered by inseg already. - * FIN is copied from ooseq to inseg if present. */ - while (next && - TCP_SEQ_GEQ(seqno + tcplen, - next->tcphdr->seqno + next->len)) { - /* inseg cannot have FIN here (already processed above) */ - if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 && - (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { - TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN); - tcplen = TCP_TCPLEN(&inseg); - } - prev = next; - next = next->next; - tcp_seg_free(prev); - } - /* Now trim right side of inseg if it overlaps with the first - * segment on ooseq */ - if (next && - TCP_SEQ_GT(seqno + tcplen, - next->tcphdr->seqno)) { - /* inseg cannot have FIN here (already processed above) */ - inseg.len = (u16_t)(next->tcphdr->seqno - seqno); - if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { - inseg.len -= 1; - } - pbuf_realloc(inseg.p, inseg.len); - tcplen = TCP_TCPLEN(&inseg); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n", - (seqno + tcplen) == next->tcphdr->seqno); - } - pcb->ooseq = next; - } - } -#endif /* TCP_QUEUE_OOSEQ */ - - pcb->rcv_nxt = seqno + tcplen; - - /* Update the receiver's (our) window. */ - LWIP_ASSERT("tcp_receive: tcplen > rcv_wnd\n", pcb->rcv_wnd >= tcplen); - pcb->rcv_wnd -= tcplen; - - tcp_update_rcv_ann_wnd(pcb); - - /* If there is data in the segment, we make preparations to - pass this up to the application. The ->recv_data variable - is used for holding the pbuf that goes to the - application. The code for reassembling out-of-sequence data - chains its data on this pbuf as well. - - If the segment was a FIN, we set the TF_GOT_FIN flag that will - be used to indicate to the application that the remote side has - closed its end of the connection. */ - if (inseg.p->tot_len > 0) { - recv_data = inseg.p; - /* Since this pbuf now is the responsibility of the - application, we delete our reference to it so that we won't - (mistakingly) deallocate it. */ - inseg.p = NULL; - } - if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n")); - recv_flags |= TF_GOT_FIN; - } - -#if TCP_QUEUE_OOSEQ - /* We now check if we have segments on the ->ooseq queue that - are now in sequence. */ - while (pcb->ooseq != NULL && - pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) { - - cseg = pcb->ooseq; - seqno = pcb->ooseq->tcphdr->seqno; - - pcb->rcv_nxt += TCP_TCPLEN(cseg); - LWIP_ASSERT("tcp_receive: ooseq tcplen > rcv_wnd\n", - pcb->rcv_wnd >= TCP_TCPLEN(cseg)); - pcb->rcv_wnd -= TCP_TCPLEN(cseg); - - tcp_update_rcv_ann_wnd(pcb); - - if (cseg->p->tot_len > 0) { - /* Chain this pbuf onto the pbuf that we will pass to - the application. */ - /* With window scaling, this can overflow recv_data->tot_len, but - that's not a problem since we explicitly fix that before passing - recv_data to the application. */ - if (recv_data) { - pbuf_cat(recv_data, cseg->p); - } else { - recv_data = cseg->p; - } - cseg->p = NULL; - } - if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n")); - recv_flags |= TF_GOT_FIN; - if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */ - pcb->state = CLOSE_WAIT; - } - } - - pcb->ooseq = cseg->next; - tcp_seg_free(cseg); - } -#endif /* TCP_QUEUE_OOSEQ */ - - - /* Acknowledge the segment(s). */ - tcp_ack(pcb); - -#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS - if (ip_current_is_v6()) { - /* Inform neighbor reachability of forward progress. */ - nd6_reachability_hint(ip6_current_src_addr()); - } -#endif /* LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS*/ - - } else { - /* We get here if the incoming segment is out-of-sequence. */ - tcp_send_empty_ack(pcb); -#if TCP_QUEUE_OOSEQ - /* We queue the segment on the ->ooseq queue. */ - if (pcb->ooseq == NULL) { - pcb->ooseq = tcp_seg_copy(&inseg); - } else { - /* If the queue is not empty, we walk through the queue and - try to find a place where the sequence number of the - incoming segment is between the sequence numbers of the - previous and the next segment on the ->ooseq queue. That is - the place where we put the incoming segment. If needed, we - trim the second edges of the previous and the incoming - segment so that it will fit into the sequence. - - If the incoming segment has the same sequence number as a - segment on the ->ooseq queue, we discard the segment that - contains less data. */ - - prev = NULL; - for (next = pcb->ooseq; next != NULL; next = next->next) { - if (seqno == next->tcphdr->seqno) { - /* The sequence number of the incoming segment is the - same as the sequence number of the segment on - ->ooseq. We check the lengths to see which one to - discard. */ - if (inseg.len > next->len) { - /* The incoming segment is larger than the old - segment. We replace some segments with the new - one. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - if (prev != NULL) { - prev->next = cseg; - } else { - pcb->ooseq = cseg; - } - tcp_oos_insert_segment(cseg, next); - } - break; - } else { - /* Either the lengths are the same or the incoming - segment was smaller than the old one; in either - case, we ditch the incoming segment. */ - break; - } - } else { - if (prev == NULL) { - if (TCP_SEQ_LT(seqno, next->tcphdr->seqno)) { - /* The sequence number of the incoming segment is lower - than the sequence number of the first segment on the - queue. We put the incoming segment first on the - queue. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - pcb->ooseq = cseg; - tcp_oos_insert_segment(cseg, next); - } - break; - } - } else { - /*if (TCP_SEQ_LT(prev->tcphdr->seqno, seqno) && - TCP_SEQ_LT(seqno, next->tcphdr->seqno)) {*/ - if (TCP_SEQ_BETWEEN(seqno, prev->tcphdr->seqno+1, next->tcphdr->seqno-1)) { - /* The sequence number of the incoming segment is in - between the sequence numbers of the previous and - the next segment on ->ooseq. We trim trim the previous - segment, delete next segments that included in received segment - and trim received, if needed. */ - cseg = tcp_seg_copy(&inseg); - if (cseg != NULL) { - if (TCP_SEQ_GT(prev->tcphdr->seqno + prev->len, seqno)) { - /* We need to trim the prev segment. */ - prev->len = (u16_t)(seqno - prev->tcphdr->seqno); - pbuf_realloc(prev->p, prev->len); - } - prev->next = cseg; - tcp_oos_insert_segment(cseg, next); - } - break; - } - } - /* If the "next" segment is the last segment on the - ooseq queue, we add the incoming segment to the end - of the list. */ - if (next->next == NULL && - TCP_SEQ_GT(seqno, next->tcphdr->seqno)) { - if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) { - /* segment "next" already contains all data */ - break; - } - next->next = tcp_seg_copy(&inseg); - if (next->next != NULL) { - if (TCP_SEQ_GT(next->tcphdr->seqno + next->len, seqno)) { - /* We need to trim the last segment. */ - next->len = (u16_t)(seqno - next->tcphdr->seqno); - pbuf_realloc(next->p, next->len); - } - /* check if the remote side overruns our receive window */ - if (TCP_SEQ_GT((u32_t)tcplen + seqno, pcb->rcv_nxt + (u32_t)pcb->rcv_wnd)) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, - ("tcp_receive: other end overran receive window" - "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", - seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd)); - if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) { - /* Must remove the FIN from the header as we're trimming - * that byte of sequence-space from the packet */ - TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) & ~TCP_FIN); - } - /* Adjust length of segment to fit in the window. */ - next->next->len = (u16_t)(pcb->rcv_nxt + pcb->rcv_wnd - seqno); - pbuf_realloc(next->next->p, next->next->len); - tcplen = TCP_TCPLEN(next->next); - LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n", - (seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd)); - } - } - break; - } - } - prev = next; - } - } -#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS - /* Check that the data on ooseq doesn't exceed one of the limits - and throw away everything above that limit. */ - ooseq_blen = 0; - ooseq_qlen = 0; - prev = NULL; - for (next = pcb->ooseq; next != NULL; prev = next, next = next->next) { - struct pbuf *p = next->p; - ooseq_blen += p->tot_len; - ooseq_qlen += pbuf_clen(p); - if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) || - (ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) { - /* too much ooseq data, dump this and everything after it */ - tcp_segs_free(next); - if (prev == NULL) { - /* first ooseq segment is too much, dump the whole queue */ - pcb->ooseq = NULL; - } else { - /* just dump 'next' and everything after it */ - prev->next = NULL; - } - break; - } - } -#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */ -#endif /* TCP_QUEUE_OOSEQ */ - } - } else { - /* The incoming segment is not within the window. */ - tcp_send_empty_ack(pcb); - } - } else { - /* Segments with length 0 is taken care of here. Segments that - fall out of the window are ACKed. */ - if (!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)) { - tcp_ack_now(pcb); - } - } -} - -static u8_t -tcp_getoptbyte(void) -{ - if ((tcphdr_opt2 == NULL) || (tcp_optidx < tcphdr_opt1len)) { - u8_t* opts = (u8_t *)tcphdr + TCP_HLEN; - return opts[tcp_optidx++]; - } else { - u8_t idx = (u8_t)(tcp_optidx++ - tcphdr_opt1len); - return tcphdr_opt2[idx]; - } -} - -/** - * Parses the options contained in the incoming segment. - * - * Called from tcp_listen_input() and tcp_process(). - * Currently, only the MSS option is supported! - * - * @param pcb the tcp_pcb for which a segment arrived - */ -static void -tcp_parseopt(struct tcp_pcb *pcb) -{ - u8_t data; - u16_t mss; -#if LWIP_TCP_TIMESTAMPS - u32_t tsval; -#endif - - /* Parse the TCP MSS option, if present. */ - if (tcphdr_optlen != 0) { - for (tcp_optidx = 0; tcp_optidx < tcphdr_optlen; ) { - u8_t opt = tcp_getoptbyte(); - switch (opt) { - case LWIP_TCP_OPT_EOL: - /* End of options. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: EOL\n")); - return; - case LWIP_TCP_OPT_NOP: - /* NOP option. */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: NOP\n")); - break; - case LWIP_TCP_OPT_MSS: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: MSS\n")); - if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_MSS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_MSS) > tcphdr_optlen) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* An MSS option with the right option length. */ - mss = (tcp_getoptbyte() << 8); - mss |= tcp_getoptbyte(); - /* Limit the mss to the configured TCP_MSS and prevent division by zero */ - pcb->mss = ((mss > TCP_MSS) || (mss == 0)) ? TCP_MSS : mss; - break; -#if LWIP_WND_SCALE - case LWIP_TCP_OPT_WS: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: WND_SCALE\n")); - if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_WS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_WS) > tcphdr_optlen) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* If syn was received with wnd scale option, - activate wnd scale opt, but only if this is not a retransmission */ - if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) { - /* An WND_SCALE option with the right option length. */ - data = tcp_getoptbyte(); - pcb->snd_scale = data; - if (pcb->snd_scale > 14U) { - pcb->snd_scale = 14U; - } - pcb->rcv_scale = TCP_RCV_SCALE; - pcb->flags |= TF_WND_SCALE; - /* window scaling is enabled, we can use the full receive window */ - LWIP_ASSERT("window not at default value", pcb->rcv_wnd == TCPWND_MIN16(TCP_WND)); - LWIP_ASSERT("window not at default value", pcb->rcv_ann_wnd == TCPWND_MIN16(TCP_WND)); - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCP_WND; - } - break; -#endif -#if LWIP_TCP_TIMESTAMPS - case LWIP_TCP_OPT_TS: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: TS\n")); - if (tcp_getoptbyte() != LWIP_TCP_OPT_LEN_TS || (tcp_optidx - 2 + LWIP_TCP_OPT_LEN_TS) > tcphdr_optlen) { - /* Bad length */ - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - return; - } - /* TCP timestamp option with valid length */ - tsval = tcp_getoptbyte(); - tsval |= (tcp_getoptbyte() << 8); - tsval |= (tcp_getoptbyte() << 16); - tsval |= (tcp_getoptbyte() << 24); - if (flags & TCP_SYN) { - pcb->ts_recent = lwip_ntohl(tsval); - /* Enable sending timestamps in every segment now that we know - the remote host supports it. */ - pcb->flags |= TF_TIMESTAMP; - } else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) { - pcb->ts_recent = lwip_ntohl(tsval); - } - /* Advance to next option (6 bytes already read) */ - tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6; - break; -#endif - default: - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: other\n")); - data = tcp_getoptbyte(); - if (data < 2) { - LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n")); - /* If the length field is zero, the options are malformed - and we don't process them further. */ - return; - } - /* All other options have a length field, so that we easily - can skip past them. */ - tcp_optidx += data - 2; - } - } - } -} - -void -tcp_trigger_input_pcb_close(void) -{ - recv_flags |= TF_CLOSED; -} - -#endif /* LWIP_TCP */ diff --git a/components/net/lwip-2.0.2/src/core/tcp_out.c b/components/net/lwip-2.0.2/src/core/tcp_out.c deleted file mode 100644 index 2435408aeb..0000000000 --- a/components/net/lwip-2.0.2/src/core/tcp_out.c +++ /dev/null @@ -1,1671 +0,0 @@ -/** - * @file - * Transmission Control Protocol, outgoing traffic - * - * The output functions of TCP. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/priv/tcp_priv.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/memp.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/inet_chksum.h" -#include "lwip/stats.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#if LWIP_TCP_TIMESTAMPS -#include "lwip/sys.h" -#endif - -#include - -/* Define some copy-macros for checksum-on-copy so that the code looks - nicer by preventing too many ifdef's. */ -#if TCP_CHECKSUM_ON_COPY -#define TCP_DATA_COPY(dst, src, len, seg) do { \ - tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), \ - len, &seg->chksum, &seg->chksum_swapped); \ - seg->flags |= TF_SEG_DATA_CHECKSUMMED; } while(0) -#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) \ - tcp_seg_add_chksum(LWIP_CHKSUM_COPY(dst, src, len), len, chksum, chksum_swapped); -#else /* TCP_CHECKSUM_ON_COPY*/ -#define TCP_DATA_COPY(dst, src, len, seg) MEMCPY(dst, src, len) -#define TCP_DATA_COPY2(dst, src, len, chksum, chksum_swapped) MEMCPY(dst, src, len) -#endif /* TCP_CHECKSUM_ON_COPY*/ - -/** Define this to 1 for an extra check that the output checksum is valid - * (usefule when the checksum is generated by the application, not the stack) */ -#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK -#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 0 -#endif -/* Allow to override the failure of sanity check from warning to e.g. hard failure */ -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK -#ifndef TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL -#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(msg) LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, msg) -#endif -#endif - -#if TCP_OVERSIZE -/** The size of segment pbufs created when TCP_OVERSIZE is enabled */ -#ifndef TCP_OVERSIZE_CALC_LENGTH -#define TCP_OVERSIZE_CALC_LENGTH(length) ((length) + TCP_OVERSIZE) -#endif -#endif - -/* Forward declarations.*/ -static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif); - -/** Allocate a pbuf and create a tcphdr at p->payload, used for output - * functions other than the default tcp_output -> tcp_output_segment - * (e.g. tcp_send_empty_ack, etc.) - * - * @param pcb tcp pcb for which to send a packet (used to initialize tcp_hdr) - * @param optlen length of header-options - * @param datalen length of tcp data to reserve in pbuf - * @param seqno_be seqno in network byte order (big-endian) - * @return pbuf with p->payload being the tcp_hdr - */ -static struct pbuf * -tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen, - u32_t seqno_be /* already in network byte order */) -{ - struct tcp_hdr *tcphdr; - struct pbuf *p = pbuf_alloc(PBUF_IP, TCP_HLEN + optlen + datalen, PBUF_RAM); - if (p != NULL) { - LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", - (p->len >= TCP_HLEN + optlen)); - tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = lwip_htons(pcb->local_port); - tcphdr->dest = lwip_htons(pcb->remote_port); - tcphdr->seqno = seqno_be; - tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); - TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK); - tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); - tcphdr->chksum = 0; - tcphdr->urgp = 0; - - /* If we're sending a packet, update the announced right window edge */ - pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; - } - return p; -} - -/** - * Called by tcp_close() to send a segment including FIN flag but not data. - * - * @param pcb the tcp_pcb over which to send a segment - * @return ERR_OK if sent, another err_t otherwise - */ -err_t -tcp_send_fin(struct tcp_pcb *pcb) -{ - /* first, try to add the fin to the last unsent segment */ - if (pcb->unsent != NULL) { - struct tcp_seg *last_unsent; - for (last_unsent = pcb->unsent; last_unsent->next != NULL; - last_unsent = last_unsent->next); - - if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) { - /* no SYN/FIN/RST flag in the header, we can add the FIN flag */ - TCPH_SET_FLAG(last_unsent->tcphdr, TCP_FIN); - pcb->flags |= TF_FIN; - return ERR_OK; - } - } - /* no data, no length, flags, copy=1, no optdata */ - return tcp_enqueue_flags(pcb, TCP_FIN); -} - -/** - * Create a TCP segment with prefilled header. - * - * Called by tcp_write and tcp_enqueue_flags. - * - * @param pcb Protocol control block for the TCP connection. - * @param p pbuf that is used to hold the TCP header. - * @param flags TCP flags for header. - * @param seqno TCP sequence number of this packet - * @param optflags options to include in TCP header - * @return a new tcp_seg pointing to p, or NULL. - * The TCP header is filled in except ackno and wnd. - * p is freed on failure. - */ -static struct tcp_seg * -tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, u8_t optflags) -{ - struct tcp_seg *seg; - u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags); - - if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n")); - pbuf_free(p); - return NULL; - } - seg->flags = optflags; - seg->next = NULL; - seg->p = p; - LWIP_ASSERT("p->tot_len >= optlen", p->tot_len >= optlen); - seg->len = p->tot_len - optlen; -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = 0; -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - seg->chksum = 0; - seg->chksum_swapped = 0; - /* check optflags */ - LWIP_ASSERT("invalid optflags passed: TF_SEG_DATA_CHECKSUMMED", - (optflags & TF_SEG_DATA_CHECKSUMMED) == 0); -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* build TCP header */ - if (pbuf_header(p, TCP_HLEN)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no room for TCP header in pbuf.\n")); - TCP_STATS_INC(tcp.err); - tcp_seg_free(seg); - return NULL; - } - seg->tcphdr = (struct tcp_hdr *)seg->p->payload; - seg->tcphdr->src = lwip_htons(pcb->local_port); - seg->tcphdr->dest = lwip_htons(pcb->remote_port); - seg->tcphdr->seqno = lwip_htonl(seqno); - /* ackno is set in tcp_output */ - TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags); - /* wnd and chksum are set in tcp_output */ - seg->tcphdr->urgp = 0; - return seg; -} - -/** - * Allocate a PBUF_RAM pbuf, perhaps with extra space at the end. - * - * This function is like pbuf_alloc(layer, length, PBUF_RAM) except - * there may be extra bytes available at the end. - * - * @param layer flag to define header size. - * @param length size of the pbuf's payload. - * @param max_length maximum usable size of payload+oversize. - * @param oversize pointer to a u16_t that will receive the number of usable tail bytes. - * @param pcb The TCP connection that will enqueue the pbuf. - * @param apiflags API flags given to tcp_write. - * @param first_seg true when this pbuf will be used in the first enqueued segment. - */ -#if TCP_OVERSIZE -static struct pbuf * -tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length, - u16_t *oversize, struct tcp_pcb *pcb, u8_t apiflags, - u8_t first_seg) -{ - struct pbuf *p; - u16_t alloc = length; - -#if LWIP_NETIF_TX_SINGLE_PBUF - LWIP_UNUSED_ARG(max_length); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(apiflags); - LWIP_UNUSED_ARG(first_seg); - alloc = max_length; -#else /* LWIP_NETIF_TX_SINGLE_PBUF */ - if (length < max_length) { - /* Should we allocate an oversized pbuf, or just the minimum - * length required? If tcp_write is going to be called again - * before this segment is transmitted, we want the oversized - * buffer. If the segment will be transmitted immediately, we can - * save memory by allocating only length. We use a simple - * heuristic based on the following information: - * - * Did the user set TCP_WRITE_FLAG_MORE? - * - * Will the Nagle algorithm defer transmission of this segment? - */ - if ((apiflags & TCP_WRITE_FLAG_MORE) || - (!(pcb->flags & TF_NODELAY) && - (!first_seg || - pcb->unsent != NULL || - pcb->unacked != NULL))) { - alloc = LWIP_MIN(max_length, LWIP_MEM_ALIGN_SIZE(TCP_OVERSIZE_CALC_LENGTH(length))); - } - } -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - p = pbuf_alloc(layer, alloc, PBUF_RAM); - if (p == NULL) { - return NULL; - } - LWIP_ASSERT("need unchained pbuf", p->next == NULL); - *oversize = p->len - length; - /* trim p->len to the currently used size */ - p->len = p->tot_len = length; - return p; -} -#else /* TCP_OVERSIZE */ -#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM) -#endif /* TCP_OVERSIZE */ - -#if TCP_CHECKSUM_ON_COPY -/** Add a checksum of newly added data to the segment */ -static void -tcp_seg_add_chksum(u16_t chksum, u16_t len, u16_t *seg_chksum, - u8_t *seg_chksum_swapped) -{ - u32_t helper; - /* add chksum to old chksum and fold to u16_t */ - helper = chksum + *seg_chksum; - chksum = FOLD_U32T(helper); - if ((len & 1) != 0) { - *seg_chksum_swapped = 1 - *seg_chksum_swapped; - chksum = SWAP_BYTES_IN_WORD(chksum); - } - *seg_chksum = chksum; -} -#endif /* TCP_CHECKSUM_ON_COPY */ - -/** Checks if tcp_write is allowed or not (checks state, snd_buf and snd_queuelen). - * - * @param pcb the tcp pcb to check for - * @param len length of data to send (checked agains snd_buf) - * @return ERR_OK if tcp_write is allowed to proceed, another err_t otherwise - */ -static err_t -tcp_write_checks(struct tcp_pcb *pcb, u16_t len) -{ - /* connection is in invalid state for data transmission? */ - if ((pcb->state != ESTABLISHED) && - (pcb->state != CLOSE_WAIT) && - (pcb->state != SYN_SENT) && - (pcb->state != SYN_RCVD)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n")); - return ERR_CONN; - } else if (len == 0) { - return ERR_OK; - } - - /* fail on too much data */ - if (len > pcb->snd_buf) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too much data (len=%"U16_F" > snd_buf=%"TCPWNDSIZE_F")\n", - len, pcb->snd_buf)); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: queuelen: %"TCPWNDSIZE_F"\n", (tcpwnd_size_t)pcb->snd_queuelen)); - - /* If total number of pbufs on the unsent/unacked queues exceeds the - * configured maximum, return an error */ - /* check for configured max queuelen and possible overflow */ - if ((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_write: too long queue %"U16_F" (max %"U16_F")\n", - pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: pbufs on queue => at least one queue non-empty", - pcb->unacked != NULL || pcb->unsent != NULL); - } else { - LWIP_ASSERT("tcp_write: no pbufs on queue => both queues empty", - pcb->unacked == NULL && pcb->unsent == NULL); - } - return ERR_OK; -} - -/** - * @ingroup tcp_raw - * Write data for sending (but does not send it immediately). - * - * It waits in the expectation of more data being sent soon (as - * it can send them more efficiently by combining them together). - * To prompt the system to send data now, call tcp_output() after - * calling tcp_write(). - * - * @param pcb Protocol control block for the TCP connection to enqueue data for. - * @param arg Pointer to the data to be enqueued for sending. - * @param len Data length in bytes - * @param apiflags combination of following flags : - * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack - * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will not be set on last segment sent, - * @return ERR_OK if enqueued, another err_t on error - */ -err_t -tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) -{ - struct pbuf *concat_p = NULL; - struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL; - u16_t pos = 0; /* position in 'arg' data */ - u16_t queuelen; - u8_t optlen = 0; - u8_t optflags = 0; -#if TCP_OVERSIZE - u16_t oversize = 0; - u16_t oversize_used = 0; -#if TCP_OVERSIZE_DBGCHECK - u16_t oversize_add = 0; -#endif /* TCP_OVERSIZE_DBGCHECK*/ -#endif /* TCP_OVERSIZE */ - u16_t extendlen = 0; -#if TCP_CHECKSUM_ON_COPY - u16_t concat_chksum = 0; - u8_t concat_chksum_swapped = 0; - u16_t concat_chksummed = 0; -#endif /* TCP_CHECKSUM_ON_COPY */ - err_t err; - /* don't allocate segments bigger than half the maximum window we ever received */ - u16_t mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max/2)); - mss_local = mss_local ? mss_local : pcb->mss; - -#if LWIP_NETIF_TX_SINGLE_PBUF - /* Always copy to try to create single pbufs for TX */ - apiflags |= TCP_WRITE_FLAG_COPY; -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", - (void *)pcb, arg, len, (u16_t)apiflags)); - LWIP_ERROR("tcp_write: arg == NULL (programmer violates API)", - arg != NULL, return ERR_ARG;); - - err = tcp_write_checks(pcb, len); - if (err != ERR_OK) { - return err; - } - queuelen = pcb->snd_queuelen; - -#if LWIP_TCP_TIMESTAMPS - if ((pcb->flags & TF_TIMESTAMP)) { - /* Make sure the timestamp option is only included in data segments if we - agreed about it with the remote host. */ - optflags = TF_SEG_OPTS_TS; - optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); - /* ensure that segments can hold at least one data byte... */ - mss_local = LWIP_MAX(mss_local, LWIP_TCP_OPT_LEN_TS + 1); - } -#endif /* LWIP_TCP_TIMESTAMPS */ - - - /* - * TCP segmentation is done in three phases with increasing complexity: - * - * 1. Copy data directly into an oversized pbuf. - * 2. Chain a new pbuf to the end of pcb->unsent. - * 3. Create new segments. - * - * We may run out of memory at any point. In that case we must - * return ERR_MEM and not change anything in pcb. Therefore, all - * changes are recorded in local variables and committed at the end - * of the function. Some pcb fields are maintained in local copies: - * - * queuelen = pcb->snd_queuelen - * oversize = pcb->unsent_oversize - * - * These variables are set consistently by the phases: - * - * seg points to the last segment tampered with. - * - * pos records progress as data is segmented. - */ - - /* Find the tail of the unsent queue. */ - if (pcb->unsent != NULL) { - u16_t space; - u16_t unsent_optlen; - - /* @todo: this could be sped up by keeping last_unsent in the pcb */ - for (last_unsent = pcb->unsent; last_unsent->next != NULL; - last_unsent = last_unsent->next); - - /* Usable space at the end of the last unsent segment */ - unsent_optlen = LWIP_TCP_OPT_LENGTH(last_unsent->flags); - LWIP_ASSERT("mss_local is too small", mss_local >= last_unsent->len + unsent_optlen); - space = mss_local - (last_unsent->len + unsent_optlen); - - /* - * Phase 1: Copy data directly into an oversized pbuf. - * - * The number of bytes copied is recorded in the oversize_used - * variable. The actual copying is done at the bottom of the - * function. - */ -#if TCP_OVERSIZE -#if TCP_OVERSIZE_DBGCHECK - /* check that pcb->unsent_oversize matches last_unsent->oversize_left */ - LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)", - pcb->unsent_oversize == last_unsent->oversize_left); -#endif /* TCP_OVERSIZE_DBGCHECK */ - oversize = pcb->unsent_oversize; - if (oversize > 0) { - LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space); - seg = last_unsent; - oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len)); - pos += oversize_used; - oversize -= oversize_used; - space -= oversize_used; - } - /* now we are either finished or oversize is zero */ - LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len)); -#endif /* TCP_OVERSIZE */ - - /* - * Phase 2: Chain a new pbuf to the end of pcb->unsent. - * - * As an exception when NOT copying the data, if the given data buffer - * directly follows the last unsent data buffer in memory, extend the last - * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation. - * - * We don't extend segments containing SYN/FIN flags or options - * (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at - * the end. - */ - if ((pos < len) && (space > 0) && (last_unsent->len > 0)) { - u16_t seglen = LWIP_MIN(space, len - pos); - seg = last_unsent; - - /* Create a pbuf with a copy or reference to seglen bytes. We - * can use PBUF_RAW here since the data appears in the middle of - * a segment. A header will never be prepended. */ - if (apiflags & TCP_WRITE_FLAG_COPY) { - /* Data is copied */ - if ((concat_p = tcp_pbuf_prealloc(PBUF_RAW, seglen, space, &oversize, pcb, apiflags, 1)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", - seglen)); - goto memerr; - } -#if TCP_OVERSIZE_DBGCHECK - oversize_add = oversize; -#endif /* TCP_OVERSIZE_DBGCHECK */ - TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped); -#if TCP_CHECKSUM_ON_COPY - concat_chksummed += seglen; -#endif /* TCP_CHECKSUM_ON_COPY */ - queuelen += pbuf_clen(concat_p); - } else { - /* Data is not copied */ - /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */ - struct pbuf *p; - for (p = last_unsent->p; p->next != NULL; p = p->next); - if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) { - LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0); - extendlen = seglen; - } else { - if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("tcp_write: could not allocate memory for zero-copy pbuf\n")); - goto memerr; - } - /* reference the non-volatile payload data */ - ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos; - queuelen += pbuf_clen(concat_p); - } -#if TCP_CHECKSUM_ON_COPY - /* calculate the checksum of nocopy-data */ - tcp_seg_add_chksum(~inet_chksum((const u8_t*)arg + pos, seglen), seglen, - &concat_chksum, &concat_chksum_swapped); - concat_chksummed += seglen; -#endif /* TCP_CHECKSUM_ON_COPY */ - } - - pos += seglen; - } - } else { -#if TCP_OVERSIZE - LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)", - pcb->unsent_oversize == 0); -#endif /* TCP_OVERSIZE */ - } - - /* - * Phase 3: Create new segments. - * - * The new segments are chained together in the local 'queue' - * variable, ready to be appended to pcb->unsent. - */ - while (pos < len) { - struct pbuf *p; - u16_t left = len - pos; - u16_t max_len = mss_local - optlen; - u16_t seglen = LWIP_MIN(left, max_len); -#if TCP_CHECKSUM_ON_COPY - u16_t chksum = 0; - u8_t chksum_swapped = 0; -#endif /* TCP_CHECKSUM_ON_COPY */ - - if (apiflags & TCP_WRITE_FLAG_COPY) { - /* If copy is set, memory should be allocated and data copied - * into pbuf */ - if ((p = tcp_pbuf_prealloc(PBUF_TRANSPORT, seglen + optlen, mss_local, &oversize, pcb, apiflags, queue == NULL)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write : could not allocate memory for pbuf copy size %"U16_F"\n", seglen)); - goto memerr; - } - LWIP_ASSERT("tcp_write: check that first pbuf can hold the complete seglen", - (p->len >= seglen)); - TCP_DATA_COPY2((char *)p->payload + optlen, (const u8_t*)arg + pos, seglen, &chksum, &chksum_swapped); - } else { - /* Copy is not set: First allocate a pbuf for holding the data. - * Since the referenced data is available at least until it is - * sent out on the link (as it has to be ACKed by the remote - * party) we can safely use PBUF_ROM instead of PBUF_REF here. - */ - struct pbuf *p2; -#if TCP_OVERSIZE - LWIP_ASSERT("oversize == 0", oversize == 0); -#endif /* TCP_OVERSIZE */ - if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for zero-copy pbuf\n")); - goto memerr; - } -#if TCP_CHECKSUM_ON_COPY - /* calculate the checksum of nocopy-data */ - chksum = ~inet_chksum((const u8_t*)arg + pos, seglen); - if (seglen & 1) { - chksum_swapped = 1; - chksum = SWAP_BYTES_IN_WORD(chksum); - } -#endif /* TCP_CHECKSUM_ON_COPY */ - /* reference the non-volatile payload data */ - ((struct pbuf_rom*)p2)->payload = (const u8_t*)arg + pos; - - /* Second, allocate a pbuf for the headers. */ - if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { - /* If allocation fails, we have to deallocate the data pbuf as - * well. */ - pbuf_free(p2); - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: could not allocate memory for header pbuf\n")); - goto memerr; - } - /* Concatenate the headers and data pbufs together. */ - pbuf_cat(p/*header*/, p2/*data*/); - } - - queuelen += pbuf_clen(p); - - /* Now that there are more segments queued, we check again if the - * length of the queue exceeds the configured maximum or - * overflows. */ - if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n", - queuelen, (int)TCP_SND_QUEUELEN)); - pbuf_free(p); - goto memerr; - } - - if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) { - goto memerr; - } -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = oversize; -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - seg->chksum = chksum; - seg->chksum_swapped = chksum_swapped; - seg->flags |= TF_SEG_DATA_CHECKSUMMED; -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* first segment of to-be-queued data? */ - if (queue == NULL) { - queue = seg; - } else { - /* Attach the segment to the end of the queued segments */ - LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL); - prev_seg->next = seg; - } - /* remember last segment of to-be-queued data for next iteration */ - prev_seg = seg; - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n", - lwip_ntohl(seg->tcphdr->seqno), - lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg))); - - pos += seglen; - } - - /* - * All three segmentation phases were successful. We can commit the - * transaction. - */ -#if TCP_OVERSIZE_DBGCHECK - if ((last_unsent != NULL) && (oversize_add != 0)) { - last_unsent->oversize_left += oversize_add; - } -#endif /* TCP_OVERSIZE_DBGCHECK */ - - /* - * Phase 1: If data has been added to the preallocated tail of - * last_unsent, we update the length fields of the pbuf chain. - */ -#if TCP_OVERSIZE - if (oversize_used > 0) { - struct pbuf *p; - /* Bump tot_len of whole chain, len of tail */ - for (p = last_unsent->p; p; p = p->next) { - p->tot_len += oversize_used; - if (p->next == NULL) { - TCP_DATA_COPY((char *)p->payload + p->len, arg, oversize_used, last_unsent); - p->len += oversize_used; - } - } - last_unsent->len += oversize_used; -#if TCP_OVERSIZE_DBGCHECK - LWIP_ASSERT("last_unsent->oversize_left >= oversize_used", - last_unsent->oversize_left >= oversize_used); - last_unsent->oversize_left -= oversize_used; -#endif /* TCP_OVERSIZE_DBGCHECK */ - } - pcb->unsent_oversize = oversize; -#endif /* TCP_OVERSIZE */ - - /* - * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we - * determined that the last ROM pbuf can be extended to include the new data. - */ - if (concat_p != NULL) { - LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty", - (last_unsent != NULL)); - pbuf_cat(last_unsent->p, concat_p); - last_unsent->len += concat_p->tot_len; - } else if (extendlen > 0) { - struct pbuf *p; - LWIP_ASSERT("tcp_write: extension of reference requires reference", - last_unsent != NULL && last_unsent->p != NULL); - for (p = last_unsent->p; p->next != NULL; p = p->next) { - p->tot_len += extendlen; - } - p->tot_len += extendlen; - p->len += extendlen; - last_unsent->len += extendlen; - } - -#if TCP_CHECKSUM_ON_COPY - if (concat_chksummed) { - LWIP_ASSERT("tcp_write: concat checksum needs concatenated data", - concat_p != NULL || extendlen > 0); - /*if concat checksumm swapped - swap it back */ - if (concat_chksum_swapped) { - concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum); - } - tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum, - &last_unsent->chksum_swapped); - last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED; - } -#endif /* TCP_CHECKSUM_ON_COPY */ - - /* - * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that - * is harmless - */ - if (last_unsent == NULL) { - pcb->unsent = queue; - } else { - last_unsent->next = queue; - } - - /* - * Finally update the pcb state. - */ - pcb->snd_lbb += len; - pcb->snd_buf -= len; - pcb->snd_queuelen = queuelen; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n", - pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: valid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - - /* Set the PSH flag in the last segment that we enqueued. */ - if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) { - TCPH_SET_FLAG(seg->tcphdr, TCP_PSH); - } - - return ERR_OK; -memerr: - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - - if (concat_p != NULL) { - pbuf_free(concat_p); - } - if (queue != NULL) { - tcp_segs_free(queue); - } - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL || - pcb->unsent != NULL); - } - LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen)); - return ERR_MEM; -} - -/** - * Enqueue TCP options for transmission. - * - * Called by tcp_connect(), tcp_listen_input(), and tcp_send_ctrl(). - * - * @param pcb Protocol control block for the TCP connection. - * @param flags TCP header flags to set in the outgoing segment. - */ -err_t -tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) -{ - struct pbuf *p; - struct tcp_seg *seg; - u8_t optflags = 0; - u8_t optlen = 0; - - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen)); - - LWIP_ASSERT("tcp_enqueue_flags: need either TCP_SYN or TCP_FIN in flags (programmer violates API)", - (flags & (TCP_SYN | TCP_FIN)) != 0); - - /* check for configured max queuelen and possible overflow (FIN flag should always come through!) */ - if (((pcb->snd_queuelen >= TCP_SND_QUEUELEN) || (pcb->snd_queuelen > TCP_SNDQUEUELEN_OVERFLOW)) && - ((flags & TCP_FIN) == 0)) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("tcp_enqueue_flags: too long queue %"U16_F" (max %"U16_F")\n", - pcb->snd_queuelen, (u16_t)TCP_SND_QUEUELEN)); - TCP_STATS_INC(tcp.memerr); - pcb->flags |= TF_NAGLEMEMERR; - return ERR_MEM; - } - - if (flags & TCP_SYN) { - optflags = TF_SEG_OPTS_MSS; -#if LWIP_WND_SCALE - if ((pcb->state != SYN_RCVD) || (pcb->flags & TF_WND_SCALE)) { - /* In a (sent in state SYN_RCVD), the window scale option may only - be sent if we received a window scale option from the remote host. */ - optflags |= TF_SEG_OPTS_WND_SCALE; - } -#endif /* LWIP_WND_SCALE */ - } -#if LWIP_TCP_TIMESTAMPS - if ((pcb->flags & TF_TIMESTAMP)) { - /* Make sure the timestamp option is only included in data segments if we - agreed about it with the remote host. */ - optflags |= TF_SEG_OPTS_TS; - } -#endif /* LWIP_TCP_TIMESTAMPS */ - optlen = LWIP_TCP_OPT_LENGTH(optflags); - - /* Allocate pbuf with room for TCP header + options */ - if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) { - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("tcp_enqueue_flags: check that first pbuf can hold optlen", - (p->len >= optlen)); - - /* Allocate memory for tcp_seg, and fill in fields. */ - if ((seg = tcp_create_segment(pcb, p, flags, pcb->snd_lbb, optflags)) == NULL) { - pcb->flags |= TF_NAGLEMEMERR; - TCP_STATS_INC(tcp.memerr); - return ERR_MEM; - } - LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % LWIP_MIN(MEM_ALIGNMENT, 4)) == 0); - LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); - - LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, - ("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n", - lwip_ntohl(seg->tcphdr->seqno), - lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg), - (u16_t)flags)); - - /* Now append seg to pcb->unsent queue */ - if (pcb->unsent == NULL) { - pcb->unsent = seg; - } else { - struct tcp_seg *useg; - for (useg = pcb->unsent; useg->next != NULL; useg = useg->next); - useg->next = seg; - } -#if TCP_OVERSIZE - /* The new unsent tail has no space */ - pcb->unsent_oversize = 0; -#endif /* TCP_OVERSIZE */ - - /* SYN and FIN bump the sequence number */ - if ((flags & TCP_SYN) || (flags & TCP_FIN)) { - pcb->snd_lbb++; - /* optlen does not influence snd_buf */ - } - if (flags & TCP_FIN) { - pcb->flags |= TF_FIN; - } - - /* update number of segments on the queues */ - pcb->snd_queuelen += pbuf_clen(seg->p); - LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue_flags: %"S16_F" (after enqueued)\n", pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) { - LWIP_ASSERT("tcp_enqueue_flags: invalid queue length", - pcb->unacked != NULL || pcb->unsent != NULL); - } - - return ERR_OK; -} - -#if LWIP_TCP_TIMESTAMPS -/* Build a timestamp option (12 bytes long) at the specified options pointer) - * - * @param pcb tcp_pcb - * @param opts option pointer where to store the timestamp option - */ -static void -tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts) -{ - /* Pad with two NOP options to make everything nicely aligned */ - opts[0] = PP_HTONL(0x0101080A); - opts[1] = lwip_htonl(sys_now()); - opts[2] = lwip_htonl(pcb->ts_recent); -} -#endif - -#if LWIP_WND_SCALE -/** Build a window scale option (3 bytes long) at the specified options pointer) - * - * @param opts option pointer where to store the window scale option - */ -static void -tcp_build_wnd_scale_option(u32_t *opts) -{ - /* Pad with one NOP option to make everything nicely aligned */ - opts[0] = PP_HTONL(0x01030300 | TCP_RCV_SCALE); -} -#endif - -/** - * Send an ACK without data. - * - * @param pcb Protocol control block for the TCP connection to send the ACK - */ -err_t -tcp_send_empty_ack(struct tcp_pcb *pcb) -{ - err_t err; - struct pbuf *p; - u8_t optlen = 0; - struct netif *netif; -#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP - struct tcp_hdr *tcphdr; -#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ - -#if LWIP_TCP_TIMESTAMPS - if (pcb->flags & TF_TIMESTAMP) { - optlen = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_TS); - } -#endif - - p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt)); - if (p == NULL) { - /* let tcp_fasttmr retry sending this ACK */ - pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n")); - return ERR_BUF; - } -#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP - tcphdr = (struct tcp_hdr *)p->payload; -#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */ - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, - ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt)); - - /* NB. MSS and window scale options are only sent on SYNs, so ignore them here */ -#if LWIP_TCP_TIMESTAMPS - pcb->ts_lastacksent = pcb->rcv_nxt; - - if (pcb->flags & TF_TIMESTAMP) { - tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1)); - } -#endif - - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - err = ERR_RTE; - } else { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); - } -#endif - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, - pcb->ttl, pcb->tos, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - } - pbuf_free(p); - - if (err != ERR_OK) { - /* let tcp_fasttmr retry sending this ACK */ - pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW); - } else { - /* remove ACK flags from the PCB, as we sent an empty ACK now */ - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - - return err; -} - -/** - * @ingroup tcp_raw - * Find out what we can send and send it - * - * @param pcb Protocol control block for the TCP connection to send data - * @return ERR_OK if data has been sent or nothing to send - * another err_t on error - */ -err_t -tcp_output(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg, *useg; - u32_t wnd, snd_nxt; - err_t err; - struct netif *netif; -#if TCP_CWND_DEBUG - s16_t i = 0; -#endif /* TCP_CWND_DEBUG */ - - /* pcb->state LISTEN not allowed here */ - LWIP_ASSERT("don't call tcp_output for listen-pcbs", - pcb->state != LISTEN); - - /* First, check if we are invoked by the TCP input processing - code. If so, we do not output anything. Instead, we rely on the - input processing code to call us when input processing is done - with. */ - if (tcp_input_pcb == pcb) { - return ERR_OK; - } - - wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd); - - seg = pcb->unsent; - - /* If the TF_ACK_NOW flag is set and no data will be sent (either - * because the ->unsent queue is empty or because the window does - * not allow it), construct an empty ACK segment and send it. - * - * If data is to be sent, we will just piggyback the ACK (see below). - */ - if (pcb->flags & TF_ACK_NOW && - (seg == NULL || - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { - return tcp_send_empty_ack(pcb); - } - - /* useg should point to last segment on unacked queue */ - useg = pcb->unacked; - if (useg != NULL) { - for (; useg->next != NULL; useg = useg->next); - } - - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - return ERR_RTE; - } - - /* If we don't have a local IP address, we get one from netif */ - if (ip_addr_isany(&pcb->local_ip)) { - const ip_addr_t *local_ip = ip_netif_get_local_ip(netif, &pcb->remote_ip); - if (local_ip == NULL) { - return ERR_RTE; - } - ip_addr_copy(pcb->local_ip, *local_ip); - } - -#if TCP_OUTPUT_DEBUG - if (seg == NULL) { - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", - (void*)pcb->unsent)); - } -#endif /* TCP_OUTPUT_DEBUG */ -#if TCP_CWND_DEBUG - if (seg == NULL) { - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F - ", cwnd %"TCPWNDSIZE_F", wnd %"U32_F - ", seg == NULL, ack %"U32_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, pcb->lastack)); - } else { - LWIP_DEBUGF(TCP_CWND_DEBUG, - ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F - ", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len, - lwip_ntohl(seg->tcphdr->seqno), pcb->lastack)); - } -#endif /* TCP_CWND_DEBUG */ - /* Check if we need to start the persistent timer when the next unsent segment - * does not fit within the remaining send window and RTO timer is not running (we - * have no in-flight data). A traditional approach would fill the remaining window - * with part of the unsent segment (which will engage zero-window probing upon - * reception of the zero window update from the receiver). This ensures the - * subsequent window update is reliably received. With the goal of being lightweight, - * we avoid splitting the unsent segment and treat the window as already zero. - */ - if (seg != NULL && - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd && - wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) { - /* Start the persist timer */ - if (pcb->persist_backoff == 0) { - pcb->persist_cnt = 0; - pcb->persist_backoff = 1; - } - goto output_done; - } - /* data available and window allows it to be sent? */ - while (seg != NULL && - lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { - LWIP_ASSERT("RST not expected here!", - (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0); - /* Stop sending if the nagle algorithm would prevent it - * Don't stop: - * - if tcp_write had a memory error before (prevent delayed ACK timeout) or - * - if FIN was already enqueued for this PCB (SYN is always alone in a segment - - * either seg->next != NULL or pcb->unacked == NULL; - * RST is no sent using tcp_write/tcp_output. - */ - if ((tcp_do_output_nagle(pcb) == 0) && - ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) { - break; - } -#if TCP_CWND_DEBUG - LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n", - pcb->snd_wnd, pcb->cwnd, wnd, - lwip_ntohl(seg->tcphdr->seqno) + seg->len - - pcb->lastack, - lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i)); - ++i; -#endif /* TCP_CWND_DEBUG */ - - if (pcb->state != SYN_SENT) { - TCPH_SET_FLAG(seg->tcphdr, TCP_ACK); - } - -#if TCP_OVERSIZE_DBGCHECK - seg->oversize_left = 0; -#endif /* TCP_OVERSIZE_DBGCHECK */ - err = tcp_output_segment(seg, pcb, netif); - if (err != ERR_OK) { - /* segment could not be sent, for whatever reason */ - pcb->flags |= TF_NAGLEMEMERR; - return err; - } - pcb->unsent = seg->next; - if (pcb->state != SYN_SENT) { - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW); - } - snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg); - if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { - pcb->snd_nxt = snd_nxt; - } - /* put segment on unacknowledged list if length > 0 */ - if (TCP_TCPLEN(seg) > 0) { - seg->next = NULL; - /* unacked list is empty? */ - if (pcb->unacked == NULL) { - pcb->unacked = seg; - useg = seg; - /* unacked list is not empty? */ - } else { - /* In the case of fast retransmit, the packet should not go to the tail - * of the unacked queue, but rather somewhere before it. We need to check for - * this case. -STJ Jul 27, 2004 */ - if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) { - /* add segment to before tail of unacked list, keeping the list sorted */ - struct tcp_seg **cur_seg = &(pcb->unacked); - while (*cur_seg && - TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { - cur_seg = &((*cur_seg)->next ); - } - seg->next = (*cur_seg); - (*cur_seg) = seg; - } else { - /* add segment to tail of unacked list */ - useg->next = seg; - useg = useg->next; - } - } - /* do not queue empty segments on the unacked list */ - } else { - tcp_seg_free(seg); - } - seg = pcb->unsent; - } -output_done: -#if TCP_OVERSIZE - if (pcb->unsent == NULL) { - /* last unsent has been removed, reset unsent_oversize */ - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - - pcb->flags &= ~TF_NAGLEMEMERR; - return ERR_OK; -} - -/** - * Called by tcp_output() to actually send a TCP segment over IP. - * - * @param seg the tcp_seg to send - * @param pcb the tcp_pcb for the TCP connection used to send the segment - * @param netif the netif used to send the segment - */ -static err_t -tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif) -{ - err_t err; - u16_t len; - u32_t *opts; - - if (seg->p->ref != 1) { - /* This can happen if the pbuf of this segment is still referenced by the - netif driver due to deferred transmission. Since this function modifies - p->len, we must not continue in this case. */ - return ERR_OK; - } - - /* The TCP header has already been constructed, but the ackno and - wnd fields remain. */ - seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt); - - /* advertise our receive window size in this TCP segment */ -#if LWIP_WND_SCALE - if (seg->flags & TF_SEG_OPTS_WND_SCALE) { - /* The Window field in a SYN segment itself (the only type where we send - the window scale option) is never scaled. */ - seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd)); - } else -#endif /* LWIP_WND_SCALE */ - { - seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd))); - } - - pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; - - /* Add any requested options. NB MSS option is only set on SYN - packets, so ignore it here */ - /* cast through void* to get rid of alignment warnings */ - opts = (u32_t *)(void *)(seg->tcphdr + 1); - if (seg->flags & TF_SEG_OPTS_MSS) { - u16_t mss; -#if TCP_CALCULATE_EFF_SEND_MSS - mss = tcp_eff_send_mss(TCP_MSS, &pcb->local_ip, &pcb->remote_ip); -#else /* TCP_CALCULATE_EFF_SEND_MSS */ - mss = TCP_MSS; -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - *opts = TCP_BUILD_MSS_OPTION(mss); - opts += 1; - } -#if LWIP_TCP_TIMESTAMPS - pcb->ts_lastacksent = pcb->rcv_nxt; - - if (seg->flags & TF_SEG_OPTS_TS) { - tcp_build_timestamp_option(pcb, opts); - opts += 3; - } -#endif -#if LWIP_WND_SCALE - if (seg->flags & TF_SEG_OPTS_WND_SCALE) { - tcp_build_wnd_scale_option(opts); - opts += 1; - } -#endif - - /* Set retransmission timer running if it is not currently enabled - This must be set before checking the route. */ - if (pcb->rtime < 0) { - pcb->rtime = 0; - } - - if (pcb->rttest == 0) { - pcb->rttest = tcp_ticks; - pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno); - - LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); - } - LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", - lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) + - seg->len)); - - len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); - if (len == 0) { - /** Exclude retransmitted segments from this count. */ - MIB2_STATS_INC(mib2.tcpoutsegs); - } - - seg->p->len -= len; - seg->p->tot_len -= len; - - seg->p->payload = seg->tcphdr; - - seg->tcphdr->chksum = 0; -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { -#if TCP_CHECKSUM_ON_COPY - u32_t acc; -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK - u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, - seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ - if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { - LWIP_ASSERT("data included but not checksummed", - seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); - } - - /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ - acc = ip_chksum_pseudo_partial(seg->p, IP_PROTO_TCP, - seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4, &pcb->local_ip, &pcb->remote_ip); - /* add payload checksum */ - if (seg->chksum_swapped) { - seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); - seg->chksum_swapped = 0; - } - acc += (u16_t)~(seg->chksum); - seg->tcphdr->chksum = FOLD_U32T(acc); -#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK - if (chksum_slow != seg->tcphdr->chksum) { - TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL( - ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", - seg->tcphdr->chksum, chksum_slow)); - seg->tcphdr->chksum = chksum_slow; - } -#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ -#else /* TCP_CHECKSUM_ON_COPY */ - seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP, - seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip); -#endif /* TCP_CHECKSUM_ON_COPY */ - } -#endif /* CHECKSUM_GEN_TCP */ - TCP_STATS_INC(tcp.xmit); - - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - pcb->tos, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - return err; -} - -/** - * Send a TCP RESET packet (empty segment with RST flag set) either to - * abort a connection or to show that there is no matching local connection - * for a received segment. - * - * Called by tcp_abort() (to abort a local connection), tcp_input() (if no - * matching local pcb was found), tcp_listen_input() (if incoming segment - * has ACK flag set) and tcp_process() (received segment in the wrong state) - * - * Since a RST segment is in most cases not sent for an active connection, - * tcp_rst() has a number of arguments that are taken from a tcp_pcb for - * most other segment output functions. - * - * @param seqno the sequence number to use for the outgoing segment - * @param ackno the acknowledge number to use for the outgoing segment - * @param local_ip the local IP address to send the segment from - * @param remote_ip the remote IP address to send the segment to - * @param local_port the local TCP port to send the segment from - * @param remote_port the remote TCP port to send the segment to - */ -void -tcp_rst(u32_t seqno, u32_t ackno, - const ip_addr_t *local_ip, const ip_addr_t *remote_ip, - u16_t local_port, u16_t remote_port) -{ - struct pbuf *p; - struct tcp_hdr *tcphdr; - struct netif *netif; - p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n")); - return; - } - LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr", - (p->len >= sizeof(struct tcp_hdr))); - - tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->src = lwip_htons(local_port); - tcphdr->dest = lwip_htons(remote_port); - tcphdr->seqno = lwip_htonl(seqno); - tcphdr->ackno = lwip_htonl(ackno); - TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK); -#if LWIP_WND_SCALE - tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); -#else - tcphdr->wnd = PP_HTONS(TCP_WND); -#endif - tcphdr->chksum = 0; - tcphdr->urgp = 0; - - TCP_STATS_INC(tcp.xmit); - MIB2_STATS_INC(mib2.tcpoutrsts); - - netif = ip_route(local_ip, remote_ip); - if (netif != NULL) { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - local_ip, remote_ip); - } -#endif - /* Send output with hardcoded TTL/HL since we have no access to the pcb */ - ip_output_if(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif); - } - pbuf_free(p); - LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno)); -} - -/** - * Requeue all unacked segments for retransmission - * - * Called by tcp_slowtmr() for slow retransmission. - * - * @param pcb the tcp_pcb for which to re-enqueue all unacked segments - */ -void -tcp_rexmit_rto(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg; - - if (pcb->unacked == NULL) { - return; - } - - /* Move all unacked segments to the head of the unsent queue */ - for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); - /* concatenate unsent queue after unacked queue */ - seg->next = pcb->unsent; -#if TCP_OVERSIZE_DBGCHECK - /* if last unsent changed, we need to update unsent_oversize */ - if (pcb->unsent == NULL) { - pcb->unsent_oversize = seg->oversize_left; - } -#endif /* TCP_OVERSIZE_DBGCHECK */ - /* unsent queue is the concatenated queue (of unacked, unsent) */ - pcb->unsent = pcb->unacked; - /* unacked queue is now empty */ - pcb->unacked = NULL; - - /* increment number of retransmissions */ - if (pcb->nrtx < 0xFF) { - ++pcb->nrtx; - } - - /* Don't take any RTT measurements after retransmitting. */ - pcb->rttest = 0; - - /* Do the actual retransmission */ - tcp_output(pcb); -} - -/** - * Requeue the first unacked segment for retransmission - * - * Called by tcp_receive() for fast retransmit. - * - * @param pcb the tcp_pcb for which to retransmit the first unacked segment - */ -void -tcp_rexmit(struct tcp_pcb *pcb) -{ - struct tcp_seg *seg; - struct tcp_seg **cur_seg; - - if (pcb->unacked == NULL) { - return; - } - - /* Move the first unacked segment to the unsent queue */ - /* Keep the unsent queue sorted. */ - seg = pcb->unacked; - pcb->unacked = seg->next; - - cur_seg = &(pcb->unsent); - while (*cur_seg && - TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { - cur_seg = &((*cur_seg)->next ); - } - seg->next = *cur_seg; - *cur_seg = seg; -#if TCP_OVERSIZE - if (seg->next == NULL) { - /* the retransmitted segment is last in unsent, so reset unsent_oversize */ - pcb->unsent_oversize = 0; - } -#endif /* TCP_OVERSIZE */ - - if (pcb->nrtx < 0xFF) { - ++pcb->nrtx; - } - - /* Don't take any rtt measurements after retransmitting. */ - pcb->rttest = 0; - - /* Do the actual retransmission. */ - MIB2_STATS_INC(mib2.tcpretranssegs); - /* No need to call tcp_output: we are always called from tcp_input() - and thus tcp_output directly returns. */ -} - - -/** - * Handle retransmission after three dupacks received - * - * @param pcb the tcp_pcb for which to retransmit the first unacked segment - */ -void -tcp_rexmit_fast(struct tcp_pcb *pcb) -{ - if (pcb->unacked != NULL && !(pcb->flags & TF_INFR)) { - /* This is fast retransmit. Retransmit the first unacked segment. */ - LWIP_DEBUGF(TCP_FR_DEBUG, - ("tcp_receive: dupacks %"U16_F" (%"U32_F - "), fast retransmit %"U32_F"\n", - (u16_t)pcb->dupacks, pcb->lastack, - lwip_ntohl(pcb->unacked->tcphdr->seqno))); - tcp_rexmit(pcb); - - /* Set ssthresh to half of the minimum of the current - * cwnd and the advertised window */ - pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2; - - /* The minimum value for ssthresh should be 2 MSS */ - if (pcb->ssthresh < (2U * pcb->mss)) { - LWIP_DEBUGF(TCP_FR_DEBUG, - ("tcp_receive: The minimum value for ssthresh %"TCPWNDSIZE_F - " should be min 2 mss %"U16_F"...\n", - pcb->ssthresh, (u16_t)(2*pcb->mss))); - pcb->ssthresh = 2*pcb->mss; - } - - pcb->cwnd = pcb->ssthresh + 3 * pcb->mss; - pcb->flags |= TF_INFR; - - /* Reset the retransmission timer to prevent immediate rto retransmissions */ - pcb->rtime = 0; - } -} - - -/** - * Send keepalive packets to keep a connection active although - * no data is sent over it. - * - * Called by tcp_slowtmr() - * - * @param pcb the tcp_pcb for which to send a keepalive packet - */ -err_t -tcp_keepalive(struct tcp_pcb *pcb) -{ - err_t err; - struct pbuf *p; - struct netif *netif; - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to ")); - ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", - tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); - - p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1)); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, - ("tcp_keepalive: could not allocate memory for pbuf\n")); - return ERR_MEM; - } - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - err = ERR_RTE; - } else { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload; - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); - } -#endif /* CHECKSUM_GEN_TCP */ - TCP_STATS_INC(tcp.xmit); - - /* Send output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - } - pbuf_free(p); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n", - pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); - return err; -} - - -/** - * Send persist timer zero-window probes to keep a connection active - * when a window update is lost. - * - * Called by tcp_slowtmr() - * - * @param pcb the tcp_pcb for which to send a zero-window probe packet - */ -err_t -tcp_zero_window_probe(struct tcp_pcb *pcb) -{ - err_t err; - struct pbuf *p; - struct tcp_hdr *tcphdr; - struct tcp_seg *seg; - u16_t len; - u8_t is_fin; - u32_t snd_nxt; - struct netif *netif; - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to ")); - ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(TCP_DEBUG, ("\n")); - - LWIP_DEBUGF(TCP_DEBUG, - ("tcp_zero_window_probe: tcp_ticks %"U32_F - " pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n", - tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent)); - - seg = pcb->unacked; - - if (seg == NULL) { - seg = pcb->unsent; - } - if (seg == NULL) { - /* nothing to send, zero window probe not needed */ - return ERR_OK; - } - - is_fin = ((TCPH_FLAGS(seg->tcphdr) & TCP_FIN) != 0) && (seg->len == 0); - /* we want to send one seqno: either FIN or data (no options) */ - len = is_fin ? 0 : 1; - - p = tcp_output_alloc_header(pcb, 0, len, seg->tcphdr->seqno); - if (p == NULL) { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: no memory for pbuf\n")); - return ERR_MEM; - } - tcphdr = (struct tcp_hdr *)p->payload; - - if (is_fin) { - /* FIN segment, no data */ - TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); - } else { - /* Data segment, copy in one byte from the head of the unacked queue */ - char *d = ((char *)p->payload + TCP_HLEN); - /* Depending on whether the segment has already been sent (unacked) or not - (unsent), seg->p->payload points to the IP header or TCP header. - Ensure we copy the first TCP data byte: */ - pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len); - } - - /* The byte may be acknowledged without the window being opened. */ - snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1; - if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { - pcb->snd_nxt = snd_nxt; - } - - netif = ip_route(&pcb->local_ip, &pcb->remote_ip); - if (netif == NULL) { - err = ERR_RTE; - } else { -#if CHECKSUM_GEN_TCP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) { - tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &pcb->local_ip, &pcb->remote_ip); - } -#endif - TCP_STATS_INC(tcp.xmit); - - /* Send output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, - 0, IP_PROTO_TCP, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - } - - pbuf_free(p); - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: seqno %"U32_F - " ackno %"U32_F" err %d.\n", - pcb->snd_nxt - 1, pcb->rcv_nxt, (int)err)); - return err; -} -#endif /* LWIP_TCP */ diff --git a/components/net/lwip-2.0.2/src/core/timeouts.c b/components/net/lwip-2.0.2/src/core/timeouts.c deleted file mode 100644 index 227d71fc9b..0000000000 --- a/components/net/lwip-2.0.2/src/core/timeouts.c +++ /dev/null @@ -1,433 +0,0 @@ -/** - * @file - * Stack-internal timers implementation. - * This file includes timer callbacks for stack-internal timers as well as - * functions to set up or stop timers and check for expired timers. - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -#include "lwip/opt.h" - -#include "lwip/timeouts.h" -#include "lwip/priv/tcp_priv.h" - -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/priv/tcpip_priv.h" - -#include "lwip/ip4_frag.h" -#include "lwip/etharp.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/igmp.h" -#include "lwip/dns.h" -#include "lwip/nd6.h" -#include "lwip/ip6_frag.h" -#include "lwip/mld6.h" -#include "lwip/sys.h" -#include "lwip/pbuf.h" - -#if LWIP_DEBUG_TIMERNAMES -#define HANDLER(x) x, #x -#else /* LWIP_DEBUG_TIMERNAMES */ -#define HANDLER(x) x -#endif /* LWIP_DEBUG_TIMERNAMES */ - -/** This array contains all stack-internal cyclic timers. To get the number of - * timers, use LWIP_ARRAYSIZE() */ -const struct lwip_cyclic_timer lwip_cyclic_timers[] = { -#if LWIP_TCP - /* The TCP timer is a special case: it does not have to run always and - is triggered to start from TCP using tcp_timer_needed() */ - {TCP_TMR_INTERVAL, HANDLER(tcp_tmr)}, -#endif /* LWIP_TCP */ -#if LWIP_IPV4 -#if IP_REASSEMBLY - {IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)}, -#endif /* IP_REASSEMBLY */ -#if LWIP_ARP - {ARP_TMR_INTERVAL, HANDLER(etharp_tmr)}, -#endif /* LWIP_ARP */ -#if LWIP_DHCP - {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)}, - {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)}, -#endif /* LWIP_DHCP */ -#if LWIP_AUTOIP - {AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)}, -#endif /* LWIP_AUTOIP */ -#if LWIP_IGMP - {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)}, -#endif /* LWIP_IGMP */ -#endif /* LWIP_IPV4 */ -#if LWIP_DNS - {DNS_TMR_INTERVAL, HANDLER(dns_tmr)}, -#endif /* LWIP_DNS */ -#if LWIP_IPV6 - {ND6_TMR_INTERVAL, HANDLER(nd6_tmr)}, -#if LWIP_IPV6_REASS - {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)}, -#endif /* LWIP_IPV6_REASS */ -#if LWIP_IPV6_MLD - {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)}, -#endif /* LWIP_IPV6_MLD */ -#endif /* LWIP_IPV6 */ -}; - -#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM - -/** The one and only timeout list */ -static struct sys_timeo *next_timeout; -static u32_t timeouts_last_time; - -#if LWIP_TCP -/** global variable that shows if the tcp timer is currently scheduled or not */ -static int tcpip_tcp_timer_active; - -/** - * Timer callback function that calls tcp_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -tcpip_tcp_timer(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - /* call TCP timer handler */ - tcp_tmr(); - /* timer still needed? */ - if (tcp_active_pcbs || tcp_tw_pcbs) { - /* restart timer */ - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } else { - /* disable timer */ - tcpip_tcp_timer_active = 0; - } -} - -/** - * Called from TCP_REG when registering a new PCB: - * the reason is to have the TCP timer only running when - * there are active (or time-wait) PCBs. - */ -void -tcp_timer_needed(void) -{ - /* timer is off but needed again? */ - if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { - /* enable and start timer */ - tcpip_tcp_timer_active = 1; - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); - } -} -#endif /* LWIP_TCP */ - -/** - * Timer callback function that calls mld6_tmr() and reschedules itself. - * - * @param arg unused argument - */ -static void -cyclic_timer(void *arg) -{ - const struct lwip_cyclic_timer* cyclic = (const struct lwip_cyclic_timer*)arg; -#if LWIP_DEBUG_TIMERNAMES - LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name)); -#endif - cyclic->handler(); - sys_timeout(cyclic->interval_ms, cyclic_timer, arg); -} - -/** Initialize this module */ -void sys_timeouts_init(void) -{ - size_t i; - /* tcp_tmr() at index 0 is started on demand */ - for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) { - /* we have to cast via size_t to get rid of const warning - (this is OK as cyclic_timer() casts back to const* */ - sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i])); - } - - /* Initialise timestamp for sys_check_timeouts */ - timeouts_last_time = sys_now(); -} - -/** - * Create a one-shot timer (aka timeout). Timeouts are processed in the - * following cases: - * - while waiting for a message using sys_timeouts_mbox_fetch() - * - by calling sys_check_timeouts() (NO_SYS==1 only) - * - * @param msecs time in milliseconds after that the timer should expire - * @param handler callback function to call when msecs have elapsed - * @param arg argument to pass to the callback function - */ -#if LWIP_DEBUG_TIMERNAMES -void -sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name) -#else /* LWIP_DEBUG_TIMERNAMES */ -void -sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) -#endif /* LWIP_DEBUG_TIMERNAMES */ -{ - struct sys_timeo *timeout, *t; - u32_t now, diff; - - timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); - if (timeout == NULL) { - LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL); - return; - } - - now = sys_now(); - if (next_timeout == NULL) { - diff = 0; - timeouts_last_time = now; - } else { - diff = now - timeouts_last_time; - } - - timeout->next = NULL; - timeout->h = handler; - timeout->arg = arg; - timeout->time = msecs + diff; -#if LWIP_DEBUG_TIMERNAMES - timeout->handler_name = handler_name; - LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", - (void *)timeout, msecs, handler_name, (void *)arg)); -#endif /* LWIP_DEBUG_TIMERNAMES */ - - if (next_timeout == NULL) { - next_timeout = timeout; - return; - } - - if (next_timeout->time > msecs) { - next_timeout->time -= msecs; - timeout->next = next_timeout; - next_timeout = timeout; - } else { - for (t = next_timeout; t != NULL; t = t->next) { - timeout->time -= t->time; - if (t->next == NULL || t->next->time > timeout->time) { - if (t->next != NULL) { - t->next->time -= timeout->time; - } else if (timeout->time > msecs) { - /* If this is the case, 'timeouts_last_time' and 'now' differs too much. - This can be due to sys_check_timeouts() not being called at the right - times, but also when stopping in a breakpoint. Anyway, let's assume - this is not wanted, so add the first timer's time instead of 'diff' */ - timeout->time = msecs + next_timeout->time; - } - timeout->next = t->next; - t->next = timeout; - break; - } - } - } -} - -/** - * Go through timeout list (for this task only) and remove the first matching - * entry (subsequent entries remain untouched), even though the timeout has not - * triggered yet. - * - * @param handler callback function that would be called by the timeout - * @param arg callback argument that would be passed to handler -*/ -void -sys_untimeout(sys_timeout_handler handler, void *arg) -{ - struct sys_timeo *prev_t, *t; - - if (next_timeout == NULL) { - return; - } - - for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { - if ((t->h == handler) && (t->arg == arg)) { - /* We have a match */ - /* Unlink from previous in list */ - if (prev_t == NULL) { - next_timeout = t->next; - } else { - prev_t->next = t->next; - } - /* If not the last one, add time of this one back to next */ - if (t->next != NULL) { - t->next->time += t->time; - } - memp_free(MEMP_SYS_TIMEOUT, t); - return; - } - } - return; -} - -/** - * @ingroup lwip_nosys - * Handle timeouts for NO_SYS==1 (i.e. without using - * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout - * handler functions when timeouts expire. - * - * Must be called periodically from your main loop. - */ -#if !NO_SYS && !defined __DOXYGEN__ -static -#endif /* !NO_SYS */ -void -sys_check_timeouts(void) -{ - if (next_timeout) { - struct sys_timeo *tmptimeout; - u32_t diff; - sys_timeout_handler handler; - void *arg; - u8_t had_one; - u32_t now; - - now = sys_now(); - /* this cares for wraparounds */ - diff = now - timeouts_last_time; - do { - PBUF_CHECK_FREE_OOSEQ(); - had_one = 0; - tmptimeout = next_timeout; - if (tmptimeout && (tmptimeout->time <= diff)) { - /* timeout has expired */ - had_one = 1; - timeouts_last_time += tmptimeout->time; - diff -= tmptimeout->time; - next_timeout = tmptimeout->next; - handler = tmptimeout->h; - arg = tmptimeout->arg; -#if LWIP_DEBUG_TIMERNAMES - if (handler != NULL) { - LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", - tmptimeout->handler_name, arg)); - } -#endif /* LWIP_DEBUG_TIMERNAMES */ - memp_free(MEMP_SYS_TIMEOUT, tmptimeout); - if (handler != NULL) { -#if !NO_SYS - /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the - timeout handler function. */ - LOCK_TCPIP_CORE(); -#endif /* !NO_SYS */ - handler(arg); -#if !NO_SYS - UNLOCK_TCPIP_CORE(); -#endif /* !NO_SYS */ - } - LWIP_TCPIP_THREAD_ALIVE(); - } - /* repeat until all expired timers have been called */ - } while (had_one); - } -} - -/** Set back the timestamp of the last call to sys_check_timeouts() - * This is necessary if sys_check_timeouts() hasn't been called for a long - * time (e.g. while saving energy) to prevent all timer functions of that - * period being called. - */ -void -sys_restart_timeouts(void) -{ - timeouts_last_time = sys_now(); -} - -/** Return the time left before the next timeout is due. If no timeouts are - * enqueued, returns 0xffffffff - */ -#if !NO_SYS -static -#endif /* !NO_SYS */ -u32_t -sys_timeouts_sleeptime(void) -{ - u32_t diff; - if (next_timeout == NULL) { - return 0xffffffff; - } - diff = sys_now() - timeouts_last_time; - if (diff > next_timeout->time) { - return 0; - } else { - return next_timeout->time - diff; - } -} - -#if !NO_SYS - -/** - * Wait (forever) for a message to arrive in an mbox. - * While waiting, timeouts are processed. - * - * @param mbox the mbox to fetch the message from - * @param msg the place to store the message - */ -void -sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) -{ - u32_t sleeptime; - -again: - if (!next_timeout) { - sys_arch_mbox_fetch(mbox, msg, 0); - return; - } - - sleeptime = sys_timeouts_sleeptime(); - if (sleeptime == 0 || sys_arch_mbox_fetch(mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) { - /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred - before a message could be fetched. */ - sys_check_timeouts(); - /* We try again to fetch a message from the mbox. */ - goto again; - } -} - -#endif /* NO_SYS */ - -#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ -/* Satisfy the TCP code which calls this function */ -void -tcp_timer_needed(void) -{ -} -#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ diff --git a/components/net/lwip-2.0.2/src/core/udp.c b/components/net/lwip-2.0.2/src/core/udp.c deleted file mode 100644 index ce2e3d295f..0000000000 --- a/components/net/lwip-2.0.2/src/core/udp.c +++ /dev/null @@ -1,1191 +0,0 @@ -/** - * @file - * User Datagram Protocol module\n - * The code for the User Datagram Protocol UDP & UDPLite (RFC 3828).\n - * See also @ref udp_raw - * - * @defgroup udp_raw UDP - * @ingroup callbackstyle_api - * User Datagram Protocol module\n - * @see @ref raw_api and @ref netconn - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* @todo Check the use of '(struct udp_pcb).chksum_len_rx'! - */ - -#include "lwip/opt.h" - -#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/udp.h" -#include "lwip/def.h" -#include "lwip/memp.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/icmp.h" -#include "lwip/icmp6.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/dhcp.h" - -#include - -#ifndef UDP_LOCAL_PORT_RANGE_START -/* From http://www.iana.org/assignments/port-numbers: - "The Dynamic and/or Private Ports are those from 49152 through 65535" */ -#define UDP_LOCAL_PORT_RANGE_START 0xc000 -#define UDP_LOCAL_PORT_RANGE_END 0xffff -#define UDP_ENSURE_LOCAL_PORT_RANGE(port) ((u16_t)(((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)) -#endif - -/* last local UDP port */ -static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START; - -/* The list of UDP PCBs */ -/* exported in udp.h (was static) */ -struct udp_pcb *udp_pcbs; - -/** - * Initialize this module. - */ -void -udp_init(void) -{ -#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) - udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND()); -#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */ -} - -/** - * Allocate a new local UDP port. - * - * @return a new (free) local UDP port number - */ -static u16_t -udp_new_port(void) -{ - u16_t n = 0; - struct udp_pcb *pcb; - -again: - if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) { - udp_port = UDP_LOCAL_PORT_RANGE_START; - } - /* Check all PCBs. */ - for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { - if (pcb->local_port == udp_port) { - if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) { - return 0; - } - goto again; - } - } - return udp_port; -} - -/** Common code to see if the current input packet matches the pcb - * (current input packet is accessed via ip(4/6)_current_* macros) - * - * @param pcb pcb to check - * @param inp network interface on which the datagram was received (only used for IPv4) - * @param broadcast 1 if his is an IPv4 broadcast (global or subnet-only), 0 otherwise (only used for IPv4) - * @return 1 on match, 0 otherwise - */ -static u8_t -udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast) -{ - LWIP_UNUSED_ARG(inp); /* in IPv6 only case */ - LWIP_UNUSED_ARG(broadcast); /* in IPv6 only case */ - - /* Dual-stack: PCBs listening to any IP type also listen to any IP address */ - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -#if LWIP_IPV4 && IP_SOF_BROADCAST_RECV - if ((broadcast != 0) && !ip_get_option(pcb, SOF_BROADCAST)) { - return 0; - } -#endif /* LWIP_IPV4 && IP_SOF_BROADCAST_RECV */ - return 1; - } - - /* Only need to check PCB if incoming IP version matches PCB IP version */ - if (IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ip_current_dest_addr())) { -#if LWIP_IPV4 - /* Special case: IPv4 broadcast: all or broadcasts in my subnet - * Note: broadcast variable can only be 1 if it is an IPv4 broadcast */ - if (broadcast != 0) { -#if IP_SOF_BROADCAST_RECV - if (ip_get_option(pcb, SOF_BROADCAST)) -#endif /* IP_SOF_BROADCAST_RECV */ - { - if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || - ((ip4_current_dest_addr()->addr == IPADDR_BROADCAST)) || - ip4_addr_netcmp(ip_2_ip4(&pcb->local_ip), ip4_current_dest_addr(), netif_ip4_netmask(inp))) { - return 1; - } - } - } else -#endif /* LWIP_IPV4 */ - /* Handle IPv4 and IPv6: all or exact match */ - if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) { - return 1; - } - } - - return 0; -} - -/** - * Process an incoming UDP datagram. - * - * Given an incoming UDP datagram (as a chain of pbufs) this function - * finds a corresponding UDP PCB and hands over the pbuf to the pcbs - * recv function. If no pcb is found or the datagram is incorrect, the - * pbuf is freed. - * - * @param p pbuf to be demultiplexed to a UDP PCB (p->payload pointing to the UDP header) - * @param inp network interface on which the datagram was received. - * - */ -void -udp_input(struct pbuf *p, struct netif *inp) -{ - struct udp_hdr *udphdr; - struct udp_pcb *pcb, *prev; - struct udp_pcb *uncon_pcb; - u16_t src, dest; - u8_t broadcast; - u8_t for_us = 0; - - LWIP_UNUSED_ARG(inp); - - PERF_START; - - UDP_STATS_INC(udp.recv); - - /* Check minimum length (UDP header) */ - if (p->len < UDP_HLEN) { - /* drop short packets */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len)); - UDP_STATS_INC(udp.lenerr); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpinerrors); - pbuf_free(p); - goto end; - } - - udphdr = (struct udp_hdr *)p->payload; - - /* is broadcast packet ? */ - broadcast = ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()); - - LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len)); - - /* convert src and dest ports to host byte order */ - src = lwip_ntohs(udphdr->src); - dest = lwip_ntohs(udphdr->dest); - - udp_debug_print(udphdr); - - /* print the UDP source and destination */ - LWIP_DEBUGF(UDP_DEBUG, ("udp (")); - ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest))); - ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr()); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src))); - - pcb = NULL; - prev = NULL; - uncon_pcb = NULL; - /* Iterate through the UDP pcb list for a matching pcb. - * 'Perfect match' pcbs (connected to the remote port & ip address) are - * preferred. If no perfect match is found, the first unconnected pcb that - * matches the local port and ip address gets the datagram. */ - for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) { - /* print the PCB local and remote address */ - LWIP_DEBUGF(UDP_DEBUG, ("pcb (")); - ip_addr_debug_print(UDP_DEBUG, &pcb->local_ip); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", pcb->local_port)); - ip_addr_debug_print(UDP_DEBUG, &pcb->remote_ip); - LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", pcb->remote_port)); - - /* compare PCB local addr+port to UDP destination addr+port */ - if ((pcb->local_port == dest) && - (udp_input_local_match(pcb, inp, broadcast) != 0)) { - if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) && - ((uncon_pcb == NULL) -#if SO_REUSE - /* prefer specific IPs over cath-all */ - || !ip_addr_isany(&pcb->local_ip) -#endif /* SO_REUSE */ - )) { - /* the first unconnected matching PCB */ - uncon_pcb = pcb; - } - - /* compare PCB remote addr+port to UDP source addr+port */ - if ((pcb->remote_port == src) && - (ip_addr_isany_val(pcb->remote_ip) || - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { - /* the first fully matching PCB */ - if (prev != NULL) { - /* move the pcb to the front of udp_pcbs so that is - found faster next time */ - prev->next = pcb->next; - pcb->next = udp_pcbs; - udp_pcbs = pcb; - } else { - UDP_STATS_INC(udp.cachehit); - } - break; - } - } - - prev = pcb; - } - /* no fully matching pcb found? then look for an unconnected pcb */ - if (pcb == NULL) { - pcb = uncon_pcb; - } - - /* Check checksum if this is a match or if it was directed at us. */ - if (pcb != NULL) { - for_us = 1; - } else { -#if LWIP_IPV6 - if (ip_current_is_v6()) { - for_us = netif_get_ip6_addr_match(inp, ip6_current_dest_addr()) >= 0; - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 - if (!ip_current_is_v6()) { - for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); - } -#endif /* LWIP_IPV4 */ - } - - if (for_us) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); -#if CHECKSUM_CHECK_UDP - IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) { -#if LWIP_UDPLITE - if (ip_current_header_proto() == IP_PROTO_UDPLITE) { - /* Do the UDP Lite checksum */ - u16_t chklen = lwip_ntohs(udphdr->len); - if (chklen < sizeof(struct udp_hdr)) { - if (chklen == 0) { - /* For UDP-Lite, checksum length of 0 means checksum - over the complete packet (See RFC 3828 chap. 3.1) */ - chklen = p->tot_len; - } else { - /* At least the UDP-Lite header must be covered by the - checksum! (Again, see RFC 3828 chap. 3.1) */ - goto chkerr; - } - } - if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE, - p->tot_len, chklen, - ip_current_src_addr(), ip_current_dest_addr()) != 0) { - goto chkerr; - } - } else -#endif /* LWIP_UDPLITE */ - { - if (udphdr->chksum != 0) { - if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len, - ip_current_src_addr(), - ip_current_dest_addr()) != 0) { - goto chkerr; - } - } - } - } -#endif /* CHECKSUM_CHECK_UDP */ - if (pbuf_header(p, -UDP_HLEN)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpinerrors); - pbuf_free(p); - goto end; - } - - if (pcb != NULL) { - MIB2_STATS_INC(mib2.udpindatagrams); -#if SO_REUSE && SO_REUSE_RXTOALL - if (ip_get_option(pcb, SOF_REUSEADDR) && - (broadcast || ip_addr_ismulticast(ip_current_dest_addr()))) { - /* pass broadcast- or multicast packets to all multicast pcbs - if SOF_REUSEADDR is set on the first match */ - struct udp_pcb *mpcb; - u8_t p_header_changed = 0; - s16_t hdrs_len = (s16_t)(ip_current_header_tot_len() + UDP_HLEN); - for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) { - if (mpcb != pcb) { - /* compare PCB local addr+port to UDP destination addr+port */ - if ((mpcb->local_port == dest) && - (udp_input_local_match(mpcb, inp, broadcast) != 0)) { - /* pass a copy of the packet to all local matches */ - if (mpcb->recv != NULL) { - struct pbuf *q; - /* for that, move payload to IP header again */ - if (p_header_changed == 0) { - pbuf_header_force(p, hdrs_len); - p_header_changed = 1; - } - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if (q != NULL) { - err_t err = pbuf_copy(q, p); - if (err == ERR_OK) { - /* move payload to UDP data */ - pbuf_header(q, -hdrs_len); - mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src); - } - } - } - } - } - } - if (p_header_changed) { - /* and move payload to UDP data again */ - pbuf_header(p, -hdrs_len); - } - } -#endif /* SO_REUSE && SO_REUSE_RXTOALL */ - /* callback */ - if (pcb->recv != NULL) { - /* now the recv function is responsible for freeing p */ - pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src); - } else { - /* no recv function registered? then we have to free the pbuf! */ - pbuf_free(p); - goto end; - } - } else { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: not for us.\n")); - -#if LWIP_ICMP || LWIP_ICMP6 - /* No match was found, send ICMP destination port unreachable unless - destination address was broadcast/multicast. */ - if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) { - /* move payload pointer back to ip header */ - pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN)); - icmp_port_unreach(ip_current_is_v6(), p); - } -#endif /* LWIP_ICMP || LWIP_ICMP6 */ - UDP_STATS_INC(udp.proterr); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpnoports); - pbuf_free(p); - } - } else { - pbuf_free(p); - } -end: - PERF_STOP("udp_input"); - return; -#if CHECKSUM_CHECK_UDP -chkerr: - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("udp_input: UDP (or UDP Lite) datagram discarded due to failing checksum\n")); - UDP_STATS_INC(udp.chkerr); - UDP_STATS_INC(udp.drop); - MIB2_STATS_INC(mib2.udpinerrors); - pbuf_free(p); - PERF_STOP("udp_input"); -#endif /* CHECKSUM_CHECK_UDP */ -} - -/** - * @ingroup udp_raw - * Send data using UDP. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * - * The datagram will be sent to the current remote_ip & remote_port - * stored in pcb. If the pcb is not bound to a port, it will - * automatically be bound to a random port. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occurred. - * - ERR_MEM. Out of memory. - * - ERR_RTE. Could not find route to destination address. - * - ERR_VAL. No PCB or PCB is dual-stack - * - More errors could be returned by lower protocol layers. - * - * @see udp_disconnect() udp_sendto() - */ -err_t -udp_send(struct udp_pcb *pcb, struct pbuf *p) -{ - if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { - return ERR_VAL; - } - - /* send to the packet using remote ip and port stored in the pcb */ - return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port); -} - -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP -/** @ingroup udp_raw - * Same as udp_send() but with checksum - */ -err_t -udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, - u8_t have_chksum, u16_t chksum) -{ - if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->remote_ip)) { - return ERR_VAL; - } - - /* send to the packet using remote ip and port stored in the pcb */ - return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port, - have_chksum, chksum); -} -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - -/** - * @ingroup udp_raw - * Send data to a specified address using UDP. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * @param dst_ip Destination IP address. - * @param dst_port Destination UDP port. - * - * dst_ip & dst_port are expected to be in the same byte order as in the pcb. - * - * If the PCB already has a remote address association, it will - * be restored after the data is sent. - * - * @return lwIP error code (@see udp_send for possible error codes) - * - * @see udp_disconnect() udp_send() - */ -err_t -udp_sendto(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0); -} - -/** @ingroup udp_raw - * Same as udp_sendto(), but with checksum */ -err_t -udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, - u16_t dst_port, u8_t have_chksum, u16_t chksum) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct netif *netif; - const ip_addr_t *dst_ip_route = dst_ip; - - if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { - return ERR_VAL; - } - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n")); - -#if LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) - if (ip_addr_ismulticast(dst_ip_route)) { -#if LWIP_IPV6 - if (IP_IS_V6(dst_ip)) { - /* For multicast, find a netif based on source address. */ - dst_ip_route = &pcb->local_ip; - } else -#endif /* LWIP_IPV6 */ - { -#if LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS - /* IPv4 does not use source-based routing by default, so we use an - administratively selected interface for multicast by default. - However, this can be overridden by setting an interface address - in pcb->multicast_ip that is used for routing. */ - if (!ip_addr_isany_val(pcb->multicast_ip) && - !ip4_addr_cmp(ip_2_ip4(&pcb->multicast_ip), IP4_ADDR_BROADCAST)) { - dst_ip_route = &pcb->multicast_ip; - } -#endif /* LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS */ - } - } -#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */ - - /* find the outgoing network interface for this packet */ - if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - /* Don't call ip_route() with IP_ANY_TYPE */ - netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route); - } else { - netif = ip_route(&pcb->local_ip, dst_ip_route); - } - - /* no outgoing network interface could be found? */ - if (netif == NULL) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dst_ip); - LWIP_DEBUGF(UDP_DEBUG, ("\n")); - UDP_STATS_INC(udp.rterr); - return ERR_RTE; - } -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum); -#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - return udp_sendto_if(pcb, p, dst_ip, dst_port, netif); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ -} - -/** - * @ingroup udp_raw - * Send data to a specified address using UDP. - * The netif used for sending can be specified. - * - * This function exists mainly for DHCP, to be able to send UDP packets - * on a netif that is still down. - * - * @param pcb UDP PCB used to send the data. - * @param p chain of pbuf's to be sent. - * @param dst_ip Destination IP address. - * @param dst_port Destination UDP port. - * @param netif the netif used for sending. - * - * dst_ip & dst_port are expected to be in the same byte order as in the pcb. - * - * @return lwIP error code (@see udp_send for possible error codes) - * - * @see udp_disconnect() udp_send() - */ -err_t -udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0); -} - -/** Same as udp_sendto_if(), but with checksum */ -err_t -udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, - u16_t dst_port, struct netif *netif, u8_t have_chksum, - u16_t chksum) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - const ip_addr_t *src_ip; - - if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { - return ERR_VAL; - } - - /* PCB local address is IP_ANY_ADDR? */ -#if LWIP_IPV6 - if (IP_IS_V6(dst_ip)) { - if (ip6_addr_isany(ip_2_ip6(&pcb->local_ip))) { - src_ip = ip6_select_source_address(netif, ip_2_ip6(dst_ip)); - if (src_ip == NULL) { - /* No suitable source address was found. */ - return ERR_RTE; - } - } else { - /* use UDP PCB local IPv6 address as source address, if still valid. */ - if (netif_get_ip6_addr_match(netif, ip_2_ip6(&pcb->local_ip)) < 0) { - /* Address isn't valid anymore. */ - return ERR_RTE; - } - src_ip = &pcb->local_ip; - } - } -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 && LWIP_IPV6 - else -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#if LWIP_IPV4 - if (ip4_addr_isany(ip_2_ip4(&pcb->local_ip)) || - ip4_addr_ismulticast(ip_2_ip4(&pcb->local_ip))) { - /* if the local_ip is any or multicast - * use the outgoing network interface IP address as source address */ - src_ip = netif_ip_addr4(netif); - } else { - /* check if UDP PCB local IP address is correct - * this could be an old address if netif->ip_addr has changed */ - if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) { - /* local_ip doesn't match, drop the packet */ - return ERR_RTE; - } - /* use UDP PCB local IP address as source address */ - src_ip = &pcb->local_ip; - } -#endif /* LWIP_IPV4 */ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); -#else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - return udp_sendto_if_src(pcb, p, dst_ip, dst_port, netif, src_ip); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ -} - -/** @ingroup udp_raw - * Same as @ref udp_sendto_if, but with source address */ -err_t -udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) -{ -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP - return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0, src_ip); -} - -/** Same as udp_sendto_if_src(), but with checksum */ -err_t -udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, - u16_t dst_port, struct netif *netif, u8_t have_chksum, - u16_t chksum, const ip_addr_t *src_ip) -{ -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - struct udp_hdr *udphdr; - err_t err; - struct pbuf *q; /* q will be sent down the stack */ - u8_t ip_proto; - u8_t ttl; - - if ((pcb == NULL) || (dst_ip == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, src_ip) || - !IP_ADDR_PCB_VERSION_MATCH(pcb, dst_ip)) { - return ERR_VAL; - } - -#if LWIP_IPV4 && IP_SOF_BROADCAST - /* broadcast filter? */ - if (!ip_get_option(pcb, SOF_BROADCAST) && -#if LWIP_IPV6 - IP_IS_V4(dst_ip) && -#endif /* LWIP_IPV6 */ - ip_addr_isbroadcast(dst_ip, netif)) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, - ("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb)); - return ERR_VAL; - } -#endif /* LWIP_IPV4 && IP_SOF_BROADCAST */ - - /* if the PCB is not yet bound to a port, bind it here */ - if (pcb->local_port == 0) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send: not yet bound to a port, binding now\n")); - err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); - if (err != ERR_OK) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: forced port bind failed\n")); - return err; - } - } - - /* not enough space to add an UDP header to first pbuf in given p chain? */ - if (pbuf_header(p, UDP_HLEN)) { - /* allocate header in a separate new pbuf */ - q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); - /* new header pbuf could not be allocated? */ - if (q == NULL) { - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); - return ERR_MEM; - } - if (p->tot_len != 0) { - /* chain header q in front of given pbuf p (only if p contains data) */ - pbuf_chain(q, p); - } - /* first pbuf q points to header pbuf */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); - } else { - /* adding space for header within p succeeded */ - /* first pbuf q equals given pbuf */ - q = p; - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p)); - } - LWIP_ASSERT("check that first pbuf can hold struct udp_hdr", - (q->len >= sizeof(struct udp_hdr))); - /* q now represents the packet to be sent */ - udphdr = (struct udp_hdr *)q->payload; - udphdr->src = lwip_htons(pcb->local_port); - udphdr->dest = lwip_htons(dst_port); - /* in UDP, 0 checksum means 'no checksum' */ - udphdr->chksum = 0x0000; - - /* Multicast Loop? */ -#if (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) - if (((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) && ip_addr_ismulticast(dst_ip)) { - q->flags |= PBUF_FLAG_MCASTLOOP; - } -#endif /* (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len)); - -#if LWIP_UDPLITE - /* UDP Lite protocol? */ - if (pcb->flags & UDP_FLAGS_UDPLITE) { - u16_t chklen, chklen_hdr; - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); - /* set UDP message length in UDP header */ - chklen_hdr = chklen = pcb->chksum_len_tx; - if ((chklen < sizeof(struct udp_hdr)) || (chklen > q->tot_len)) { - if (chklen != 0) { - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); - } - /* For UDP-Lite, checksum length of 0 means checksum - over the complete packet. (See RFC 3828 chap. 3.1) - At least the UDP-Lite header must be covered by the - checksum, therefore, if chksum_len has an illegal - value, we generate the checksum over the complete - packet to be safe. */ - chklen_hdr = 0; - chklen = q->tot_len; - } - udphdr->len = lwip_htons(chklen_hdr); - /* calculate checksum */ -#if CHECKSUM_GEN_UDP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - chklen = UDP_HLEN; - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE, - q->tot_len, chklen, src_ip, dst_ip); -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - u32_t acc; - acc = udphdr->chksum + (u16_t)~(chksum); - udphdr->chksum = FOLD_U32T(acc); - } -#endif /* LWIP_CHECKSUM_ON_COPY */ - - /* chksum zero must become 0xffff, as zero means 'no checksum' */ - if (udphdr->chksum == 0x0000) { - udphdr->chksum = 0xffff; - } - } -#endif /* CHECKSUM_GEN_UDP */ - - ip_proto = IP_PROTO_UDPLITE; - } else -#endif /* LWIP_UDPLITE */ - { /* UDP */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len)); - udphdr->len = lwip_htons(q->tot_len); - /* calculate checksum */ -#if CHECKSUM_GEN_UDP - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) { - /* Checksum is mandatory over IPv6. */ - if (IP_IS_V6(dst_ip) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) { - u16_t udpchksum; -#if LWIP_CHECKSUM_ON_COPY - if (have_chksum) { - u32_t acc; - udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP, - q->tot_len, UDP_HLEN, src_ip, dst_ip); - acc = udpchksum + (u16_t)~(chksum); - udpchksum = FOLD_U32T(acc); - } else -#endif /* LWIP_CHECKSUM_ON_COPY */ - { - udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len, - src_ip, dst_ip); - } - - /* chksum zero must become 0xffff, as zero means 'no checksum' */ - if (udpchksum == 0x0000) { - udpchksum = 0xffff; - } - udphdr->chksum = udpchksum; - } - } -#endif /* CHECKSUM_GEN_UDP */ - ip_proto = IP_PROTO_UDP; - } - - /* Determine TTL to use */ -#if LWIP_MULTICAST_TX_OPTIONS - ttl = (ip_addr_ismulticast(dst_ip) ? udp_get_multicast_ttl(pcb) : pcb->ttl); -#else /* LWIP_MULTICAST_TX_OPTIONS */ - ttl = pcb->ttl; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum)); - LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,0x%02"X16_F",)\n", (u16_t)ip_proto)); - /* output to IP */ - NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint)); - err = ip_output_if_src(q, src_ip, dst_ip, ttl, pcb->tos, ip_proto, netif); - NETIF_SET_HWADDRHINT(netif, NULL); - - /* @todo: must this be increased even if error occurred? */ - MIB2_STATS_INC(mib2.udpoutdatagrams); - - /* did we chain a separate header pbuf earlier? */ - if (q != p) { - /* free the header pbuf */ - pbuf_free(q); - q = NULL; - /* p is still referenced by the caller, and will live on */ - } - - UDP_STATS_INC(udp.xmit); - return err; -} - -/** - * @ingroup udp_raw - * Bind an UDP PCB. - * - * @param pcb UDP PCB to be bound with a local address ipaddr and port. - * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to - * bind to all local interfaces. - * @param port local UDP port to bind with. Use 0 to automatically bind - * to a random port between UDP_LOCAL_PORT_RANGE_START and - * UDP_LOCAL_PORT_RANGE_END. - * - * ipaddr & port are expected to be in the same byte order as in the pcb. - * - * @return lwIP error code. - * - ERR_OK. Successful. No error occurred. - * - ERR_USE. The specified ipaddr and port are already bound to by - * another UDP PCB. - * - * @see udp_disconnect() - */ -err_t -udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) -{ - struct udp_pcb *ipcb; - u8_t rebind; - -#if LWIP_IPV4 - /* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */ - if (ipaddr == NULL) { - ipaddr = IP4_ADDR_ANY; - } -#endif /* LWIP_IPV4 */ - - /* still need to check for ipaddr == NULL in IPv6 only case */ - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE, ipaddr); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, (", port = %"U16_F")\n", port)); - - rebind = 0; - /* Check for double bind and rebind of the same pcb */ - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - /* is this UDP PCB already on active list? */ - if (pcb == ipcb) { - rebind = 1; - break; - } - } - - /* no port specified? */ - if (port == 0) { - port = udp_new_port(); - if (port == 0) { - /* no more ports available in local range */ - LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n")); - return ERR_USE; - } - } else { - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - if (pcb != ipcb) { - /* By default, we don't allow to bind to a port that any other udp - PCB is already bound to, unless *all* PCBs with that port have tha - REUSEADDR flag set. */ -#if SO_REUSE - if (!ip_get_option(pcb, SOF_REUSEADDR) || - !ip_get_option(ipcb, SOF_REUSEADDR)) -#endif /* SO_REUSE */ - { - /* port matches that of PCB in list and REUSEADDR not set -> reject */ - if ((ipcb->local_port == port) && - /* IP address matches? */ - ip_addr_cmp(&ipcb->local_ip, ipaddr)) { - /* other PCB already binds to this local IP and port */ - LWIP_DEBUGF(UDP_DEBUG, - ("udp_bind: local port %"U16_F" already bound by another pcb\n", port)); - return ERR_USE; - } - } - } - } - } - - ip_addr_set_ipaddr(&pcb->local_ip, ipaddr); - - pcb->local_port = port; - mib2_udp_bind(pcb); - /* pcb not active yet? */ - if (rebind == 0) { - /* place the PCB on the active list if not already there */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; - } - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_bind: bound to ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, &pcb->local_ip); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->local_port)); - return ERR_OK; -} - -/** - * @ingroup udp_raw - * Connect an UDP PCB. - * - * This will associate the UDP PCB with the remote address. - * - * @param pcb UDP PCB to be connected with remote address ipaddr and port. - * @param ipaddr remote IP address to connect with. - * @param port remote UDP port to connect with. - * - * @return lwIP error code - * - * ipaddr & port are expected to be in the same byte order as in the pcb. - * - * The udp pcb is bound to a random local port if not already bound. - * - * @see udp_disconnect() - */ -err_t -udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) -{ - struct udp_pcb *ipcb; - - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - - if (pcb->local_port == 0) { - err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port); - if (err != ERR_OK) { - return err; - } - } - - ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); - pcb->remote_port = port; - pcb->flags |= UDP_FLAGS_CONNECTED; - - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("udp_connect: connected to ")); - ip_addr_debug_print(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, - &pcb->remote_ip); - LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, (", port %"U16_F")\n", pcb->remote_port)); - - /* Insert UDP PCB into the list of active UDP PCBs. */ - for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) { - if (pcb == ipcb) { - /* already on the list, just return */ - return ERR_OK; - } - } - /* PCB not yet on the list, add PCB now */ - pcb->next = udp_pcbs; - udp_pcbs = pcb; - return ERR_OK; -} - -/** - * @ingroup udp_raw - * Disconnect a UDP PCB - * - * @param pcb the udp pcb to disconnect. - */ -void -udp_disconnect(struct udp_pcb *pcb) -{ - /* reset remote address association */ -#if LWIP_IPV4 && LWIP_IPV6 - if (IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { - ip_addr_copy(pcb->remote_ip, *IP_ANY_TYPE); - } else { -#endif - ip_addr_set_any(IP_IS_V6_VAL(pcb->remote_ip), &pcb->remote_ip); -#if LWIP_IPV4 && LWIP_IPV6 - } -#endif - pcb->remote_port = 0; - /* mark PCB as unconnected */ - pcb->flags &= ~UDP_FLAGS_CONNECTED; -} - -/** - * @ingroup udp_raw - * Set a receive callback for a UDP PCB - * - * This callback will be called when receiving a datagram for the pcb. - * - * @param pcb the pcb for which to set the recv callback - * @param recv function pointer of the callback function - * @param recv_arg additional argument to pass to the callback function - */ -void -udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) -{ - /* remember recv() callback and user data */ - pcb->recv = recv; - pcb->recv_arg = recv_arg; -} - -/** - * @ingroup udp_raw - * Remove an UDP PCB. - * - * @param pcb UDP PCB to be removed. The PCB is removed from the list of - * UDP PCB's and the data structure is freed from memory. - * - * @see udp_new() - */ -void -udp_remove(struct udp_pcb *pcb) -{ - struct udp_pcb *pcb2; - - mib2_udp_unbind(pcb); - /* pcb to be removed is first in list? */ - if (udp_pcbs == pcb) { - /* make list start at 2nd pcb */ - udp_pcbs = udp_pcbs->next; - /* pcb not 1st in list */ - } else { - for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { - /* find pcb in udp_pcbs list */ - if (pcb2->next != NULL && pcb2->next == pcb) { - /* remove pcb from list */ - pcb2->next = pcb->next; - break; - } - } - } - memp_free(MEMP_UDP_PCB, pcb); -} - -/** - * @ingroup udp_raw - * Create a UDP PCB. - * - * @return The UDP PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @see udp_remove() - */ -struct udp_pcb * -udp_new(void) -{ - struct udp_pcb *pcb; - pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB); - /* could allocate UDP PCB? */ - if (pcb != NULL) { - /* UDP Lite: by initializing to all zeroes, chksum_len is set to 0 - * which means checksum is generated over the whole datagram per default - * (recommended as default by RFC 3828). */ - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct udp_pcb)); - pcb->ttl = UDP_TTL; -#if LWIP_MULTICAST_TX_OPTIONS - udp_set_multicast_ttl(pcb, UDP_TTL); -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - } - return pcb; -} - -/** - * @ingroup udp_raw - * Create a UDP PCB for specific IP type. - * - * @param type IP address type, see @ref lwip_ip_addr_type definitions. - * If you want to listen to IPv4 and IPv6 (dual-stack) packets, - * supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE. - * @return The UDP PCB which was created. NULL if the PCB data structure - * could not be allocated. - * - * @see udp_remove() - */ -struct udp_pcb * -udp_new_ip_type(u8_t type) -{ - struct udp_pcb *pcb; - pcb = udp_new(); -#if LWIP_IPV4 && LWIP_IPV6 - if (pcb != NULL) { - IP_SET_TYPE_VAL(pcb->local_ip, type); - IP_SET_TYPE_VAL(pcb->remote_ip, type); - } -#else - LWIP_UNUSED_ARG(type); -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - return pcb; -} - -/** This function is called from netif.c when address is changed - * - * @param old_addr IP address of the netif before change - * @param new_addr IP address of the netif after change - */ -void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr) -{ - struct udp_pcb* upcb; - - if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) { - for (upcb = udp_pcbs; upcb != NULL; upcb = upcb->next) { - /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&upcb->local_ip, old_addr)) { - /* The PCB is bound to the old ipaddr and - * is set to bound to the new one instead */ - ip_addr_copy(upcb->local_ip, *new_addr); - } - } - } -} - -#if UDP_DEBUG -/** - * Print UDP header information for debug purposes. - * - * @param udphdr pointer to the udp header in memory. - */ -void -udp_debug_print(struct udp_hdr *udphdr) -{ - LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n")); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n", - lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest))); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); - LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n", - lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum))); - LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n")); -} -#endif /* UDP_DEBUG */ - -#endif /* LWIP_UDP */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/api.h b/components/net/lwip-2.0.2/src/include/lwip/api.h deleted file mode 100644 index 516bd163dd..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/api.h +++ /dev/null @@ -1,400 +0,0 @@ -/** - * @file - * netconn API (to be used from non-TCPIP threads) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_API_H -#define LWIP_HDR_API_H - -#include "lwip/opt.h" - -#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -/* Note: Netconn API is always available when sockets are enabled - - * sockets are implemented on top of them */ - -#include "lwip/arch.h" -#include "lwip/netbuf.h" -#include "lwip/sys.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Throughout this file, IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ - -/* Flags for netconn_write (u8_t) */ -#define NETCONN_NOFLAG 0x00 -#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ -#define NETCONN_COPY 0x01 -#define NETCONN_MORE 0x02 -#define NETCONN_DONTBLOCK 0x04 - -/* Flags for struct netconn.flags (u8_t) */ -/** Should this netconn avoid blocking? */ -#define NETCONN_FLAG_NON_BLOCKING 0x02 -/** Was the last connect action a non-blocking one? */ -#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 -/** If a nonblocking write has been rejected before, poll_tcp needs to - check if the netconn is writable again */ -#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 -#if LWIP_IPV6 -/** If this flag is set then only IPv6 communication is allowed on the - netconn. As per RFC#3493 this features defaults to OFF allowing - dual-stack usage by default. */ -#define NETCONN_FLAG_IPV6_V6ONLY 0x20 -#endif /* LWIP_IPV6 */ - - -/* Helpers to process several netconn_types by the same code */ -#define NETCONNTYPE_GROUP(t) ((t)&0xF0) -#define NETCONNTYPE_DATAGRAM(t) ((t)&0xE0) -#if LWIP_IPV6 -#define NETCONN_TYPE_IPV6 0x08 -#define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0) -#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) -#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) -#else /* LWIP_IPV6 */ -#define NETCONNTYPE_ISIPV6(t) (0) -#define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) -#define NETCONNTYPE_ISUDPNOCHKSUM(t) ((t) == NETCONN_UDPNOCHKSUM) -#endif /* LWIP_IPV6 */ - -/** @ingroup netconn_common - * Protocol family and type of the netconn - */ -enum netconn_type { - NETCONN_INVALID = 0, - /** TCP IPv4 */ - NETCONN_TCP = 0x10, -#if LWIP_IPV6 - /** TCP IPv6 */ - NETCONN_TCP_IPV6 = NETCONN_TCP | NETCONN_TYPE_IPV6 /* 0x18 */, -#endif /* LWIP_IPV6 */ - /** UDP IPv4 */ - NETCONN_UDP = 0x20, - /** UDP IPv4 lite */ - NETCONN_UDPLITE = 0x21, - /** UDP IPv4 no checksum */ - NETCONN_UDPNOCHKSUM = 0x22, - -#if LWIP_IPV6 - /** UDP IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - NETCONN_UDP_IPV6 = NETCONN_UDP | NETCONN_TYPE_IPV6 /* 0x28 */, - /** UDP IPv6 lite (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - NETCONN_UDPLITE_IPV6 = NETCONN_UDPLITE | NETCONN_TYPE_IPV6 /* 0x29 */, - /** UDP IPv6 no checksum (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - NETCONN_UDPNOCHKSUM_IPV6 = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_IPV6 /* 0x2a */, -#endif /* LWIP_IPV6 */ - - /** Raw connection IPv4 */ - NETCONN_RAW = 0x40 -#if LWIP_IPV6 - /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ - , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ -#endif /* LWIP_IPV6 */ -}; - -/** Current state of the netconn. Non-TCP netconns are always - * in state NETCONN_NONE! */ -enum netconn_state { - NETCONN_NONE, - NETCONN_WRITE, - NETCONN_LISTEN, - NETCONN_CONNECT, - NETCONN_CLOSE -}; - -/** Used to inform the callback function about changes - * - * Event explanation: - * - * In the netconn implementation, there are three ways to block a client: - * - * - accept mbox (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); in netconn_accept()) - * - receive mbox (sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); in netconn_recv_data()) - * - send queue is full (sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0); in lwip_netconn_do_write()) - * - * The events have to be seen as events signaling the state of these mboxes/semaphores. For non-blocking - * connections, you need to know in advance whether a call to a netconn function call would block or not, - * and these events tell you about that. - * - * RCVPLUS events say: Safe to perform a potentially blocking call call once more. - * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe - * to call netconn_accept 3 times without being blocked. - * Same thing for receive mbox. - * - * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged". - * Socket implementation decrements the counter. - * - * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something. - * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again. - * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking. - */ -enum netconn_evt { - NETCONN_EVT_RCVPLUS, - NETCONN_EVT_RCVMINUS, - NETCONN_EVT_SENDPLUS, - NETCONN_EVT_SENDMINUS, - NETCONN_EVT_ERROR -}; - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -/** Used for netconn_join_leave_group() */ -enum netconn_igmp { - NETCONN_JOIN, - NETCONN_LEAVE -}; -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -/* Used for netconn_gethostbyname_addrtype(), these should match the DNS_ADDRTYPE defines in dns.h */ -#define NETCONN_DNS_DEFAULT NETCONN_DNS_IPV4_IPV6 -#define NETCONN_DNS_IPV4 0 -#define NETCONN_DNS_IPV6 1 -#define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ -#define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ -#endif /* LWIP_DNS */ - -/* forward-declare some structs to avoid to include their headers */ -struct ip_pcb; -struct tcp_pcb; -struct udp_pcb; -struct raw_pcb; -struct netconn; -struct api_msg; - -/** A callback prototype to inform about events for a netconn */ -typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); - -/** A netconn descriptor */ -struct netconn { - /** type of the netconn (TCP, UDP or RAW) */ - enum netconn_type type; - /** current state of the netconn */ - enum netconn_state state; - /** the lwIP internal protocol control block */ - union { - struct ip_pcb *ip; - struct tcp_pcb *tcp; - struct udp_pcb *udp; - struct raw_pcb *raw; - } pcb; - /** the last error this netconn had */ - err_t last_err; -#if !LWIP_NETCONN_SEM_PER_THREAD - /** sem that is used to synchronously execute functions in the core context */ - sys_sem_t op_completed; -#endif - /** mbox where received packets are stored until they are fetched - by the netconn application thread (can grow quite big) */ - sys_mbox_t recvmbox; -#if LWIP_TCP - /** mbox where new connections are stored until processed - by the application thread */ - sys_mbox_t acceptmbox; -#endif /* LWIP_TCP */ - /** only used for socket layer */ -#if LWIP_SOCKET - int socket; -#endif /* LWIP_SOCKET */ -#if LWIP_SO_SNDTIMEO - /** timeout to wait for sending data (which means enqueueing data for sending - in internal buffers) in milliseconds */ - s32_t send_timeout; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVTIMEO - /** timeout in milliseconds to wait for new data to be received - (or connections to arrive for listening netconns) */ - int recv_timeout; -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF - /** maximum amount of bytes queued in recvmbox - not used for TCP: adjust TCP_WND instead! */ - int recv_bufsize; - /** number of bytes currently in recvmbox to be received, - tested against recv_bufsize to limit bytes on recvmbox - for UDP and RAW, used for FIONREAD */ - int recv_avail; -#endif /* LWIP_SO_RCVBUF */ -#if LWIP_SO_LINGER - /** values <0 mean linger is disabled, values > 0 are seconds to linger */ - s16_t linger; -#endif /* LWIP_SO_LINGER */ - /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ - u8_t flags; -#if LWIP_TCP - /** TCP: when data passed to netconn_write doesn't fit into the send buffer, - this temporarily stores how much is already sent. */ - size_t write_offset; - /** TCP: when data passed to netconn_write doesn't fit into the send buffer, - this temporarily stores the message. - Also used during connect and close. */ - struct api_msg *current_msg; -#endif /* LWIP_TCP */ - /** A callback function that is informed about events for this netconn */ - netconn_callback callback; -}; - -/** Register an Network connection event */ -#define API_EVENT(c,e,l) if (c->callback) { \ - (*c->callback)(c, e, l); \ - } - -/** Set conn->last_err to err but don't overwrite fatal errors */ -#define NETCONN_SET_SAFE_ERR(conn, err) do { if ((conn) != NULL) { \ - SYS_ARCH_DECL_PROTECT(netconn_set_safe_err_lev); \ - SYS_ARCH_PROTECT(netconn_set_safe_err_lev); \ - if (!ERR_IS_FATAL((conn)->last_err)) { \ - (conn)->last_err = err; \ - } \ - SYS_ARCH_UNPROTECT(netconn_set_safe_err_lev); \ -}} while(0); - -/* Network connection functions: */ - -/** @ingroup netconn_common - * Create new netconn connection - * @param t @ref netconn_type */ -#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) -#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) -struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, - netconn_callback callback); -err_t netconn_delete(struct netconn *conn); -/** Get the type of a netconn (as enum netconn_type). */ -#define netconn_type(conn) (conn->type) - -err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, - u16_t *port, u8_t local); -/** @ingroup netconn_common */ -#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) -/** @ingroup netconn_common */ -#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) - -err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); -err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port); -err_t netconn_disconnect (struct netconn *conn); -err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); -/** @ingroup netconn_tcp */ -#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) -err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); -err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); -err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); -err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, - const ip_addr_t *addr, u16_t port); -err_t netconn_send(struct netconn *conn, struct netbuf *buf); -err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, - u8_t apiflags, size_t *bytes_written); -/** @ingroup netconn_tcp */ -#define netconn_write(conn, dataptr, size, apiflags) \ - netconn_write_partly(conn, dataptr, size, apiflags, NULL) -err_t netconn_close(struct netconn *conn); -err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); - -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -err_t netconn_join_leave_group(struct netconn *conn, const ip_addr_t *multiaddr, - const ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ -#if LWIP_DNS -#if LWIP_IPV4 && LWIP_IPV6 -err_t netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype); -#define netconn_gethostbyname(name, addr) netconn_gethostbyname_addrtype(name, addr, NETCONN_DNS_DEFAULT) -#else /* LWIP_IPV4 && LWIP_IPV6 */ -err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); -#define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ -#endif /* LWIP_DNS */ - -#define netconn_err(conn) ((conn)->last_err) -#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) - -/** Set the blocking status of netconn calls (@todo: write/send is missing) */ -#define netconn_set_nonblocking(conn, val) do { if(val) { \ - (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) -/** Get the blocking status of netconn calls (@todo: write/send is missing) */ -#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) - -#if LWIP_IPV6 -/** @ingroup netconn_common - * TCP: Set the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) - */ -#define netconn_set_ipv6only(conn, val) do { if(val) { \ - (conn)->flags |= NETCONN_FLAG_IPV6_V6ONLY; \ -} else { \ - (conn)->flags &= ~ NETCONN_FLAG_IPV6_V6ONLY; }} while(0) -/** @ingroup netconn_common - * TCP: Get the IPv6 ONLY status of netconn calls (see NETCONN_FLAG_IPV6_V6ONLY) - */ -#define netconn_get_ipv6only(conn) (((conn)->flags & NETCONN_FLAG_IPV6_V6ONLY) != 0) -#endif /* LWIP_IPV6 */ - -#if LWIP_SO_SNDTIMEO -/** Set the send timeout in milliseconds */ -#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout)) -/** Get the send timeout in milliseconds */ -#define netconn_get_sendtimeout(conn) ((conn)->send_timeout) -#endif /* LWIP_SO_SNDTIMEO */ -#if LWIP_SO_RCVTIMEO -/** Set the receive timeout in milliseconds */ -#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) -/** Get the receive timeout in milliseconds */ -#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) -#endif /* LWIP_SO_RCVTIMEO */ -#if LWIP_SO_RCVBUF -/** Set the receive buffer in bytes */ -#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) -/** Get the receive buffer in bytes */ -#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) -#endif /* LWIP_SO_RCVBUF*/ - -#if LWIP_NETCONN_SEM_PER_THREAD -void netconn_thread_init(void); -void netconn_thread_cleanup(void); -#else /* LWIP_NETCONN_SEM_PER_THREAD */ -#define netconn_thread_init() -#define netconn_thread_cleanup() -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#endif /* LWIP_HDR_API_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/FILES b/components/net/lwip-2.0.2/src/include/lwip/apps/FILES deleted file mode 100644 index adfc0f3345..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/FILES +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains application headers. -Every application shall provide one api file APP.h and optionally one options file APP_opts.h diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/fs.h b/components/net/lwip-2.0.2/src/include/lwip/apps/fs.h deleted file mode 100644 index bb176fa010..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/fs.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_APPS_FS_H -#define LWIP_HDR_APPS_FS_H - -#include "httpd_opts.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define FS_READ_EOF -1 -#define FS_READ_DELAYED -2 - -#if HTTPD_PRECALCULATED_CHECKSUM -struct fsdata_chksum { - u32_t offset; - u16_t chksum; - u16_t len; -}; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ - -#define FS_FILE_FLAGS_HEADER_INCLUDED 0x01 -#define FS_FILE_FLAGS_HEADER_PERSISTENT 0x02 - -struct fs_file { - const char *data; - int len; - int index; - void *pextension; -#if HTTPD_PRECALCULATED_CHECKSUM - const struct fsdata_chksum *chksum; - u16_t chksum_count; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ - u8_t flags; -#if LWIP_HTTPD_CUSTOM_FILES - u8_t is_custom_file; -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#if LWIP_HTTPD_FILE_STATE - void *state; -#endif /* LWIP_HTTPD_FILE_STATE */ -}; - -#if LWIP_HTTPD_FS_ASYNC_READ -typedef void (*fs_wait_cb)(void *arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -err_t fs_open(struct fs_file *file, const char *name); -void fs_close(struct fs_file *file); -#if LWIP_HTTPD_DYNAMIC_FILE_READ -#if LWIP_HTTPD_FS_ASYNC_READ -int fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_read(struct fs_file *file, char *buffer, int count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -#if LWIP_HTTPD_FS_ASYNC_READ -int fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_bytes_left(struct fs_file *file); - -#if LWIP_HTTPD_FILE_STATE -/** This user-defined function is called when a file is opened. */ -void *fs_state_init(struct fs_file *file, const char *name); -/** This user-defined function is called when a file is closed. */ -void fs_state_free(struct fs_file *file, void *state); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_FS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/httpd.h b/components/net/lwip-2.0.2/src/include/lwip/apps/httpd.h deleted file mode 100644 index 40f1811e57..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/httpd.h +++ /dev/null @@ -1,236 +0,0 @@ -/** - * @file - * HTTP server - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * This version of the file has been modified by Texas Instruments to offer - * simple server-side-include (SSI) and Common Gateway Interface (CGI) - * capability. - */ - -#ifndef LWIP_HDR_APPS_HTTPD_H -#define LWIP_HDR_APPS_HTTPD_H - -#include "httpd_opts.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_HTTPD_CGI - -/* - * Function pointer for a CGI script handler. - * - * This function is called each time the HTTPD server is asked for a file - * whose name was previously registered as a CGI function using a call to - * http_set_cgi_handler. The iIndex parameter provides the index of the - * CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters - * pcParam and pcValue provide access to the parameters provided along with - * the URI. iNumParams provides a count of the entries in the pcParam and - * pcValue arrays. Each entry in the pcParam array contains the name of a - * parameter with the corresponding entry in the pcValue array containing the - * value for that parameter. Note that pcParam may contain multiple elements - * with the same name if, for example, a multi-selection list control is used - * in the form generating the data. - * - * The function should return a pointer to a character string which is the - * path and filename of the response that is to be sent to the connected - * browser, for example "/thanks.htm" or "/response/error.ssi". - * - * The maximum number of parameters that will be passed to this function via - * iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming - * HTTP request above this number will be discarded. - * - * Requests intended for use by this CGI mechanism must be sent using the GET - * method (which encodes all parameters within the URI rather than in a block - * later in the request). Attempts to use the POST method will result in the - * request being ignored. - * - */ -typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[], - char *pcValue[]); - -/* - * Structure defining the base filename (URL) of a CGI and the associated - * function which is to be called when that URL is requested. - */ -typedef struct -{ - const char *pcCGIName; - tCGIHandler pfnCGIHandler; -} tCGI; - -void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers); - -#endif /* LWIP_HTTPD_CGI */ - -#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI - -#if LWIP_HTTPD_CGI_SSI -/** Define this generic CGI handler in your application. - * It is called once for every URI with parameters. - * The parameters can be stored to - */ -extern void httpd_cgi_handler(const char* uri, int iNumParams, char **pcParam, char **pcValue -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , void *connection_state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); -#endif /* LWIP_HTTPD_CGI_SSI */ - -#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ - -#if LWIP_HTTPD_SSI - -/* - * Function pointer for the SSI tag handler callback. - * - * This function will be called each time the HTTPD server detects a tag of the - * form in a .shtml, .ssi or .shtm file where "name" appears as - * one of the tags supplied to http_set_ssi_handler in the ppcTags array. The - * returned insert string, which will be appended after the the string - * "" in file sent back to the client,should be written to pointer - * pcInsert. iInsertLen contains the size of the buffer pointed to by - * pcInsert. The iIndex parameter provides the zero-based index of the tag as - * found in the ppcTags array and identifies the tag that is to be processed. - * - * The handler returns the number of characters written to pcInsert excluding - * any terminating NULL or a negative number to indicate a failure (tag not - * recognized, for example). - * - * Note that the behavior of this SSI mechanism is somewhat different from the - * "normal" SSI processing as found in, for example, the Apache web server. In - * this case, the inserted text is appended following the SSI tag rather than - * replacing the tag entirely. This allows for an implementation that does not - * require significant additional buffering of output data yet which will still - * offer usable SSI functionality. One downside to this approach is when - * attempting to use SSI within JavaScript. The SSI tag is structured to - * resemble an HTML comment but this syntax does not constitute a comment - * within JavaScript and, hence, leaving the tag in place will result in - * problems in these cases. To work around this, any SSI tag which needs to - * output JavaScript code must do so in an encapsulated way, sending the whole - * HTML section as a single include. - */ -typedef u16_t (*tSSIHandler)( -#if LWIP_HTTPD_SSI_RAW - const char* ssi_tag_name, -#else /* LWIP_HTTPD_SSI_RAW */ - int iIndex, -#endif /* LWIP_HTTPD_SSI_RAW */ - char *pcInsert, int iInsertLen -#if LWIP_HTTPD_SSI_MULTIPART - , u16_t current_tag_part, u16_t *next_tag_part -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , void *connection_state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); - -/** Set the SSI handler function - * (if LWIP_HTTPD_SSI_RAW==1, only the first argument is used) - */ -void http_set_ssi_handler(tSSIHandler pfnSSIHandler, - const char **ppcTags, int iNumTags); - -/** For LWIP_HTTPD_SSI_RAW==1, return this to indicate the tag is unknown. - * In this case, the webserver writes a warning into the page. - * You can also just return 0 to write nothing for unknown tags. - */ -#define HTTPD_SSI_TAG_UNKNOWN 0xFFFF - -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_SUPPORT_POST - -/* These functions must be implemented by the application */ - -/** Called when a POST request has been received. The application can decide - * whether to accept it or not. - * - * @param connection Unique connection identifier, valid until httpd_post_end - * is called. - * @param uri The HTTP header URI receiving the POST request. - * @param http_request The raw HTTP request (the first packet, normally). - * @param http_request_len Size of 'http_request'. - * @param content_len Content-Length from HTTP header. - * @param response_uri Filename of response file, to be filled when denying the - * request - * @param response_uri_len Size of the 'response_uri' buffer. - * @param post_auto_wnd Set this to 0 to let the callback code handle window - * updates by calling 'httpd_post_data_recved' (to throttle rx speed) - * default is 1 (httpd handles window updates automatically) - * @return ERR_OK: Accept the POST request, data may be passed in - * another err_t: Deny the POST request, send back 'bad request'. - */ -err_t httpd_post_begin(void *connection, const char *uri, const char *http_request, - u16_t http_request_len, int content_len, char *response_uri, - u16_t response_uri_len, u8_t *post_auto_wnd); - -/** Called for each pbuf of data that has been received for a POST. - * ATTENTION: The application is responsible for freeing the pbufs passed in! - * - * @param connection Unique connection identifier. - * @param p Received data. - * @return ERR_OK: Data accepted. - * another err_t: Data denied, http_post_get_response_uri will be called. - */ -err_t httpd_post_receive_data(void *connection, struct pbuf *p); - -/** Called when all data is received or when the connection is closed. - * The application must return the filename/URI of a file to send in response - * to this POST request. If the response_uri buffer is untouched, a 404 - * response is returned. - * - * @param connection Unique connection identifier. - * @param response_uri Filename of response file, to be filled when denying the request - * @param response_uri_len Size of the 'response_uri' buffer. - */ -void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len); - -#if LWIP_HTTPD_POST_MANUAL_WND -void httpd_post_data_recved(void *connection, u16_t recved_len); -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - -#endif /* LWIP_HTTPD_SUPPORT_POST */ - -void httpd_init(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HTTPD_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/httpd_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/httpd_opts.h deleted file mode 100644 index 340db15f66..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/httpd_opts.h +++ /dev/null @@ -1,323 +0,0 @@ -/** - * @file - * HTTP server options list - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * This version of the file has been modified by Texas Instruments to offer - * simple server-side-include (SSI) and Common Gateway Interface (CGI) - * capability. - */ - -#ifndef LWIP_HDR_APPS_HTTPD_OPTS_H -#define LWIP_HDR_APPS_HTTPD_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup httpd_opts Options - * @ingroup httpd - * @{ - */ - -/** Set this to 1 to support CGI (old style) */ -#if !defined LWIP_HTTPD_CGI || defined __DOXYGEN__ -#define LWIP_HTTPD_CGI 0 -#endif - -/** Set this to 1 to support CGI (new style) */ -#if !defined LWIP_HTTPD_CGI_SSI || defined __DOXYGEN__ -#define LWIP_HTTPD_CGI_SSI 0 -#endif - -/** Set this to 1 to support SSI (Server-Side-Includes) */ -#if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI 0 -#endif - -/** Set this to 1 to implement an SSI tag handler callback that gets a const char* - * to the tag (instead of an index into a pre-registered array of known tags) */ -#if !defined LWIP_HTTPD_SSI_RAW || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI_RAW 0 -#endif - -/** Set this to 1 to support HTTP POST */ -#if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_POST 0 -#endif - -/* The maximum number of parameters that the CGI handler can be sent. */ -#if !defined LWIP_HTTPD_MAX_CGI_PARAMETERS || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_CGI_PARAMETERS 16 -#endif - -/** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more - * arguments indicating a counter for insert string that are too long to be - * inserted at once: the SSI handler function must then set 'next_tag_part' - * which will be passed back to it in the next call. */ -#if !defined LWIP_HTTPD_SSI_MULTIPART || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI_MULTIPART 0 -#endif - -/* The maximum length of the string comprising the tag name */ -#if !defined LWIP_HTTPD_MAX_TAG_NAME_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_TAG_NAME_LEN 8 -#endif - -/* The maximum length of string that can be returned to replace any given tag */ -#if !defined LWIP_HTTPD_MAX_TAG_INSERT_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192 -#endif - -#if !defined LWIP_HTTPD_POST_MANUAL_WND || defined __DOXYGEN__ -#define LWIP_HTTPD_POST_MANUAL_WND 0 -#endif - -/** This string is passed in the HTTP header as "Server: " */ -#if !defined HTTPD_SERVER_AGENT || defined __DOXYGEN__ -#define HTTPD_SERVER_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)" -#endif - -/** Set this to 1 if you want to include code that creates HTTP headers - * at runtime. Default is off: HTTP headers are then created statically - * by the makefsdata tool. Static headers mean smaller code size, but - * the (readonly) fsdata will grow a bit as every file includes the HTTP - * header. */ -#if !defined LWIP_HTTPD_DYNAMIC_HEADERS || defined __DOXYGEN__ -#define LWIP_HTTPD_DYNAMIC_HEADERS 0 -#endif - -#if !defined HTTPD_DEBUG || defined __DOXYGEN__ -#define HTTPD_DEBUG LWIP_DBG_OFF -#endif - -/** Set this to 1 to use a memp pool for allocating - * struct http_state instead of the heap. - */ -#if !defined HTTPD_USE_MEM_POOL || defined __DOXYGEN__ -#define HTTPD_USE_MEM_POOL 0 -#endif - -/** The server port for HTTPD to use */ -#if !defined HTTPD_SERVER_PORT || defined __DOXYGEN__ -#define HTTPD_SERVER_PORT 80 -#endif - -/** Maximum retries before the connection is aborted/closed. - * - number of times pcb->poll is called -> default is 4*500ms = 2s; - * - reset when pcb->sent is called - */ -#if !defined HTTPD_MAX_RETRIES || defined __DOXYGEN__ -#define HTTPD_MAX_RETRIES 4 -#endif - -/** The poll delay is X*500ms */ -#if !defined HTTPD_POLL_INTERVAL || defined __DOXYGEN__ -#define HTTPD_POLL_INTERVAL 4 -#endif - -/** Priority for tcp pcbs created by HTTPD (very low by default). - * Lower priorities get killed first when running out of memory. - */ -#if !defined HTTPD_TCP_PRIO || defined __DOXYGEN__ -#define HTTPD_TCP_PRIO TCP_PRIO_MIN -#endif - -/** Set this to 1 to enable timing each file sent */ -#if !defined LWIP_HTTPD_TIMING || defined __DOXYGEN__ -#define LWIP_HTTPD_TIMING 0 -#endif -/** Set this to 1 to enable timing each file sent */ -#if !defined HTTPD_DEBUG_TIMING || defined __DOXYGEN__ -#define HTTPD_DEBUG_TIMING LWIP_DBG_OFF -#endif - -/** Set this to one to show error pages when parsing a request fails instead - of simply closing the connection. */ -#if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_EXTSTATUS 0 -#endif - -/** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */ -#if !defined LWIP_HTTPD_SUPPORT_V09 || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_V09 1 -#endif - -/** Set this to 1 to enable HTTP/1.1 persistent connections. - * ATTENTION: If the generated file system includes HTTP headers, these must - * include the "Connection: keep-alive" header (pass argument "-11" to makefsdata). - */ -#if !defined LWIP_HTTPD_SUPPORT_11_KEEPALIVE || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_11_KEEPALIVE 0 -#endif - -/** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */ -#if !defined LWIP_HTTPD_SUPPORT_REQUESTLIST || defined __DOXYGEN__ -#define LWIP_HTTPD_SUPPORT_REQUESTLIST 1 -#endif - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST -/** Number of rx pbufs to enqueue to parse an incoming request (up to the first - newline) */ -#if !defined LWIP_HTTPD_REQ_QUEUELEN || defined __DOXYGEN__ -#define LWIP_HTTPD_REQ_QUEUELEN 5 -#endif - -/** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming - request (up to the first double-newline) */ -#if !defined LWIP_HTTPD_REQ_BUFSIZE || defined __DOXYGEN__ -#define LWIP_HTTPD_REQ_BUFSIZE LWIP_HTTPD_MAX_REQ_LENGTH -#endif - -/** Defines the maximum length of a HTTP request line (up to the first CRLF, - copied from pbuf into this a global buffer when pbuf- or packet-queues - are received - otherwise the input pbuf is used directly) */ -#if !defined LWIP_HTTPD_MAX_REQ_LENGTH || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_REQ_LENGTH LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE)) -#endif -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -/** This is the size of a static buffer used when URIs end with '/'. - * In this buffer, the directory requested is concatenated with all the - * configured default file names. - * Set to 0 to disable checking default filenames on non-root directories. - */ -#if !defined LWIP_HTTPD_MAX_REQUEST_URI_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_MAX_REQUEST_URI_LEN 63 -#endif - -/** Maximum length of the filename to send as response to a POST request, - * filled in by the application when a POST is finished. - */ -#if !defined LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN || defined __DOXYGEN__ -#define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63 -#endif - -/** Set this to 0 to not send the SSI tag (default is on, so the tag will - * be sent in the HTML page */ -#if !defined LWIP_HTTPD_SSI_INCLUDE_TAG || defined __DOXYGEN__ -#define LWIP_HTTPD_SSI_INCLUDE_TAG 1 -#endif - -/** Set this to 1 to call tcp_abort when tcp_close fails with memory error. - * This can be used to prevent consuming all memory in situations where the - * HTTP server has low priority compared to other communication. */ -#if !defined LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR || defined __DOXYGEN__ -#define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR 0 -#endif - -/** Set this to 1 to kill the oldest connection when running out of - * memory for 'struct http_state' or 'struct http_ssi_state'. - * ATTENTION: This puts all connections on a linked list, so may be kind of slow. - */ -#if !defined LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED || defined __DOXYGEN__ -#define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0 -#endif - -/** Set this to 1 to send URIs without extension without headers - * (who uses this at all??) */ -#if !defined LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI || defined __DOXYGEN__ -#define LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI 0 -#endif - -/** Default: Tags are sent from struct http_state and are therefore volatile */ -#if !defined HTTP_IS_TAG_VOLATILE || defined __DOXYGEN__ -#define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY -#endif - -/* By default, the httpd is limited to send 2*pcb->mss to keep resource usage low - when http is not an important protocol in the device. */ -#if !defined HTTPD_LIMIT_SENDING_TO_2MSS || defined __DOXYGEN__ -#define HTTPD_LIMIT_SENDING_TO_2MSS 1 -#endif - -/* Define this to a function that returns the maximum amount of data to enqueue. - The function have this signature: u16_t fn(struct tcp_pcb* pcb); */ -#if !defined HTTPD_MAX_WRITE_LEN || defined __DOXYGEN__ -#if HTTPD_LIMIT_SENDING_TO_2MSS -#define HTTPD_MAX_WRITE_LEN(pcb) (2 * tcp_mss(pcb)) -#endif -#endif - -/*------------------- FS OPTIONS -------------------*/ - -/** Set this to 1 and provide the functions: - * - "int fs_open_custom(struct fs_file *file, const char *name)" - * Called first for every opened file to allow opening files - * that are not included in fsdata(_custom).c - * - "void fs_close_custom(struct fs_file *file)" - * Called to free resources allocated by fs_open_custom(). - */ -#if !defined LWIP_HTTPD_CUSTOM_FILES || defined __DOXYGEN__ -#define LWIP_HTTPD_CUSTOM_FILES 0 -#endif - -/** Set this to 1 to support fs_read() to dynamically read file data. - * Without this (default=off), only one-block files are supported, - * and the contents must be ready after fs_open(). - */ -#if !defined LWIP_HTTPD_DYNAMIC_FILE_READ || defined __DOXYGEN__ -#define LWIP_HTTPD_DYNAMIC_FILE_READ 0 -#endif - -/** Set this to 1 to include an application state argument per file - * that is opened. This allows to keep a state per connection/file. - */ -#if !defined LWIP_HTTPD_FILE_STATE || defined __DOXYGEN__ -#define LWIP_HTTPD_FILE_STATE 0 -#endif - -/** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for - * predefined (MSS-sized) chunks of the files to prevent having to calculate - * the checksums at runtime. */ -#if !defined HTTPD_PRECALCULATED_CHECKSUM || defined __DOXYGEN__ -#define HTTPD_PRECALCULATED_CHECKSUM 0 -#endif - -/** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations - * (fs_read_async returns FS_READ_DELAYED and calls a callback when finished). - */ -#if !defined LWIP_HTTPD_FS_ASYNC_READ || defined __DOXYGEN__ -#define LWIP_HTTPD_FS_ASYNC_READ 0 -#endif - -/** Set this to 1 to include "fsdata_custom.c" instead of "fsdata.c" for the - * file system (to prevent changing the file included in CVS) */ -#if !defined HTTPD_USE_CUSTOM_FSDATA || defined __DOXYGEN__ -#define HTTPD_USE_CUSTOM_FSDATA 0 -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_HTTPD_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/lwiperf.h b/components/net/lwip-2.0.2/src/include/lwip/apps/lwiperf.h deleted file mode 100644 index 7dbebb0826..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/lwiperf.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file - * lwIP iPerf server implementation - */ - -/* - * Copyright (c) 2014 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_APPS_LWIPERF_H -#define LWIP_HDR_APPS_LWIPERF_H - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define LWIPERF_TCP_PORT_DEFAULT 5001 - -/** lwIPerf test results */ -enum lwiperf_report_type -{ - /** The server side test is done */ - LWIPERF_TCP_DONE_SERVER, - /** The client side test is done */ - LWIPERF_TCP_DONE_CLIENT, - /** Local error lead to test abort */ - LWIPERF_TCP_ABORTED_LOCAL, - /** Data check error lead to test abort */ - LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, - /** Transmit error lead to test abort */ - LWIPERF_TCP_ABORTED_LOCAL_TXERROR, - /** Remote side aborted the test */ - LWIPERF_TCP_ABORTED_REMOTE -}; - -/** Prototype of a report function that is called when a session is finished. - This report function can show the test results. - @param report_type contains the test result */ -typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, - const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, - u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec); - - -void* lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void* report_arg); -void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg); -void lwiperf_abort(void* lwiperf_session); - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_LWIPERF_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/mdns.h b/components/net/lwip-2.0.2/src/include/lwip/apps/mdns.h deleted file mode 100644 index d036816115..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/mdns.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file - * MDNS responder - */ - - /* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ -#ifndef LWIP_HDR_MDNS_H -#define LWIP_HDR_MDNS_H - -#include "lwip/apps/mdns_opts.h" -#include "lwip/netif.h" - -#if LWIP_MDNS_RESPONDER - -enum mdns_sd_proto { - DNSSD_PROTO_UDP = 0, - DNSSD_PROTO_TCP = 1 -}; - -#define MDNS_LABEL_MAXLEN 63 - -struct mdns_host; -struct mdns_service; - -/** Callback function to add text to a reply, called when generating the reply */ -typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); - -void mdns_resp_init(void); - -err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); -err_t mdns_resp_remove_netif(struct netif *netif); - -err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); -err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); -void mdns_resp_netif_settings_changed(struct netif *netif); - -#endif /* LWIP_MDNS_RESPONDER */ - -#endif /* LWIP_HDR_MDNS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/mdns_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/mdns_opts.h deleted file mode 100644 index bf186bcce1..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/mdns_opts.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file - * MDNS responder - */ - - /* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#ifndef LWIP_HDR_APPS_MDNS_OPTS_H -#define LWIP_HDR_APPS_MDNS_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup mdns_opts Options - * @ingroup mdns - * @{ - */ - -/** - * LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS - * transport. IGMP is needed for IPv4 multicast. - */ -#ifndef LWIP_MDNS_RESPONDER -#define LWIP_MDNS_RESPONDER 0 -#endif /* LWIP_MDNS_RESPONDER */ - -/** The maximum number of services per netif */ -#ifndef MDNS_MAX_SERVICES -#define MDNS_MAX_SERVICES 1 -#endif - -/** - * MDNS_DEBUG: Enable debugging for multicast DNS. - */ -#ifndef MDNS_DEBUG -#define MDNS_DEBUG LWIP_DBG_OFF -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ - diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/mdns_priv.h b/components/net/lwip-2.0.2/src/include/lwip/apps/mdns_priv.h deleted file mode 100644 index 8ee6db86af..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/mdns_priv.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file - * MDNS responder private definitions - */ - - /* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ -#ifndef LWIP_HDR_MDNS_PRIV_H -#define LWIP_HDR_MDNS_PRIV_H - -#include "lwip/apps/mdns_opts.h" -#include "lwip/pbuf.h" - -#if LWIP_MDNS_RESPONDER - -/* Domain struct and methods - visible for unit tests */ - -#define MDNS_DOMAIN_MAXLEN 256 -#define MDNS_READNAME_ERROR 0xFFFF - -struct mdns_domain { - /* Encoded domain name */ - u8_t name[MDNS_DOMAIN_MAXLEN]; - /* Total length of domain name, including zero */ - u16_t length; - /* Set if compression of this domain is not allowed */ - u8_t skip_compression; -}; - -err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); -u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); -int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); -u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); - -#endif /* LWIP_MDNS_RESPONDER */ - -#endif /* LWIP_HDR_MDNS_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/mqtt.h b/components/net/lwip-2.0.2/src/include/lwip/apps/mqtt.h deleted file mode 100644 index 34b230b888..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/mqtt.h +++ /dev/null @@ -1,244 +0,0 @@ -/** - * @file - * MQTT client - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Andersson - * - */ -#ifndef LWIP_HDR_APPS_MQTT_CLIENT_H -#define LWIP_HDR_APPS_MQTT_CLIENT_H - -#include "lwip/apps/mqtt_opts.h" -#include "lwip/err.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct mqtt_client_t mqtt_client_t; - -/** @ingroup mqtt - * Default MQTT port */ -#define MQTT_PORT 1883 - -/*---------------------------------------------------------------------------------------------- */ -/* Connection with server */ - -/** - * @ingroup mqtt - * Client information and connection parameters */ -struct mqtt_connect_client_info_t { - /** Client identifier, must be set by caller */ - const char *client_id; - /** User name and password, set to NULL if not used */ - const char* client_user; - const char* client_pass; - /** keep alive time in seconds, 0 to disable keep alive functionality*/ - u16_t keep_alive; - /** will topic, set to NULL if will is not to be used, - will_msg, will_qos and will retain are then ignored */ - const char* will_topic; - const char* will_msg; - u8_t will_qos; - u8_t will_retain; -}; - -/** - * @ingroup mqtt - * Connection status codes */ -typedef enum -{ - MQTT_CONNECT_ACCEPTED = 0, - MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1, - MQTT_CONNECT_REFUSED_IDENTIFIER = 2, - MQTT_CONNECT_REFUSED_SERVER = 3, - MQTT_CONNECT_REFUSED_USERNAME_PASS = 4, - MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_ = 5, - MQTT_CONNECT_DISCONNECTED = 256, - MQTT_CONNECT_TIMEOUT = 257 -} mqtt_connection_status_t; - -/** - * @ingroup mqtt - * Function prototype for mqtt connection status callback. Called when - * client has connected to the server after initiating a mqtt connection attempt by - * calling mqtt_connect() or when connection is closed by server or an error - * - * @param client MQTT client itself - * @param arg Additional argument to pass to the callback function - * @param status Connect result code or disconnection notification @see mqtt_connection_status_t - * - */ -typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); - - -/** - * @ingroup mqtt - * Data callback flags */ -enum { - /** Flag set when last fragment of data arrives in data callback */ - MQTT_DATA_FLAG_LAST = 1 -}; - -/** - * @ingroup mqtt - * Function prototype for MQTT incoming publish data callback function. Called when data - * arrives to a subscribed topic @see mqtt_subscribe - * - * @param arg Additional argument to pass to the callback function - * @param data User data, pointed object, data may not be referenced after callback return, - NULL is passed when all publish data are delivered - * @param len Length of publish data fragment - * @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message - * - */ -typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags); - - -/** - * @ingroup mqtt - * Function prototype for MQTT incoming publish function. Called when an incoming publish - * arrives to a subscribed topic @see mqtt_subscribe - * - * @param arg Additional argument to pass to the callback function - * @param topic Zero terminated Topic text string, topic may not be referenced after callback return - * @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked - */ -typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len); - - -/** - * @ingroup mqtt - * Function prototype for mqtt request callback. Called when a subscribe, unsubscribe - * or publish request has completed - * @param arg Pointer to user data supplied when invoking request - * @param err ERR_OK on success - * ERR_TIMEOUT if no response was received within timeout, - * ERR_ABRT if (un)subscribe was denied - */ -typedef void (*mqtt_request_cb_t)(void *arg, err_t err); - - -/** - * Pending request item, binds application callback to pending server requests - */ -struct mqtt_request_t -{ - /** Next item in list, NULL means this is the last in chain, - next pointing at itself means request is unallocated */ - struct mqtt_request_t *next; - /** Callback to upper layer */ - mqtt_request_cb_t cb; - void *arg; - /** MQTT packet identifier */ - u16_t pkt_id; - /** Expire time relative to element before this */ - u16_t timeout_diff; -}; - -/** Ring buffer */ -struct mqtt_ringbuf_t { - u16_t put; - u16_t get; - u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE]; -}; - -/** MQTT client */ -struct mqtt_client_t -{ - /** Timers and timeouts */ - u16_t cyclic_tick; - u16_t keep_alive; - u16_t server_watchdog; - /** Packet identifier generator*/ - u16_t pkt_id_seq; - /** Packet identifier of pending incoming publish */ - u16_t inpub_pkt_id; - /** Connection state */ - u8_t conn_state; - struct tcp_pcb *conn; - /** Connection callback */ - void *connect_arg; - mqtt_connection_cb_t connect_cb; - /** Pending requests to server */ - struct mqtt_request_t *pend_req_queue; - struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT]; - void *inpub_arg; - /** Incoming data callback */ - mqtt_incoming_data_cb_t data_cb; - mqtt_incoming_publish_cb_t pub_cb; - /** Input */ - u32_t msg_idx; - u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN]; - /** Output ring-buffer */ - struct mqtt_ringbuf_t output; -}; - - -/** Connect to server */ -err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg, - const struct mqtt_connect_client_info_t *client_info); - -/** Disconnect from server */ -void mqtt_disconnect(mqtt_client_t *client); - -/** Create new client */ -mqtt_client_t *mqtt_client_new(void); - -/** Check connection status */ -u8_t mqtt_client_is_connected(mqtt_client_t *client); - -/** Set callback to call for incoming publish */ -void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t, - mqtt_incoming_data_cb_t data_cb, void *arg); - -/** Common function for subscribe and unsubscribe */ -err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub); - -/** @ingroup mqtt - *Subscribe to topic */ -#define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1) -/** @ingroup mqtt - * Unsubscribe to topic */ -#define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0) - - -/** Publish data to topic */ -err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, - mqtt_request_cb_t cb, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/mqtt_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/mqtt_opts.h deleted file mode 100644 index ffefacd259..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/mqtt_opts.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file - * MQTT client options - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Andersson - * - */ -#ifndef LWIP_HDR_APPS_MQTT_OPTS_H -#define LWIP_HDR_APPS_MQTT_OPTS_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup mqtt_opts Options - * @ingroup mqtt - * @{ - */ - -/** - * Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads - */ -#ifndef MQTT_OUTPUT_RINGBUF_SIZE -#define MQTT_OUTPUT_RINGBUF_SIZE 256 -#endif - -/** - * Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8 - * If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8 - */ -#ifndef MQTT_VAR_HEADER_BUFFER_LEN -#define MQTT_VAR_HEADER_BUFFER_LEN 128 -#endif - -/** - * Maximum number of pending subscribe, unsubscribe and publish requests to server . - */ -#ifndef MQTT_REQ_MAX_IN_FLIGHT -#define MQTT_REQ_MAX_IN_FLIGHT 4 -#endif - -/** - * Seconds between each cyclic timer call. - */ -#ifndef MQTT_CYCLIC_TIMER_INTERVAL -#define MQTT_CYCLIC_TIMER_INTERVAL 5 -#endif - -/** - * Publish, subscribe and unsubscribe request timeout in seconds. - */ -#ifndef MQTT_REQ_TIMEOUT -#define MQTT_REQ_TIMEOUT 30 -#endif - -/** - * Seconds for MQTT connect response timeout after sending connect request - */ -#ifndef MQTT_CONNECT_TIMOUT -#define MQTT_CONNECT_TIMOUT 100 -#endif - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_MQTT_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns.h b/components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns.h deleted file mode 100644 index c9f68d8d12..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file - * NETBIOS name service responder - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#ifndef LWIP_HDR_APPS_NETBIOS_H -#define LWIP_HDR_APPS_NETBIOS_H - -#include "lwip/apps/netbiosns_opts.h" - -void netbiosns_init(void); -#ifndef NETBIOS_LWIP_NAME -void netbiosns_set_name(const char* hostname); -#endif -void netbiosns_stop(void); - -#endif /* LWIP_HDR_APPS_NETBIOS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns_opts.h deleted file mode 100644 index 0909ef7b94..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/netbiosns_opts.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file - * NETBIOS name service responder options - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#ifndef LWIP_HDR_APPS_NETBIOS_OPTS_H -#define LWIP_HDR_APPS_NETBIOS_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup netbiosns_opts Options - * @ingroup netbiosns - * @{ - */ - -/** NetBIOS name of lwip device - * This must be uppercase until NETBIOS_STRCMP() is defined to a string - * comparision function that is case insensitive. - * If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME): - * (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "") - * - * If this is not defined, netbiosns_set_name() can be called at runtime to change the name. - */ -#ifdef __DOXYGEN__ -#define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV" -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_NETBIOS_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp.h deleted file mode 100644 index 10e8ff434b..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file - * SNMP server main API - start and basic configuration - */ - -/* - * Copyright (c) 2001, 2002 Leon Woestenberg - * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Leon Woestenberg - * Martin Hentschel - * - */ -#ifndef LWIP_HDR_APPS_SNMP_H -#define LWIP_HDR_APPS_SNMP_H - -#include "lwip/apps/snmp_opts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/err.h" -#include "lwip/apps/snmp_core.h" - -/** SNMP variable binding descriptor (publically needed for traps) */ -struct snmp_varbind -{ - /** pointer to next varbind, NULL for last in list */ - struct snmp_varbind *next; - /** pointer to previous varbind, NULL for first in list */ - struct snmp_varbind *prev; - - /** object identifier */ - struct snmp_obj_id oid; - - /** value ASN1 type */ - u8_t type; - /** object value length */ - u16_t value_len; - /** object value */ - void *value; -}; - -/** - * @ingroup snmp_core - * Agent setup, start listening to port 161. - */ -void snmp_init(void); -void snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs); - -void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid); -const struct snmp_obj_id* snmp_get_device_enterprise_oid(void); - -void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); -void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst); - -/** Generic trap: cold start */ -#define SNMP_GENTRAP_COLDSTART 0 -/** Generic trap: warm start */ -#define SNMP_GENTRAP_WARMSTART 1 -/** Generic trap: link down */ -#define SNMP_GENTRAP_LINKDOWN 2 -/** Generic trap: link up */ -#define SNMP_GENTRAP_LINKUP 3 -/** Generic trap: authentication failure */ -#define SNMP_GENTRAP_AUTH_FAILURE 4 -/** Generic trap: EGP neighbor lost */ -#define SNMP_GENTRAP_EGP_NEIGHBOR_LOSS 5 -/** Generic trap: enterprise specific */ -#define SNMP_GENTRAP_ENTERPRISE_SPECIFIC 6 - -err_t snmp_send_trap_generic(s32_t generic_trap); -err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); -err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); - -#define SNMP_AUTH_TRAPS_DISABLED 0 -#define SNMP_AUTH_TRAPS_ENABLED 1 -void snmp_set_auth_traps_enabled(u8_t enable); -u8_t snmp_get_auth_traps_enabled(void); - -const char * snmp_get_community(void); -const char * snmp_get_community_write(void); -const char * snmp_get_community_trap(void); -void snmp_set_community(const char * const community); -void snmp_set_community_write(const char * const community); -void snmp_set_community_trap(const char * const community); - -void snmp_coldstart_trap(void); -void snmp_authfail_trap(void); - -typedef void (*snmp_write_callback_fct)(const u32_t* oid, u8_t oid_len, void* callback_arg); -void snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg); - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_core.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_core.h deleted file mode 100644 index e781c532b3..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_core.h +++ /dev/null @@ -1,364 +0,0 @@ -/** - * @file - * SNMP core API for implementing MIBs - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - */ - -#ifndef LWIP_HDR_APPS_SNMP_CORE_H -#define LWIP_HDR_APPS_SNMP_CORE_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* basic ASN1 defines */ -#define SNMP_ASN1_CLASS_UNIVERSAL 0x00 -#define SNMP_ASN1_CLASS_APPLICATION 0x40 -#define SNMP_ASN1_CLASS_CONTEXT 0x80 -#define SNMP_ASN1_CLASS_PRIVATE 0xC0 - -#define SNMP_ASN1_CONTENTTYPE_PRIMITIVE 0x00 -#define SNMP_ASN1_CONTENTTYPE_CONSTRUCTED 0x20 - -/* universal tags (from ASN.1 spec.) */ -#define SNMP_ASN1_UNIVERSAL_END_OF_CONTENT 0 -#define SNMP_ASN1_UNIVERSAL_INTEGER 2 -#define SNMP_ASN1_UNIVERSAL_OCTET_STRING 4 -#define SNMP_ASN1_UNIVERSAL_NULL 5 -#define SNMP_ASN1_UNIVERSAL_OBJECT_ID 6 -#define SNMP_ASN1_UNIVERSAL_SEQUENCE_OF 16 - -/* application specific (SNMP) tags (from SNMPv2-SMI) */ -#define SNMP_ASN1_APPLICATION_IPADDR 0 /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */ -#define SNMP_ASN1_APPLICATION_COUNTER 1 /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */ -#define SNMP_ASN1_APPLICATION_GAUGE 2 /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */ -#define SNMP_ASN1_APPLICATION_TIMETICKS 3 /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */ -#define SNMP_ASN1_APPLICATION_OPAQUE 4 /* [APPLICATION 4] IMPLICIT OCTET STRING */ -#define SNMP_ASN1_APPLICATION_COUNTER64 6 /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */ - -/* context specific (SNMP) tags (from RFC 1905) */ -#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE 1 - -/* full ASN1 type defines */ -#define SNMP_ASN1_TYPE_END_OF_CONTENT (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_END_OF_CONTENT) -#define SNMP_ASN1_TYPE_INTEGER (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_INTEGER) -#define SNMP_ASN1_TYPE_OCTET_STRING (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OCTET_STRING) -#define SNMP_ASN1_TYPE_NULL (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_NULL) -#define SNMP_ASN1_TYPE_OBJECT_ID (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OBJECT_ID) -#define SNMP_ASN1_TYPE_SEQUENCE (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_UNIVERSAL_SEQUENCE_OF) -#define SNMP_ASN1_TYPE_IPADDR (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_IPADDR) -#define SNMP_ASN1_TYPE_IPADDRESS SNMP_ASN1_TYPE_IPADDR -#define SNMP_ASN1_TYPE_COUNTER (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER) -#define SNMP_ASN1_TYPE_COUNTER32 SNMP_ASN1_TYPE_COUNTER -#define SNMP_ASN1_TYPE_GAUGE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_GAUGE) -#define SNMP_ASN1_TYPE_GAUGE32 SNMP_ASN1_TYPE_GAUGE -#define SNMP_ASN1_TYPE_UNSIGNED32 SNMP_ASN1_TYPE_GAUGE -#define SNMP_ASN1_TYPE_TIMETICKS (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_TIMETICKS) -#define SNMP_ASN1_TYPE_OPAQUE (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_OPAQUE) -#define SNMP_ASN1_TYPE_COUNTER64 (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER64) - -#define SNMP_VARBIND_EXCEPTION_OFFSET 0xF0 -#define SNMP_VARBIND_EXCEPTION_MASK 0x0F - -/** error codes predefined by SNMP prot. */ -typedef enum { - SNMP_ERR_NOERROR = 0, -/* -outdated v1 error codes. do not use anmore! -#define SNMP_ERR_NOSUCHNAME 2 use SNMP_ERR_NOSUCHINSTANCE instead -#define SNMP_ERR_BADVALUE 3 use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead -#define SNMP_ERR_READONLY 4 use SNMP_ERR_NOTWRITABLE instead -*/ - SNMP_ERR_GENERROR = 5, - SNMP_ERR_NOACCESS = 6, - SNMP_ERR_WRONGTYPE = 7, - SNMP_ERR_WRONGLENGTH = 8, - SNMP_ERR_WRONGENCODING = 9, - SNMP_ERR_WRONGVALUE = 10, - SNMP_ERR_NOCREATION = 11, - SNMP_ERR_INCONSISTENTVALUE = 12, - SNMP_ERR_RESOURCEUNAVAILABLE = 13, - SNMP_ERR_COMMITFAILED = 14, - SNMP_ERR_UNDOFAILED = 15, - SNMP_ERR_NOTWRITABLE = 17, - SNMP_ERR_INCONSISTENTNAME = 18, - - SNMP_ERR_NOSUCHINSTANCE = SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE -} snmp_err_t; - -/** internal object identifier representation */ -struct snmp_obj_id -{ - u8_t len; - u32_t id[SNMP_MAX_OBJ_ID_LEN]; -}; - -struct snmp_obj_id_const_ref -{ - u8_t len; - const u32_t* id; -}; - -extern const struct snmp_obj_id_const_ref snmp_zero_dot_zero; /* administrative identifier from SNMPv2-SMI */ - -/** SNMP variant value, used as reference in struct snmp_node_instance and table implementation */ -union snmp_variant_value -{ - void* ptr; - const void* const_ptr; - u32_t u32; - s32_t s32; -}; - - -/** -SNMP MIB node types - tree node is the only node the stack can process in order to walk the tree, - all other nodes are assumed to be leaf nodes. - This cannot be an enum because users may want to define their own node types. -*/ -#define SNMP_NODE_TREE 0x00 -/* predefined leaf node types */ -#define SNMP_NODE_SCALAR 0x01 -#define SNMP_NODE_SCALAR_ARRAY 0x02 -#define SNMP_NODE_TABLE 0x03 -#define SNMP_NODE_THREADSYNC 0x04 - -/** node "base class" layout, the mandatory fields for a node */ -struct snmp_node -{ - /** one out of SNMP_NODE_TREE or any leaf node type (like SNMP_NODE_SCALAR) */ - u8_t node_type; - /** the number assigned to this node which used as part of the full OID */ - u32_t oid; -}; - -/** SNMP node instance access types */ -typedef enum { - SNMP_NODE_INSTANCE_ACCESS_READ = 1, - SNMP_NODE_INSTANCE_ACCESS_WRITE = 2, - SNMP_NODE_INSTANCE_READ_ONLY = SNMP_NODE_INSTANCE_ACCESS_READ, - SNMP_NODE_INSTANCE_READ_WRITE = (SNMP_NODE_INSTANCE_ACCESS_READ | SNMP_NODE_INSTANCE_ACCESS_WRITE), - SNMP_NODE_INSTANCE_WRITE_ONLY = SNMP_NODE_INSTANCE_ACCESS_WRITE, - SNMP_NODE_INSTANCE_NOT_ACCESSIBLE = 0 -} snmp_access_t; - -struct snmp_node_instance; - -typedef s16_t (*node_instance_get_value_method)(struct snmp_node_instance*, void*); -typedef snmp_err_t (*node_instance_set_test_method)(struct snmp_node_instance*, u16_t, void*); -typedef snmp_err_t (*node_instance_set_value_method)(struct snmp_node_instance*, u16_t, void*); -typedef void (*node_instance_release_method)(struct snmp_node_instance*); - -#define SNMP_GET_VALUE_RAW_DATA 0x8000 - -/** SNMP node instance */ -struct snmp_node_instance -{ - /** prefilled with the node, get_instance() is called on; may be changed by user to any value to pass an arbitrary node between calls to get_instance() and get_value/test_value/set_value */ - const struct snmp_node* node; - /** prefilled with the instance id requested; for get_instance() this is the exact oid requested; for get_next_instance() this is the relative starting point, stack expects relative oid of next node here */ - struct snmp_obj_id instance_oid; - - /** ASN type for this object (see snmp_asn1.h for definitions) */ - u8_t asn1_type; - /** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */ - snmp_access_t access; - - /** returns object value for the given object identifier. Return values <0 to indicate an error */ - node_instance_get_value_method get_value; - /** tests length and/or range BEFORE setting */ - node_instance_set_test_method set_test; - /** sets object value, only called when set_test() was successful */ - node_instance_set_value_method set_value; - /** called in any case when the instance is not required anymore by stack (useful for freeing memory allocated in get_instance/get_next_instance methods) */ - node_instance_release_method release_instance; - - /** reference to pass arbitrary value between calls to get_instance() and get_value/test_value/set_value */ - union snmp_variant_value reference; - /** see reference (if reference is a pointer, the length of underlying data may be stored here or anything else) */ - u32_t reference_len; -}; - - -/** SNMP tree node */ -struct snmp_tree_node -{ - /** inherited "base class" members */ - struct snmp_node node; - u16_t subnode_count; - const struct snmp_node* const *subnodes; -}; - -#define SNMP_CREATE_TREE_NODE(oid, subnodes) \ - {{ SNMP_NODE_TREE, (oid) }, \ - (u16_t)LWIP_ARRAYSIZE(subnodes), (subnodes) } - -#define SNMP_CREATE_EMPTY_TREE_NODE(oid) \ - {{ SNMP_NODE_TREE, (oid) }, \ - 0, NULL } - -/** SNMP leaf node */ -struct snmp_leaf_node -{ - /** inherited "base class" members */ - struct snmp_node node; - snmp_err_t (*get_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - snmp_err_t (*get_next_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -}; - -/** represents a single mib with its base oid and root node */ -struct snmp_mib -{ - const u32_t *base_oid; - u8_t base_oid_len; - const struct snmp_node *root_node; -}; - -#define SNMP_MIB_CREATE(oid_list, root_node) { (oid_list), (u8_t)LWIP_ARRAYSIZE(oid_list), root_node } - -/** OID range structure */ -struct snmp_oid_range -{ - u32_t min; - u32_t max; -}; - -/** checks if incoming OID length and values are in allowed ranges */ -u8_t snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len); - -typedef enum { - SNMP_NEXT_OID_STATUS_SUCCESS, - SNMP_NEXT_OID_STATUS_NO_MATCH, - SNMP_NEXT_OID_STATUS_BUF_TO_SMALL -} snmp_next_oid_status_t; - -/** state for next_oid_init / next_oid_check functions */ -struct snmp_next_oid_state -{ - const u32_t* start_oid; - u8_t start_oid_len; - - u32_t* next_oid; - u8_t next_oid_len; - u8_t next_oid_max_len; - - snmp_next_oid_status_t status; - void* reference; -}; - -void snmp_next_oid_init(struct snmp_next_oid_state *state, - const u32_t *start_oid, u8_t start_oid_len, - u32_t *next_oid_buf, u8_t next_oid_max_len); -u8_t snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len); -u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference); - -void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); -void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); -void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); -void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); -u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); -s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); - -#if LWIP_IPV4 -u8_t snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip); -void snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid); -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 -u8_t snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip); -void snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid); -#endif /* LWIP_IPV6 */ -#if LWIP_IPV4 || LWIP_IPV6 -u8_t snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid); -u8_t snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid); - -u8_t snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip); -u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port); -#endif /* LWIP_IPV4 || LWIP_IPV6 */ - -struct netif; -u8_t netif_to_num(const struct netif *netif); - -snmp_err_t snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value); /* generic function which can be used if test is always successful */ - -err_t snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value); -err_t snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value); -u8_t snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count); -u8_t snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value); - -struct snmp_statistics -{ - u32_t inpkts; - u32_t outpkts; - u32_t inbadversions; - u32_t inbadcommunitynames; - u32_t inbadcommunityuses; - u32_t inasnparseerrs; - u32_t intoobigs; - u32_t innosuchnames; - u32_t inbadvalues; - u32_t inreadonlys; - u32_t ingenerrs; - u32_t intotalreqvars; - u32_t intotalsetvars; - u32_t ingetrequests; - u32_t ingetnexts; - u32_t insetrequests; - u32_t ingetresponses; - u32_t intraps; - u32_t outtoobigs; - u32_t outnosuchnames; - u32_t outbadvalues; - u32_t outgenerrs; - u32_t outgetrequests; - u32_t outgetnexts; - u32_t outsetrequests; - u32_t outgetresponses; - u32_t outtraps; -}; - -extern struct snmp_statistics snmp_stats; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_CORE_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_mib2.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_mib2.h deleted file mode 100644 index 2f4a68935e..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_mib2.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file - * SNMP MIB2 API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ -#ifndef LWIP_HDR_APPS_SNMP_MIB2_H -#define LWIP_HDR_APPS_SNMP_MIB2_H - -#include "lwip/apps/snmp_opts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ -#if SNMP_LWIP_MIB2 - -#include "lwip/apps/snmp_core.h" - -extern const struct snmp_mib mib2; - -#if SNMP_USE_NETCONN -#include "lwip/apps/snmp_threadsync.h" -void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg); -extern struct snmp_threadsync_instance snmp_mib2_lwip_locks; -#endif - -#ifndef SNMP_SYSSERVICES -#define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) -#endif - -void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */ -void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); -void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen); -void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); -void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen); -void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); -void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen); - -#endif /* SNMP_LWIP_MIB2 */ -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_MIB2_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_opts.h deleted file mode 100644 index 6c9ba7beb3..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_opts.h +++ /dev/null @@ -1,293 +0,0 @@ -/** - * @file - * SNMP server options list - */ - -/* - * Copyright (c) 2015 Dirk Ziegelmeier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ -#ifndef LWIP_HDR_SNMP_OPTS_H -#define LWIP_HDR_SNMP_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup snmp_opts Options - * @ingroup snmp - * @{ - */ - -/** - * LWIP_SNMP==1: This enables the lwIP SNMP agent. UDP must be available - * for SNMP transport. - * If you want to use your own SNMP agent, leave this disabled. - * To integrate MIB2 of an external agent, you need to enable - * LWIP_MIB2_CALLBACKS and MIB2_STATS. This will give you the callbacks - * and statistics counters you need to get MIB2 working. - */ -#if !defined LWIP_SNMP || defined __DOXYGEN__ -#define LWIP_SNMP 0 -#endif - -/** - * SNMP_USE_NETCONN: Use netconn API instead of raw API. - * Makes SNMP agent run in a worker thread, so blocking operations - * can be done in MIB calls. - */ -#if !defined SNMP_USE_NETCONN || defined __DOXYGEN__ -#define SNMP_USE_NETCONN 0 -#endif - -/** - * SNMP_USE_RAW: Use raw API. - * SNMP agent does not run in a worker thread, so blocking operations - * should not be done in MIB calls. - */ -#if !defined SNMP_USE_RAW || defined __DOXYGEN__ -#define SNMP_USE_RAW 1 -#endif - -#if SNMP_USE_NETCONN && SNMP_USE_RAW -#error SNMP stack can use only one of the APIs {raw, netconn} -#endif - -#if LWIP_SNMP && !SNMP_USE_NETCONN && !SNMP_USE_RAW -#error SNMP stack needs a receive API and UDP {raw, netconn} -#endif - -#if SNMP_USE_NETCONN -/** - * SNMP_STACK_SIZE: Stack size of SNMP netconn worker thread - */ -#if !defined SNMP_STACK_SIZE || defined __DOXYGEN__ -#define SNMP_STACK_SIZE DEFAULT_THREAD_STACKSIZE -#endif - -/** - * SNMP_THREAD_PRIO: SNMP netconn worker thread priority - */ -#if !defined SNMP_THREAD_PRIO || defined __DOXYGEN__ -#define SNMP_THREAD_PRIO DEFAULT_THREAD_PRIO -#endif -#endif /* SNMP_USE_NETCONN */ - -/** - * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap - * destination is required - */ -#if !defined SNMP_TRAP_DESTINATIONS || defined __DOXYGEN__ -#define SNMP_TRAP_DESTINATIONS 1 -#endif - -/** - * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not - * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). - * Unsafe requests are disabled by default! - */ -#if !defined SNMP_SAFE_REQUESTS || defined __DOXYGEN__ -#define SNMP_SAFE_REQUESTS 1 -#endif - -/** - * The maximum length of strings used. - */ -#if !defined SNMP_MAX_OCTET_STRING_LEN || defined __DOXYGEN__ -#define SNMP_MAX_OCTET_STRING_LEN 127 -#endif - -/** - * The maximum number of Sub ID's inside an object identifier. - * Indirectly this also limits the maximum depth of SNMP tree. - */ -#if !defined SNMP_MAX_OBJ_ID_LEN || defined __DOXYGEN__ -#define SNMP_MAX_OBJ_ID_LEN 50 -#endif - -#if !defined SNMP_MAX_VALUE_SIZE || defined __DOXYGEN__ -/** - * The maximum size of a value. - */ -#define SNMP_MIN_VALUE_SIZE (2 * sizeof(u32_t*)) /* size required to store the basic types (8 bytes for counter64) */ -/** - * The minimum size of a value. - */ -#define SNMP_MAX_VALUE_SIZE LWIP_MAX(LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN), sizeof(u32_t)*(SNMP_MAX_OBJ_ID_LEN)), SNMP_MIN_VALUE_SIZE) -#endif - -/** - * The snmp read-access community. Used for write-access and traps, too - * unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively. - */ -#if !defined SNMP_COMMUNITY || defined __DOXYGEN__ -#define SNMP_COMMUNITY "public" -#endif - -/** - * The snmp write-access community. - * Set this community to "" in order to disallow any write access. - */ -#if !defined SNMP_COMMUNITY_WRITE || defined __DOXYGEN__ -#define SNMP_COMMUNITY_WRITE "private" -#endif - -/** - * The snmp community used for sending traps. - */ -#if !defined SNMP_COMMUNITY_TRAP || defined __DOXYGEN__ -#define SNMP_COMMUNITY_TRAP "public" -#endif - -/** - * The maximum length of community string. - * If community names shall be adjusted at runtime via snmp_set_community() calls, - * enter here the possible maximum length (+1 for terminating null character). - */ -#if !defined SNMP_MAX_COMMUNITY_STR_LEN || defined __DOXYGEN__ -#define SNMP_MAX_COMMUNITY_STR_LEN LWIP_MAX(LWIP_MAX(sizeof(SNMP_COMMUNITY), sizeof(SNMP_COMMUNITY_WRITE)), sizeof(SNMP_COMMUNITY_TRAP)) -#endif - -/** - * The OID identifiying the device. This may be the enterprise OID itself or any OID located below it in tree. - */ -#if !defined SNMP_DEVICE_ENTERPRISE_OID || defined __DOXYGEN__ -#define SNMP_LWIP_ENTERPRISE_OID 26381 -/** - * IANA assigned enterprise ID for lwIP is 26381 - * @see http://www.iana.org/assignments/enterprise-numbers - * - * @note this enterprise ID is assigned to the lwIP project, - * all object identifiers living under this ID are assigned - * by the lwIP maintainers! - * @note don't change this define, use snmp_set_device_enterprise_oid() - * - * If you need to create your own private MIB you'll need - * to apply for your own enterprise ID with IANA: - * http://www.iana.org/numbers.html - */ -#define SNMP_DEVICE_ENTERPRISE_OID {1, 3, 6, 1, 4, 1, SNMP_LWIP_ENTERPRISE_OID} -/** - * Length of SNMP_DEVICE_ENTERPRISE_OID - */ -#define SNMP_DEVICE_ENTERPRISE_OID_LEN 7 -#endif - -/** - * SNMP_DEBUG: Enable debugging for SNMP messages. - */ -#if !defined SNMP_DEBUG || defined __DOXYGEN__ -#define SNMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. - */ -#if !defined SNMP_MIB_DEBUG || defined __DOXYGEN__ -#define SNMP_MIB_DEBUG LWIP_DBG_OFF -#endif - -/** - * Indicates if the MIB2 implementation of LWIP SNMP stack is used. - */ -#if !defined SNMP_LWIP_MIB2 || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2 LWIP_SNMP -#endif - -/** - * Value return for sysDesc field of MIB2. - */ -#if !defined SNMP_LWIP_MIB2_SYSDESC || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSDESC "lwIP" -#endif - -/** - * Value return for sysName field of MIB2. - * To make sysName field settable, call snmp_mib2_set_sysname() to provide the necessary buffers. - */ -#if !defined SNMP_LWIP_MIB2_SYSNAME || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSNAME "FQDN-unk" -#endif - -/** - * Value return for sysContact field of MIB2. - * To make sysContact field settable, call snmp_mib2_set_syscontact() to provide the necessary buffers. - */ -#if !defined SNMP_LWIP_MIB2_SYSCONTACT || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSCONTACT "" -#endif - -/** - * Value return for sysLocation field of MIB2. - * To make sysLocation field settable, call snmp_mib2_set_syslocation() to provide the necessary buffers. - */ -#if !defined SNMP_LWIP_MIB2_SYSLOCATION || defined __DOXYGEN__ -#define SNMP_LWIP_MIB2_SYSLOCATION "" -#endif - -/** - * This value is used to limit the repetitions processed in GetBulk requests (value == 0 means no limitation). - * This may be useful to limit the load for a single request. - * According to SNMP RFC 1905 it is allowed to not return all requested variables from a GetBulk request if system load would be too high. - * so the effect is that the client will do more requests to gather all data. - * For the stack this could be useful in case that SNMP processing is done in TCP/IP thread. In this situation a request with many - * repetitions could block the thread for a longer time. Setting limit here will keep the stack more responsive. - */ -#if !defined SNMP_LWIP_GETBULK_MAX_REPETITIONS || defined __DOXYGEN__ -#define SNMP_LWIP_GETBULK_MAX_REPETITIONS 0 -#endif - -/** - * @} - */ - -/* - ------------------------------------ - ---------- SNMPv3 options ---------- - ------------------------------------ -*/ - -/** - * LWIP_SNMP_V3==1: This enables EXPERIMENTAL SNMPv3 support. LWIP_SNMP must - * also be enabled. - * THIS IS UNDER DEVELOPMENT AND SHOULD NOT BE ENABLED IN PRODUCTS. - */ -#ifndef LWIP_SNMP_V3 -#define LWIP_SNMP_V3 0 -#endif - -#ifndef LWIP_SNMP_V3_CRYPTO -#define LWIP_SNMP_V3_CRYPTO LWIP_SNMP_V3 -#endif - -#ifndef LWIP_SNMP_V3_MBEDTLS -#define LWIP_SNMP_V3_MBEDTLS LWIP_SNMP_V3 -#endif - -#endif /* LWIP_HDR_SNMP_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_scalar.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_scalar.h deleted file mode 100644 index 40a060c640..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_scalar.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file - * SNMP server MIB API to implement scalar nodes - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_SCALAR_H -#define LWIP_HDR_APPS_SNMP_SCALAR_H - -#include "lwip/apps/snmp_opts.h" -#include "lwip/apps/snmp_core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -/** basic scalar node */ -struct snmp_scalar_node -{ - /** inherited "base class" members */ - struct snmp_leaf_node node; - u8_t asn1_type; - snmp_access_t access; - node_instance_get_value_method get_value; - node_instance_set_test_method set_test; - node_instance_set_value_method set_value; -}; - - -snmp_err_t snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_SCALAR_CREATE_NODE(oid, access, asn1_type, get_value_method, set_test_method, set_value_method) \ - {{{ SNMP_NODE_SCALAR, (oid) }, \ - snmp_scalar_get_instance, \ - snmp_scalar_get_next_instance }, \ - (asn1_type), (access), (get_value_method), (set_test_method), (set_value_method) } - -#define SNMP_SCALAR_CREATE_NODE_READONLY(oid, asn1_type, get_value_method) SNMP_SCALAR_CREATE_NODE(oid, SNMP_NODE_INSTANCE_READ_ONLY, asn1_type, get_value_method, NULL, NULL) - -/** scalar array node - a tree node which contains scalars only as children */ -struct snmp_scalar_array_node_def -{ - u32_t oid; - u8_t asn1_type; - snmp_access_t access; -}; - -typedef s16_t (*snmp_scalar_array_get_value_method)(const struct snmp_scalar_array_node_def*, void*); -typedef snmp_err_t (*snmp_scalar_array_set_test_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); -typedef snmp_err_t (*snmp_scalar_array_set_value_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); - -/** basic scalar array node */ -struct snmp_scalar_array_node -{ - /** inherited "base class" members */ - struct snmp_leaf_node node; - u16_t array_node_count; - const struct snmp_scalar_array_node_def* array_nodes; - snmp_scalar_array_get_value_method get_value; - snmp_scalar_array_set_test_method set_test; - snmp_scalar_array_set_value_method set_value; -}; - -snmp_err_t snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_SCALAR_CREATE_ARRAY_NODE(oid, array_nodes, get_value_method, set_test_method, set_value_method) \ - {{{ SNMP_NODE_SCALAR_ARRAY, (oid) }, \ - snmp_scalar_array_get_instance, \ - snmp_scalar_array_get_next_instance }, \ - (u16_t)LWIP_ARRAYSIZE(array_nodes), (array_nodes), (get_value_method), (set_test_method), (set_value_method) } - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_SCALAR_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_table.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_table.h deleted file mode 100644 index 4988b51c25..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_table.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @file - * SNMP server MIB API to implement table nodes - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_TABLE_H -#define LWIP_HDR_APPS_SNMP_TABLE_H - -#include "lwip/apps/snmp_opts.h" -#include "lwip/apps/snmp_core.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -/** default (customizable) read/write table */ -struct snmp_table_col_def -{ - u32_t index; - u8_t asn1_type; - snmp_access_t access; -}; - -/** table node */ -struct snmp_table_node -{ - /** inherited "base class" members */ - struct snmp_leaf_node node; - u16_t column_count; - const struct snmp_table_col_def* columns; - snmp_err_t (*get_cell_instance)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance); - snmp_err_t (*get_next_cell_instance)(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance); - /** returns object value for the given object identifier */ - node_instance_get_value_method get_value; - /** tests length and/or range BEFORE setting */ - node_instance_set_test_method set_test; - /** sets object value, only called when set_test() was successful */ - node_instance_set_value_method set_value; -}; - -snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_TABLE_CREATE(oid, columns, get_cell_instance_method, get_next_cell_instance_method, get_value_method, set_test_method, set_value_method) \ - {{{ SNMP_NODE_TABLE, (oid) }, \ - snmp_table_get_instance, \ - snmp_table_get_next_instance }, \ - (u16_t)LWIP_ARRAYSIZE(columns), (columns), \ - (get_cell_instance_method), (get_next_cell_instance_method), \ - (get_value_method), (set_test_method), (set_value_method)} - -#define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */ - - -/** simple read-only table */ -typedef enum { - SNMP_VARIANT_VALUE_TYPE_U32, - SNMP_VARIANT_VALUE_TYPE_S32, - SNMP_VARIANT_VALUE_TYPE_PTR, - SNMP_VARIANT_VALUE_TYPE_CONST_PTR -} snmp_table_column_data_type_t; - -struct snmp_table_simple_col_def -{ - u32_t index; - u8_t asn1_type; - snmp_table_column_data_type_t data_type; /* depending of what union member is used to store the value*/ -}; - -/** simple read-only table node */ -struct snmp_table_simple_node -{ - /* inherited "base class" members */ - struct snmp_leaf_node node; - u16_t column_count; - const struct snmp_table_simple_col_def* columns; - snmp_err_t (*get_cell_value)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len); - snmp_err_t (*get_next_cell_instance_and_value)(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len); -}; - -snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -#define SNMP_TABLE_CREATE_SIMPLE(oid, columns, get_cell_value_method, get_next_cell_instance_and_value_method) \ - {{{ SNMP_NODE_TABLE, (oid) }, \ - snmp_table_simple_get_instance, \ - snmp_table_simple_get_next_instance }, \ - (u16_t)LWIP_ARRAYSIZE(columns), (columns), (get_cell_value_method), (get_next_cell_instance_and_value_method) } - -s16_t snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value); -s16_t snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value); -s16_t snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value); - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_TABLE_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_threadsync.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_threadsync.h deleted file mode 100644 index a25dbf2d0f..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmp_threadsync.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file - * SNMP server MIB API to implement thread synchronization - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_THREADSYNC_H -#define LWIP_HDR_APPS_SNMP_THREADSYNC_H - -#include "lwip/apps/snmp_opts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "lwip/sys.h" - -typedef void (*snmp_threadsync_called_fn)(void* arg); -typedef void (*snmp_threadsync_synchronizer_fn)(snmp_threadsync_called_fn fn, void* arg); - - -/** Thread sync runtime data. For internal usage only. */ -struct threadsync_data -{ - union { - snmp_err_t err; - s16_t s16; - } retval; - union { - const u32_t *root_oid; - void *value; - } arg1; - union { - u8_t root_oid_len; - u16_t len; - } arg2; - const struct snmp_threadsync_node *threadsync_node; - struct snmp_node_instance proxy_instance; -}; - -/** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */ -struct snmp_threadsync_instance -{ - sys_sem_t sem; - sys_mutex_t sem_usage_mutex; - snmp_threadsync_synchronizer_fn sync_fn; - struct threadsync_data data; -}; - -/** SNMP thread sync proxy leaf node */ -struct snmp_threadsync_node -{ - /* inherited "base class" members */ - struct snmp_leaf_node node; - - const struct snmp_leaf_node *target; - struct snmp_threadsync_instance *instance; -}; - -snmp_err_t snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); -snmp_err_t snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); - -/** Create thread sync proxy node */ -#define SNMP_CREATE_THREAD_SYNC_NODE(oid, target_leaf_node, threadsync_instance) \ - {{{ SNMP_NODE_THREADSYNC, (oid) }, \ - snmp_threadsync_get_instance, \ - snmp_threadsync_get_next_instance }, \ - (target_leaf_node), \ - (threadsync_instance) } - -/** Create thread sync instance data */ -void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn); - -#endif /* LWIP_SNMP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNMP_THREADSYNC_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/snmpv3.h b/components/net/lwip-2.0.2/src/include/lwip/apps/snmpv3.h deleted file mode 100644 index c99fed4e10..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/snmpv3.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_V3_H -#define LWIP_HDR_APPS_SNMP_V3_H - -#include "lwip/apps/snmp_opts.h" -#include "lwip/err.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#define SNMP_V3_AUTH_ALGO_INVAL 0 -#define SNMP_V3_AUTH_ALGO_MD5 1 -#define SNMP_V3_AUTH_ALGO_SHA 2 - -#define SNMP_V3_PRIV_ALGO_INVAL 0 -#define SNMP_V3_PRIV_ALGO_DES 1 -#define SNMP_V3_PRIV_ALGO_AES 2 - -#define SNMP_V3_PRIV_MODE_DECRYPT 0 -#define SNMP_V3_PRIV_MODE_ENCRYPT 1 - -/* - * The following callback functions must be implemented by the application. - * There is a dummy implementation in snmpv3_dummy.c. - */ - -void snmpv3_get_engine_id(const char **id, u8_t *len); -err_t snmpv3_set_engine_id(const char* id, u8_t len); - -u32_t snmpv3_get_engine_boots(void); -void snmpv3_set_engine_boots(u32_t boots); - -u32_t snmpv3_get_engine_time(void); -void snmpv3_reset_engine_time(void); - -err_t snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key); - -/* The following functions are provided by the SNMPv3 agent */ - -void snmpv3_engine_id_changed(void); - -void snmpv3_password_to_key_md5( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength, /* IN - length of snmpEngineID */ - u8_t *key); /* OUT - pointer to caller 16-octet buffer */ - -void snmpv3_password_to_key_sha( - const u8_t *password, /* IN */ - u8_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength, /* IN - length of snmpEngineID */ - u8_t *key); /* OUT - pointer to caller 20-octet buffer */ - -#endif - -#endif /* LWIP_HDR_APPS_SNMP_V3_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/sntp.h b/components/net/lwip-2.0.2/src/include/lwip/apps/sntp.h deleted file mode 100644 index 40df9cc590..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/sntp.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file - * SNTP client API - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_APPS_SNTP_H -#define LWIP_HDR_APPS_SNTP_H - -#include "lwip/apps/sntp_opts.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* SNTP operating modes: default is to poll using unicast. - The mode has to be set before calling sntp_init(). */ -#define SNTP_OPMODE_POLL 0 -#define SNTP_OPMODE_LISTENONLY 1 -void sntp_setoperatingmode(u8_t operating_mode); -u8_t sntp_getoperatingmode(void); - -void sntp_init(void); -void sntp_stop(void); -u8_t sntp_enabled(void); - -void sntp_setserver(u8_t idx, const ip_addr_t *addr); -const ip_addr_t* sntp_getserver(u8_t idx); - -#if SNTP_SERVER_DNS -void sntp_setservername(u8_t idx, char *server); -char *sntp_getservername(u8_t idx); -#endif /* SNTP_SERVER_DNS */ - -#if SNTP_GET_SERVERS_FROM_DHCP -void sntp_servermode_dhcp(int set_servers_from_dhcp); -#else /* SNTP_GET_SERVERS_FROM_DHCP */ -#define sntp_servermode_dhcp(x) -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_SNTP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/sntp_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/sntp_opts.h deleted file mode 100644 index f3651f90e6..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/sntp_opts.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @file - * SNTP client options list - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_APPS_SNTP_OPTS_H -#define LWIP_HDR_APPS_SNTP_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup sntp_opts Options - * @ingroup sntp - * @{ - */ - -/** SNTP macro to change system time in seconds - * Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds instead of this one - * if you need the additional precision. - */ -#if !defined SNTP_SET_SYSTEM_TIME || defined __DOXYGEN__ -#define SNTP_SET_SYSTEM_TIME(sec) LWIP_UNUSED_ARG(sec) -#endif - -/** The maximum number of SNTP servers that can be set */ -#if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__ -#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS -#endif - -/** Set this to 1 to implement the callback function called by dhcp when - * NTP servers are received. */ -#if !defined SNTP_GET_SERVERS_FROM_DHCP || defined __DOXYGEN__ -#define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV -#endif - -/** Set this to 1 to support DNS names (or IP address strings) to set sntp servers - * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: - * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" - */ -#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ -#define SNTP_SERVER_DNS 0 -#endif - -/** - * SNTP_DEBUG: Enable debugging for SNTP. - */ -#if !defined SNTP_DEBUG || defined __DOXYGEN__ -#define SNTP_DEBUG LWIP_DBG_OFF -#endif - -/** SNTP server port */ -#if !defined SNTP_PORT || defined __DOXYGEN__ -#define SNTP_PORT 123 -#endif - -/** Set this to 1 to allow config of SNTP server(s) by DNS name */ -#if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ -#define SNTP_SERVER_DNS 0 -#endif - -/** Sanity check: - * Define this to - * - 0 to turn off sanity checks (default; smaller code) - * - >= 1 to check address and port of the response packet to ensure the - * response comes from the server we sent the request to. - * - >= 2 to check returned Originate Timestamp against Transmit Timestamp - * sent to the server (to ensure response to older request). - * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp - * fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast). - * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each - * greater than or equal to 0 and less than infinity, where infinity is - * currently a cozy number like one second. This check avoids using a - * server whose synchronization source has expired for a very long time. - */ -#if !defined SNTP_CHECK_RESPONSE || defined __DOXYGEN__ -#define SNTP_CHECK_RESPONSE 0 -#endif - -/** According to the RFC, this shall be a random delay - * between 1 and 5 minutes (in milliseconds) to prevent load peaks. - * This can be defined to a random generation function, - * which must return the delay in milliseconds as u32_t. - * Turned off by default. - */ -#if !defined SNTP_STARTUP_DELAY || defined __DOXYGEN__ -#define SNTP_STARTUP_DELAY 0 -#endif - -/** If you want the startup delay to be a function, define this - * to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1. - */ -#if !defined SNTP_STARTUP_DELAY_FUNC || defined __DOXYGEN__ -#define SNTP_STARTUP_DELAY_FUNC SNTP_STARTUP_DELAY -#endif - -/** SNTP receive timeout - in milliseconds - * Also used as retry timeout - this shouldn't be too low. - * Default is 3 seconds. - */ -#if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__ -#define SNTP_RECV_TIMEOUT 3000 -#endif - -/** SNTP update delay - in milliseconds - * Default is 1 hour. Must not be beolw 15 seconds by specification (i.e. 15000) - */ -#if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__ -#define SNTP_UPDATE_DELAY 3600000 -#endif - -/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2 - * to send in request and compare in response. - */ -#if !defined SNTP_GET_SYSTEM_TIME || defined __DOXYGEN__ -#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0) -#endif - -/** Default retry timeout (in milliseconds) if the response - * received is invalid. - * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached. - */ -#if !defined SNTP_RETRY_TIMEOUT || defined __DOXYGEN__ -#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT -#endif - -/** Maximum retry timeout (in milliseconds). */ -#if !defined SNTP_RETRY_TIMEOUT_MAX || defined __DOXYGEN__ -#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10) -#endif - -/** Increase retry timeout with every retry sent - * Default is on to conform to RFC. - */ -#if !defined SNTP_RETRY_TIMEOUT_EXP || defined __DOXYGEN__ -#define SNTP_RETRY_TIMEOUT_EXP 1 -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_SNTP_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/tftp_opts.h b/components/net/lwip-2.0.2/src/include/lwip/apps/tftp_opts.h deleted file mode 100644 index 6968a803b4..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/tftp_opts.h +++ /dev/null @@ -1,105 +0,0 @@ -/****************************************************************//** - * - * @file tftp_opts.h - * - * @author Logan Gunthorpe - * - * @brief Trivial File Transfer Protocol (RFC 1350) implementation options - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - ********************************************************************/ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * - */ - -#ifndef LWIP_HDR_APPS_TFTP_OPTS_H -#define LWIP_HDR_APPS_TFTP_OPTS_H - -#include "lwip/opt.h" - -/** - * @defgroup tftp_opts Options - * @ingroup tftp - * @{ - */ - -/** - * Enable TFTP debug messages - */ -#if !defined TFTP_DEBUG || defined __DOXYGEN__ -#define TFTP_DEBUG LWIP_DBG_ON -#endif - -/** - * TFTP server port - */ -#if !defined TFTP_PORT || defined __DOXYGEN__ -#define TFTP_PORT 69 -#endif - -/** - * TFTP timeout - */ -#if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__ -#define TFTP_TIMEOUT_MSECS 10000 -#endif - -/** - * Max. number of retries when a file is read from server - */ -#if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__ -#define TFTP_MAX_RETRIES 5 -#endif - -/** - * TFTP timer cyclic interval - */ -#if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__ -#define TFTP_TIMER_MSECS 50 -#endif - -/** - * Max. length of TFTP filename - */ -#if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__ -#define TFTP_MAX_FILENAME_LEN 20 -#endif - -/** - * Max. length of TFTP mode - */ -#if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ -#define TFTP_MAX_MODE_LEN 7 -#endif - -/** - * @} - */ - -#endif /* LWIP_HDR_APPS_TFTP_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/apps/tftp_server.h b/components/net/lwip-2.0.2/src/include/lwip/apps/tftp_server.h deleted file mode 100644 index 3fbe701e0a..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/apps/tftp_server.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************//** - * - * @file tftp_server.h - * - * @author Logan Gunthorpe - * - * @brief Trivial File Transfer Protocol (RFC 1350) - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - ********************************************************************/ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * - */ - -#ifndef LWIP_HDR_APPS_TFTP_SERVER_H -#define LWIP_HDR_APPS_TFTP_SERVER_H - -#include "lwip/apps/tftp_opts.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @ingroup tftp - * TFTP context containing callback functions for TFTP transfers - */ -struct tftp_context { - /** - * Open file for read/write. - * @param fname Filename - * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) - * @param write Flag indicating read (0) or write (!= 0) access - * @returns File handle supplied to other functions - */ - void* (*open)(const char* fname, const char* mode, u8_t write); - /** - * Close file handle - * @param handle File handle returned by open() - */ - void (*close)(void* handle); - /** - * Read from file - * @param handle File handle returned by open() - * @param buf Target buffer to copy read data to - * @param bytes Number of bytes to copy to buf - * @returns >= 0: Success; < 0: Error - */ - int (*read)(void* handle, void* buf, int bytes); - /** - * Write to file - * @param handle File handle returned by open() - * @param pbuf PBUF adjusted such that payload pointer points - * to the beginning of write data. In other words, - * TFTP headers are stripped off. - * @returns >= 0: Success; < 0: Error - */ - int (*write)(void* handle, struct pbuf* p); -}; - -err_t tftp_init(const struct tftp_context* ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/arch.h b/components/net/lwip-2.0.2/src/include/lwip/arch.h deleted file mode 100644 index 42f47778ae..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/arch.h +++ /dev/null @@ -1,320 +0,0 @@ -/** - * @file - * Support for different processor and compiler architectures - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ARCH_H -#define LWIP_HDR_ARCH_H - -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif - -#include "arch/cc.h" - -/** - * @defgroup compiler_abstraction Compiler/platform abstraction - * @ingroup sys_layer - * All defines related to this section must not be placed in lwipopts.h, - * but in arch/cc.h! - * These options cannot be \#defined in lwipopts.h since they are not options - * of lwIP itself, but options of the lwIP port to your system. - * @{ - */ - -/** Define the byte order of the system. - * Needed for conversion of network data to host byte order. - * Allowed values: LITTLE_ENDIAN and BIG_ENDIAN - */ -#ifndef BYTE_ORDER -#define BYTE_ORDER LITTLE_ENDIAN -#endif - -/** Define random number generator function of your system */ -#ifdef __DOXYGEN__ -#define LWIP_RAND() ((u32_t)rand()) -#endif - -/** Platform specific diagnostic output.\n - * Note the default implementation pulls in printf, which may - * in turn pull in a lot of standard libary code. In resource-constrained - * systems, this should be defined to something less resource-consuming. - */ -#ifndef LWIP_PLATFORM_DIAG -#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) -#include -#include -#endif - -/** Platform specific assertion handling.\n - * Note the default implementation pulls in printf, fflush and abort, which may - * in turn pull in a lot of standard libary code. In resource-constrained - * systems, this should be defined to something less resource-consuming. - */ -#ifndef LWIP_PLATFORM_ASSERT -#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \ - x, __LINE__, __FILE__); fflush(NULL); abort();} while(0) -#include -#include -#endif - -/** Define this to 1 in arch/cc.h of your port if you do not want to - * include stddef.h header to get size_t. You need to typedef size_t - * by yourself in this case. - */ -#ifndef LWIP_NO_STDDEF_H -#define LWIP_NO_STDDEF_H 0 -#endif - -#if !LWIP_NO_STDDEF_H -#include /* for size_t */ -#endif - -/** Define this to 1 in arch/cc.h of your port if your compiler does not provide - * the stdint.h header. You need to typedef the generic types listed in - * lwip/arch.h yourself in this case (u8_t, u16_t...). - */ -#ifndef LWIP_NO_STDINT_H -#define LWIP_NO_STDINT_H 0 -#endif - -/* Define generic types used in lwIP */ -#if !LWIP_NO_STDINT_H -#include -typedef uint8_t u8_t; -typedef int8_t s8_t; -typedef uint16_t u16_t; -typedef int16_t s16_t; -typedef uint32_t u32_t; -typedef int32_t s32_t; -typedef uintptr_t mem_ptr_t; -#endif - -/** Define this to 1 in arch/cc.h of your port if your compiler does not provide - * the inttypes.h header. You need to define the format strings listed in - * lwip/arch.h yourself in this case (X8_F, U16_F...). - */ -#ifndef LWIP_NO_INTTYPES_H -#define LWIP_NO_INTTYPES_H 0 -#endif - -/* Define (sn)printf formatters for these lwIP types */ -#if !LWIP_NO_INTTYPES_H -#include -#ifndef X8_F -#define X8_F "02" PRIx8 -#endif -#ifndef U16_F -#define U16_F PRIu16 -#endif -#ifndef S16_F -#define S16_F PRId16 -#endif -#ifndef X16_F -#define X16_F PRIx16 -#endif -#ifndef U32_F -#define U32_F PRIu32 -#endif -#ifndef S32_F -#define S32_F PRId32 -#endif -#ifndef X32_F -#define X32_F PRIx32 -#endif -#ifndef SZT_F -#define SZT_F PRIuPTR -#endif -#endif - -/** Define this to 1 in arch/cc.h of your port if your compiler does not provide - * the limits.h header. You need to define the type limits yourself in this case - * (e.g. INT_MAX). - */ -#ifndef LWIP_NO_LIMITS_H -#define LWIP_NO_LIMITS_H 0 -#endif - -/* Include limits.h? */ -#if !LWIP_NO_LIMITS_H -#include -#endif - -/** C++ const_cast(val) equivalent to remove constness from a value (GCC -Wcast-qual) */ -#ifndef LWIP_CONST_CAST -#define LWIP_CONST_CAST(target_type, val) ((target_type)((ptrdiff_t)val)) -#endif - -/** Get rid of alignment cast warnings (GCC -Wcast-align) */ -#ifndef LWIP_ALIGNMENT_CAST -#define LWIP_ALIGNMENT_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) -#endif - -/** Get rid of warnings related to pointer-to-numeric and vice-versa casts, - * e.g. "conversion from 'u8_t' to 'void *' of greater size" - */ -#ifndef LWIP_PTR_NUMERIC_CAST -#define LWIP_PTR_NUMERIC_CAST(target_type, val) LWIP_CONST_CAST(target_type, val) -#endif - -/** Allocates a memory buffer of specified size that is of sufficient size to align - * its start address using LWIP_MEM_ALIGN. - * You can declare your own version here e.g. to enforce alignment without adding - * trailing padding bytes (see LWIP_MEM_ALIGN_BUFFER) or your own section placement - * requirements.\n - * e.g. if you use gcc and need 32 bit alignment:\n - * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[size] \_\_attribute\_\_((aligned(4)))\n - * or more portable:\n - * \#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u32_t variable_name[(size + sizeof(u32_t) - 1) / sizeof(u32_t)] - */ -#ifndef LWIP_DECLARE_MEMORY_ALIGNED -#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)] - -#endif - -/** Calculate memory size for an aligned buffer - returns the next highest - * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and - * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). - */ -#ifndef LWIP_MEM_ALIGN_SIZE -#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1U) & ~(MEM_ALIGNMENT-1U)) -#endif - -/** Calculate safe memory size for an aligned buffer when using an unaligned - * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the - * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) - */ -#ifndef LWIP_MEM_ALIGN_BUFFER -#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1U)) -#endif - -/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT - * so that ADDR % MEM_ALIGNMENT == 0 - */ -#ifndef LWIP_MEM_ALIGN -#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** Packed structs support. - * Placed BEFORE declaration of a packed struct.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifndef PACK_STRUCT_BEGIN -#define PACK_STRUCT_BEGIN -#endif /* PACK_STRUCT_BEGIN */ - -/** Packed structs support. - * Placed AFTER declaration of a packed struct.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifndef PACK_STRUCT_END -#define PACK_STRUCT_END -#endif /* PACK_STRUCT_END */ - -/** Packed structs support. - * Placed between end of declaration of a packed struct and trailing semicolon.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifndef PACK_STRUCT_STRUCT -#if defined(__GNUC__) || defined(__clang__) -#define PACK_STRUCT_STRUCT __attribute__((packed)) -#else -#define PACK_STRUCT_STRUCT -#endif -#endif /* PACK_STRUCT_STRUCT */ - -/** Packed structs support. - * Wraps u32_t and u16_t members.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifndef PACK_STRUCT_FIELD -#define PACK_STRUCT_FIELD(x) x -#endif /* PACK_STRUCT_FIELD */ - -/** Packed structs support. - * Wraps u8_t members, where some compilers warn that packing is not necessary.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifndef PACK_STRUCT_FLD_8 -#define PACK_STRUCT_FLD_8(x) PACK_STRUCT_FIELD(x) -#endif /* PACK_STRUCT_FLD_8 */ - -/** Packed structs support. - * Wraps members that are packed structs themselves, where some compilers warn that packing is not necessary.\n - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifndef PACK_STRUCT_FLD_S -#define PACK_STRUCT_FLD_S(x) PACK_STRUCT_FIELD(x) -#endif /* PACK_STRUCT_FLD_S */ - -/** Packed structs support using \#include files before and after struct to be packed.\n - * The file included BEFORE the struct is "arch/bpstruct.h".\n - * The file included AFTER the struct is "arch/epstruct.h".\n - * This can be used to implement struct packing on MS Visual C compilers, see - * the Win32 port in the lwIP contrib repository for reference. - * For examples of packed struct declarations, see include/lwip/prot/ subfolder.\n - * A port to GCC/clang is included in lwIP, if you use these compilers there is nothing to do here. - */ -#ifdef __DOXYGEN__ -#define PACK_STRUCT_USE_INCLUDES -#endif - -/** Eliminates compiler warning about unused arguments (GCC -Wextra -Wunused). */ -#ifndef LWIP_UNUSED_ARG -#define LWIP_UNUSED_ARG(x) (void)x -#endif /* LWIP_UNUSED_ARG */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ARCH_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/autoip.h b/components/net/lwip-2.0.2/src/include/lwip/autoip.h deleted file mode 100644 index 1d85bccff8..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/autoip.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file - * - * AutoIP Automatic LinkLocal IP Configuration - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dominik Spies - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - */ - -#ifndef LWIP_HDR_AUTOIP_H -#define LWIP_HDR_AUTOIP_H - -#include "lwip/opt.h" - -#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netif.h" -/* #include "lwip/udp.h" */ -#include "lwip/etharp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** AutoIP Timing */ -#define AUTOIP_TMR_INTERVAL 100 -#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) - -/** AutoIP state information per netif */ -struct autoip -{ - /** the currently selected, probed, announced or used LL IP-Address */ - ip4_addr_t llipaddr; - /** current AutoIP state machine state */ - u8_t state; - /** sent number of probes or announces, dependent on state */ - u8_t sent_num; - /** ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ - u16_t ttw; - /** ticks until a conflict can be solved by defending */ - u8_t lastconflict; - /** total number of probed/used Link Local IP-Addresses */ - u8_t tried_llipaddr; -}; - - -void autoip_set_struct(struct netif *netif, struct autoip *autoip); -/** Remove a struct autoip previously set to the netif using autoip_set_struct() */ -#define autoip_remove_struct(netif) do { (netif)->autoip = NULL; } while (0) -err_t autoip_start(struct netif *netif); -err_t autoip_stop(struct netif *netif); -void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); -void autoip_tmr(void); -void autoip_network_changed(struct netif *netif); -u8_t autoip_supplied_address(const struct netif *netif); - -/* for lwIP internal use by ip4.c */ -u8_t autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr); - -#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 && LWIP_AUTOIP */ - -#endif /* LWIP_HDR_AUTOIP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/debug.h b/components/net/lwip-2.0.2/src/include/lwip/debug.h deleted file mode 100644 index a142f1cff3..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/debug.h +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @file - * Debug messages infrastructure - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_DEBUG_H -#define LWIP_HDR_DEBUG_H - -#include "lwip/arch.h" -#include "lwip/opt.h" - -/** - * @defgroup debugging_levels LWIP_DBG_MIN_LEVEL and LWIP_DBG_TYPES_ON values - * @ingroup lwip_opts_debugmsg - * @{ - */ - -/** @name Debug level (LWIP_DBG_MIN_LEVEL) - * @{ - */ -/** Debug level: ALL messages*/ -#define LWIP_DBG_LEVEL_ALL 0x00 -/** Debug level: Warnings. bad checksums, dropped packets, ... */ -#define LWIP_DBG_LEVEL_WARNING 0x01 -/** Debug level: Serious. memory allocation failures, ... */ -#define LWIP_DBG_LEVEL_SERIOUS 0x02 -/** Debug level: Severe */ -#define LWIP_DBG_LEVEL_SEVERE 0x03 -/** - * @} - */ - -#define LWIP_DBG_MASK_LEVEL 0x03 -/* compatibility define only */ -#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL - -/** @name Enable/disable debug messages completely (LWIP_DBG_TYPES_ON) - * @{ - */ -/** flag for LWIP_DEBUGF to enable that debug message */ -#define LWIP_DBG_ON 0x80U -/** flag for LWIP_DEBUGF to disable that debug message */ -#define LWIP_DBG_OFF 0x00U -/** - * @} - */ - -/** @name Debug message types (LWIP_DBG_TYPES_ON) - * @{ - */ -/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ -#define LWIP_DBG_TRACE 0x40U -/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ -#define LWIP_DBG_STATE 0x20U -/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ -#define LWIP_DBG_FRESH 0x10U -/** flag for LWIP_DEBUGF to halt after printing this debug message */ -#define LWIP_DBG_HALT 0x08U -/** - * @} - */ - -/** - * @} - */ - -/** - * @defgroup lwip_assertions Assertion handling - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_NOASSERT: Disable LWIP_ASSERT checks: - * To disable assertions define LWIP_NOASSERT in arch/cc.h. - */ -#ifdef __DOXYGEN__ -#define LWIP_NOASSERT -#undef LWIP_NOASSERT -#endif -/** - * @} - */ - -#ifndef LWIP_NOASSERT -#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) { \ - LWIP_PLATFORM_ASSERT(message); }} while(0) -#ifndef LWIP_PLATFORM_ASSERT -#error "If you want to use LWIP_ASSERT, LWIP_PLATFORM_ASSERT(message) needs to be defined in your arch/cc.h" -#endif -#else /* LWIP_NOASSERT */ -#define LWIP_ASSERT(message, assertion) -#endif /* LWIP_NOASSERT */ - -#ifndef LWIP_ERROR -#ifndef LWIP_NOASSERT -#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_ASSERT(message) -#elif defined LWIP_DEBUG -#define LWIP_PLATFORM_ERROR(message) LWIP_PLATFORM_DIAG((message)) -#else -#define LWIP_PLATFORM_ERROR(message) -#endif - -/* if "expression" isn't true, then print "message" and execute "handler" expression */ -#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ - LWIP_PLATFORM_ERROR(message); handler;}} while(0) -#endif /* LWIP_ERROR */ - -/** Enable debug message printing, but only if debug message type is enabled - * AND is of correct type AND is at least LWIP_DBG_LEVEL. - */ -#ifdef __DOXYGEN__ -#define LWIP_DEBUG -#undef LWIP_DEBUG -#endif - -#ifdef LWIP_DEBUG -#ifndef LWIP_PLATFORM_DIAG -#error "If you want to use LWIP_DEBUG, LWIP_PLATFORM_DIAG(message) needs to be defined in your arch/cc.h" -#endif -#define LWIP_DEBUGF(debug, message) do { \ - if ( \ - ((debug) & LWIP_DBG_ON) && \ - ((debug) & LWIP_DBG_TYPES_ON) && \ - ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ - LWIP_PLATFORM_DIAG(message); \ - if ((debug) & LWIP_DBG_HALT) { \ - while(1); \ - } \ - } \ - } while(0) - -#else /* LWIP_DEBUG */ -#define LWIP_DEBUGF(debug, message) -#endif /* LWIP_DEBUG */ - -#endif /* LWIP_HDR_DEBUG_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/def.h b/components/net/lwip-2.0.2/src/include/lwip/def.h deleted file mode 100644 index aaa64c77ab..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/def.h +++ /dev/null @@ -1,142 +0,0 @@ -/** - * @file - * various utility macros - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_DEF_H -#define LWIP_HDR_DEF_H - -/* arch.h might define NULL already */ -#include "lwip/arch.h" -#include "lwip/opt.h" -#if LWIP_PERF -#include "arch/perf.h" -#else /* LWIP_PERF */ -#define PERF_START /* null definition */ -#define PERF_STOP(x) /* null definition */ -#endif /* LWIP_PERF */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) -#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) - -/* Get the number of entries in an array ('x' must NOT be a pointer!) */ -#define LWIP_ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) - -/** Create u32_t value from bytes */ -#define LWIP_MAKEU32(a,b,c,d) (((u32_t)((a) & 0xff) << 24) | \ - ((u32_t)((b) & 0xff) << 16) | \ - ((u32_t)((c) & 0xff) << 8) | \ - (u32_t)((d) & 0xff)) - -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else -#define NULL ((void *)0) -#endif -#endif - -#if BYTE_ORDER == BIG_ENDIAN -#define lwip_htons(x) (x) -#define lwip_ntohs(x) (x) -#define lwip_htonl(x) (x) -#define lwip_ntohl(x) (x) -#define PP_HTONS(x) (x) -#define PP_NTOHS(x) (x) -#define PP_HTONL(x) (x) -#define PP_NTOHL(x) (x) -#else /* BYTE_ORDER != BIG_ENDIAN */ -#ifndef lwip_htons -u16_t lwip_htons(u16_t x); -#endif -#define lwip_ntohs(x) lwip_htons(x) - -#ifndef lwip_htonl -u32_t lwip_htonl(u32_t x); -#endif -#define lwip_ntohl(x) lwip_htonl(x) - -/* Provide usual function names as macros for users, but this can be turned off */ -#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS -#define htons(x) lwip_htons(x) -#define ntohs(x) lwip_ntohs(x) -#define htonl(x) lwip_htonl(x) -#define ntohl(x) lwip_ntohl(x) -#endif - -/* These macros should be calculated by the preprocessor and are used - with compile-time constants only (so that there is no little-endian - overhead at runtime). */ -#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8)) -#define PP_NTOHS(x) PP_HTONS(x) -#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ - (((x) & 0x0000ff00UL) << 8) | \ - (((x) & 0x00ff0000UL) >> 8) | \ - (((x) & 0xff000000UL) >> 24)) -#define PP_NTOHL(x) PP_HTONL(x) - -#endif /* BYTE_ORDER == BIG_ENDIAN */ - -/* Functions that are not available as standard implementations. - * In cc.h, you can #define these to implementations available on - * your platform to save some code bytes if you use these functions - * in your application, too. - */ - -#ifndef lwip_itoa -/* This can be #defined to itoa() or snprintf(result, bufsize, "%d", number) depending on your platform */ -void lwip_itoa(char* result, size_t bufsize, int number); -#endif -#ifndef lwip_strnicmp -/* This can be #defined to strnicmp() or strncasecmp() depending on your platform */ -int lwip_strnicmp(const char* str1, const char* str2, size_t len); -#endif -#ifndef lwip_stricmp -/* This can be #defined to stricmp() or strcasecmp() depending on your platform */ -int lwip_stricmp(const char* str1, const char* str2); -#endif -#ifndef lwip_strnstr -/* This can be #defined to strnstr() depending on your platform */ -char* lwip_strnstr(const char* buffer, const char* token, size_t n); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_DEF_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/dhcp.h b/components/net/lwip-2.0.2/src/include/lwip/dhcp.h deleted file mode 100644 index ac1b18e9f1..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/dhcp.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @file - * DHCP client API - */ - -/* - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Leon Woestenberg - * - */ -#ifndef LWIP_HDR_DHCP_H -#define LWIP_HDR_DHCP_H - -#include "lwip/opt.h" - -#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/netif.h" -#include "lwip/udp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** period (in seconds) of the application calling dhcp_coarse_tmr() */ -#define DHCP_COARSE_TIMER_SECS 60 -/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ -#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) -/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ -#define DHCP_FINE_TIMER_MSECS 500 - -#define DHCP_BOOT_FILE_LEN 128U - -/* AutoIP cooperation flags (struct dhcp.autoip_coop_state) */ -typedef enum { - DHCP_AUTOIP_COOP_STATE_OFF = 0, - DHCP_AUTOIP_COOP_STATE_ON = 1 -} dhcp_autoip_coop_state_enum_t; - -struct dhcp -{ - /** transaction identifier of last sent request */ - u32_t xid; - /** incoming msg */ - struct dhcp_msg *msg_in; - /** track PCB allocation state */ - u8_t pcb_allocated; - /** current DHCP state machine state */ - u8_t state; - /** retries of current request */ - u8_t tries; -#if LWIP_DHCP_AUTOIP_COOP - u8_t autoip_coop_state; -#endif - u8_t subnet_mask_given; - - struct pbuf *p_out; /* pbuf of outcoming msg */ - struct dhcp_msg *msg_out; /* outgoing msg */ - u16_t options_out_len; /* outgoing msg options length */ - u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ - u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ - u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ - u16_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ - u16_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ - u16_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ - u16_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ - ip_addr_t server_ip_addr; /* dhcp server address that offered this lease (ip_addr_t because passed to UDP) */ - ip4_addr_t offered_ip_addr; - ip4_addr_t offered_sn_mask; - ip4_addr_t offered_gw_addr; - - u32_t offered_t0_lease; /* lease period (in seconds) */ - u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ - u32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ -#if LWIP_DHCP_BOOTP_FILE - ip4_addr_t offered_si_addr; - char boot_file_name[DHCP_BOOT_FILE_LEN]; -#endif /* LWIP_DHCP_BOOTPFILE */ -}; - - -void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); -/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ -#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) -void dhcp_cleanup(struct netif *netif); -err_t dhcp_start(struct netif *netif); -err_t dhcp_renew(struct netif *netif); -err_t dhcp_release(struct netif *netif); -void dhcp_stop(struct netif *netif); -void dhcp_inform(struct netif *netif); -void dhcp_network_changed(struct netif *netif); -#if DHCP_DOES_ARP_CHECK -void dhcp_arp_reply(struct netif *netif, const ip4_addr_t *addr); -#endif -u8_t dhcp_supplied_address(const struct netif *netif); -/* to be called every minute */ -void dhcp_coarse_tmr(void); -/* to be called every half second */ -void dhcp_fine_tmr(void); - -#if LWIP_DHCP_GET_NTP_SRV -/** This function must exist, in other to add offered NTP servers to - * the NTP (or SNTP) engine. - * See LWIP_DHCP_MAX_NTP_SERVERS */ -extern void dhcp_set_ntp_servers(u8_t num_ntp_servers, const ip4_addr_t* ntp_server_addrs); -#endif /* LWIP_DHCP_GET_NTP_SRV */ - -#define netif_dhcp_data(netif) ((struct dhcp*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_DHCP */ - -#endif /*LWIP_HDR_DHCP_H*/ diff --git a/components/net/lwip-2.0.2/src/include/lwip/dhcp6.h b/components/net/lwip-2.0.2/src/include/lwip/dhcp6.h deleted file mode 100644 index 455336d37d..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/dhcp6.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file - * - * IPv6 address autoconfiguration as per RFC 4862. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * IPv6 address autoconfiguration as per RFC 4862. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_IP6_DHCP6_H -#define LWIP_HDR_IP6_DHCP6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6_DHCP6 /* don't build if not configured for use in lwipopts.h */ - - -struct dhcp6 -{ - /*@todo: implement DHCP6*/ -}; - -#endif /* LWIP_IPV6_DHCP6 */ - -#endif /* LWIP_HDR_IP6_DHCP6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/dns.h b/components/net/lwip-2.0.2/src/include/lwip/dns.h deleted file mode 100644 index 1453d72341..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/dns.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @file - * DNS API - */ - -/** - * lwip DNS resolver header file. - - * Author: Jim Pettinato - * April 2007 - - * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LWIP_HDR_DNS_H -#define LWIP_HDR_DNS_H - -#include "lwip/opt.h" - -#if LWIP_DNS - -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** DNS timer period */ -#define DNS_TMR_INTERVAL 1000 - -/* DNS resolve types: */ -#define LWIP_DNS_ADDRTYPE_IPV4 0 -#define LWIP_DNS_ADDRTYPE_IPV6 1 -#define LWIP_DNS_ADDRTYPE_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ -#define LWIP_DNS_ADDRTYPE_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ -#if LWIP_IPV4 && LWIP_IPV6 -#ifndef LWIP_DNS_ADDRTYPE_DEFAULT -#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4_IPV6 -#endif -#elif LWIP_IPV4 -#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV4 -#else -#define LWIP_DNS_ADDRTYPE_DEFAULT LWIP_DNS_ADDRTYPE_IPV6 -#endif - -#if DNS_LOCAL_HOSTLIST -/** struct used for local host-list */ -struct local_hostlist_entry { - /** static hostname */ - const char *name; - /** static host address in network byteorder */ - ip_addr_t addr; - struct local_hostlist_entry *next; -}; -#define DNS_LOCAL_HOSTLIST_ELEM(name, addr_init) {name, addr_init, NULL} -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN -#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH -#endif -#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ -#endif /* DNS_LOCAL_HOSTLIST */ - -#if LWIP_IPV4 -extern const ip_addr_t dns_mquery_v4group; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 -extern const ip_addr_t dns_mquery_v6group; -#endif /* LWIP_IPV6 */ - -/** Callback which is invoked when a hostname is found. - * A function of this type must be implemented by the application using the DNS resolver. - * @param name pointer to the name that was looked up. - * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, - * or NULL if the name could not be found (or on any other error). - * @param callback_arg a user-specified callback argument passed to dns_gethostbyname -*/ -typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, void *callback_arg); - -void dns_init(void); -void dns_tmr(void); -void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver); -const ip_addr_t* dns_getserver(u8_t numdns); -err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, - dns_found_callback found, void *callback_arg); -err_t dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, - dns_found_callback found, void *callback_arg, - u8_t dns_addrtype); - - -#if DNS_LOCAL_HOSTLIST -size_t dns_local_iterate(dns_found_callback iterator_fn, void *iterator_arg); -err_t dns_local_lookup(const char *hostname, ip_addr_t *addr, u8_t dns_addrtype); -#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC -int dns_local_removehost(const char *hostname, const ip_addr_t *addr); -err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ -#endif /* DNS_LOCAL_HOSTLIST */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_DNS */ - -#endif /* LWIP_HDR_DNS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/err.h b/components/net/lwip-2.0.2/src/include/lwip/err.h deleted file mode 100644 index 84e528d1ed..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/err.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @file - * lwIP Error codes - */ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ERR_H -#define LWIP_HDR_ERR_H - -#include "lwip/opt.h" -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup infrastructure_errors Error codes - * @ingroup infrastructure - * @{ - */ - -/** Define LWIP_ERR_T in cc.h if you want to use - * a different type for your platform (must be signed). */ -#ifdef LWIP_ERR_T -typedef LWIP_ERR_T err_t; -#else /* LWIP_ERR_T */ -typedef s8_t err_t; -#endif /* LWIP_ERR_T*/ - -/** Definitions for error constants. */ -typedef enum { -/** No error, everything OK. */ - ERR_OK = 0, -/** Out of memory error. */ - ERR_MEM = -1, -/** Buffer error. */ - ERR_BUF = -2, -/** Timeout. */ - ERR_TIMEOUT = -3, -/** Routing problem. */ - ERR_RTE = -4, -/** Operation in progress */ - ERR_INPROGRESS = -5, -/** Illegal value. */ - ERR_VAL = -6, -/** Operation would block. */ - ERR_WOULDBLOCK = -7, -/** Address in use. */ - ERR_USE = -8, -/** Already connecting. */ - ERR_ALREADY = -9, -/** Conn already established.*/ - ERR_ISCONN = -10, -/** Not connected. */ - ERR_CONN = -11, -/** Low-level netif error */ - ERR_IF = -12, - -/** Connection aborted. */ - ERR_ABRT = -13, -/** Connection reset. */ - ERR_RST = -14, -/** Connection closed. */ - ERR_CLSD = -15, -/** Illegal argument. */ - ERR_ARG = -16 -} err_enum_t; - -#define ERR_IS_FATAL(e) ((e) <= ERR_ABRT) - -/** - * @} - */ - -#ifdef LWIP_DEBUG -extern const char *lwip_strerr(err_t err); -#else -#define lwip_strerr(x) "" -#endif /* LWIP_DEBUG */ - -#if !NO_SYS -int err_to_errno(err_t err); -#endif /* !NO_SYS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ERR_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/errno.h b/components/net/lwip-2.0.2/src/include/lwip/errno.h deleted file mode 100644 index 641cffb09c..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/errno.h +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @file - * Posix Errno defines - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ERRNO_H -#define LWIP_HDR_ERRNO_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LWIP_PROVIDE_ERRNO - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ - -#ifndef errno -extern int errno; -#endif - -#else /* LWIP_PROVIDE_ERRNO */ - -/* Define LWIP_ERRNO_INCLUDE to to include the error defines here */ -#ifdef LWIP_ERRNO_INCLUDE -#include LWIP_ERRNO_INCLUDE -#endif /* LWIP_ERRNO_INCLUDE */ - -#endif /* LWIP_PROVIDE_ERRNO */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ERRNO_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/etharp.h b/components/net/lwip-2.0.2/src/include/lwip/etharp.h deleted file mode 100644 index 7080a19d05..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/etharp.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file - * Ethernet output function - handles OUTGOING ethernet level traffic, implements - * ARP resolving. - * To be used in most low-level netif implementations - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_NETIF_ETHARP_H -#define LWIP_HDR_NETIF_ETHARP_H - -#include "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip4_addr.h" -#include "lwip/netif.h" -#include "lwip/ip4.h" -#include "lwip/prot/ethernet.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_IPV4 && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/prot/etharp.h" - -/** 1 seconds period */ -#define ARP_TMR_INTERVAL 1000 - -#if ARP_QUEUEING -/** struct for queueing outgoing packets for unknown address - * defined here to be accessed by memp.h - */ -struct etharp_q_entry { - struct etharp_q_entry *next; - struct pbuf *p; -}; -#endif /* ARP_QUEUEING */ - -#define etharp_init() /* Compatibility define, no init needed. */ -void etharp_tmr(void); -s8_t etharp_find_addr(struct netif *netif, const ip4_addr_t *ipaddr, - struct eth_addr **eth_ret, const ip4_addr_t **ip_ret); -u8_t etharp_get_entry(u8_t i, ip4_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); -err_t etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); -err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q); -err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr); -/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; - * this is an ARP packet sent by a node in order to spontaneously cause other - * nodes to update an entry in their ARP cache. - * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ -#define etharp_gratuitous(netif) etharp_request((netif), netif_ip4_addr(netif)) -void etharp_cleanup_netif(struct netif *netif); - -#if ETHARP_SUPPORT_STATIC_ENTRIES -err_t etharp_add_static_entry(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr); -err_t etharp_remove_static_entry(const ip4_addr_t *ipaddr); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - -#endif /* LWIP_IPV4 && LWIP_ARP */ - -void etharp_input(struct pbuf *p, struct netif *netif); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_ARP || LWIP_ETHERNET */ - -#endif /* LWIP_HDR_NETIF_ETHARP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ethip6.h b/components/net/lwip-2.0.2/src/include/lwip/ethip6.h deleted file mode 100644 index 5e88dffd05..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ethip6.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file - * - * Ethernet output for IPv6. Uses ND tables for link-layer addressing. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_ETHIP6_H -#define LWIP_HDR_ETHIP6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 && LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 && LWIP_ETHERNET */ - -#endif /* LWIP_HDR_ETHIP6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/icmp.h b/components/net/lwip-2.0.2/src/include/lwip/icmp.h deleted file mode 100644 index f5a31fd4c0..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/icmp.h +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @file - * ICMP API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_ICMP_H -#define LWIP_HDR_ICMP_H - -#include "lwip/opt.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/prot/icmp.h" - -#if LWIP_IPV6 && LWIP_ICMP6 -#include "lwip/icmp6.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** ICMP destination unreachable codes */ -enum icmp_dur_type { - /** net unreachable */ - ICMP_DUR_NET = 0, - /** host unreachable */ - ICMP_DUR_HOST = 1, - /** protocol unreachable */ - ICMP_DUR_PROTO = 2, - /** port unreachable */ - ICMP_DUR_PORT = 3, - /** fragmentation needed and DF set */ - ICMP_DUR_FRAG = 4, - /** source route failed */ - ICMP_DUR_SR = 5 -}; - -/** ICMP time exceeded codes */ -enum icmp_te_type { - /** time to live exceeded in transit */ - ICMP_TE_TTL = 0, - /** fragment reassembly time exceeded */ - ICMP_TE_FRAG = 1 -}; - -#if LWIP_IPV4 && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ - -void icmp_input(struct pbuf *p, struct netif *inp); -void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); -void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); - -#endif /* LWIP_IPV4 && LWIP_ICMP */ - -#if LWIP_IPV4 && LWIP_IPV6 -#if LWIP_ICMP && LWIP_ICMP6 -#define icmp_port_unreach(isipv6, pbuf) ((isipv6) ? \ - icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) : \ - icmp_dest_unreach(pbuf, ICMP_DUR_PORT)) -#elif LWIP_ICMP -#define icmp_port_unreach(isipv6, pbuf) do{ if(!(isipv6)) { icmp_dest_unreach(pbuf, ICMP_DUR_PORT);}}while(0) -#elif LWIP_ICMP6 -#define icmp_port_unreach(isipv6, pbuf) do{ if(isipv6) { icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT);}}while(0) -#else -#define icmp_port_unreach(isipv6, pbuf) -#endif -#elif LWIP_IPV6 && LWIP_ICMP6 -#define icmp_port_unreach(isipv6, pbuf) icmp6_dest_unreach(pbuf, ICMP6_DUR_PORT) -#elif LWIP_IPV4 && LWIP_ICMP -#define icmp_port_unreach(isipv6, pbuf) icmp_dest_unreach(pbuf, ICMP_DUR_PORT) -#else /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) */ -#define icmp_port_unreach(isipv6, pbuf) -#endif /* (LWIP_IPV6 && LWIP_ICMP6) || (LWIP_IPV4 && LWIP_ICMP) LWIP_IPV4*/ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_ICMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/icmp6.h b/components/net/lwip-2.0.2/src/include/lwip/icmp6.h deleted file mode 100644 index a29dc8c1c2..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/icmp6.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file - * - * IPv6 version of ICMP, as per RFC 4443. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_ICMP6_H -#define LWIP_HDR_ICMP6_H - -#include "lwip/opt.h" -#include "lwip/pbuf.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" -#include "lwip/prot/icmp6.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_ICMP6 && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -void icmp6_input(struct pbuf *p, struct netif *inp); -void icmp6_dest_unreach(struct pbuf *p, enum icmp6_dur_code c); -void icmp6_packet_too_big(struct pbuf *p, u32_t mtu); -void icmp6_time_exceeded(struct pbuf *p, enum icmp6_te_code c); -void icmp6_param_problem(struct pbuf *p, enum icmp6_pp_code c, u32_t pointer); - -#endif /* LWIP_ICMP6 && LWIP_IPV6 */ - - -#ifdef __cplusplus -} -#endif - - -#endif /* LWIP_HDR_ICMP6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/igmp.h b/components/net/lwip-2.0.2/src/include/lwip/igmp.h deleted file mode 100644 index ffd80e680c..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/igmp.h +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file - * IGMP API - */ - -/* - * Copyright (c) 2002 CITEL Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is a contribution to the lwIP TCP/IP stack. - * The Swedish Institute of Computer Science and Adam Dunkels - * are specifically granted permission to redistribute this - * source code. -*/ - -#ifndef LWIP_HDR_IGMP_H -#define LWIP_HDR_IGMP_H - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/pbuf.h" - -#if LWIP_IPV4 && LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* IGMP timer */ -#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ -#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) -#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) - -/* Compatibility defines (don't use for new code) */ -#define IGMP_DEL_MAC_FILTER NETIF_DEL_MAC_FILTER -#define IGMP_ADD_MAC_FILTER NETIF_ADD_MAC_FILTER - -/** - * igmp group structure - there is - * a list of groups for each interface - * these should really be linked from the interface, but - * if we keep them separate we will not affect the lwip original code - * too much - * - * There will be a group for the all systems group address but this - * will not run the state machine as it is used to kick off reports - * from all the other groups - */ -struct igmp_group { - /** next link */ - struct igmp_group *next; - /** multicast address */ - ip4_addr_t group_address; - /** signifies we were the last person to report */ - u8_t last_reporter_flag; - /** current state of the group */ - u8_t group_state; - /** timer for reporting, negative is OFF */ - u16_t timer; - /** counter of simultaneous uses */ - u8_t use; -}; - -/* Prototypes */ -void igmp_init(void); -err_t igmp_start(struct netif *netif); -err_t igmp_stop(struct netif *netif); -void igmp_report_groups(struct netif *netif); -struct igmp_group *igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr); -void igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest); -err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); -err_t igmp_joingroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); -err_t igmp_leavegroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); -err_t igmp_leavegroup_netif(struct netif *netif, const ip4_addr_t *groupaddr); -void igmp_tmr(void); - -/** @ingroup igmp - * Get list head of IGMP groups for netif. - * Note: The allsystems group IP is contained in the list as first entry. - * @see @ref netif_set_igmp_mac_filter() - */ -#define netif_igmp_data(netif) ((struct igmp_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 && LWIP_IGMP */ - -#endif /* LWIP_HDR_IGMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/inet.h b/components/net/lwip-2.0.2/src/include/lwip/inet.h deleted file mode 100644 index 4a34f02653..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/inet.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @file - * This file (together with sockets.h) aims to provide structs and functions from - * - arpa/inet.h - * - netinet/in.h - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_INET_H -#define LWIP_HDR_INET_H - -#include "lwip/opt.h" -#include "lwip/def.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) -typedef u32_t in_addr_t; -#endif - -struct in_addr { - in_addr_t s_addr; -}; - -struct in6_addr { - union { - u32_t u32_addr[4]; - u8_t u8_addr[16]; - } un; -#define s6_addr un.u8_addr -}; - -/** 255.255.255.255 */ -#define INADDR_NONE IPADDR_NONE -/** 127.0.0.1 */ -#define INADDR_LOOPBACK IPADDR_LOOPBACK -/** 0.0.0.0 */ -#define INADDR_ANY IPADDR_ANY -/** 255.255.255.255 */ -#define INADDR_BROADCAST IPADDR_BROADCAST - -/** This macro can be used to initialize a variable of type struct in6_addr - to the IPv6 wildcard address. */ -#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} -/** This macro can be used to initialize a variable of type struct in6_addr - to the IPv6 loopback address. */ -#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} -/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -extern const struct in6_addr in6addr_any; - -/* Definitions of the bits in an (IPv4) Internet address integer. - - On subnets, host and network parts are found according to - the subnet mask, not these masks. */ -#define IN_CLASSA(a) IP_CLASSA(a) -#define IN_CLASSA_NET IP_CLASSA_NET -#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT -#define IN_CLASSA_HOST IP_CLASSA_HOST -#define IN_CLASSA_MAX IP_CLASSA_MAX - -#define IN_CLASSB(b) IP_CLASSB(b) -#define IN_CLASSB_NET IP_CLASSB_NET -#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT -#define IN_CLASSB_HOST IP_CLASSB_HOST -#define IN_CLASSB_MAX IP_CLASSB_MAX - -#define IN_CLASSC(c) IP_CLASSC(c) -#define IN_CLASSC_NET IP_CLASSC_NET -#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT -#define IN_CLASSC_HOST IP_CLASSC_HOST -#define IN_CLASSC_MAX IP_CLASSC_MAX - -#define IN_CLASSD(d) IP_CLASSD(d) -#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ -#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ -#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ -#define IN_CLASSD_MAX IP_CLASSD_MAX - -#define IN_MULTICAST(a) IP_MULTICAST(a) - -#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) -#define IN_BADCLASS(a) IP_BADCLASS(a) - -#define IN_LOOPBACKNET IP_LOOPBACKNET - - -#ifndef INET_ADDRSTRLEN -#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -#endif -#if LWIP_IPV6 -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX -#endif -#endif - -#if LWIP_IPV4 - -#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) -#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) -/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ -#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) - -/* directly map this to the lwip internal functions */ -#define inet_addr(cp) ipaddr_addr(cp) -#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) - -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ - (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ - (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ - (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} -#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ - (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ - (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ - (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} -/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ -#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) - -/* directly map this to the lwip internal functions */ -#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) -#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) -#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) - -#endif /* LWIP_IPV6 */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_INET_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/inet_chksum.h b/components/net/lwip-2.0.2/src/include/lwip/inet_chksum.h deleted file mode 100644 index 4e23d7f194..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/inet_chksum.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file - * IP checksum calculation functions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_INET_CHKSUM_H -#define LWIP_HDR_INET_CHKSUM_H - -#include "lwip/opt.h" - -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" - -/** Swap the bytes in an u16_t: much like lwip_htons() for little-endian */ -#ifndef SWAP_BYTES_IN_WORD -#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) -#endif /* SWAP_BYTES_IN_WORD */ - -/** Split an u32_t in two u16_ts and add them up */ -#ifndef FOLD_U32T -#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) -#endif - -#if LWIP_CHECKSUM_ON_COPY -/** Function-like macro: same as MEMCPY but returns the checksum of copied data - as u16_t */ -# ifndef LWIP_CHKSUM_COPY -# define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) -# ifndef LWIP_CHKSUM_COPY_ALGORITHM -# define LWIP_CHKSUM_COPY_ALGORITHM 1 -# endif /* LWIP_CHKSUM_COPY_ALGORITHM */ -# else /* LWIP_CHKSUM_COPY */ -# define LWIP_CHKSUM_COPY_ALGORITHM 0 -# endif /* LWIP_CHKSUM_COPY */ -#else /* LWIP_CHECKSUM_ON_COPY */ -# define LWIP_CHKSUM_COPY_ALGORITHM 0 -#endif /* LWIP_CHECKSUM_ON_COPY */ - -#ifdef __cplusplus -extern "C" { -#endif - -u16_t inet_chksum(const void *dataptr, u16_t len); -u16_t inet_chksum_pbuf(struct pbuf *p); -#if LWIP_CHKSUM_COPY_ALGORITHM -u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len); -#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ - -#if LWIP_IPV4 -u16_t inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip4_addr_t *src, const ip4_addr_t *dest); -u16_t inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, - u16_t proto_len, u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest); -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -u16_t ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip6_addr_t *src, const ip6_addr_t *dest); -u16_t ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest); -#endif /* LWIP_IPV6 */ - - -u16_t ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, - const ip_addr_t *src, const ip_addr_t *dest); -u16_t ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, - u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_INET_H */ - diff --git a/components/net/lwip-2.0.2/src/include/lwip/init.h b/components/net/lwip-2.0.2/src/include/lwip/init.h deleted file mode 100644 index d94eeb441d..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/init.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * lwIP initialization API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_INIT_H -#define LWIP_HDR_INIT_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup lwip_version Version - * @ingroup lwip - * @{ - */ - -/** X.x.x: Major version of the stack */ -#define LWIP_VERSION_MAJOR 2U -/** x.X.x: Minor version of the stack */ -#define LWIP_VERSION_MINOR 0U -/** x.x.X: Revision of the stack */ -#define LWIP_VERSION_REVISION 2U -/** For release candidates, this is set to 1..254 - * For official releases, this is set to 255 (LWIP_RC_RELEASE) - * For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */ -#define LWIP_VERSION_RC LWIP_RC_RELEASE - -/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ -#define LWIP_RC_RELEASE 255U -/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for Git versions */ -#define LWIP_RC_DEVELOPMENT 0U - -#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) -#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) -#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) - -/* Some helper defines to get a version string */ -#define LWIP_VERSTR2(x) #x -#define LWIP_VERSTR(x) LWIP_VERSTR2(x) -#if LWIP_VERSION_IS_RELEASE -#define LWIP_VERSION_STRING_SUFFIX "" -#elif LWIP_VERSION_IS_DEVELOPMENT -#define LWIP_VERSION_STRING_SUFFIX "d" -#else -#define LWIP_VERSION_STRING_SUFFIX "rc" LWIP_VERSTR(LWIP_VERSION_RC) -#endif - -/** Provides the version of the stack */ -#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ - LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) -/** Provides the version of the stack as string */ -#define LWIP_VERSION_STRING LWIP_VERSTR(LWIP_VERSION_MAJOR) "." LWIP_VERSTR(LWIP_VERSION_MINOR) "." LWIP_VERSTR(LWIP_VERSION_REVISION) LWIP_VERSION_STRING_SUFFIX - -/** - * @} - */ - -/* Modules initialization */ -void lwip_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_INIT_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip.h b/components/net/lwip-2.0.2/src/include/lwip/ip.h deleted file mode 100644 index 0673be9b4a..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip.h +++ /dev/null @@ -1,319 +0,0 @@ -/** - * @file - * IP API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP_H -#define LWIP_HDR_IP_H - -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "lwip/netif.h" -#include "lwip/ip4.h" -#include "lwip/ip6.h" -#include "lwip/prot/ip.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* This is passed as the destination address to ip_output_if (not - to ip_output), meaning that an IP header already is constructed - in the pbuf. This is used when TCP retransmits. */ -#define LWIP_IP_HDRINCL NULL - -/** pbufs passed to IP must have a ref-count of 1 as their payload pointer - gets altered as the packet is passed down the stack */ -#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX -#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) -#endif - -#if LWIP_NETIF_HWADDRHINT -#define IP_PCB_ADDRHINT ;u8_t addr_hint -#else -#define IP_PCB_ADDRHINT -#endif /* LWIP_NETIF_HWADDRHINT */ - -/** This is the common part of all PCB types. It needs to be at the - beginning of a PCB type definition. It is located here so that - changes to this common part are made in one location instead of - having to change all PCB structs. */ -#define IP_PCB \ - /* ip addresses in network byte order */ \ - ip_addr_t local_ip; \ - ip_addr_t remote_ip; \ - /* Socket options */ \ - u8_t so_options; \ - /* Type Of Service */ \ - u8_t tos; \ - /* Time To Live */ \ - u8_t ttl \ - /* link layer address resolution hint */ \ - IP_PCB_ADDRHINT - -struct ip_pcb { -/* Common members of all PCB types */ - IP_PCB; -}; - -/* - * Option flags per-socket. These are the same like SO_XXX in sockets.h - */ -#define SOF_REUSEADDR 0x04U /* allow local address reuse */ -#define SOF_KEEPALIVE 0x08U /* keep connections alive */ -#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ - -/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ -#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) - -/** Global variables of this module, kept in a struct for efficient access using base+index. */ -struct ip_globals -{ - /** The interface that accepted the packet for the current callback invocation. */ - struct netif *current_netif; - /** The interface that received the packet for the current callback invocation. */ - struct netif *current_input_netif; -#if LWIP_IPV4 - /** Header of the input packet currently being processed. */ - struct ip_hdr *current_ip4_header; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - /** Header of the input IPv6 packet currently being processed. */ - struct ip6_hdr *current_ip6_header; -#endif /* LWIP_IPV6 */ - /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ - u16_t current_ip_header_tot_len; - /** Source IP address of current_header */ - ip_addr_t current_iphdr_src; - /** Destination IP address of current_header */ - ip_addr_t current_iphdr_dest; -}; -extern struct ip_globals ip_data; - - -/** Get the interface that accepted the current packet. - * This may or may not be the receiving netif, depending on your netif/network setup. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip_current_netif() (ip_data.current_netif) -/** Get the interface that received the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip_current_input_netif() (ip_data.current_input_netif) -/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ -#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) -/** Source IP address of current_header */ -#define ip_current_src_addr() (&ip_data.current_iphdr_src) -/** Destination IP address of current_header */ -#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) - -#if LWIP_IPV4 && LWIP_IPV6 -/** Get the IPv4 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) -/** Get the IPv6 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) -/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ -#define ip_current_is_v6() (ip6_current_header() != NULL) -/** Source IPv6 address of current_header */ -#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) -/** Destination IPv6 address of current_header */ -#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) -/** Get the transport layer protocol */ -#define ip_current_header_proto() (ip_current_is_v6() ? \ - IP6H_NEXTH(ip6_current_header()) :\ - IPH_PROTO(ip4_current_header())) -/** Get the transport layer header */ -#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ - (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) - -/** Source IP4 address of current_header */ -#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) -/** Destination IP4 address of current_header */ -#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) - -#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ - -/** Get the IPv4 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) -/** Always returns FALSE when only supporting IPv4 only */ -#define ip_current_is_v6() 0 -/** Get the transport layer protocol */ -#define ip_current_header_proto() IPH_PROTO(ip4_current_header()) -/** Get the transport layer header */ -#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) -/** Source IP4 address of current_header */ -#define ip4_current_src_addr() (&ip_data.current_iphdr_src) -/** Destination IP4 address of current_header */ -#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) - -#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ - -/** Get the IPv6 header of the current packet. - * This function must only be called from a receive callback (udp_recv, - * raw_recv, tcp_accept). It will return NULL otherwise. */ -#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) -/** Always returns TRUE when only supporting IPv6 only */ -#define ip_current_is_v6() 1 -/** Get the transport layer protocol */ -#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) -/** Get the transport layer header */ -#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header())) -/** Source IP6 address of current_header */ -#define ip6_current_src_addr() (&ip_data.current_iphdr_src) -/** Destination IP6 address of current_header */ -#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) - -#endif /* LWIP_IPV6 */ - -/** Union source address of current_header */ -#define ip_current_src_addr() (&ip_data.current_iphdr_src) -/** Union destination address of current_header */ -#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) - -/** Gets an IP pcb option (SOF_* flags) */ -#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) -/** Sets an IP pcb option (SOF_* flags) */ -#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) -/** Resets an IP pcb option (SOF_* flags) */ -#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) - -#if LWIP_IPV4 && LWIP_IPV6 -/** - * @ingroup ip - * Output IP packet, netif is selected by source address - */ -#define ip_output(p, src, dest, ttl, tos, proto) \ - (IP_IS_V6(dest) ? \ - ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ - ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) -/** - * @ingroup ip - * Output IP packet to specified interface - */ -#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ - (IP_IS_V6(dest) ? \ - ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ - ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) -/** - * @ingroup ip - * Output IP packet to interface specifying source address - */ -#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ - (IP_IS_V6(dest) ? \ - ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ - ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) -/** Output IP packet with addr_hint */ -#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ - (IP_IS_V6(dest) ? \ - ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ - ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) -/** - * @ingroup ip - * Get netif for address combination. See \ref ip6_route and \ref ip4_route - */ -#define ip_route(src, dest) \ - (IP_IS_V6(dest) ? \ - ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ - ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) -/** - * @ingroup ip - * Get netif for IP. - */ -#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ - ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ - ip4_netif_get_local_ip(netif)) -#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) - -err_t ip_input(struct pbuf *p, struct netif *inp); - -#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ - -#define ip_output(p, src, dest, ttl, tos, proto) \ - ip4_output(p, src, dest, ttl, tos, proto) -#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ - ip4_output_if(p, src, dest, ttl, tos, proto, netif) -#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ - ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) -#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ - ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) -#define ip_route(src, dest) \ - ip4_route_src(dest, src) -#define ip_netif_get_local_ip(netif, dest) \ - ip4_netif_get_local_ip(netif) -#define ip_debug_print(is_ipv6, p) ip4_debug_print(p) - -#define ip_input ip4_input - -#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ - -#define ip_output(p, src, dest, ttl, tos, proto) \ - ip6_output(p, src, dest, ttl, tos, proto) -#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ - ip6_output_if(p, src, dest, ttl, tos, proto, netif) -#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ - ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) -#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ - ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) -#define ip_route(src, dest) \ - ip6_route(src, dest) -#define ip_netif_get_local_ip(netif, dest) \ - ip6_netif_get_local_ip(netif, dest) -#define ip_debug_print(is_ipv6, p) ip6_debug_print(p) - -#define ip_input ip6_input - -#endif /* LWIP_IPV6 */ - -#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ - (netif) = ip_route(src, dest); \ - (ipaddr) = ip_netif_get_local_ip(netif, dest); \ -}while(0) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_IP_H */ - - diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip4.h b/components/net/lwip-2.0.2/src/include/lwip/ip4.h deleted file mode 100644 index 48246ecc25..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip4.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file - * IPv4 API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP4_H -#define LWIP_HDR_IP4_H - -#include "lwip/opt.h" - -#if LWIP_IPV4 - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/ip4_addr.h" -#include "lwip/err.h" -#include "lwip/netif.h" -#include "lwip/prot/ip4.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef LWIP_HOOK_IP4_ROUTE_SRC -#define LWIP_IPV4_SRC_ROUTING 1 -#else -#define LWIP_IPV4_SRC_ROUTING 0 -#endif - -/** Currently, the function ip_output_if_opt() is only used with IGMP */ -#define IP_OPTIONS_SEND (LWIP_IPV4 && LWIP_IGMP) - -#define ip_init() /* Compatibility define, no init needed. */ -struct netif *ip4_route(const ip4_addr_t *dest); -#if LWIP_IPV4_SRC_ROUTING -struct netif *ip4_route_src(const ip4_addr_t *dest, const ip4_addr_t *src); -#else /* LWIP_IPV4_SRC_ROUTING */ -#define ip4_route_src(dest, src) ip4_route(dest) -#endif /* LWIP_IPV4_SRC_ROUTING */ -err_t ip4_input(struct pbuf *p, struct netif *inp); -err_t ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto); -err_t ip4_output_if(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); -err_t ip4_output_if_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); -#if LWIP_NETIF_HWADDRHINT -err_t ip4_output_hinted(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); -#endif /* LWIP_NETIF_HWADDRHINT */ -#if IP_OPTIONS_SEND -err_t ip4_output_if_opt(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen); -err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, - u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, - u16_t optlen); -#endif /* IP_OPTIONS_SEND */ - -#if LWIP_MULTICAST_TX_OPTIONS -void ip4_set_default_multicast_netif(struct netif* default_multicast_netif); -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#define ip4_netif_get_local_ip(netif) (((netif) != NULL) ? netif_ip_addr4(netif) : NULL) - -#if IP_DEBUG -void ip4_debug_print(struct pbuf *p); -#else -#define ip4_debug_print(p) -#endif /* IP_DEBUG */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP_H */ - - diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip4_addr.h b/components/net/lwip-2.0.2/src/include/lwip/ip4_addr.h deleted file mode 100644 index 51b46b8d4c..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip4_addr.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file - * IPv4 address API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP4_ADDR_H -#define LWIP_HDR_IP4_ADDR_H - -#include "lwip/opt.h" -#include "lwip/def.h" - -#if LWIP_IPV4 - -#ifdef __cplusplus -extern "C" { -#endif - -/** This is the aligned version of ip4_addr_t, - used as local variable, on the stack, etc. */ -struct ip4_addr { - u32_t addr; -}; - -/** ip4_addr_t uses a struct for convenience only, so that the same defines can - * operate both on ip4_addr_t as well as on ip4_addr_p_t. */ -typedef struct ip4_addr ip4_addr_t; - -/** - * struct ipaddr2 is used in the definition of the ARP packet format in - * order to support compilers that don't have structure packing. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip4_addr2 { - PACK_STRUCT_FIELD(u16_t addrw[2]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Forward declaration to not include netif.h */ -struct netif; - -/** 255.255.255.255 */ -#define IPADDR_NONE ((u32_t)0xffffffffUL) -/** 127.0.0.1 */ -#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) -/** 0.0.0.0 */ -#define IPADDR_ANY ((u32_t)0x00000000UL) -/** 255.255.255.255 */ -#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) - -/* Definitions of the bits in an Internet address integer. - - On subnets, host and network parts are found according to - the subnet mask, not these masks. */ -#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) -#define IP_CLASSA_NET 0xff000000 -#define IP_CLASSA_NSHIFT 24 -#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) -#define IP_CLASSA_MAX 128 - -#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) -#define IP_CLASSB_NET 0xffff0000 -#define IP_CLASSB_NSHIFT 16 -#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) -#define IP_CLASSB_MAX 65536 - -#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) -#define IP_CLASSC_NET 0xffffff00 -#define IP_CLASSC_NSHIFT 8 -#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) - -#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) -#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ -#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ -#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ -#define IP_MULTICAST(a) IP_CLASSD(a) - -#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) -#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) - -#define IP_LOOPBACKNET 127 /* official! */ - -/** Set an IP address given by the four byte-parts */ -#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) - -/** MEMCPY-like copying of IP addresses where addresses are known to be - * 16-bit-aligned if the port is correctly configured (so a port could define - * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ -#ifndef IPADDR2_COPY -#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip4_addr_t)) -#endif - -/** Copy IP address - faster than ip4_addr_set: no NULL check */ -#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) -/** Safely copy one IP address to another (src may be NULL) */ -#define ip4_addr_set(dest, src) ((dest)->addr = \ - ((src) == NULL ? 0 : \ - (src)->addr)) -/** Set complete address to zero */ -#define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) -/** Set address to IPADDR_ANY (no need for lwip_htonl()) */ -#define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) -/** Set address to loopback address */ -#define ip4_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) -/** Check if an address is in the loopback region */ -#define ip4_addr_isloopback(ipaddr) (((ipaddr)->addr & PP_HTONL(IP_CLASSA_NET)) == PP_HTONL(((u32_t)IP_LOOPBACKNET) << 24)) -/** Safely copy one IP address to another and change byte order - * from host- to network-order. */ -#define ip4_addr_set_hton(dest, src) ((dest)->addr = \ - ((src) == NULL ? 0:\ - lwip_htonl((src)->addr))) -/** IPv4 only: set the IP address given as an u32_t */ -#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) -/** IPv4 only: get the IP address as an u32_t */ -#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) - -/** Get the network address by combining host address with netmask */ -#define ip4_addr_get_network(target, host, netmask) do { ((target)->addr = ((host)->addr) & ((netmask)->addr)); } while(0) - -/** - * Determine if two address are on the same network. - * - * @arg addr1 IP address 1 - * @arg addr2 IP address 2 - * @arg mask network identifier mask - * @return !0 if the network identifiers of both address match - */ -#define ip4_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ - (mask)->addr) == \ - ((addr2)->addr & \ - (mask)->addr)) -#define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) - -#define ip4_addr_isany_val(addr1) ((addr1).addr == IPADDR_ANY) -#define ip4_addr_isany(addr1) ((addr1) == NULL || ip4_addr_isany_val(*(addr1))) - -#define ip4_addr_isbroadcast(addr1, netif) ip4_addr_isbroadcast_u32((addr1)->addr, netif) -u8_t ip4_addr_isbroadcast_u32(u32_t addr, const struct netif *netif); - -#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) -u8_t ip4_addr_netmask_valid(u32_t netmask); - -#define ip4_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) - -#define ip4_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) - -#define ip4_addr_debug_print_parts(debug, a, b, c, d) \ - LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, a, b, c, d)) -#define ip4_addr_debug_print(debug, ipaddr) \ - ip4_addr_debug_print_parts(debug, \ - (u16_t)((ipaddr) != NULL ? ip4_addr1_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr2_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr3_16(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? ip4_addr4_16(ipaddr) : 0)) -#define ip4_addr_debug_print_val(debug, ipaddr) \ - ip4_addr_debug_print_parts(debug, \ - ip4_addr1_16(&(ipaddr)), \ - ip4_addr2_16(&(ipaddr)), \ - ip4_addr3_16(&(ipaddr)), \ - ip4_addr4_16(&(ipaddr))) - -/* Get one byte from the 4-byte address */ -#define ip4_addr1(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[0]) -#define ip4_addr2(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[1]) -#define ip4_addr3(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[2]) -#define ip4_addr4(ipaddr) (((const u8_t*)(&(ipaddr)->addr))[3]) -/* These are cast to u16_t, with the intent that they are often arguments - * to printf using the U16_F format from cc.h. */ -#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) -#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) -#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) -#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) - -#define IP4ADDR_STRLEN_MAX 16 - -/** For backwards compatibility */ -#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) - -u32_t ipaddr_addr(const char *cp); -int ip4addr_aton(const char *cp, ip4_addr_t *addr); -/** returns ptr to static buffer; not reentrant! */ -char *ip4addr_ntoa(const ip4_addr_t *addr); -char *ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip4_frag.h b/components/net/lwip-2.0.2/src/include/lwip/ip4_frag.h deleted file mode 100644 index ed5bf14a31..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip4_frag.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file - * IP fragmentation/reassembly - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jani Monoses - * - */ - -#ifndef LWIP_HDR_IP4_FRAG_H -#define LWIP_HDR_IP4_FRAG_H - -#include "lwip/opt.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/ip_addr.h" -#include "lwip/ip.h" - -#if LWIP_IPV4 - -#ifdef __cplusplus -extern "C" { -#endif - -#if IP_REASSEMBLY -/* The IP reassembly timer interval in milliseconds. */ -#define IP_TMR_INTERVAL 1000 - -/** IP reassembly helper struct. - * This is exported because memp needs to know the size. - */ -struct ip_reassdata { - struct ip_reassdata *next; - struct pbuf *p; - struct ip_hdr iphdr; - u16_t datagram_len; - u8_t flags; - u8_t timer; -}; - -void ip_reass_init(void); -void ip_reass_tmr(void); -struct pbuf * ip4_reass(struct pbuf *p); -#endif /* IP_REASSEMBLY */ - -#if IP_FRAG -#if !LWIP_NETIF_TX_SINGLE_PBUF -#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED -#define LWIP_PBUF_CUSTOM_REF_DEFINED -/** A custom pbuf that holds a reference to another pbuf, which is freed - * when this custom pbuf is freed. This is used to create a custom PBUF_REF - * that points into the original pbuf. */ -struct pbuf_custom_ref { - /** 'base class' */ - struct pbuf_custom pc; - /** pointer to the original pbuf that is referenced */ - struct pbuf *original; -}; -#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ -#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ - -err_t ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest); -#endif /* IP_FRAG */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV4 */ - -#endif /* LWIP_HDR_IP4_FRAG_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip6.h b/components/net/lwip-2.0.2/src/include/lwip/ip6.h deleted file mode 100644 index 099b94fb74..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip6.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file - * - * IPv6 layer. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_IP6_H -#define LWIP_HDR_IP6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/prot/ip6.h" -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/netif.h" - -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct netif *ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest); -const ip_addr_t *ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest); -err_t ip6_input(struct pbuf *p, struct netif *inp); -err_t ip6_output(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth); -err_t ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); -err_t ip6_output_if_src(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, struct netif *netif); -#if LWIP_NETIF_HWADDRHINT -err_t ip6_output_hinted(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, - u8_t hl, u8_t tc, u8_t nexth, u8_t *addr_hint); -#endif /* LWIP_NETIF_HWADDRHINT */ -#if LWIP_IPV6_MLD -err_t ip6_options_add_hbh_ra(struct pbuf * p, u8_t nexth, u8_t value); -#endif /* LWIP_IPV6_MLD */ - -#define ip6_netif_get_local_ip(netif, dest) (((netif) != NULL) ? \ - ip6_select_source_address(netif, dest) : NULL) - -#if IP6_DEBUG -void ip6_debug_print(struct pbuf *p); -#else -#define ip6_debug_print(p) -#endif /* IP6_DEBUG */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_IP6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip6_addr.h b/components/net/lwip-2.0.2/src/include/lwip/ip6_addr.h deleted file mode 100644 index ee381aeb23..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip6_addr.h +++ /dev/null @@ -1,285 +0,0 @@ -/** - * @file - * - * IPv6 addresses. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * Structs and macros for handling IPv6 addresses. - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_IP6_ADDR_H -#define LWIP_HDR_IP6_ADDR_H - -#include "lwip/opt.h" -#include "def.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - - -#ifdef __cplusplus -extern "C" { -#endif - - -/** This is the aligned version of ip6_addr_t, - used as local variable, on the stack, etc. */ -struct ip6_addr { - u32_t addr[4]; -}; - -/** IPv6 address */ -typedef struct ip6_addr ip6_addr_t; - -/** Set an IPv6 partial address given by byte-parts */ -#define IP6_ADDR_PART(ip6addr, index, a,b,c,d) \ - (ip6addr)->addr[index] = PP_HTONL(LWIP_MAKEU32(a,b,c,d)) - -/** Set a full IPv6 address by passing the 4 u32_t indices in network byte order - (use PP_HTONL() for constants) */ -#define IP6_ADDR(ip6addr, idx0, idx1, idx2, idx3) do { \ - (ip6addr)->addr[0] = idx0; \ - (ip6addr)->addr[1] = idx1; \ - (ip6addr)->addr[2] = idx2; \ - (ip6addr)->addr[3] = idx3; } while(0) - -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK1(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK2(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[0])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK3(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK4(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[1])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK5(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK6(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[2])) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK7(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) -/** Access address in 16-bit block */ -#define IP6_ADDR_BLOCK8(ip6addr) ((u16_t)((lwip_htonl((ip6addr)->addr[3])) & 0xffff)) - -/** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ -#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ - (dest).addr[1] = (src).addr[1]; \ - (dest).addr[2] = (src).addr[2]; \ - (dest).addr[3] = (src).addr[3];}while(0) -/** Safely copy one IPv6 address to another (src may be NULL) */ -#define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ - (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ - (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ - (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) - -/** Set complete address to zero */ -#define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = 0;}while(0) - -/** Set address to ipv6 'any' (no need for lwip_htonl()) */ -#define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) -/** Set address to ipv6 loopback address */ -#define ip6_addr_set_loopback(ip6addr) do{(ip6addr)->addr[0] = 0; \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) -/** Safely copy one IPv6 address to another and change byte order - * from host- to network-order. */ -#define ip6_addr_set_hton(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : lwip_htonl((src)->addr[0]); \ - (dest)->addr[1] = (src) == NULL ? 0 : lwip_htonl((src)->addr[1]); \ - (dest)->addr[2] = (src) == NULL ? 0 : lwip_htonl((src)->addr[2]); \ - (dest)->addr[3] = (src) == NULL ? 0 : lwip_htonl((src)->addr[3]);}while(0) - - -/** - * Determine if two IPv6 address are on the same network. - * - * @arg addr1 IPv6 address 1 - * @arg addr2 IPv6 address 2 - * @return !0 if the network identifiers of both address match - */ -#define ip6_addr_netcmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ - ((addr1)->addr[1] == (addr2)->addr[1])) - -#define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ - ((addr1)->addr[1] == (addr2)->addr[1]) && \ - ((addr1)->addr[2] == (addr2)->addr[2]) && \ - ((addr1)->addr[3] == (addr2)->addr[3])) - -#define ip6_get_subnet_id(ip6addr) (lwip_htonl((ip6addr)->addr[2]) & 0x0000ffffUL) - -#define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ - ((ip6addr).addr[1] == 0) && \ - ((ip6addr).addr[2] == 0) && \ - ((ip6addr).addr[3] == 0)) -#define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) - -#define ip6_addr_isloopback(ip6addr) (((ip6addr)->addr[0] == 0UL) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) - -#define ip6_addr_isglobal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xe0000000UL)) == PP_HTONL(0x20000000UL)) - -#define ip6_addr_islinklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfe800000UL)) - -#define ip6_addr_issitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xffc00000UL)) == PP_HTONL(0xfec00000UL)) - -#define ip6_addr_isuniquelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xfe000000UL)) == PP_HTONL(0xfc000000UL)) - -#define ip6_addr_isipv4mappedipv6(ip6addr) (((ip6addr)->addr[0] == 0) && ((ip6addr)->addr[1] == 0) && (((ip6addr)->addr[2]) == PP_HTONL(0x0000FFFFUL))) - -#define ip6_addr_ismulticast(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) -#define ip6_addr_multicast_transient_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00100000UL)) -#define ip6_addr_multicast_prefix_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00200000UL)) -#define ip6_addr_multicast_rendezvous_flag(ip6addr) ((ip6addr)->addr[0] & PP_HTONL(0x00400000UL)) -#define ip6_addr_multicast_scope(ip6addr) ((lwip_htonl((ip6addr)->addr[0]) >> 16) & 0xf) -#define IP6_MULTICAST_SCOPE_RESERVED 0x0 -#define IP6_MULTICAST_SCOPE_RESERVED0 0x0 -#define IP6_MULTICAST_SCOPE_INTERFACE_LOCAL 0x1 -#define IP6_MULTICAST_SCOPE_LINK_LOCAL 0x2 -#define IP6_MULTICAST_SCOPE_RESERVED3 0x3 -#define IP6_MULTICAST_SCOPE_ADMIN_LOCAL 0x4 -#define IP6_MULTICAST_SCOPE_SITE_LOCAL 0x5 -#define IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL 0x8 -#define IP6_MULTICAST_SCOPE_GLOBAL 0xe -#define IP6_MULTICAST_SCOPE_RESERVEDF 0xf -#define ip6_addr_ismulticast_iflocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff010000UL)) -#define ip6_addr_ismulticast_linklocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff020000UL)) -#define ip6_addr_ismulticast_adminlocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff040000UL)) -#define ip6_addr_ismulticast_sitelocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff050000UL)) -#define ip6_addr_ismulticast_orglocal(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff080000UL)) -#define ip6_addr_ismulticast_global(ip6addr) (((ip6addr)->addr[0] & PP_HTONL(0xff8f0000UL)) == PP_HTONL(0xff0e0000UL)) - -/* @todo define get/set for well-know multicast addresses, e.g. ff02::1 */ -#define ip6_addr_isallnodes_iflocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff010000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) - -#define ip6_addr_isallnodes_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000001UL))) -#define ip6_addr_set_allnodes_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000001UL);}while(0) - -#define ip6_addr_isallrouters_linklocal(ip6addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0UL) && \ - ((ip6addr)->addr[2] == 0UL) && \ - ((ip6addr)->addr[3] == PP_HTONL(0x00000002UL))) -#define ip6_addr_set_allrouters_linklocal(ip6addr) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = 0; \ - (ip6addr)->addr[3] = PP_HTONL(0x00000002UL);}while(0) - -#define ip6_addr_issolicitednode(ip6addr) ( ((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ - (((ip6addr)->addr[3] & PP_HTONL(0xff000000UL)) == PP_HTONL(0xff000000UL)) ) - -#define ip6_addr_set_solicitednode(ip6addr, if_id) do{(ip6addr)->addr[0] = PP_HTONL(0xff020000UL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[2] = PP_HTONL(0x00000001UL); \ - (ip6addr)->addr[3] = (PP_HTONL(0xff000000UL) | (if_id));}while(0) - -#define ip6_addr_cmp_solicitednode(ip6addr, sn_addr) (((ip6addr)->addr[0] == PP_HTONL(0xff020000UL)) && \ - ((ip6addr)->addr[1] == 0) && \ - ((ip6addr)->addr[2] == PP_HTONL(0x00000001UL)) && \ - ((ip6addr)->addr[3] == (PP_HTONL(0xff000000UL) | (sn_addr)->addr[3]))) - -/* IPv6 address states. */ -#define IP6_ADDR_INVALID 0x00 -#define IP6_ADDR_TENTATIVE 0x08 -#define IP6_ADDR_TENTATIVE_1 0x09 /* 1 probe sent */ -#define IP6_ADDR_TENTATIVE_2 0x0a /* 2 probes sent */ -#define IP6_ADDR_TENTATIVE_3 0x0b /* 3 probes sent */ -#define IP6_ADDR_TENTATIVE_4 0x0c /* 4 probes sent */ -#define IP6_ADDR_TENTATIVE_5 0x0d /* 5 probes sent */ -#define IP6_ADDR_TENTATIVE_6 0x0e /* 6 probes sent */ -#define IP6_ADDR_TENTATIVE_7 0x0f /* 7 probes sent */ -#define IP6_ADDR_VALID 0x10 /* This bit marks an address as valid (preferred or deprecated) */ -#define IP6_ADDR_PREFERRED 0x30 -#define IP6_ADDR_DEPRECATED 0x10 /* Same as VALID (valid but not preferred) */ - -#define IP6_ADDR_TENTATIVE_COUNT_MASK 0x07 /* 1-7 probes sent */ - -#define ip6_addr_isinvalid(addr_state) (addr_state == IP6_ADDR_INVALID) -#define ip6_addr_istentative(addr_state) (addr_state & IP6_ADDR_TENTATIVE) -#define ip6_addr_isvalid(addr_state) (addr_state & IP6_ADDR_VALID) /* Include valid, preferred, and deprecated. */ -#define ip6_addr_ispreferred(addr_state) (addr_state == IP6_ADDR_PREFERRED) -#define ip6_addr_isdeprecated(addr_state) (addr_state == IP6_ADDR_DEPRECATED) - -#define ip6_addr_debug_print_parts(debug, a, b, c, d, e, f, g, h) \ - LWIP_DEBUGF(debug, ("%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F ":%" X16_F, \ - a, b, c, d, e, f, g, h)) -#define ip6_addr_debug_print(debug, ipaddr) \ - ip6_addr_debug_print_parts(debug, \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK1(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK2(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK3(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK4(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK5(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK6(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK7(ipaddr) : 0), \ - (u16_t)((ipaddr) != NULL ? IP6_ADDR_BLOCK8(ipaddr) : 0)) -#define ip6_addr_debug_print_val(debug, ipaddr) \ - ip6_addr_debug_print_parts(debug, \ - IP6_ADDR_BLOCK1(&(ipaddr)), \ - IP6_ADDR_BLOCK2(&(ipaddr)), \ - IP6_ADDR_BLOCK3(&(ipaddr)), \ - IP6_ADDR_BLOCK4(&(ipaddr)), \ - IP6_ADDR_BLOCK5(&(ipaddr)), \ - IP6_ADDR_BLOCK6(&(ipaddr)), \ - IP6_ADDR_BLOCK7(&(ipaddr)), \ - IP6_ADDR_BLOCK8(&(ipaddr))) - -#define IP6ADDR_STRLEN_MAX 46 - -int ip6addr_aton(const char *cp, ip6_addr_t *addr); -/** returns ptr to static buffer; not reentrant! */ -char *ip6addr_ntoa(const ip6_addr_t *addr); -char *ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); - - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_IP6_ADDR_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip6_frag.h b/components/net/lwip-2.0.2/src/include/lwip/ip6_frag.h deleted file mode 100644 index 6be274734b..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip6_frag.h +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file - * - * IPv6 fragmentation and reassembly. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ -#ifndef LWIP_HDR_IP6_FRAG_H -#define LWIP_HDR_IP6_FRAG_H - -#include "lwip/opt.h" -#include "lwip/pbuf.h" -#include "lwip/ip6_addr.h" -#include "lwip/ip6.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -#if LWIP_IPV6 && LWIP_IPV6_REASS /* don't build if not configured for use in lwipopts.h */ - -/** IP6_FRAG_COPYHEADER==1: for platforms where sizeof(void*) > 4, this needs to - * be enabled (to not overwrite part of the data). When enabled, the IPv6 header - * is copied instead of referencing it, which gives more room for struct ip6_reass_helper */ -#ifndef IPV6_FRAG_COPYHEADER -#define IPV6_FRAG_COPYHEADER 0 -#endif - -/** The IPv6 reassembly timer interval in milliseconds. */ -#define IP6_REASS_TMR_INTERVAL 1000 - -/* Copy the complete header of the first fragment to struct ip6_reassdata - or just point to its original location in the first pbuf? */ -#if IPV6_FRAG_COPYHEADER -#define IPV6_FRAG_HDRPTR -#define IPV6_FRAG_HDRREF(hdr) (&(hdr)) -#else /* IPV6_FRAG_COPYHEADER */ -#define IPV6_FRAG_HDRPTR * -#define IPV6_FRAG_HDRREF(hdr) (hdr) -#endif /* IPV6_FRAG_COPYHEADER */ - -/** IPv6 reassembly helper struct. - * This is exported because memp needs to know the size. - */ -struct ip6_reassdata { - struct ip6_reassdata *next; - struct pbuf *p; - struct ip6_hdr IPV6_FRAG_HDRPTR iphdr; - u32_t identification; - u16_t datagram_len; - u8_t nexth; - u8_t timer; -}; - -#define ip6_reass_init() /* Compatibility define */ -void ip6_reass_tmr(void); -struct pbuf *ip6_reass(struct pbuf *p); - -#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_FRAG /* don't build if not configured for use in lwipopts.h */ - -#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED -#define LWIP_PBUF_CUSTOM_REF_DEFINED -/** A custom pbuf that holds a reference to another pbuf, which is freed - * when this custom pbuf is freed. This is used to create a custom PBUF_REF - * that points into the original pbuf. */ -struct pbuf_custom_ref { - /** 'base class' */ - struct pbuf_custom pc; - /** pointer to the original pbuf that is referenced */ - struct pbuf *original; -}; -#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ - -err_t ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest); - -#endif /* LWIP_IPV6 && LWIP_IPV6_FRAG */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_IP6_FRAG_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/ip_addr.h b/components/net/lwip-2.0.2/src/include/lwip/ip_addr.h deleted file mode 100644 index 11f65d25bd..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/ip_addr.h +++ /dev/null @@ -1,407 +0,0 @@ -/** - * @file - * IP address API (common IPv4 and IPv6) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_IP_ADDR_H -#define LWIP_HDR_IP_ADDR_H - -#include "lwip/opt.h" -#include "lwip/def.h" - -#include "lwip/ip4_addr.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @ingroup ipaddr - * IP address types for use in ip_addr_t.type member. - * @see tcp_new_ip_type(), udp_new_ip_type(), raw_new_ip_type(). - */ -enum lwip_ip_addr_type { - /** IPv4 */ - IPADDR_TYPE_V4 = 0U, - /** IPv6 */ - IPADDR_TYPE_V6 = 6U, - /** IPv4+IPv6 ("dual-stack") */ - IPADDR_TYPE_ANY = 46U -}; - -#if LWIP_IPV4 && LWIP_IPV6 -/** - * @ingroup ipaddr - * A union struct for both IP version's addresses. - * ATTENTION: watch out for its size when adding IPv6 address scope! - */ -typedef struct ip_addr { - union { - ip6_addr_t ip6; - ip4_addr_t ip4; - } u_addr; - /** @ref lwip_ip_addr_type */ - u8_t type; -} ip_addr_t; - -extern const ip_addr_t ip_addr_any_type; - -/** @ingroup ip4addr */ -#define IPADDR4_INIT(u32val) { { { { u32val, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_V4 } -/** @ingroup ip4addr */ -#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) -/** @ingroup ip6addr */ -#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } -/** @ingroup ip6addr */ -#define IPADDR6_INIT_HOST(a, b, c, d) { { { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } }, IPADDR_TYPE_V6 } - -/** @ingroup ipaddr */ -#define IP_IS_ANY_TYPE_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_ANY) -/** @ingroup ipaddr */ -#define IPADDR_ANY_TYPE_INIT { { { { 0ul, 0ul, 0ul, 0ul } } }, IPADDR_TYPE_ANY } - -/** @ingroup ip4addr */ -#define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) -/** @ingroup ip6addr */ -#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) -/** @ingroup ip4addr */ -#define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) -/** @ingroup ip6addr */ -#define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) - -#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) -#define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) -#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) - -#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) (IP_GET_TYPE(&pcb->local_ip) == IP_GET_TYPE(ipaddr)) -#define IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr) (IP_IS_ANY_TYPE_VAL(pcb->local_ip) || IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) - -/** @ingroup ip6addr - * Convert generic ip address to specific protocol version - */ -#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) -/** @ingroup ip4addr - * Convert generic ip address to specific protocol version - */ -#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) - -/** @ingroup ip4addr */ -#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) -/** @ingroup ip6addr */ -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ - IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) -/** @ingroup ip6addr */ -#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) - -/** @ingroup ipaddr */ -#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) -/** @ingroup ip6addr */ -#define ip_addr_copy_from_ip6(dest, src) do{ \ - ip6_addr_copy(*ip_2_ip6(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V6); }while(0) -/** @ingroup ip4addr */ -#define ip_addr_copy_from_ip4(dest, src) do{ \ - ip4_addr_copy(*ip_2_ip4(&(dest)), src); IP_SET_TYPE_VAL(dest, IPADDR_TYPE_V4); }while(0) -/** @ingroup ip4addr */ -#define ip_addr_set_ip4_u32(ipaddr, val) do{if(ipaddr){ip4_addr_set_u32(ip_2_ip4(ipaddr), val); \ - IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ip4addr */ -#define ip_addr_get_ip4_u32(ipaddr) (((ipaddr) && IP_IS_V4(ipaddr)) ? \ - ip4_addr_get_u32(ip_2_ip4(ipaddr)) : 0) -/** @ingroup ipaddr */ -#define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ - ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ - ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) -/** @ingroup ipaddr */ -#define ip_addr_set_zero(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) -/** @ingroup ip5addr */ -#define ip_addr_set_zero_ip4(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) -/** @ingroup ip6addr */ -#define ip_addr_set_zero_ip6(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ - ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_loopback(is_ipv6, ipaddr) do{if(is_ipv6){ \ - ip6_addr_set_loopback(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_loopback(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_set_hton(dest, src) do{if(IP_IS_V6(src)){ \ - ip6_addr_set_hton(ip_2_ip6(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V6); }else{ \ - ip4_addr_set_hton(ip_2_ip4(ipaddr), (src)); IP_SET_TYPE(dest, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_get_network(target, host, netmask) do{if(IP_IS_V6(host)){ \ - ip4_addr_set_zero(ip_2_ip4(target)); IP_SET_TYPE(target, IPADDR_TYPE_V6); } else { \ - ip4_addr_get_network(ip_2_ip4(target), ip_2_ip4(host), ip_2_ip4(netmask)); IP_SET_TYPE(target, IPADDR_TYPE_V4); }}while(0) -/** @ingroup ipaddr */ -#define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ - 0 : \ - ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) -/** @ingroup ipaddr */ -#define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ - ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ - ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) -/** @ingroup ipaddr */ -#define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isany(ip_2_ip6(ipaddr)) : \ - ip4_addr_isany(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ - ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ - ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) -/** @ingroup ipaddr */ -#define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -/** @ingroup ipaddr */ -#define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ - ip4_addr_isloopback(ip_2_ip4(ipaddr))) -/** @ingroup ipaddr */ -#define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ - ip4_addr_islinklocal(ip_2_ip4(ipaddr))) -#define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ - ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ - ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) -#define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ - ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ - ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) -/** @ingroup ipaddr */ -#define ipaddr_ntoa(addr) (((addr) == NULL) ? "NULL" : \ - ((IP_IS_V6(addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr)))) -/** @ingroup ipaddr */ -#define ipaddr_ntoa_r(addr, buf, buflen) (((addr) == NULL) ? "NULL" : \ - ((IP_IS_V6(addr)) ? ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen) : ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen))) -int ipaddr_aton(const char *cp, ip_addr_t *addr); - -/** @ingroup ipaddr */ -#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX - -/** @ingroup ipaddr */ -#define ip4_2_ipv4_mapped_ipv6(ip6addr, ip4addr) do { \ - (ip6addr)->addr[3] = (ip4addr)->addr; \ - (ip6addr)->addr[2] = PP_HTONL(0x0000FFFFUL); \ - (ip6addr)->addr[1] = 0; \ - (ip6addr)->addr[0] = 0; } while(0); - -/** @ingroup ipaddr */ -#define unmap_ipv4_mapped_ipv6(ip4addr, ip6addr) \ - (ip4addr)->addr = (ip6addr)->addr[3]; - -#define IP46_ADDR_ANY(type) (((type) == IPADDR_TYPE_V6)? IP6_ADDR_ANY : IP4_ADDR_ANY) - -#else /* LWIP_IPV4 && LWIP_IPV6 */ - -#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 -#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 - -#if LWIP_IPV4 - -typedef ip4_addr_t ip_addr_t; -#define IPADDR4_INIT(u32val) { u32val } -#define IPADDR4_INIT_BYTES(a,b,c,d) IPADDR4_INIT(PP_HTONL(LWIP_MAKEU32(a,b,c,d))) -#define IP_IS_V4_VAL(ipaddr) 1 -#define IP_IS_V6_VAL(ipaddr) 0 -#define IP_IS_V4(ipaddr) 1 -#define IP_IS_V6(ipaddr) 0 -#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 -#define IP_SET_TYPE_VAL(ipaddr, iptype) -#define IP_SET_TYPE(ipaddr, iptype) -#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 -#define ip_2_ip4(ipaddr) (ipaddr) -#define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) - -#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) -#define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) -#define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) -#define ip_addr_set(dest, src) ip4_addr_set(dest, src) -#define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) -#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) -#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) -#define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) -#define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) -#define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) -#define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) -#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) -#define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) -#define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) -#define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) -#define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) -#define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) -#define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) -#define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) -#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) -#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) - -#define IPADDR_STRLEN_MAX IP4ADDR_STRLEN_MAX - -#define IP46_ADDR_ANY(type) (IP4_ADDR_ANY) - -#else /* LWIP_IPV4 */ - -typedef ip6_addr_t ip_addr_t; -#define IPADDR6_INIT(a, b, c, d) { { a, b, c, d } } -#define IPADDR6_INIT_HOST(a, b, c, d) { { PP_HTONL(a), PP_HTONL(b), PP_HTONL(c), PP_HTONL(d) } } -#define IP_IS_V4_VAL(ipaddr) 0 -#define IP_IS_V6_VAL(ipaddr) 1 -#define IP_IS_V4(ipaddr) 0 -#define IP_IS_V6(ipaddr) 1 -#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 -#define IP_SET_TYPE_VAL(ipaddr, iptype) -#define IP_SET_TYPE(ipaddr, iptype) -#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 -#define ip_2_ip6(ipaddr) (ipaddr) -#define IP_ADDR6(ipaddr,i0,i1,i2,i3) IP6_ADDR(ipaddr,i0,i1,i2,i3) -#define IP_ADDR6_HOST(ipaddr,i0,i1,i2,i3) IP_ADDR6(ipaddr,PP_HTONL(i0),PP_HTONL(i1),PP_HTONL(i2),PP_HTONL(i3)) - -#define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) -#define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) -#define ip_addr_set(dest, src) ip6_addr_set(dest, src) -#define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) -#define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) -#define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) -#define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) -#define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) -#define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) -#define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) -#define ip_addr_netcmp(addr1, addr2, mask) 0 -#define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) -#define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) -#define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) -#define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) -#define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) -#define ip_addr_isbroadcast(addr, netif) 0 -#define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) -#define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) -#define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) -#define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) -#define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) -#define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) - -#define IPADDR_STRLEN_MAX IP6ADDR_STRLEN_MAX - -#define IP46_ADDR_ANY(type) (IP6_ADDR_ANY) - -#endif /* LWIP_IPV4 */ -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#if LWIP_IPV4 - -extern const ip_addr_t ip_addr_any; -extern const ip_addr_t ip_addr_broadcast; - -/** - * @ingroup ip4addr - * Can be used as a fixed/const ip_addr_t - * for the IP wildcard. - * Defined to @ref IP4_ADDR_ANY when IPv4 is enabled. - * Defined to @ref IP6_ADDR_ANY in IPv6 only systems. - * Use this if you can handle IPv4 _AND_ IPv6 addresses. - * Use @ref IP4_ADDR_ANY or @ref IP6_ADDR_ANY when the IP - * type matters. - */ -#define IP_ADDR_ANY IP4_ADDR_ANY -/** - * @ingroup ip4addr - * Can be used as a fixed/const ip_addr_t - * for the IPv4 wildcard and the broadcast address - */ -#define IP4_ADDR_ANY (&ip_addr_any) -/** - * @ingroup ip4addr - * Can be used as a fixed/const ip4_addr_t - * for the wildcard and the broadcast address - */ -#define IP4_ADDR_ANY4 (ip_2_ip4(&ip_addr_any)) - -/** @ingroup ip4addr */ -#define IP_ADDR_BROADCAST (&ip_addr_broadcast) -/** @ingroup ip4addr */ -#define IP4_ADDR_BROADCAST (ip_2_ip4(&ip_addr_broadcast)) - -#endif /* LWIP_IPV4*/ - -#if LWIP_IPV6 - -extern const ip_addr_t ip6_addr_any; - -/** - * @ingroup ip6addr - * IP6_ADDR_ANY can be used as a fixed ip_addr_t - * for the IPv6 wildcard address - */ -#define IP6_ADDR_ANY (&ip6_addr_any) -/** - * @ingroup ip6addr - * IP6_ADDR_ANY6 can be used as a fixed ip6_addr_t - * for the IPv6 wildcard address - */ -#define IP6_ADDR_ANY6 (ip_2_ip6(&ip6_addr_any)) - -#if !LWIP_IPV4 -/** IPv6-only configurations */ -#define IP_ADDR_ANY IP6_ADDR_ANY -#endif /* !LWIP_IPV4 */ - -#endif - -#if LWIP_IPV4 && LWIP_IPV6 -/** @ingroup ipaddr */ -#define IP_ANY_TYPE (&ip_addr_any_type) -#else -#define IP_ANY_TYPE IP_ADDR_ANY -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_IP_ADDR_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/mem.h b/components/net/lwip-2.0.2/src/include/lwip/mem.h deleted file mode 100644 index ff208d25c3..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/mem.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file - * Heap API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_MEM_H -#define LWIP_HDR_MEM_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if MEM_LIBC_MALLOC - -#include "lwip/arch.h" - -typedef size_t mem_size_t; -#define MEM_SIZE_F SZT_F - -#elif MEM_USE_POOLS - -typedef u16_t mem_size_t; -#define MEM_SIZE_F U16_F - -#else - -/* MEM_SIZE would have to be aligned, but using 64000 here instead of - * 65535 leaves some room for alignment... - */ -#if MEM_SIZE > 64000L -typedef u32_t mem_size_t; -#define MEM_SIZE_F U32_F -#else -typedef u16_t mem_size_t; -#define MEM_SIZE_F U16_F -#endif /* MEM_SIZE > 64000 */ -#endif - -void mem_init(void); -void *mem_trim(void *mem, mem_size_t size); -void *mem_malloc(mem_size_t size); -void *mem_calloc(mem_size_t count, mem_size_t size); -void mem_free(void *mem); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_MEM_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/memp.h b/components/net/lwip-2.0.2/src/include/lwip/memp.h deleted file mode 100644 index 68fcd99145..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/memp.h +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @file - * Memory pool API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_MEMP_H -#define LWIP_HDR_MEMP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* run once with empty definition to handle all custom includes in lwippools.h */ -#define LWIP_MEMPOOL(name,num,size,desc) -#include "lwip/priv/memp_std.h" - -/** Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ -typedef enum { -#define LWIP_MEMPOOL(name,num,size,desc) MEMP_##name, -#include "lwip/priv/memp_std.h" - MEMP_MAX -} memp_t; - -#include "lwip/priv/memp_priv.h" -#include "lwip/stats.h" - -extern const struct memp_desc* const memp_pools[MEMP_MAX]; - -/** - * @ingroup mempool - * Declare prototype for private memory pool if it is used in multiple files - */ -#define LWIP_MEMPOOL_PROTOTYPE(name) extern const struct memp_desc memp_ ## name - -#if MEMP_MEM_MALLOC - -#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ - LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ - const struct memp_desc memp_ ## name = { \ - DECLARE_LWIP_MEMPOOL_DESC(desc) \ - LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ - LWIP_MEM_ALIGN_SIZE(size) \ - }; - -#else /* MEMP_MEM_MALLOC */ - -/** - * @ingroup mempool - * Declare a private memory pool - * Private mempools example: - * .h: only when pool is used in multiple .c files: LWIP_MEMPOOL_PROTOTYPE(my_private_pool); - * .c: - * - in global variables section: LWIP_MEMPOOL_DECLARE(my_private_pool, 10, sizeof(foo), "Some description") - * - call ONCE before using pool (e.g. in some init() function): LWIP_MEMPOOL_INIT(my_private_pool); - * - allocate: void* my_new_mem = LWIP_MEMPOOL_ALLOC(my_private_pool); - * - free: LWIP_MEMPOOL_FREE(my_private_pool, my_new_mem); - * - * To relocate a pool, declare it as extern in cc.h. Example for GCC: - * extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_my_private_pool[]; - */ -#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \ - LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \ - \ - LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(memp_stats_ ## name) \ - \ - static struct memp *memp_tab_ ## name; \ - \ - const struct memp_desc memp_ ## name = { \ - DECLARE_LWIP_MEMPOOL_DESC(desc) \ - LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(memp_stats_ ## name) \ - LWIP_MEM_ALIGN_SIZE(size), \ - (num), \ - memp_memory_ ## name ## _base, \ - &memp_tab_ ## name \ - }; - -#endif /* MEMP_MEM_MALLOC */ - -/** - * @ingroup mempool - * Initialize a private memory pool - */ -#define LWIP_MEMPOOL_INIT(name) memp_init_pool(&memp_ ## name) -/** - * @ingroup mempool - * Allocate from a private memory pool - */ -#define LWIP_MEMPOOL_ALLOC(name) memp_malloc_pool(&memp_ ## name) -/** - * @ingroup mempool - * Free element from a private memory pool - */ -#define LWIP_MEMPOOL_FREE(name, x) memp_free_pool(&memp_ ## name, (x)) - -#if MEM_USE_POOLS -/** This structure is used to save the pool one element came from. - * This has to be defined here as it is required for pool size calculation. */ -struct memp_malloc_helper -{ - memp_t poolnr; -#if MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) - u16_t size; -#endif /* MEMP_OVERFLOW_CHECK || (LWIP_STATS && MEM_STATS) */ -}; -#endif /* MEM_USE_POOLS */ - -void memp_init(void); - -#if MEMP_OVERFLOW_CHECK -void *memp_malloc_fn(memp_t type, const char* file, const int line); -#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) -#else -void *memp_malloc(memp_t type); -#endif -void memp_free(memp_t type, void *mem); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_MEMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/mld6.h b/components/net/lwip-2.0.2/src/include/lwip/mld6.h deleted file mode 100644 index 7fa0797f27..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/mld6.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file - * - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_MLD6_H -#define LWIP_HDR_MLD6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6_MLD && LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** MLD group */ -struct mld_group { - /** next link */ - struct mld_group *next; - /** multicast address */ - ip6_addr_t group_address; - /** signifies we were the last person to report */ - u8_t last_reporter_flag; - /** current state of the group */ - u8_t group_state; - /** timer for reporting */ - u16_t timer; - /** counter of simultaneous uses */ - u8_t use; -}; - -#define MLD6_TMR_INTERVAL 100 /* Milliseconds */ - -err_t mld6_stop(struct netif *netif); -void mld6_report_groups(struct netif *netif); -void mld6_tmr(void); -struct mld_group *mld6_lookfor_group(struct netif *ifp, const ip6_addr_t *addr); -void mld6_input(struct pbuf *p, struct netif *inp); -err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); -err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); -err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr); -err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr); - -/** @ingroup mld6 - * Get list head of MLD6 groups for netif. - * Note: The allnodes group IP is NOT in the list, since it must always - * be received for correct IPv6 operation. - * @see @ref netif_set_mld_mac_filter() - */ -#define netif_mld6_data(netif) ((struct mld_group *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6_MLD && LWIP_IPV6 */ - -#endif /* LWIP_HDR_MLD6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/nd6.h b/components/net/lwip-2.0.2/src/include/lwip/nd6.h deleted file mode 100644 index 8204fa4cce..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/nd6.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_ND6_H -#define LWIP_HDR_ND6_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip6_addr.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** 1 second period */ -#define ND6_TMR_INTERVAL 1000 - -struct pbuf; -struct netif; - -void nd6_tmr(void); -void nd6_input(struct pbuf *p, struct netif *inp); -void nd6_clear_destination_cache(void); -struct netif *nd6_find_route(const ip6_addr_t *ip6addr); -err_t nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp); -u16_t nd6_get_destination_mtu(const ip6_addr_t *ip6addr, struct netif *netif); -#if LWIP_ND6_TCP_REACHABILITY_HINTS -void nd6_reachability_hint(const ip6_addr_t *ip6addr); -#endif /* LWIP_ND6_TCP_REACHABILITY_HINTS */ -void nd6_cleanup_netif(struct netif *netif); -#if LWIP_IPV6_MLD -void nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state); -#endif /* LWIP_IPV6_MLD */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_ND6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/netbuf.h b/components/net/lwip-2.0.2/src/include/lwip/netbuf.h deleted file mode 100644 index e6865f80f9..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/netbuf.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * netbuf API (for netconn API) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_NETBUF_H -#define LWIP_HDR_NETBUF_H - -#include "lwip/opt.h" - -#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -/* Note: Netconn API is always available when sockets are enabled - - * sockets are implemented on top of them */ - -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This netbuf has dest-addr/port set */ -#define NETBUF_FLAG_DESTADDR 0x01 -/** This netbuf includes a checksum */ -#define NETBUF_FLAG_CHKSUM 0x02 - -/** "Network buffer" - contains data and addressing info */ -struct netbuf { - struct pbuf *p, *ptr; - ip_addr_t addr; - u16_t port; -#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -#if LWIP_CHECKSUM_ON_COPY - u8_t flags; -#endif /* LWIP_CHECKSUM_ON_COPY */ - u16_t toport_chksum; -#if LWIP_NETBUF_RECVINFO - ip_addr_t toaddr; -#endif /* LWIP_NETBUF_RECVINFO */ -#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ -}; - -/* Network buffer functions: */ -struct netbuf * netbuf_new (void); -void netbuf_delete (struct netbuf *buf); -void * netbuf_alloc (struct netbuf *buf, u16_t size); -void netbuf_free (struct netbuf *buf); -err_t netbuf_ref (struct netbuf *buf, - const void *dataptr, u16_t size); -void netbuf_chain (struct netbuf *head, struct netbuf *tail); - -err_t netbuf_data (struct netbuf *buf, - void **dataptr, u16_t *len); -s8_t netbuf_next (struct netbuf *buf); -void netbuf_first (struct netbuf *buf); - - -#define netbuf_copy_partial(buf, dataptr, len, offset) \ - pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) -#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) -#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) -#define netbuf_len(buf) ((buf)->p->tot_len) -#define netbuf_fromaddr(buf) (&((buf)->addr)) -#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) -#define netbuf_fromport(buf) ((buf)->port) -#if LWIP_NETBUF_RECVINFO -#define netbuf_destaddr(buf) (&((buf)->toaddr)) -#define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr) -#if LWIP_CHECKSUM_ON_COPY -#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) -#else /* LWIP_CHECKSUM_ON_COPY */ -#define netbuf_destport(buf) ((buf)->toport_chksum) -#endif /* LWIP_CHECKSUM_ON_COPY */ -#endif /* LWIP_NETBUF_RECVINFO */ -#if LWIP_CHECKSUM_ON_COPY -#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ - (buf)->toport_chksum = chksum; } while(0) -#endif /* LWIP_CHECKSUM_ON_COPY */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#endif /* LWIP_HDR_NETBUF_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/netdb.h b/components/net/lwip-2.0.2/src/include/lwip/netdb.h deleted file mode 100644 index d3d15dfac5..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/netdb.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file - * NETDB API (sockets) - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_NETDB_H -#define LWIP_HDR_NETDB_H - -#include "lwip/opt.h" - -#if LWIP_DNS && LWIP_SOCKET - -#include "lwip/arch.h" -#include "lwip/inet.h" -#include "lwip/sockets.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* some rarely used options */ -#ifndef LWIP_DNS_API_DECLARE_H_ERRNO -#define LWIP_DNS_API_DECLARE_H_ERRNO 1 -#endif - -#ifndef LWIP_DNS_API_DEFINE_ERRORS -#define LWIP_DNS_API_DEFINE_ERRORS 1 -#endif - -#ifndef LWIP_DNS_API_DEFINE_FLAGS -#define LWIP_DNS_API_DEFINE_FLAGS 1 -#endif - -#ifndef LWIP_DNS_API_DECLARE_STRUCTS -#define LWIP_DNS_API_DECLARE_STRUCTS 1 -#endif - -#if LWIP_DNS_API_DEFINE_ERRORS -/** Errors used by the DNS API functions, h_errno can be one of them */ -#define EAI_NONAME 200 -#define EAI_SERVICE 201 -#define EAI_FAIL 202 -#define EAI_MEMORY 203 -#define EAI_FAMILY 204 - -#define HOST_NOT_FOUND 210 -#define NO_DATA 211 -#define NO_RECOVERY 212 -#define TRY_AGAIN 213 -#endif /* LWIP_DNS_API_DEFINE_ERRORS */ - -#if LWIP_DNS_API_DEFINE_FLAGS -/* input flags for struct addrinfo */ -#define AI_PASSIVE 0x01 -#define AI_CANONNAME 0x02 -#define AI_NUMERICHOST 0x04 -#define AI_NUMERICSERV 0x08 -#define AI_V4MAPPED 0x10 -#define AI_ALL 0x20 -#define AI_ADDRCONFIG 0x40 -#endif /* LWIP_DNS_API_DEFINE_FLAGS */ - -#if LWIP_DNS_API_DECLARE_STRUCTS -struct hostent { - char *h_name; /* Official name of the host. */ - char **h_aliases; /* A pointer to an array of pointers to alternative host names, - terminated by a null pointer. */ - int h_addrtype; /* Address type. */ - int h_length; /* The length, in bytes, of the address. */ - char **h_addr_list; /* A pointer to an array of pointers to network addresses (in - network byte order) for the host, terminated by a null pointer. */ -#define h_addr h_addr_list[0] /* for backward compatibility */ -}; - -struct addrinfo { - int ai_flags; /* Input flags. */ - int ai_family; /* Address family of socket. */ - int ai_socktype; /* Socket type. */ - int ai_protocol; /* Protocol of socket. */ - socklen_t ai_addrlen; /* Length of socket address. */ - struct sockaddr *ai_addr; /* Socket address of socket. */ - char *ai_canonname; /* Canonical name of service location. */ - struct addrinfo *ai_next; /* Pointer to next in list. */ -}; -#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ - -#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) - -#if LWIP_DNS_API_DECLARE_H_ERRNO -/* application accessible error code set by the DNS API functions */ -extern int h_errno; -#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ - -struct hostent *lwip_gethostbyname(const char *name); -int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop); -void lwip_freeaddrinfo(struct addrinfo *ai); -int lwip_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); - -#if LWIP_COMPAT_SOCKETS -/** @ingroup netdbapi */ -#define gethostbyname(name) lwip_gethostbyname(name) -/** @ingroup netdbapi */ -#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ - lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) -/** @ingroup netdbapi */ -#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) -/** @ingroup netdbapi */ -#define getaddrinfo(nodname, servname, hints, res) \ - lwip_getaddrinfo(nodname, servname, hints, res) -#endif /* LWIP_COMPAT_SOCKETS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_DNS && LWIP_SOCKET */ - -#endif /* LWIP_HDR_NETDB_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/netif.h b/components/net/lwip-2.0.2/src/include/lwip/netif.h deleted file mode 100644 index 67a2d24de8..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/netif.h +++ /dev/null @@ -1,474 +0,0 @@ -/** - * @file - * netif API (to be used from TCPIP thread) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_NETIF_H -#define LWIP_HDR_NETIF_H - -#include "lwip/opt.h" - -#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) - -#include "lwip/err.h" - -#include "lwip/ip_addr.h" - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Throughout this file, IP addresses are expected to be in - * the same byte order as in IP_PCB. */ - -/** Must be the maximum of all used hardware address lengths - across all types of interfaces in use. - This does not have to be changed, normally. */ -#ifndef NETIF_MAX_HWADDR_LEN -#define NETIF_MAX_HWADDR_LEN 6U -#endif - -/** - * @defgroup netif_flags Flags - * @ingroup netif - * @{ - */ - -/** Whether the network interface is 'up'. This is - * a software flag used to control whether this network - * interface is enabled and processes traffic. - * It must be set by the startup code before this netif can be used - * (also for dhcp/autoip). - */ -#define NETIF_FLAG_UP 0x01U -/** If set, the netif has broadcast capability. - * Set by the netif driver in its init function. */ -#define NETIF_FLAG_BROADCAST 0x02U -/** If set, the interface has an active link - * (set by the network interface driver). - * Either set by the netif driver in its init function (if the link - * is up at that time) or at a later point once the link comes up - * (if link detection is supported by the hardware). */ -#define NETIF_FLAG_LINK_UP 0x04U -/** If set, the netif is an ethernet device using ARP. - * Set by the netif driver in its init function. - * Used to check input packet types and use of DHCP. */ -#define NETIF_FLAG_ETHARP 0x08U -/** If set, the netif is an ethernet device. It might not use - * ARP or TCP/IP if it is used for PPPoE only. - */ -#define NETIF_FLAG_ETHERNET 0x10U -/** If set, the netif has IGMP capability. - * Set by the netif driver in its init function. */ -#define NETIF_FLAG_IGMP 0x20U -/** If set, the netif has MLD6 capability. - * Set by the netif driver in its init function. */ -#define NETIF_FLAG_MLD6 0x40U - -/** - * @} - */ - -enum lwip_internal_netif_client_data_index -{ -#if LWIP_DHCP - LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, -#endif -#if LWIP_AUTOIP - LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, -#endif -#if LWIP_IGMP - LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, -#endif -#if LWIP_IPV6_MLD - LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, -#endif - LWIP_NETIF_CLIENT_DATA_INDEX_MAX -}; - -#if LWIP_CHECKSUM_CTRL_PER_NETIF -#define NETIF_CHECKSUM_GEN_IP 0x0001 -#define NETIF_CHECKSUM_GEN_UDP 0x0002 -#define NETIF_CHECKSUM_GEN_TCP 0x0004 -#define NETIF_CHECKSUM_GEN_ICMP 0x0008 -#define NETIF_CHECKSUM_GEN_ICMP6 0x0010 -#define NETIF_CHECKSUM_CHECK_IP 0x0100 -#define NETIF_CHECKSUM_CHECK_UDP 0x0200 -#define NETIF_CHECKSUM_CHECK_TCP 0x0400 -#define NETIF_CHECKSUM_CHECK_ICMP 0x0800 -#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000 -#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF -#define NETIF_CHECKSUM_DISABLE_ALL 0x0000 -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ - -struct netif; - -/** MAC Filter Actions, these are passed to a netif's igmp_mac_filter or - * mld_mac_filter callback function. */ -enum netif_mac_filter_action { - /** Delete a filter entry */ - NETIF_DEL_MAC_FILTER = 0, - /** Add a filter entry */ - NETIF_ADD_MAC_FILTER = 1 -}; - -/** Function prototype for netif init functions. Set up flags and output/linkoutput - * callback functions in this function. - * - * @param netif The netif to initialize - */ -typedef err_t (*netif_init_fn)(struct netif *netif); -/** Function prototype for netif->input functions. This function is saved as 'input' - * callback function in the netif struct. Call it when a packet has been received. - * - * @param p The received packet, copied into a pbuf - * @param inp The netif which received the packet - */ -typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); - -#if LWIP_IPV4 -/** Function prototype for netif->output functions. Called by lwIP when a packet - * shall be sent. For ethernet netif, set this to 'etharp_output' and set - * 'linkoutput'. - * - * @param netif The netif which shall send a packet - * @param p The packet to send (p->payload points to IP header) - * @param ipaddr The IP address to which the packet shall be sent - */ -typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, - const ip4_addr_t *ipaddr); -#endif /* LWIP_IPV4*/ - -#if LWIP_IPV6 -/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet - * shall be sent. For ethernet netif, set this to 'ethip6_output' and set - * 'linkoutput'. - * - * @param netif The netif which shall send a packet - * @param p The packet to send (p->payload points to IP header) - * @param ipaddr The IPv6 address to which the packet shall be sent - */ -typedef err_t (*netif_output_ip6_fn)(struct netif *netif, struct pbuf *p, - const ip6_addr_t *ipaddr); -#endif /* LWIP_IPV6 */ - -/** Function prototype for netif->linkoutput functions. Only used for ethernet - * netifs. This function is called by ARP when a packet shall be sent. - * - * @param netif The netif which shall send a packet - * @param p The packet to send (raw ethernet packet) - */ -typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); -/** Function prototype for netif status- or link-callback functions. */ -typedef void (*netif_status_callback_fn)(struct netif *netif); -#if LWIP_IPV4 && LWIP_IGMP -/** Function prototype for netif igmp_mac_filter functions */ -typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, - const ip4_addr_t *group, enum netif_mac_filter_action action); -#endif /* LWIP_IPV4 && LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD -/** Function prototype for netif mld_mac_filter functions */ -typedef err_t (*netif_mld_mac_filter_fn)(struct netif *netif, - const ip6_addr_t *group, enum netif_mac_filter_action action); -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - -#if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || (LWIP_NUM_NETIF_CLIENT_DATA > 0) -u8_t netif_alloc_client_data_id(void); -/** @ingroup netif_cd - * Set client data. Obtain ID from netif_alloc_client_data_id(). - */ -#define netif_set_client_data(netif, id, data) netif_get_client_data(netif, id) = (data) -/** @ingroup netif_cd - * Get client data. Obtain ID from netif_alloc_client_data_id(). - */ -#define netif_get_client_data(netif, id) (netif)->client_data[(id)] -#endif /* LWIP_DHCP || LWIP_AUTOIP || (LWIP_NUM_NETIF_CLIENT_DATA > 0) */ - -/** Generic data structure used for all lwIP network interfaces. - * The following fields should be filled in by the initialization - * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ -struct netif { - /** pointer to next in linked list */ - struct netif *next; - -#if LWIP_IPV4 - /** IP address configuration in network byte order */ - ip_addr_t ip_addr; - ip_addr_t netmask; - ip_addr_t gw; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - /** Array of IPv6 addresses for this netif. */ - ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; - /** The state of each IPv6 address (Tentative, Preferred, etc). - * @see ip6_addr.h */ - u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; -#endif /* LWIP_IPV6 */ - /** This function is called by the network device driver - * to pass a packet up the TCP/IP stack. */ - netif_input_fn input; -#if LWIP_IPV4 - /** This function is called by the IP module when it wants - * to send a packet on the interface. This function typically - * first resolves the hardware address, then sends the packet. - * For ethernet physical layer, this is usually etharp_output() */ - netif_output_fn output; -#endif /* LWIP_IPV4 */ - /** This function is called by ethernet_output() when it wants - * to send a packet on the interface. This function outputs - * the pbuf as-is on the link medium. */ - netif_linkoutput_fn linkoutput; -#if LWIP_IPV6 - /** This function is called by the IPv6 module when it wants - * to send a packet on the interface. This function typically - * first resolves the hardware address, then sends the packet. - * For ethernet physical layer, this is usually ethip6_output() */ - netif_output_ip6_fn output_ip6; -#endif /* LWIP_IPV6 */ -#if LWIP_NETIF_STATUS_CALLBACK - /** This function is called when the netif state is set to up or down - */ - netif_status_callback_fn status_callback; -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK - /** This function is called when the netif link is set to up or down - */ - netif_status_callback_fn link_callback; -#endif /* LWIP_NETIF_LINK_CALLBACK */ -#if LWIP_NETIF_REMOVE_CALLBACK - /** This function is called when the netif has been removed */ - netif_status_callback_fn remove_callback; -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - /** This field can be set by the device driver and could point - * to state information for the device. */ - void *state; -#ifdef netif_get_client_data - void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; -#endif -#if LWIP_IPV6_AUTOCONFIG - /** is this netif enabled for IPv6 autoconfiguration */ - u8_t ip6_autoconfig_enabled; -#endif /* LWIP_IPV6_AUTOCONFIG */ -#if LWIP_IPV6_SEND_ROUTER_SOLICIT - /** Number of Router Solicitation messages that remain to be sent. */ - u8_t rs_count; -#endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ -#if LWIP_NETIF_HOSTNAME - /* the hostname for this netif, NULL is a valid value */ - const char* hostname; -#endif /* LWIP_NETIF_HOSTNAME */ -#if LWIP_CHECKSUM_CTRL_PER_NETIF - u16_t chksum_flags; -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ - /** maximum transfer unit (in bytes) */ - u16_t mtu; - /** number of bytes used in hwaddr */ - u8_t hwaddr_len; - /** link level hardware address of this interface */ - u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; - /** flags (@see @ref netif_flags) */ - u8_t flags; - /** descriptive abbreviation */ - char name[2]; - /** number of this interface */ - u8_t num; -#if MIB2_STATS - /** link type (from "snmp_ifType" enum from snmp_mib2.h) */ - u8_t link_type; - /** (estimate) link speed */ - u32_t link_speed; - /** timestamp at last change made (up/down) */ - u32_t ts; - /** counters */ - struct stats_mib2_netif_ctrs mib2_counters; -#endif /* MIB2_STATS */ -#if LWIP_IPV4 && LWIP_IGMP - /** This function could be called to add or delete an entry in the multicast - filter table of the ethernet MAC.*/ - netif_igmp_mac_filter_fn igmp_mac_filter; -#endif /* LWIP_IPV4 && LWIP_IGMP */ -#if LWIP_IPV6 && LWIP_IPV6_MLD - /** This function could be called to add or delete an entry in the IPv6 multicast - filter table of the ethernet MAC. */ - netif_mld_mac_filter_fn mld_mac_filter; -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ -#if LWIP_NETIF_HWADDRHINT - u8_t *addr_hint; -#endif /* LWIP_NETIF_HWADDRHINT */ -#if ENABLE_LOOPBACK - /* List of packets to be queued for ourselves. */ - struct pbuf *loop_first; - struct pbuf *loop_last; -#if LWIP_LOOPBACK_MAX_PBUFS - u16_t loop_cnt_current; -#endif /* LWIP_LOOPBACK_MAX_PBUFS */ -#endif /* ENABLE_LOOPBACK */ -}; - -#if LWIP_CHECKSUM_CTRL_PER_NETIF -#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \ - (netif)->chksum_flags = chksumflags; } while(0) -#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0)) -#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */ -#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) -#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) -#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */ - -/** The list of network interfaces. */ -extern struct netif *netif_list; -/** The default network interface. */ -extern struct netif *netif_default; - -void netif_init(void); - -struct netif *netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input); -#if LWIP_IPV4 -void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, - const ip4_addr_t *gw); -#endif /* LWIP_IPV4 */ -void netif_remove(struct netif * netif); - -/* Returns a network interface given its name. The name is of the form - "et0", where the first two letters are the "name" field in the - netif structure, and the digit is in the num field in the same - structure. */ -struct netif *netif_find(const char *name); - -void netif_set_default(struct netif *netif); - -#if LWIP_IPV4 -void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); -void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); -void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); -/** @ingroup netif_ip4 */ -#define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) -/** @ingroup netif_ip4 */ -#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask))) -/** @ingroup netif_ip4 */ -#define netif_ip4_gw(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw))) -/** @ingroup netif_ip4 */ -#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) -/** @ingroup netif_ip4 */ -#define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask)) -/** @ingroup netif_ip4 */ -#define netif_ip_gw4(netif) ((const ip_addr_t*)&((netif)->gw)) -#endif /* LWIP_IPV4 */ - -void netif_set_up(struct netif *netif); -void netif_set_down(struct netif *netif); -/** @ingroup netif - * Ask if an interface is up - */ -#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) - -#if LWIP_NETIF_STATUS_CALLBACK -void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback); -#endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_REMOVE_CALLBACK -void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback); -#endif /* LWIP_NETIF_REMOVE_CALLBACK */ - -void netif_set_link_up(struct netif *netif); -void netif_set_link_down(struct netif *netif); -/** Ask if a link is up */ -#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) - -#if LWIP_NETIF_LINK_CALLBACK -void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback); -#endif /* LWIP_NETIF_LINK_CALLBACK */ - -#if LWIP_NETIF_HOSTNAME -/** @ingroup netif */ -#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) -/** @ingroup netif */ -#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) -#endif /* LWIP_NETIF_HOSTNAME */ - -#if LWIP_IGMP -/** @ingroup netif */ -#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) -#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) -#endif /* LWIP_IGMP */ - -#if LWIP_IPV6 && LWIP_IPV6_MLD -/** @ingroup netif */ -#define netif_set_mld_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->mld_mac_filter = function; }}while(0) -#define netif_get_mld_mac_filter(netif) (((netif) != NULL) ? ((netif)->mld_mac_filter) : NULL) -#define netif_mld_mac_filter(netif, addr, action) do { if((netif) && (netif)->mld_mac_filter) { (netif)->mld_mac_filter((netif), (addr), (action)); }}while(0) -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - -#if ENABLE_LOOPBACK -err_t netif_loop_output(struct netif *netif, struct pbuf *p); -void netif_poll(struct netif *netif); -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING -void netif_poll_all(void); -#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ -#endif /* ENABLE_LOOPBACK */ - -err_t netif_input(struct pbuf *p, struct netif *inp); - -#if LWIP_IPV6 -/** @ingroup netif_ip6 */ -#define netif_ip_addr6(netif, i) ((const ip_addr_t*)(&((netif)->ip6_addr[i]))) -/** @ingroup netif_ip6 */ -#define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) -void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6); -void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3); -#define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) -void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state); -s8_t netif_get_ip6_addr_match(struct netif *netif, const ip6_addr_t *ip6addr); -void netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit); -err_t netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chosen_idx); -#define netif_set_ip6_autoconfig_enabled(netif, action) do { if(netif) { (netif)->ip6_autoconfig_enabled = (action); }}while(0) -#endif /* LWIP_IPV6 */ - -#if LWIP_NETIF_HWADDRHINT -#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint)) -#else /* LWIP_NETIF_HWADDRHINT */ -#define NETIF_SET_HWADDRHINT(netif, hint) -#endif /* LWIP_NETIF_HWADDRHINT */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_NETIF_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/netifapi.h b/components/net/lwip-2.0.2/src/include/lwip/netifapi.h deleted file mode 100644 index 8bd2b4f76f..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/netifapi.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file - * netif API (to be used from non-TCPIP threads) - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#ifndef LWIP_HDR_NETIFAPI_H -#define LWIP_HDR_NETIFAPI_H - -#include "lwip/opt.h" - -#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sys.h" -#include "lwip/netif.h" -#include "lwip/dhcp.h" -#include "lwip/autoip.h" -#include "lwip/priv/tcpip_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_MPU_COMPATIBLE -#define NETIFAPI_IPADDR_DEF(type, m) type m -#else /* LWIP_MPU_COMPATIBLE */ -#define NETIFAPI_IPADDR_DEF(type, m) const type * m -#endif /* LWIP_MPU_COMPATIBLE */ - -typedef void (*netifapi_void_fn)(struct netif *netif); -typedef err_t (*netifapi_errt_fn)(struct netif *netif); - -struct netifapi_msg { - struct tcpip_api_call_data call; - struct netif *netif; - union { - struct { -#if LWIP_IPV4 - NETIFAPI_IPADDR_DEF(ip4_addr_t, ipaddr); - NETIFAPI_IPADDR_DEF(ip4_addr_t, netmask); - NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); -#endif /* LWIP_IPV4 */ - void *state; - netif_init_fn init; - netif_input_fn input; - } add; - struct { - netifapi_void_fn voidfunc; - netifapi_errt_fn errtfunc; - } common; - } msg; -}; - - -/* API for application */ -err_t netifapi_netif_add(struct netif *netif, -#if LWIP_IPV4 - const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, -#endif /* LWIP_IPV4 */ - void *state, netif_init_fn init, netif_input_fn input); - -#if LWIP_IPV4 -err_t netifapi_netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, - const ip4_addr_t *netmask, const ip4_addr_t *gw); -#endif /* LWIP_IPV4*/ - -err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - netifapi_errt_fn errtfunc); - -/** @ingroup netifapi_netif */ -#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) -/** @ingroup netifapi_netif */ -#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) - -/** - * @defgroup netifapi_dhcp4 DHCPv4 - * @ingroup netifapi - * To be called from non-TCPIP threads - */ -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_inform(n) netifapi_netif_common(n, dhcp_inform, NULL) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_renew(n) netifapi_netif_common(n, NULL, dhcp_renew) -/** @ingroup netifapi_dhcp4 */ -#define netifapi_dhcp_release(n) netifapi_netif_common(n, NULL, dhcp_release) - -/** - * @defgroup netifapi_autoip AUTOIP - * @ingroup netifapi - * To be called from non-TCPIP threads - */ -/** @ingroup netifapi_autoip */ -#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) -/** @ingroup netifapi_autoip */ -#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETIF_API */ - -#endif /* LWIP_HDR_NETIFAPI_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/opt.h b/components/net/lwip-2.0.2/src/include/lwip/opt.h deleted file mode 100644 index fd459af144..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/opt.h +++ /dev/null @@ -1,2876 +0,0 @@ -/** - * @file - * - * lwIP Options Configuration - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -/* - * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - - * without this, doxygen does not see the actual #define - */ - -#if !defined LWIP_HDR_OPT_H -#define LWIP_HDR_OPT_H - -/* - * Include user defined options first. Anything not defined in these files - * will be set to standard values. Override anything you don't like! - */ -#include "lwipopts.h" -#include "lwip/debug.h" - -/** - * @defgroup lwip_opts Options (lwipopts.h) - * @ingroup lwip - * - * @defgroup lwip_opts_debug Debugging - * @ingroup lwip_opts - * - * @defgroup lwip_opts_infrastructure Infrastructure - * @ingroup lwip_opts - * - * @defgroup lwip_opts_callback Callback-style APIs - * @ingroup lwip_opts - * - * @defgroup lwip_opts_threadsafe_apis Thread-safe APIs - * @ingroup lwip_opts - */ - - /* - ------------------------------------ - -------------- NO SYS -------------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_nosys NO_SYS - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * NO_SYS==1: Use lwIP without OS-awareness (no thread, semaphores, mutexes or - * mboxes). This means threaded APIs cannot be used (socket, netconn, - * i.e. everything in the 'api' folder), only the callback-style raw API is - * available (and you have to watch out for yourself that you don't access - * lwIP functions/structures from more than one context at a time!) - */ -#if !defined NO_SYS || defined __DOXYGEN__ -#define NO_SYS 0 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_timers Timers - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_TIMERS==0: Drop support for sys_timeout and lwip-internal cyclic timers. - * (the array of lwip-internal cyclic timers is still provided) - * (check NO_SYS_NO_TIMERS for compatibility to old versions) - */ -#if !defined LWIP_TIMERS || defined __DOXYGEN__ -#ifdef NO_SYS_NO_TIMERS -#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) -#else -#define LWIP_TIMERS 1 -#endif -#endif - -/** - * LWIP_TIMERS_CUSTOM==1: Provide your own timer implementation. - * Function prototypes in timeouts.h and the array of lwip-internal cyclic timers - * are still included, but the implementation is not. The following functions - * will be required: sys_timeouts_init(), sys_timeout(), sys_untimeout(), - * sys_timeouts_mbox_fetch() - */ -#if !defined LWIP_TIMERS_CUSTOM || defined __DOXYGEN__ -#define LWIP_TIMERS_CUSTOM 0 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_memcpy memcpy - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * MEMCPY: override this if you have a faster implementation at hand than the - * one included in your C library - */ -#if !defined MEMCPY || defined __DOXYGEN__ -#define MEMCPY(dst,src,len) memcpy(dst,src,len) -#endif - -/** - * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a - * call to memcpy() if the length is known at compile time and is small. - */ -#if !defined SMEMCPY || defined __DOXYGEN__ -#define SMEMCPY(dst,src,len) memcpy(dst,src,len) -#endif -/** - * @} - */ - -/* - ------------------------------------ - ----------- Core locking ----------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_lock Core locking and MPU - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_MPU_COMPATIBLE: enables special memory management mechanism - * which makes lwip able to work on MPU (Memory Protection Unit) system - * by not passing stack-pointers to other threads - * (this decreases performance as memory is allocated from pools instead - * of keeping it on the stack) - */ -#if !defined LWIP_MPU_COMPATIBLE || defined __DOXYGEN__ -#define LWIP_MPU_COMPATIBLE 0 -#endif - -/** - * LWIP_TCPIP_CORE_LOCKING - * Creates a global mutex that is held during TCPIP thread operations. - * Can be locked by client code to perform lwIP operations without changing - * into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and - * UNLOCK_TCPIP_CORE(). - * Your system should provide mutexes supporting priority inversion to use this. - */ -#if !defined LWIP_TCPIP_CORE_LOCKING || defined __DOXYGEN__ -#define LWIP_TCPIP_CORE_LOCKING 1 -#endif - -/** - * LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled, - * this lets tcpip_input() grab the mutex for input packets as well, - * instead of allocating a message and passing it to tcpip_thread. - * - * ATTENTION: this does not work when tcpip_input() is called from - * interrupt context! - */ -#if !defined LWIP_TCPIP_CORE_LOCKING_INPUT || defined __DOXYGEN__ -#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 -#endif - -/** - * SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt - * protection) for certain critical regions during buffer allocation, deallocation - * and memory allocation and deallocation. - * ATTENTION: This is required when using lwIP from more than one context! If - * you disable this, you must be sure what you are doing! - */ -#if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__ -#define SYS_LIGHTWEIGHT_PROT 1 -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- Memory options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_mem Heap and memory pools - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library - * instead of the lwip internal allocator. Can save code size if you - * already use it. - */ -#if !defined MEM_LIBC_MALLOC || defined __DOXYGEN__ -#define MEM_LIBC_MALLOC 0 -#endif - -/** - * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. - * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution - * speed (heap alloc can be much slower than pool alloc) and usage from interrupts - * (especially if your netif driver allocates PBUF_POOL pbufs for received frames - * from interrupt)! - * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools, - * not only for internal pools defined in memp_std.h)! - */ -#if !defined MEMP_MEM_MALLOC || defined __DOXYGEN__ -#define MEMP_MEM_MALLOC 0 -#endif - -/** - * MEM_ALIGNMENT: should be set to the alignment of the CPU - * 4 byte alignment -> \#define MEM_ALIGNMENT 4 - * 2 byte alignment -> \#define MEM_ALIGNMENT 2 - */ -#if !defined MEM_ALIGNMENT || defined __DOXYGEN__ -#define MEM_ALIGNMENT 1 -#endif - -/** - * MEM_SIZE: the size of the heap memory. If the application will send - * a lot of data that needs to be copied, this should be set high. - */ -#if !defined MEM_SIZE || defined __DOXYGEN__ -#define MEM_SIZE 1600 -#endif - -/** - * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable - * amount of bytes before and after each memp element in every pool and fills - * it with a prominent default value. - * MEMP_OVERFLOW_CHECK == 0 no checking - * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed - * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time - * memp_malloc() or memp_free() is called (useful but slow!) - */ -#if !defined MEMP_OVERFLOW_CHECK || defined __DOXYGEN__ -#define MEMP_OVERFLOW_CHECK 0 -#endif - -/** - * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make - * sure that there are no cycles in the linked lists. - */ -#if !defined MEMP_SANITY_CHECK || defined __DOXYGEN__ -#define MEMP_SANITY_CHECK 0 -#endif - -/** - * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set - * of memory pools of various sizes. When mem_malloc is called, an element of - * the smallest pool that can provide the length needed is returned. - * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. - */ -#if !defined MEM_USE_POOLS || defined __DOXYGEN__ -#define MEM_USE_POOLS 0 -#endif - -/** - * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next - * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more - * reliable. */ -#if !defined MEM_USE_POOLS_TRY_BIGGER_POOL || defined __DOXYGEN__ -#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 -#endif - -/** - * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h - * that defines additional pools beyond the "standard" ones required - * by lwIP. If you set this to 1, you must have lwippools.h in your - * include path somewhere. - */ -#if !defined MEMP_USE_CUSTOM_POOLS || defined __DOXYGEN__ -#define MEMP_USE_CUSTOM_POOLS 0 -#endif - -/** - * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from - * interrupt context (or another context that doesn't allow waiting for a - * semaphore). - * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, - * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs - * with each loop so that mem_free can run. - * - * ATTENTION: As you can see from the above description, this leads to dis-/ - * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc - * can need longer. - * - * If you don't want that, at least for NO_SYS=0, you can still use the following - * functions to enqueue a deallocation call which then runs in the tcpip_thread - * context: - * - pbuf_free_callback(p); - * - mem_free_callback(m); - */ -#if !defined LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT || defined __DOXYGEN__ -#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 -#endif -/** - * @} - */ - -/* - ------------------------------------------------ - ---------- Internal Memory Pool Sizes ---------- - ------------------------------------------------ -*/ -/** - * @defgroup lwip_opts_memp Internal memory pools - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). - * If the application sends a lot of data out of ROM (or other static memory), - * this should be set high. - */ -#if !defined MEMP_NUM_PBUF || defined __DOXYGEN__ -#define MEMP_NUM_PBUF 16 -#endif - -/** - * MEMP_NUM_RAW_PCB: Number of raw connection PCBs - * (requires the LWIP_RAW option) - */ -#if !defined MEMP_NUM_RAW_PCB || defined __DOXYGEN__ -#define MEMP_NUM_RAW_PCB 4 -#endif - -/** - * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One - * per active UDP "connection". - * (requires the LWIP_UDP option) - */ -#if !defined MEMP_NUM_UDP_PCB || defined __DOXYGEN__ -#define MEMP_NUM_UDP_PCB 4 -#endif - -/** - * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. - * (requires the LWIP_TCP option) - */ -#if !defined MEMP_NUM_TCP_PCB || defined __DOXYGEN__ -#define MEMP_NUM_TCP_PCB 5 -#endif - -/** - * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. - * (requires the LWIP_TCP option) - */ -#if !defined MEMP_NUM_TCP_PCB_LISTEN || defined __DOXYGEN__ -#define MEMP_NUM_TCP_PCB_LISTEN 8 -#endif - -/** - * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. - * (requires the LWIP_TCP option) - */ -#if !defined MEMP_NUM_TCP_SEG || defined __DOXYGEN__ -#define MEMP_NUM_TCP_SEG 16 -#endif - -/** - * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for - * reassembly (whole packets, not fragments!) - */ -#if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ -#define MEMP_NUM_REASSDATA 5 -#endif - -/** - * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent - * (fragments, not whole packets!). - * This is only used with LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 - * with DMA-enabled MACs where the packet is not yet sent when netif->output - * returns. - */ -#if !defined MEMP_NUM_FRAG_PBUF || defined __DOXYGEN__ -#define MEMP_NUM_FRAG_PBUF 15 -#endif - -/** - * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing - * packets (pbufs) that are waiting for an ARP request (to resolve - * their destination address) to finish. - * (requires the ARP_QUEUEING option) - */ -#if !defined MEMP_NUM_ARP_QUEUE || defined __DOXYGEN__ -#define MEMP_NUM_ARP_QUEUE 30 -#endif - -/** - * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces - * can be members at the same time (one per netif - allsystems group -, plus one - * per netif membership). - * (requires the LWIP_IGMP option) - */ -#if !defined MEMP_NUM_IGMP_GROUP || defined __DOXYGEN__ -#define MEMP_NUM_IGMP_GROUP 8 -#endif - -/** - * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. - * The default number of timeouts is calculated here for all enabled modules. - * The formula expects settings to be either '0' or '1'. - */ -#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__ -#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) -#endif - -/** - * MEMP_NUM_NETBUF: the number of struct netbufs. - * (only needed if you use the sequential API, like api_lib.c) - */ -#if !defined MEMP_NUM_NETBUF || defined __DOXYGEN__ -#define MEMP_NUM_NETBUF 2 -#endif - -/** - * MEMP_NUM_NETCONN: the number of struct netconns. - * (only needed if you use the sequential API, like api_lib.c) - */ -#if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ -#define MEMP_NUM_NETCONN 4 -#endif - -/** - * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used - * for callback/timeout API communication. - * (only needed if you use tcpip.c) - */ -#if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_API 8 -#endif - -/** - * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used - * for incoming packets. - * (only needed if you use tcpip.c) - */ -#if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ -#define MEMP_NUM_TCPIP_MSG_INPKT 8 -#endif - -/** - * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls - * (before freeing the corresponding memory using lwip_freeaddrinfo()). - */ -#if !defined MEMP_NUM_NETDB || defined __DOXYGEN__ -#define MEMP_NUM_NETDB 1 -#endif - -/** - * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list - * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. - */ -#if !defined MEMP_NUM_LOCALHOSTLIST || defined __DOXYGEN__ -#define MEMP_NUM_LOCALHOSTLIST 1 -#endif - -/** - * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. - */ -#if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ -#define PBUF_POOL_SIZE 16 -#endif - -/** MEMP_NUM_API_MSG: the number of concurrently active calls to various - * socket, netconn, and tcpip functions - */ -#if !defined MEMP_NUM_API_MSG || defined __DOXYGEN__ -#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API -#endif - -/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname - */ -#if !defined MEMP_NUM_DNS_API_MSG || defined __DOXYGEN__ -#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API -#endif - -/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls - * to getsockopt/setsockopt - */ -#if !defined MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA || defined __DOXYGEN__ -#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API -#endif - -/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the - * netifapi functions - */ -#if !defined MEMP_NUM_NETIFAPI_MSG || defined __DOXYGEN__ -#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- ARP options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_arp ARP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_ARP==1: Enable ARP functionality. - */ -#if !defined LWIP_ARP || defined __DOXYGEN__ -#define LWIP_ARP 1 -#endif - -/** - * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. - */ -#if !defined ARP_TABLE_SIZE || defined __DOXYGEN__ -#define ARP_TABLE_SIZE 10 -#endif - -/** the time an ARP entry stays valid after its last update, - * for ARP_TMR_INTERVAL = 1000, this is - * (60 * 5) seconds = 5 minutes. - */ -#if !defined ARP_MAXAGE || defined __DOXYGEN__ -#define ARP_MAXAGE 300 -#endif - -/** - * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address - * resolution. By default, only the most recent packet is queued per IP address. - * This is sufficient for most protocols and mainly reduces TCP connection - * startup time. Set this to 1 if you know your application sends more than one - * packet in a row to an IP address that is not in the ARP cache. - */ -#if !defined ARP_QUEUEING || defined __DOXYGEN__ -#define ARP_QUEUEING 0 -#endif - -/** The maximum number of packets which may be queued for each - * unresolved address by other network layers. Defaults to 3, 0 means disabled. - * Old packets are dropped, new packets are queued. - */ -#if !defined ARP_QUEUE_LEN || defined __DOXYGEN__ -#define ARP_QUEUE_LEN 3 -#endif - -/** - * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with - * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and - * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. - * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. - * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. - * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. - * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) - * that returns 1 to accept a packet or 0 to drop a packet. - */ -#if !defined ETHARP_SUPPORT_VLAN || defined __DOXYGEN__ -#define ETHARP_SUPPORT_VLAN 0 -#endif - -/** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled - */ -#if !defined LWIP_ETHERNET || defined __DOXYGEN__ -#define LWIP_ETHERNET LWIP_ARP -#endif - -/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure - * alignment of payload after that header. Since the header is 14 bytes long, - * without this padding e.g. addresses in the IP header will not be aligned - * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. - */ -#if !defined ETH_PAD_SIZE || defined __DOXYGEN__ -#define ETH_PAD_SIZE 0 -#endif - -/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table - * entries (using etharp_add_static_entry/etharp_remove_static_entry). - */ -#if !defined ETHARP_SUPPORT_STATIC_ENTRIES || defined __DOXYGEN__ -#define ETHARP_SUPPORT_STATIC_ENTRIES 0 -#endif - -/** ETHARP_TABLE_MATCH_NETIF==1: Match netif for ARP table entries. - * If disabled, duplicate IP address on multiple netifs are not supported - * (but this should only occur for AutoIP). - */ -#if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__ -#define ETHARP_TABLE_MATCH_NETIF 0 -#endif -/** - * @} - */ - -/* - -------------------------------- - ---------- IP options ---------- - -------------------------------- -*/ -/** - * @defgroup lwip_opts_ipv4 IPv4 - * @ingroup lwip_opts - * @{ - */ -/** - * LWIP_IPV4==1: Enable IPv4 - */ -#if !defined LWIP_IPV4 || defined __DOXYGEN__ -#define LWIP_IPV4 1 -#endif - -/** - * IP_FORWARD==1: Enables the ability to forward IP packets across network - * interfaces. If you are going to run lwIP on a device with only one network - * interface, define this to 0. - */ -#if !defined IP_FORWARD || defined __DOXYGEN__ -#define IP_FORWARD 0 -#endif - -/** - * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that - * this option does not affect outgoing packet sizes, which can be controlled - * via IP_FRAG. - */ -#if !defined IP_REASSEMBLY || defined __DOXYGEN__ -#define IP_REASSEMBLY 1 -#endif - -/** - * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note - * that this option does not affect incoming packet sizes, which can be - * controlled via IP_REASSEMBLY. - */ -#if !defined IP_FRAG || defined __DOXYGEN__ -#define IP_FRAG 1 -#endif - -#if !LWIP_IPV4 -/* disable IPv4 extensions when IPv4 is disabled */ -#undef IP_FORWARD -#define IP_FORWARD 0 -#undef IP_REASSEMBLY -#define IP_REASSEMBLY 0 -#undef IP_FRAG -#define IP_FRAG 0 -#endif /* !LWIP_IPV4 */ - -/** - * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. - * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. - * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). - */ -#if !defined IP_OPTIONS_ALLOWED || defined __DOXYGEN__ -#define IP_OPTIONS_ALLOWED 1 -#endif - -/** - * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) - * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived - * in this time, the whole packet is discarded. - */ -#if !defined IP_REASS_MAXAGE || defined __DOXYGEN__ -#define IP_REASS_MAXAGE 3 -#endif - -/** - * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. - * Since the received pbufs are enqueued, be sure to configure - * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive - * packets even if the maximum amount of fragments is enqueued for reassembly! - */ -#if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__ -#define IP_REASS_MAX_PBUFS 10 -#endif - -/** - * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. - */ -#if !defined IP_DEFAULT_TTL || defined __DOXYGEN__ -#define IP_DEFAULT_TTL 255 -#endif - -/** - * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast - * filter per pcb on udp and raw send operations. To enable broadcast filter - * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. - */ -#if !defined IP_SOF_BROADCAST || defined __DOXYGEN__ -#define IP_SOF_BROADCAST 0 -#endif - -/** - * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast - * filter on recv operations. - */ -#if !defined IP_SOF_BROADCAST_RECV || defined __DOXYGEN__ -#define IP_SOF_BROADCAST_RECV 0 -#endif - -/** - * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back - * out on the netif where it was received. This should only be used for - * wireless networks. - * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming - * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! - */ -#if !defined IP_FORWARD_ALLOW_TX_ON_RX_NETIF || defined __DOXYGEN__ -#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 -#endif - -/** - * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first - * local TCP/UDP pcb (default==0). This can prevent creating predictable port - * numbers after booting a device. - */ -#if !defined LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS || defined __DOXYGEN__ -#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- ICMP options ---------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_icmp ICMP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_ICMP==1: Enable ICMP module inside the IP stack. - * Be careful, disable that make your product non-compliant to RFC1122 - */ -#if !defined LWIP_ICMP || defined __DOXYGEN__ -#define LWIP_ICMP 1 -#endif - -/** - * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. - */ -#if !defined ICMP_TTL || defined __DOXYGEN__ -#define ICMP_TTL (IP_DEFAULT_TTL) -#endif - -/** - * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) - */ -#if !defined LWIP_BROADCAST_PING || defined __DOXYGEN__ -#define LWIP_BROADCAST_PING 0 -#endif - -/** - * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) - */ -#if !defined LWIP_MULTICAST_PING || defined __DOXYGEN__ -#define LWIP_MULTICAST_PING 0 -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- RAW options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_raw RAW - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. - */ -#if !defined LWIP_RAW || defined __DOXYGEN__ -#define LWIP_RAW 0 -#endif - -/** - * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. - */ -#if !defined RAW_TTL || defined __DOXYGEN__ -#define RAW_TTL (IP_DEFAULT_TTL) -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- DHCP options ---------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_dhcp DHCP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_DHCP==1: Enable DHCP module. - */ -#if !defined LWIP_DHCP || defined __DOXYGEN__ -#define LWIP_DHCP 0 -#endif -#if !LWIP_IPV4 -/* disable DHCP when IPv4 is disabled */ -#undef LWIP_DHCP -#define LWIP_DHCP 0 -#endif /* !LWIP_IPV4 */ - -/** - * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. - */ -#if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__ -#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) -#endif - -/** - * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has - * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and - * netif drivers might not set this flag, the default is off. If enabled, - * netif_set_link_up() must be called to continue dhcp starting. - */ -#if !defined LWIP_DHCP_CHECK_LINK_UP -#define LWIP_DHCP_CHECK_LINK_UP 0 -#endif - -/** - * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. - */ -#if !defined LWIP_DHCP_BOOTP_FILE || defined __DOXYGEN__ -#define LWIP_DHCP_BOOTP_FILE 0 -#endif - -/** - * LWIP_DHCP_GETS_NTP==1: Request NTP servers with discover/select. For each - * response packet, an callback is called, which has to be provided by the port: - * void dhcp_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs); -*/ -#if !defined LWIP_DHCP_GET_NTP_SRV || defined __DOXYGEN__ -#define LWIP_DHCP_GET_NTP_SRV 0 -#endif - -/** - * The maximum of NTP servers requested - */ -#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__ -#define LWIP_DHCP_MAX_NTP_SERVERS 1 -#endif - -/** - * LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select. - * DHCP servers received in the response are passed to DNS via @ref dns_setserver() - * (up to the maximum limit defined here). - */ -#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__ -#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- AUTOIP options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_autoip AUTOIP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_AUTOIP==1: Enable AUTOIP module. - */ -#if !defined LWIP_AUTOIP || defined __DOXYGEN__ -#define LWIP_AUTOIP 0 -#endif -#if !LWIP_IPV4 -/* disable AUTOIP when IPv4 is disabled */ -#undef LWIP_AUTOIP -#define LWIP_AUTOIP 0 -#endif /* !LWIP_IPV4 */ - -/** - * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on - * the same interface at the same time. - */ -#if !defined LWIP_DHCP_AUTOIP_COOP || defined __DOXYGEN__ -#define LWIP_DHCP_AUTOIP_COOP 0 -#endif - -/** - * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes - * that should be sent before falling back on AUTOIP (the DHCP client keeps - * running in this case). This can be set as low as 1 to get an AutoIP address - * very quickly, but you should be prepared to handle a changing IP address - * when DHCP overrides AutoIP. - */ -#if !defined LWIP_DHCP_AUTOIP_COOP_TRIES || defined __DOXYGEN__ -#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ----- SNMP MIB2 support ----- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_mib2 SNMP MIB2 callbacks - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_MIB2_CALLBACKS==1: Turn on SNMP MIB2 callbacks. - * Turn this on to get callbacks needed to implement MIB2. - * Usually MIB2_STATS should be enabled, too. - */ -#if !defined LWIP_MIB2_CALLBACKS || defined __DOXYGEN__ -#define LWIP_MIB2_CALLBACKS 0 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ----- Multicast/IGMP options ----- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_igmp IGMP - * @ingroup lwip_opts_ipv4 - * @{ - */ -/** - * LWIP_IGMP==1: Turn on IGMP module. - */ -#if !defined LWIP_IGMP || defined __DOXYGEN__ -#define LWIP_IGMP 0 -#endif -#if !LWIP_IPV4 -#undef LWIP_IGMP -#define LWIP_IGMP 0 -#endif - -/** - * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options - * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP - */ -#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ -#define LWIP_MULTICAST_TX_OPTIONS (LWIP_IGMP && LWIP_UDP) -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- DNS options ----------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_dns DNS - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS - * transport. - */ -#if !defined LWIP_DNS || defined __DOXYGEN__ -#define LWIP_DNS 0 -#endif - -/** DNS maximum number of entries to maintain locally. */ -#if !defined DNS_TABLE_SIZE || defined __DOXYGEN__ -#define DNS_TABLE_SIZE 4 -#endif - -/** DNS maximum host name length supported in the name table. */ -#if !defined DNS_MAX_NAME_LENGTH || defined __DOXYGEN__ -#define DNS_MAX_NAME_LENGTH 256 -#endif - -/** The maximum of DNS servers - * The first server can be initialized automatically by defining - * DNS_SERVER_ADDRESS(ipaddr), where 'ipaddr' is an 'ip_addr_t*' - */ -#if !defined DNS_MAX_SERVERS || defined __DOXYGEN__ -#define DNS_MAX_SERVERS 2 -#endif - -/** DNS do a name checking between the query and the response. */ -#if !defined DNS_DOES_NAME_CHECK || defined __DOXYGEN__ -#define DNS_DOES_NAME_CHECK 1 -#endif - -/** LWIP_DNS_SECURE: controls the security level of the DNS implementation - * Use all DNS security features by default. - * This is overridable but should only be needed by very small targets - * or when using against non standard DNS servers. */ -#if !defined LWIP_DNS_SECURE || defined __DOXYGEN__ -#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -#endif - -/* A list of DNS security features follows */ -#define LWIP_DNS_SECURE_RAND_XID 1 -#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 -#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 - -/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer: - * \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \ - * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)} - * - * Instead, you can also use an external function: - * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) - * that looks up the IP address and returns ERR_OK if found (LWIP_DNS_ADDRTYPE_xxx is passed in dns_addrtype). - */ -#if !defined DNS_LOCAL_HOSTLIST || defined __DOXYGEN__ -#define DNS_LOCAL_HOSTLIST 0 -#endif /* DNS_LOCAL_HOSTLIST */ - -/** If this is turned on, the local host-list can be dynamically changed - * at runtime. */ -#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__ -#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 -#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -/** Set this to 1 to enable querying ".local" names via mDNS - * using a One-Shot Multicast DNS Query */ -#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__ -#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- UDP options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_udp UDP - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_UDP==1: Turn on UDP. - */ -#if !defined LWIP_UDP || defined __DOXYGEN__ -#define LWIP_UDP 1 -#endif - -/** - * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) - */ -#if !defined LWIP_UDPLITE || defined __DOXYGEN__ -#define LWIP_UDPLITE 0 -#endif - -/** - * UDP_TTL: Default Time-To-Live value. - */ -#if !defined UDP_TTL || defined __DOXYGEN__ -#define UDP_TTL (IP_DEFAULT_TTL) -#endif - -/** - * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. - */ -#if !defined LWIP_NETBUF_RECVINFO || defined __DOXYGEN__ -#define LWIP_NETBUF_RECVINFO 0 -#endif -/** - * @} - */ - -/* - --------------------------------- - ---------- TCP options ---------- - --------------------------------- -*/ -/** - * @defgroup lwip_opts_tcp TCP - * @ingroup lwip_opts_callback - * @{ - */ -/** - * LWIP_TCP==1: Turn on TCP. - */ -#if !defined LWIP_TCP || defined __DOXYGEN__ -#define LWIP_TCP 1 -#endif - -/** - * TCP_TTL: Default Time-To-Live value. - */ -#if !defined TCP_TTL || defined __DOXYGEN__ -#define TCP_TTL (IP_DEFAULT_TTL) -#endif - -/** - * TCP_WND: The size of a TCP window. This must be at least - * (2 * TCP_MSS) for things to work well. - * ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size - * with scaling applied. Maximum window value in the TCP header - * will be TCP_WND >> TCP_RCV_SCALE - */ -#if !defined TCP_WND || defined __DOXYGEN__ -#define TCP_WND (4 * TCP_MSS) -#endif - -/** - * TCP_MAXRTX: Maximum number of retransmissions of data segments. - */ -#if !defined TCP_MAXRTX || defined __DOXYGEN__ -#define TCP_MAXRTX 12 -#endif - -/** - * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. - */ -#if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ -#define TCP_SYNMAXRTX 6 -#endif - -/** - * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. - * Define to 0 if your device is low on memory. - */ -#if !defined TCP_QUEUE_OOSEQ || defined __DOXYGEN__ -#define TCP_QUEUE_OOSEQ (LWIP_TCP) -#endif - -/** - * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, - * you might want to increase this.) - * For the receive side, this MSS is advertised to the remote side - * when opening a connection. For the transmit size, this MSS sets - * an upper limit on the MSS advertised by the remote host. - */ -#if !defined TCP_MSS || defined __DOXYGEN__ -#define TCP_MSS 536 -#endif - -/** - * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really - * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which - * reflects the available reassembly buffer size at the remote host) and the - * largest size permitted by the IP layer" (RFC 1122) - * Setting this to 1 enables code that checks TCP_MSS against the MTU of the - * netif used for a connection and limits the MSS if it would be too big otherwise. - */ -#if !defined TCP_CALCULATE_EFF_SEND_MSS || defined __DOXYGEN__ -#define TCP_CALCULATE_EFF_SEND_MSS 1 -#endif - - -/** - * TCP_SND_BUF: TCP sender buffer space (bytes). - * To achieve good performance, this should be at least 2 * TCP_MSS. - */ -#if !defined TCP_SND_BUF || defined __DOXYGEN__ -#define TCP_SND_BUF (2 * TCP_MSS) -#endif - -/** - * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least - * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. - */ -#if !defined TCP_SND_QUEUELEN || defined __DOXYGEN__ -#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) -#endif - -/** - * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than - * TCP_SND_BUF. It is the amount of space which must be available in the - * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). - */ -#if !defined TCP_SNDLOWAT || defined __DOXYGEN__ -#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) -#endif - -/** - * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less - * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below - * this number, select returns writable (combined with TCP_SNDLOWAT). - */ -#if !defined TCP_SNDQUEUELOWAT || defined __DOXYGEN__ -#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) -#endif - -/** - * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. - * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. - */ -#if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__ -#define TCP_OOSEQ_MAX_BYTES 0 -#endif - -/** - * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. - * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. - */ -#if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__ -#define TCP_OOSEQ_MAX_PBUFS 0 -#endif - -/** - * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. - */ -#if !defined TCP_LISTEN_BACKLOG || defined __DOXYGEN__ -#define TCP_LISTEN_BACKLOG 0 -#endif - -/** - * The maximum allowed backlog for TCP listen netconns. - * This backlog is used unless another is explicitly specified. - * 0xff is the maximum (u8_t). - */ -#if !defined TCP_DEFAULT_LISTEN_BACKLOG || defined __DOXYGEN__ -#define TCP_DEFAULT_LISTEN_BACKLOG 0xff -#endif - -/** - * TCP_OVERSIZE: The maximum number of bytes that tcp_write may - * allocate ahead of time in an attempt to create shorter pbuf chains - * for transmission. The meaningful range is 0 to TCP_MSS. Some - * suggested values are: - * - * 0: Disable oversized allocation. Each tcp_write() allocates a new - pbuf (old behaviour). - * 1: Allocate size-aligned pbufs with minimal excess. Use this if your - * scatter-gather DMA requires aligned fragments. - * 128: Limit the pbuf/memory overhead to 20%. - * TCP_MSS: Try to create unfragmented TCP packets. - * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. - */ -#if !defined TCP_OVERSIZE || defined __DOXYGEN__ -#define TCP_OVERSIZE TCP_MSS -#endif - -/** - * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. - * The timestamp option is currently only used to help remote hosts, it is not - * really used locally. Therefore, it is only enabled when a TS option is - * received in the initial SYN packet from a remote host. - */ -#if !defined LWIP_TCP_TIMESTAMPS || defined __DOXYGEN__ -#define LWIP_TCP_TIMESTAMPS 0 -#endif - -/** - * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an - * explicit window update - */ -#if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__ -#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) -#endif - -/** - * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. - * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all - * events (accept, sent, etc) that happen in the system. - * LWIP_CALLBACK_API==1: The PCB callback function is called directly - * for the event. This is the default. - */ -#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) || defined __DOXYGEN__ -#define LWIP_EVENT_API 0 -#define LWIP_CALLBACK_API 1 -#else -#ifndef LWIP_EVENT_API -#define LWIP_EVENT_API 0 -#endif -#ifndef LWIP_CALLBACK_API -#define LWIP_CALLBACK_API 0 -#endif -#endif - -/** - * LWIP_WND_SCALE and TCP_RCV_SCALE: - * Set LWIP_WND_SCALE to 1 to enable window scaling. - * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the - * range of [0..14]). - * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large - * send window while having a small receive window only. - */ -#if !defined LWIP_WND_SCALE || defined __DOXYGEN__ -#define LWIP_WND_SCALE 0 -#define TCP_RCV_SCALE 0 -#endif -/** - * @} - */ - -/* - ---------------------------------- - ---------- Pbuf options ---------- - ---------------------------------- -*/ -/** - * @defgroup lwip_opts_pbuf PBUF - * @ingroup lwip_opts - * @{ - */ -/** - * PBUF_LINK_HLEN: the number of bytes that should be allocated for a - * link level header. The default is 14, the standard value for - * Ethernet. - */ -#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ -#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ -#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) -#else /* LWIP_HOOK_VLAN_SET */ -#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) -#endif /* LWIP_HOOK_VLAN_SET */ -#endif - -/** - * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated - * for an additional encapsulation header before ethernet headers (e.g. 802.11) - */ -#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__ -#define PBUF_LINK_ENCAPSULATION_HLEN 0u -#endif - -/** - * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is - * designed to accommodate single full size TCP frame in one pbuf, including - * TCP_MSS, IP header, and link header. - */ -#if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__ -#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) -#endif -/** - * @} - */ - -/* - ------------------------------------------------ - ---------- Network Interfaces options ---------- - ------------------------------------------------ -*/ -/** - * @defgroup lwip_opts_netif NETIF - * @ingroup lwip_opts - * @{ - */ -/** - * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname - * field. - */ -#if !defined LWIP_NETIF_HOSTNAME || defined __DOXYGEN__ -#define LWIP_NETIF_HOSTNAME 0 -#endif - -/** - * LWIP_NETIF_API==1: Support netif api (in netifapi.c) - */ -#if !defined LWIP_NETIF_API || defined __DOXYGEN__ -#define LWIP_NETIF_API 0 -#endif - -/** - * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface - * changes its up/down status (i.e., due to DHCP IP acquisition) - */ -#if !defined LWIP_NETIF_STATUS_CALLBACK || defined __DOXYGEN__ -#define LWIP_NETIF_STATUS_CALLBACK 0 -#endif - -/** - * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface - * whenever the link changes (i.e., link down) - */ -#if !defined LWIP_NETIF_LINK_CALLBACK || defined __DOXYGEN__ -#define LWIP_NETIF_LINK_CALLBACK 0 -#endif - -/** - * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called - * when a netif has been removed - */ -#if !defined LWIP_NETIF_REMOVE_CALLBACK || defined __DOXYGEN__ -#define LWIP_NETIF_REMOVE_CALLBACK 0 -#endif - -/** - * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table - * indices) in struct netif. TCP and UDP can make use of this to prevent - * scanning the ARP table for every sent packet. While this is faster for big - * ARP tables or many concurrent connections, it might be counterproductive - * if you have a tiny ARP table or if there never are concurrent connections. - */ -#if !defined LWIP_NETIF_HWADDRHINT || defined __DOXYGEN__ -#define LWIP_NETIF_HWADDRHINT 0 -#endif - -/** - * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data - * to be sent into one single pbuf. This is for compatibility with DMA-enabled - * MACs that do not support scatter-gather. - * Beware that this might involve CPU-memcpy before transmitting that would not - * be needed without this flag! Use this only if you need to! - * - * @todo: TCP and IP-frag do not work with this, yet: - */ -#if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__ -#define LWIP_NETIF_TX_SINGLE_PBUF 0 -#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ - -/** - * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store - * data in client_data member array of struct netif. - */ -#if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__ -#define LWIP_NUM_NETIF_CLIENT_DATA 0 -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- LOOPIF options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_loop Loopback interface - * @ingroup lwip_opts_netif - * @{ - */ -/** - * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1). - * This is only needed when no real netifs are available. If at least one other - * netif is available, loopback traffic uses this netif. - */ -#if !defined LWIP_HAVE_LOOPIF || defined __DOXYGEN__ -#define LWIP_HAVE_LOOPIF LWIP_NETIF_LOOPBACK -#endif - -/** - * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1). - */ -#if !defined LWIP_LOOPIF_MULTICAST || defined __DOXYGEN__ -#define LWIP_LOOPIF_MULTICAST 0 -#endif - -/** - * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP - * address equal to the netif IP address, looping them back up the stack. - */ -#if !defined LWIP_NETIF_LOOPBACK || defined __DOXYGEN__ -#define LWIP_NETIF_LOOPBACK 0 -#endif - -/** - * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback - * sending for each netif (0 = disabled) - */ -#if !defined LWIP_LOOPBACK_MAX_PBUFS || defined __DOXYGEN__ -#define LWIP_LOOPBACK_MAX_PBUFS 0 -#endif - -/** - * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in - * the system, as netifs must change how they behave depending on this setting - * for the LWIP_NETIF_LOOPBACK option to work. - * Setting this is needed to avoid reentering non-reentrant functions like - * tcp_input(). - * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a - * multithreaded environment like tcpip.c. In this case, netif->input() - * is called directly. - * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. - * The packets are put on a list and netif_poll() must be called in - * the main application loop. - */ -#if !defined LWIP_NETIF_LOOPBACK_MULTITHREADING || defined __DOXYGEN__ -#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- Thread options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_thread Threading - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. - */ -#if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__ -#define TCPIP_THREAD_NAME "tcpip_thread" -#endif - -/** - * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. - * The stack size value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined TCPIP_THREAD_STACKSIZE || defined __DOXYGEN__ -#define TCPIP_THREAD_STACKSIZE 0 -#endif - -/** - * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. - * The priority value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ -#define TCPIP_THREAD_PRIO 1 -#endif - -/** - * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages - * The queue size value itself is platform-dependent, but is passed to - * sys_mbox_new() when tcpip_init is called. - */ -#if !defined TCPIP_MBOX_SIZE || defined __DOXYGEN__ -#define TCPIP_MBOX_SIZE 0 -#endif - -/** - * Define this to something that triggers a watchdog. This is called from - * tcpip_thread after processing a message. - */ -#if !defined LWIP_TCPIP_THREAD_ALIVE || defined __DOXYGEN__ -#define LWIP_TCPIP_THREAD_ALIVE() -#endif - -/** - * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. - */ -#if !defined SLIPIF_THREAD_NAME || defined __DOXYGEN__ -#define SLIPIF_THREAD_NAME "slipif_loop" -#endif - -/** - * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. - * The stack size value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined SLIPIF_THREAD_STACKSIZE || defined __DOXYGEN__ -#define SLIPIF_THREAD_STACKSIZE 0 -#endif - -/** - * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. - * The priority value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined SLIPIF_THREAD_PRIO || defined __DOXYGEN__ -#define SLIPIF_THREAD_PRIO 1 -#endif - -/** - * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. - */ -#if !defined DEFAULT_THREAD_NAME || defined __DOXYGEN__ -#define DEFAULT_THREAD_NAME "lwIP" -#endif - -/** - * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. - * The stack size value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined DEFAULT_THREAD_STACKSIZE || defined __DOXYGEN__ -#define DEFAULT_THREAD_STACKSIZE 0 -#endif - -/** - * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. - * The priority value itself is platform-dependent, but is passed to - * sys_thread_new() when the thread is created. - */ -#if !defined DEFAULT_THREAD_PRIO || defined __DOXYGEN__ -#define DEFAULT_THREAD_PRIO 1 -#endif - -/** - * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a - * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed - * to sys_mbox_new() when the recvmbox is created. - */ -#if !defined DEFAULT_RAW_RECVMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_RAW_RECVMBOX_SIZE 0 -#endif - -/** - * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a - * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed - * to sys_mbox_new() when the recvmbox is created. - */ -#if !defined DEFAULT_UDP_RECVMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_UDP_RECVMBOX_SIZE 0 -#endif - -/** - * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a - * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed - * to sys_mbox_new() when the recvmbox is created. - */ -#if !defined DEFAULT_TCP_RECVMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_TCP_RECVMBOX_SIZE 0 -#endif - -/** - * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. - * The queue size value itself is platform-dependent, but is passed to - * sys_mbox_new() when the acceptmbox is created. - */ -#if !defined DEFAULT_ACCEPTMBOX_SIZE || defined __DOXYGEN__ -#define DEFAULT_ACCEPTMBOX_SIZE 0 -#endif -/** - * @} - */ - -/* - ---------------------------------------------- - ---------- Sequential layer options ---------- - ---------------------------------------------- -*/ -/** - * @defgroup lwip_opts_netconn Netconn - * @ingroup lwip_opts_threadsafe_apis - * @{ - */ -/** - * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) - */ -#if !defined LWIP_NETCONN || defined __DOXYGEN__ -#define LWIP_NETCONN 1 -#endif - -/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create - * timers running in tcpip_thread from another thread. - */ -#if !defined LWIP_TCPIP_TIMEOUT || defined __DOXYGEN__ -#define LWIP_TCPIP_TIMEOUT 0 -#endif - -/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per - * thread calling socket/netconn functions instead of allocating one - * semaphore per netconn (and per select etc.) - * ATTENTION: a thread-local semaphore for API calls is needed: - * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* - * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore - * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore - * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). - * Ports may call these for threads created with sys_thread_new(). - */ -#if !defined LWIP_NETCONN_SEM_PER_THREAD || defined __DOXYGEN__ -#define LWIP_NETCONN_SEM_PER_THREAD 0 -#endif - -/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, - * writing from a 2nd thread and closing from a 3rd thread at the same time. - * ATTENTION: This is currently really alpha! Some requirements: - * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from - * multiple threads at once - * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox - * and prevent a task pending on this during/after deletion - */ -#if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__ -#define LWIP_NETCONN_FULLDUPLEX 0 -#endif -/** - * @} - */ - -/* - ------------------------------------ - ---------- Socket options ---------- - ------------------------------------ -*/ -/** - * @defgroup lwip_opts_socket Sockets - * @ingroup lwip_opts_threadsafe_apis - * @{ - */ -/** - * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) - */ -#if !defined LWIP_SOCKET || defined __DOXYGEN__ -#define LWIP_SOCKET 1 -#endif - -/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete - * successfully, as required by POSIX. Default is POSIX-compliant. - */ -#if !defined LWIP_SOCKET_SET_ERRNO || defined __DOXYGEN__ -#define LWIP_SOCKET_SET_ERRNO 1 -#endif - -/** - * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines. - * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created. - * While this helps code completion, it might conflict with existing libraries. - * (only used if you use sockets.c) - */ -#if !defined LWIP_COMPAT_SOCKETS || defined __DOXYGEN__ -#define LWIP_COMPAT_SOCKETS 1 -#endif - -/** - * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. - * Disable this option if you use a POSIX operating system that uses the same - * names (read, write & close). (only used if you use sockets.c) - */ -#if !defined LWIP_POSIX_SOCKETS_IO_NAMES || defined __DOXYGEN__ -#define LWIP_POSIX_SOCKETS_IO_NAMES 1 -#endif - -/** - * LWIP_SOCKET_OFFSET==n: Increases the file descriptor number created by LwIP with n. - * This can be useful when there are multiple APIs which create file descriptors. - * When they all start with a different offset and you won't make them overlap you can - * re implement read/write/close/ioctl/fnctl to send the requested action to the right - * library (sharing select will need more work though). - */ -#if !defined LWIP_SOCKET_OFFSET || defined __DOXYGEN__ -#define LWIP_SOCKET_OFFSET 0 -#endif - -/** - * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT - * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set - * in seconds. (does not require sockets.c, and will affect tcp.c) - */ -#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__ -#define LWIP_TCP_KEEPALIVE 0 -#endif - -/** - * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and - * SO_SNDTIMEO processing. - */ -#if !defined LWIP_SO_SNDTIMEO || defined __DOXYGEN__ -#define LWIP_SO_SNDTIMEO 0 -#endif - -/** - * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and - * SO_RCVTIMEO processing. - */ -#if !defined LWIP_SO_RCVTIMEO || defined __DOXYGEN__ -#define LWIP_SO_RCVTIMEO 0 -#endif - -/** - * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int - * (milliseconds, much like winsock does) instead of a struct timeval (default). - */ -#if !defined LWIP_SO_SNDRCVTIMEO_NONSTANDARD || defined __DOXYGEN__ -#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 -#endif - -/** - * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. - */ -#if !defined LWIP_SO_RCVBUF || defined __DOXYGEN__ -#define LWIP_SO_RCVBUF 0 -#endif - -/** - * LWIP_SO_LINGER==1: Enable SO_LINGER processing. - */ -#if !defined LWIP_SO_LINGER || defined __DOXYGEN__ -#define LWIP_SO_LINGER 0 -#endif - -/** - * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. - */ -#if !defined RECV_BUFSIZE_DEFAULT || defined __DOXYGEN__ -#define RECV_BUFSIZE_DEFAULT INT_MAX -#endif - -/** - * By default, TCP socket/netconn close waits 20 seconds max to send the FIN - */ -#if !defined LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT || defined __DOXYGEN__ -#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 20000 -#endif - -/** - * SO_REUSE==1: Enable SO_REUSEADDR option. - */ -#if !defined SO_REUSE || defined __DOXYGEN__ -#define SO_REUSE 0 -#endif - -/** - * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets - * to all local matches if SO_REUSEADDR is turned on. - * WARNING: Adds a memcpy for every packet if passing to more than one pcb! - */ -#if !defined SO_REUSE_RXTOALL || defined __DOXYGEN__ -#define SO_REUSE_RXTOALL 0 -#endif - -/** - * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of - * pending data in the network buffer. This is the way windows does it. It's - * the default for lwIP since it is smaller. - * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next - * pending datagram in bytes. This is the way linux does it. This code is only - * here for compatibility. - */ -#if !defined LWIP_FIONREAD_LINUXMODE || defined __DOXYGEN__ -#define LWIP_FIONREAD_LINUXMODE 0 -#endif -/** - * @} - */ - -/* - ---------------------------------------- - ---------- Statistics options ---------- - ---------------------------------------- -*/ -/** - * @defgroup lwip_opts_stats Statistics - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_STATS==1: Enable statistics collection in lwip_stats. - */ -#if !defined LWIP_STATS || defined __DOXYGEN__ -#define LWIP_STATS 1 -#endif - -#if LWIP_STATS - -/** - * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. - */ -#if !defined LWIP_STATS_DISPLAY || defined __DOXYGEN__ -#define LWIP_STATS_DISPLAY 0 -#endif - -/** - * LINK_STATS==1: Enable link stats. - */ -#if !defined LINK_STATS || defined __DOXYGEN__ -#define LINK_STATS 1 -#endif - -/** - * ETHARP_STATS==1: Enable etharp stats. - */ -#if !defined ETHARP_STATS || defined __DOXYGEN__ -#define ETHARP_STATS (LWIP_ARP) -#endif - -/** - * IP_STATS==1: Enable IP stats. - */ -#if !defined IP_STATS || defined __DOXYGEN__ -#define IP_STATS 1 -#endif - -/** - * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is - * on if using either frag or reass. - */ -#if !defined IPFRAG_STATS || defined __DOXYGEN__ -#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) -#endif - -/** - * ICMP_STATS==1: Enable ICMP stats. - */ -#if !defined ICMP_STATS || defined __DOXYGEN__ -#define ICMP_STATS 1 -#endif - -/** - * IGMP_STATS==1: Enable IGMP stats. - */ -#if !defined IGMP_STATS || defined __DOXYGEN__ -#define IGMP_STATS (LWIP_IGMP) -#endif - -/** - * UDP_STATS==1: Enable UDP stats. Default is on if - * UDP enabled, otherwise off. - */ -#if !defined UDP_STATS || defined __DOXYGEN__ -#define UDP_STATS (LWIP_UDP) -#endif - -/** - * TCP_STATS==1: Enable TCP stats. Default is on if TCP - * enabled, otherwise off. - */ -#if !defined TCP_STATS || defined __DOXYGEN__ -#define TCP_STATS (LWIP_TCP) -#endif - -/** - * MEM_STATS==1: Enable mem.c stats. - */ -#if !defined MEM_STATS || defined __DOXYGEN__ -#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) -#endif - -/** - * MEMP_STATS==1: Enable memp.c pool stats. - */ -#if !defined MEMP_STATS || defined __DOXYGEN__ -#define MEMP_STATS (MEMP_MEM_MALLOC == 0) -#endif - -/** - * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). - */ -#if !defined SYS_STATS || defined __DOXYGEN__ -#define SYS_STATS (NO_SYS == 0) -#endif - -/** - * IP6_STATS==1: Enable IPv6 stats. - */ -#if !defined IP6_STATS || defined __DOXYGEN__ -#define IP6_STATS (LWIP_IPV6) -#endif - -/** - * ICMP6_STATS==1: Enable ICMP for IPv6 stats. - */ -#if !defined ICMP6_STATS || defined __DOXYGEN__ -#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) -#endif - -/** - * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. - */ -#if !defined IP6_FRAG_STATS || defined __DOXYGEN__ -#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) -#endif - -/** - * MLD6_STATS==1: Enable MLD for IPv6 stats. - */ -#if !defined MLD6_STATS || defined __DOXYGEN__ -#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) -#endif - -/** - * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. - */ -#if !defined ND6_STATS || defined __DOXYGEN__ -#define ND6_STATS (LWIP_IPV6) -#endif - -/** - * MIB2_STATS==1: Stats for SNMP MIB2. - */ -#if !defined MIB2_STATS || defined __DOXYGEN__ -#define MIB2_STATS 0 -#endif - -#else - -#define LINK_STATS 0 -#define ETHARP_STATS 0 -#define IP_STATS 0 -#define IPFRAG_STATS 0 -#define ICMP_STATS 0 -#define IGMP_STATS 0 -#define UDP_STATS 0 -#define TCP_STATS 0 -#define MEM_STATS 0 -#define MEMP_STATS 0 -#define SYS_STATS 0 -#define LWIP_STATS_DISPLAY 0 -#define IP6_STATS 0 -#define ICMP6_STATS 0 -#define IP6_FRAG_STATS 0 -#define MLD6_STATS 0 -#define ND6_STATS 0 -#define MIB2_STATS 0 - -#endif /* LWIP_STATS */ -/** - * @} - */ - -/* - -------------------------------------- - ---------- Checksum options ---------- - -------------------------------------- -*/ -/** - * @defgroup lwip_opts_checksum Checksum - * @ingroup lwip_opts_infrastructure - * @{ - */ -/** - * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled - * per netif. - * ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled! - */ -#if !defined LWIP_CHECKSUM_CTRL_PER_NETIF || defined __DOXYGEN__ -#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 -#endif - -/** - * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. - */ -#if !defined CHECKSUM_GEN_IP || defined __DOXYGEN__ -#define CHECKSUM_GEN_IP 1 -#endif - -/** - * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. - */ -#if !defined CHECKSUM_GEN_UDP || defined __DOXYGEN__ -#define CHECKSUM_GEN_UDP 1 -#endif - -/** - * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. - */ -#if !defined CHECKSUM_GEN_TCP || defined __DOXYGEN__ -#define CHECKSUM_GEN_TCP 1 -#endif - -/** - * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. - */ -#if !defined CHECKSUM_GEN_ICMP || defined __DOXYGEN__ -#define CHECKSUM_GEN_ICMP 1 -#endif - -/** - * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. - */ -#if !defined CHECKSUM_GEN_ICMP6 || defined __DOXYGEN__ -#define CHECKSUM_GEN_ICMP6 1 -#endif - -/** - * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. - */ -#if !defined CHECKSUM_CHECK_IP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_IP 1 -#endif - -/** - * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. - */ -#if !defined CHECKSUM_CHECK_UDP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_UDP 1 -#endif - -/** - * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. - */ -#if !defined CHECKSUM_CHECK_TCP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_TCP 1 -#endif - -/** - * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. - */ -#if !defined CHECKSUM_CHECK_ICMP || defined __DOXYGEN__ -#define CHECKSUM_CHECK_ICMP 1 -#endif - -/** - * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets - */ -#if !defined CHECKSUM_CHECK_ICMP6 || defined __DOXYGEN__ -#define CHECKSUM_CHECK_ICMP6 1 -#endif - -/** - * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from - * application buffers to pbufs. - */ -#if !defined LWIP_CHECKSUM_ON_COPY || defined __DOXYGEN__ -#define LWIP_CHECKSUM_ON_COPY 0 -#endif -/** - * @} - */ - -/* - --------------------------------------- - ---------- IPv6 options --------------- - --------------------------------------- -*/ -/** - * @defgroup lwip_opts_ipv6 IPv6 - * @ingroup lwip_opts - * @{ - */ -/** - * LWIP_IPV6==1: Enable IPv6 - */ -#if !defined LWIP_IPV6 || defined __DOXYGEN__ -#define LWIP_IPV6 0 -#endif - -/** - * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. - */ -#if !defined LWIP_IPV6_NUM_ADDRESSES || defined __DOXYGEN__ -#define LWIP_IPV6_NUM_ADDRESSES 3 -#endif - -/** - * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs - */ -#if !defined LWIP_IPV6_FORWARD || defined __DOXYGEN__ -#define LWIP_IPV6_FORWARD 0 -#endif - -/** - * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. - */ -#if !defined LWIP_IPV6_FRAG || defined __DOXYGEN__ -#define LWIP_IPV6_FRAG 0 -#endif - -/** - * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented - */ -#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ -#define LWIP_IPV6_REASS (LWIP_IPV6) -#endif - -/** - * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during - * network startup. - */ -#if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__ -#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 -#endif - -/** - * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. - */ -#if !defined LWIP_IPV6_AUTOCONFIG || defined __DOXYGEN__ -#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) -#endif - -/** - * LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts. - */ -#if !defined LWIP_IPV6_DUP_DETECT_ATTEMPTS || defined __DOXYGEN__ -#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_icmp6 ICMP6 - * @ingroup lwip_opts_ipv6 - * @{ - */ -/** - * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) - */ -#if !defined LWIP_ICMP6 || defined __DOXYGEN__ -#define LWIP_ICMP6 (LWIP_IPV6) -#endif - -/** - * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in - * ICMPv6 error messages. - */ -#if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__ -#define LWIP_ICMP6_DATASIZE 8 -#endif - -/** - * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages - */ -#if !defined LWIP_ICMP6_HL || defined __DOXYGEN__ -#define LWIP_ICMP6_HL 255 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_mld6 Multicast listener discovery - * @ingroup lwip_opts_ipv6 - * @{ - */ -/** - * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. - * If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must - * indiscriminately pass all inbound IPv6 multicast traffic to lwIP. - */ -#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__ -#define LWIP_IPV6_MLD (LWIP_IPV6) -#endif - -/** - * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined. - * There must be enough groups so that each netif can join the solicited-node - * multicast group for each of its local addresses, plus one for MDNS if - * applicable, plus any number of groups to be joined on UDP sockets. - */ -#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__ -#define MEMP_NUM_MLD6_GROUP 4 -#endif -/** - * @} - */ - -/** - * @defgroup lwip_opts_nd6 Neighbor discovery - * @ingroup lwip_opts_ipv6 - * @{ - */ -/** - * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address - * is being resolved. - */ -#if !defined LWIP_ND6_QUEUEING || defined __DOXYGEN__ -#define LWIP_ND6_QUEUEING (LWIP_IPV6) -#endif - -/** - * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. - */ -#if !defined MEMP_NUM_ND6_QUEUE || defined __DOXYGEN__ -#define MEMP_NUM_ND6_QUEUE 20 -#endif - -/** - * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache - */ -#if !defined LWIP_ND6_NUM_NEIGHBORS || defined __DOXYGEN__ -#define LWIP_ND6_NUM_NEIGHBORS 10 -#endif - -/** - * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache - */ -#if !defined LWIP_ND6_NUM_DESTINATIONS || defined __DOXYGEN__ -#define LWIP_ND6_NUM_DESTINATIONS 10 -#endif - -/** - * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache - */ -#if !defined LWIP_ND6_NUM_PREFIXES || defined __DOXYGEN__ -#define LWIP_ND6_NUM_PREFIXES 5 -#endif - -/** - * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache - */ -#if !defined LWIP_ND6_NUM_ROUTERS || defined __DOXYGEN__ -#define LWIP_ND6_NUM_ROUTERS 3 -#endif - -/** - * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send - * (neighbor solicit and router solicit) - */ -#if !defined LWIP_ND6_MAX_MULTICAST_SOLICIT || defined __DOXYGEN__ -#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 -#endif - -/** - * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages - * to send during neighbor reachability detection. - */ -#if !defined LWIP_ND6_MAX_UNICAST_SOLICIT || defined __DOXYGEN__ -#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 -#endif - -/** - * Unused: See ND RFC (time in milliseconds). - */ -#if !defined LWIP_ND6_MAX_ANYCAST_DELAY_TIME || defined __DOXYGEN__ -#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 -#endif - -/** - * Unused: See ND RFC - */ -#if !defined LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT || defined __DOXYGEN__ -#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 -#endif - -/** - * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). - * May be updated by router advertisement messages. - */ -#if !defined LWIP_ND6_REACHABLE_TIME || defined __DOXYGEN__ -#define LWIP_ND6_REACHABLE_TIME 30000 -#endif - -/** - * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages - */ -#if !defined LWIP_ND6_RETRANS_TIMER || defined __DOXYGEN__ -#define LWIP_ND6_RETRANS_TIMER 1000 -#endif - -/** - * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation - * message is sent, during neighbor reachability detection. - */ -#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__ -#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 -#endif - -/** - * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update - * Reachable time and retransmission timers, and netif MTU. - */ -#if !defined LWIP_ND6_ALLOW_RA_UPDATES || defined __DOXYGEN__ -#define LWIP_ND6_ALLOW_RA_UPDATES 1 -#endif - -/** - * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery - * with reachability hints for connected destinations. This helps avoid sending - * unicast neighbor solicitation messages. - */ -#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ -#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 -#endif - -/** - * LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive - * DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS - * servers to the DNS module. - */ -#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__ -#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 -#endif -/** - * @} - */ - -/** - * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. - */ -#if !defined LWIP_IPV6_DHCP6 || defined __DOXYGEN__ -#define LWIP_IPV6_DHCP6 0 -#endif - -/* - --------------------------------------- - ---------- Hook options --------------- - --------------------------------------- -*/ - -/** - * @defgroup lwip_opts_hooks Hooks - * @ingroup lwip_opts_infrastructure - * Hooks are undefined by default, define them to a function if you need them. - * @{ - */ - -/** - * LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks. - * Declare your hook function prototypes in there, you may also #include all headers - * providing data types that are need in this file. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h" -#endif - -/** - * LWIP_HOOK_TCP_ISN: - * Hook for generation of the Initial Sequence Number (ISN) for a new TCP - * connection. The default lwIP ISN generation algorithm is very basic and may - * allow for TCP spoofing attacks. This hook provides the means to implement - * the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), - * or any other desired algorithm as a replacement. - * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for - * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n - * Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port); - * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n - * Arguments: - * - local_ip: pointer to the local IP address of the connection - * - local_port: local port number of the connection (host-byte order) - * - remote_ip: pointer to the remote IP address of the connection - * - remote_port: remote port number of the connection (host-byte order)\n - * Return value: - * - the 32-bit Initial Sequence Number to use for the new TCP connection. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port) -#endif - -/** - * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): - * - called from ip_input() (IPv4) - * - pbuf: received struct pbuf passed to ip_input() - * - input_netif: struct netif on which the packet has been received - * Return values: - * - 0: Hook has not consumed the packet, packet is processed as normal - * - != 0: Hook has consumed the packet. - * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook - * (i.e. free it when done). - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) -#endif - -/** - * LWIP_HOOK_IP4_ROUTE(dest): - * - called from ip_route() (IPv4) - * - dest: destination IPv4 address - * Returns the destination netif or NULL if no destination netif is found. In - * that case, ip_route() continues as normal. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP4_ROUTE() -#endif - -/** - * LWIP_HOOK_IP4_ROUTE_SRC(dest, src): - * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL) - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP4_ROUTE_SRC(dest, src) -#endif - -/** - * LWIP_HOOK_ETHARP_GET_GW(netif, dest): - * - called from etharp_output() (IPv4) - * - netif: the netif used for sending - * - dest: the destination IPv4 address - * Returns the IPv4 address of the gateway to handle the specified destination - * IPv4 address. If NULL is returned, the netif's default gateway is used. - * The returned address MUST be directly reachable on the specified netif! - * This function is meant to implement advanced IPv4 routing together with - * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is - * not part of lwIP but can e.g. be hidden in the netif's state argument. -*/ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_ETHARP_GET_GW(netif, dest) -#endif - -/** - * LWIP_HOOK_IP6_INPUT(pbuf, input_netif): - * - called from ip6_input() (IPv6) - * - pbuf: received struct pbuf passed to ip6_input() - * - input_netif: struct netif on which the packet has been received - * Return values: - * - 0: Hook has not consumed the packet, packet is processed as normal - * - != 0: Hook has consumed the packet. - * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook - * (i.e. free it when done). - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP6_INPUT(pbuf, input_netif) -#endif - -/** - * LWIP_HOOK_IP6_ROUTE(src, dest): - * - called from ip6_route() (IPv6) - * - src: sourc IPv6 address - * - dest: destination IPv6 address - * Returns the destination netif or NULL if no destination netif is found. In - * that case, ip6_route() continues as normal. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_IP6_ROUTE(src, dest) -#endif - -/** - * LWIP_HOOK_ND6_GET_GW(netif, dest): - * - called from nd6_get_next_hop_entry() (IPv6) - * - netif: the netif used for sending - * - dest: the destination IPv6 address - * Returns the IPv6 address of the next hop to handle the specified destination - * IPv6 address. If NULL is returned, a NDP-discovered router is used instead. - * The returned address MUST be directly reachable on the specified netif! - * This function is meant to implement advanced IPv6 routing together with - * LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is - * not part of lwIP but can e.g. be hidden in the netif's state argument. -*/ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_ND6_GET_GW(netif, dest) -#endif - -/** - * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): - * - called from ethernet_input() if VLAN support is enabled - * - netif: struct netif on which the packet has been received - * - eth_hdr: struct eth_hdr of the packet - * - vlan_hdr: struct eth_vlan_hdr of the packet - * Return values: - * - 0: Packet must be dropped. - * - != 0: Packet must be accepted. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr) -#endif - -/** - * LWIP_HOOK_VLAN_SET: - * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data - * on per-netif basis to implement this callback, see @ref netif_cd. - * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n - * Signature: s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n - * Arguments: - * - netif: struct netif that the packet will be sent through - * - p: struct pbuf packet to be sent - * - src: source eth address - * - dst: destination eth address - * - eth_type: ethernet type to packet to be sent\n - * - * - * Return values: - * - <0: Packet shall not contain VLAN header. - * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type) -#endif - -/** - * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): - * - called from memp_free() when a memp pool was empty and an item is now available - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type) -#endif - -/** - * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): - * Called from ethernet_input() when an unknown eth type is encountered. - * Return ERR_OK if packet is accepted, any error code otherwise. - * Payload points to ethernet header! - */ -#ifdef __DOXYGEN__ -#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) -#endif -/** - * @} - */ - -/* - --------------------------------------- - ---------- Debugging options ---------- - --------------------------------------- -*/ -/** - * @defgroup lwip_opts_debugmsg Debug messages - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is - * compared against this value. If it is smaller, then debugging - * messages are written. - * @see debugging_levels - */ -#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ -#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL -#endif - -/** - * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable - * debug messages of certain types. - * @see debugging_levels - */ -#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__ -#define LWIP_DBG_TYPES_ON LWIP_DBG_ON -#endif - -/** - * ETHARP_DEBUG: Enable debugging in etharp.c. - */ -#if !defined ETHARP_DEBUG || defined __DOXYGEN__ -#define ETHARP_DEBUG LWIP_DBG_OFF -#endif - -/** - * NETIF_DEBUG: Enable debugging in netif.c. - */ -#if !defined NETIF_DEBUG || defined __DOXYGEN__ -#define NETIF_DEBUG LWIP_DBG_OFF -#endif - -/** - * PBUF_DEBUG: Enable debugging in pbuf.c. - */ -#if !defined PBUF_DEBUG || defined __DOXYGEN__ -#define PBUF_DEBUG LWIP_DBG_OFF -#endif - -/** - * API_LIB_DEBUG: Enable debugging in api_lib.c. - */ -#if !defined API_LIB_DEBUG || defined __DOXYGEN__ -#define API_LIB_DEBUG LWIP_DBG_OFF -#endif - -/** - * API_MSG_DEBUG: Enable debugging in api_msg.c. - */ -#if !defined API_MSG_DEBUG || defined __DOXYGEN__ -#define API_MSG_DEBUG LWIP_DBG_OFF -#endif - -/** - * SOCKETS_DEBUG: Enable debugging in sockets.c. - */ -#if !defined SOCKETS_DEBUG || defined __DOXYGEN__ -#define SOCKETS_DEBUG LWIP_DBG_OFF -#endif - -/** - * ICMP_DEBUG: Enable debugging in icmp.c. - */ -#if !defined ICMP_DEBUG || defined __DOXYGEN__ -#define ICMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * IGMP_DEBUG: Enable debugging in igmp.c. - */ -#if !defined IGMP_DEBUG || defined __DOXYGEN__ -#define IGMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * INET_DEBUG: Enable debugging in inet.c. - */ -#if !defined INET_DEBUG || defined __DOXYGEN__ -#define INET_DEBUG LWIP_DBG_OFF -#endif - -/** - * IP_DEBUG: Enable debugging for IP. - */ -#if !defined IP_DEBUG || defined __DOXYGEN__ -#define IP_DEBUG LWIP_DBG_OFF -#endif - -/** - * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. - */ -#if !defined IP_REASS_DEBUG || defined __DOXYGEN__ -#define IP_REASS_DEBUG LWIP_DBG_OFF -#endif - -/** - * RAW_DEBUG: Enable debugging in raw.c. - */ -#if !defined RAW_DEBUG || defined __DOXYGEN__ -#define RAW_DEBUG LWIP_DBG_OFF -#endif - -/** - * MEM_DEBUG: Enable debugging in mem.c. - */ -#if !defined MEM_DEBUG || defined __DOXYGEN__ -#define MEM_DEBUG LWIP_DBG_OFF -#endif - -/** - * MEMP_DEBUG: Enable debugging in memp.c. - */ -#if !defined MEMP_DEBUG || defined __DOXYGEN__ -#define MEMP_DEBUG LWIP_DBG_OFF -#endif - -/** - * SYS_DEBUG: Enable debugging in sys.c. - */ -#if !defined SYS_DEBUG || defined __DOXYGEN__ -#define SYS_DEBUG LWIP_DBG_OFF -#endif - -/** - * TIMERS_DEBUG: Enable debugging in timers.c. - */ -#if !defined TIMERS_DEBUG || defined __DOXYGEN__ -#define TIMERS_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_DEBUG: Enable debugging for TCP. - */ -#if !defined TCP_DEBUG || defined __DOXYGEN__ -#define TCP_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. - */ -#if !defined TCP_INPUT_DEBUG || defined __DOXYGEN__ -#define TCP_INPUT_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. - */ -#if !defined TCP_FR_DEBUG || defined __DOXYGEN__ -#define TCP_FR_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit - * timeout. - */ -#if !defined TCP_RTO_DEBUG || defined __DOXYGEN__ -#define TCP_RTO_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. - */ -#if !defined TCP_CWND_DEBUG || defined __DOXYGEN__ -#define TCP_CWND_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. - */ -#if !defined TCP_WND_DEBUG || defined __DOXYGEN__ -#define TCP_WND_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. - */ -#if !defined TCP_OUTPUT_DEBUG || defined __DOXYGEN__ -#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. - */ -#if !defined TCP_RST_DEBUG || defined __DOXYGEN__ -#define TCP_RST_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. - */ -#if !defined TCP_QLEN_DEBUG || defined __DOXYGEN__ -#define TCP_QLEN_DEBUG LWIP_DBG_OFF -#endif - -/** - * UDP_DEBUG: Enable debugging in UDP. - */ -#if !defined UDP_DEBUG || defined __DOXYGEN__ -#define UDP_DEBUG LWIP_DBG_OFF -#endif - -/** - * TCPIP_DEBUG: Enable debugging in tcpip.c. - */ -#if !defined TCPIP_DEBUG || defined __DOXYGEN__ -#define TCPIP_DEBUG LWIP_DBG_OFF -#endif - -/** - * SLIP_DEBUG: Enable debugging in slipif.c. - */ -#if !defined SLIP_DEBUG || defined __DOXYGEN__ -#define SLIP_DEBUG LWIP_DBG_OFF -#endif - -/** - * DHCP_DEBUG: Enable debugging in dhcp.c. - */ -#if !defined DHCP_DEBUG || defined __DOXYGEN__ -#define DHCP_DEBUG LWIP_DBG_OFF -#endif - -/** - * AUTOIP_DEBUG: Enable debugging in autoip.c. - */ -#if !defined AUTOIP_DEBUG || defined __DOXYGEN__ -#define AUTOIP_DEBUG LWIP_DBG_OFF -#endif - -/** - * DNS_DEBUG: Enable debugging for DNS. - */ -#if !defined DNS_DEBUG || defined __DOXYGEN__ -#define DNS_DEBUG LWIP_DBG_OFF -#endif - -/** - * IP6_DEBUG: Enable debugging for IPv6. - */ -#if !defined IP6_DEBUG || defined __DOXYGEN__ -#define IP6_DEBUG LWIP_DBG_OFF -#endif -/** - * @} - */ - -/* - -------------------------------------------------- - ---------- Performance tracking options ---------- - -------------------------------------------------- -*/ -/** - * @defgroup lwip_opts_perf Performance - * @ingroup lwip_opts_debug - * @{ - */ -/** - * LWIP_PERF: Enable performance testing for lwIP - * (if enabled, arch/perf.h is included) - */ -#if !defined LWIP_PERF || defined __DOXYGEN__ -#define LWIP_PERF 0 -#endif -/** - * @} - */ - -#endif /* LWIP_HDR_OPT_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/pbuf.h b/components/net/lwip-2.0.2/src/include/lwip/pbuf.h deleted file mode 100644 index 90610461ea..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/pbuf.h +++ /dev/null @@ -1,263 +0,0 @@ -/** - * @file - * pbuf API - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_PBUF_H -#define LWIP_HDR_PBUF_H - -#include "lwip/opt.h" -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** LWIP_SUPPORT_CUSTOM_PBUF==1: Custom pbufs behave much like their pbuf type - * but they are allocated by external code (initialised by calling - * pbuf_alloced_custom()) and when pbuf_free gives up their last reference, they - * are freed by calling pbuf_custom->custom_free_function(). - * Currently, the pbuf_custom code is only needed for one specific configuration - * of IP_FRAG, unless required by external driver/application code. */ -#ifndef LWIP_SUPPORT_CUSTOM_PBUF -#define LWIP_SUPPORT_CUSTOM_PBUF ((IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG)) -#endif - -/* @todo: We need a mechanism to prevent wasting memory in every pbuf - (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ - -#define PBUF_TRANSPORT_HLEN 20 -#if LWIP_IPV6 -#define PBUF_IP_HLEN 40 -#else -#define PBUF_IP_HLEN 20 -#endif - -/** - * @ingroup pbuf - * Enumeration of pbuf layers - */ -typedef enum { - /** Includes spare room for transport layer header, e.g. UDP header. - * Use this if you intend to pass the pbuf to functions like udp_send(). - */ - PBUF_TRANSPORT, - /** Includes spare room for IP header. - * Use this if you intend to pass the pbuf to functions like raw_send(). - */ - PBUF_IP, - /** Includes spare room for link layer header (ethernet header). - * Use this if you intend to pass the pbuf to functions like ethernet_output(). - * @see PBUF_LINK_HLEN - */ - PBUF_LINK, - /** Includes spare room for additional encapsulation header before ethernet - * headers (e.g. 802.11). - * Use this if you intend to pass the pbuf to functions like netif->linkoutput(). - * @see PBUF_LINK_ENCAPSULATION_HLEN - */ - PBUF_RAW_TX, - /** Use this for input packets in a netif driver when calling netif->input() - * in the most common case - ethernet-layer netif driver. */ - PBUF_RAW -} pbuf_layer; - -/** - * @ingroup pbuf - * Enumeration of pbuf types - */ -typedef enum { - /** pbuf data is stored in RAM, used for TX mostly, struct pbuf and its payload - are allocated in one piece of contiguous memory (so the first payload byte - can be calculated from struct pbuf). - pbuf_alloc() allocates PBUF_RAM pbufs as unchained pbufs (although that might - change in future versions). - This should be used for all OUTGOING packets (TX).*/ - PBUF_RAM, - /** pbuf data is stored in ROM, i.e. struct pbuf and its payload are located in - totally different memory areas. Since it points to ROM, payload does not - have to be copied when queued for transmission. */ - PBUF_ROM, - /** pbuf comes from the pbuf pool. Much like PBUF_ROM but payload might change - so it has to be duplicated when queued before transmitting, depending on - who has a 'ref' to it. */ - PBUF_REF, - /** pbuf payload refers to RAM. This one comes from a pool and should be used - for RX. Payload can be chained (scatter-gather RX) but like PBUF_RAM, struct - pbuf and its payload are allocated in one piece of contiguous memory (so - the first payload byte can be calculated from struct pbuf). - Don't use this for TX, if the pool becomes empty e.g. because of TCP queuing, - you are unable to receive TCP acks! */ - PBUF_POOL -} pbuf_type; - - -/** indicates this packet's data should be immediately passed to the application */ -#define PBUF_FLAG_PUSH 0x01U -/** indicates this is a custom pbuf: pbuf_free calls pbuf_custom->custom_free_function() - when the last reference is released (plus custom PBUF_RAM cannot be trimmed) */ -#define PBUF_FLAG_IS_CUSTOM 0x02U -/** indicates this pbuf is UDP multicast to be looped back */ -#define PBUF_FLAG_MCASTLOOP 0x04U -/** indicates this pbuf was received as link-level broadcast */ -#define PBUF_FLAG_LLBCAST 0x08U -/** indicates this pbuf was received as link-level multicast */ -#define PBUF_FLAG_LLMCAST 0x10U -/** indicates this pbuf includes a TCP FIN flag */ -#define PBUF_FLAG_TCP_FIN 0x20U - -/** Main packet buffer struct */ -struct pbuf { - /** next pbuf in singly linked pbuf chain */ - struct pbuf *next; - - /** pointer to the actual data in the buffer */ - void *payload; - - /** - * total length of this buffer and all next buffers in chain - * belonging to the same packet. - * - * For non-queue packet chains this is the invariant: - * p->tot_len == p->len + (p->next? p->next->tot_len: 0) - */ - u16_t tot_len; - - /** length of this buffer */ - u16_t len; - - /** pbuf_type as u8_t instead of enum to save space */ - u8_t /*pbuf_type*/ type; - - /** misc flags */ - u8_t flags; - - /** - * the reference count always equals the number of pointers - * that refer to this pbuf. This can be pointers from an application, - * the stack itself, or pbuf->next pointers from a chain. - */ - u16_t ref; -}; - - -/** Helper struct for const-correctness only. - * The only meaning of this one is to provide a const payload pointer - * for PBUF_ROM type. - */ -struct pbuf_rom { - /** next pbuf in singly linked pbuf chain */ - struct pbuf *next; - - /** pointer to the actual data in the buffer */ - const void *payload; -}; - -#if LWIP_SUPPORT_CUSTOM_PBUF -/** Prototype for a function to free a custom pbuf */ -typedef void (*pbuf_free_custom_fn)(struct pbuf *p); - -/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ -struct pbuf_custom { - /** The actual pbuf */ - struct pbuf pbuf; - /** This function is called when pbuf_free deallocates this pbuf(_custom) */ - pbuf_free_custom_fn custom_free_function; -}; -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ - -/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */ -#ifndef PBUF_POOL_FREE_OOSEQ -#define PBUF_POOL_FREE_OOSEQ 1 -#endif /* PBUF_POOL_FREE_OOSEQ */ -#if LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ -extern volatile u8_t pbuf_free_ooseq_pending; -void pbuf_free_ooseq(void); -/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ() - at regular intervals from main level to check if ooseq pbufs need to be - freed! */ -#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \ - /* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \ - ooseq queued pbufs now */ \ - pbuf_free_ooseq(); }}while(0) -#else /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ */ - /* Otherwise declare an empty PBUF_CHECK_FREE_OOSEQ */ - #define PBUF_CHECK_FREE_OOSEQ() -#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && NO_SYS && PBUF_POOL_FREE_OOSEQ*/ - -/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ -#define pbuf_init() - -struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); -#if LWIP_SUPPORT_CUSTOM_PBUF -struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, - struct pbuf_custom *p, void *payload_mem, - u16_t payload_mem_len); -#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ -void pbuf_realloc(struct pbuf *p, u16_t size); -u8_t pbuf_header(struct pbuf *p, s16_t header_size); -u8_t pbuf_header_force(struct pbuf *p, s16_t header_size); -void pbuf_ref(struct pbuf *p); -u8_t pbuf_free(struct pbuf *p); -u16_t pbuf_clen(const struct pbuf *p); -void pbuf_cat(struct pbuf *head, struct pbuf *tail); -void pbuf_chain(struct pbuf *head, struct pbuf *tail); -struct pbuf *pbuf_dechain(struct pbuf *p); -err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from); -u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); -err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); -err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset); -struct pbuf *pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset); -struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); -#if LWIP_CHECKSUM_ON_COPY -err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, - u16_t len, u16_t *chksum); -#endif /* LWIP_CHECKSUM_ON_COPY */ -#if LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE -void pbuf_split_64k(struct pbuf *p, struct pbuf **rest); -#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */ - -u8_t pbuf_get_at(const struct pbuf* p, u16_t offset); -int pbuf_try_get_at(const struct pbuf* p, u16_t offset); -void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data); -u16_t pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n); -u16_t pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset); -u16_t pbuf_strstr(const struct pbuf* p, const char* substr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PBUF_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/priv/api_msg.h b/components/net/lwip-2.0.2/src/include/lwip/priv/api_msg.h deleted file mode 100644 index f12b8b7d4f..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/priv/api_msg.h +++ /dev/null @@ -1,216 +0,0 @@ -/** - * @file - * netconn API lwIP internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_API_MSG_H -#define LWIP_HDR_API_MSG_H - -#include "lwip/opt.h" - -#if LWIP_NETCONN || LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -/* Note: Netconn API is always available when sockets are enabled - - * sockets are implemented on top of them */ - -#include "lwip/arch.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "lwip/sys.h" -#include "lwip/igmp.h" -#include "lwip/api.h" -#include "lwip/priv/tcpip_priv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_MPU_COMPATIBLE -#if LWIP_NETCONN_SEM_PER_THREAD -#define API_MSG_M_DEF_SEM(m) *m -#else -#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) -#endif -#else /* LWIP_MPU_COMPATIBLE */ -#define API_MSG_M_DEF_SEM(m) API_MSG_M_DEF(m) -#endif /* LWIP_MPU_COMPATIBLE */ - -/* For the netconn API, these values are use as a bitmask! */ -#define NETCONN_SHUT_RD 1 -#define NETCONN_SHUT_WR 2 -#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) - -/* IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ -/** This struct includes everything that is necessary to execute a function - for a netconn in another thread context (mainly used to process netconns - in the tcpip_thread context to be thread safe). */ -struct api_msg { - /** The netconn which to process - always needed: it includes the semaphore - which is used to block the application thread until the function finished. */ - struct netconn *conn; - /** The return value of the function executed in tcpip_thread. */ - err_t err; - /** Depending on the executed function, one of these union members is used */ - union { - /** used for lwip_netconn_do_send */ - struct netbuf *b; - /** used for lwip_netconn_do_newconn */ - struct { - u8_t proto; - } n; - /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ - struct { - API_MSG_M_DEF_C(ip_addr_t, ipaddr); - u16_t port; - } bc; - /** used for lwip_netconn_do_getaddr */ - struct { - ip_addr_t API_MSG_M_DEF(ipaddr); - u16_t API_MSG_M_DEF(port); - u8_t local; - } ad; - /** used for lwip_netconn_do_write */ - struct { - const void *dataptr; - size_t len; - u8_t apiflags; -#if LWIP_SO_SNDTIMEO - u32_t time_started; -#endif /* LWIP_SO_SNDTIMEO */ - } w; - /** used for lwip_netconn_do_recv */ - struct { - u32_t len; - } r; -#if LWIP_TCP - /** used for lwip_netconn_do_close (/shutdown) */ - struct { - u8_t shut; -#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - u32_t time_started; -#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - u8_t polls_left; -#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - } sd; -#endif /* LWIP_TCP */ -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) - /** used for lwip_netconn_do_join_leave_group */ - struct { - API_MSG_M_DEF_C(ip_addr_t, multiaddr); - API_MSG_M_DEF_C(ip_addr_t, netif_addr); - enum netconn_igmp join_or_leave; - } jl; -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ -#if TCP_LISTEN_BACKLOG - struct { - u8_t backlog; - } lb; -#endif /* TCP_LISTEN_BACKLOG */ - } msg; -#if LWIP_NETCONN_SEM_PER_THREAD - sys_sem_t* op_completed_sem; -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ -}; - -#if LWIP_NETCONN_SEM_PER_THREAD -#define LWIP_API_MSG_SEM(msg) ((msg)->op_completed_sem) -#else /* LWIP_NETCONN_SEM_PER_THREAD */ -#define LWIP_API_MSG_SEM(msg) (&(msg)->conn->op_completed) -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ - - -#if LWIP_DNS -/** As lwip_netconn_do_gethostbyname requires more arguments but doesn't require a netconn, - it has its own struct (to avoid struct api_msg getting bigger than necessary). - lwip_netconn_do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg - (see netconn_gethostbyname). */ -struct dns_api_msg { - /** Hostname to query or dotted IP address string */ -#if LWIP_MPU_COMPATIBLE - char name[DNS_MAX_NAME_LENGTH]; -#else /* LWIP_MPU_COMPATIBLE */ - const char *name; -#endif /* LWIP_MPU_COMPATIBLE */ - /** The resolved address is stored here */ - ip_addr_t API_MSG_M_DEF(addr); -#if LWIP_IPV4 && LWIP_IPV6 - /** Type of resolve call */ - u8_t dns_addrtype; -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - /** This semaphore is posted when the name is resolved, the application thread - should wait on it. */ - sys_sem_t API_MSG_M_DEF_SEM(sem); - /** Errors are given back here */ - err_t API_MSG_M_DEF(err); -}; -#endif /* LWIP_DNS */ - -#if LWIP_TCP -extern u8_t netconn_aborted; -#endif /* LWIP_TCP */ - -void lwip_netconn_do_newconn (void *m); -void lwip_netconn_do_delconn (void *m); -void lwip_netconn_do_bind (void *m); -void lwip_netconn_do_connect (void *m); -void lwip_netconn_do_disconnect (void *m); -void lwip_netconn_do_listen (void *m); -void lwip_netconn_do_send (void *m); -void lwip_netconn_do_recv (void *m); -#if TCP_LISTEN_BACKLOG -void lwip_netconn_do_accepted (void *m); -#endif /* TCP_LISTEN_BACKLOG */ -void lwip_netconn_do_write (void *m); -void lwip_netconn_do_getaddr (void *m); -void lwip_netconn_do_close (void *m); -void lwip_netconn_do_shutdown (void *m); -#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -void lwip_netconn_do_join_leave_group(void *m); -#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ - -#if LWIP_DNS -void lwip_netconn_do_gethostbyname(void *arg); -#endif /* LWIP_DNS */ - -struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); -void netconn_free(struct netconn *conn); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#endif /* LWIP_HDR_API_MSG_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/priv/memp_priv.h b/components/net/lwip-2.0.2/src/include/lwip/priv/memp_priv.h deleted file mode 100644 index f246061dad..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/priv/memp_priv.h +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file - * memory pools lwIP internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_MEMP_PRIV_H -#define LWIP_HDR_MEMP_PRIV_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "lwip/mem.h" - -#if MEMP_OVERFLOW_CHECK -/* if MEMP_OVERFLOW_CHECK is turned on, we reserve some bytes at the beginning - * and at the end of each element, initialize them as 0xcd and check - * them later. */ -/* If MEMP_OVERFLOW_CHECK is >= 2, on every call to memp_malloc or memp_free, - * every single element in each pool is checked! - * This is VERY SLOW but also very helpful. */ -/* MEMP_SANITY_REGION_BEFORE and MEMP_SANITY_REGION_AFTER can be overridden in - * lwipopts.h to change the amount reserved for checking. */ -#ifndef MEMP_SANITY_REGION_BEFORE -#define MEMP_SANITY_REGION_BEFORE 16 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#if MEMP_SANITY_REGION_BEFORE > 0 -#define MEMP_SANITY_REGION_BEFORE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_BEFORE) -#else -#define MEMP_SANITY_REGION_BEFORE_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_BEFORE*/ -#ifndef MEMP_SANITY_REGION_AFTER -#define MEMP_SANITY_REGION_AFTER 16 -#endif /* MEMP_SANITY_REGION_AFTER*/ -#if MEMP_SANITY_REGION_AFTER > 0 -#define MEMP_SANITY_REGION_AFTER_ALIGNED LWIP_MEM_ALIGN_SIZE(MEMP_SANITY_REGION_AFTER) -#else -#define MEMP_SANITY_REGION_AFTER_ALIGNED 0 -#endif /* MEMP_SANITY_REGION_AFTER*/ - -/* MEMP_SIZE: save space for struct memp and for sanity check */ -#define MEMP_SIZE (LWIP_MEM_ALIGN_SIZE(sizeof(struct memp)) + MEMP_SANITY_REGION_BEFORE_ALIGNED) -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x) + MEMP_SANITY_REGION_AFTER_ALIGNED) - -#else /* MEMP_OVERFLOW_CHECK */ - -/* No sanity checks - * We don't need to preserve the struct memp while not allocated, so we - * can save a little space and set MEMP_SIZE to 0. - */ -#define MEMP_SIZE 0 -#define MEMP_ALIGN_SIZE(x) (LWIP_MEM_ALIGN_SIZE(x)) - -#endif /* MEMP_OVERFLOW_CHECK */ - -#if !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK -struct memp { - struct memp *next; -#if MEMP_OVERFLOW_CHECK - const char *file; - int line; -#endif /* MEMP_OVERFLOW_CHECK */ -}; -#endif /* !MEMP_MEM_MALLOC || MEMP_OVERFLOW_CHECK */ - -#if MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS -/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ -typedef enum { - /* Get the first (via: - MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ - MEMP_POOL_HELPER_FIRST = ((u8_t) -#define LWIP_MEMPOOL(name,num,size,desc) -#define LWIP_MALLOC_MEMPOOL_START 1 -#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 -#define LWIP_MALLOC_MEMPOOL_END -#include "lwip/priv/memp_std.h" - ) , - /* Get the last (via: - MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ - MEMP_POOL_HELPER_LAST = ((u8_t) -#define LWIP_MEMPOOL(name,num,size,desc) -#define LWIP_MALLOC_MEMPOOL_START -#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * -#define LWIP_MALLOC_MEMPOOL_END 1 -#include "lwip/priv/memp_std.h" - ) -} memp_pool_helper_t; - -/* The actual start and stop values are here (cast them over) - We use this helper type and these defines so we can avoid using const memp_t values */ -#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) -#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) -#endif /* MEM_USE_POOLS && MEMP_USE_CUSTOM_POOLS */ - -/** Memory pool descriptor */ -struct memp_desc { -#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY - /** Textual description */ - const char *desc; -#endif /* LWIP_DEBUG || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY */ -#if MEMP_STATS - /** Statistics */ - struct stats_mem *stats; -#endif - - /** Element size */ - u16_t size; - -#if !MEMP_MEM_MALLOC - /** Number of elements */ - u16_t num; - - /** Base address */ - u8_t *base; - - /** First free element of each pool. Elements form a linked list. */ - struct memp **tab; -#endif /* MEMP_MEM_MALLOC */ -}; - -#if defined(LWIP_DEBUG) || MEMP_OVERFLOW_CHECK || LWIP_STATS_DISPLAY -#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc), -#else -#define DECLARE_LWIP_MEMPOOL_DESC(desc) -#endif - -#if MEMP_STATS -#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) static struct stats_mem name; -#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) &name, -#else -#define LWIP_MEMPOOL_DECLARE_STATS_INSTANCE(name) -#define LWIP_MEMPOOL_DECLARE_STATS_REFERENCE(name) -#endif - -void memp_init_pool(const struct memp_desc *desc); - -#if MEMP_OVERFLOW_CHECK -void *memp_malloc_pool_fn(const struct memp_desc* desc, const char* file, const int line); -#define memp_malloc_pool(d) memp_malloc_pool_fn((d), __FILE__, __LINE__) -#else -void *memp_malloc_pool(const struct memp_desc *desc); -#endif -void memp_free_pool(const struct memp_desc* desc, void *mem); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_MEMP_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/priv/memp_std.h b/components/net/lwip-2.0.2/src/include/lwip/priv/memp_std.h deleted file mode 100644 index ce9fd50031..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/priv/memp_std.h +++ /dev/null @@ -1,146 +0,0 @@ -/** - * @file - * lwIP internal memory pools (do not use in application code) - * This file is deliberately included multiple times: once with empty - * definition of LWIP_MEMPOOL() to handle all includes and multiple times - * to build up various lists of mem pools. - */ - -/* - * SETUP: Make sure we define everything we will need. - * - * We have create three types of pools: - * 1) MEMPOOL - standard pools - * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c - * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct - * - * If the include'r doesn't require any special treatment of each of the types - * above, then will declare #2 & #3 to be just standard mempools. - */ -#ifndef LWIP_MALLOC_MEMPOOL -/* This treats "malloc pools" just like any other pool. - The pools are a little bigger to provide 'size' as the amount of user data. */ -#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper))), "MALLOC_"#size) -#define LWIP_MALLOC_MEMPOOL_START -#define LWIP_MALLOC_MEMPOOL_END -#endif /* LWIP_MALLOC_MEMPOOL */ - -#ifndef LWIP_PBUF_MEMPOOL -/* This treats "pbuf pools" just like any other pool. - * Allocates buffers for a pbuf struct AND a payload size */ -#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) -#endif /* LWIP_PBUF_MEMPOOL */ - - -/* - * A list of internal pools used by LWIP. - * - * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) - * creates a pool name MEMP_pool_name. description is used in stats.c - */ -#if LWIP_RAW -LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB") -#endif /* LWIP_RAW */ - -#if LWIP_UDP -LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB") -#endif /* LWIP_UDP */ - -#if LWIP_TCP -LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB") -LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") -LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG") -#endif /* LWIP_TCP */ - -#if LWIP_IPV4 && IP_REASSEMBLY -LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA") -#endif /* LWIP_IPV4 && IP_REASSEMBLY */ -#if (IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF) || (LWIP_IPV6 && LWIP_IPV6_FRAG) -LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF") -#endif /* IP_FRAG && !LWIP_NETIF_TX_SINGLE_PBUF || (LWIP_IPV6 && LWIP_IPV6_FRAG) */ - -#if LWIP_NETCONN || LWIP_SOCKET -LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") -LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") -#endif /* LWIP_NETCONN || LWIP_SOCKET */ - -#if NO_SYS==0 -LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") -#if LWIP_MPU_COMPATIBLE -LWIP_MEMPOOL(API_MSG, MEMP_NUM_API_MSG, sizeof(struct api_msg), "API_MSG") -#if LWIP_DNS -LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg), "DNS_API_MSG") -#endif -#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING -LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") -#endif -#if LWIP_NETIF_API -LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") -#endif -#endif /* LWIP_MPU_COMPATIBLE */ -#if !LWIP_TCPIP_CORE_LOCKING_INPUT -LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") -#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ -#endif /* NO_SYS==0 */ - -#if LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING -LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE") -#endif /* LWIP_IPV4 && LWIP_ARP && ARP_QUEUEING */ - -#if LWIP_IGMP -LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP") -#endif /* LWIP_IGMP */ - -#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM -LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT") -#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ - -#if LWIP_DNS && LWIP_SOCKET -LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") -#endif /* LWIP_DNS && LWIP_SOCKET */ -#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC -LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") -#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ - -#if LWIP_IPV6 && LWIP_ND6_QUEUEING -LWIP_MEMPOOL(ND6_QUEUE, MEMP_NUM_ND6_QUEUE, sizeof(struct nd6_q_entry), "ND6_QUEUE") -#endif /* LWIP_IPV6 && LWIP_ND6_QUEUEING */ - -#if LWIP_IPV6 && LWIP_IPV6_REASS -LWIP_MEMPOOL(IP6_REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip6_reassdata), "IP6_REASSDATA") -#endif /* LWIP_IPV6 && LWIP_IPV6_REASS */ - -#if LWIP_IPV6 && LWIP_IPV6_MLD -LWIP_MEMPOOL(MLD6_GROUP, MEMP_NUM_MLD6_GROUP, sizeof(struct mld_group), "MLD6_GROUP") -#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - - -/* - * A list of pools of pbuf's used by LWIP. - * - * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) - * creates a pool name MEMP_pool_name. description is used in stats.c - * This allocates enough space for the pbuf struct and a payload. - * (Example: pbuf_payload_size=0 allocates only size for the struct) - */ -LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM") -LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, PBUF_POOL_BUFSIZE, "PBUF_POOL") - - -/* - * Allow for user-defined pools; this must be explicitly set in lwipopts.h - * since the default is to NOT look for lwippools.h - */ -#if MEMP_USE_CUSTOM_POOLS -#include "lwippools.h" -#endif /* MEMP_USE_CUSTOM_POOLS */ - -/* - * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later - * (#undef is ignored for something that is not defined) - */ -#undef LWIP_MEMPOOL -#undef LWIP_MALLOC_MEMPOOL -#undef LWIP_MALLOC_MEMPOOL_START -#undef LWIP_MALLOC_MEMPOOL_END -#undef LWIP_PBUF_MEMPOOL diff --git a/components/net/lwip-2.0.2/src/include/lwip/priv/nd6_priv.h b/components/net/lwip-2.0.2/src/include/lwip/priv/nd6_priv.h deleted file mode 100644 index 4bda0b793a..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/priv/nd6_priv.h +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @file - * - * Neighbor discovery and stateless address autoconfiguration for IPv6. - * Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 - * (Address autoconfiguration). - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_ND6_PRIV_H -#define LWIP_HDR_ND6_PRIV_H - -#include "lwip/opt.h" - -#if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_ND6_QUEUEING -/** struct for queueing outgoing packets for unknown address - * defined here to be accessed by memp.h - */ -struct nd6_q_entry { - struct nd6_q_entry *next; - struct pbuf *p; -}; -#endif /* LWIP_ND6_QUEUEING */ - -/** Struct for tables. */ -struct nd6_neighbor_cache_entry { - ip6_addr_t next_hop_address; - struct netif *netif; - u8_t lladdr[NETIF_MAX_HWADDR_LEN]; - /*u32_t pmtu;*/ -#if LWIP_ND6_QUEUEING - /** Pointer to queue of pending outgoing packets on this entry. */ - struct nd6_q_entry *q; -#else /* LWIP_ND6_QUEUEING */ - /** Pointer to a single pending outgoing packet on this entry. */ - struct pbuf *q; -#endif /* LWIP_ND6_QUEUEING */ - u8_t state; - u8_t isrouter; - union { - u32_t reachable_time; /* in ms since value may originate from network packet */ - u32_t delay_time; /* ticks (ND6_TMR_INTERVAL) */ - u32_t probes_sent; - u32_t stale_time; /* ticks (ND6_TMR_INTERVAL) */ - } counter; -}; - -struct nd6_destination_cache_entry { - ip6_addr_t destination_addr; - ip6_addr_t next_hop_addr; - u16_t pmtu; - u32_t age; -}; - -struct nd6_prefix_list_entry { - ip6_addr_t prefix; - struct netif *netif; - u32_t invalidation_timer; /* in ms since value may originate from network packet */ -#if LWIP_IPV6_AUTOCONFIG - u8_t flags; -#define ND6_PREFIX_AUTOCONFIG_AUTONOMOUS 0x01 -#define ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED 0x02 -#define ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE 0x04 -#endif /* LWIP_IPV6_AUTOCONFIG */ -}; - -struct nd6_router_list_entry { - struct nd6_neighbor_cache_entry *neighbor_entry; - u32_t invalidation_timer; /* in ms since value may originate from network packet */ - u8_t flags; -}; - -enum nd6_neighbor_cache_entry_state { - ND6_NO_ENTRY = 0, - ND6_INCOMPLETE, - ND6_REACHABLE, - ND6_STALE, - ND6_DELAY, - ND6_PROBE -}; - -/* Router tables. */ -/* @todo make these static? and entries accessible through API? */ -extern struct nd6_neighbor_cache_entry neighbor_cache[]; -extern struct nd6_destination_cache_entry destination_cache[]; -extern struct nd6_prefix_list_entry prefix_list[]; -extern struct nd6_router_list_entry default_router_list[]; - -/* Default values, can be updated by a RA message. */ -extern u32_t reachable_time; -extern u32_t retrans_timer; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 */ - -#endif /* LWIP_HDR_ND6_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/priv/tcp_priv.h b/components/net/lwip-2.0.2/src/include/lwip/priv/tcp_priv.h deleted file mode 100644 index 73e8967e47..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/priv/tcp_priv.h +++ /dev/null @@ -1,507 +0,0 @@ -/** - * @file - * TCP internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCP_PRIV_H -#define LWIP_HDR_TCP_PRIV_H - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/tcp.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/ip.h" -#include "lwip/icmp.h" -#include "lwip/err.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/prot/tcp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Functions for interfacing with TCP: */ - -/* Lower layer interface to TCP: */ -void tcp_init (void); /* Initialize this module. */ -void tcp_tmr (void); /* Must be called every - TCP_TMR_INTERVAL - ms. (Typically 250 ms). */ -/* It is also possible to call these two functions at the right - intervals (instead of calling tcp_tmr()). */ -void tcp_slowtmr (void); -void tcp_fasttmr (void); - -/* Call this from a netif driver (watch out for threading issues!) that has - returned a memory error on transmit and now has free buffers to send more. - This iterates all active pcbs that had an error and tries to call - tcp_output, so use this with care as it might slow down the system. */ -void tcp_txnow (void); - -/* Only used by IP to pass a TCP segment to TCP: */ -void tcp_input (struct pbuf *p, struct netif *inp); -/* Used within the TCP code only: */ -struct tcp_pcb * tcp_alloc (u8_t prio); -void tcp_abandon (struct tcp_pcb *pcb, int reset); -err_t tcp_send_empty_ack(struct tcp_pcb *pcb); -void tcp_rexmit (struct tcp_pcb *pcb); -void tcp_rexmit_rto (struct tcp_pcb *pcb); -void tcp_rexmit_fast (struct tcp_pcb *pcb); -u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); -err_t tcp_process_refused_data(struct tcp_pcb *pcb); - -/** - * This is the Nagle algorithm: try to combine user data to send as few TCP - * segments as possible. Only send if - * - no previously transmitted data on the connection remains unacknowledged or - * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or - * - the only unsent segment is at least pcb->mss bytes long (or there is more - * than one unsent segment - with lwIP, this can happen although unsent->len < mss) - * - or if we are in fast-retransmit (TF_INFR) - */ -#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ - ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ - (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ - ((tpcb)->unsent->len >= (tpcb)->mss))) || \ - ((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \ - ) ? 1 : 0) -#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) - - -#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0) -#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0) -#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0) -#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0) -/* is b<=a<=c? */ -#if 0 /* see bug #10548 */ -#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) -#endif -#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) - -#ifndef TCP_TMR_INTERVAL -#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ -#endif /* TCP_TMR_INTERVAL */ - -#ifndef TCP_FAST_INTERVAL -#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ -#endif /* TCP_FAST_INTERVAL */ - -#ifndef TCP_SLOW_INTERVAL -#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ -#endif /* TCP_SLOW_INTERVAL */ - -#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ -#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ - -#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ - -#ifndef TCP_MSL -#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ -#endif - -/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ -#ifndef TCP_KEEPIDLE_DEFAULT -#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ -#endif - -#ifndef TCP_KEEPINTVL_DEFAULT -#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ -#endif - -#ifndef TCP_KEEPCNT_DEFAULT -#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ -#endif - -#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ - -#define TCP_TCPLEN(seg) ((seg)->len + (((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0) ? 1U : 0U)) - -/** Flags used on input processing, not on pcb->flags -*/ -#define TF_RESET (u8_t)0x08U /* Connection was reset. */ -#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ -#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ - - -#if LWIP_EVENT_API - -#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) ret = lwip_tcp_event(arg, (pcb),\ - LWIP_EVENT_ACCEPT, NULL, 0, err) -#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_SENT, NULL, space, ERR_OK) -#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_RECV, (p), 0, (err)) -#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_RECV, NULL, 0, ERR_OK) -#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ - LWIP_EVENT_CONNECTED, NULL, 0, (err)) -#define TCP_EVENT_POLL(pcb,ret) do { if ((pcb)->state != SYN_RCVD) { \ - ret = lwip_tcp_event((pcb)->callback_arg, (pcb), LWIP_EVENT_POLL, NULL, 0, ERR_OK); \ - } else { \ - ret = ERR_ARG; } } while(0) -#define TCP_EVENT_ERR(last_state,errf,arg,err) do { if (last_state != SYN_RCVD) { \ - lwip_tcp_event((arg), NULL, LWIP_EVENT_ERR, NULL, 0, (err)); } } while(0) - -#else /* LWIP_EVENT_API */ - -#define TCP_EVENT_ACCEPT(lpcb,pcb,arg,err,ret) \ - do { \ - if((lpcb)->accept != NULL) \ - (ret) = (lpcb)->accept((arg),(pcb),(err)); \ - else (ret) = ERR_ARG; \ - } while (0) - -#define TCP_EVENT_SENT(pcb,space,ret) \ - do { \ - if((pcb)->sent != NULL) \ - (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ - else (ret) = ERR_OK; \ - } while (0) - -#define TCP_EVENT_RECV(pcb,p,err,ret) \ - do { \ - if((pcb)->recv != NULL) { \ - (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ - } else { \ - (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ - } \ - } while (0) - -#define TCP_EVENT_CLOSED(pcb,ret) \ - do { \ - if(((pcb)->recv != NULL)) { \ - (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ - } else { \ - (ret) = ERR_OK; \ - } \ - } while (0) - -#define TCP_EVENT_CONNECTED(pcb,err,ret) \ - do { \ - if((pcb)->connected != NULL) \ - (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ - else (ret) = ERR_OK; \ - } while (0) - -#define TCP_EVENT_POLL(pcb,ret) \ - do { \ - if((pcb)->poll != NULL) \ - (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ - else (ret) = ERR_OK; \ - } while (0) - -#define TCP_EVENT_ERR(last_state,errf,arg,err) \ - do { \ - LWIP_UNUSED_ARG(last_state); \ - if((errf) != NULL) \ - (errf)((arg),(err)); \ - } while (0) - -#endif /* LWIP_EVENT_API */ - -/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ -#if TCP_OVERSIZE && defined(LWIP_DEBUG) -#define TCP_OVERSIZE_DBGCHECK 1 -#else -#define TCP_OVERSIZE_DBGCHECK 0 -#endif - -/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ -#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) - -/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ -struct tcp_seg { - struct tcp_seg *next; /* used when putting segments on a queue */ - struct pbuf *p; /* buffer containing data + TCP header */ - u16_t len; /* the TCP length of this segment */ -#if TCP_OVERSIZE_DBGCHECK - u16_t oversize_left; /* Extra bytes available at the end of the last - pbuf in unsent (used for asserting vs. - tcp_pcb.unsent_oversize only) */ -#endif /* TCP_OVERSIZE_DBGCHECK */ -#if TCP_CHECKSUM_ON_COPY - u16_t chksum; - u8_t chksum_swapped; -#endif /* TCP_CHECKSUM_ON_COPY */ - u8_t flags; -#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ -#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ -#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is - checksummed into 'chksum' */ -#define TF_SEG_OPTS_WND_SCALE (u8_t)0x08U /* Include WND SCALE option */ - struct tcp_hdr *tcphdr; /* the TCP header */ -}; - -#define LWIP_TCP_OPT_EOL 0 -#define LWIP_TCP_OPT_NOP 1 -#define LWIP_TCP_OPT_MSS 2 -#define LWIP_TCP_OPT_WS 3 -#define LWIP_TCP_OPT_TS 8 - -#define LWIP_TCP_OPT_LEN_MSS 4 -#if LWIP_TCP_TIMESTAMPS -#define LWIP_TCP_OPT_LEN_TS 10 -#define LWIP_TCP_OPT_LEN_TS_OUT 12 /* aligned for output (includes NOP padding) */ -#else -#define LWIP_TCP_OPT_LEN_TS_OUT 0 -#endif -#if LWIP_WND_SCALE -#define LWIP_TCP_OPT_LEN_WS 3 -#define LWIP_TCP_OPT_LEN_WS_OUT 4 /* aligned for output (includes NOP padding) */ -#else -#define LWIP_TCP_OPT_LEN_WS_OUT 0 -#endif - -#define LWIP_TCP_OPT_LENGTH(flags) \ - (flags & TF_SEG_OPTS_MSS ? LWIP_TCP_OPT_LEN_MSS : 0) + \ - (flags & TF_SEG_OPTS_TS ? LWIP_TCP_OPT_LEN_TS_OUT : 0) + \ - (flags & TF_SEG_OPTS_WND_SCALE ? LWIP_TCP_OPT_LEN_WS_OUT : 0) - -/** This returns a TCP header option for MSS in an u32_t */ -#define TCP_BUILD_MSS_OPTION(mss) lwip_htonl(0x02040000 | ((mss) & 0xFFFF)) - -#if LWIP_WND_SCALE -#define TCPWNDSIZE_F U32_F -#define TCPWND_MAX 0xFFFFFFFFU -#define TCPWND_CHECK16(x) LWIP_ASSERT("window size > 0xFFFF", (x) <= 0xFFFF) -#define TCPWND_MIN16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) -#else /* LWIP_WND_SCALE */ -#define TCPWNDSIZE_F U16_F -#define TCPWND_MAX 0xFFFFU -#define TCPWND_CHECK16(x) -#define TCPWND_MIN16(x) x -#endif /* LWIP_WND_SCALE */ - -/* Global variables: */ -extern struct tcp_pcb *tcp_input_pcb; -extern u32_t tcp_ticks; -extern u8_t tcp_active_pcbs_changed; - -/* The TCP PCB lists. */ -union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ - struct tcp_pcb_listen *listen_pcbs; - struct tcp_pcb *pcbs; -}; -extern struct tcp_pcb *tcp_bound_pcbs; -extern union tcp_listen_pcbs_t tcp_listen_pcbs; -extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a - state in which they accept or send - data. */ -extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ - -#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 -#define NUM_TCP_PCB_LISTS 4 -extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; - -/* Axioms about the above lists: - 1) Every TCP PCB that is not CLOSED is in one of the lists. - 2) A PCB is only in one of the lists. - 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. - 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. -*/ -/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB - with a PCB list or removes a PCB from a list, respectively. */ -#ifndef TCP_DEBUG_PCB_LISTS -#define TCP_DEBUG_PCB_LISTS 0 -#endif -#if TCP_DEBUG_PCB_LISTS -#define TCP_REG(pcbs, npcb) do {\ - struct tcp_pcb *tcp_tmp_pcb; \ - LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ - for (tcp_tmp_pcb = *(pcbs); \ - tcp_tmp_pcb != NULL; \ - tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ - } \ - LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ - (npcb)->next = *(pcbs); \ - LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ - *(pcbs) = (npcb); \ - LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ - tcp_timer_needed(); \ - } while(0) -#define TCP_RMV(pcbs, npcb) do { \ - struct tcp_pcb *tcp_tmp_pcb; \ - LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ - LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ - if(*(pcbs) == (npcb)) { \ - *(pcbs) = (*pcbs)->next; \ - } else for (tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - if(tcp_tmp_pcb->next == (npcb)) { \ - tcp_tmp_pcb->next = (npcb)->next; \ - break; \ - } \ - } \ - (npcb)->next = NULL; \ - LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ - LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ - } while(0) - -#else /* LWIP_DEBUG */ - -#define TCP_REG(pcbs, npcb) \ - do { \ - (npcb)->next = *pcbs; \ - *(pcbs) = (npcb); \ - tcp_timer_needed(); \ - } while (0) - -#define TCP_RMV(pcbs, npcb) \ - do { \ - if(*(pcbs) == (npcb)) { \ - (*(pcbs)) = (*pcbs)->next; \ - } \ - else { \ - struct tcp_pcb *tcp_tmp_pcb; \ - for (tcp_tmp_pcb = *pcbs; \ - tcp_tmp_pcb != NULL; \ - tcp_tmp_pcb = tcp_tmp_pcb->next) { \ - if(tcp_tmp_pcb->next == (npcb)) { \ - tcp_tmp_pcb->next = (npcb)->next; \ - break; \ - } \ - } \ - } \ - (npcb)->next = NULL; \ - } while(0) - -#endif /* LWIP_DEBUG */ - -#define TCP_REG_ACTIVE(npcb) \ - do { \ - TCP_REG(&tcp_active_pcbs, npcb); \ - tcp_active_pcbs_changed = 1; \ - } while (0) - -#define TCP_RMV_ACTIVE(npcb) \ - do { \ - TCP_RMV(&tcp_active_pcbs, npcb); \ - tcp_active_pcbs_changed = 1; \ - } while (0) - -#define TCP_PCB_REMOVE_ACTIVE(pcb) \ - do { \ - tcp_pcb_remove(&tcp_active_pcbs, pcb); \ - tcp_active_pcbs_changed = 1; \ - } while (0) - - -/* Internal functions: */ -struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); -void tcp_pcb_purge(struct tcp_pcb *pcb); -void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); - -void tcp_segs_free(struct tcp_seg *seg); -void tcp_seg_free(struct tcp_seg *seg); -struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); - -#define tcp_ack(pcb) \ - do { \ - if((pcb)->flags & TF_ACK_DELAY) { \ - (pcb)->flags &= ~TF_ACK_DELAY; \ - (pcb)->flags |= TF_ACK_NOW; \ - } \ - else { \ - (pcb)->flags |= TF_ACK_DELAY; \ - } \ - } while (0) - -#define tcp_ack_now(pcb) \ - do { \ - (pcb)->flags |= TF_ACK_NOW; \ - } while (0) - -err_t tcp_send_fin(struct tcp_pcb *pcb); -err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags); - -void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); - -void tcp_rst(u32_t seqno, u32_t ackno, - const ip_addr_t *local_ip, const ip_addr_t *remote_ip, - u16_t local_port, u16_t remote_port); - -u32_t tcp_next_iss(struct tcp_pcb *pcb); - -err_t tcp_keepalive(struct tcp_pcb *pcb); -err_t tcp_zero_window_probe(struct tcp_pcb *pcb); -void tcp_trigger_input_pcb_close(void); - -#if TCP_CALCULATE_EFF_SEND_MSS -u16_t tcp_eff_send_mss_impl(u16_t sendmss, const ip_addr_t *dest -#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING - , const ip_addr_t *src -#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ - ); -#if LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING -#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest, src) -#else /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ -#define tcp_eff_send_mss(sendmss, src, dest) tcp_eff_send_mss_impl(sendmss, dest) -#endif /* LWIP_IPV6 || LWIP_IPV4_SRC_ROUTING */ -#endif /* TCP_CALCULATE_EFF_SEND_MSS */ - -#if LWIP_CALLBACK_API -err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); -#endif /* LWIP_CALLBACK_API */ - -#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG -void tcp_debug_print(struct tcp_hdr *tcphdr); -void tcp_debug_print_flags(u8_t flags); -void tcp_debug_print_state(enum tcp_state s); -void tcp_debug_print_pcbs(void); -s16_t tcp_pcbs_sane(void); -#else -# define tcp_debug_print(tcphdr) -# define tcp_debug_print_flags(flags) -# define tcp_debug_print_state(s) -# define tcp_debug_print_pcbs() -# define tcp_pcbs_sane() 1 -#endif /* TCP_DEBUG */ - -/** External function (implemented in timers.c), called when TCP detects - * that a timer is needed (i.e. active- or time-wait-pcb found). */ -void tcp_timer_needed(void); - -void tcp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_TCP */ - -#endif /* LWIP_HDR_TCP_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/priv/tcpip_priv.h b/components/net/lwip-2.0.2/src/include/lwip/priv/tcpip_priv.h deleted file mode 100644 index 630efb1402..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/priv/tcpip_priv.h +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @file - * TCPIP API internal implementations (do not use in application code) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCPIP_PRIV_H -#define LWIP_HDR_TCPIP_PRIV_H - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/tcpip.h" -#include "lwip/sys.h" -#include "lwip/timeouts.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct pbuf; -struct netif; - -#if LWIP_MPU_COMPATIBLE -#define API_VAR_REF(name) (*(name)) -#define API_VAR_DECLARE(type, name) type * name -#define API_VAR_ALLOC(type, pool, name, errorval) do { \ - name = (type *)memp_malloc(pool); \ - if (name == NULL) { \ - return errorval; \ - } \ - } while(0) -#define API_VAR_ALLOC_POOL(type, pool, name, errorval) do { \ - name = (type *)LWIP_MEMPOOL_ALLOC(pool); \ - if (name == NULL) { \ - return errorval; \ - } \ - } while(0) -#define API_VAR_FREE(pool, name) memp_free(pool, name) -#define API_VAR_FREE_POOL(pool, name) LWIP_MEMPOOL_FREE(pool, name) -#define API_EXPR_REF(expr) (&(expr)) -#if LWIP_NETCONN_SEM_PER_THREAD -#define API_EXPR_REF_SEM(expr) (expr) -#else -#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) -#endif -#define API_EXPR_DEREF(expr) expr -#define API_MSG_M_DEF(m) m -#define API_MSG_M_DEF_C(t, m) t m -#else /* LWIP_MPU_COMPATIBLE */ -#define API_VAR_REF(name) name -#define API_VAR_DECLARE(type, name) type name -#define API_VAR_ALLOC(type, pool, name, errorval) -#define API_VAR_ALLOC_POOL(type, pool, name, errorval) -#define API_VAR_FREE(pool, name) -#define API_VAR_FREE_POOL(pool, name) -#define API_EXPR_REF(expr) expr -#define API_EXPR_REF_SEM(expr) API_EXPR_REF(expr) -#define API_EXPR_DEREF(expr) (*(expr)) -#define API_MSG_M_DEF(m) *m -#define API_MSG_M_DEF_C(t, m) const t * m -#endif /* LWIP_MPU_COMPATIBLE */ - -err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem); - -struct tcpip_api_call_data -{ -#if !LWIP_TCPIP_CORE_LOCKING - err_t err; -#if !LWIP_NETCONN_SEM_PER_THREAD - sys_sem_t sem; -#endif /* LWIP_NETCONN_SEM_PER_THREAD */ -#else /* !LWIP_TCPIP_CORE_LOCKING */ - u8_t dummy; /* avoid empty struct :-( */ -#endif /* !LWIP_TCPIP_CORE_LOCKING */ -}; -typedef err_t (*tcpip_api_call_fn)(struct tcpip_api_call_data* call); -err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call); - -enum tcpip_msg_type { - TCPIP_MSG_API, - TCPIP_MSG_API_CALL, - TCPIP_MSG_INPKT, -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS - TCPIP_MSG_TIMEOUT, - TCPIP_MSG_UNTIMEOUT, -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - TCPIP_MSG_CALLBACK, - TCPIP_MSG_CALLBACK_STATIC -}; - -struct tcpip_msg { - enum tcpip_msg_type type; - union { - struct { - tcpip_callback_fn function; - void* msg; - } api_msg; - struct { - tcpip_api_call_fn function; - struct tcpip_api_call_data *arg; - sys_sem_t *sem; - } api_call; - struct { - struct pbuf *p; - struct netif *netif; - netif_input_fn input_fn; - } inp; - struct { - tcpip_callback_fn function; - void *ctx; - } cb; -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS - struct { - u32_t msecs; - sys_timeout_handler h; - void *arg; - } tmo; -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - } msg; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* !NO_SYS */ - -#endif /* LWIP_HDR_TCPIP_PRIV_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/autoip.h b/components/net/lwip-2.0.2/src/include/lwip/prot/autoip.h deleted file mode 100644 index fd3af8a9fc..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/autoip.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file - * AutoIP protocol definitions - */ - -/* - * - * Copyright (c) 2007 Dominik Spies - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dominik Spies - * - * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform - * with RFC 3927. - * - */ - -#ifndef LWIP_HDR_PROT_AUTOIP_H -#define LWIP_HDR_PROT_AUTOIP_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* 169.254.0.0 */ -#define AUTOIP_NET 0xA9FE0000 -/* 169.254.1.0 */ -#define AUTOIP_RANGE_START (AUTOIP_NET | 0x0100) -/* 169.254.254.255 */ -#define AUTOIP_RANGE_END (AUTOIP_NET | 0xFEFF) - -/* RFC 3927 Constants */ -#define PROBE_WAIT 1 /* second (initial random delay) */ -#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ -#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ -#define PROBE_NUM 3 /* (number of probe packets) */ -#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ -#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ -#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ -#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ -#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ -#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ - -/* AutoIP client states */ -typedef enum { - AUTOIP_STATE_OFF = 0, - AUTOIP_STATE_PROBING = 1, - AUTOIP_STATE_ANNOUNCING = 2, - AUTOIP_STATE_BOUND = 3 -} autoip_state_enum_t; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_AUTOIP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/dhcp.h b/components/net/lwip-2.0.2/src/include/lwip/prot/dhcp.h deleted file mode 100644 index 112953cb8b..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/dhcp.h +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file - * DHCP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Leon Woestenberg - * Copyright (c) 2001-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Leon Woestenberg - * - */ -#ifndef LWIP_HDR_PROT_DHCP_H -#define LWIP_HDR_PROT_DHCP_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define DHCP_CLIENT_PORT 68 -#define DHCP_SERVER_PORT 67 - - - /* DHCP message item offsets and length */ -#define DHCP_CHADDR_LEN 16U -#define DHCP_SNAME_OFS 44U -#define DHCP_SNAME_LEN 64U -#define DHCP_FILE_OFS 108U -#define DHCP_FILE_LEN 128U -#define DHCP_MSG_LEN 236U -#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4U) /* 4 byte: cookie */ - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** minimum set of fields of any DHCP message */ -struct dhcp_msg -{ - PACK_STRUCT_FLD_8(u8_t op); - PACK_STRUCT_FLD_8(u8_t htype); - PACK_STRUCT_FLD_8(u8_t hlen); - PACK_STRUCT_FLD_8(u8_t hops); - PACK_STRUCT_FIELD(u32_t xid); - PACK_STRUCT_FIELD(u16_t secs); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); - PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); - PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); - PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); - PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); - PACK_STRUCT_FIELD(u32_t cookie); -#define DHCP_MIN_OPTIONS_LEN 68U -/** make sure user does not configure this too small */ -#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) -# undef DHCP_OPTIONS_LEN -#endif -/** allow this to be configured in lwipopts.h, but not too small */ -#if (!defined(DHCP_OPTIONS_LEN)) -/** set this to be sufficient for your options in outgoing DHCP msgs */ -# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN -#endif - PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - -/* DHCP client states */ -typedef enum { - DHCP_STATE_OFF = 0, - DHCP_STATE_REQUESTING = 1, - DHCP_STATE_INIT = 2, - DHCP_STATE_REBOOTING = 3, - DHCP_STATE_REBINDING = 4, - DHCP_STATE_RENEWING = 5, - DHCP_STATE_SELECTING = 6, - DHCP_STATE_INFORMING = 7, - DHCP_STATE_CHECKING = 8, - DHCP_STATE_PERMANENT = 9, /* not yet implemented */ - DHCP_STATE_BOUND = 10, - DHCP_STATE_RELEASING = 11, /* not yet implemented */ - DHCP_STATE_BACKING_OFF = 12 -} dhcp_state_enum_t; - -/* DHCP op codes */ -#define DHCP_BOOTREQUEST 1 -#define DHCP_BOOTREPLY 2 - -/* DHCP message types */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -/** DHCP hardware type, currently only ethernet is supported */ -#define DHCP_HTYPE_ETH 1 - -#define DHCP_MAGIC_COOKIE 0x63825363UL - -/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ - -/* BootP options */ -#define DHCP_OPTION_PAD 0 -#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DNS_SERVER 6 -#define DHCP_OPTION_HOSTNAME 12 -#define DHCP_OPTION_IP_TTL 23 -#define DHCP_OPTION_MTU 26 -#define DHCP_OPTION_BROADCAST 28 -#define DHCP_OPTION_TCP_TTL 37 -#define DHCP_OPTION_NTP 42 -#define DHCP_OPTION_END 255 - -/* DHCP options */ -#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ -#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ -#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ - -#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ -#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 - -#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ -#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ - -#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ -#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 - -#define DHCP_OPTION_T1 58 /* T1 renewal time */ -#define DHCP_OPTION_T2 59 /* T2 rebinding time */ -#define DHCP_OPTION_US 60 -#define DHCP_OPTION_CLIENT_ID 61 -#define DHCP_OPTION_TFTP_SERVERNAME 66 -#define DHCP_OPTION_BOOTFILE 67 - -/* possible combinations of overloading the file and sname fields with options */ -#define DHCP_OVERLOAD_NONE 0 -#define DHCP_OVERLOAD_FILE 1 -#define DHCP_OVERLOAD_SNAME 2 -#define DHCP_OVERLOAD_SNAME_FILE 3 - - -#ifdef __cplusplus -} -#endif - -#endif /*LWIP_HDR_PROT_DHCP_H*/ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/dns.h b/components/net/lwip-2.0.2/src/include/lwip/prot/dns.h deleted file mode 100644 index 94782d6e9c..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/dns.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file - * DNS - host name to IP address resolver. - */ - -/* - * Port to lwIP from uIP - * by Jim Pettinato April 2007 - * - * security fixes and more by Simon Goldschmidt - * - * uIP version Copyright (c) 2002-2003, Adam Dunkels. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LWIP_HDR_PROT_DNS_H -#define LWIP_HDR_PROT_DNS_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** DNS server port address */ -#ifndef DNS_SERVER_PORT -#define DNS_SERVER_PORT 53 -#endif - -/* DNS field TYPE used for "Resource Records" */ -#define DNS_RRTYPE_A 1 /* a host address */ -#define DNS_RRTYPE_NS 2 /* an authoritative name server */ -#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ -#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ -#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ -#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ -#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ -#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ -#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ -#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ -#define DNS_RRTYPE_WKS 11 /* a well known service description */ -#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ -#define DNS_RRTYPE_HINFO 13 /* host information */ -#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ -#define DNS_RRTYPE_MX 15 /* mail exchange */ -#define DNS_RRTYPE_TXT 16 /* text strings */ -#define DNS_RRTYPE_AAAA 28 /* IPv6 address */ -#define DNS_RRTYPE_SRV 33 /* service location */ -#define DNS_RRTYPE_ANY 255 /* any type */ - -/* DNS field CLASS used for "Resource Records" */ -#define DNS_RRCLASS_IN 1 /* the Internet */ -#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ -#define DNS_RRCLASS_CH 3 /* the CHAOS class */ -#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ -#define DNS_RRCLASS_ANY 255 /* any class */ -#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ - -/* DNS protocol flags */ -#define DNS_FLAG1_RESPONSE 0x80 -#define DNS_FLAG1_OPCODE_STATUS 0x10 -#define DNS_FLAG1_OPCODE_INVERSE 0x08 -#define DNS_FLAG1_OPCODE_STANDARD 0x00 -#define DNS_FLAG1_AUTHORATIVE 0x04 -#define DNS_FLAG1_TRUNC 0x02 -#define DNS_FLAG1_RD 0x01 -#define DNS_FLAG2_RA 0x80 -#define DNS_FLAG2_ERR_MASK 0x0f -#define DNS_FLAG2_ERR_NONE 0x00 -#define DNS_FLAG2_ERR_NAME 0x03 - -#define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF) - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** DNS message header */ -struct dns_hdr { - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FLD_8(u8_t flags1); - PACK_STRUCT_FLD_8(u8_t flags2); - PACK_STRUCT_FIELD(u16_t numquestions); - PACK_STRUCT_FIELD(u16_t numanswers); - PACK_STRUCT_FIELD(u16_t numauthrr); - PACK_STRUCT_FIELD(u16_t numextrarr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define SIZEOF_DNS_HDR 12 - - -/* Multicast DNS definitions */ - -/** UDP port for multicast DNS queries */ -#ifndef DNS_MQUERY_PORT -#define DNS_MQUERY_PORT 5353 -#endif - -/* IPv4 group for multicast DNS queries: 224.0.0.251 */ -#ifndef DNS_MQUERY_IPV4_GROUP_INIT -#define DNS_MQUERY_IPV4_GROUP_INIT IPADDR4_INIT_BYTES(224,0,0,251) -#endif - -/* IPv6 group for multicast DNS queries: FF02::FB */ -#ifndef DNS_MQUERY_IPV6_GROUP_INIT -#define DNS_MQUERY_IPV6_GROUP_INIT IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_DNS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/etharp.h b/components/net/lwip-2.0.2/src/include/lwip/prot/etharp.h deleted file mode 100644 index ec78305b82..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/etharp.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file - * ARP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ETHARP_H -#define LWIP_HDR_PROT_ETHARP_H - -#include "lwip/arch.h" -#include "lwip/prot/ethernet.h" -#include "lwip/ip4_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ETHARP_HWADDR_LEN -#define ETHARP_HWADDR_LEN ETH_HWADDR_LEN -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** the ARP message, see RFC 826 ("Packet format") */ -struct etharp_hdr { - PACK_STRUCT_FIELD(u16_t hwtype); - PACK_STRUCT_FIELD(u16_t proto); - PACK_STRUCT_FLD_8(u8_t hwlen); - PACK_STRUCT_FLD_8(u8_t protolen); - PACK_STRUCT_FIELD(u16_t opcode); - PACK_STRUCT_FLD_S(struct eth_addr shwaddr); - PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); - PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); - PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETHARP_HDR 28 - -/* ARP hwtype values */ -enum etharp_hwtype { - HWTYPE_ETHERNET = 1 - /* others not used */ -}; - -/* ARP message types (opcodes) */ -enum etharp_opcode { - ARP_REQUEST = 1, - ARP_REPLY = 2 -}; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ETHARP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/ethernet.h b/components/net/lwip-2.0.2/src/include/lwip/prot/ethernet.h deleted file mode 100644 index fae4570479..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/ethernet.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @file - * Ethernet protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ETHERNET_H -#define LWIP_HDR_PROT_ETHERNET_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ETH_HWADDR_LEN -#ifdef ETHARP_HWADDR_LEN -#define ETH_HWADDR_LEN ETHARP_HWADDR_LEN /* compatibility mode */ -#else -#define ETH_HWADDR_LEN 6 -#endif -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct eth_addr { - PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** Ethernet header */ -struct eth_hdr { -#if ETH_PAD_SIZE - PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); -#endif - PACK_STRUCT_FLD_S(struct eth_addr dest); - PACK_STRUCT_FLD_S(struct eth_addr src); - PACK_STRUCT_FIELD(u16_t type); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/** VLAN header inserted between ethernet header and payload - * if 'type' in ethernet header is ETHTYPE_VLAN. - * See IEEE802.Q */ -struct eth_vlan_hdr { - PACK_STRUCT_FIELD(u16_t prio_vid); - PACK_STRUCT_FIELD(u16_t tpid); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define SIZEOF_VLAN_HDR 4 -#define VLAN_ID(vlan_hdr) (lwip_htons((vlan_hdr)->prio_vid) & 0xFFF) - -/** - * @ingroup ethernet - * A list of often ethtypes (although lwIP does not use all of them): */ -enum eth_type { - /** Internet protocol v4 */ - ETHTYPE_IP = 0x0800U, - /** Address resolution protocol */ - ETHTYPE_ARP = 0x0806U, - /** Wake on lan */ - ETHTYPE_WOL = 0x0842U, - /** RARP */ - ETHTYPE_RARP = 0x8035U, - /** Virtual local area network */ - ETHTYPE_VLAN = 0x8100U, - /** Internet protocol v6 */ - ETHTYPE_IPV6 = 0x86DDU, - /** PPP Over Ethernet Discovery Stage */ - ETHTYPE_PPPOEDISC = 0x8863U, - /** PPP Over Ethernet Session Stage */ - ETHTYPE_PPPOE = 0x8864U, - /** Jumbo Frames */ - ETHTYPE_JUMBO = 0x8870U, - /** EAPOL, EAP over LAN */ - ETHTYPE_EAPOL = 0x888EU, - /** Process field network */ - ETHTYPE_PROFINET = 0x8892U, - /** Ethernet for control automation technology */ - ETHTYPE_ETHERCAT = 0x88A4U, - /** Link layer discovery protocol */ - ETHTYPE_LLDP = 0x88CCU, - /** Serial real-time communication system */ - ETHTYPE_SERCOS = 0x88CDU, - /** Media redundancy protocol */ - ETHTYPE_MRP = 0x88E3U, - /** Precision time protocol */ - ETHTYPE_PTP = 0x88F7U, - /** Q-in-Q, 802.1ad */ - ETHTYPE_QINQ = 0x9100U, -}; - -/** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ -#define LL_IP4_MULTICAST_ADDR_0 0x01 -#define LL_IP4_MULTICAST_ADDR_1 0x00 -#define LL_IP4_MULTICAST_ADDR_2 0x5e - -/** IPv6 multicast uses this prefix */ -#define LL_IP6_MULTICAST_ADDR_0 0x33 -#define LL_IP6_MULTICAST_ADDR_1 0x33 - -/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables - * or known to be 32-bit aligned within the protocol header. */ -#ifndef ETHADDR32_COPY -#define ETHADDR32_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) -#endif - -/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local - * variables and known to be 16-bit aligned within the protocol header. */ -#ifndef ETHADDR16_COPY -#define ETHADDR16_COPY(dst, src) SMEMCPY(dst, src, ETH_HWADDR_LEN) -#endif - -#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ETHERNET_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/icmp.h b/components/net/lwip-2.0.2/src/include/lwip/prot/icmp.h deleted file mode 100644 index 7d19385c72..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/icmp.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file - * ICMP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ICMP_H -#define LWIP_HDR_PROT_ICMP_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ICMP_ER 0 /* echo reply */ -#define ICMP_DUR 3 /* destination unreachable */ -#define ICMP_SQ 4 /* source quench */ -#define ICMP_RD 5 /* redirect */ -#define ICMP_ECHO 8 /* echo */ -#define ICMP_TE 11 /* time exceeded */ -#define ICMP_PP 12 /* parameter problem */ -#define ICMP_TS 13 /* timestamp */ -#define ICMP_TSR 14 /* timestamp reply */ -#define ICMP_IRQ 15 /* information request */ -#define ICMP_IR 16 /* information reply */ -#define ICMP_AM 17 /* address mask request */ -#define ICMP_AMR 18 /* address mask reply */ - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -/** This is the standard ICMP header only that the u32_t data - * is split to two u16_t like ICMP echo needs it. - * This header is also used for other ICMP types that do not - * use the data part. - */ -PACK_STRUCT_BEGIN -struct icmp_echo_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Compatibility defines, old versions used to combine type and code to an u16_t */ -#define ICMPH_TYPE(hdr) ((hdr)->type) -#define ICMPH_CODE(hdr) ((hdr)->code) -#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) -#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ICMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/icmp6.h b/components/net/lwip-2.0.2/src/include/lwip/prot/icmp6.h deleted file mode 100644 index 3461120421..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/icmp6.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @file - * ICMP6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ICMP6_H -#define LWIP_HDR_PROT_ICMP6_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** ICMP type */ -enum icmp6_type { - /** Destination unreachable */ - ICMP6_TYPE_DUR = 1, - /** Packet too big */ - ICMP6_TYPE_PTB = 2, - /** Time exceeded */ - ICMP6_TYPE_TE = 3, - /** Parameter problem */ - ICMP6_TYPE_PP = 4, - /** Private experimentation */ - ICMP6_TYPE_PE1 = 100, - /** Private experimentation */ - ICMP6_TYPE_PE2 = 101, - /** Reserved for expansion of error messages */ - ICMP6_TYPE_RSV_ERR = 127, - - /** Echo request */ - ICMP6_TYPE_EREQ = 128, - /** Echo reply */ - ICMP6_TYPE_EREP = 129, - /** Multicast listener query */ - ICMP6_TYPE_MLQ = 130, - /** Multicast listener report */ - ICMP6_TYPE_MLR = 131, - /** Multicast listener done */ - ICMP6_TYPE_MLD = 132, - /** Router solicitation */ - ICMP6_TYPE_RS = 133, - /** Router advertisement */ - ICMP6_TYPE_RA = 134, - /** Neighbor solicitation */ - ICMP6_TYPE_NS = 135, - /** Neighbor advertisement */ - ICMP6_TYPE_NA = 136, - /** Redirect */ - ICMP6_TYPE_RD = 137, - /** Multicast router advertisement */ - ICMP6_TYPE_MRA = 151, - /** Multicast router solicitation */ - ICMP6_TYPE_MRS = 152, - /** Multicast router termination */ - ICMP6_TYPE_MRT = 153, - /** Private experimentation */ - ICMP6_TYPE_PE3 = 200, - /** Private experimentation */ - ICMP6_TYPE_PE4 = 201, - /** Reserved for expansion of informational messages */ - ICMP6_TYPE_RSV_INF = 255 -}; - -/** ICMP destination unreachable codes */ -enum icmp6_dur_code { - /** No route to destination */ - ICMP6_DUR_NO_ROUTE = 0, - /** Communication with destination administratively prohibited */ - ICMP6_DUR_PROHIBITED = 1, - /** Beyond scope of source address */ - ICMP6_DUR_SCOPE = 2, - /** Address unreachable */ - ICMP6_DUR_ADDRESS = 3, - /** Port unreachable */ - ICMP6_DUR_PORT = 4, - /** Source address failed ingress/egress policy */ - ICMP6_DUR_POLICY = 5, - /** Reject route to destination */ - ICMP6_DUR_REJECT_ROUTE = 6 -}; - -/** ICMP time exceeded codes */ -enum icmp6_te_code { - /** Hop limit exceeded in transit */ - ICMP6_TE_HL = 0, - /** Fragment reassembly time exceeded */ - ICMP6_TE_FRAG = 1 -}; - -/** ICMP parameter code */ -enum icmp6_pp_code { - /** Erroneous header field encountered */ - ICMP6_PP_FIELD = 0, - /** Unrecognized next header type encountered */ - ICMP6_PP_HEADER = 1, - /** Unrecognized IPv6 option encountered */ - ICMP6_PP_OPTION = 2 -}; - -/** This is the standard ICMP6 header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct icmp6_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t data); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** This is the ICMP6 header adapted for echo req/resp. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct icmp6_echo_hdr { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t id); - PACK_STRUCT_FIELD(u16_t seqno); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ICMP6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/igmp.h b/components/net/lwip-2.0.2/src/include/lwip/prot/igmp.h deleted file mode 100644 index d60cb31ee7..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/igmp.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file - * IGMP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IGMP_H -#define LWIP_HDR_PROT_IGMP_H - -#include "lwip/arch.h" -#include "lwip/ip4_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * IGMP constants - */ -#define IGMP_TTL 1 -#define IGMP_MINLEN 8 -#define ROUTER_ALERT 0x9404U -#define ROUTER_ALERTLEN 4 - -/* - * IGMP message types, including version number. - */ -#define IGMP_MEMB_QUERY 0x11 /* Membership query */ -#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */ -#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */ -#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */ - -/* Group membership states */ -#define IGMP_GROUP_NON_MEMBER 0 -#define IGMP_GROUP_DELAYING_MEMBER 1 -#define IGMP_GROUP_IDLE_MEMBER 2 - -/** - * IGMP packet format. - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct igmp_msg { - PACK_STRUCT_FLD_8(u8_t igmp_msgtype); - PACK_STRUCT_FLD_8(u8_t igmp_maxresp); - PACK_STRUCT_FIELD(u16_t igmp_checksum); - PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_IGMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/ip.h b/components/net/lwip-2.0.2/src/include/lwip/prot/ip.h deleted file mode 100644 index bbfae36752..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/ip.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file - * IP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IP_H -#define LWIP_HDR_PROT_IP_H - -#include "lwip/arch.h" - -#define IP_PROTO_ICMP 1 -#define IP_PROTO_IGMP 2 -#define IP_PROTO_UDP 17 -#define IP_PROTO_UDPLITE 136 -#define IP_PROTO_TCP 6 - -/** This operates on a void* by loading the first byte */ -#define IP_HDR_GET_VERSION(ptr) ((*(u8_t*)(ptr)) >> 4) - -#endif /* LWIP_HDR_PROT_IP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/ip4.h b/components/net/lwip-2.0.2/src/include/lwip/prot/ip4.h deleted file mode 100644 index bd442c6892..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/ip4.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file - * IPv4 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IP4_H -#define LWIP_HDR_PROT_IP4_H - -#include "lwip/arch.h" -#include "lwip/ip4_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This is the packed version of ip4_addr_t, - used in network headers that are itself packed */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip4_addr_packed { - PACK_STRUCT_FIELD(u32_t addr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -typedef struct ip4_addr_packed ip4_addr_p_t; - -/* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */ -#define IP_HLEN 20 - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -/* The IPv4 header */ -struct ip_hdr { - /* version / header length */ - PACK_STRUCT_FLD_8(u8_t _v_hl); - /* type of service */ - PACK_STRUCT_FLD_8(u8_t _tos); - /* total length */ - PACK_STRUCT_FIELD(u16_t _len); - /* identification */ - PACK_STRUCT_FIELD(u16_t _id); - /* fragment offset field */ - PACK_STRUCT_FIELD(u16_t _offset); -#define IP_RF 0x8000U /* reserved fragment flag */ -#define IP_DF 0x4000U /* don't fragment flag */ -#define IP_MF 0x2000U /* more fragments flag */ -#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ - /* time to live */ - PACK_STRUCT_FLD_8(u8_t _ttl); - /* protocol*/ - PACK_STRUCT_FLD_8(u8_t _proto); - /* checksum */ - PACK_STRUCT_FIELD(u16_t _chksum); - /* source and destination IP addresses */ - PACK_STRUCT_FLD_S(ip4_addr_p_t src); - PACK_STRUCT_FLD_S(ip4_addr_p_t dest); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Macros to get struct ip_hdr fields: */ -#define IPH_V(hdr) ((hdr)->_v_hl >> 4) -#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) -#define IPH_TOS(hdr) ((hdr)->_tos) -#define IPH_LEN(hdr) ((hdr)->_len) -#define IPH_ID(hdr) ((hdr)->_id) -#define IPH_OFFSET(hdr) ((hdr)->_offset) -#define IPH_TTL(hdr) ((hdr)->_ttl) -#define IPH_PROTO(hdr) ((hdr)->_proto) -#define IPH_CHKSUM(hdr) ((hdr)->_chksum) - -/* Macros to set struct ip_hdr fields: */ -#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) -#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) -#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) -#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) -#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) -#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) -#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) -#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_IP4_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/ip6.h b/components/net/lwip-2.0.2/src/include/lwip/prot/ip6.h deleted file mode 100644 index 6e1e2632bf..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/ip6.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file - * IPv6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_IP6_H -#define LWIP_HDR_PROT_IP6_H - -#include "lwip/arch.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** This is the packed version of ip6_addr_t, - used in network headers that are itself packed */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_addr_packed { - PACK_STRUCT_FIELD(u32_t addr[4]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -typedef struct ip6_addr_packed ip6_addr_p_t; - -#define IP6_HLEN 40 - -#define IP6_NEXTH_HOPBYHOP 0 -#define IP6_NEXTH_TCP 6 -#define IP6_NEXTH_UDP 17 -#define IP6_NEXTH_ENCAPS 41 -#define IP6_NEXTH_ROUTING 43 -#define IP6_NEXTH_FRAGMENT 44 -#define IP6_NEXTH_ICMP6 58 -#define IP6_NEXTH_NONE 59 -#define IP6_NEXTH_DESTOPTS 60 -#define IP6_NEXTH_UDPLITE 136 - -/** The IPv6 header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_hdr { - /** version / traffic class / flow label */ - PACK_STRUCT_FIELD(u32_t _v_tc_fl); - /** payload length */ - PACK_STRUCT_FIELD(u16_t _plen); - /** next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /** hop limit */ - PACK_STRUCT_FLD_8(u8_t _hoplim); - /** source and destination IP addresses */ - PACK_STRUCT_FLD_S(ip6_addr_p_t src); - PACK_STRUCT_FLD_S(ip6_addr_p_t dest); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Hop-by-hop router alert option. */ -#define IP6_HBH_HLEN 8 -#define IP6_PAD1_OPTION 0 -#define IP6_PADN_ALERT_OPTION 1 -#define IP6_ROUTER_ALERT_OPTION 5 -#define IP6_ROUTER_ALERT_VALUE_MLD 0 -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_hbh_hdr { - /* next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /* header length */ - PACK_STRUCT_FLD_8(u8_t _hlen); - /* router alert option type */ - PACK_STRUCT_FLD_8(u8_t _ra_opt_type); - /* router alert option data len */ - PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); - /* router alert option data */ - PACK_STRUCT_FIELD(u16_t _ra_opt_data); - /* PadN option type */ - PACK_STRUCT_FLD_8(u8_t _padn_opt_type); - /* PadN option data len */ - PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* Fragment header. */ -#define IP6_FRAG_HLEN 8 -#define IP6_FRAG_OFFSET_MASK 0xfff8 -#define IP6_FRAG_MORE_FLAG 0x0001 -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ip6_frag_hdr { - /* next header */ - PACK_STRUCT_FLD_8(u8_t _nexth); - /* reserved */ - PACK_STRUCT_FLD_8(u8_t reserved); - /* fragment offset */ - PACK_STRUCT_FIELD(u16_t _fragment_offset); - /* fragmented packet identification */ - PACK_STRUCT_FIELD(u32_t _identification); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#define IP6H_V(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) -#define IP6H_TC(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) -#define IP6H_FL(hdr) (lwip_ntohl((hdr)->_v_tc_fl) & 0x000fffff) -#define IP6H_PLEN(hdr) (lwip_ntohs((hdr)->_plen)) -#define IP6H_NEXTH(hdr) ((hdr)->_nexth) -#define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) -#define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) - -#define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (lwip_htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) -#define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = lwip_htons(plen) -#define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) -#define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_IP6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/mld6.h b/components/net/lwip-2.0.2/src/include/lwip/prot/mld6.h deleted file mode 100644 index be3a006af2..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/mld6.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file - * MLD6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_MLD6_H -#define LWIP_HDR_PROT_MLD6_H - -#include "lwip/arch.h" -#include "lwip/prot/ip6.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Multicast listener report/query/done message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct mld_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t max_resp_delay); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_MLD6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/nd6.h b/components/net/lwip-2.0.2/src/include/lwip/prot/nd6.h deleted file mode 100644 index 2d4903d15b..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/nd6.h +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @file - * ND6 protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_ND6_H -#define LWIP_HDR_PROT_ND6_H - -#include "lwip/arch.h" -#include "lwip/ip6_addr.h" -#include "lwip/prot/ip6.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** Neighbor solicitation message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ns_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Neighbor advertisement message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct na_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FLD_8(u8_t reserved[3]); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#define ND6_FLAG_ROUTER (0x80) -#define ND6_FLAG_SOLICITED (0x40) -#define ND6_FLAG_OVERRIDE (0x20) - -/** Router solicitation message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct rs_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Router advertisement message header. */ -#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) -#define ND6_RA_FLAG_OTHER_CONFIG (0x40) -#define ND6_RA_FLAG_HOME_AGENT (0x20) -#define ND6_RA_PREFERENCE_MASK (0x18) -#define ND6_RA_PREFERENCE_HIGH (0x08) -#define ND6_RA_PREFERENCE_MEDIUM (0x00) -#define ND6_RA_PREFERENCE_LOW (0x18) -#define ND6_RA_PREFERENCE_DISABLED (0x10) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct ra_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FLD_8(u8_t current_hop_limit); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FIELD(u16_t router_lifetime); - PACK_STRUCT_FIELD(u32_t reachable_time); - PACK_STRUCT_FIELD(u32_t retrans_timer); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Redirect message header. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct redirect_header { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u32_t reserved); - PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); - PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); - /* Options follow. */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Link-layer address option. */ -#define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) -#define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct lladdr_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Prefix information option. */ -#define ND6_OPTION_TYPE_PREFIX_INFO (0x03) -#define ND6_PREFIX_FLAG_ON_LINK (0x80) -#define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) -#define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) -#define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct prefix_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t prefix_length); - PACK_STRUCT_FLD_8(u8_t flags); - PACK_STRUCT_FIELD(u32_t valid_lifetime); - PACK_STRUCT_FIELD(u32_t preferred_lifetime); - PACK_STRUCT_FLD_8(u8_t reserved2[3]); - PACK_STRUCT_FLD_8(u8_t site_prefix_length); - PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Redirected header option. */ -#define ND6_OPTION_TYPE_REDIR_HDR (0x04) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct redirected_header_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t reserved[6]); - /* Portion of redirected packet follows. */ - /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** MTU option. */ -#define ND6_OPTION_TYPE_MTU (0x05) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct mtu_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FIELD(u32_t mtu); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Route information option. */ -#define ND6_OPTION_TYPE_ROUTE_INFO (24) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct route_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FLD_8(u8_t prefix_length); - PACK_STRUCT_FLD_8(u8_t preference); - PACK_STRUCT_FIELD(u32_t route_lifetime); - PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** Recursive DNS Server Option. */ -#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS -#define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS -#else -#define LWIP_RDNSS_OPTION_MAX_SERVERS 1 -#endif -#define ND6_OPTION_TYPE_RDNSS (25) -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct rdnss_option { - PACK_STRUCT_FLD_8(u8_t type); - PACK_STRUCT_FLD_8(u8_t length); - PACK_STRUCT_FIELD(u16_t reserved); - PACK_STRUCT_FIELD(u32_t lifetime); - PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_ND6_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/tcp.h b/components/net/lwip-2.0.2/src/include/lwip/prot/tcp.h deleted file mode 100644 index 67fe7b9e5f..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/tcp.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file - * TCP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_TCP_H -#define LWIP_HDR_PROT_TCP_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Length of the TCP header, excluding options. */ -#define TCP_HLEN 20 - -/* Fields are (of course) in network byte order. - * Some fields are converted to host byte order in tcp_input(). - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct tcp_hdr { - PACK_STRUCT_FIELD(u16_t src); - PACK_STRUCT_FIELD(u16_t dest); - PACK_STRUCT_FIELD(u32_t seqno); - PACK_STRUCT_FIELD(u32_t ackno); - PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); - PACK_STRUCT_FIELD(u16_t wnd); - PACK_STRUCT_FIELD(u16_t chksum); - PACK_STRUCT_FIELD(u16_t urgp); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* TCP header flags bits */ -#define TCP_FIN 0x01U -#define TCP_SYN 0x02U -#define TCP_RST 0x04U -#define TCP_PSH 0x08U -#define TCP_ACK 0x10U -#define TCP_URG 0x20U -#define TCP_ECE 0x40U -#define TCP_CWR 0x80U -/* Valid TCP header flags */ -#define TCP_FLAGS 0x3fU - -#define TCPH_HDRLEN(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) -#define TCPH_FLAGS(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) - -#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr)) -#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags)) -#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags))) - -#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags)) -#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags)) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_TCP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/prot/udp.h b/components/net/lwip-2.0.2/src/include/lwip/prot/udp.h deleted file mode 100644 index 664f19a3e7..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/prot/udp.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file - * UDP protocol definitions - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_PROT_UDP_H -#define LWIP_HDR_PROT_UDP_H - -#include "lwip/arch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UDP_HLEN 8 - -/* Fields are (of course) in network byte order. */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct udp_hdr { - PACK_STRUCT_FIELD(u16_t src); - PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ - PACK_STRUCT_FIELD(u16_t len); - PACK_STRUCT_FIELD(u16_t chksum); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_PROT_UDP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/raw.h b/components/net/lwip-2.0.2/src/include/lwip/raw.h deleted file mode 100644 index 30aa147109..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/raw.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * raw API (to be used from TCPIP thread)\n - * See also @ref raw_raw - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_RAW_H -#define LWIP_HDR_RAW_H - -#include "lwip/opt.h" - -#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/def.h" -#include "lwip/ip.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct raw_pcb; - -/** Function prototype for raw pcb receive callback functions. - * @param arg user supplied argument (raw_pcb.recv_arg) - * @param pcb the raw_pcb which received data - * @param p the packet buffer that was received - * @param addr the remote IP address from which the packet was received - * @return 1 if the packet was 'eaten' (aka. deleted), - * 0 if the packet lives on - * If returning 1, the callback is responsible for freeing the pbuf - * if it's not used any more. - */ -typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr); - -/** the RAW protocol control block */ -struct raw_pcb { - /* Common members of all PCB types */ - IP_PCB; - - struct raw_pcb *next; - - u8_t protocol; - - /** receive callback function */ - raw_recv_fn recv; - /* user-supplied argument for the recv callback */ - void *recv_arg; -#if LWIP_IPV6 - /* fields for handling checksum computations as per RFC3542. */ - u16_t chksum_offset; - u8_t chksum_reqd; -#endif -}; - -/* The following functions is the application layer interface to the - RAW code. */ -struct raw_pcb * raw_new (u8_t proto); -struct raw_pcb * raw_new_ip_type(u8_t type, u8_t proto); -void raw_remove (struct raw_pcb *pcb); -err_t raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr); -err_t raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr); - -err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); -err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); - -void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); - -/* The following functions are the lower layer interface to RAW. */ -u8_t raw_input (struct pbuf *p, struct netif *inp); -#define raw_init() /* Compatibility define, no init needed. */ - -void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - -/* for compatibility with older implementation */ -#define raw_new_ip6(proto) raw_new_ip_type(IPADDR_TYPE_V6, proto) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_RAW */ - -#endif /* LWIP_HDR_RAW_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/sio.h b/components/net/lwip-2.0.2/src/include/lwip/sio.h deleted file mode 100644 index 7643e19569..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/sio.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - */ - -/* - * This is the interface to the platform specific serial IO module - * It needs to be implemented by those platforms which need SLIP or PPP - */ - -#ifndef SIO_H -#define SIO_H - -#include "lwip/arch.h" -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* If you want to define sio_fd_t elsewhere or differently, - define this in your cc.h file. */ -#ifndef __sio_fd_t_defined -typedef void * sio_fd_t; -#endif - -/* The following functions can be defined to something else in your cc.h file - or be implemented in your custom sio.c file. */ - -#ifndef sio_open -/** - * Opens a serial device for communication. - * - * @param devnum device number - * @return handle to serial device if successful, NULL otherwise - */ -sio_fd_t sio_open(u8_t devnum); -#endif - -#ifndef sio_send -/** - * Sends a single character to the serial device. - * - * @param c character to send - * @param fd serial device handle - * - * @note This function will block until the character can be sent. - */ -void sio_send(u8_t c, sio_fd_t fd); -#endif - -#ifndef sio_recv -/** - * Receives a single character from the serial device. - * - * @param fd serial device handle - * - * @note This function will block until a character is received. - */ -u8_t sio_recv(sio_fd_t fd); -#endif - -#ifndef sio_read -/** - * Reads from the serial device. - * - * @param fd serial device handle - * @param data pointer to data buffer for receiving - * @param len maximum length (in bytes) of data to receive - * @return number of bytes actually received - may be 0 if aborted by sio_read_abort - * - * @note This function will block until data can be received. The blocking - * can be cancelled by calling sio_read_abort(). - */ -u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len); -#endif - -#ifndef sio_tryread -/** - * Tries to read from the serial device. Same as sio_read but returns - * immediately if no data is available and never blocks. - * - * @param fd serial device handle - * @param data pointer to data buffer for receiving - * @param len maximum length (in bytes) of data to receive - * @return number of bytes actually received - */ -u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len); -#endif - -#ifndef sio_write -/** - * Writes to the serial device. - * - * @param fd serial device handle - * @param data pointer to data to send - * @param len length (in bytes) of data to send - * @return number of bytes actually sent - * - * @note This function will block until all data can be sent. - */ -u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len); -#endif - -#ifndef sio_read_abort -/** - * Aborts a blocking sio_read() call. - * - * @param fd serial device handle - */ -void sio_read_abort(sio_fd_t fd); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* SIO_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/snmp.h b/components/net/lwip-2.0.2/src/include/lwip/snmp.h deleted file mode 100644 index 8704d0b4d2..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/snmp.h +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file - * SNMP support API for implementing netifs and statitics for MIB2 - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Dirk Ziegelmeier - * - */ -#ifndef LWIP_HDR_SNMP_H -#define LWIP_HDR_SNMP_H - -#include "lwip/opt.h" -#include "lwip/ip_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct udp_pcb; -struct netif; - -/** - * @defgroup netif_mib2 MIB2 statistics - * @ingroup netif - */ - -/* MIB2 statistics functions */ -#if MIB2_STATS /* don't build if not configured for use in lwipopts.h */ -/** - * @ingroup netif_mib2 - * @see RFC1213, "MIB-II, 6. Definitions" - */ -enum snmp_ifType { - snmp_ifType_other=1, /* none of the following */ - snmp_ifType_regular1822, - snmp_ifType_hdh1822, - snmp_ifType_ddn_x25, - snmp_ifType_rfc877_x25, - snmp_ifType_ethernet_csmacd, - snmp_ifType_iso88023_csmacd, - snmp_ifType_iso88024_tokenBus, - snmp_ifType_iso88025_tokenRing, - snmp_ifType_iso88026_man, - snmp_ifType_starLan, - snmp_ifType_proteon_10Mbit, - snmp_ifType_proteon_80Mbit, - snmp_ifType_hyperchannel, - snmp_ifType_fddi, - snmp_ifType_lapb, - snmp_ifType_sdlc, - snmp_ifType_ds1, /* T-1 */ - snmp_ifType_e1, /* european equiv. of T-1 */ - snmp_ifType_basicISDN, - snmp_ifType_primaryISDN, /* proprietary serial */ - snmp_ifType_propPointToPointSerial, - snmp_ifType_ppp, - snmp_ifType_softwareLoopback, - snmp_ifType_eon, /* CLNP over IP [11] */ - snmp_ifType_ethernet_3Mbit, - snmp_ifType_nsip, /* XNS over IP */ - snmp_ifType_slip, /* generic SLIP */ - snmp_ifType_ultra, /* ULTRA technologies */ - snmp_ifType_ds3, /* T-3 */ - snmp_ifType_sip, /* SMDS */ - snmp_ifType_frame_relay -}; - -/** This macro has a precision of ~49 days because sys_now returns u32_t. \#define your own if you want ~490 days. */ -#ifndef MIB2_COPY_SYSUPTIME_TO -#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) (*(ptrToVal) = (sys_now() / 10)) -#endif - -/** - * @ingroup netif_mib2 - * Increment stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) - */ -#define MIB2_STATS_NETIF_INC(n, x) do { ++(n)->mib2_counters.x; } while(0) -/** - * @ingroup netif_mib2 - * Add value to stats member for SNMP MIB2 stats (struct stats_mib2_netif_ctrs) - */ -#define MIB2_STATS_NETIF_ADD(n, x, val) do { (n)->mib2_counters.x += (val); } while(0) - -/** - * @ingroup netif_mib2 - * Init MIB2 statistic counters in netif - * @param netif Netif to init - * @param type one of enum @ref snmp_ifType - * @param speed your link speed here (units: bits per second) - */ -#define MIB2_INIT_NETIF(netif, type, speed) do { \ - (netif)->link_type = (type); \ - (netif)->link_speed = (speed);\ - (netif)->ts = 0; \ - (netif)->mib2_counters.ifinoctets = 0; \ - (netif)->mib2_counters.ifinucastpkts = 0; \ - (netif)->mib2_counters.ifinnucastpkts = 0; \ - (netif)->mib2_counters.ifindiscards = 0; \ - (netif)->mib2_counters.ifinerrors = 0; \ - (netif)->mib2_counters.ifinunknownprotos = 0; \ - (netif)->mib2_counters.ifoutoctets = 0; \ - (netif)->mib2_counters.ifoutucastpkts = 0; \ - (netif)->mib2_counters.ifoutnucastpkts = 0; \ - (netif)->mib2_counters.ifoutdiscards = 0; \ - (netif)->mib2_counters.ifouterrors = 0; } while(0) -#else /* MIB2_STATS */ -#ifndef MIB2_COPY_SYSUPTIME_TO -#define MIB2_COPY_SYSUPTIME_TO(ptrToVal) -#endif -#define MIB2_INIT_NETIF(netif, type, speed) -#define MIB2_STATS_NETIF_INC(n, x) -#define MIB2_STATS_NETIF_ADD(n, x, val) -#endif /* MIB2_STATS */ - -/* LWIP MIB2 callbacks */ -#if LWIP_MIB2_CALLBACKS /* don't build if not configured for use in lwipopts.h */ -/* network interface */ -void mib2_netif_added(struct netif *ni); -void mib2_netif_removed(struct netif *ni); - -#if LWIP_IPV4 && LWIP_ARP -/* ARP (for atTable and ipNetToMediaTable) */ -void mib2_add_arp_entry(struct netif *ni, ip4_addr_t *ip); -void mib2_remove_arp_entry(struct netif *ni, ip4_addr_t *ip); -#else /* LWIP_IPV4 && LWIP_ARP */ -#define mib2_add_arp_entry(ni,ip) -#define mib2_remove_arp_entry(ni,ip) -#endif /* LWIP_IPV4 && LWIP_ARP */ - -/* IP */ -#if LWIP_IPV4 -void mib2_add_ip4(struct netif *ni); -void mib2_remove_ip4(struct netif *ni); -void mib2_add_route_ip4(u8_t dflt, struct netif *ni); -void mib2_remove_route_ip4(u8_t dflt, struct netif *ni); -#endif /* LWIP_IPV4 */ - -/* UDP */ -#if LWIP_UDP -void mib2_udp_bind(struct udp_pcb *pcb); -void mib2_udp_unbind(struct udp_pcb *pcb); -#endif /* LWIP_UDP */ - -#else /* LWIP_MIB2_CALLBACKS */ -/* LWIP_MIB2_CALLBACKS support not available */ -/* define everything to be empty */ - -/* network interface */ -#define mib2_netif_added(ni) -#define mib2_netif_removed(ni) - -/* ARP */ -#define mib2_add_arp_entry(ni,ip) -#define mib2_remove_arp_entry(ni,ip) - -/* IP */ -#define mib2_add_ip4(ni) -#define mib2_remove_ip4(ni) -#define mib2_add_route_ip4(dflt, ni) -#define mib2_remove_route_ip4(dflt, ni) - -/* UDP */ -#define mib2_udp_bind(pcb) -#define mib2_udp_unbind(pcb) -#endif /* LWIP_MIB2_CALLBACKS */ - -/* for source-code compatibility reasons only, can be removed (not used internally) */ -#define NETIF_INIT_SNMP MIB2_INIT_NETIF -#define snmp_add_ifinoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifinoctets, value) -#define snmp_inc_ifinucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinucastpkts) -#define snmp_inc_ifinnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifinnucastpkts) -#define snmp_inc_ifindiscards(ni) MIB2_STATS_NETIF_INC(ni, ifindiscards) -#define snmp_inc_ifinerrors(ni) MIB2_STATS_NETIF_INC(ni, ifinerrors) -#define snmp_inc_ifinunknownprotos(ni) MIB2_STATS_NETIF_INC(ni, ifinunknownprotos) -#define snmp_add_ifoutoctets(ni,value) MIB2_STATS_NETIF_ADD(ni, ifoutoctets, value) -#define snmp_inc_ifoutucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutucastpkts) -#define snmp_inc_ifoutnucastpkts(ni) MIB2_STATS_NETIF_INC(ni, ifoutnucastpkts) -#define snmp_inc_ifoutdiscards(ni) MIB2_STATS_NETIF_INC(ni, ifoutdiscards) -#define snmp_inc_ifouterrors(ni) MIB2_STATS_NETIF_INC(ni, ifouterrors) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_SNMP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/sockets.h b/components/net/lwip-2.0.2/src/include/lwip/sockets.h deleted file mode 100644 index 2522056dba..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/sockets.h +++ /dev/null @@ -1,593 +0,0 @@ -/** - * @file - * Socket API (to be used from non-TCPIP threads) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - - -#ifndef LWIP_HDR_SOCKETS_H -#define LWIP_HDR_SOCKETS_H - -#include "lwip/opt.h" - -#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/ip_addr.h" -#include "lwip/err.h" -#include "lwip/inet.h" -#include "lwip/errno.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) -typedef u8_t sa_family_t; -#endif -/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) -typedef u16_t in_port_t; -#endif - -#if LWIP_IPV4 -/* members are in network byte order */ -struct sockaddr_in { - u8_t sin_len; - sa_family_t sin_family; - in_port_t sin_port; - struct in_addr sin_addr; -#define SIN_ZERO_LEN 8 - char sin_zero[SIN_ZERO_LEN]; -}; -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -struct sockaddr_in6 { - u8_t sin6_len; /* length of this structure */ - sa_family_t sin6_family; /* AF_INET6 */ - in_port_t sin6_port; /* Transport layer port # */ - u32_t sin6_flowinfo; /* IPv6 flow information */ - struct in6_addr sin6_addr; /* IPv6 address */ - u32_t sin6_scope_id; /* Set of interfaces for scope */ -}; -#endif /* LWIP_IPV6 */ - -struct sockaddr { - u8_t sa_len; - sa_family_t sa_family; - char sa_data[14]; -}; - -struct sockaddr_storage { - u8_t s2_len; - sa_family_t ss_family; - char s2_data1[2]; - u32_t s2_data2[3]; -#if LWIP_IPV6 - u32_t s2_data3[3]; -#endif /* LWIP_IPV6 */ -}; - -/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED - to prevent this code from redefining it. */ -#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) -typedef u32_t socklen_t; -#endif - -struct lwip_sock; - -#if !LWIP_TCPIP_CORE_LOCKING -/** Maximum optlen used by setsockopt/getsockopt */ -#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 - -/** This struct is used to pass data to the set/getsockopt_internal - * functions running in tcpip_thread context (only a void* is allowed) */ -struct lwip_setgetsockopt_data { - /** socket index for which to change options */ - int s; - /** level of the option to process */ - int level; - /** name of the option to process */ - int optname; - /** set: value to set the option to - * get: value of the option is stored here */ -#if LWIP_MPU_COMPATIBLE - u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; -#else - union { - void *p; - const void *pc; - } optval; -#endif - /** size of *optval */ - socklen_t optlen; - /** if an error occurs, it is temporarily stored here */ - err_t err; - /** semaphore to wake up the calling task */ - void* completed_sem; -}; -#endif /* !LWIP_TCPIP_CORE_LOCKING */ - -#if !defined(iovec) -struct iovec { - void *iov_base; - size_t iov_len; -}; -#endif - -struct msghdr { - void *msg_name; - socklen_t msg_namelen; - struct iovec *msg_iov; - int msg_iovlen; - void *msg_control; - socklen_t msg_controllen; - int msg_flags; -}; - -/* Socket protocol types (TCP/UDP/RAW) */ -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 - -/* - * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) - */ -#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ -#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ - - -/* - * Additional options, not kept in so_options. - */ -#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ -#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ -#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ -#define SO_LINGER 0x0080 /* linger on close if data present */ -#define SO_DONTLINGER ((int)(~SO_LINGER)) -#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ -#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ -#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ -#define SO_RCVBUF 0x1002 /* receive buffer size */ -#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ -#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ -#define SO_SNDTIMEO 0x1005 /* send timeout */ -#define SO_RCVTIMEO 0x1006 /* receive timeout */ -#define SO_ERROR 0x1007 /* get error status and clear */ -#define SO_TYPE 0x1008 /* get socket type */ -#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ -#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ - - -/* - * Structure used for manipulating linger option. - */ -struct linger { - int l_onoff; /* option on/off */ - int l_linger; /* linger time in seconds */ -}; - -/* - * Level number for (get/set)sockopt() to apply to socket itself. - */ -#define SOL_SOCKET 0xfff /* options for socket level */ - - -#define AF_UNSPEC 0 -#define AF_INET 2 -#if LWIP_IPV6 -#define AF_INET6 10 -#else /* LWIP_IPV6 */ -#define AF_INET6 AF_UNSPEC -#endif /* LWIP_IPV6 */ -#define PF_INET AF_INET -#define PF_INET6 AF_INET6 -#define PF_UNSPEC AF_UNSPEC - -#define IPPROTO_IP 0 -#define IPPROTO_ICMP 1 -#define IPPROTO_TCP 6 -#define IPPROTO_UDP 17 -#if LWIP_IPV6 -#define IPPROTO_IPV6 41 -#define IPPROTO_ICMPV6 58 -#endif /* LWIP_IPV6 */ -#define IPPROTO_UDPLITE 136 -#define IPPROTO_RAW 255 - -/* Flags we can use with send and recv. */ -#define MSG_PEEK 0x01 /* Peeks at an incoming message */ -#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ -#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ -#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ -#define MSG_MORE 0x10 /* Sender will send more */ - - -/* - * Options for level IPPROTO_IP - */ -#define IP_TOS 1 -#define IP_TTL 2 - -#if LWIP_TCP -/* - * Options for level IPPROTO_TCP - */ -#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ -#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ -#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ -#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ -#endif /* LWIP_TCP */ - -#if LWIP_IPV6 -/* - * Options for level IPPROTO_IPV6 - */ -#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ -#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ -#endif /* LWIP_IPV6 */ - -#if LWIP_UDP && LWIP_UDPLITE -/* - * Options for level IPPROTO_UDPLITE - */ -#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ -#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ -#endif /* LWIP_UDP && LWIP_UDPLITE*/ - - -#if LWIP_MULTICAST_TX_OPTIONS -/* - * Options and types for UDP multicast traffic handling - */ -#define IP_MULTICAST_TTL 5 -#define IP_MULTICAST_IF 6 -#define IP_MULTICAST_LOOP 7 -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#if LWIP_IGMP -/* - * Options and types related to multicast membership - */ -#define IP_ADD_MEMBERSHIP 3 -#define IP_DROP_MEMBERSHIP 4 - -typedef struct ip_mreq { - struct in_addr imr_multiaddr; /* IP multicast address of group */ - struct in_addr imr_interface; /* local IP address of interface */ -} ip_mreq; -#endif /* LWIP_IGMP */ - -/* - * The Type of Service provides an indication of the abstract - * parameters of the quality of service desired. These parameters are - * to be used to guide the selection of the actual service parameters - * when transmitting a datagram through a particular network. Several - * networks offer service precedence, which somehow treats high - * precedence traffic as more important than other traffic (generally - * by accepting only traffic above a certain precedence at time of high - * load). The major choice is a three way tradeoff between low-delay, - * high-reliability, and high-throughput. - * The use of the Delay, Throughput, and Reliability indications may - * increase the cost (in some sense) of the service. In many networks - * better performance for one of these parameters is coupled with worse - * performance on another. Except for very unusual cases at most two - * of these three indications should be set. - */ -#define IPTOS_TOS_MASK 0x1E -#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) -#define IPTOS_LOWDELAY 0x10 -#define IPTOS_THROUGHPUT 0x08 -#define IPTOS_RELIABILITY 0x04 -#define IPTOS_LOWCOST 0x02 -#define IPTOS_MINCOST IPTOS_LOWCOST - -/* - * The Network Control precedence designation is intended to be used - * within a network only. The actual use and control of that - * designation is up to each network. The Internetwork Control - * designation is intended for use by gateway control originators only. - * If the actual use of these precedence designations is of concern to - * a particular network, it is the responsibility of that network to - * control the access to, and use of, those precedence designations. - */ -#define IPTOS_PREC_MASK 0xe0 -#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) -#define IPTOS_PREC_NETCONTROL 0xe0 -#define IPTOS_PREC_INTERNETCONTROL 0xc0 -#define IPTOS_PREC_CRITIC_ECP 0xa0 -#define IPTOS_PREC_FLASHOVERRIDE 0x80 -#define IPTOS_PREC_FLASH 0x60 -#define IPTOS_PREC_IMMEDIATE 0x40 -#define IPTOS_PREC_PRIORITY 0x20 -#define IPTOS_PREC_ROUTINE 0x00 - - -/* - * Commands for ioctlsocket(), taken from the BSD file fcntl.h. - * lwip_ioctl only supports FIONREAD and FIONBIO, for now - * - * Ioctl's have the command encoded in the lower word, - * and the size of any in or out parameters in the upper - * word. The high 2 bits of the upper word are used - * to encode the in/out status of the parameter; for now - * we restrict parameters to at most 128 bytes. - */ -#if !defined(FIONREAD) || !defined(FIONBIO) -#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ -#define IOC_VOID 0x20000000UL /* no parameters */ -#define IOC_OUT 0x40000000UL /* copy out parameters */ -#define IOC_IN 0x80000000UL /* copy in parameters */ -#define IOC_INOUT (IOC_IN|IOC_OUT) - /* 0x20000000 distinguishes new & - old ioctl's */ -#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) - -#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) - -#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ - -#ifndef FIONREAD -#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ -#endif -#ifndef FIONBIO -#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ -#endif - -/* Socket I/O Controls: unimplemented */ -#ifndef SIOCSHIWAT -#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ -#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ -#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ -#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ -#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ -#endif - -/* commands for fnctl */ -#ifndef F_GETFL -#define F_GETFL 3 -#endif -#ifndef F_SETFL -#define F_SETFL 4 -#endif - -/* File status flags and file access modes for fnctl, - these are bits in an int. */ -#ifndef O_NONBLOCK -#define O_NONBLOCK 1 /* nonblocking I/O */ -#endif -#ifndef O_NDELAY -#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ -#endif - -#ifndef SHUT_RD - #define SHUT_RD 0 - #define SHUT_WR 1 - #define SHUT_RDWR 2 -#endif - -/* FD_SET used for lwip_select */ -#ifndef FD_SET -#undef FD_SETSIZE -/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ -#define FD_SETSIZE MEMP_NUM_NETCONN -#define FDSETSAFESET(n, code) do { \ - if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ - code; }} while(0) -#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ - (code) : 0) -#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) - -typedef struct fd_set -{ - unsigned char fd_bits [(FD_SETSIZE+7)/8]; -} fd_set; - -#elif LWIP_SOCKET_OFFSET -#error LWIP_SOCKET_OFFSET does not work with external FD_SET! -#elif FD_SETSIZE < MEMP_NUM_NETCONN -#error "external FD_SETSIZE too small for number of sockets" -#endif /* FD_SET */ - -/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided - * by your system, set this to 0 and include in cc.h */ -#ifndef LWIP_TIMEVAL_PRIVATE -#define LWIP_TIMEVAL_PRIVATE 1 -#endif - -#if LWIP_TIMEVAL_PRIVATE -struct timeval { - long tv_sec; /* seconds */ - long tv_usec; /* and microseconds */ -}; -#endif /* LWIP_TIMEVAL_PRIVATE */ - -#define lwip_socket_init() /* Compatibility define, no init needed. */ -void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ -void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ - -#if LWIP_COMPAT_SOCKETS == 2 -/* This helps code parsers/code completion by not having the COMPAT functions as defines */ -#define lwip_accept accept -#define lwip_bind bind -#define lwip_shutdown shutdown -#define lwip_getpeername getpeername -#define lwip_getsockname getsockname -#define lwip_setsockopt setsockopt -#define lwip_getsockopt getsockopt -#define lwip_close closesocket -#define lwip_connect connect -#define lwip_listen listen -#define lwip_recv recv -#define lwip_recvfrom recvfrom -#define lwip_send send -#define lwip_sendmsg sendmsg -#define lwip_sendto sendto -#define lwip_socket socket -#define lwip_select select -#define lwip_ioctlsocket ioctl - -#if LWIP_POSIX_SOCKETS_IO_NAMES -#define lwip_read read -#define lwip_write write -#define lwip_writev writev -#undef lwip_close -#define lwip_close close -#define closesocket(s) close(s) -#define lwip_fcntl fcntl -#define lwip_ioctl ioctl -#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -#endif /* LWIP_COMPAT_SOCKETS == 2 */ - -int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); -int lwip_shutdown(int s, int how); -int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); -int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); -int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); -int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); -int lwip_close(int s); -int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); -int lwip_listen(int s, int backlog); -int lwip_recv(int s, void *mem, size_t len, int flags); -int lwip_read(int s, void *mem, size_t len); -int lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); -int lwip_send(int s, const void *dataptr, size_t size, int flags); -int lwip_sendmsg(int s, const struct msghdr *message, int flags); -int lwip_sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen); -int lwip_socket(int domain, int type, int protocol); -int lwip_write(int s, const void *dataptr, size_t size); -int lwip_writev(int s, const struct iovec *iov, int iovcnt); -int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout); -int lwip_ioctl(int s, long cmd, void *argp); -int lwip_fcntl(int s, int cmd, int val); - -#if LWIP_COMPAT_SOCKETS -#if LWIP_COMPAT_SOCKETS != 2 -/** @ingroup socket */ -#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) -/** @ingroup socket */ -#define bind(s,name,namelen) lwip_bind(s,name,namelen) -/** @ingroup socket */ -#define shutdown(s,how) lwip_shutdown(s,how) -/** @ingroup socket */ -#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) -/** @ingroup socket */ -#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) -/** @ingroup socket */ -#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) -/** @ingroup socket */ -#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) -/** @ingroup socket */ -#define closesocket(s) lwip_close(s) -/** @ingroup socket */ -#define connect(s,name,namelen) lwip_connect(s,name,namelen) -/** @ingroup socket */ -#define listen(s,backlog) lwip_listen(s,backlog) -/** @ingroup socket */ -#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) -/** @ingroup socket */ -#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) -/** @ingroup socket */ -#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) -/** @ingroup socket */ -#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) -/** @ingroup socket */ -#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) -/** @ingroup socket */ -#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) -/** @ingroup socket */ -#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -/** @ingroup socket */ -#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) - -#if LWIP_POSIX_SOCKETS_IO_NAMES -/** @ingroup socket */ -#define read(s,mem,len) lwip_read(s,mem,len) -/** @ingroup socket */ -#define write(s,dataptr,len) lwip_write(s,dataptr,len) -/** @ingroup socket */ -#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) -/** @ingroup socket */ -#define close(s) lwip_close(s) -/** @ingroup socket */ -#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) -/** @ingroup socket */ -#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) -#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -#endif /* LWIP_COMPAT_SOCKETS != 2 */ - -#if LWIP_IPV4 && LWIP_IPV6 -/** @ingroup socket */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ - : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) -/** @ingroup socket */ -#define inet_pton(af,src,dst) \ - (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ - : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) -#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) -#define inet_pton(af,src,dst) \ - (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) -#else /* LWIP_IPV4 && LWIP_IPV6 */ -#define inet_ntop(af,src,dst,size) \ - (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) -#define inet_pton(af,src,dst) \ - (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) -#endif /* LWIP_IPV4 && LWIP_IPV6 */ - -#endif /* LWIP_COMPAT_SOCKETS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SOCKET */ - -#endif /* LWIP_HDR_SOCKETS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/stats.h b/components/net/lwip-2.0.2/src/include/lwip/stats.h deleted file mode 100644 index bcda2ace6e..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/stats.h +++ /dev/null @@ -1,491 +0,0 @@ -/** - * @file - * Statistics API (to be used from TCPIP thread) - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_STATS_H -#define LWIP_HDR_STATS_H - -#include "lwip/opt.h" - -#include "lwip/mem.h" -#include "lwip/memp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_STATS - -#ifndef LWIP_STATS_LARGE -#define LWIP_STATS_LARGE 0 -#endif - -#if LWIP_STATS_LARGE -#define STAT_COUNTER u32_t -#define STAT_COUNTER_F U32_F -#else -#define STAT_COUNTER u16_t -#define STAT_COUNTER_F U16_F -#endif - -/** Protocol related stats */ -struct stats_proto { - STAT_COUNTER xmit; /* Transmitted packets. */ - STAT_COUNTER recv; /* Received packets. */ - STAT_COUNTER fw; /* Forwarded packets. */ - STAT_COUNTER drop; /* Dropped packets. */ - STAT_COUNTER chkerr; /* Checksum error. */ - STAT_COUNTER lenerr; /* Invalid length error. */ - STAT_COUNTER memerr; /* Out of memory error. */ - STAT_COUNTER rterr; /* Routing error. */ - STAT_COUNTER proterr; /* Protocol error. */ - STAT_COUNTER opterr; /* Error in options. */ - STAT_COUNTER err; /* Misc error. */ - STAT_COUNTER cachehit; -}; - -/** IGMP stats */ -struct stats_igmp { - STAT_COUNTER xmit; /* Transmitted packets. */ - STAT_COUNTER recv; /* Received packets. */ - STAT_COUNTER drop; /* Dropped packets. */ - STAT_COUNTER chkerr; /* Checksum error. */ - STAT_COUNTER lenerr; /* Invalid length error. */ - STAT_COUNTER memerr; /* Out of memory error. */ - STAT_COUNTER proterr; /* Protocol error. */ - STAT_COUNTER rx_v1; /* Received v1 frames. */ - STAT_COUNTER rx_group; /* Received group-specific queries. */ - STAT_COUNTER rx_general; /* Received general queries. */ - STAT_COUNTER rx_report; /* Received reports. */ - STAT_COUNTER tx_join; /* Sent joins. */ - STAT_COUNTER tx_leave; /* Sent leaves. */ - STAT_COUNTER tx_report; /* Sent reports. */ -}; - -/** Memory stats */ -struct stats_mem { -#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY - const char *name; -#endif /* defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY */ - STAT_COUNTER err; - mem_size_t avail; - mem_size_t used; - mem_size_t max; - STAT_COUNTER illegal; -}; - -/** System element stats */ -struct stats_syselem { - STAT_COUNTER used; - STAT_COUNTER max; - STAT_COUNTER err; -}; - -/** System stats */ -struct stats_sys { - struct stats_syselem sem; - struct stats_syselem mutex; - struct stats_syselem mbox; -}; - -/** SNMP MIB2 stats */ -struct stats_mib2 { - /* IP */ - u32_t ipinhdrerrors; - u32_t ipinaddrerrors; - u32_t ipinunknownprotos; - u32_t ipindiscards; - u32_t ipindelivers; - u32_t ipoutrequests; - u32_t ipoutdiscards; - u32_t ipoutnoroutes; - u32_t ipreasmoks; - u32_t ipreasmfails; - u32_t ipfragoks; - u32_t ipfragfails; - u32_t ipfragcreates; - u32_t ipreasmreqds; - u32_t ipforwdatagrams; - u32_t ipinreceives; - - /* TCP */ - u32_t tcpactiveopens; - u32_t tcppassiveopens; - u32_t tcpattemptfails; - u32_t tcpestabresets; - u32_t tcpoutsegs; - u32_t tcpretranssegs; - u32_t tcpinsegs; - u32_t tcpinerrs; - u32_t tcpoutrsts; - - /* UDP */ - u32_t udpindatagrams; - u32_t udpnoports; - u32_t udpinerrors; - u32_t udpoutdatagrams; - - /* ICMP */ - u32_t icmpinmsgs; - u32_t icmpinerrors; - u32_t icmpindestunreachs; - u32_t icmpintimeexcds; - u32_t icmpinparmprobs; - u32_t icmpinsrcquenchs; - u32_t icmpinredirects; - u32_t icmpinechos; - u32_t icmpinechoreps; - u32_t icmpintimestamps; - u32_t icmpintimestampreps; - u32_t icmpinaddrmasks; - u32_t icmpinaddrmaskreps; - u32_t icmpoutmsgs; - u32_t icmpouterrors; - u32_t icmpoutdestunreachs; - u32_t icmpouttimeexcds; - u32_t icmpoutechos; /* can be incremented by user application ('ping') */ - u32_t icmpoutechoreps; -}; - -/** - * @ingroup netif_mib2 - * SNMP MIB2 interface stats - */ -struct stats_mib2_netif_ctrs { - /** The total number of octets received on the interface, including framing characters */ - u32_t ifinoctets; - /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were - * not addressed to a multicast or broadcast address at this sub-layer */ - u32_t ifinucastpkts; - /** The number of packets, delivered by this sub-layer to a higher (sub-)layer, which were - * addressed to a multicast or broadcast address at this sub-layer */ - u32_t ifinnucastpkts; - /** The number of inbound packets which were chosen to be discarded even though no errors had - * been detected to prevent their being deliverable to a higher-layer protocol. One possible - * reason for discarding such a packet could be to free up buffer space */ - u32_t ifindiscards; - /** For packet-oriented interfaces, the number of inbound packets that contained errors - * preventing them from being deliverable to a higher-layer protocol. For character- - * oriented or fixed-length interfaces, the number of inbound transmission units that - * contained errors preventing them from being deliverable to a higher-layer protocol. */ - u32_t ifinerrors; - /** For packet-oriented interfaces, the number of packets received via the interface which - * were discarded because of an unknown or unsupported protocol. For character-oriented - * or fixed-length interfaces that support protocol multiplexing the number of transmission - * units received via the interface which were discarded because of an unknown or unsupported - * protocol. For any interface that does not support protocol multiplexing, this counter will - * always be 0 */ - u32_t ifinunknownprotos; - /** The total number of octets transmitted out of the interface, including framing characters. */ - u32_t ifoutoctets; - /** The total number of packets that higher-level protocols requested be transmitted, and - * which were not addressed to a multicast or broadcast address at this sub-layer, including - * those that were discarded or not sent. */ - u32_t ifoutucastpkts; - /** The total number of packets that higher-level protocols requested be transmitted, and which - * were addressed to a multicast or broadcast address at this sub-layer, including - * those that were discarded or not sent. */ - u32_t ifoutnucastpkts; - /** The number of outbound packets which were chosen to be discarded even though no errors had - * been detected to prevent their being transmitted. One possible reason for discarding - * such a packet could be to free up buffer space. */ - u32_t ifoutdiscards; - /** For packet-oriented interfaces, the number of outbound packets that could not be transmitted - * because of errors. For character-oriented or fixed-length interfaces, the number of outbound - * transmission units that could not be transmitted because of errors. */ - u32_t ifouterrors; -}; - -/** lwIP stats container */ -struct stats_ { -#if LINK_STATS - /** Link level */ - struct stats_proto link; -#endif -#if ETHARP_STATS - /** ARP */ - struct stats_proto etharp; -#endif -#if IPFRAG_STATS - /** Fragmentation */ - struct stats_proto ip_frag; -#endif -#if IP_STATS - /** IP */ - struct stats_proto ip; -#endif -#if ICMP_STATS - /** ICMP */ - struct stats_proto icmp; -#endif -#if IGMP_STATS - /** IGMP */ - struct stats_igmp igmp; -#endif -#if UDP_STATS - /** UDP */ - struct stats_proto udp; -#endif -#if TCP_STATS - /** TCP */ - struct stats_proto tcp; -#endif -#if MEM_STATS - /** Heap */ - struct stats_mem mem; -#endif -#if MEMP_STATS - /** Internal memory pools */ - struct stats_mem *memp[MEMP_MAX]; -#endif -#if SYS_STATS - /** System */ - struct stats_sys sys; -#endif -#if IP6_STATS - /** IPv6 */ - struct stats_proto ip6; -#endif -#if ICMP6_STATS - /** ICMP6 */ - struct stats_proto icmp6; -#endif -#if IP6_FRAG_STATS - /** IPv6 fragmentation */ - struct stats_proto ip6_frag; -#endif -#if MLD6_STATS - /** Multicast listener discovery */ - struct stats_igmp mld6; -#endif -#if ND6_STATS - /** Neighbor discovery */ - struct stats_proto nd6; -#endif -#if MIB2_STATS - /** SNMP MIB2 */ - struct stats_mib2 mib2; -#endif -}; - -/** Global variable containing lwIP internal statistics. Add this to your debugger's watchlist. */ -extern struct stats_ lwip_stats; - -/** Init statistics */ -void stats_init(void); - -#define STATS_INC(x) ++lwip_stats.x -#define STATS_DEC(x) --lwip_stats.x -#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ - if (lwip_stats.x.max < lwip_stats.x.used) { \ - lwip_stats.x.max = lwip_stats.x.used; \ - } \ - } while(0) -#define STATS_GET(x) lwip_stats.x -#else /* LWIP_STATS */ -#define stats_init() -#define STATS_INC(x) -#define STATS_DEC(x) -#define STATS_INC_USED(x) -#endif /* LWIP_STATS */ - -#if TCP_STATS -#define TCP_STATS_INC(x) STATS_INC(x) -#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") -#else -#define TCP_STATS_INC(x) -#define TCP_STATS_DISPLAY() -#endif - -#if UDP_STATS -#define UDP_STATS_INC(x) STATS_INC(x) -#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") -#else -#define UDP_STATS_INC(x) -#define UDP_STATS_DISPLAY() -#endif - -#if ICMP_STATS -#define ICMP_STATS_INC(x) STATS_INC(x) -#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") -#else -#define ICMP_STATS_INC(x) -#define ICMP_STATS_DISPLAY() -#endif - -#if IGMP_STATS -#define IGMP_STATS_INC(x) STATS_INC(x) -#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp, "IGMP") -#else -#define IGMP_STATS_INC(x) -#define IGMP_STATS_DISPLAY() -#endif - -#if IP_STATS -#define IP_STATS_INC(x) STATS_INC(x) -#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") -#else -#define IP_STATS_INC(x) -#define IP_STATS_DISPLAY() -#endif - -#if IPFRAG_STATS -#define IPFRAG_STATS_INC(x) STATS_INC(x) -#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") -#else -#define IPFRAG_STATS_INC(x) -#define IPFRAG_STATS_DISPLAY() -#endif - -#if ETHARP_STATS -#define ETHARP_STATS_INC(x) STATS_INC(x) -#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") -#else -#define ETHARP_STATS_INC(x) -#define ETHARP_STATS_DISPLAY() -#endif - -#if LINK_STATS -#define LINK_STATS_INC(x) STATS_INC(x) -#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") -#else -#define LINK_STATS_INC(x) -#define LINK_STATS_DISPLAY() -#endif - -#if MEM_STATS -#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y -#define MEM_STATS_INC(x) STATS_INC(mem.x) -#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) -#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y -#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") -#else -#define MEM_STATS_AVAIL(x, y) -#define MEM_STATS_INC(x) -#define MEM_STATS_INC_USED(x, y) -#define MEM_STATS_DEC_USED(x, y) -#define MEM_STATS_DISPLAY() -#endif - - #if MEMP_STATS -#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i]->x) -#define MEMP_STATS_DISPLAY(i) stats_display_memp(lwip_stats.memp[i], i) -#define MEMP_STATS_GET(x, i) STATS_GET(memp[i]->x) - #else -#define MEMP_STATS_DEC(x, i) -#define MEMP_STATS_DISPLAY(i) -#define MEMP_STATS_GET(x, i) 0 -#endif - -#if SYS_STATS -#define SYS_STATS_INC(x) STATS_INC(sys.x) -#define SYS_STATS_DEC(x) STATS_DEC(sys.x) -#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) -#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) -#else -#define SYS_STATS_INC(x) -#define SYS_STATS_DEC(x) -#define SYS_STATS_INC_USED(x) -#define SYS_STATS_DISPLAY() -#endif - -#if IP6_STATS -#define IP6_STATS_INC(x) STATS_INC(x) -#define IP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6, "IPv6") -#else -#define IP6_STATS_INC(x) -#define IP6_STATS_DISPLAY() -#endif - -#if ICMP6_STATS -#define ICMP6_STATS_INC(x) STATS_INC(x) -#define ICMP6_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp6, "ICMPv6") -#else -#define ICMP6_STATS_INC(x) -#define ICMP6_STATS_DISPLAY() -#endif - -#if IP6_FRAG_STATS -#define IP6_FRAG_STATS_INC(x) STATS_INC(x) -#define IP6_FRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip6_frag, "IPv6 FRAG") -#else -#define IP6_FRAG_STATS_INC(x) -#define IP6_FRAG_STATS_DISPLAY() -#endif - -#if MLD6_STATS -#define MLD6_STATS_INC(x) STATS_INC(x) -#define MLD6_STATS_DISPLAY() stats_display_igmp(&lwip_stats.mld6, "MLDv1") -#else -#define MLD6_STATS_INC(x) -#define MLD6_STATS_DISPLAY() -#endif - -#if ND6_STATS -#define ND6_STATS_INC(x) STATS_INC(x) -#define ND6_STATS_DISPLAY() stats_display_proto(&lwip_stats.nd6, "ND") -#else -#define ND6_STATS_INC(x) -#define ND6_STATS_DISPLAY() -#endif - -#if MIB2_STATS -#define MIB2_STATS_INC(x) STATS_INC(x) -#else -#define MIB2_STATS_INC(x) -#endif - -/* Display of statistics */ -#if LWIP_STATS_DISPLAY -void stats_display(void); -void stats_display_proto(struct stats_proto *proto, const char *name); -void stats_display_igmp(struct stats_igmp *igmp, const char *name); -void stats_display_mem(struct stats_mem *mem, const char *name); -void stats_display_memp(struct stats_mem *mem, int index); -void stats_display_sys(struct stats_sys *sys); -#else /* LWIP_STATS_DISPLAY */ -#define stats_display() -#define stats_display_proto(proto, name) -#define stats_display_igmp(igmp, name) -#define stats_display_mem(mem, name) -#define stats_display_memp(mem, index) -#define stats_display_sys(sys) -#endif /* LWIP_STATS_DISPLAY */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_STATS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/sys.h b/components/net/lwip-2.0.2/src/include/lwip/sys.h deleted file mode 100644 index d12bae0f96..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/sys.h +++ /dev/null @@ -1,455 +0,0 @@ -/** - * @file - * OS abstraction layer - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - */ - -#ifndef LWIP_HDR_SYS_H -#define LWIP_HDR_SYS_H - -#include "lwip/opt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if NO_SYS - -/* For a totally minimal and standalone system, we provide null - definitions of the sys_ functions. */ -typedef u8_t sys_sem_t; -typedef u8_t sys_mutex_t; -typedef u8_t sys_mbox_t; - -#define sys_sem_new(s, c) ERR_OK -#define sys_sem_signal(s) -#define sys_sem_wait(s) -#define sys_arch_sem_wait(s,t) -#define sys_sem_free(s) -#define sys_sem_valid(s) 0 -#define sys_sem_valid_val(s) 0 -#define sys_sem_set_invalid(s) -#define sys_sem_set_invalid_val(s) -#define sys_mutex_new(mu) ERR_OK -#define sys_mutex_lock(mu) -#define sys_mutex_unlock(mu) -#define sys_mutex_free(mu) -#define sys_mutex_valid(mu) 0 -#define sys_mutex_set_invalid(mu) -#define sys_mbox_new(m, s) ERR_OK -#define sys_mbox_fetch(m,d) -#define sys_mbox_tryfetch(m,d) -#define sys_mbox_post(m,d) -#define sys_mbox_trypost(m,d) -#define sys_mbox_free(m) -#define sys_mbox_valid(m) -#define sys_mbox_valid_val(m) -#define sys_mbox_set_invalid(m) -#define sys_mbox_set_invalid_val(m) - -#define sys_thread_new(n,t,a,s,p) - -#define sys_msleep(t) - -#else /* NO_SYS */ - -/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ -#define SYS_ARCH_TIMEOUT 0xffffffffUL - -/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. - * For now we use the same magic value, but we allow this to change in future. - */ -#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT - -#include "lwip/err.h" -#include "arch/sys_arch.h" - -/** Function prototype for thread functions */ -typedef void (*lwip_thread_fn)(void *arg); - -/* Function prototypes for functions to be implemented by platform ports - (in sys_arch.c) */ - -/* Mutex functions: */ - -/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores - should be used instead */ -#ifndef LWIP_COMPAT_MUTEX -#define LWIP_COMPAT_MUTEX 0 -#endif - -#if LWIP_COMPAT_MUTEX -/* for old ports that don't have mutexes: define them to binary semaphores */ -#define sys_mutex_t sys_sem_t -#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) -#define sys_mutex_lock(mutex) sys_sem_wait(mutex) -#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) -#define sys_mutex_free(mutex) sys_sem_free(mutex) -#define sys_mutex_valid(mutex) sys_sem_valid(mutex) -#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) - -#else /* LWIP_COMPAT_MUTEX */ - -/** - * @ingroup sys_mutex - * Create a new mutex. - * Note that mutexes are expected to not be taken recursively by the lwIP code, - * so both implementation types (recursive or non-recursive) should work. - * @param mutex pointer to the mutex to create - * @return ERR_OK if successful, another err_t otherwise - */ -err_t sys_mutex_new(sys_mutex_t *mutex); -/** - * @ingroup sys_mutex - * Lock a mutex - * @param mutex the mutex to lock - */ -void sys_mutex_lock(sys_mutex_t *mutex); -/** - * @ingroup sys_mutex - * Unlock a mutex - * @param mutex the mutex to unlock - */ -void sys_mutex_unlock(sys_mutex_t *mutex); -/** - * @ingroup sys_mutex - * Delete a semaphore - * @param mutex the mutex to delete - */ -void sys_mutex_free(sys_mutex_t *mutex); -#ifndef sys_mutex_valid -/** - * @ingroup sys_mutex - * Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid - */ -int sys_mutex_valid(sys_mutex_t *mutex); -#endif -#ifndef sys_mutex_set_invalid -/** - * @ingroup sys_mutex - * Set a mutex invalid so that sys_mutex_valid returns 0 - */ -void sys_mutex_set_invalid(sys_mutex_t *mutex); -#endif -#endif /* LWIP_COMPAT_MUTEX */ - -/* Semaphore functions: */ - -/** - * @ingroup sys_sem - * Create a new semaphore - * @param sem pointer to the semaphore to create - * @param count initial count of the semaphore - * @return ERR_OK if successful, another err_t otherwise - */ -err_t sys_sem_new(sys_sem_t *sem, u8_t count); -/** - * @ingroup sys_sem - * Signals a semaphore - * @param sem the semaphore to signal - */ -void sys_sem_signal(sys_sem_t *sem); -/** - * @ingroup sys_sem - * Wait for a semaphore for the specified timeout - * @param sem the semaphore to wait for - * @param timeout timeout in milliseconds to wait (0 = wait forever) - * @return time (in milliseconds) waited for the semaphore - * or SYS_ARCH_TIMEOUT on timeout - */ -u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); -/** - * @ingroup sys_sem - * Delete a semaphore - * @param sem semaphore to delete - */ -void sys_sem_free(sys_sem_t *sem); -/** Wait for a semaphore - forever/no timeout */ -#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) -#ifndef sys_sem_valid -/** - * @ingroup sys_sem - * Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid - */ -int sys_sem_valid(sys_sem_t *sem); -#endif -#ifndef sys_sem_set_invalid -/** - * @ingroup sys_sem - * Set a semaphore invalid so that sys_sem_valid returns 0 - */ -void sys_sem_set_invalid(sys_sem_t *sem); -#endif -#ifndef sys_sem_valid_val -/** - * Same as sys_sem_valid() but taking a value, not a pointer - */ -#define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) -#endif -#ifndef sys_sem_set_invalid_val -/** - * Same as sys_sem_set_invalid() but taking a value, not a pointer - */ -#define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) -#endif - -#ifndef sys_msleep -/** - * @ingroup sys_misc - * Sleep for specified number of ms - */ -void sys_msleep(u32_t ms); /* only has a (close to) 1 ms resolution. */ -#endif - -/* Mailbox functions. */ - -/** - * @ingroup sys_mbox - * Create a new mbox of specified size - * @param mbox pointer to the mbox to create - * @param size (minimum) number of messages in this mbox - * @return ERR_OK if successful, another err_t otherwise - */ -err_t sys_mbox_new(sys_mbox_t *mbox, int size); -/** - * @ingroup sys_mbox - * Post a message to an mbox - may not fail - * -> blocks if full, only used from tasks not from ISR - * @param mbox mbox to posts the message - * @param msg message to post (ATTENTION: can be NULL) - */ -void sys_mbox_post(sys_mbox_t *mbox, void *msg); -/** - * @ingroup sys_mbox - * Try to post a message to an mbox - may fail if full or ISR - * @param mbox mbox to posts the message - * @param msg message to post (ATTENTION: can be NULL) - */ -err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); -/** - * @ingroup sys_mbox - * Wait for a new message to arrive in the mbox - * @param mbox mbox to get a message from - * @param msg pointer where the message is stored - * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) - * @return time (in milliseconds) waited for a message, may be 0 if not waited - or SYS_ARCH_TIMEOUT on timeout - * The returned time has to be accurate to prevent timer jitter! - */ -u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); -/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ -#ifndef sys_arch_mbox_tryfetch -/** - * @ingroup sys_mbox - * Wait for a new message to arrive in the mbox - * @param mbox mbox to get a message from - * @param msg pointer where the message is stored - * @return 0 (milliseconds) if a message has been received - * or SYS_MBOX_EMPTY if the mailbox is empty - */ -u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); -#endif -/** - * For now, we map straight to sys_arch implementation. - */ -#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) -/** - * @ingroup sys_mbox - * Delete an mbox - * @param mbox mbox to delete - */ -void sys_mbox_free(sys_mbox_t *mbox); -#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) -#ifndef sys_mbox_valid -/** - * @ingroup sys_mbox - * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid - */ -int sys_mbox_valid(sys_mbox_t *mbox); -#endif -#ifndef sys_mbox_set_invalid -/** - * @ingroup sys_mbox - * Set an mbox invalid so that sys_mbox_valid returns 0 - */ -void sys_mbox_set_invalid(sys_mbox_t *mbox); -#endif -#ifndef sys_mbox_valid_val -/** - * Same as sys_mbox_valid() but taking a value, not a pointer - */ -#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) -#endif -#ifndef sys_mbox_set_invalid_val -/** - * Same as sys_mbox_set_invalid() but taking a value, not a pointer - */ -#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) -#endif - - -/** - * @ingroup sys_misc - * The only thread function: - * Creates a new thread - * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) - * @param name human-readable name for the thread (used for debugging purposes) - * @param thread thread-function - * @param arg parameter passed to 'thread' - * @param stacksize stack size in bytes for the new thread (may be ignored by ports) - * @param prio priority of the new thread (may be ignored by ports) */ -sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); - -#endif /* NO_SYS */ - -/* sys_init() must be called before anything else. */ -void sys_init(void); - -#ifndef sys_jiffies -/** - * Ticks/jiffies since power up. - */ -u32_t sys_jiffies(void); -#endif - -/** - * @ingroup sys_time - * Returns the current time in milliseconds, - * may be the same as sys_jiffies or at least based on it. - */ -u32_t sys_now(void); - -/* Critical Region Protection */ -/* These functions must be implemented in the sys_arch.c file. - In some implementations they can provide a more light-weight protection - mechanism than using semaphores. Otherwise semaphores can be used for - implementation */ -#ifndef SYS_ARCH_PROTECT -/** SYS_LIGHTWEIGHT_PROT - * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection - * for certain critical regions during buffer allocation, deallocation and memory - * allocation and deallocation. - */ -#if SYS_LIGHTWEIGHT_PROT - -/** - * @ingroup sys_prot - * SYS_ARCH_DECL_PROTECT - * declare a protection variable. This macro will default to defining a variable of - * type sys_prot_t. If a particular port needs a different implementation, then - * this macro may be defined in sys_arch.h. - */ -#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev -/** - * @ingroup sys_prot - * SYS_ARCH_PROTECT - * Perform a "fast" protect. This could be implemented by - * disabling interrupts for an embedded system or by using a semaphore or - * mutex. The implementation should allow calling SYS_ARCH_PROTECT when - * already protected. The old protection level is returned in the variable - * "lev". This macro will default to calling the sys_arch_protect() function - * which should be implemented in sys_arch.c. If a particular port needs a - * different implementation, then this macro may be defined in sys_arch.h - */ -#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() -/** - * @ingroup sys_prot - * SYS_ARCH_UNPROTECT - * Perform a "fast" set of the protection level to "lev". This could be - * implemented by setting the interrupt level to "lev" within the MACRO or by - * using a semaphore or mutex. This macro will default to calling the - * sys_arch_unprotect() function which should be implemented in - * sys_arch.c. If a particular port needs a different implementation, then - * this macro may be defined in sys_arch.h - */ -#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) -sys_prot_t sys_arch_protect(void); -void sys_arch_unprotect(sys_prot_t pval); - -#else - -#define SYS_ARCH_DECL_PROTECT(lev) -#define SYS_ARCH_PROTECT(lev) -#define SYS_ARCH_UNPROTECT(lev) - -#endif /* SYS_LIGHTWEIGHT_PROT */ - -#endif /* SYS_ARCH_PROTECT */ - -/* - * Macros to set/get and increase/decrease variables in a thread-safe way. - * Use these for accessing variable that are used from more than one thread. - */ - -#ifndef SYS_ARCH_INC -#define SYS_ARCH_INC(var, val) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - var += val; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_INC */ - -#ifndef SYS_ARCH_DEC -#define SYS_ARCH_DEC(var, val) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - var -= val; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_DEC */ - -#ifndef SYS_ARCH_GET -#define SYS_ARCH_GET(var, ret) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - ret = var; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_GET */ - -#ifndef SYS_ARCH_SET -#define SYS_ARCH_SET(var, val) do { \ - SYS_ARCH_DECL_PROTECT(old_level); \ - SYS_ARCH_PROTECT(old_level); \ - var = val; \ - SYS_ARCH_UNPROTECT(old_level); \ - } while(0) -#endif /* SYS_ARCH_SET */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_SYS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/tcp.h b/components/net/lwip-2.0.2/src/include/lwip/tcp.h deleted file mode 100644 index 34d1c10158..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/tcp.h +++ /dev/null @@ -1,433 +0,0 @@ -/** - * @file - * TCP API (to be used from TCPIP thread)\n - * See also @ref tcp_raw - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCP_H -#define LWIP_HDR_TCP_H - -#include "lwip/opt.h" - -#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/ip.h" -#include "lwip/icmp.h" -#include "lwip/err.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct tcp_pcb; - -/** Function prototype for tcp accept callback functions. Called when a new - * connection can be accepted on a listening pcb. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param newpcb The new connection pcb - * @param err An error code if there has been an error accepting. - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); - -/** Function prototype for tcp receive callback functions. Called when data has - * been received. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb The connection pcb which received data - * @param p The received data (or NULL when the connection has been closed!) - * @param err An error code if there has been an error receiving - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, - struct pbuf *p, err_t err); - -/** Function prototype for tcp sent callback functions. Called when sent data has - * been acknowledged by the remote side. Use it to free corresponding resources. - * This also means that the pcb has now space available to send new data. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb The connection pcb for which data has been acknowledged - * @param len The amount of bytes acknowledged - * @return ERR_OK: try to send some data by calling tcp_output - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, - u16_t len); - -/** Function prototype for tcp poll callback functions. Called periodically as - * specified by @see tcp_poll. - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb tcp pcb - * @return ERR_OK: try to send some data by calling tcp_output - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - */ -typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); - -/** Function prototype for tcp error callback functions. Called when the pcb - * receives a RST or is unexpectedly closed for any other reason. - * - * @note The corresponding pcb is already freed when this callback is called! - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param err Error code to indicate why the pcb has been closed - * ERR_ABRT: aborted through tcp_abort or by a TCP timer - * ERR_RST: the connection was reset by the remote host - */ -typedef void (*tcp_err_fn)(void *arg, err_t err); - -/** Function prototype for tcp connected callback functions. Called when a pcb - * is connected to the remote side after initiating a connection attempt by - * calling tcp_connect(). - * - * @param arg Additional argument to pass to the callback function (@see tcp_arg()) - * @param tpcb The connection pcb which is connected - * @param err An unused error code, always ERR_OK currently ;-) @todo! - * Only return ERR_ABRT if you have called tcp_abort from within the - * callback function! - * - * @note When a connection attempt fails, the error callback is currently called! - */ -typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); - -#if LWIP_WND_SCALE -#define RCV_WND_SCALE(pcb, wnd) (((wnd) >> (pcb)->rcv_scale)) -#define SND_WND_SCALE(pcb, wnd) (((wnd) << (pcb)->snd_scale)) -#define TCPWND16(x) ((u16_t)LWIP_MIN((x), 0xFFFF)) -#define TCP_WND_MAX(pcb) ((tcpwnd_size_t)(((pcb)->flags & TF_WND_SCALE) ? TCP_WND : TCPWND16(TCP_WND))) -typedef u32_t tcpwnd_size_t; -#else -#define RCV_WND_SCALE(pcb, wnd) (wnd) -#define SND_WND_SCALE(pcb, wnd) (wnd) -#define TCPWND16(x) (x) -#define TCP_WND_MAX(pcb) TCP_WND -typedef u16_t tcpwnd_size_t; -#endif - -#if LWIP_WND_SCALE || TCP_LISTEN_BACKLOG || LWIP_TCP_TIMESTAMPS -typedef u16_t tcpflags_t; -#else -typedef u8_t tcpflags_t; -#endif - -enum tcp_state { - CLOSED = 0, - LISTEN = 1, - SYN_SENT = 2, - SYN_RCVD = 3, - ESTABLISHED = 4, - FIN_WAIT_1 = 5, - FIN_WAIT_2 = 6, - CLOSE_WAIT = 7, - CLOSING = 8, - LAST_ACK = 9, - TIME_WAIT = 10 -}; - -/** - * members common to struct tcp_pcb and struct tcp_listen_pcb - */ -#define TCP_PCB_COMMON(type) \ - type *next; /* for the linked list */ \ - void *callback_arg; \ - enum tcp_state state; /* TCP state */ \ - u8_t prio; \ - /* ports are in host byte order */ \ - u16_t local_port - - -/** the TCP protocol control block for listening pcbs */ -struct tcp_pcb_listen { -/** Common members of all PCB types */ - IP_PCB; -/** Protocol specific PCB members */ - TCP_PCB_COMMON(struct tcp_pcb_listen); - -#if LWIP_CALLBACK_API - /* Function to call when a listener has been connected. */ - tcp_accept_fn accept; -#endif /* LWIP_CALLBACK_API */ - -#if TCP_LISTEN_BACKLOG - u8_t backlog; - u8_t accepts_pending; -#endif /* TCP_LISTEN_BACKLOG */ -}; - - -/** the TCP protocol control block */ -struct tcp_pcb { -/** common PCB members */ - IP_PCB; -/** protocol specific PCB members */ - TCP_PCB_COMMON(struct tcp_pcb); - - /* ports are in host byte order */ - u16_t remote_port; - - tcpflags_t flags; -#define TF_ACK_DELAY 0x01U /* Delayed ACK. */ -#define TF_ACK_NOW 0x02U /* Immediate ACK. */ -#define TF_INFR 0x04U /* In fast recovery. */ -#define TF_CLOSEPEND 0x08U /* If this is set, tcp_close failed to enqueue the FIN (retried in tcp_tmr) */ -#define TF_RXCLOSED 0x10U /* rx closed by tcp_shutdown */ -#define TF_FIN 0x20U /* Connection was closed locally (FIN segment enqueued). */ -#define TF_NODELAY 0x40U /* Disable Nagle algorithm */ -#define TF_NAGLEMEMERR 0x80U /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ -#if LWIP_WND_SCALE -#define TF_WND_SCALE 0x0100U /* Window Scale option enabled */ -#endif -#if TCP_LISTEN_BACKLOG -#define TF_BACKLOGPEND 0x0200U /* If this is set, a connection pcb has increased the backlog on its listener */ -#endif -#if LWIP_TCP_TIMESTAMPS -#define TF_TIMESTAMP 0x0400U /* Timestamp option enabled */ -#endif - - /* the rest of the fields are in host byte order - as we have to do some math with them */ - - /* Timers */ - u8_t polltmr, pollinterval; - u8_t last_timer; - u32_t tmr; - - /* receiver variables */ - u32_t rcv_nxt; /* next seqno expected */ - tcpwnd_size_t rcv_wnd; /* receiver window available */ - tcpwnd_size_t rcv_ann_wnd; /* receiver window to announce */ - u32_t rcv_ann_right_edge; /* announced right edge of window */ - - /* Retransmission timer. */ - s16_t rtime; - - u16_t mss; /* maximum segment size */ - - /* RTT (round trip time) estimation variables */ - u32_t rttest; /* RTT estimate in 500ms ticks */ - u32_t rtseq; /* sequence number being timed */ - s16_t sa, sv; /* @todo document this */ - - s16_t rto; /* retransmission time-out */ - u8_t nrtx; /* number of retransmissions */ - - /* fast retransmit/recovery */ - u8_t dupacks; - u32_t lastack; /* Highest acknowledged seqno. */ - - /* congestion avoidance/control variables */ - tcpwnd_size_t cwnd; - tcpwnd_size_t ssthresh; - - /* sender variables */ - u32_t snd_nxt; /* next new seqno to be sent */ - u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last - window update. */ - u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ - tcpwnd_size_t snd_wnd; /* sender window */ - tcpwnd_size_t snd_wnd_max; /* the maximum sender window announced by the remote host */ - - tcpwnd_size_t snd_buf; /* Available buffer space for sending (in bytes). */ -#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) - u16_t snd_queuelen; /* Number of pbufs currently in the send buffer. */ - -#if TCP_OVERSIZE - /* Extra bytes available at the end of the last pbuf in unsent. */ - u16_t unsent_oversize; -#endif /* TCP_OVERSIZE */ - - /* These are ordered by sequence number: */ - struct tcp_seg *unsent; /* Unsent (queued) segments. */ - struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ -#if TCP_QUEUE_OOSEQ - struct tcp_seg *ooseq; /* Received out of sequence segments. */ -#endif /* TCP_QUEUE_OOSEQ */ - - struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ - -#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG - struct tcp_pcb_listen* listener; -#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */ - -#if LWIP_CALLBACK_API - /* Function to be called when more send buffer space is available. */ - tcp_sent_fn sent; - /* Function to be called when (in-sequence) data has arrived. */ - tcp_recv_fn recv; - /* Function to be called when a connection has been set up. */ - tcp_connected_fn connected; - /* Function which is called periodically. */ - tcp_poll_fn poll; - /* Function to be called whenever a fatal error occurs. */ - tcp_err_fn errf; -#endif /* LWIP_CALLBACK_API */ - -#if LWIP_TCP_TIMESTAMPS - u32_t ts_lastacksent; - u32_t ts_recent; -#endif /* LWIP_TCP_TIMESTAMPS */ - - /* idle time before KEEPALIVE is sent */ - u32_t keep_idle; -#if LWIP_TCP_KEEPALIVE - u32_t keep_intvl; - u32_t keep_cnt; -#endif /* LWIP_TCP_KEEPALIVE */ - - /* Persist timer counter */ - u8_t persist_cnt; - /* Persist timer back-off */ - u8_t persist_backoff; - - /* KEEPALIVE counter */ - u8_t keep_cnt_sent; - -#if LWIP_WND_SCALE - u8_t snd_scale; - u8_t rcv_scale; -#endif -}; - -#if LWIP_EVENT_API - -enum lwip_event { - LWIP_EVENT_ACCEPT, - LWIP_EVENT_SENT, - LWIP_EVENT_RECV, - LWIP_EVENT_CONNECTED, - LWIP_EVENT_POLL, - LWIP_EVENT_ERR -}; - -err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, - enum lwip_event, - struct pbuf *p, - u16_t size, - err_t err); - -#endif /* LWIP_EVENT_API */ - -/* Application program's interface: */ -struct tcp_pcb * tcp_new (void); -struct tcp_pcb * tcp_new_ip_type (u8_t type); - -void tcp_arg (struct tcp_pcb *pcb, void *arg); -#if LWIP_CALLBACK_API -void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv); -void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent); -void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err); -void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept); -#endif /* LWIP_CALLBACK_API */ -void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval); - -#if LWIP_TCP_TIMESTAMPS -#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) -#else /* LWIP_TCP_TIMESTAMPS */ -#define tcp_mss(pcb) ((pcb)->mss) -#endif /* LWIP_TCP_TIMESTAMPS */ -#define tcp_sndbuf(pcb) (TCPWND16((pcb)->snd_buf)) -#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) -/** @ingroup tcp_raw */ -#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) -/** @ingroup tcp_raw */ -#define tcp_nagle_enable(pcb) ((pcb)->flags = (tcpflags_t)((pcb)->flags & ~TF_NODELAY)) -/** @ingroup tcp_raw */ -#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) - -#if TCP_LISTEN_BACKLOG -#define tcp_backlog_set(pcb, new_backlog) do { \ - LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", (pcb)->state == LISTEN); \ - ((struct tcp_pcb_listen *)(pcb))->backlog = ((new_backlog) ? (new_backlog) : 1); } while(0) -void tcp_backlog_delayed(struct tcp_pcb* pcb); -void tcp_backlog_accepted(struct tcp_pcb* pcb); -#else /* TCP_LISTEN_BACKLOG */ -#define tcp_backlog_set(pcb, new_backlog) -#define tcp_backlog_delayed(pcb) -#define tcp_backlog_accepted(pcb) -#endif /* TCP_LISTEN_BACKLOG */ -#define tcp_accepted(pcb) /* compatibility define, not needed any more */ - -void tcp_recved (struct tcp_pcb *pcb, u16_t len); -err_t tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port); -err_t tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port, tcp_connected_fn connected); - -struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err); -struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); -/** @ingroup tcp_raw */ -#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) - -void tcp_abort (struct tcp_pcb *pcb); -err_t tcp_close (struct tcp_pcb *pcb); -err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx); - -/* Flags for "apiflags" parameter in tcp_write */ -#define TCP_WRITE_FLAG_COPY 0x01 -#define TCP_WRITE_FLAG_MORE 0x02 - -err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, - u8_t apiflags); - -void tcp_setprio (struct tcp_pcb *pcb, u8_t prio); - -#define TCP_PRIO_MIN 1 -#define TCP_PRIO_NORMAL 64 -#define TCP_PRIO_MAX 127 - -err_t tcp_output (struct tcp_pcb *pcb); - - -const char* tcp_debug_state_str(enum tcp_state s); - -/* for compatibility with older implementation */ -#define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_TCP */ - -#endif /* LWIP_HDR_TCP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/tcpip.h b/components/net/lwip-2.0.2/src/include/lwip/tcpip.h deleted file mode 100644 index f2f6b469f1..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/tcpip.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file - * Functions to sync with TCPIP thread - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_TCPIP_H -#define LWIP_HDR_TCPIP_H - -#include "lwip/opt.h" - -#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/err.h" -#include "lwip/timeouts.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_TCPIP_CORE_LOCKING -/** The global semaphore to lock the stack. */ -extern sys_mutex_t lock_tcpip_core; -/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ -#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) -/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */ -#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) -#else /* LWIP_TCPIP_CORE_LOCKING */ -#define LOCK_TCPIP_CORE() -#define UNLOCK_TCPIP_CORE() -#endif /* LWIP_TCPIP_CORE_LOCKING */ - -struct pbuf; -struct netif; - -/** Function prototype for the init_done function passed to tcpip_init */ -typedef void (*tcpip_init_done_fn)(void *arg); -/** Function prototype for functions passed to tcpip_callback() */ -typedef void (*tcpip_callback_fn)(void *ctx); - -/* Forward declarations */ -struct tcpip_callback_msg; - -void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); - -err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn); -err_t tcpip_input(struct pbuf *p, struct netif *inp); - -err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); -/** - * @ingroup lwip_os - * @see tcpip_callback_with_block - */ -#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) - -struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx); -void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg); -err_t tcpip_trycallback(struct tcpip_callback_msg* msg); - -/* free pbufs or heap memory from another context without blocking */ -err_t pbuf_free_callback(struct pbuf *p); -err_t mem_free_callback(void *m); - -#if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS -err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); -err_t tcpip_untimeout(sys_timeout_handler h, void *arg); -#endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ - -#ifdef __cplusplus -} -#endif - -#endif /* !NO_SYS */ - -#endif /* LWIP_HDR_TCPIP_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/timeouts.h b/components/net/lwip-2.0.2/src/include/lwip/timeouts.h deleted file mode 100644 index c9b93aa02a..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/timeouts.h +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file - * Timer implementations - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_TIMEOUTS_H -#define LWIP_HDR_TIMEOUTS_H - -#include "lwip/opt.h" -#include "lwip/err.h" -#if !NO_SYS -#include "lwip/sys.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef LWIP_DEBUG_TIMERNAMES -#ifdef LWIP_DEBUG -#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG -#else /* LWIP_DEBUG */ -#define LWIP_DEBUG_TIMERNAMES 0 -#endif /* LWIP_DEBUG*/ -#endif - -/** Function prototype for a stack-internal timer function that has to be - * called at a defined interval */ -typedef void (* lwip_cyclic_timer_handler)(void); - -/** This struct contains information about a stack-internal timer function - that has to be called at a defined interval */ -struct lwip_cyclic_timer { - u32_t interval_ms; - lwip_cyclic_timer_handler handler; -#if LWIP_DEBUG_TIMERNAMES - const char* handler_name; -#endif /* LWIP_DEBUG_TIMERNAMES */ -}; - -/** This array contains all stack-internal cyclic timers. To get the number of - * timers, use LWIP_ARRAYSIZE() */ -extern const struct lwip_cyclic_timer lwip_cyclic_timers[]; - -#if LWIP_TIMERS - -/** Function prototype for a timeout callback function. Register such a function - * using sys_timeout(). - * - * @param arg Additional argument to pass to the function - set up by sys_timeout() - */ -typedef void (* sys_timeout_handler)(void *arg); - -struct sys_timeo { - struct sys_timeo *next; - u32_t time; - sys_timeout_handler h; - void *arg; -#if LWIP_DEBUG_TIMERNAMES - const char* handler_name; -#endif /* LWIP_DEBUG_TIMERNAMES */ -}; - -void sys_timeouts_init(void); - -#if LWIP_DEBUG_TIMERNAMES -void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name); -#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) -#else /* LWIP_DEBUG_TIMERNAMES */ -void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg); -#endif /* LWIP_DEBUG_TIMERNAMES */ - -void sys_untimeout(sys_timeout_handler handler, void *arg); -void sys_restart_timeouts(void); -#if NO_SYS -void sys_check_timeouts(void); -u32_t sys_timeouts_sleeptime(void); -#else /* NO_SYS */ -void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); -#endif /* NO_SYS */ - - -#endif /* LWIP_TIMERS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_TIMEOUTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/lwip/udp.h b/components/net/lwip-2.0.2/src/include/lwip/udp.h deleted file mode 100644 index b929907394..0000000000 --- a/components/net/lwip-2.0.2/src/include/lwip/udp.h +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file - * UDP API (to be used from TCPIP thread)\n - * See also @ref udp_raw - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_UDP_H -#define LWIP_HDR_UDP_H - -#include "lwip/opt.h" - -#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/ip_addr.h" -#include "lwip/ip.h" -#include "lwip/ip6_addr.h" -#include "lwip/prot/udp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UDP_FLAGS_NOCHKSUM 0x01U -#define UDP_FLAGS_UDPLITE 0x02U -#define UDP_FLAGS_CONNECTED 0x04U -#define UDP_FLAGS_MULTICAST_LOOP 0x08U - -struct udp_pcb; - -/** Function prototype for udp pcb receive callback functions - * addr and port are in same byte order as in the pcb - * The callback is responsible for freeing the pbuf - * if it's not used any more. - * - * ATTENTION: Be aware that 'addr' might point into the pbuf 'p' so freeing this pbuf - * can make 'addr' invalid, too. - * - * @param arg user supplied argument (udp_pcb.recv_arg) - * @param pcb the udp_pcb which received data - * @param p the packet buffer that was received - * @param addr the remote IP address from which the packet was received - * @param port the remote port from which the packet was received - */ -typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *addr, u16_t port); - -/** the UDP protocol control block */ -struct udp_pcb { -/** Common members of all PCB types */ - IP_PCB; - -/* Protocol specific PCB members */ - - struct udp_pcb *next; - - u8_t flags; - /** ports are in host byte order */ - u16_t local_port, remote_port; - -#if LWIP_MULTICAST_TX_OPTIONS - /** outgoing network interface for multicast packets */ - ip_addr_t multicast_ip; - /** TTL for outgoing multicast packets */ - u8_t mcast_ttl; -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#if LWIP_UDPLITE - /** used for UDP_LITE only */ - u16_t chksum_len_rx, chksum_len_tx; -#endif /* LWIP_UDPLITE */ - - /** receive callback function */ - udp_recv_fn recv; - /** user-supplied argument for the recv callback */ - void *recv_arg; -}; -/* udp_pcbs export for external reference (e.g. SNMP agent) */ -extern struct udp_pcb *udp_pcbs; - -/* The following functions is the application layer interface to the - UDP code. */ -struct udp_pcb * udp_new (void); -struct udp_pcb * udp_new_ip_type(u8_t type); -void udp_remove (struct udp_pcb *pcb); -err_t udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port); -err_t udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, - u16_t port); -void udp_disconnect (struct udp_pcb *pcb); -void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, - void *recv_arg); -err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - struct netif *netif); -err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - struct netif *netif, const ip_addr_t *src_ip); -err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port); -err_t udp_send (struct udp_pcb *pcb, struct pbuf *p); - -#if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP -err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - struct netif *netif, u8_t have_chksum, - u16_t chksum); -err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, - u8_t have_chksum, u16_t chksum); -err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, - u8_t have_chksum, u16_t chksum); -err_t udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, - const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, - u8_t have_chksum, u16_t chksum, const ip_addr_t *src_ip); -#endif /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ - -#define udp_flags(pcb) ((pcb)->flags) -#define udp_setflags(pcb, f) ((pcb)->flags = (f)) - -/* The following functions are the lower layer interface to UDP. */ -void udp_input (struct pbuf *p, struct netif *inp); - -void udp_init (void); - -/* for compatibility with older implementation */ -#define udp_new_ip6() udp_new_ip_type(IPADDR_TYPE_V6) - -#if LWIP_MULTICAST_TX_OPTIONS -#define udp_set_multicast_netif_addr(pcb, ip4addr) ip_addr_copy_from_ip4((pcb)->multicast_ip, *(ip4addr)) -#define udp_get_multicast_netif_addr(pcb) ip_2_ip4(&(pcb)->multicast_ip) -#define udp_set_multicast_ttl(pcb, value) do { (pcb)->mcast_ttl = value; } while(0) -#define udp_get_multicast_ttl(pcb) ((pcb)->mcast_ttl) -#endif /* LWIP_MULTICAST_TX_OPTIONS */ - -#if UDP_DEBUG -void udp_debug_print(struct udp_hdr *udphdr); -#else -#define udp_debug_print(udphdr) -#endif - -void udp_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_UDP */ - -#endif /* LWIP_HDR_UDP_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/etharp.h b/components/net/lwip-2.0.2/src/include/netif/etharp.h deleted file mode 100644 index b536fd280f..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/etharp.h +++ /dev/null @@ -1,3 +0,0 @@ -/* ARP has been moved to core/ipv4, provide this #include for compatibility only */ -#include "lwip/etharp.h" -#include "netif/ethernet.h" diff --git a/components/net/lwip-2.0.2/src/include/netif/ethernet.h b/components/net/lwip-2.0.2/src/include/netif/ethernet.h deleted file mode 100644 index 49649cbf8b..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ethernet.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file - * Ethernet input function - handles INCOMING ethernet level traffic - * To be used in most low-level netif implementations - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#ifndef LWIP_HDR_NETIF_ETHERNET_H -#define LWIP_HDR_NETIF_ETHERNET_H - -#include "lwip/opt.h" - -#include "lwip/pbuf.h" -#include "lwip/netif.h" -#include "lwip/prot/ethernet.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if LWIP_ARP || LWIP_ETHERNET - -/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) - * to a filter function that returns the correct netif when using multiple - * netifs on one hardware interface where the netif's low-level receive - * routine cannot decide for the correct netif (e.g. when mapping multiple - * IP addresses to one hardware interface). - */ -#ifndef LWIP_ARP_FILTER_NETIF -#define LWIP_ARP_FILTER_NETIF 0 -#endif - -err_t ethernet_input(struct pbuf *p, struct netif *netif); -err_t ethernet_output(struct netif* netif, struct pbuf* p, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type); - -extern const struct eth_addr ethbroadcast, ethzero; - -#endif /* LWIP_ARP || LWIP_ETHERNET */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_NETIF_ETHERNET_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ethernetif.h b/components/net/lwip-2.0.2/src/include/netif/ethernetif.h deleted file mode 100644 index 1459e3241d..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ethernetif.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __NETIF_ETHERNETIF_H__ -#define __NETIF_ETHERNETIF_H__ - -#include "lwip/netif.h" -#include - -#define NIOCTL_GADDR 0x01 -#ifndef RT_LWIP_ETH_MTU -#define ETHERNET_MTU 1500 -#else -#define ETHERNET_MTU RT_LWIP_ETH_MTU -#endif - -/* eth flag with auto_linkup or phy_linkup */ -#define ETHIF_LINK_AUTOUP 0x0000 -#define ETHIF_LINK_PHYUP 0x0100 - -struct eth_device -{ - /* inherit from rt_device */ - struct rt_device parent; - - /* network interface for lwip */ - struct netif *netif; - struct rt_semaphore tx_ack; - - rt_uint16_t flags; - rt_uint8_t link_changed; - rt_uint8_t link_status; - rt_uint8_t rx_notice; - - /* eth device interface */ - struct pbuf* (*eth_rx)(rt_device_t dev); - rt_err_t (*eth_tx)(rt_device_t dev, struct pbuf* p); -}; - -#ifdef __cplusplus -extern "C" { -#endif - - rt_err_t eth_device_ready(struct eth_device* dev); - rt_err_t eth_device_init(struct eth_device * dev, const char *name); - rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flag); - rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up); - void eth_device_deinit(struct eth_device *dev); - - int eth_system_device_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __NETIF_ETHERNETIF_H__ */ diff --git a/components/net/lwip-2.0.2/src/include/netif/lowpan6.h b/components/net/lwip-2.0.2/src/include/netif/lowpan6.h deleted file mode 100644 index 4174644bb3..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/lowpan6.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file - * - * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. - */ - -/* - * Copyright (c) 2015 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_LOWPAN6_H -#define LWIP_HDR_LOWPAN6_H - -#include "netif/lowpan6_opts.h" - -#if LWIP_IPV6 && LWIP_6LOWPAN /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/ip.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** 1 second period */ -#define LOWPAN6_TMR_INTERVAL 1000 - -void lowpan6_tmr(void); - -err_t lowpan6_set_context(u8_t index, const ip6_addr_t * context); -err_t lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low); - -#if LWIP_IPV4 -err_t lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr); -#endif /* LWIP_IPV4 */ -err_t lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr); -err_t lowpan6_input(struct pbuf * p, struct netif *netif); -err_t lowpan6_if_init(struct netif *netif); - -/* pan_id in network byte order. */ -err_t lowpan6_set_pan_id(u16_t pan_id); - -#if !NO_SYS -err_t tcpip_6lowpan_input(struct pbuf *p, struct netif *inp); -#endif /* !NO_SYS */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ - -#endif /* LWIP_HDR_LOWPAN6_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/lowpan6_opts.h b/components/net/lwip-2.0.2/src/include/netif/lowpan6_opts.h deleted file mode 100644 index fb93ea05de..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/lowpan6_opts.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file - * 6LowPAN options list - */ - -/* - * Copyright (c) 2015 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -#ifndef LWIP_HDR_LOWPAN6_OPTS_H -#define LWIP_HDR_LOWPAN6_OPTS_H - -#include "lwip/opt.h" - -#ifndef LWIP_6LOWPAN -#define LWIP_6LOWPAN 0 -#endif - -#ifndef LWIP_6LOWPAN_NUM_CONTEXTS -#define LWIP_6LOWPAN_NUM_CONTEXTS 10 -#endif - -#ifndef LWIP_6LOWPAN_INFER_SHORT_ADDRESS -#define LWIP_6LOWPAN_INFER_SHORT_ADDRESS 1 -#endif - -#ifndef LWIP_6LOWPAN_IPHC -#define LWIP_6LOWPAN_IPHC 1 -#endif - -#ifndef LWIP_6LOWPAN_HW_CRC -#define LWIP_6LOWPAN_HW_CRC 1 -#endif - -#ifndef LOWPAN6_DEBUG -#define LOWPAN6_DEBUG LWIP_DBG_OFF -#endif - -#endif /* LWIP_HDR_LOWPAN6_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ccp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ccp.h deleted file mode 100644 index 14dd65962c..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ccp.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * ccp.h - Definitions for PPP Compression Control Protocol. - * - * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ccp.h,v 1.12 2004/11/04 10:02:26 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef CCP_H -#define CCP_H - -/* - * CCP codes. - */ - -#define CCP_CONFREQ 1 -#define CCP_CONFACK 2 -#define CCP_TERMREQ 5 -#define CCP_TERMACK 6 -#define CCP_RESETREQ 14 -#define CCP_RESETACK 15 - -/* - * Max # bytes for a CCP option - */ - -#define CCP_MAX_OPTION_LENGTH 32 - -/* - * Parts of a CCP packet. - */ - -#define CCP_CODE(dp) ((dp)[0]) -#define CCP_ID(dp) ((dp)[1]) -#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3]) -#define CCP_HDRLEN 4 - -#define CCP_OPT_CODE(dp) ((dp)[0]) -#define CCP_OPT_LENGTH(dp) ((dp)[1]) -#define CCP_OPT_MINLEN 2 - -#if BSDCOMPRESS_SUPPORT -/* - * Definitions for BSD-Compress. - */ - -#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */ -#define CILEN_BSD_COMPRESS 3 /* length of config. option */ - -/* Macros for handling the 3rd byte of the BSD-Compress config option. */ -#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */ -#define BSD_VERSION(x) ((x) >> 5) /* version of option format */ -#define BSD_CURRENT_VERSION 1 /* current version number */ -#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n)) - -#define BSD_MIN_BITS 9 /* smallest code size supported */ -#define BSD_MAX_BITS 15 /* largest code size supported */ -#endif /* BSDCOMPRESS_SUPPORT */ - -#if DEFLATE_SUPPORT -/* - * Definitions for Deflate. - */ - -#define CI_DEFLATE 26 /* config option for Deflate */ -#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ -#define CILEN_DEFLATE 4 /* length of its config option */ - -#define DEFLATE_MIN_SIZE 9 -#define DEFLATE_MAX_SIZE 15 -#define DEFLATE_METHOD_VAL 8 -#define DEFLATE_SIZE(x) (((x) >> 4) + 8) -#define DEFLATE_METHOD(x) ((x) & 0x0F) -#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) -#define DEFLATE_CHK_SEQUENCE 0 -#endif /* DEFLATE_SUPPORT */ - -#if MPPE_SUPPORT -/* - * Definitions for MPPE. - */ - -#define CI_MPPE 18 /* config option for MPPE */ -#define CILEN_MPPE 6 /* length of config option */ -#endif /* MPPE_SUPPORT */ - -#if PREDICTOR_SUPPORT -/* - * Definitions for other, as yet unsupported, compression methods. - */ - -#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */ -#define CILEN_PREDICTOR_1 2 /* length of its config option */ -#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */ -#define CILEN_PREDICTOR_2 2 /* length of its config option */ -#endif /* PREDICTOR_SUPPORT */ - -typedef struct ccp_options { -#if DEFLATE_SUPPORT - unsigned int deflate :1; /* do Deflate? */ - unsigned int deflate_correct :1; /* use correct code for deflate? */ - unsigned int deflate_draft :1; /* use draft RFC code for deflate? */ -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - unsigned int bsd_compress :1; /* do BSD Compress? */ -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - unsigned int predictor_1 :1; /* do Predictor-1? */ - unsigned int predictor_2 :1; /* do Predictor-2? */ -#endif /* PREDICTOR_SUPPORT */ - -#if MPPE_SUPPORT - u8_t mppe; /* MPPE bitfield */ -#endif /* MPPE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - u_short bsd_bits; /* # bits/code for BSD Compress */ -#endif /* BSDCOMPRESS_SUPPORT */ -#if DEFLATE_SUPPORT - u_short deflate_size; /* lg(window size) for Deflate */ -#endif /* DEFLATE_SUPPORT */ - u8_t method; /* code for chosen compression method */ -} ccp_options; - -extern const struct protent ccp_protent; - -void ccp_resetrequest(ppp_pcb *pcb); /* Issue a reset-request. */ - -#endif /* CCP_H */ -#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/chap-md5.h b/components/net/lwip-2.0.2/src/include/netif/ppp/chap-md5.h deleted file mode 100644 index eb0269fe50..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/chap-md5.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * chap-md5.h - New CHAP/MD5 implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -extern const struct chap_digest_type md5_digest; - -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/chap-new.h b/components/net/lwip-2.0.2/src/include/netif/ppp/chap-new.h deleted file mode 100644 index 64eae32202..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/chap-new.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * chap-new.c - New CHAP implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef CHAP_H -#define CHAP_H - -#include "ppp.h" - -/* - * CHAP packets begin with a standard header with code, id, len (2 bytes). - */ -#define CHAP_HDRLEN 4 - -/* - * Values for the code field. - */ -#define CHAP_CHALLENGE 1 -#define CHAP_RESPONSE 2 -#define CHAP_SUCCESS 3 -#define CHAP_FAILURE 4 - -/* - * CHAP digest codes. - */ -#define CHAP_MD5 5 -#if MSCHAP_SUPPORT -#define CHAP_MICROSOFT 0x80 -#define CHAP_MICROSOFT_V2 0x81 -#endif /* MSCHAP_SUPPORT */ - -/* - * Semi-arbitrary limits on challenge and response fields. - */ -#define MAX_CHALLENGE_LEN 64 -#define MAX_RESPONSE_LEN 64 - -/* - * These limits apply to challenge and response packets we send. - * The +4 is the +1 that we actually need rounded up. - */ -#define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) -#define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) - -/* bitmask of supported algorithms */ -#if MSCHAP_SUPPORT -#define MDTYPE_MICROSOFT_V2 0x1 -#define MDTYPE_MICROSOFT 0x2 -#endif /* MSCHAP_SUPPORT */ -#define MDTYPE_MD5 0x4 -#define MDTYPE_NONE 0 - -#if MSCHAP_SUPPORT -/* Return the digest alg. ID for the most preferred digest type. */ -#define CHAP_DIGEST(mdtype) \ - ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ - ((mdtype) & MDTYPE_MICROSOFT_V2)? CHAP_MICROSOFT_V2: \ - ((mdtype) & MDTYPE_MICROSOFT)? CHAP_MICROSOFT: \ - 0 -#else /* !MSCHAP_SUPPORT */ -#define CHAP_DIGEST(mdtype) \ - ((mdtype) & MDTYPE_MD5)? CHAP_MD5: \ - 0 -#endif /* MSCHAP_SUPPORT */ - -/* Return the bit flag (lsb set) for our most preferred digest type. */ -#define CHAP_MDTYPE(mdtype) ((mdtype) ^ ((mdtype) - 1)) & (mdtype) - -/* Return the bit flag for a given digest algorithm ID. */ -#if MSCHAP_SUPPORT -#define CHAP_MDTYPE_D(digest) \ - ((digest) == CHAP_MICROSOFT_V2)? MDTYPE_MICROSOFT_V2: \ - ((digest) == CHAP_MICROSOFT)? MDTYPE_MICROSOFT: \ - ((digest) == CHAP_MD5)? MDTYPE_MD5: \ - 0 -#else /* !MSCHAP_SUPPORT */ -#define CHAP_MDTYPE_D(digest) \ - ((digest) == CHAP_MD5)? MDTYPE_MD5: \ - 0 -#endif /* MSCHAP_SUPPORT */ - -/* Can we do the requested digest? */ -#if MSCHAP_SUPPORT -#define CHAP_CANDIGEST(mdtype, digest) \ - ((digest) == CHAP_MICROSOFT_V2)? (mdtype) & MDTYPE_MICROSOFT_V2: \ - ((digest) == CHAP_MICROSOFT)? (mdtype) & MDTYPE_MICROSOFT: \ - ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ - 0 -#else /* !MSCHAP_SUPPORT */ -#define CHAP_CANDIGEST(mdtype, digest) \ - ((digest) == CHAP_MD5)? (mdtype) & MDTYPE_MD5: \ - 0 -#endif /* MSCHAP_SUPPORT */ - -/* - * The code for each digest type has to supply one of these. - */ -struct chap_digest_type { - int code; - -#if PPP_SERVER - /* - * Note: challenge and response arguments below are formatted as - * a length byte followed by the actual challenge/response data. - */ - void (*generate_challenge)(ppp_pcb *pcb, unsigned char *challenge); - int (*verify_response)(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space); -#endif /* PPP_SERVER */ - void (*make_response)(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *priv); - int (*check_success)(ppp_pcb *pcb, unsigned char *pkt, int len, unsigned char *priv); - void (*handle_failure)(ppp_pcb *pcb, unsigned char *pkt, int len); -}; - -/* - * Each interface is described by chap structure. - */ -#if CHAP_SUPPORT -typedef struct chap_client_state { - u8_t flags; - const char *name; - const struct chap_digest_type *digest; - unsigned char priv[64]; /* private area for digest's use */ -} chap_client_state; - -#if PPP_SERVER -typedef struct chap_server_state { - u8_t flags; - u8_t id; - const char *name; - const struct chap_digest_type *digest; - int challenge_xmits; - int challenge_pktlen; - unsigned char challenge[CHAL_MAX_PKTLEN]; -} chap_server_state; -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPORT */ - -#if 0 /* UNUSED */ -/* Hook for a plugin to validate CHAP challenge */ -extern int (*chap_verify_hook)(char *name, char *ourname, int id, - const struct chap_digest_type *digest, - unsigned char *challenge, unsigned char *response, - char *message, int message_space); -#endif /* UNUSED */ - -#if PPP_SERVER -/* Called by authentication code to start authenticating the peer. */ -extern void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code); -#endif /* PPP_SERVER */ - -/* Called by auth. code to start authenticating us to the peer. */ -extern void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code); - -/* Represents the CHAP protocol to the main pppd code */ -extern const struct protent chap_protent; - -#endif /* CHAP_H */ -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/chap_ms.h b/components/net/lwip-2.0.2/src/include/netif/ppp/chap_ms.h deleted file mode 100644 index 0795291158..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/chap_ms.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * chap_ms.h - Challenge Handshake Authentication Protocol definitions. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef CHAPMS_INCLUDE -#define CHAPMS_INCLUDE - -extern const struct chap_digest_type chapms_digest; -extern const struct chap_digest_type chapms2_digest; - -#endif /* CHAPMS_INCLUDE */ - -#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/eap.h b/components/net/lwip-2.0.2/src/include/netif/ppp/eap.h deleted file mode 100644 index 3ee9aaf81a..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/eap.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * eap.h - Extensible Authentication Protocol for PPP (RFC 2284) - * - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - * - * Non-exclusive rights to redistribute, modify, translate, and use - * this software in source and binary forms, in whole or in part, is - * hereby granted, provided that the above copyright notice is - * duplicated in any source form, and that neither the name of the - * copyright holder nor the author is used to endorse or promote - * products derived from this software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Original version by James Carlson - * - * $Id: eap.h,v 1.2 2003/06/11 23:56:26 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPP_EAP_H -#define PPP_EAP_H - -#include "ppp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Packet header = Code, id, length. - */ -#define EAP_HEADERLEN 4 - - -/* EAP message codes. */ -#define EAP_REQUEST 1 -#define EAP_RESPONSE 2 -#define EAP_SUCCESS 3 -#define EAP_FAILURE 4 - -/* EAP types */ -#define EAPT_IDENTITY 1 -#define EAPT_NOTIFICATION 2 -#define EAPT_NAK 3 /* (response only) */ -#define EAPT_MD5CHAP 4 -#define EAPT_OTP 5 /* One-Time Password; RFC 1938 */ -#define EAPT_TOKEN 6 /* Generic Token Card */ -/* 7 and 8 are unassigned. */ -#define EAPT_RSA 9 /* RSA Public Key Authentication */ -#define EAPT_DSS 10 /* DSS Unilateral */ -#define EAPT_KEA 11 /* KEA */ -#define EAPT_KEA_VALIDATE 12 /* KEA-VALIDATE */ -#define EAPT_TLS 13 /* EAP-TLS */ -#define EAPT_DEFENDER 14 /* Defender Token (AXENT) */ -#define EAPT_W2K 15 /* Windows 2000 EAP */ -#define EAPT_ARCOT 16 /* Arcot Systems */ -#define EAPT_CISCOWIRELESS 17 /* Cisco Wireless */ -#define EAPT_NOKIACARD 18 /* Nokia IP smart card */ -#define EAPT_SRP 19 /* Secure Remote Password */ -/* 20 is deprecated */ - -/* EAP SRP-SHA1 Subtypes */ -#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ -#define EAPSRP_CKEY 1 /* Response 1 - Client Key */ -#define EAPSRP_SKEY 2 /* Request 2 - Server Key */ -#define EAPSRP_CVALIDATOR 2 /* Response 2 - Client Validator */ -#define EAPSRP_SVALIDATOR 3 /* Request 3 - Server Validator */ -#define EAPSRP_ACK 3 /* Response 3 - final ack */ -#define EAPSRP_LWRECHALLENGE 4 /* Req/resp 4 - Lightweight rechal */ - -#define SRPVAL_EBIT 0x00000001 /* Use shared key for ECP */ - -#define SRP_PSEUDO_ID "pseudo_" -#define SRP_PSEUDO_LEN 7 - -#define MD5_SIGNATURE_SIZE 16 -#define EAP_MIN_CHALLENGE_LENGTH 17 -#define EAP_MAX_CHALLENGE_LENGTH 24 -#define EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH 3 /* 2^3-1 = 7, 17+7 = 24 */ - -#define EAP_STATES \ - "Initial", "Pending", "Closed", "Listen", "Identify", \ - "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" - -#define eap_client_active(pcb) ((pcb)->eap.es_client.ea_state == eapListen) -#if PPP_SERVER -#define eap_server_active(pcb) \ - ((pcb)->eap.es_server.ea_state >= eapIdentify && \ - (pcb)->eap.es_server.ea_state <= eapMD5Chall) -#endif /* PPP_SERVER */ - -/* - * Complete EAP state for one PPP session. - */ -enum eap_state_code { - eapInitial = 0, /* No EAP authentication yet requested */ - eapPending, /* Waiting for LCP (no timer) */ - eapClosed, /* Authentication not in use */ - eapListen, /* Client ready (and timer running) */ - eapIdentify, /* EAP Identify sent */ - eapSRP1, /* Sent EAP SRP-SHA1 Subtype 1 */ - eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ - eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ - eapMD5Chall, /* Sent MD5-Challenge */ - eapOpen, /* Completed authentication */ - eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ - eapBadAuth /* Failed authentication */ -}; - -struct eap_auth { - const char *ea_name; /* Our name */ - char ea_peer[MAXNAMELEN +1]; /* Peer's name */ - void *ea_session; /* Authentication library linkage */ - u_char *ea_skey; /* Shared encryption key */ - u_short ea_namelen; /* Length of our name */ - u_short ea_peerlen; /* Length of peer's name */ - enum eap_state_code ea_state; - u_char ea_id; /* Current id */ - u_char ea_requests; /* Number of Requests sent/received */ - u_char ea_responses; /* Number of Responses */ - u_char ea_type; /* One of EAPT_* */ - u32_t ea_keyflags; /* SRP shared key usage flags */ -}; - -#ifndef EAP_MAX_CHALLENGE_LENGTH -#define EAP_MAX_CHALLENGE_LENGTH 24 -#endif -typedef struct eap_state { - struct eap_auth es_client; /* Client (authenticatee) data */ -#if PPP_SERVER - struct eap_auth es_server; /* Server (authenticator) data */ -#endif /* PPP_SERVER */ - int es_savedtime; /* Saved timeout */ - int es_rechallenge; /* EAP rechallenge interval */ - int es_lwrechallenge; /* SRP lightweight rechallenge inter */ - u8_t es_usepseudo; /* Use SRP Pseudonym if offered one */ - int es_usedpseudo; /* Set if we already sent PN */ - int es_challen; /* Length of challenge string */ - u_char es_challenge[EAP_MAX_CHALLENGE_LENGTH]; -} eap_state; - -/* - * Timeouts. - */ -#if 0 /* moved to ppp_opts.h */ -#define EAP_DEFTIMEOUT 3 /* Timeout (seconds) for rexmit */ -#define EAP_DEFTRANSMITS 10 /* max # times to transmit */ -#define EAP_DEFREQTIME 20 /* Time to wait for peer request */ -#define EAP_DEFALLOWREQ 20 /* max # times to accept requests */ -#endif /* moved to ppp_opts.h */ - -void eap_authwithpeer(ppp_pcb *pcb, const char *localname); -void eap_authpeer(ppp_pcb *pcb, const char *localname); - -extern const struct protent eap_protent; - -#ifdef __cplusplus -} -#endif - -#endif /* PPP_EAP_H */ - -#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ecp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ecp.h deleted file mode 100644 index 5cdce29d5b..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ecp.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ecp.h - Definitions for PPP Encryption Control Protocol. - * - * Copyright (c) 2002 Google, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ecp.h,v 1.2 2003/01/10 07:12:36 fcusack Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -typedef struct ecp_options { - bool required; /* Is ECP required? */ - unsigned enctype; /* Encryption type */ -} ecp_options; - -extern fsm ecp_fsm[]; -extern ecp_options ecp_wantoptions[]; -extern ecp_options ecp_gotoptions[]; -extern ecp_options ecp_allowoptions[]; -extern ecp_options ecp_hisoptions[]; - -extern const struct protent ecp_protent; - -#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/eui64.h b/components/net/lwip-2.0.2/src/include/netif/ppp/eui64.h deleted file mode 100644 index 20ac22eede..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/eui64.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * eui64.h - EUI64 routines for IPv6CP. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: eui64.h,v 1.6 2002/12/04 23:03:32 paulus Exp $ -*/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef EUI64_H -#define EUI64_H - -/* - * @todo: - * - * Maybe this should be done by processing struct in6_addr directly... - */ -typedef union -{ - u8_t e8[8]; - u16_t e16[4]; - u32_t e32[2]; -} eui64_t; - -#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0) -#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \ - ((e).e32[1] == (o).e32[1])) -#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0; - -#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t)) - -#define eui64_magic(e) do { \ - (e).e32[0] = magic(); \ - (e).e32[1] = magic(); \ - (e).e8[0] &= ~2; \ - } while (0) -#define eui64_magic_nz(x) do { \ - eui64_magic(x); \ - } while (eui64_iszero(x)) -#define eui64_magic_ne(x, y) do { \ - eui64_magic(x); \ - } while (eui64_equals(x, y)) - -#define eui64_get(ll, cp) do { \ - eui64_copy((*cp), (ll)); \ - (cp) += sizeof(eui64_t); \ - } while (0) - -#define eui64_put(ll, cp) do { \ - eui64_copy((ll), (*cp)); \ - (cp) += sizeof(eui64_t); \ - } while (0) - -#define eui64_set32(e, l) do { \ - (e).e32[0] = 0; \ - (e).e32[1] = lwip_htonl(l); \ - } while (0) -#define eui64_setlo32(e, l) eui64_set32(e, l) - -char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */ - -#endif /* EUI64_H */ -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/fsm.h b/components/net/lwip-2.0.2/src/include/netif/ppp/fsm.h deleted file mode 100644 index b6915d3b80..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/fsm.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: fsm.h,v 1.10 2004/11/13 02:28:15 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef FSM_H -#define FSM_H - -#include "ppp.h" - -/* - * Packet header = Code, id, length. - */ -#define HEADERLEN 4 - - -/* - * CP (LCP, IPCP, etc.) codes. - */ -#define CONFREQ 1 /* Configuration Request */ -#define CONFACK 2 /* Configuration Ack */ -#define CONFNAK 3 /* Configuration Nak */ -#define CONFREJ 4 /* Configuration Reject */ -#define TERMREQ 5 /* Termination Request */ -#define TERMACK 6 /* Termination Ack */ -#define CODEREJ 7 /* Code Reject */ - - -/* - * Each FSM is described by an fsm structure and fsm callbacks. - */ -typedef struct fsm { - ppp_pcb *pcb; /* PPP Interface */ - const struct fsm_callbacks *callbacks; /* Callback routines */ - const char *term_reason; /* Reason for closing protocol */ - u8_t seen_ack; /* Have received valid Ack/Nak/Rej to Req */ - /* -- This is our only flag, we might use u_int :1 if we have more flags */ - u16_t protocol; /* Data Link Layer Protocol field value */ - u8_t state; /* State */ - u8_t flags; /* Contains option bits */ - u8_t id; /* Current id */ - u8_t reqid; /* Current request id */ - u8_t retransmits; /* Number of retransmissions left */ - u8_t nakloops; /* Number of nak loops since last ack */ - u8_t rnakloops; /* Number of naks received */ - u8_t maxnakloops; /* Maximum number of nak loops tolerated - (necessary because IPCP require a custom large max nak loops value) */ - u8_t term_reason_len; /* Length of term_reason */ -} fsm; - - -typedef struct fsm_callbacks { - void (*resetci) /* Reset our Configuration Information */ - (fsm *); - int (*cilen) /* Length of our Configuration Information */ - (fsm *); - void (*addci) /* Add our Configuration Information */ - (fsm *, u_char *, int *); - int (*ackci) /* ACK our Configuration Information */ - (fsm *, u_char *, int); - int (*nakci) /* NAK our Configuration Information */ - (fsm *, u_char *, int, int); - int (*rejci) /* Reject our Configuration Information */ - (fsm *, u_char *, int); - int (*reqci) /* Request peer's Configuration Information */ - (fsm *, u_char *, int *, int); - void (*up) /* Called when fsm reaches PPP_FSM_OPENED state */ - (fsm *); - void (*down) /* Called when fsm leaves PPP_FSM_OPENED state */ - (fsm *); - void (*starting) /* Called when we want the lower layer */ - (fsm *); - void (*finished) /* Called when we don't want the lower layer */ - (fsm *); - void (*protreject) /* Called when Protocol-Reject received */ - (int); - void (*retransmit) /* Retransmission is necessary */ - (fsm *); - int (*extcode) /* Called when unknown code received */ - (fsm *, int, int, u_char *, int); - const char *proto_name; /* String name for protocol (for messages) */ -} fsm_callbacks; - - -/* - * Link states. - */ -#define PPP_FSM_INITIAL 0 /* Down, hasn't been opened */ -#define PPP_FSM_STARTING 1 /* Down, been opened */ -#define PPP_FSM_CLOSED 2 /* Up, hasn't been opened */ -#define PPP_FSM_STOPPED 3 /* Open, waiting for down event */ -#define PPP_FSM_CLOSING 4 /* Terminating the connection, not open */ -#define PPP_FSM_STOPPING 5 /* Terminating, but open */ -#define PPP_FSM_REQSENT 6 /* We've sent a Config Request */ -#define PPP_FSM_ACKRCVD 7 /* We've received a Config Ack */ -#define PPP_FSM_ACKSENT 8 /* We've sent a Config Ack */ -#define PPP_FSM_OPENED 9 /* Connection available */ - - -/* - * Flags - indicate options controlling FSM operation - */ -#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ -#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ -#define OPT_SILENT 4 /* Wait for peer to speak first */ - - -/* - * Timeouts. - */ -#if 0 /* moved to ppp_opts.h */ -#define DEFTIMEOUT 3 /* Timeout time in seconds */ -#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ -#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ -#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ -#endif /* moved to ppp_opts.h */ - - -/* - * Prototypes - */ -void fsm_init(fsm *f); -void fsm_lowerup(fsm *f); -void fsm_lowerdown(fsm *f); -void fsm_open(fsm *f); -void fsm_close(fsm *f, const char *reason); -void fsm_input(fsm *f, u_char *inpacket, int l); -void fsm_protreject(fsm *f); -void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen); - - -#endif /* FSM_H */ -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ipcp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ipcp.h deleted file mode 100644 index 45f46b31ff..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ipcp.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ipcp.h - IP Control Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipcp.h,v 1.14 2002/12/04 23:03:32 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef IPCP_H -#define IPCP_H - -/* - * Options. - */ -#define CI_ADDRS 1 /* IP Addresses */ -#if VJ_SUPPORT -#define CI_COMPRESSTYPE 2 /* Compression Type */ -#endif /* VJ_SUPPORT */ -#define CI_ADDR 3 - -#if LWIP_DNS -#define CI_MS_DNS1 129 /* Primary DNS value */ -#define CI_MS_DNS2 131 /* Secondary DNS value */ -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ -#define CI_MS_WINS1 130 /* Primary WINS value */ -#define CI_MS_WINS2 132 /* Secondary WINS value */ -#endif /* UNUSED - WINS */ - -#if VJ_SUPPORT -#define MAX_STATES 16 /* from slcompress.h */ - -#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ -#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ -#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */ - /* maxslot and slot number compression) */ - -#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ -#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ - /* compression option*/ -#endif /* VJ_SUPPORT */ - -typedef struct ipcp_options { - unsigned int neg_addr :1; /* Negotiate IP Address? */ - unsigned int old_addrs :1; /* Use old (IP-Addresses) option? */ - unsigned int req_addr :1; /* Ask peer to send IP address? */ -#if 0 /* UNUSED */ - unsigned int default_route :1; /* Assign default route through interface? */ - unsigned int replace_default_route :1; /* Replace default route through interface? */ -#endif /* UNUSED */ -#if 0 /* UNUSED - PROXY ARP */ - unsigned int proxy_arp :1; /* Make proxy ARP entry for peer? */ -#endif /* UNUSED - PROXY ARP */ -#if VJ_SUPPORT - unsigned int neg_vj :1; /* Van Jacobson Compression? */ - unsigned int old_vj :1; /* use old (short) form of VJ option? */ - unsigned int cflag :1; -#endif /* VJ_SUPPORT */ - unsigned int accept_local :1; /* accept peer's value for ouraddr */ - unsigned int accept_remote :1; /* accept peer's value for hisaddr */ -#if LWIP_DNS - unsigned int req_dns1 :1; /* Ask peer to send primary DNS address? */ - unsigned int req_dns2 :1; /* Ask peer to send secondary DNS address? */ -#endif /* LWIP_DNS */ - - u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ -#if LWIP_DNS - u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */ -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ -#endif /* UNUSED - WINS */ - -#if VJ_SUPPORT - u16_t vj_protocol; /* protocol value to use in VJ option */ - u8_t maxslotindex; /* values for RFC1332 VJ compression neg. */ -#endif /* VJ_SUPPORT */ -} ipcp_options; - -#if 0 /* UNUSED, already defined by lwIP */ -char *ip_ntoa (u32_t); -#endif /* UNUSED, already defined by lwIP */ - -extern const struct protent ipcp_protent; - -#endif /* IPCP_H */ -#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ipv6cp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ipv6cp.h deleted file mode 100644 index 07d1ae3186..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ipv6cp.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * ipv6cp.h - PPP IPV6 Control Protocol. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* Original version, based on RFC2023 : - - Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt - Économique ayant pour membres BULL S.A. et l'INRIA). - - Ce logiciel informatique est disponible aux conditions - usuelles dans la recherche, c'est-à-dire qu'il peut - être utilisé, copié, modifié, distribué à l'unique - condition que ce texte soit conservé afin que - l'origine de ce logiciel soit reconnue. - - Le nom de l'Institut National de Recherche en Informatique - et en Automatique (INRIA), de l'IMAG, ou d'une personne morale - ou physique ayant participé à l'élaboration de ce logiciel ne peut - être utilisé sans son accord préalable explicite. - - Ce logiciel est fourni tel quel sans aucune garantie, - support ou responsabilité d'aucune sorte. - Ce logiciel est dérivé de sources d'origine - "University of California at Berkeley" et - "Digital Equipment Corporation" couvertes par des copyrights. - - L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) - est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National - Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). - - This work has been done in the context of GIE DYADE (joint R & D venture - between BULL S.A. and INRIA). - - This software is available with usual "research" terms - with the aim of retain credits of the software. - Permission to use, copy, modify and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, - and the name of INRIA, IMAG, or any contributor not be used in advertising - or publicity pertaining to this material without the prior explicit - permission. The software is provided "as is" without any - warranties, support or liabilities of any kind. - This software is derived from source code from - "University of California at Berkeley" and - "Digital Equipment Corporation" protected by copyrights. - - Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) - is a federation of seven research units funded by the CNRS, National - Polytechnic Institute of Grenoble and University Joseph Fourier. - The research unit in Software, Systems, Networks (LSR) is member of IMAG. -*/ - -/* - * Derived from : - * - * - * ipcp.h - IP Control Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipv6cp.h,v 1.7 2002/12/04 23:03:32 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef IPV6CP_H -#define IPV6CP_H - -#include "eui64.h" - -/* - * Options. - */ -#define CI_IFACEID 1 /* Interface Identifier */ -#ifdef IPV6CP_COMP -#define CI_COMPRESSTYPE 2 /* Compression Type */ -#endif /* IPV6CP_COMP */ - -/* No compression types yet defined. - *#define IPV6CP_COMP 0x004f - */ -typedef struct ipv6cp_options { - unsigned int neg_ifaceid :1; /* Negotiate interface identifier? */ - unsigned int req_ifaceid :1; /* Ask peer to send interface identifier? */ - unsigned int accept_local :1; /* accept peer's value for iface id? */ - unsigned int opt_local :1; /* ourtoken set by option */ - unsigned int opt_remote :1; /* histoken set by option */ - unsigned int use_ip :1; /* use IP as interface identifier */ -#if 0 - unsigned int use_persistent :1; /* use uniquely persistent value for address */ -#endif -#ifdef IPV6CP_COMP - unsigned int neg_vj :1; /* Van Jacobson Compression? */ -#endif /* IPV6CP_COMP */ - -#ifdef IPV6CP_COMP - u_short vj_protocol; /* protocol value to use in VJ option */ -#endif /* IPV6CP_COMP */ - eui64_t ourid, hisid; /* Interface identifiers */ -} ipv6cp_options; - -extern const struct protent ipv6cp_protent; - -#endif /* IPV6CP_H */ -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/lcp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/lcp.h deleted file mode 100644 index 12e2a05fc9..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/lcp.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * lcp.h - Link Control Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: lcp.h,v 1.20 2004/11/14 22:53:42 carlsonj Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef LCP_H -#define LCP_H - -#include "ppp.h" - -/* - * Options. - */ -#define CI_VENDOR 0 /* Vendor Specific */ -#define CI_MRU 1 /* Maximum Receive Unit */ -#define CI_ASYNCMAP 2 /* Async Control Character Map */ -#define CI_AUTHTYPE 3 /* Authentication Type */ -#define CI_QUALITY 4 /* Quality Protocol */ -#define CI_MAGICNUMBER 5 /* Magic Number */ -#define CI_PCOMPRESSION 7 /* Protocol Field Compression */ -#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ -#define CI_FCSALTERN 9 /* FCS-Alternatives */ -#define CI_SDP 10 /* Self-Describing-Pad */ -#define CI_NUMBERED 11 /* Numbered-Mode */ -#define CI_CALLBACK 13 /* callback */ -#define CI_MRRU 17 /* max reconstructed receive unit; multilink */ -#define CI_SSNHF 18 /* short sequence numbers for multilink */ -#define CI_EPDISC 19 /* endpoint discriminator */ -#define CI_MPPLUS 22 /* Multi-Link-Plus-Procedure */ -#define CI_LDISC 23 /* Link-Discriminator */ -#define CI_LCPAUTH 24 /* LCP Authentication */ -#define CI_COBS 25 /* Consistent Overhead Byte Stuffing */ -#define CI_PREFELIS 26 /* Prefix Elision */ -#define CI_MPHDRFMT 27 /* MP Header Format */ -#define CI_I18N 28 /* Internationalization */ -#define CI_SDL 29 /* Simple Data Link */ - -/* - * LCP-specific packet types (code numbers). - */ -#define PROTREJ 8 /* Protocol Reject */ -#define ECHOREQ 9 /* Echo Request */ -#define ECHOREP 10 /* Echo Reply */ -#define DISCREQ 11 /* Discard Request */ -#define IDENTIF 12 /* Identification */ -#define TIMEREM 13 /* Time Remaining */ - -/* Value used as data for CI_CALLBACK option */ -#define CBCP_OPT 6 /* Use callback control protocol */ - -#if 0 /* moved to ppp_opts.h */ -#define DEFMRU 1500 /* Try for this */ -#define MINMRU 128 /* No MRUs below this */ -#define MAXMRU 16384 /* Normally limit MRU to this */ -#endif /* moved to ppp_opts.h */ - -/* An endpoint discriminator, used with multilink. */ -#define MAX_ENDP_LEN 20 /* maximum length of discriminator value */ -struct epdisc { - unsigned char class_; /* -- The word "class" is reserved in C++. */ - unsigned char length; - unsigned char value[MAX_ENDP_LEN]; -}; - -/* - * The state of options is described by an lcp_options structure. - */ -typedef struct lcp_options { - unsigned int passive :1; /* Don't die if we don't get a response */ - unsigned int silent :1; /* Wait for the other end to start first */ -#if 0 /* UNUSED */ - unsigned int restart :1; /* Restart vs. exit after close */ -#endif /* UNUSED */ - unsigned int neg_mru :1; /* Negotiate the MRU? */ - unsigned int neg_asyncmap :1; /* Negotiate the async map? */ -#if PAP_SUPPORT - unsigned int neg_upap :1; /* Ask for UPAP authentication? */ -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - unsigned int neg_chap :1; /* Ask for CHAP authentication? */ -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - unsigned int neg_eap :1; /* Ask for EAP authentication? */ -#endif /* EAP_SUPPORT */ - unsigned int neg_magicnumber :1; /* Ask for magic number? */ - unsigned int neg_pcompression :1; /* HDLC Protocol Field Compression? */ - unsigned int neg_accompression :1; /* HDLC Address/Control Field Compression? */ -#if LQR_SUPPORT - unsigned int neg_lqr :1; /* Negotiate use of Link Quality Reports */ -#endif /* LQR_SUPPORT */ - unsigned int neg_cbcp :1; /* Negotiate use of CBCP */ -#ifdef HAVE_MULTILINK - unsigned int neg_mrru :1; /* negotiate multilink MRRU */ -#endif /* HAVE_MULTILINK */ - unsigned int neg_ssnhf :1; /* negotiate short sequence numbers */ - unsigned int neg_endpoint :1; /* negotiate endpoint discriminator */ - - u16_t mru; /* Value of MRU */ -#ifdef HAVE_MULTILINK - u16_t mrru; /* Value of MRRU, and multilink enable */ -#endif /* MULTILINK */ -#if CHAP_SUPPORT - u8_t chap_mdtype; /* which MD types (hashing algorithm) */ -#endif /* CHAP_SUPPORT */ - u32_t asyncmap; /* Value of async map */ - u32_t magicnumber; - u8_t numloops; /* Number of loops during magic number neg. */ -#if LQR_SUPPORT - u32_t lqr_period; /* Reporting period for LQR 1/100ths second */ -#endif /* LQR_SUPPORT */ - struct epdisc endpoint; /* endpoint discriminator */ -} lcp_options; - -void lcp_open(ppp_pcb *pcb); -void lcp_close(ppp_pcb *pcb, const char *reason); -void lcp_lowerup(ppp_pcb *pcb); -void lcp_lowerdown(ppp_pcb *pcb); -void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len); /* send protocol reject */ - -extern const struct protent lcp_protent; - -#if 0 /* moved to ppp_opts.h */ -/* Default number of times we receive our magic number from the peer - before deciding the link is looped-back. */ -#define DEFLOOPBACKFAIL 10 -#endif /* moved to ppp_opts.h */ - -#endif /* LCP_H */ -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/magic.h b/components/net/lwip-2.0.2/src/include/netif/ppp/magic.h deleted file mode 100644 index a2a9b530e5..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/magic.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * magic.h - PPP Magic Number definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: magic.h,v 1.5 2003/06/11 23:56:26 paulus Exp $ - */ -/***************************************************************************** -* randm.h - Random number generator header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1998 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-05-29 Guy Lancaster , Global Election Systems Inc. -* Extracted from avos. -*****************************************************************************/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef MAGIC_H -#define MAGIC_H - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - -/* - * Initialize the random number generator. - */ -void magic_init(void); - -/* - * Randomize our random seed value. To be called for truely random events - * such as user operations and network traffic. - */ -void magic_randomize(void); - -/* - * Return a new random number. - */ -u32_t magic(void); /* Returns the next magic number */ - -/* - * Fill buffer with random bytes - * - * Use the random pool to generate random data. This degrades to pseudo - * random when used faster than randomness is supplied using magic_churnrand(). - * Thus it's important to make sure that the results of this are not - * published directly because one could predict the next result to at - * least some degree. Also, it's important to get a good seed before - * the first use. - */ -void magic_random_bytes(unsigned char *buf, u32_t buf_len); - -/* - * Return a new random number between 0 and (2^pow)-1 included. - */ -u32_t magic_pow(u8_t pow); - -#endif /* MAGIC_H */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/mppe.h b/components/net/lwip-2.0.2/src/include/netif/ppp/mppe.h deleted file mode 100644 index 1ae8a5d924..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/mppe.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * mppe.h - Definitions for MPPE - * - * Copyright (c) 2008 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef MPPE_H -#define MPPE_H - -#include "netif/ppp/pppcrypt.h" - -#define MPPE_PAD 4 /* MPPE growth per frame */ -#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ - -/* option bits for ccp_options.mppe */ -#define MPPE_OPT_40 0x01 /* 40 bit */ -#define MPPE_OPT_128 0x02 /* 128 bit */ -#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ -/* unsupported opts */ -#define MPPE_OPT_56 0x08 /* 56 bit */ -#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ -#define MPPE_OPT_D 0x20 /* Unknown */ -#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) -#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ - -/* - * This is not nice ... the alternative is a bitfield struct though. - * And unfortunately, we cannot share the same bits for the option - * names above since C and H are the same bit. We could do a u_int32 - * but then we have to do a lwip_htonl() all the time and/or we still need - * to know which octet is which. - */ -#define MPPE_C_BIT 0x01 /* MPPC */ -#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ -#define MPPE_L_BIT 0x20 /* 40-bit */ -#define MPPE_S_BIT 0x40 /* 128-bit */ -#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ -#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ - -/* Does not include H bit; used for least significant octet only. */ -#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) - -/* Build a CI from mppe opts (see RFC 3078) */ -#define MPPE_OPTS_TO_CI(opts, ci) \ - do { \ - u_char *ptr = ci; /* u_char[4] */ \ - \ - /* H bit */ \ - if (opts & MPPE_OPT_STATEFUL) \ - *ptr++ = 0x0; \ - else \ - *ptr++ = MPPE_H_BIT; \ - *ptr++ = 0; \ - *ptr++ = 0; \ - \ - /* S,L bits */ \ - *ptr = 0; \ - if (opts & MPPE_OPT_128) \ - *ptr |= MPPE_S_BIT; \ - if (opts & MPPE_OPT_40) \ - *ptr |= MPPE_L_BIT; \ - /* M,D,C bits not supported */ \ - } while (/* CONSTCOND */ 0) - -/* The reverse of the above */ -#define MPPE_CI_TO_OPTS(ci, opts) \ - do { \ - const u_char *ptr = ci; /* u_char[4] */ \ - \ - opts = 0; \ - \ - /* H bit */ \ - if (!(ptr[0] & MPPE_H_BIT)) \ - opts |= MPPE_OPT_STATEFUL; \ - \ - /* S,L bits */ \ - if (ptr[3] & MPPE_S_BIT) \ - opts |= MPPE_OPT_128; \ - if (ptr[3] & MPPE_L_BIT) \ - opts |= MPPE_OPT_40; \ - \ - /* M,D,C bits */ \ - if (ptr[3] & MPPE_M_BIT) \ - opts |= MPPE_OPT_56; \ - if (ptr[3] & MPPE_D_BIT) \ - opts |= MPPE_OPT_D; \ - if (ptr[3] & MPPE_C_BIT) \ - opts |= MPPE_OPT_MPPC; \ - \ - /* Other bits */ \ - if (ptr[0] & ~MPPE_H_BIT) \ - opts |= MPPE_OPT_UNKNOWN; \ - if (ptr[1] || ptr[2]) \ - opts |= MPPE_OPT_UNKNOWN; \ - if (ptr[3] & ~MPPE_ALL_BITS) \ - opts |= MPPE_OPT_UNKNOWN; \ - } while (/* CONSTCOND */ 0) - -/* Shared MPPE padding between MSCHAP and MPPE */ -#define SHA1_PAD_SIZE 40 - -static const u8_t mppe_sha1_pad1[SHA1_PAD_SIZE] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -static const u8_t mppe_sha1_pad2[SHA1_PAD_SIZE] = { - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 -}; - -/* - * State for an MPPE (de)compressor. - */ -typedef struct ppp_mppe_state { - lwip_arc4_context arc4; - u8_t master_key[MPPE_MAX_KEY_LEN]; - u8_t session_key[MPPE_MAX_KEY_LEN]; - u8_t keylen; /* key length in bytes */ - /* NB: 128-bit == 16, 40-bit == 8! - * If we want to support 56-bit, the unit has to change to bits - */ - u8_t bits; /* MPPE control bits */ - u16_t ccount; /* 12-bit coherency count (seqno) */ - u16_t sanity_errors; /* take down LCP if too many */ - unsigned int stateful :1; /* stateful mode flag */ - unsigned int discard :1; /* stateful mode packet loss flag */ -} ppp_mppe_state; - -void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key); -void mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options); -void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state); -err_t mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol); -void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state); -err_t mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb); - -#endif /* MPPE_H */ -#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/arc4.h b/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/arc4.h deleted file mode 100644 index 4af724cd90..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/arc4.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file arc4.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_ARC4 - -#ifndef LWIP_INCLUDED_POLARSSL_ARC4_H -#define LWIP_INCLUDED_POLARSSL_ARC4_H - -/** - * \brief ARC4 context structure - */ -typedef struct -{ - int x; /*!< permutation index */ - int y; /*!< permutation index */ - unsigned char m[256]; /*!< permutation table */ -} -arc4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief ARC4 key schedule - * - * \param ctx ARC4 context to be initialized - * \param key the secret key - * \param keylen length of the key - */ -void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ); - -/** - * \brief ARC4 cipher function - * - * \param ctx ARC4 context - * \param buf buffer to be processed - * \param buflen amount of data in buf - */ -void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_ARC4_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/des.h b/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/des.h deleted file mode 100644 index e893890ed7..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/des.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * \file des.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_DES - -#ifndef LWIP_INCLUDED_POLARSSL_DES_H -#define LWIP_INCLUDED_POLARSSL_DES_H - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -/** - * \brief DES context structure - */ -typedef struct -{ - int mode; /*!< encrypt/decrypt */ - unsigned long sk[32]; /*!< DES subkeys */ -} -des_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief DES key schedule (56-bit, encryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - */ -void des_setkey_enc( des_context *ctx, unsigned char key[8] ); - -/** - * \brief DES key schedule (56-bit, decryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - */ -void des_setkey_dec( des_context *ctx, unsigned char key[8] ); - -/** - * \brief DES-ECB block encryption/decryption - * - * \param ctx DES context - * \param input 64-bit input block - * \param output 64-bit output block - */ -void des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_DES_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md4.h b/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md4.h deleted file mode 100644 index 570445687e..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md4.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * \file md4.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_MD4 - -#ifndef LWIP_INCLUDED_POLARSSL_MD4_H -#define LWIP_INCLUDED_POLARSSL_MD4_H - -/** - * \brief MD4 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -md4_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD4 context setup - * - * \param ctx context to be initialized - */ -void md4_starts( md4_context *ctx ); - -/** - * \brief MD4 process buffer - * - * \param ctx MD4 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md4_update( md4_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief MD4 final digest - * - * \param ctx MD4 context - * \param output MD4 checksum result - */ -void md4_finish( md4_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD4( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD4 checksum result - */ -void md4( unsigned char *input, int ilen, unsigned char output[16] ); - - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_MD4_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md5.h b/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md5.h deleted file mode 100644 index 1244011890..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/md5.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file md5.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_MD5 - -#ifndef LWIP_INCLUDED_POLARSSL_MD5_H -#define LWIP_INCLUDED_POLARSSL_MD5_H - -/** - * \brief MD5 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -md5_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - */ -void md5_starts( md5_context *ctx ); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void md5_update( md5_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - */ -void md5_finish( md5_context *ctx, unsigned char output[16] ); - -/** - * \brief Output = MD5( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD5 checksum result - */ -void md5( unsigned char *input, int ilen, unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_MD5_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/sha1.h b/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/sha1.h deleted file mode 100644 index a4c53e07c5..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/polarssl/sha1.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * \file sha1.h - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if LWIP_INCLUDED_POLARSSL_SHA1 - -#ifndef LWIP_INCLUDED_POLARSSL_SHA1_H -#define LWIP_INCLUDED_POLARSSL_SHA1_H - -/** - * \brief SHA-1 context structure - */ -typedef struct -{ - unsigned long total[2]; /*!< number of bytes processed */ - unsigned long state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -sha1_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void sha1_starts( sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ); - -/** - * \brief Output = SHA-1( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void sha1( unsigned char *input, int ilen, unsigned char output[20] ); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_INCLUDED_POLARSSL_SHA1_H */ - -#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ppp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ppp.h deleted file mode 100644 index d9ea097efd..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ppp.h +++ /dev/null @@ -1,690 +0,0 @@ -/***************************************************************************** -* ppp.h - Network Point to Point Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPP_H -#define PPP_H - -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/mem.h" -#include "lwip/netif.h" -#include "lwip/sys.h" -#include "lwip/timeouts.h" -#if PPP_IPV6_SUPPORT -#include "lwip/ip6_addr.h" -#endif /* PPP_IPV6_SUPPORT */ - -/* Disable non-working or rarely used PPP feature, so rarely that we don't want to bloat ppp_opts.h with them */ -#ifndef PPP_OPTIONS -#define PPP_OPTIONS 0 -#endif - -#ifndef PPP_NOTIFY -#define PPP_NOTIFY 0 -#endif - -#ifndef PPP_REMOTENAME -#define PPP_REMOTENAME 0 -#endif - -#ifndef PPP_IDLETIMELIMIT -#define PPP_IDLETIMELIMIT 0 -#endif - -#ifndef PPP_LCP_ADAPTIVE -#define PPP_LCP_ADAPTIVE 0 -#endif - -#ifndef PPP_MAXCONNECT -#define PPP_MAXCONNECT 0 -#endif - -#ifndef PPP_ALLOWED_ADDRS -#define PPP_ALLOWED_ADDRS 0 -#endif - -#ifndef PPP_PROTOCOLNAME -#define PPP_PROTOCOLNAME 0 -#endif - -#ifndef PPP_STATS_SUPPORT -#define PPP_STATS_SUPPORT 0 -#endif - -#ifndef DEFLATE_SUPPORT -#define DEFLATE_SUPPORT 0 -#endif - -#ifndef BSDCOMPRESS_SUPPORT -#define BSDCOMPRESS_SUPPORT 0 -#endif - -#ifndef PREDICTOR_SUPPORT -#define PREDICTOR_SUPPORT 0 -#endif - -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ - -/* - * The basic PPP frame. - */ -#define PPP_HDRLEN 4 /* octets for standard ppp header */ -#define PPP_FCSLEN 2 /* octets for FCS */ - -/* - * Values for phase. - */ -#define PPP_PHASE_DEAD 0 -#define PPP_PHASE_MASTER 1 -#define PPP_PHASE_HOLDOFF 2 -#define PPP_PHASE_INITIALIZE 3 -#define PPP_PHASE_SERIALCONN 4 -#define PPP_PHASE_DORMANT 5 -#define PPP_PHASE_ESTABLISH 6 -#define PPP_PHASE_AUTHENTICATE 7 -#define PPP_PHASE_CALLBACK 8 -#define PPP_PHASE_NETWORK 9 -#define PPP_PHASE_RUNNING 10 -#define PPP_PHASE_TERMINATE 11 -#define PPP_PHASE_DISCONNECT 12 - -/* Error codes. */ -#define PPPERR_NONE 0 /* No error. */ -#define PPPERR_PARAM 1 /* Invalid parameter. */ -#define PPPERR_OPEN 2 /* Unable to open PPP session. */ -#define PPPERR_DEVICE 3 /* Invalid I/O device for PPP. */ -#define PPPERR_ALLOC 4 /* Unable to allocate resources. */ -#define PPPERR_USER 5 /* User interrupt. */ -#define PPPERR_CONNECT 6 /* Connection lost. */ -#define PPPERR_AUTHFAIL 7 /* Failed authentication challenge. */ -#define PPPERR_PROTOCOL 8 /* Failed to meet protocol. */ -#define PPPERR_PEERDEAD 9 /* Connection timeout */ -#define PPPERR_IDLETIMEOUT 10 /* Idle Timeout */ -#define PPPERR_CONNECTTIME 11 /* Max connect time reached */ -#define PPPERR_LOOPBACK 12 /* Loopback detected */ - -/* Whether auth support is enabled at all */ -#define PPP_AUTH_SUPPORT (PAP_SUPPORT || CHAP_SUPPORT || EAP_SUPPORT) - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - -/* - * Other headers require ppp_pcb definition for prototypes, but ppp_pcb - * require some structure definition from other headers as well, we are - * fixing the dependency loop here by declaring the ppp_pcb type then - * by including headers containing necessary struct definition for ppp_pcb - */ -typedef struct ppp_pcb_s ppp_pcb; - -/* Type definitions for BSD code. */ -#ifndef __u_char_defined -typedef unsigned long u_long; -typedef unsigned int u_int; -typedef unsigned short u_short; -typedef unsigned char u_char; -#endif - -#include "fsm.h" -#include "lcp.h" -#if CCP_SUPPORT -#include "ccp.h" -#endif /* CCP_SUPPORT */ -#if MPPE_SUPPORT -#include "mppe.h" -#endif /* MPPE_SUPPORT */ -#if PPP_IPV4_SUPPORT -#include "ipcp.h" -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT -#include "ipv6cp.h" -#endif /* PPP_IPV6_SUPPORT */ -#if PAP_SUPPORT -#include "upap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "chap-new.h" -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#include "eap.h" -#endif /* EAP_SUPPORT */ -#if VJ_SUPPORT -#include "vj.h" -#endif /* VJ_SUPPORT */ - -/* Link status callback function prototype */ -typedef void (*ppp_link_status_cb_fn)(ppp_pcb *pcb, int err_code, void *ctx); - -/* - * PPP configuration. - */ -typedef struct ppp_settings_s { - -#if PPP_SERVER && PPP_AUTH_SUPPORT - unsigned int auth_required :1; /* Peer is required to authenticate */ - unsigned int null_login :1; /* Username of "" and a password of "" are acceptable */ -#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ -#if PPP_REMOTENAME - unsigned int explicit_remote :1; /* remote_name specified with remotename opt */ -#endif /* PPP_REMOTENAME */ -#if PAP_SUPPORT - unsigned int refuse_pap :1; /* Don't proceed auth. with PAP */ -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - unsigned int refuse_chap :1; /* Don't proceed auth. with CHAP */ -#endif /* CHAP_SUPPORT */ -#if MSCHAP_SUPPORT - unsigned int refuse_mschap :1; /* Don't proceed auth. with MS-CHAP */ - unsigned int refuse_mschap_v2 :1; /* Don't proceed auth. with MS-CHAPv2 */ -#endif /* MSCHAP_SUPPORT */ -#if EAP_SUPPORT - unsigned int refuse_eap :1; /* Don't proceed auth. with EAP */ -#endif /* EAP_SUPPORT */ -#if LWIP_DNS - unsigned int usepeerdns :1; /* Ask peer for DNS adds */ -#endif /* LWIP_DNS */ - unsigned int persist :1; /* Persist mode, always try to open the connection */ -#if PRINTPKT_SUPPORT - unsigned int hide_password :1; /* Hide password in dumped packets */ -#endif /* PRINTPKT_SUPPORT */ - unsigned int noremoteip :1; /* Let him have no IP address */ - unsigned int lax_recv :1; /* accept control chars in asyncmap */ - unsigned int noendpoint :1; /* don't send/accept endpoint discriminator */ -#if PPP_LCP_ADAPTIVE - unsigned int lcp_echo_adaptive :1; /* request echo only if the link was idle */ -#endif /* PPP_LCP_ADAPTIVE */ -#if MPPE_SUPPORT - unsigned int require_mppe :1; /* Require MPPE (Microsoft Point to Point Encryption) */ - unsigned int refuse_mppe_40 :1; /* Allow MPPE 40-bit mode? */ - unsigned int refuse_mppe_128 :1; /* Allow MPPE 128-bit mode? */ - unsigned int refuse_mppe_stateful :1; /* Allow MPPE stateful mode? */ -#endif /* MPPE_SUPPORT */ - - u16_t listen_time; /* time to listen first (ms), waiting for peer to send LCP packet */ - -#if PPP_IDLETIMELIMIT - u16_t idle_time_limit; /* Disconnect if idle for this many seconds */ -#endif /* PPP_IDLETIMELIMIT */ -#if PPP_MAXCONNECT - u32_t maxconnect; /* Maximum connect time (seconds) */ -#endif /* PPP_MAXCONNECT */ - -#if PPP_AUTH_SUPPORT - /* auth data */ - const char *user; /* Username for PAP */ - const char *passwd; /* Password for PAP, secret for CHAP */ -#if PPP_REMOTENAME - char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */ -#endif /* PPP_REMOTENAME */ - -#if PAP_SUPPORT - u8_t pap_timeout_time; /* Timeout (seconds) for auth-req retrans. */ - u8_t pap_max_transmits; /* Number of auth-reqs sent */ -#if PPP_SERVER - u8_t pap_req_timeout; /* Time to wait for auth-req from peer */ -#endif /* PPP_SERVER */ -#endif /* PAP_SUPPPORT */ - -#if CHAP_SUPPORT - u8_t chap_timeout_time; /* Timeout (seconds) for retransmitting req */ - u8_t chap_max_transmits; /* max # times to send challenge */ -#if PPP_SERVER - u8_t chap_rechallenge_time; /* Time to wait for auth-req from peer */ -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPPORT */ - -#if EAP_SUPPORT - u8_t eap_req_time; /* Time to wait (for retransmit/fail) */ - u8_t eap_allow_req; /* Max Requests allowed */ -#if PPP_SERVER - u8_t eap_timeout_time; /* Time to wait (for retransmit/fail) */ - u8_t eap_max_transmits; /* Max Requests allowed */ -#endif /* PPP_SERVER */ -#endif /* EAP_SUPPORT */ - -#endif /* PPP_AUTH_SUPPORT */ - - u8_t fsm_timeout_time; /* Timeout time in seconds */ - u8_t fsm_max_conf_req_transmits; /* Maximum Configure-Request transmissions */ - u8_t fsm_max_term_transmits; /* Maximum Terminate-Request transmissions */ - u8_t fsm_max_nak_loops; /* Maximum number of nak loops tolerated */ - - u8_t lcp_loopbackfail; /* Number of times we receive our magic number from the peer - before deciding the link is looped-back. */ - u8_t lcp_echo_interval; /* Interval between LCP echo-requests */ - u8_t lcp_echo_fails; /* Tolerance to unanswered echo-requests */ - -} ppp_settings; - -#if PPP_SERVER -struct ppp_addrs { -#if PPP_IPV4_SUPPORT - ip4_addr_t our_ipaddr, his_ipaddr, netmask; -#if LWIP_DNS - ip4_addr_t dns1, dns2; -#endif /* LWIP_DNS */ -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - ip6_addr_t our6_ipaddr, his6_ipaddr; -#endif /* PPP_IPV6_SUPPORT */ -}; -#endif /* PPP_SERVER */ - -/* - * PPP interface control block. - */ -struct ppp_pcb_s { - ppp_settings settings; - const struct link_callbacks *link_cb; - void *link_ctx_cb; - void (*link_status_cb)(ppp_pcb *pcb, int err_code, void *ctx); /* Status change callback */ -#if PPP_NOTIFY_PHASE - void (*notify_phase_cb)(ppp_pcb *pcb, u8_t phase, void *ctx); /* Notify phase callback */ -#endif /* PPP_NOTIFY_PHASE */ - void *ctx_cb; /* Callbacks optional pointer */ - struct netif *netif; /* PPP interface */ - u8_t phase; /* where the link is at */ - u8_t err_code; /* Code indicating why interface is down. */ - - /* flags */ -#if PPP_IPV4_SUPPORT - unsigned int ask_for_local :1; /* request our address from peer */ - unsigned int ipcp_is_open :1; /* haven't called np_finished() */ - unsigned int ipcp_is_up :1; /* have called ipcp_up() */ - unsigned int if4_up :1; /* True when the IPv4 interface is up. */ -#if 0 /* UNUSED - PROXY ARP */ - unsigned int proxy_arp_set :1; /* Have created proxy arp entry */ -#endif /* UNUSED - PROXY ARP */ -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - unsigned int ipv6cp_is_up :1; /* have called ip6cp_up() */ - unsigned int if6_up :1; /* True when the IPv6 interface is up. */ -#endif /* PPP_IPV6_SUPPORT */ - unsigned int lcp_echo_timer_running :1; /* set if a timer is running */ -#if VJ_SUPPORT - unsigned int vj_enabled :1; /* Flag indicating VJ compression enabled. */ -#endif /* VJ_SUPPORT */ -#if CCP_SUPPORT - unsigned int ccp_all_rejected :1; /* we rejected all peer's options */ -#endif /* CCP_SUPPORT */ -#if MPPE_SUPPORT - unsigned int mppe_keys_set :1; /* Have the MPPE keys been set? */ -#endif /* MPPE_SUPPORT */ - -#if PPP_AUTH_SUPPORT - /* auth data */ -#if PPP_SERVER && defined(HAVE_MULTILINK) - char peer_authname[MAXNAMELEN + 1]; /* The name by which the peer authenticated itself to us. */ -#endif /* PPP_SERVER && defined(HAVE_MULTILINK) */ - u16_t auth_pending; /* Records which authentication operations haven't completed yet. */ - u16_t auth_done; /* Records which authentication operations have been completed. */ - -#if PAP_SUPPORT - upap_state upap; /* PAP data */ -#endif /* PAP_SUPPORT */ - -#if CHAP_SUPPORT - chap_client_state chap_client; /* CHAP client data */ -#if PPP_SERVER - chap_server_state chap_server; /* CHAP server data */ -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPORT */ - -#if EAP_SUPPORT - eap_state eap; /* EAP data */ -#endif /* EAP_SUPPORT */ -#endif /* PPP_AUTH_SUPPORT */ - - fsm lcp_fsm; /* LCP fsm structure */ - lcp_options lcp_wantoptions; /* Options that we want to request */ - lcp_options lcp_gotoptions; /* Options that peer ack'd */ - lcp_options lcp_allowoptions; /* Options we allow peer to request */ - lcp_options lcp_hisoptions; /* Options that we ack'd */ - u16_t peer_mru; /* currently negotiated peer MRU */ - u8_t lcp_echos_pending; /* Number of outstanding echo msgs */ - u8_t lcp_echo_number; /* ID number of next echo frame */ - - u8_t num_np_open; /* Number of network protocols which we have opened. */ - u8_t num_np_up; /* Number of network protocols which have come up. */ - -#if VJ_SUPPORT - struct vjcompress vj_comp; /* Van Jacobson compression header. */ -#endif /* VJ_SUPPORT */ - -#if CCP_SUPPORT - fsm ccp_fsm; /* CCP fsm structure */ - ccp_options ccp_wantoptions; /* what to request the peer to use */ - ccp_options ccp_gotoptions; /* what the peer agreed to do */ - ccp_options ccp_allowoptions; /* what we'll agree to do */ - ccp_options ccp_hisoptions; /* what we agreed to do */ - u8_t ccp_localstate; /* Local state (mainly for handling reset-reqs and reset-acks). */ - u8_t ccp_receive_method; /* Method chosen on receive path */ - u8_t ccp_transmit_method; /* Method chosen on transmit path */ -#if MPPE_SUPPORT - ppp_mppe_state mppe_comp; /* MPPE "compressor" structure */ - ppp_mppe_state mppe_decomp; /* MPPE "decompressor" structure */ -#endif /* MPPE_SUPPORT */ -#endif /* CCP_SUPPORT */ - -#if PPP_IPV4_SUPPORT - fsm ipcp_fsm; /* IPCP fsm structure */ - ipcp_options ipcp_wantoptions; /* Options that we want to request */ - ipcp_options ipcp_gotoptions; /* Options that peer ack'd */ - ipcp_options ipcp_allowoptions; /* Options we allow peer to request */ - ipcp_options ipcp_hisoptions; /* Options that we ack'd */ -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT - fsm ipv6cp_fsm; /* IPV6CP fsm structure */ - ipv6cp_options ipv6cp_wantoptions; /* Options that we want to request */ - ipv6cp_options ipv6cp_gotoptions; /* Options that peer ack'd */ - ipv6cp_options ipv6cp_allowoptions; /* Options we allow peer to request */ - ipv6cp_options ipv6cp_hisoptions; /* Options that we ack'd */ -#endif /* PPP_IPV6_SUPPORT */ -}; - -/************************ - *** PUBLIC FUNCTIONS *** - ************************/ - -/* - * WARNING: For multi-threads environment, all ppp_set_* functions most - * only be called while the PPP is in the dead phase (i.e. disconnected). - */ - -#if PPP_AUTH_SUPPORT -/* - * Set PPP authentication. - * - * Warning: Using PPPAUTHTYPE_ANY might have security consequences. - * RFC 1994 says: - * - * In practice, within or associated with each PPP server, there is a - * database which associates "user" names with authentication - * information ("secrets"). It is not anticipated that a particular - * named user would be authenticated by multiple methods. This would - * make the user vulnerable to attacks which negotiate the least secure - * method from among a set (such as PAP rather than CHAP). If the same - * secret was used, PAP would reveal the secret to be used later with - * CHAP. - * - * Instead, for each user name there should be an indication of exactly - * one method used to authenticate that user name. If a user needs to - * make use of different authentication methods under different - * circumstances, then distinct user names SHOULD be employed, each of - * which identifies exactly one authentication method. - * - * Default is none auth type, unset (NULL) user and passwd. - */ -#define PPPAUTHTYPE_NONE 0x00 -#define PPPAUTHTYPE_PAP 0x01 -#define PPPAUTHTYPE_CHAP 0x02 -#define PPPAUTHTYPE_MSCHAP 0x04 -#define PPPAUTHTYPE_MSCHAP_V2 0x08 -#define PPPAUTHTYPE_EAP 0x10 -#define PPPAUTHTYPE_ANY 0xff -void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd); - -/* - * If set, peer is required to authenticate. This is mostly necessary for PPP server support. - * - * Default is false. - */ -#define ppp_set_auth_required(ppp, boolval) (ppp->settings.auth_required = boolval) -#endif /* PPP_AUTH_SUPPORT */ - -#if PPP_IPV4_SUPPORT -/* - * Set PPP interface "our" and "his" IPv4 addresses. This is mostly necessary for PPP server - * support but it can also be used on a PPP link where each side choose its own IP address. - * - * Default is unset (0.0.0.0). - */ -#define ppp_set_ipcp_ouraddr(ppp, addr) do { ppp->ipcp_wantoptions.ouraddr = ip4_addr_get_u32(addr); \ - ppp->ask_for_local = ppp->ipcp_wantoptions.ouraddr != 0; } while(0) -#define ppp_set_ipcp_hisaddr(ppp, addr) (ppp->ipcp_wantoptions.hisaddr = ip4_addr_get_u32(addr)) -#if LWIP_DNS -/* - * Set DNS server addresses that are sent if the peer asks for them. This is mostly necessary - * for PPP server support. - * - * Default is unset (0.0.0.0). - */ -#define ppp_set_ipcp_dnsaddr(ppp, index, addr) (ppp->ipcp_allowoptions.dnsaddr[index] = ip4_addr_get_u32(addr)) - -/* - * If set, we ask the peer for up to 2 DNS server addresses. Received DNS server addresses are - * registered using the dns_setserver() function. - * - * Default is false. - */ -#define ppp_set_usepeerdns(ppp, boolval) (ppp->settings.usepeerdns = boolval) -#endif /* LWIP_DNS */ -#endif /* PPP_IPV4_SUPPORT */ - -#if MPPE_SUPPORT -/* Disable MPPE (Microsoft Point to Point Encryption). This parameter is exclusive. */ -#define PPP_MPPE_DISABLE 0x00 -/* Require the use of MPPE (Microsoft Point to Point Encryption). */ -#define PPP_MPPE_ENABLE 0x01 -/* Allow MPPE to use stateful mode. Stateless mode is still attempted first. */ -#define PPP_MPPE_ALLOW_STATEFUL 0x02 -/* Refuse the use of MPPE with 40-bit encryption. Conflict with PPP_MPPE_REFUSE_128. */ -#define PPP_MPPE_REFUSE_40 0x04 -/* Refuse the use of MPPE with 128-bit encryption. Conflict with PPP_MPPE_REFUSE_40. */ -#define PPP_MPPE_REFUSE_128 0x08 -/* - * Set MPPE configuration - * - * Default is disabled. - */ -void ppp_set_mppe(ppp_pcb *pcb, u8_t flags); -#endif /* MPPE_SUPPORT */ - -/* - * Wait for up to intval milliseconds for a valid PPP packet from the peer. - * At the end of this time, or when a valid PPP packet is received from the - * peer, we commence negotiation by sending our first LCP packet. - * - * Default is 0. - */ -#define ppp_set_listen_time(ppp, intval) (ppp->settings.listen_time = intval) - -/* - * If set, we will attempt to initiate a connection but if no reply is received from - * the peer, we will then just wait passively for a valid LCP packet from the peer. - * - * Default is false. - */ -#define ppp_set_passive(ppp, boolval) (ppp->lcp_wantoptions.passive = boolval) - -/* - * If set, we will not transmit LCP packets to initiate a connection until a valid - * LCP packet is received from the peer. This is what we usually call the server mode. - * - * Default is false. - */ -#define ppp_set_silent(ppp, boolval) (ppp->lcp_wantoptions.silent = boolval) - -/* - * If set, enable protocol field compression negotiation in both the receive and - * the transmit direction. - * - * Default is true. - */ -#define ppp_set_neg_pcomp(ppp, boolval) (ppp->lcp_wantoptions.neg_pcompression = \ - ppp->lcp_allowoptions.neg_pcompression = boolval) - -/* - * If set, enable Address/Control compression in both the receive and the transmit - * direction. - * - * Default is true. - */ -#define ppp_set_neg_accomp(ppp, boolval) (ppp->lcp_wantoptions.neg_accompression = \ - ppp->lcp_allowoptions.neg_accompression = boolval) - -/* - * If set, enable asyncmap negotiation. Otherwise forcing all control characters to - * be escaped for both the transmit and the receive direction. - * - * Default is true. - */ -#define ppp_set_neg_asyncmap(ppp, boolval) (ppp->lcp_wantoptions.neg_asyncmap = \ - ppp->lcp_allowoptions.neg_asyncmap = boolval) - -/* - * This option sets the Async-Control-Character-Map (ACCM) for this end of the link. - * The ACCM is a set of 32 bits, one for each of the ASCII control characters with - * values from 0 to 31, where a 1 bit indicates that the corresponding control - * character should not be used in PPP packets sent to this system. The map is - * an unsigned 32 bits integer where the least significant bit (00000001) represents - * character 0 and the most significant bit (80000000) represents character 31. - * We will then ask the peer to send these characters as a 2-byte escape sequence. - * - * Default is 0. - */ -#define ppp_set_asyncmap(ppp, intval) (ppp->lcp_wantoptions.asyncmap = intval) - -/* - * Set a PPP interface as the default network interface - * (used to output all packets for which no specific route is found). - */ -#define ppp_set_default(ppp) netif_set_default(ppp->netif) - -#if PPP_NOTIFY_PHASE -/* - * Set a PPP notify phase callback. - * - * This can be used for example to set a LED pattern depending on the - * current phase of the PPP session. - */ -typedef void (*ppp_notify_phase_cb_fn)(ppp_pcb *pcb, u8_t phase, void *ctx); -void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); -#endif /* PPP_NOTIFY_PHASE */ - -/* - * Initiate a PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * Holdoff is the time to wait (in seconds) before initiating - * the connection. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff); - -#if PPP_SERVER -/* - * Listen for an incoming PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_listen(ppp_pcb *pcb); -#endif /* PPP_SERVER */ - -/* - * Initiate the end of a PPP connection. - * Any outstanding packets in the queues are dropped. - * - * Setting nocarrier to 1 close the PPP connection without initiating the - * shutdown procedure. Always using nocarrier = 0 is still recommended, - * this is going to take a little longer time if your link is down, but - * is a safer choice for the PPP state machine. - * - * Return 0 on success, an error code on failure. - */ -err_t ppp_close(ppp_pcb *pcb, u8_t nocarrier); - -/* - * Release the control block. - * - * This can only be called if PPP is in the dead phase. - * - * You must use ppp_close() before if you wish to terminate - * an established PPP session. - * - * Return 0 on success, an error code on failure. - */ -err_t ppp_free(ppp_pcb *pcb); - -/* - * PPP IOCTL commands. - * - * Get the up status - 0 for down, non-zero for up. The argument must - * point to an int. - */ -#define PPPCTLG_UPSTATUS 0 - -/* - * Get the PPP error code. The argument must point to an int. - * Returns a PPPERR_* value. - */ -#define PPPCTLG_ERRCODE 1 - -/* - * Get the fd associated with a PPP over serial - */ -#define PPPCTLG_FD 2 - -/* - * Get and set parameters for the given connection. - * Return 0 on success, an error code on failure. - */ -err_t ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); - -/* Get the PPP netif interface */ -#define ppp_netif(ppp) (ppp->netif) - -/* Set an lwIP-style status-callback for the selected PPP device */ -#define ppp_set_netif_statuscallback(ppp, status_cb) \ - netif_set_status_callback(ppp->netif, status_cb); - -/* Set an lwIP-style link-callback for the selected PPP device */ -#define ppp_set_netif_linkcallback(ppp, link_cb) \ - netif_set_link_callback(ppp->netif, link_cb); - -#endif /* PPP_H */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ppp_impl.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ppp_impl.h deleted file mode 100644 index 1d4c7742f3..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ppp_impl.h +++ /dev/null @@ -1,629 +0,0 @@ -/***************************************************************************** -* ppp.h - Network Point to Point Protocol header file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original derived from BSD codes. -*****************************************************************************/ -#ifndef LWIP_HDR_PPP_IMPL_H -#define LWIP_HDR_PPP_IMPL_H - -#include "netif/ppp/ppp_opts.h" - -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifdef PPP_INCLUDE_SETTINGS_HEADER -#include "ppp_settings.h" -#endif - -#include /* formats */ -#include -#include -#include /* strtol() */ - -#include "lwip/netif.h" -#include "lwip/def.h" -#include "lwip/timeouts.h" - -#include "ppp.h" -#include "pppdebug.h" - -/* - * Memory used for control packets. - * - * PPP_CTRL_PBUF_MAX_SIZE is the amount of memory we allocate when we - * cannot figure out how much we are going to use before filling the buffer. - */ -#if PPP_USE_PBUF_RAM -#define PPP_CTRL_PBUF_TYPE PBUF_RAM -#define PPP_CTRL_PBUF_MAX_SIZE 512 -#else /* PPP_USE_PBUF_RAM */ -#define PPP_CTRL_PBUF_TYPE PBUF_POOL -#define PPP_CTRL_PBUF_MAX_SIZE PBUF_POOL_BUFSIZE -#endif /* PPP_USE_PBUF_RAM */ - -/* - * The basic PPP frame. - */ -#define PPP_ADDRESS(p) (((u_char *)(p))[0]) -#define PPP_CONTROL(p) (((u_char *)(p))[1]) -#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3]) - -/* - * Significant octet values. - */ -#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ -#define PPP_UI 0x03 /* Unnumbered Information */ -#define PPP_FLAG 0x7e /* Flag Sequence */ -#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ -#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ - -/* - * Protocol field values. - */ -#define PPP_IP 0x21 /* Internet Protocol */ -#if 0 /* UNUSED */ -#define PPP_AT 0x29 /* AppleTalk Protocol */ -#define PPP_IPX 0x2b /* IPX protocol */ -#endif /* UNUSED */ -#if VJ_SUPPORT -#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ -#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ -#endif /* VJ_SUPPORT */ -#if PPP_IPV6_SUPPORT -#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ -#endif /* PPP_IPV6_SUPPORT */ -#if CCP_SUPPORT -#define PPP_COMP 0xfd /* compressed packet */ -#endif /* CCP_SUPPORT */ -#define PPP_IPCP 0x8021 /* IP Control Protocol */ -#if 0 /* UNUSED */ -#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ -#define PPP_IPXCP 0x802b /* IPX Control Protocol */ -#endif /* UNUSED */ -#if PPP_IPV6_SUPPORT -#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ -#endif /* PPP_IPV6_SUPPORT */ -#if CCP_SUPPORT -#define PPP_CCP 0x80fd /* Compression Control Protocol */ -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT -#define PPP_ECP 0x8053 /* Encryption Control Protocol */ -#endif /* ECP_SUPPORT */ -#define PPP_LCP 0xc021 /* Link Control Protocol */ -#if PAP_SUPPORT -#define PPP_PAP 0xc023 /* Password Authentication Protocol */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT -#define PPP_LQR 0xc025 /* Link Quality Report protocol */ -#endif /* LQR_SUPPORT */ -#if CHAP_SUPPORT -#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ -#endif /* CHAP_SUPPORT */ -#if CBCP_SUPPORT -#define PPP_CBCP 0xc029 /* Callback Control Protocol */ -#endif /* CBCP_SUPPORT */ -#if EAP_SUPPORT -#define PPP_EAP 0xc227 /* Extensible Authentication Protocol */ -#endif /* EAP_SUPPORT */ - -/* - * The following struct gives the addresses of procedures to call - * for a particular lower link level protocol. - */ -struct link_callbacks { - /* Start a connection (e.g. Initiate discovery phase) */ - void (*connect) (ppp_pcb *pcb, void *ctx); -#if PPP_SERVER - /* Listen for an incoming connection (Passive mode) */ - void (*listen) (ppp_pcb *pcb, void *ctx); -#endif /* PPP_SERVER */ - /* End a connection (i.e. initiate disconnect phase) */ - void (*disconnect) (ppp_pcb *pcb, void *ctx); - /* Free lower protocol control block */ - err_t (*free) (ppp_pcb *pcb, void *ctx); - /* Write a pbuf to a ppp link, only used from PPP functions to send PPP packets. */ - err_t (*write)(ppp_pcb *pcb, void *ctx, struct pbuf *p); - /* Send a packet from lwIP core (IPv4 or IPv6) */ - err_t (*netif_output)(ppp_pcb *pcb, void *ctx, struct pbuf *p, u_short protocol); - /* configure the transmit-side characteristics of the PPP interface */ - void (*send_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); - /* confire the receive-side characteristics of the PPP interface */ - void (*recv_config)(ppp_pcb *pcb, void *ctx, u32_t accm, int pcomp, int accomp); -}; - -/* - * What to do with network protocol (NP) packets. - */ -enum NPmode { - NPMODE_PASS, /* pass the packet through */ - NPMODE_DROP, /* silently drop the packet */ - NPMODE_ERROR, /* return an error */ - NPMODE_QUEUE /* save it up for later. */ -}; - -/* - * Statistics. - */ -#if PPP_STATS_SUPPORT -struct pppstat { - unsigned int ppp_ibytes; /* bytes received */ - unsigned int ppp_ipackets; /* packets received */ - unsigned int ppp_ierrors; /* receive errors */ - unsigned int ppp_obytes; /* bytes sent */ - unsigned int ppp_opackets; /* packets sent */ - unsigned int ppp_oerrors; /* transmit errors */ -}; - -#if VJ_SUPPORT -struct vjstat { - unsigned int vjs_packets; /* outbound packets */ - unsigned int vjs_compressed; /* outbound compressed packets */ - unsigned int vjs_searches; /* searches for connection state */ - unsigned int vjs_misses; /* times couldn't find conn. state */ - unsigned int vjs_uncompressedin; /* inbound uncompressed packets */ - unsigned int vjs_compressedin; /* inbound compressed packets */ - unsigned int vjs_errorin; /* inbound unknown type packets */ - unsigned int vjs_tossed; /* inbound packets tossed because of error */ -}; -#endif /* VJ_SUPPORT */ - -struct ppp_stats { - struct pppstat p; /* basic PPP statistics */ -#if VJ_SUPPORT - struct vjstat vj; /* VJ header compression statistics */ -#endif /* VJ_SUPPORT */ -}; - -#if CCP_SUPPORT -struct compstat { - unsigned int unc_bytes; /* total uncompressed bytes */ - unsigned int unc_packets; /* total uncompressed packets */ - unsigned int comp_bytes; /* compressed bytes */ - unsigned int comp_packets; /* compressed packets */ - unsigned int inc_bytes; /* incompressible bytes */ - unsigned int inc_packets; /* incompressible packets */ - unsigned int ratio; /* recent compression ratio << 8 */ -}; - -struct ppp_comp_stats { - struct compstat c; /* packet compression statistics */ - struct compstat d; /* packet decompression statistics */ -}; -#endif /* CCP_SUPPORT */ - -#endif /* PPP_STATS_SUPPORT */ - -#if PPP_IDLETIMELIMIT -/* - * The following structure records the time in seconds since - * the last NP packet was sent or received. - */ -struct ppp_idle { - time_t xmit_idle; /* time since last NP packet sent */ - time_t recv_idle; /* time since last NP packet received */ -}; -#endif /* PPP_IDLETIMELIMIT */ - -/* values for epdisc.class */ -#define EPD_NULL 0 /* null discriminator, no data */ -#define EPD_LOCAL 1 -#define EPD_IP 2 -#define EPD_MAC 3 -#define EPD_MAGIC 4 -#define EPD_PHONENUM 5 - -/* - * Global variables. - */ -#ifdef HAVE_MULTILINK -extern u8_t multilink; /* enable multilink operation */ -extern u8_t doing_multilink; -extern u8_t multilink_master; -extern u8_t bundle_eof; -extern u8_t bundle_terminating; -#endif - -#ifdef MAXOCTETS -extern unsigned int maxoctets; /* Maximum octetes per session (in bytes) */ -extern int maxoctets_dir; /* Direction : - 0 - in+out (default) - 1 - in - 2 - out - 3 - max(in,out) */ -extern int maxoctets_timeout; /* Timeout for check of octets limit */ -#define PPP_OCTETS_DIRECTION_SUM 0 -#define PPP_OCTETS_DIRECTION_IN 1 -#define PPP_OCTETS_DIRECTION_OUT 2 -#define PPP_OCTETS_DIRECTION_MAXOVERAL 3 -/* same as previos, but little different on RADIUS side */ -#define PPP_OCTETS_DIRECTION_MAXSESSION 4 -#endif - -/* Data input may be used by CCP and ECP, remove this entry - * from struct protent to save some flash - */ -#define PPP_DATAINPUT 0 - -/* - * The following struct gives the addresses of procedures to call - * for a particular protocol. - */ -struct protent { - u_short protocol; /* PPP protocol number */ - /* Initialization procedure */ - void (*init) (ppp_pcb *pcb); - /* Process a received packet */ - void (*input) (ppp_pcb *pcb, u_char *pkt, int len); - /* Process a received protocol-reject */ - void (*protrej) (ppp_pcb *pcb); - /* Lower layer has come up */ - void (*lowerup) (ppp_pcb *pcb); - /* Lower layer has gone down */ - void (*lowerdown) (ppp_pcb *pcb); - /* Open the protocol */ - void (*open) (ppp_pcb *pcb); - /* Close the protocol */ - void (*close) (ppp_pcb *pcb, const char *reason); -#if PRINTPKT_SUPPORT - /* Print a packet in readable form */ - int (*printpkt) (const u_char *pkt, int len, - void (*printer) (void *, const char *, ...), - void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - /* Process a received data packet */ - void (*datainput) (ppp_pcb *pcb, u_char *pkt, int len); -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - const char *name; /* Text name of protocol */ - const char *data_name; /* Text name of corresponding data protocol */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - option_t *options; /* List of command-line options */ - /* Check requested options, assign defaults */ - void (*check_options) (void); -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - /* Configure interface for demand-dial */ - int (*demand_conf) (int unit); - /* Say whether to bring up link for this pkt */ - int (*active_pkt) (u_char *pkt, int len); -#endif /* DEMAND_SUPPORT */ -}; - -/* Table of pointers to supported protocols */ -extern const struct protent* const protocols[]; - - -/* Values for auth_pending, auth_done */ -#if PAP_SUPPORT -#define PAP_WITHPEER 0x1 -#define PAP_PEER 0x2 -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#define CHAP_WITHPEER 0x4 -#define CHAP_PEER 0x8 -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#define EAP_WITHPEER 0x10 -#define EAP_PEER 0x20 -#endif /* EAP_SUPPORT */ - -/* Values for auth_done only */ -#if CHAP_SUPPORT -#define CHAP_MD5_WITHPEER 0x40 -#define CHAP_MD5_PEER 0x80 -#if MSCHAP_SUPPORT -#define CHAP_MS_SHIFT 8 /* LSB position for MS auths */ -#define CHAP_MS_WITHPEER 0x100 -#define CHAP_MS_PEER 0x200 -#define CHAP_MS2_WITHPEER 0x400 -#define CHAP_MS2_PEER 0x800 -#endif /* MSCHAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ - -/* Supported CHAP protocols */ -#if CHAP_SUPPORT - -#if MSCHAP_SUPPORT -#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) -#else /* MSCHAP_SUPPORT */ -#define CHAP_MDTYPE_SUPPORTED (MDTYPE_MD5) -#endif /* MSCHAP_SUPPORT */ - -#else /* CHAP_SUPPORT */ -#define CHAP_MDTYPE_SUPPORTED (MDTYPE_NONE) -#endif /* CHAP_SUPPORT */ - -#if PPP_STATS_SUPPORT -/* - * PPP statistics structure - */ -struct pppd_stats { - unsigned int bytes_in; - unsigned int bytes_out; - unsigned int pkts_in; - unsigned int pkts_out; -}; -#endif /* PPP_STATS_SUPPORT */ - - -/* - * PPP private functions - */ - - -/* - * Functions called from lwIP core. - */ - -/* initialize the PPP subsystem */ -int ppp_init(void); - -/* - * Functions called from PPP link protocols. - */ - -/* Create a new PPP control block */ -ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -/* Initiate LCP open request */ -void ppp_start(ppp_pcb *pcb); - -/* Called when link failed to setup */ -void ppp_link_failed(ppp_pcb *pcb); - -/* Called when link is normally down (i.e. it was asked to end) */ -void ppp_link_end(ppp_pcb *pcb); - -/* function called to process input packet */ -void ppp_input(ppp_pcb *pcb, struct pbuf *pb); - -/* helper function, merge a pbuf chain into one pbuf */ -struct pbuf *ppp_singlebuf(struct pbuf *p); - - -/* - * Functions called by PPP protocols. - */ - -/* function called by all PPP subsystems to send packets */ -err_t ppp_write(ppp_pcb *pcb, struct pbuf *p); - -/* functions called by auth.c link_terminated() */ -void ppp_link_terminated(ppp_pcb *pcb); - -void new_phase(ppp_pcb *pcb, int p); - -int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp); -int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp); - -#if PPP_IPV4_SUPPORT -int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask); -int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr); -#if 0 /* UNUSED - PROXY ARP */ -int sifproxyarp(ppp_pcb *pcb, u32_t his_adr); -int cifproxyarp(ppp_pcb *pcb, u32_t his_adr); -#endif /* UNUSED - PROXY ARP */ -#if LWIP_DNS -int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); -int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2); -#endif /* LWIP_DNS */ -#if VJ_SUPPORT -int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid); -#endif /* VJ_SUPPORT */ -int sifup(ppp_pcb *pcb); -int sifdown (ppp_pcb *pcb); -u32_t get_mask(u32_t addr); -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT -int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); -int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64); -int sif6up(ppp_pcb *pcb); -int sif6down (ppp_pcb *pcb); -#endif /* PPP_IPV6_SUPPORT */ - -#if DEMAND_SUPPORT -int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode); -#endif /* DEMAND_SUPPORt */ - -void netif_set_mtu(ppp_pcb *pcb, int mtu); -int netif_get_mtu(ppp_pcb *pcb); - -#if CCP_SUPPORT -#if 0 /* unused */ -int ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit); -#endif /* unused */ -void ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method); -void ccp_reset_comp(ppp_pcb *pcb); -void ccp_reset_decomp(ppp_pcb *pcb); -#if 0 /* unused */ -int ccp_fatal_error(ppp_pcb *pcb); -#endif /* unused */ -#endif /* CCP_SUPPORT */ - -#if PPP_IDLETIMELIMIT -int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip); -#endif /* PPP_IDLETIMELIMIT */ - -#if DEMAND_SUPPORT -int get_loop_output(void); -#endif /* DEMAND_SUPPORT */ - -/* Optional protocol names list, to make our messages a little more informative. */ -#if PPP_PROTOCOLNAME -const char * protocol_name(int proto); -#endif /* PPP_PROTOCOLNAME */ - -/* Optional stats support, to get some statistics on the PPP interface */ -#if PPP_STATS_SUPPORT -void print_link_stats(void); /* Print stats, if available */ -void reset_link_stats(int u); /* Reset (init) stats when link goes up */ -void update_link_stats(int u); /* Get stats at link termination */ -#endif /* PPP_STATS_SUPPORT */ - - - -/* - * Inline versions of get/put char/short/long. - * Pointer is advanced; we assume that both arguments - * are lvalues and will already be in registers. - * cp MUST be u_char *. - */ -#define GETCHAR(c, cp) { \ - (c) = *(cp)++; \ -} -#define PUTCHAR(c, cp) { \ - *(cp)++ = (u_char) (c); \ -} -#define GETSHORT(s, cp) { \ - (s) = *(cp)++ << 8; \ - (s) |= *(cp)++; \ -} -#define PUTSHORT(s, cp) { \ - *(cp)++ = (u_char) ((s) >> 8); \ - *(cp)++ = (u_char) (s); \ -} -#define GETLONG(l, cp) { \ - (l) = *(cp)++ << 8; \ - (l) |= *(cp)++; (l) <<= 8; \ - (l) |= *(cp)++; (l) <<= 8; \ - (l) |= *(cp)++; \ -} -#define PUTLONG(l, cp) { \ - *(cp)++ = (u_char) ((l) >> 24); \ - *(cp)++ = (u_char) ((l) >> 16); \ - *(cp)++ = (u_char) ((l) >> 8); \ - *(cp)++ = (u_char) (l); \ -} - -#define INCPTR(n, cp) ((cp) += (n)) -#define DECPTR(n, cp) ((cp) -= (n)) - -/* - * System dependent definitions for user-level 4.3BSD UNIX implementation. - */ -#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) -#define TIMEOUTMS(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t), (f), (a)); } while(0) -#define UNTIMEOUT(f, a) sys_untimeout((f), (a)) - -#define BZERO(s, n) memset(s, 0, n) -#define BCMP(s1, s2, l) memcmp(s1, s2, l) - -#define PRINTMSG(m, l) { ppp_info("Remote message: %0.*v", l, m); } - -/* - * MAKEHEADER - Add Header fields to a packet. - */ -#define MAKEHEADER(p, t) { \ - PUTCHAR(PPP_ALLSTATIONS, p); \ - PUTCHAR(PPP_UI, p); \ - PUTSHORT(t, p); } - -/* Procedures exported from auth.c */ -void link_required(ppp_pcb *pcb); /* we are starting to use the link */ -void link_terminated(ppp_pcb *pcb); /* we are finished with the link */ -void link_down(ppp_pcb *pcb); /* the LCP layer has left the Opened state */ -void upper_layers_down(ppp_pcb *pcb); /* take all NCPs down */ -void link_established(ppp_pcb *pcb); /* the link is up; authenticate now */ -void start_networks(ppp_pcb *pcb); /* start all the network control protos */ -void continue_networks(ppp_pcb *pcb); /* start network [ip, etc] control protos */ -#if PPP_AUTH_SUPPORT -#if PPP_SERVER -int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen); - /* check the user name and passwd against configuration */ -void auth_peer_fail(ppp_pcb *pcb, int protocol); - /* peer failed to authenticate itself */ -void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen); - /* peer successfully authenticated itself */ -#endif /* PPP_SERVER */ -void auth_withpeer_fail(ppp_pcb *pcb, int protocol); - /* we failed to authenticate ourselves */ -void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor); - /* we successfully authenticated ourselves */ -#endif /* PPP_AUTH_SUPPORT */ -void np_up(ppp_pcb *pcb, int proto); /* a network protocol has come up */ -void np_down(ppp_pcb *pcb, int proto); /* a network protocol has gone down */ -void np_finished(ppp_pcb *pcb, int proto); /* a network protocol no longer needs link */ -#if PPP_AUTH_SUPPORT -int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server); - /* get "secret" for chap */ -#endif /* PPP_AUTH_SUPPORT */ - -/* Procedures exported from ipcp.c */ -/* int parse_dotted_ip (char *, u32_t *); */ - -/* Procedures exported from demand.c */ -#if DEMAND_SUPPORT -void demand_conf (void); /* config interface(s) for demand-dial */ -void demand_block (void); /* set all NPs to queue up packets */ -void demand_unblock (void); /* set all NPs to pass packets */ -void demand_discard (void); /* set all NPs to discard packets */ -void demand_rexmit (int, u32_t); /* retransmit saved frames for an NP*/ -int loop_chars (unsigned char *, int); /* process chars from loopback */ -int loop_frame (unsigned char *, int); /* should we bring link up? */ -#endif /* DEMAND_SUPPORT */ - -/* Procedures exported from multilink.c */ -#ifdef HAVE_MULTILINK -void mp_check_options (void); /* Check multilink-related options */ -int mp_join_bundle (void); /* join our link to an appropriate bundle */ -void mp_exit_bundle (void); /* have disconnected our link from bundle */ -void mp_bundle_terminated (void); -char *epdisc_to_str (struct epdisc *); /* string from endpoint discrim. */ -int str_to_epdisc (struct epdisc *, char *); /* endpt disc. from str */ -#else -#define mp_bundle_terminated() /* nothing */ -#define mp_exit_bundle() /* nothing */ -#define doing_multilink 0 -#define multilink_master 0 -#endif - -/* Procedures exported from utils.c. */ -void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg); /* Format a string for output */ -int ppp_slprintf(char *buf, int buflen, const char *fmt, ...); /* sprintf++ */ -int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args); /* vsprintf++ */ -size_t ppp_strlcpy(char *dest, const char *src, size_t len); /* safe strcpy */ -size_t ppp_strlcat(char *dest, const char *src, size_t len); /* safe strncpy */ -void ppp_dbglog(const char *fmt, ...); /* log a debug message */ -void ppp_info(const char *fmt, ...); /* log an informational message */ -void ppp_notice(const char *fmt, ...); /* log a notice-level message */ -void ppp_warn(const char *fmt, ...); /* log a warning message */ -void ppp_error(const char *fmt, ...); /* log an error message */ -void ppp_fatal(const char *fmt, ...); /* log an error message and die(1) */ -#if PRINTPKT_SUPPORT -void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len); - /* dump packet to debug log if interesting */ -#endif /* PRINTPKT_SUPPORT */ - - -#endif /* PPP_SUPPORT */ -#endif /* LWIP_HDR_PPP_IMPL_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/ppp_opts.h b/components/net/lwip-2.0.2/src/include/netif/ppp/ppp_opts.h deleted file mode 100644 index fa79c090f2..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/ppp_opts.h +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#ifndef LWIP_PPP_OPTS_H -#define LWIP_PPP_OPTS_H - -#include "lwip/opt.h" - -/** - * PPP_SUPPORT==1: Enable PPP. - */ -#ifndef PPP_SUPPORT -#define PPP_SUPPORT 0 -#endif - -/** - * PPPOE_SUPPORT==1: Enable PPP Over Ethernet - */ -#ifndef PPPOE_SUPPORT -#define PPPOE_SUPPORT 0 -#endif - -/** - * PPPOL2TP_SUPPORT==1: Enable PPP Over L2TP - */ -#ifndef PPPOL2TP_SUPPORT -#define PPPOL2TP_SUPPORT 0 -#endif - -/** - * PPPOL2TP_AUTH_SUPPORT==1: Enable PPP Over L2TP Auth (enable MD5 support) - */ -#ifndef PPPOL2TP_AUTH_SUPPORT -#define PPPOL2TP_AUTH_SUPPORT PPPOL2TP_SUPPORT -#endif - -/** - * PPPOS_SUPPORT==1: Enable PPP Over Serial - */ -#ifndef PPPOS_SUPPORT -#define PPPOS_SUPPORT PPP_SUPPORT -#endif - -/** - * LWIP_PPP_API==1: Enable PPP API (in pppapi.c) - */ -#ifndef LWIP_PPP_API -#define LWIP_PPP_API (PPP_SUPPORT && (NO_SYS == 0)) -#endif - -/** - * MEMP_NUM_PPP_PCB: the number of simultaneously active PPP - * connections (requires the PPP_SUPPORT option) - */ -#ifndef MEMP_NUM_PPP_PCB -#define MEMP_NUM_PPP_PCB 1 -#endif - -#if PPP_SUPPORT - -/** - * MEMP_NUM_PPPOS_INTERFACES: the number of concurrently active PPPoS - * interfaces (only used with PPPOS_SUPPORT==1) - */ -#ifndef MEMP_NUM_PPPOS_INTERFACES -#define MEMP_NUM_PPPOS_INTERFACES MEMP_NUM_PPP_PCB -#endif - -/** - * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE - * interfaces (only used with PPPOE_SUPPORT==1) - */ -#ifndef MEMP_NUM_PPPOE_INTERFACES -#define MEMP_NUM_PPPOE_INTERFACES 1 -#endif - -/** - * MEMP_NUM_PPPOL2TP_INTERFACES: the number of concurrently active PPPoL2TP - * interfaces (only used with PPPOL2TP_SUPPORT==1) - */ -#ifndef MEMP_NUM_PPPOL2TP_INTERFACES -#define MEMP_NUM_PPPOL2TP_INTERFACES 1 -#endif - -/** - * MEMP_NUM_PPP_API_MSG: Number of concurrent PPP API messages (in pppapi.c) - */ -#ifndef MEMP_NUM_PPP_API_MSG -#define MEMP_NUM_PPP_API_MSG 5 -#endif - -/** - * PPP_DEBUG: Enable debugging for PPP. - */ -#ifndef PPP_DEBUG -#define PPP_DEBUG LWIP_DBG_OFF -#endif - -/** - * PPP_INPROC_IRQ_SAFE==1 call pppos_input() using tcpip_callback(). - * - * Please read the "PPPoS input path" chapter in the PPP documentation about this option. - */ -#ifndef PPP_INPROC_IRQ_SAFE -#define PPP_INPROC_IRQ_SAFE 0 -#endif - -/** - * PRINTPKT_SUPPORT==1: Enable PPP print packet support - * - * Mandatory for debugging, it displays exchanged packet content in debug trace. - */ -#ifndef PRINTPKT_SUPPORT -#define PRINTPKT_SUPPORT 0 -#endif - -/** - * PPP_IPV4_SUPPORT==1: Enable PPP IPv4 support - */ -#ifndef PPP_IPV4_SUPPORT -#define PPP_IPV4_SUPPORT (LWIP_IPV4) -#endif - -/** - * PPP_IPV6_SUPPORT==1: Enable PPP IPv6 support - */ -#ifndef PPP_IPV6_SUPPORT -#define PPP_IPV6_SUPPORT (LWIP_IPV6) -#endif - -/** - * PPP_NOTIFY_PHASE==1: Support PPP notify phase support - * - * PPP notify phase support allows you to set a callback which is - * called on change of the internal PPP state machine. - * - * This can be used for example to set a LED pattern depending on the - * current phase of the PPP session. - */ -#ifndef PPP_NOTIFY_PHASE -#define PPP_NOTIFY_PHASE 0 -#endif - -/** - * pbuf_type PPP is using for LCP, PAP, CHAP, EAP, CCP, IPCP and IP6CP packets. - * - * Memory allocated must be single buffered for PPP to works, it requires pbuf - * that are not going to be chained when allocated. This requires setting - * PBUF_POOL_BUFSIZE to at least 512 bytes, which is quite huge for small systems. - * - * Setting PPP_USE_PBUF_RAM to 1 makes PPP use memory from heap where continuous - * buffers are required, allowing you to use a smaller PBUF_POOL_BUFSIZE. - */ -#ifndef PPP_USE_PBUF_RAM -#define PPP_USE_PBUF_RAM 0 -#endif - -/** - * PPP_FCS_TABLE: Keep a 256*2 byte table to speed up FCS calculation for PPPoS - */ -#ifndef PPP_FCS_TABLE -#define PPP_FCS_TABLE 1 -#endif - -/** - * PAP_SUPPORT==1: Support PAP. - */ -#ifndef PAP_SUPPORT -#define PAP_SUPPORT 0 -#endif - -/** - * CHAP_SUPPORT==1: Support CHAP. - */ -#ifndef CHAP_SUPPORT -#define CHAP_SUPPORT 0 -#endif - -/** - * MSCHAP_SUPPORT==1: Support MSCHAP. - */ -#ifndef MSCHAP_SUPPORT -#define MSCHAP_SUPPORT 0 -#endif -#if MSCHAP_SUPPORT -/* MSCHAP requires CHAP support */ -#undef CHAP_SUPPORT -#define CHAP_SUPPORT 1 -#endif /* MSCHAP_SUPPORT */ - -/** - * EAP_SUPPORT==1: Support EAP. - */ -#ifndef EAP_SUPPORT -#define EAP_SUPPORT 0 -#endif - -/** - * CCP_SUPPORT==1: Support CCP. - */ -#ifndef CCP_SUPPORT -#define CCP_SUPPORT 0 -#endif - -/** - * MPPE_SUPPORT==1: Support MPPE. - */ -#ifndef MPPE_SUPPORT -#define MPPE_SUPPORT 0 -#endif -#if MPPE_SUPPORT -/* MPPE requires CCP support */ -#undef CCP_SUPPORT -#define CCP_SUPPORT 1 -/* MPPE requires MSCHAP support */ -#undef MSCHAP_SUPPORT -#define MSCHAP_SUPPORT 1 -/* MSCHAP requires CHAP support */ -#undef CHAP_SUPPORT -#define CHAP_SUPPORT 1 -#endif /* MPPE_SUPPORT */ - -/** - * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! - */ -#ifndef CBCP_SUPPORT -#define CBCP_SUPPORT 0 -#endif - -/** - * ECP_SUPPORT==1: Support ECP. CURRENTLY NOT SUPPORTED! DO NOT SET! - */ -#ifndef ECP_SUPPORT -#define ECP_SUPPORT 0 -#endif - -/** - * DEMAND_SUPPORT==1: Support dial on demand. CURRENTLY NOT SUPPORTED! DO NOT SET! - */ -#ifndef DEMAND_SUPPORT -#define DEMAND_SUPPORT 0 -#endif - -/** - * LQR_SUPPORT==1: Support Link Quality Report. Do nothing except exchanging some LCP packets. - */ -#ifndef LQR_SUPPORT -#define LQR_SUPPORT 0 -#endif - -/** - * PPP_SERVER==1: Enable PPP server support (waiting for incoming PPP session). - * - * Currently only supported for PPPoS. - */ -#ifndef PPP_SERVER -#define PPP_SERVER 0 -#endif - -#if PPP_SERVER -/* - * PPP_OUR_NAME: Our name for authentication purposes - */ -#ifndef PPP_OUR_NAME -#define PPP_OUR_NAME "lwIP" -#endif -#endif /* PPP_SERVER */ - -/** - * VJ_SUPPORT==1: Support VJ header compression. - */ -#ifndef VJ_SUPPORT -#define VJ_SUPPORT 1 -#endif -/* VJ compression is only supported for TCP over IPv4 over PPPoS. */ -#if !PPPOS_SUPPORT || !PPP_IPV4_SUPPORT || !LWIP_TCP -#undef VJ_SUPPORT -#define VJ_SUPPORT 0 -#endif /* !PPPOS_SUPPORT */ - -/** - * PPP_MD5_RANDM==1: Use MD5 for better randomness. - * Enabled by default if CHAP, EAP, or L2TP AUTH support is enabled. - */ -#ifndef PPP_MD5_RANDM -#define PPP_MD5_RANDM (CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT) -#endif - -/** - * PolarSSL embedded library - * - * - * lwIP contains some files fetched from the latest BSD release of - * the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption - * methods we need for lwIP PPP support. - * - * The PolarSSL files were cleaned to contain only the necessary struct - * fields and functions needed for lwIP. - * - * The PolarSSL API was not changed at all, so if you are already using - * PolarSSL you can choose to skip the compilation of the included PolarSSL - * library into lwIP. - * - * If you are not using the embedded copy you must include external - * libraries into your arch/cc.h port file. - * - * Beware of the stack requirements which can be a lot larger if you are not - * using our cleaned PolarSSL library. - */ - -/** - * LWIP_USE_EXTERNAL_POLARSSL: Use external PolarSSL library - */ -#ifndef LWIP_USE_EXTERNAL_POLARSSL -#define LWIP_USE_EXTERNAL_POLARSSL 0 -#endif - -/** - * LWIP_USE_EXTERNAL_MBEDTLS: Use external mbed TLS library - */ -#ifndef LWIP_USE_EXTERNAL_MBEDTLS -#define LWIP_USE_EXTERNAL_MBEDTLS 0 -#endif - -/* - * PPP Timeouts - */ - -/** - * FSM_DEFTIMEOUT: Timeout time in seconds - */ -#ifndef FSM_DEFTIMEOUT -#define FSM_DEFTIMEOUT 6 -#endif - -/** - * FSM_DEFMAXTERMREQS: Maximum Terminate-Request transmissions - */ -#ifndef FSM_DEFMAXTERMREQS -#define FSM_DEFMAXTERMREQS 2 -#endif - -/** - * FSM_DEFMAXCONFREQS: Maximum Configure-Request transmissions - */ -#ifndef FSM_DEFMAXCONFREQS -#define FSM_DEFMAXCONFREQS 10 -#endif - -/** - * FSM_DEFMAXNAKLOOPS: Maximum number of nak loops - */ -#ifndef FSM_DEFMAXNAKLOOPS -#define FSM_DEFMAXNAKLOOPS 5 -#endif - -/** - * UPAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req - */ -#ifndef UPAP_DEFTIMEOUT -#define UPAP_DEFTIMEOUT 6 -#endif - -/** - * UPAP_DEFTRANSMITS: Maximum number of auth-reqs to send - */ -#ifndef UPAP_DEFTRANSMITS -#define UPAP_DEFTRANSMITS 10 -#endif - -#if PPP_SERVER -/** - * UPAP_DEFREQTIME: Time to wait for auth-req from peer - */ -#ifndef UPAP_DEFREQTIME -#define UPAP_DEFREQTIME 30 -#endif -#endif /* PPP_SERVER */ - -/** - * CHAP_DEFTIMEOUT: Timeout (seconds) for retransmitting req - */ -#ifndef CHAP_DEFTIMEOUT -#define CHAP_DEFTIMEOUT 6 -#endif - -/** - * CHAP_DEFTRANSMITS: max # times to send challenge - */ -#ifndef CHAP_DEFTRANSMITS -#define CHAP_DEFTRANSMITS 10 -#endif - -#if PPP_SERVER -/** - * CHAP_DEFRECHALLENGETIME: If this option is > 0, rechallenge the peer every n seconds - */ -#ifndef CHAP_DEFRECHALLENGETIME -#define CHAP_DEFRECHALLENGETIME 0 -#endif -#endif /* PPP_SERVER */ - -/** - * EAP_DEFREQTIME: Time to wait for peer request - */ -#ifndef EAP_DEFREQTIME -#define EAP_DEFREQTIME 6 -#endif - -/** - * EAP_DEFALLOWREQ: max # times to accept requests - */ -#ifndef EAP_DEFALLOWREQ -#define EAP_DEFALLOWREQ 10 -#endif - -#if PPP_SERVER -/** - * EAP_DEFTIMEOUT: Timeout (seconds) for rexmit - */ -#ifndef EAP_DEFTIMEOUT -#define EAP_DEFTIMEOUT 6 -#endif - -/** - * EAP_DEFTRANSMITS: max # times to transmit - */ -#ifndef EAP_DEFTRANSMITS -#define EAP_DEFTRANSMITS 10 -#endif -#endif /* PPP_SERVER */ - -/** - * LCP_DEFLOOPBACKFAIL: Default number of times we receive our magic number from the peer - * before deciding the link is looped-back. - */ -#ifndef LCP_DEFLOOPBACKFAIL -#define LCP_DEFLOOPBACKFAIL 10 -#endif - -/** - * LCP_ECHOINTERVAL: Interval in seconds between keepalive echo requests, 0 to disable. - */ -#ifndef LCP_ECHOINTERVAL -#define LCP_ECHOINTERVAL 0 -#endif - -/** - * LCP_MAXECHOFAILS: Number of unanswered echo requests before failure. - */ -#ifndef LCP_MAXECHOFAILS -#define LCP_MAXECHOFAILS 3 -#endif - -/** - * PPP_MAXIDLEFLAG: Max Xmit idle time (in ms) before resend flag char. - */ -#ifndef PPP_MAXIDLEFLAG -#define PPP_MAXIDLEFLAG 100 -#endif - -/** - * PPP Packet sizes - */ - -/** - * PPP_MRU: Default MRU - */ -#ifndef PPP_MRU -#define PPP_MRU 1500 -#endif - -/** - * PPP_DEFMRU: Default MRU to try - */ -#ifndef PPP_DEFMRU -#define PPP_DEFMRU 1500 -#endif - -/** - * PPP_MAXMRU: Normally limit MRU to this (pppd default = 16384) - */ -#ifndef PPP_MAXMRU -#define PPP_MAXMRU 1500 -#endif - -/** - * PPP_MINMRU: No MRUs below this - */ -#ifndef PPP_MINMRU -#define PPP_MINMRU 128 -#endif - -/** - * PPPOL2TP_DEFMRU: Default MTU and MRU for L2TP - * Default = 1500 - PPPoE(6) - PPP Protocol(2) - IPv4 header(20) - UDP Header(8) - * - L2TP Header(6) - HDLC Header(2) - PPP Protocol(2) - MPPE Header(2) - PPP Protocol(2) - */ -#if PPPOL2TP_SUPPORT -#ifndef PPPOL2TP_DEFMRU -#define PPPOL2TP_DEFMRU 1450 -#endif -#endif /* PPPOL2TP_SUPPORT */ - -/** - * MAXNAMELEN: max length of hostname or name for auth - */ -#ifndef MAXNAMELEN -#define MAXNAMELEN 256 -#endif - -/** - * MAXSECRETLEN: max length of password or secret - */ -#ifndef MAXSECRETLEN -#define MAXSECRETLEN 256 -#endif - -/* ------------------------------------------------------------------------- */ - -/* - * Build triggers for embedded PolarSSL - */ -#if !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS - -/* CHAP, EAP, L2TP AUTH and MD5 Random require MD5 support */ -#if CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM -#define LWIP_INCLUDED_POLARSSL_MD5 1 -#endif /* CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT || PPP_MD5_RANDM */ - -#if MSCHAP_SUPPORT - -/* MSCHAP require MD4 support */ -#define LWIP_INCLUDED_POLARSSL_MD4 1 -/* MSCHAP require SHA1 support */ -#define LWIP_INCLUDED_POLARSSL_SHA1 1 -/* MSCHAP require DES support */ -#define LWIP_INCLUDED_POLARSSL_DES 1 - -/* MS-CHAP support is required for MPPE */ -#if MPPE_SUPPORT -/* MPPE require ARC4 support */ -#define LWIP_INCLUDED_POLARSSL_ARC4 1 -#endif /* MPPE_SUPPORT */ - -#endif /* MSCHAP_SUPPORT */ - -#endif /* !LWIP_USE_EXTERNAL_POLARSSL && !LWIP_USE_EXTERNAL_MBEDTLS */ - -/* Default value if unset */ -#ifndef LWIP_INCLUDED_POLARSSL_MD4 -#define LWIP_INCLUDED_POLARSSL_MD4 0 -#endif /* LWIP_INCLUDED_POLARSSL_MD4 */ -#ifndef LWIP_INCLUDED_POLARSSL_MD5 -#define LWIP_INCLUDED_POLARSSL_MD5 0 -#endif /* LWIP_INCLUDED_POLARSSL_MD5 */ -#ifndef LWIP_INCLUDED_POLARSSL_SHA1 -#define LWIP_INCLUDED_POLARSSL_SHA1 0 -#endif /* LWIP_INCLUDED_POLARSSL_SHA1 */ -#ifndef LWIP_INCLUDED_POLARSSL_DES -#define LWIP_INCLUDED_POLARSSL_DES 0 -#endif /* LWIP_INCLUDED_POLARSSL_DES */ -#ifndef LWIP_INCLUDED_POLARSSL_ARC4 -#define LWIP_INCLUDED_POLARSSL_ARC4 0 -#endif /* LWIP_INCLUDED_POLARSSL_ARC4 */ - -#endif /* PPP_SUPPORT */ - -#endif /* LWIP_PPP_OPTS_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/pppapi.h b/components/net/lwip-2.0.2/src/include/netif/ppp/pppapi.h deleted file mode 100644 index 913d93f749..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/pppapi.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#ifndef LWIP_PPPAPI_H -#define LWIP_PPPAPI_H - -#include "netif/ppp/ppp_opts.h" - -#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/sys.h" -#include "lwip/netif.h" -#include "lwip/priv/tcpip_priv.h" -#include "netif/ppp/ppp.h" -#if PPPOS_SUPPORT -#include "netif/ppp/pppos.h" -#endif /* PPPOS_SUPPORT */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct pppapi_msg_msg { - ppp_pcb *ppp; - union { -#if PPP_NOTIFY_PHASE - struct { - ppp_notify_phase_cb_fn notify_phase_cb; - } setnotifyphasecb; -#endif /* PPP_NOTIFY_PHASE */ -#if PPPOS_SUPPORT - struct { - struct netif *pppif; - pppos_output_cb_fn output_cb; - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } serialcreate; -#endif /* PPPOS_SUPPORT */ -#if PPPOE_SUPPORT - struct { - struct netif *pppif; - struct netif *ethif; - const char *service_name; - const char *concentrator_name; - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } ethernetcreate; -#endif /* PPPOE_SUPPORT */ -#if PPPOL2TP_SUPPORT - struct { - struct netif *pppif; - struct netif *netif; - API_MSG_M_DEF_C(ip_addr_t, ipaddr); - u16_t port; -#if PPPOL2TP_AUTH_SUPPORT - const u8_t *secret; - u8_t secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - ppp_link_status_cb_fn link_status_cb; - void *ctx_cb; - } l2tpcreate; -#endif /* PPPOL2TP_SUPPORT */ - struct { - u16_t holdoff; - } connect; - struct { - u8_t nocarrier; - } close; - struct { - u8_t cmd; - void *arg; - } ioctl; - } msg; -}; - -struct pppapi_msg { - struct tcpip_api_call_data call; - struct pppapi_msg_msg msg; -}; - -/* API for application */ -err_t pppapi_set_default(ppp_pcb *pcb); -#if PPP_NOTIFY_PHASE -err_t pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb); -#endif /* PPP_NOTIFY_PHASE */ -#if PPPOS_SUPPORT -ppp_pcb *pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOS_SUPPORT */ -#if PPPOE_SUPPORT -ppp_pcb *pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, - const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, - void *ctx_cb); -#endif /* PPPOE_SUPPORT */ -#if PPPOL2TP_SUPPORT -ppp_pcb *pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); -#endif /* PPPOL2TP_SUPPORT */ -err_t pppapi_connect(ppp_pcb *pcb, u16_t holdoff); -#if PPP_SERVER -err_t pppapi_listen(ppp_pcb *pcb); -#endif /* PPP_SERVER */ -err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier); -err_t pppapi_free(ppp_pcb *pcb); -err_t pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_PPP_API */ - -#endif /* LWIP_PPPAPI_H */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/pppcrypt.h b/components/net/lwip-2.0.2/src/include/netif/ppp/pppcrypt.h deleted file mode 100644 index a7b2099f25..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/pppcrypt.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 - * - * Extracted from chap_ms.c by James Carlson. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* This header file is included in all PPP modules needing hashes and/or ciphers */ - -#ifndef PPPCRYPT_H -#define PPPCRYPT_H - -/* - * If included PolarSSL copy is not used, user is expected to include - * external libraries in arch/cc.h (which is included by lwip/arch.h). - */ -#include "lwip/arch.h" - -/* - * Map hashes and ciphers functions to PolarSSL - */ -#if !LWIP_USE_EXTERNAL_MBEDTLS - -#include "netif/ppp/polarssl/md4.h" -#define lwip_md4_context md4_context -#define lwip_md4_init(context) -#define lwip_md4_starts md4_starts -#define lwip_md4_update md4_update -#define lwip_md4_finish md4_finish -#define lwip_md4_free(context) - -#include "netif/ppp/polarssl/md5.h" -#define lwip_md5_context md5_context -#define lwip_md5_init(context) -#define lwip_md5_starts md5_starts -#define lwip_md5_update md5_update -#define lwip_md5_finish md5_finish -#define lwip_md5_free(context) - -#include "netif/ppp/polarssl/sha1.h" -#define lwip_sha1_context sha1_context -#define lwip_sha1_init(context) -#define lwip_sha1_starts sha1_starts -#define lwip_sha1_update sha1_update -#define lwip_sha1_finish sha1_finish -#define lwip_sha1_free(context) - -#include "netif/ppp/polarssl/des.h" -#define lwip_des_context des_context -#define lwip_des_init(context) -#define lwip_des_setkey_enc des_setkey_enc -#define lwip_des_crypt_ecb des_crypt_ecb -#define lwip_des_free(context) - -#include "netif/ppp/polarssl/arc4.h" -#define lwip_arc4_context arc4_context -#define lwip_arc4_init(context) -#define lwip_arc4_setup arc4_setup -#define lwip_arc4_crypt arc4_crypt -#define lwip_arc4_free(context) - -#endif /* !LWIP_USE_EXTERNAL_MBEDTLS */ - -/* - * Map hashes and ciphers functions to mbed TLS - */ -#if LWIP_USE_EXTERNAL_MBEDTLS - -#define lwip_md4_context mbedtls_md4_context -#define lwip_md4_init mbedtls_md4_init -#define lwip_md4_starts mbedtls_md4_starts -#define lwip_md4_update mbedtls_md4_update -#define lwip_md4_finish mbedtls_md4_finish -#define lwip_md4_free mbedtls_md4_free - -#define lwip_md5_context mbedtls_md5_context -#define lwip_md5_init mbedtls_md5_init -#define lwip_md5_starts mbedtls_md5_starts -#define lwip_md5_update mbedtls_md5_update -#define lwip_md5_finish mbedtls_md5_finish -#define lwip_md5_free mbedtls_md5_free - -#define lwip_sha1_context mbedtls_sha1_context -#define lwip_sha1_init mbedtls_sha1_init -#define lwip_sha1_starts mbedtls_sha1_starts -#define lwip_sha1_update mbedtls_sha1_update -#define lwip_sha1_finish mbedtls_sha1_finish -#define lwip_sha1_free mbedtls_sha1_free - -#define lwip_des_context mbedtls_des_context -#define lwip_des_init mbedtls_des_init -#define lwip_des_setkey_enc mbedtls_des_setkey_enc -#define lwip_des_crypt_ecb mbedtls_des_crypt_ecb -#define lwip_des_free mbedtls_des_free - -#define lwip_arc4_context mbedtls_arc4_context -#define lwip_arc4_init mbedtls_arc4_init -#define lwip_arc4_setup mbedtls_arc4_setup -#define lwip_arc4_crypt(context, buffer, length) mbedtls_arc4_crypt(context, length, buffer, buffer) -#define lwip_arc4_free mbedtls_arc4_free - -#endif /* LWIP_USE_EXTERNAL_MBEDTLS */ - -void pppcrypt_56_to_64_bit_key(u_char *key, u_char *des_key); - -#endif /* PPPCRYPT_H */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/pppdebug.h b/components/net/lwip-2.0.2/src/include/netif/ppp/pppdebug.h deleted file mode 100644 index 7ead045910..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/pppdebug.h +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** -* pppdebug.h - System debugging utilities. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1998 Global Election Systems Inc. -* portions Copyright (c) 2001 by Cognizant Pty Ltd. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY (please don't use tabs!) -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-07-29 Guy Lancaster , Global Election Systems Inc. -* Original. -* -***************************************************************************** -*/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPPDEBUG_H -#define PPPDEBUG_H - -/* Trace levels. */ -#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) -#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) -#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define LOG_INFO (PPP_DEBUG) -#define LOG_DETAIL (PPP_DEBUG) -#define LOG_DEBUG (PPP_DEBUG) - -#if PPP_DEBUG - -#define MAINDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define SYSDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define FSMDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define LCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define IPCPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define IPV6CPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define UPAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define CHAPDEBUG(a) LWIP_DEBUGF(LWIP_DBG_LEVEL_WARNING, a) -#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) - -#else /* PPP_DEBUG */ - -#define MAINDEBUG(a) -#define SYSDEBUG(a) -#define FSMDEBUG(a) -#define LCPDEBUG(a) -#define IPCPDEBUG(a) -#define IPV6CPDEBUG(a) -#define UPAPDEBUG(a) -#define CHAPDEBUG(a) -#define PPPDEBUG(a, b) - -#endif /* PPP_DEBUG */ - -#endif /* PPPDEBUG_H */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/pppoe.h b/components/net/lwip-2.0.2/src/include/netif/ppp/pppoe.h deleted file mode 100644 index 9f8f2892b4..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/pppoe.h +++ /dev/null @@ -1,179 +0,0 @@ -/***************************************************************************** -* pppoe.h - PPP Over Ethernet implementation for lwIP. -* -* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 06-01-01 Marc Boucher -* Ported to lwIP. -*****************************************************************************/ - - - -/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ - -/*- - * Copyright (c) 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Martin Husemann . - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPP_OE_H -#define PPP_OE_H - -#include "ppp.h" -#include "lwip/etharp.h" - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppoehdr { - PACK_STRUCT_FLD_8(u8_t vertype); - PACK_STRUCT_FLD_8(u8_t code); - PACK_STRUCT_FIELD(u16_t session); - PACK_STRUCT_FIELD(u16_t plen); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppoetag { - PACK_STRUCT_FIELD(u16_t tag); - PACK_STRUCT_FIELD(u16_t len); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - - -#define PPPOE_STATE_INITIAL 0 -#define PPPOE_STATE_PADI_SENT 1 -#define PPPOE_STATE_PADR_SENT 2 -#define PPPOE_STATE_SESSION 3 -/* passive */ -#define PPPOE_STATE_PADO_SENT 1 - -#define PPPOE_HEADERLEN sizeof(struct pppoehdr) -#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */ - -#define PPPOE_TAG_EOL 0x0000 /* end of list */ -#define PPPOE_TAG_SNAME 0x0101 /* service name */ -#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */ -#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */ -#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */ -#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */ -#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */ -#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */ -#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */ -#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */ - -#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ -#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ -#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ -#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ -#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ - -#ifndef PPPOE_MAX_AC_COOKIE_LEN -#define PPPOE_MAX_AC_COOKIE_LEN 64 -#endif - -struct pppoe_softc { - struct pppoe_softc *next; - struct netif *sc_ethif; /* ethernet interface we are using */ - ppp_pcb *pcb; /* PPP PCB */ - - struct eth_addr sc_dest; /* hardware address of concentrator */ - u16_t sc_session; /* PPPoE session id */ - u8_t sc_state; /* discovery phase or session connected */ - -#ifdef PPPOE_TODO - u8_t *sc_service_name; /* if != NULL: requested name of service */ - u8_t *sc_concentrator_name; /* if != NULL: requested concentrator id */ -#endif /* PPPOE_TODO */ - u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */ - u8_t sc_ac_cookie_len; /* length of cookie data */ -#ifdef PPPOE_SERVER - u8_t *sc_hunique; /* content of host unique we must echo back */ - u8_t sc_hunique_len; /* length of host unique */ -#endif - u8_t sc_padi_retried; /* number of PADI retries already done */ - u8_t sc_padr_retried; /* number of PADR retries already done */ -}; - - -#define pppoe_init() /* compatibility define, no initialization needed */ - -ppp_pcb *pppoe_create(struct netif *pppif, - struct netif *ethif, - const char *service_name, const char *concentrator_name, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -/* - * Functions called from lwIP - * DO NOT CALL FROM lwIP USER APPLICATION. - */ -void pppoe_disc_input(struct netif *netif, struct pbuf *p); -void pppoe_data_input(struct netif *netif, struct pbuf *p); - -#endif /* PPP_OE_H */ - -#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/pppol2tp.h b/components/net/lwip-2.0.2/src/include/netif/ppp/pppol2tp.h deleted file mode 100644 index f03950e65d..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/pppol2tp.h +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Layer 2 Tunneling Protocol header file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPPOL2TP_H -#define PPPOL2TP_H - -#include "ppp.h" - -/* Timeout */ -#define PPPOL2TP_CONTROL_TIMEOUT (5*1000) /* base for quick timeout calculation */ -#define PPPOL2TP_SLOW_RETRY (60*1000) /* persistent retry interval */ - -#define PPPOL2TP_MAXSCCRQ 4 /* retry SCCRQ four times (quickly) */ -#define PPPOL2TP_MAXICRQ 4 /* retry IRCQ four times */ -#define PPPOL2TP_MAXICCN 4 /* retry ICCN four times */ - -/* L2TP header flags */ -#define PPPOL2TP_HEADERFLAG_CONTROL 0x8000 -#define PPPOL2TP_HEADERFLAG_LENGTH 0x4000 -#define PPPOL2TP_HEADERFLAG_SEQUENCE 0x0800 -#define PPPOL2TP_HEADERFLAG_OFFSET 0x0200 -#define PPPOL2TP_HEADERFLAG_PRIORITY 0x0100 -#define PPPOL2TP_HEADERFLAG_VERSION 0x0002 - -/* Mandatory bits for control: Control, Length, Sequence, Version 2 */ -#define PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY (PPPOL2TP_HEADERFLAG_CONTROL|PPPOL2TP_HEADERFLAG_LENGTH|PPPOL2TP_HEADERFLAG_SEQUENCE|PPPOL2TP_HEADERFLAG_VERSION) -/* Forbidden bits for control: Offset, Priority */ -#define PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN (PPPOL2TP_HEADERFLAG_OFFSET|PPPOL2TP_HEADERFLAG_PRIORITY) - -/* Mandatory bits for data: Version 2 */ -#define PPPOL2TP_HEADERFLAG_DATA_MANDATORY (PPPOL2TP_HEADERFLAG_VERSION) - -/* AVP (Attribute Value Pair) header */ -#define PPPOL2TP_AVPHEADERFLAG_MANDATORY 0x8000 -#define PPPOL2TP_AVPHEADERFLAG_HIDDEN 0x4000 -#define PPPOL2TP_AVPHEADERFLAG_LENGTHMASK 0x03ff - -/* -- AVP - Message type */ -#define PPPOL2TP_AVPTYPE_MESSAGE 0 /* Message type */ - -/* Control Connection Management */ -#define PPPOL2TP_MESSAGETYPE_SCCRQ 1 /* Start Control Connection Request */ -#define PPPOL2TP_MESSAGETYPE_SCCRP 2 /* Start Control Connection Reply */ -#define PPPOL2TP_MESSAGETYPE_SCCCN 3 /* Start Control Connection Connected */ -#define PPPOL2TP_MESSAGETYPE_STOPCCN 4 /* Stop Control Connection Notification */ -#define PPPOL2TP_MESSAGETYPE_HELLO 6 /* Hello */ -/* Call Management */ -#define PPPOL2TP_MESSAGETYPE_OCRQ 7 /* Outgoing Call Request */ -#define PPPOL2TP_MESSAGETYPE_OCRP 8 /* Outgoing Call Reply */ -#define PPPOL2TP_MESSAGETYPE_OCCN 9 /* Outgoing Call Connected */ -#define PPPOL2TP_MESSAGETYPE_ICRQ 10 /* Incoming Call Request */ -#define PPPOL2TP_MESSAGETYPE_ICRP 11 /* Incoming Call Reply */ -#define PPPOL2TP_MESSAGETYPE_ICCN 12 /* Incoming Call Connected */ -#define PPPOL2TP_MESSAGETYPE_CDN 14 /* Call Disconnect Notify */ -/* Error reporting */ -#define PPPOL2TP_MESSAGETYPE_WEN 15 /* WAN Error Notify */ -/* PPP Session Control */ -#define PPPOL2TP_MESSAGETYPE_SLI 16 /* Set Link Info */ - -/* -- AVP - Result code */ -#define PPPOL2TP_AVPTYPE_RESULTCODE 1 /* Result code */ -#define PPPOL2TP_RESULTCODE 1 /* General request to clear control connection */ - -/* -- AVP - Protocol version (!= L2TP Header version) */ -#define PPPOL2TP_AVPTYPE_VERSION 2 -#define PPPOL2TP_VERSION 0x0100 /* L2TP Protocol version 1, revision 0 */ - -/* -- AVP - Framing capabilities */ -#define PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES 3 /* Bearer capabilities */ -#define PPPOL2TP_FRAMINGCAPABILITIES 0x00000003 /* Async + Sync framing */ - -/* -- AVP - Bearer capabilities */ -#define PPPOL2TP_AVPTYPE_BEARERCAPABILITIES 4 /* Bearer capabilities */ -#define PPPOL2TP_BEARERCAPABILITIES 0x00000003 /* Analog + Digital Access */ - -/* -- AVP - Tie breaker */ -#define PPPOL2TP_AVPTYPE_TIEBREAKER 5 - -/* -- AVP - Host name */ -#define PPPOL2TP_AVPTYPE_HOSTNAME 7 /* Host name */ -#define PPPOL2TP_HOSTNAME "lwIP" /* FIXME: make it configurable */ - -/* -- AVP - Vendor name */ -#define PPPOL2TP_AVPTYPE_VENDORNAME 8 /* Vendor name */ -#define PPPOL2TP_VENDORNAME "lwIP" /* FIXME: make it configurable */ - -/* -- AVP - Assign tunnel ID */ -#define PPPOL2TP_AVPTYPE_TUNNELID 9 /* Assign Tunnel ID */ - -/* -- AVP - Receive window size */ -#define PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE 10 /* Receive window size */ -#define PPPOL2TP_RECEIVEWINDOWSIZE 8 /* FIXME: make it configurable */ - -/* -- AVP - Challenge */ -#define PPPOL2TP_AVPTYPE_CHALLENGE 11 /* Challenge */ - -/* -- AVP - Cause code */ -#define PPPOL2TP_AVPTYPE_CAUSECODE 12 /* Cause code*/ - -/* -- AVP - Challenge response */ -#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE 13 /* Challenge response */ -#define PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE 16 - -/* -- AVP - Assign session ID */ -#define PPPOL2TP_AVPTYPE_SESSIONID 14 /* Assign Session ID */ - -/* -- AVP - Call serial number */ -#define PPPOL2TP_AVPTYPE_CALLSERIALNUMBER 15 /* Call Serial Number */ - -/* -- AVP - Framing type */ -#define PPPOL2TP_AVPTYPE_FRAMINGTYPE 19 /* Framing Type */ -#define PPPOL2TP_FRAMINGTYPE 0x00000001 /* Sync framing */ - -/* -- AVP - TX Connect Speed */ -#define PPPOL2TP_AVPTYPE_TXCONNECTSPEED 24 /* TX Connect Speed */ -#define PPPOL2TP_TXCONNECTSPEED 100000000 /* Connect speed: 100 Mbits/s */ - -/* L2TP Session state */ -#define PPPOL2TP_STATE_INITIAL 0 -#define PPPOL2TP_STATE_SCCRQ_SENT 1 -#define PPPOL2TP_STATE_ICRQ_SENT 2 -#define PPPOL2TP_STATE_ICCN_SENT 3 -#define PPPOL2TP_STATE_DATA 4 - -#define PPPOL2TP_OUTPUT_DATA_HEADER_LEN 6 /* Our data header len */ - -/* - * PPPoL2TP interface control block. - */ -typedef struct pppol2tp_pcb_s pppol2tp_pcb; -struct pppol2tp_pcb_s { - ppp_pcb *ppp; /* PPP PCB */ - u8_t phase; /* L2TP phase */ - struct udp_pcb *udp; /* UDP L2TP Socket */ - struct netif *netif; /* Output interface, used as a default route */ - ip_addr_t remote_ip; /* LNS IP Address */ - u16_t remote_port; /* LNS port */ -#if PPPOL2TP_AUTH_SUPPORT - const u8_t *secret; /* Secret string */ - u8_t secret_len; /* Secret string length */ - u8_t secret_rv[16]; /* Random vector */ - u8_t challenge_hash[16]; /* Challenge response */ - u8_t send_challenge; /* Boolean whether the next sent packet should contains a challenge response */ -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - u16_t tunnel_port; /* Tunnel port */ - u16_t our_ns; /* NS to peer */ - u16_t peer_nr; /* NR from peer */ - u16_t peer_ns; /* NS from peer */ - u16_t source_tunnel_id; /* Tunnel ID assigned by peer */ - u16_t remote_tunnel_id; /* Tunnel ID assigned to peer */ - u16_t source_session_id; /* Session ID assigned by peer */ - u16_t remote_session_id; /* Session ID assigned to peer */ - - u8_t sccrq_retried; /* number of SCCRQ retries already done */ - u8_t icrq_retried; /* number of ICRQ retries already done */ - u8_t iccn_retried; /* number of ICCN retries already done */ -}; - - -/* Create a new L2TP session. */ -ppp_pcb *pppol2tp_create(struct netif *pppif, - struct netif *netif, const ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -#endif /* PPPOL2TP_H */ -#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/pppos.h b/components/net/lwip-2.0.2/src/include/netif/ppp/pppos.h deleted file mode 100644 index d924a9fc7e..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/pppos.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Serial header file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef PPPOS_H -#define PPPOS_H - -#include "lwip/sys.h" - -#include "ppp.h" -#include "vj.h" - -/* PPP packet parser states. Current state indicates operation yet to be - * completed. */ -enum { - PDIDLE = 0, /* Idle state - waiting. */ - PDSTART, /* Process start flag. */ - PDADDRESS, /* Process address field. */ - PDCONTROL, /* Process control field. */ - PDPROTOCOL1, /* Process protocol field 1. */ - PDPROTOCOL2, /* Process protocol field 2. */ - PDDATA /* Process data byte. */ -}; - -/* PPPoS serial output callback function prototype */ -typedef u32_t (*pppos_output_cb_fn)(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx); - -/* - * Extended asyncmap - allows any character to be escaped. - */ -typedef u8_t ext_accm[32]; - -/* - * PPPoS interface control block. - */ -typedef struct pppos_pcb_s pppos_pcb; -struct pppos_pcb_s { - /* -- below are data that will NOT be cleared between two sessions */ - ppp_pcb *ppp; /* PPP PCB */ - pppos_output_cb_fn output_cb; /* PPP serial output callback */ - - /* -- below are data that will be cleared between two sessions - * - * last_xmit must be the first member of cleared members, because it is - * used to know which part must not be cleared. - */ - u32_t last_xmit; /* Time of last transmission. */ - ext_accm out_accm; /* Async-Ctl-Char-Map for output. */ - - /* flags */ - unsigned int open :1; /* Set if PPPoS is open */ - unsigned int pcomp :1; /* Does peer accept protocol compression? */ - unsigned int accomp :1; /* Does peer accept addr/ctl compression? */ - - /* PPPoS rx */ - ext_accm in_accm; /* Async-Ctl-Char-Map for input. */ - struct pbuf *in_head, *in_tail; /* The input packet. */ - u16_t in_protocol; /* The input protocol code. */ - u16_t in_fcs; /* Input Frame Check Sequence value. */ - u8_t in_state; /* The input process state. */ - u8_t in_escaped; /* Escape next character. */ -}; - -/* Create a new PPPoS session. */ -ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb); - -#if !NO_SYS && !PPP_INPROC_IRQ_SAFE -/* Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. */ -err_t pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l); -#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ - -/* PPP over Serial: this is the input function to be called for received data. */ -void pppos_input(ppp_pcb *ppp, u8_t* data, int len); - - -/* - * Functions called from lwIP - * DO NOT CALL FROM lwIP USER APPLICATION. - */ -#if !NO_SYS && !PPP_INPROC_IRQ_SAFE -err_t pppos_input_sys(struct pbuf *p, struct netif *inp); -#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ - -#endif /* PPPOS_H */ -#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/upap.h b/components/net/lwip-2.0.2/src/include/netif/ppp/upap.h deleted file mode 100644 index 7da792ecc7..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/upap.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * upap.h - User/Password Authentication Protocol definitions. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: upap.h,v 1.8 2002/12/04 23:03:33 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef UPAP_H -#define UPAP_H - -#include "ppp.h" - -/* - * Packet header = Code, id, length. - */ -#define UPAP_HEADERLEN 4 - - -/* - * UPAP codes. - */ -#define UPAP_AUTHREQ 1 /* Authenticate-Request */ -#define UPAP_AUTHACK 2 /* Authenticate-Ack */ -#define UPAP_AUTHNAK 3 /* Authenticate-Nak */ - - -/* - * Client states. - */ -#define UPAPCS_INITIAL 0 /* Connection down */ -#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPCS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */ -#define UPAPCS_OPEN 4 /* We've received an Ack */ -#define UPAPCS_BADAUTH 5 /* We've received a Nak */ - -/* - * Server states. - */ -#define UPAPSS_INITIAL 0 /* Connection down */ -#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */ -#define UPAPSS_PENDING 2 /* Connection down, have requested auth */ -#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */ -#define UPAPSS_OPEN 4 /* We've sent an Ack */ -#define UPAPSS_BADAUTH 5 /* We've sent a Nak */ - - -/* - * Timeouts. - */ -#if 0 /* moved to ppp_opts.h */ -#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ -#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ -#endif /* moved to ppp_opts.h */ - -/* - * Each interface is described by upap structure. - */ -#if PAP_SUPPORT -typedef struct upap_state { - const char *us_user; /* User */ - u8_t us_userlen; /* User length */ - const char *us_passwd; /* Password */ - u8_t us_passwdlen; /* Password length */ - u8_t us_clientstate; /* Client state */ -#if PPP_SERVER - u8_t us_serverstate; /* Server state */ -#endif /* PPP_SERVER */ - u8_t us_id; /* Current id */ - u8_t us_transmits; /* Number of auth-reqs sent */ -} upap_state; -#endif /* PAP_SUPPORT */ - - -void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password); -#if PPP_SERVER -void upap_authpeer(ppp_pcb *pcb); -#endif /* PPP_SERVER */ - -extern const struct protent pap_protent; - -#endif /* UPAP_H */ -#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/ppp/vj.h b/components/net/lwip-2.0.2/src/include/netif/ppp/vj.h deleted file mode 100644 index 7f389c846f..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/ppp/vj.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Definitions for tcp compression routines. - * - * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * - Initial distribution. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#ifndef VJ_H -#define VJ_H - -#include "lwip/ip.h" -#include "lwip/priv/tcp_priv.h" - -#define MAX_SLOTS 16 /* must be > 2 and < 256 */ -#define MAX_HDR 128 - -/* - * Compressed packet format: - * - * The first octet contains the packet type (top 3 bits), TCP - * 'push' bit, and flags that indicate which of the 4 TCP sequence - * numbers have changed (bottom 5 bits). The next octet is a - * conversation number that associates a saved IP/TCP header with - * the compressed packet. The next two octets are the TCP checksum - * from the original datagram. The next 0 to 15 octets are - * sequence number changes, one change per bit set in the header - * (there may be no changes and there are two special cases where - * the receiver implicitly knows what changed -- see below). - * - * There are 5 numbers which can change (they are always inserted - * in the following order): TCP urgent pointer, window, - * acknowlegement, sequence number and IP ID. (The urgent pointer - * is different from the others in that its value is sent, not the - * change in value.) Since typical use of SLIP links is biased - * toward small packets (see comments on MTU/MSS below), changes - * use a variable length coding with one octet for numbers in the - * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the - * range 256 - 65535 or 0. (If the change in sequence number or - * ack is more than 65535, an uncompressed packet is sent.) - */ - -/* - * Packet types (must not conflict with IP protocol version) - * - * The top nibble of the first octet is the packet type. There are - * three possible types: IP (not proto TCP or tcp with one of the - * control flags set); uncompressed TCP (a normal IP/TCP packet but - * with the 8-bit protocol field replaced by an 8-bit connection id -- - * this type of packet syncs the sender & receiver); and compressed - * TCP (described above). - * - * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and - * is logically part of the 4-bit "changes" field that follows. Top - * three bits are actual packet type. For backward compatibility - * and in the interest of conserving bits, numbers are chosen so the - * IP protocol version number (4) which normally appears in this nibble - * means "IP packet". - */ - -/* packet types */ -#define TYPE_IP 0x40 -#define TYPE_UNCOMPRESSED_TCP 0x70 -#define TYPE_COMPRESSED_TCP 0x80 -#define TYPE_ERROR 0x00 - -/* Bits in first octet of compressed packet */ -#define NEW_C 0x40 /* flag bits for what changed in a packet */ -#define NEW_I 0x20 -#define NEW_S 0x08 -#define NEW_A 0x04 -#define NEW_W 0x02 -#define NEW_U 0x01 - -/* reserved, special-case values of above */ -#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */ -#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */ -#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U) - -#define TCP_PUSH_BIT 0x10 - - -/* - * "state" data for each active tcp conversation on the wire. This is - * basically a copy of the entire IP/TCP header from the last packet - * we saw from the conversation together with a small identifier - * the transmit & receive ends of the line use to locate saved header. - */ -struct cstate { - struct cstate *cs_next; /* next most recently used state (xmit only) */ - u16_t cs_hlen; /* size of hdr (receive only) */ - u8_t cs_id; /* connection # associated with this state */ - u8_t cs_filler; - union { - char csu_hdr[MAX_HDR]; - struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ - } vjcs_u; -}; -#define cs_ip vjcs_u.csu_ip -#define cs_hdr vjcs_u.csu_hdr - - -struct vjstat { - u32_t vjs_packets; /* outbound packets */ - u32_t vjs_compressed; /* outbound compressed packets */ - u32_t vjs_searches; /* searches for connection state */ - u32_t vjs_misses; /* times couldn't find conn. state */ - u32_t vjs_uncompressedin; /* inbound uncompressed packets */ - u32_t vjs_compressedin; /* inbound compressed packets */ - u32_t vjs_errorin; /* inbound unknown type packets */ - u32_t vjs_tossed; /* inbound packets tossed because of error */ -}; - -/* - * all the state data for one serial line (we need one of these per line). - */ -struct vjcompress { - struct cstate *last_cs; /* most recently used tstate */ - u8_t last_recv; /* last rcvd conn. id */ - u8_t last_xmit; /* last sent conn. id */ - u16_t flags; - u8_t maxSlotIndex; - u8_t compressSlot; /* Flag indicating OK to compress slot ID. */ -#if LINK_STATS - struct vjstat stats; -#endif - struct cstate tstate[MAX_SLOTS]; /* xmit connection states */ - struct cstate rstate[MAX_SLOTS]; /* receive connection states */ -}; - -/* flag values */ -#define VJF_TOSS 1U /* tossing rcvd frames because of input err */ - -extern void vj_compress_init (struct vjcompress *comp); -extern u8_t vj_compress_tcp (struct vjcompress *comp, struct pbuf **pb); -extern void vj_uncompress_err (struct vjcompress *comp); -extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp); -extern int vj_uncompress_tcp (struct pbuf **nb, struct vjcompress *comp); - -#endif /* VJ_H */ - -#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/include/netif/slipif.h b/components/net/lwip-2.0.2/src/include/netif/slipif.h deleted file mode 100644 index 65ba31f835..0000000000 --- a/components/net/lwip-2.0.2/src/include/netif/slipif.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file - * - * SLIP netif API - */ - -/* - * Copyright (c) 2001, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_HDR_NETIF_SLIPIF_H -#define LWIP_HDR_NETIF_SLIPIF_H - -#include "lwip/opt.h" -#include "lwip/netif.h" - -/** Set this to 1 to start a thread that blocks reading on the serial line - * (using sio_read()). - */ -#ifndef SLIP_USE_RX_THREAD -#define SLIP_USE_RX_THREAD !NO_SYS -#endif - -/** Set this to 1 to enable functions to pass in RX bytes from ISR context. - * If enabled, slipif_received_byte[s]() process incoming bytes and put assembled - * packets on a queue, which is fed into lwIP from slipif_poll(). - * If disabled, slipif_poll() polls the serial line (using sio_tryread()). - */ -#ifndef SLIP_RX_FROM_ISR -#define SLIP_RX_FROM_ISR 0 -#endif - -/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets - * received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available. - * If disabled, packets will be dropped if more than one packet is received. - */ -#ifndef SLIP_RX_QUEUE -#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -err_t slipif_init(struct netif * netif); -void slipif_poll(struct netif *netif); -#if SLIP_RX_FROM_ISR -void slipif_process_rxqueue(struct netif *netif); -void slipif_received_byte(struct netif *netif, u8_t data); -void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len); -#endif /* SLIP_RX_FROM_ISR */ - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_HDR_NETIF_SLIPIF_H */ - diff --git a/components/net/lwip-2.0.2/src/include/posix/netdb.h b/components/net/lwip-2.0.2/src/include/posix/netdb.h deleted file mode 100644 index 12d4c7f566..0000000000 --- a/components/net/lwip-2.0.2/src/include/posix/netdb.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file - * This file is a posix wrapper for lwip/netdb.h. - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/netdb.h" diff --git a/components/net/lwip-2.0.2/src/include/posix/sys/socket.h b/components/net/lwip-2.0.2/src/include/posix/sys/socket.h deleted file mode 100644 index 0ed9baf3d9..0000000000 --- a/components/net/lwip-2.0.2/src/include/posix/sys/socket.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @file - * This file is a posix wrapper for lwip/sockets.h. - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/sockets.h" diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h deleted file mode 100644 index 2de6aa1052..0000000000 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ /dev/null @@ -1,637 +0,0 @@ -#ifndef __LWIPOPTS_H__ -#define __LWIPOPTS_H__ - -#include - -#define LWIP_ERRNO_STDINCLUDE - -#define LWIP_IPV4 1 - -#ifdef RT_USING_LWIP_IPV6 -#define LWIP_IPV6 1 -#else -#define LWIP_IPV6 0 -#endif /* RT_USING_LWIP_IPV6 */ - -#define NO_SYS 0 -#define LWIP_SOCKET 1 -#define LWIP_NETCONN 1 - -#ifdef RT_LWIP_IGMP -#define LWIP_IGMP 1 -#else -#define LWIP_IGMP 0 -#endif - -#ifdef RT_LWIP_ICMP -#define LWIP_ICMP 1 -#else -#define LWIP_ICMP 0 -#endif - -#ifdef RT_LWIP_SNMP -#define LWIP_SNMP 1 -#else -#define LWIP_SNMP 0 -#endif - -#ifdef RT_LWIP_DNS -#define LWIP_DNS 1 -#else -#define LWIP_DNS 0 -#endif - -#define LWIP_HAVE_LOOPIF 0 - -#define LWIP_PLATFORM_BYTESWAP 0 - -/* #define RT_LWIP_DEBUG */ - -#ifdef RT_LWIP_DEBUG -#define LWIP_DEBUG -#endif - -/* ---------- Debug options ---------- */ -#ifdef LWIP_DEBUG -#ifdef RT_LWIP_SYS_DEBUG -#define SYS_DEBUG LWIP_DBG_ON -#else -#define SYS_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_ETHARP_DEBUG -#define ETHARP_DEBUG LWIP_DBG_ON -#else -#define ETHARP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_PPP_DEBUG -#define PPP_DEBUG LWIP_DBG_ON -#else -#define PPP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_MEM_DEBUG -#define MEM_DEBUG LWIP_DBG_ON -#else -#define MEM_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_MEMP_DEBUG -#define MEMP_DEBUG LWIP_DBG_ON -#else -#define MEMP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_PBUF_DEBUG -#define PBUF_DEBUG LWIP_DBG_ON -#else -#define PBUF_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_API_LIB_DEBUG -#define API_LIB_DEBUG LWIP_DBG_ON -#else -#define API_LIB_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_API_MSG_DEBUG -#define API_MSG_DEBUG LWIP_DBG_ON -#else -#define API_MSG_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCPIP_DEBUG -#define TCPIP_DEBUG LWIP_DBG_ON -#else -#define TCPIP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_NETIF_DEBUG -#define NETIF_DEBUG LWIP_DBG_ON -#else -#define NETIF_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_SOCKETS_DEBUG -#define SOCKETS_DEBUG LWIP_DBG_ON -#else -#define SOCKETS_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_DNS_DEBUG -#define DNS_DEBUG LWIP_DBG_ON -#else -#define DNS_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_AUTOIP_DEBUG -#define AUTOIP_DEBUG LWIP_DBG_ON -#else -#define AUTOIP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_DHCP_DEBUG -#define DHCP_DEBUG LWIP_DBG_ON -#else -#define DHCP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_IP_DEBUG -#define IP_DEBUG LWIP_DBG_ON -#else -#define IP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_IP_REASS_DEBUG -#define IP_REASS_DEBUG LWIP_DBG_ON -#else -#define IP_REASS_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_ICMP_DEBUG -#define ICMP_DEBUG LWIP_DBG_ON -#else -#define ICMP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_IGMP_DEBUG -#define IGMP_DEBUG LWIP_DBG_ON -#else -#define IGMP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_UDP_DEBUG -#define UDP_DEBUG LWIP_DBG_ON -#else -#define UDP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_DEBUG -#define TCP_DEBUG LWIP_DBG_ON -#else -#define TCP_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_INPUT_DEBUG -#define TCP_INPUT_DEBUG LWIP_DBG_ON -#else -#define TCP_INPUT_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_OUTPUT_DEBUG -#define TCP_OUTPUT_DEBUG LWIP_DBG_ON -#else -#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_RTO_DEBUG -#define TCP_RTO_DEBUG LWIP_DBG_ON -#else -#define TCP_RTO_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_CWND_DEBUG -#define TCP_CWND_DEBUG LWIP_DBG_ON -#else -#define TCP_CWND_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_WND_DEBUG -#define TCP_WND_DEBUG LWIP_DBG_ON -#else -#define TCP_WND_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_FR_DEBUG -#define TCP_FR_DEBUG LWIP_DBG_ON -#else -#define TCP_FR_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_QLEN_DEBUG -#define TCP_QLEN_DEBUG LWIP_DBG_ON -#else -#define TCP_QLEN_DEBUG LWIP_DBG_OFF -#endif - -#ifdef RT_LWIP_TCP_RST_DEBUG -#define TCP_RST_DEBUG LWIP_DBG_ON -#else -#define TCP_RST_DEBUG LWIP_DBG_OFF -#endif - -#endif /* LWIP_DEBUG */ - -#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) - -/* ---------- Memory options ---------- */ -#define MEMCPY(dst,src,len) rt_memcpy(dst,src,len) -#define SMEMCPY(dst,src,len) MEMCPY(dst,src,len) - -#ifdef RT_LWIP_MEM_ALIGNMENT -#define MEM_ALIGNMENT RT_LWIP_MEM_ALIGNMENT -#else -#define MEM_ALIGNMENT 4 -#endif - -#define MEMP_OVERFLOW_CHECK 1 -#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 -//#define MEM_LIBC_MALLOC 1 -//#define MEM_USE_POOLS 1 -//#define MEMP_USE_CUSTOM_POOLS 1 -//#define MEM_SIZE (1024*64) - -#define MEMP_MEM_MALLOC 0 - -/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application - sends a lot of data out of ROM (or other static memory), this - should be set high. */ -#define MEMP_NUM_PBUF 32 //16 - -/* the number of struct netconns */ -#ifdef RT_MEMP_NUM_NETCONN -#define MEMP_NUM_NETCONN RT_MEMP_NUM_NETCONN -#endif - -/* the number of UDP protocol control blocks. One per active RAW "connection". */ -#ifdef RT_LWIP_RAW_PCB_NUM -#define MEMP_NUM_RAW_PCB RT_LWIP_RAW_PCB_NUM -#endif - -/* the number of UDP protocol control blocks. One per active UDP "connection". */ -#ifdef RT_LWIP_UDP_PCB_NUM -#define MEMP_NUM_UDP_PCB RT_LWIP_UDP_PCB_NUM -#endif - -/* the number of simulatenously active TCP connections. */ -#ifdef RT_LWIP_TCP_PCB_NUM -#define MEMP_NUM_TCP_PCB RT_LWIP_TCP_PCB_NUM -#endif - -/* the number of simultaneously queued TCP */ -#ifdef RT_LWIP_TCP_SEG_NUM -#define MEMP_NUM_TCP_SEG RT_LWIP_TCP_SEG_NUM -#else -#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN -#endif - -/* - * You can re-define following setting in rtcofnig.h to overwrite the default - * setting in the lwip opts.h - */ -/* MEMP_NUM_NETBUF: the number of struct netbufs. */ -// #define MEMP_NUM_NETBUF 2 -/* MEMP_NUM_NETCONN: the number of struct netconns. */ -// #define MEMP_NUM_NETCONN 4 - -/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used - for sequential API communication and incoming packets. Used in - src/api/tcpip.c. */ -// #define MEMP_NUM_TCPIP_MSG_API 16 -// #define MEMP_NUM_TCPIP_MSG_INPKT 16 - -/* ---------- Pbuf options ---------- */ -/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ -#ifdef RT_LWIP_PBUF_NUM -#define PBUF_POOL_SIZE RT_LWIP_PBUF_NUM -#endif - -/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ -#ifdef RT_LWIP_PBUF_POOL_BUFSIZE -#define PBUF_POOL_BUFSIZE RT_LWIP_PBUF_POOL_BUFSIZE -#endif - -/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a - link level header. */ -#define PBUF_LINK_HLEN 16 - -#ifdef RT_LWIP_ETH_PAD_SIZE -#define ETH_PAD_SIZE RT_LWIP_ETH_PAD_SIZE -#endif - -/** SYS_LIGHTWEIGHT_PROT - * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection - * for certain critical regions during buffer allocation, deallocation and memory - * allocation and deallocation. - */ -#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0) - -#ifdef LWIP_USING_NAT -#define IP_NAT 1 -#else -#define IP_NAT 0 -#endif - -/* ---------- TCP options ---------- */ -#ifdef RT_LWIP_TCP -#define LWIP_TCP 1 -#else -#define LWIP_TCP 0 -#endif - -#define TCP_TTL 255 - -/* Controls if TCP should queue segments that arrive out of - order. Define to 0 if your device is low on memory. */ -#define TCP_QUEUE_OOSEQ 1 - -/* TCP Maximum segment size. */ -#define TCP_MSS 1460 - -/* TCP sender buffer space (bytes). */ -#ifdef RT_LWIP_TCP_SND_BUF -#define TCP_SND_BUF RT_LWIP_TCP_SND_BUF -#else -#define TCP_SND_BUF (TCP_MSS * 2) -#endif - -/* TCP sender buffer space (pbufs). This must be at least = 2 * - TCP_SND_BUF/TCP_MSS for things to work. */ -#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) - -/* TCP writable space (bytes). This must be less than or equal - to TCP_SND_BUF. It is the amount of space which must be - available in the tcp snd_buf for select to return writable */ -#define TCP_SNDLOWAT (TCP_SND_BUF/2) -#define TCP_SNDQUEUELOWAT TCP_SND_QUEUELEN/2 - -/* TCP receive window. */ -#ifdef RT_LWIP_TCP_WND -#define TCP_WND RT_LWIP_TCP_WND -#else -#define TCP_WND (TCP_MSS * 2) -#endif - -/* Maximum number of retransmissions of data segments. */ -#define TCP_MAXRTX 12 - -/* Maximum number of retransmissions of SYN segments. */ -#define TCP_SYNMAXRTX 4 - -/* tcpip thread options */ -#ifdef RT_LWIP_TCPTHREAD_PRIORITY -#define TCPIP_MBOX_SIZE RT_LWIP_TCPTHREAD_MBOX_SIZE -#define TCPIP_THREAD_PRIO RT_LWIP_TCPTHREAD_PRIORITY -#define TCPIP_THREAD_STACKSIZE RT_LWIP_TCPTHREAD_STACKSIZE -#else -#define TCPIP_MBOX_SIZE 8 -#define TCPIP_THREAD_PRIO 128 -#define TCPIP_THREAD_STACKSIZE 4096 -#endif -#define TCPIP_THREAD_NAME "tcpip" -#define DEFAULT_TCP_RECVMBOX_SIZE 10 - -/* ---------- ARP options ---------- */ -#define LWIP_ARP 1 -#define ARP_TABLE_SIZE 10 -#define ARP_QUEUEING 1 - -/* ---------- Checksum options ---------- */ -#ifdef RT_LWIP_USING_HW_CHECKSUM -#define CHECKSUM_GEN_IP 0 -#define CHECKSUM_GEN_UDP 0 -#define CHECKSUM_GEN_TCP 0 -#define CHECKSUM_GEN_ICMP 0 -#define CHECKSUM_CHECK_IP 0 -#define CHECKSUM_CHECK_UDP 0 -#define CHECKSUM_CHECK_TCP 0 -#define CHECKSUM_CHECK_ICMP 0 -#endif - -/* ---------- IP options ---------- */ -/* Define IP_FORWARD to 1 if you wish to have the ability to forward - IP packets across network interfaces. If you are going to run lwIP - on a device with only one network interface, define this to 0. */ -#define IP_FORWARD 0 - -/* IP reassembly and segmentation.These are orthogonal even - * if they both deal with IP fragments */ -#ifdef RT_LWIP_REASSEMBLY_FRAG -#define IP_REASSEMBLY 1 -#define IP_FRAG 1 -#define IP_REASS_MAX_PBUFS 10 -#define MEMP_NUM_REASSDATA 10 -#else -#define IP_REASSEMBLY 0 -#define IP_FRAG 0 -#endif - -/* ---------- ICMP options ---------- */ -#define ICMP_TTL 255 - -/* ---------- DHCP options ---------- */ -/* Define LWIP_DHCP to 1 if you want DHCP configuration of - interfaces. */ -#ifdef RT_LWIP_DHCP -#define LWIP_DHCP 1 -#else -#define LWIP_DHCP 0 -#endif - -/* 1 if you want to do an ARP check on the offered address - (recommended). */ -#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) - -/* ---------- AUTOIP options ------- */ -#define LWIP_AUTOIP 0 -#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) - -/* ---------- UDP options ---------- */ -#ifdef RT_LWIP_UDP -#define LWIP_UDP 1 -#else -#define LWIP_UDP 0 -#endif - -#define LWIP_UDPLITE 0 -#define UDP_TTL 255 -#define DEFAULT_UDP_RECVMBOX_SIZE 1 - -/* ---------- RAW options ---------- */ -#ifdef RT_LWIP_RAW -#define LWIP_RAW 1 -#else -#define LWIP_RAW 0 -#endif - -#define DEFAULT_RAW_RECVMBOX_SIZE 1 -#define DEFAULT_ACCEPTMBOX_SIZE 10 - -/* ---------- Statistics options ---------- */ -#ifdef RT_LWIP_STATS -#define LWIP_STATS 1 -#define LWIP_STATS_DISPLAY 1 -#else -#define LWIP_STATS 0 -#endif - -#if LWIP_STATS -#define LINK_STATS 1 -#define IP_STATS 1 -#define ICMP_STATS 1 -#define IGMP_STATS 1 -#define IPFRAG_STATS 1 -#define UDP_STATS 1 -#define TCP_STATS 1 -#define MEM_STATS 1 -#define MEMP_STATS 1 -#define PBUF_STATS 1 -#define SYS_STATS 1 -#define MIB2_STATS 1 -#endif /* LWIP_STATS */ - -/* ---------- PPP options ---------- */ -#ifdef RT_LWIP_PPP -#define PPP_SUPPORT 1 /* Set > 0 for PPP */ -#else -#define PPP_SUPPORT 0 /* Set > 0 for PPP */ -#endif - -#if PPP_SUPPORT -#define NUM_PPP 1 /* Max PPP sessions. */ - -/* Select modules to enable. Ideally these would be set in the makefile but - * we're limited by the command line length so you need to modify the settings - * in this file. - */ -#ifdef RT_LWIP_PPPOE -#define PPPOE_SUPPORT 1 -#else -#define PPPOE_SUPPORT 0 -#endif - -#ifdef RT_LWIP_PPPOS -#define PPPOS_SUPPORT 1 -#else -#define PPPOS_SUPPORT 0 -#endif - -#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ -#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ -#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */ -#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ -#define CCP_SUPPORT 0 /* Set > 0 for CCP (NOT FUNCTIONAL!) */ -#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */ -#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ - -#endif /* PPP_SUPPORT */ - -/** - * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. - * Disable this option if you use a POSIX operating system that uses the same - * names (read, write & close). (only used if you use sockets.c) - */ -#ifndef LWIP_POSIX_SOCKETS_IO_NAMES -#define LWIP_POSIX_SOCKETS_IO_NAMES 0 -#endif - -/** - * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT - * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set - * in seconds. (does not require sockets.c, and will affect tcp.c) - */ -#ifndef LWIP_TCP_KEEPALIVE -#define LWIP_TCP_KEEPALIVE 1 -#endif - -/** - * LWIP_NETIF_HOSTNAME==1: Support netif hostname - */ -#ifndef LWIP_NETIF_HOSTNAME -#define LWIP_NETIF_HOSTNAME 1 -#endif - -/** - * LWIP_NETIF_API==1: Support netif api (in netifapi.c) - */ -#ifndef LWIP_NETIF_API -#define LWIP_NETIF_API 1 -#endif - -#ifdef LWIP_IGMP -#include -#define LWIP_RAND rand -#endif -/* - ------------------------------------ - ---------- Socket options ---------- - ------------------------------------ -*/ -/* - * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) - */ -#ifndef LWIP_SOCKET -#define LWIP_SOCKET 1 -#endif -#include -#include - -/* - * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. - * (only used if you use sockets.c) - */ -#ifdef SAL_USING_POSIX -#define LWIP_COMPAT_SOCKETS 0 -#else -#ifndef LWIP_COMPAT_SOCKETS -#define LWIP_COMPAT_SOCKETS 1 -#endif -#endif - -/** - * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and - * SO_SNDTIMEO processing. - */ -#ifndef LWIP_SO_SNDTIMEO -#define LWIP_SO_SNDTIMEO 1 -#endif - -/** - * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and - * SO_RCVTIMEO processing. - */ -#ifndef LWIP_SO_RCVTIMEO -#define LWIP_SO_RCVTIMEO 1 -#endif - -/** - * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. - */ -#ifndef LWIP_SO_RCVBUF -#define LWIP_SO_RCVBUF 1 -#endif - -/** - * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. - */ -#ifndef RECV_BUFSIZE_DEFAULT -#define RECV_BUFSIZE_DEFAULT 8192 -#endif - -/** - * SO_REUSE==1: Enable SO_REUSEADDR option. - */ -#ifndef SO_REUSE -#define SO_REUSE 0 -#endif - -/* - ------------------------------------ - ------- Applications options ------- - ------------------------------------ -*/ - -/** - * Max. length of TFTP filename - */ -#ifdef RT_LWIP_TFTP_MAX_FILENAME_LEN -#define TFTP_MAX_FILENAME_LEN RT_LWIP_TFTP_MAX_FILENAME_LEN -#elif defined(RT_DFS_ELM_MAX_LFN) -#define TFTP_MAX_FILENAME_LEN RT_DFS_ELM_MAX_LFN -#else -#define TFTP_MAX_FILENAME_LEN 64 -#endif - - -#endif /* __LWIPOPTS_H__ */ diff --git a/components/net/lwip-2.0.2/src/lwippools.h b/components/net/lwip-2.0.2/src/lwippools.h deleted file mode 100644 index 6583863de3..0000000000 --- a/components/net/lwip-2.0.2/src/lwippools.h +++ /dev/null @@ -1,10 +0,0 @@ -#if 1 - LWIP_MALLOC_MEMPOOL_START - LWIP_MALLOC_MEMPOOL((unsigned char)128, 256) - LWIP_MALLOC_MEMPOOL((unsigned char)128, 512) - LWIP_MALLOC_MEMPOOL((unsigned char)128, 1024) - LWIP_MALLOC_MEMPOOL((unsigned char)128, 1514) - LWIP_MALLOC_MEMPOOL((unsigned char)128, 1536) - LWIP_MALLOC_MEMPOOL((unsigned char)128, 4096) - LWIP_MALLOC_MEMPOOL_END -#endif diff --git a/components/net/lwip-2.0.2/src/netif/FILES b/components/net/lwip-2.0.2/src/netif/FILES deleted file mode 100644 index a3ff431d42..0000000000 --- a/components/net/lwip-2.0.2/src/netif/FILES +++ /dev/null @@ -1,24 +0,0 @@ -This directory contains generic network interface device drivers that -do not contain any hardware or architecture specific code. The files -are: - -ethernet.c - Shared code for Ethernet based interfaces. - -ethernetif.c - An example of how an Ethernet device driver could look. This - file can be used as a "skeleton" for developing new Ethernet - network device drivers. It uses the etharp.c ARP code. - -lowpan6.c - A 6LoWPAN implementation as a netif. - -slipif.c - A generic implementation of the SLIP (Serial Line IP) - protocol. It requires a sio (serial I/O) module to work. - -ppp/ Point-to-Point Protocol stack - The lwIP PPP support is based from pppd (http://ppp.samba.org) with - huge changes to match code size and memory requirements for embedded - devices. Please read /doc/ppp.txt and ppp/PPPD_FOLLOWUP for a detailed - explanation. diff --git a/components/net/lwip-2.0.2/src/netif/ethernet.c b/components/net/lwip-2.0.2/src/netif/ethernet.c deleted file mode 100644 index 52ea4236d5..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ethernet.c +++ /dev/null @@ -1,314 +0,0 @@ -/** - * @file - * Ethernet common functions - * - * @defgroup ethernet Ethernet - * @ingroup callbackstyle_api - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * Copyright (c) 2003-2004 Leon Woestenberg - * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "lwip/opt.h" - -#if LWIP_ARP || LWIP_ETHERNET - -#include "netif/ethernet.h" -#include "lwip/def.h" -#include "lwip/stats.h" -#include "lwip/etharp.h" -#include "lwip/ip.h" -#include "lwip/snmp.h" - -#include - -#include "netif/ppp/ppp_opts.h" -#if PPPOE_SUPPORT -#include "netif/ppp/pppoe.h" -#endif /* PPPOE_SUPPORT */ - -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif - -const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; -const struct eth_addr ethzero = {{0,0,0,0,0,0}}; - -/** - * @ingroup lwip_nosys - * Process received ethernet frames. Using this function instead of directly - * calling ip_input and passing ARP frames through etharp in ethernetif_input, - * the ARP cache is protected from concurrent access.\n - * Don't call directly, pass to netif_add() and call netif->input(). - * - * @param p the received packet, p->payload pointing to the ethernet header - * @param netif the network interface on which the packet was received - * - * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL - * @see ETHARP_SUPPORT_VLAN - * @see LWIP_HOOK_VLAN_CHECK - */ -err_t -ethernet_input(struct pbuf *p, struct netif *netif) -{ - struct eth_hdr* ethhdr; - u16_t type; -#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 - s16_t ip_hdr_offset = SIZEOF_ETH_HDR; -#endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ - - if (p->len <= SIZEOF_ETH_HDR) { - /* a packet with only an ethernet header (or less) is not valid for us */ - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - MIB2_STATS_NETIF_INC(netif, ifinerrors); - goto free_and_return; - } - - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = (struct eth_hdr *)p->payload; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, - ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", - (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], - (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], - (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], - (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], - lwip_htons(ethhdr->type))); - - type = ethhdr->type; -#if ETHARP_SUPPORT_VLAN - if (type == PP_HTONS(ETHTYPE_VLAN)) { - struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); - if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { - /* a packet with only an ethernet/vlan header (or less) is not valid for us */ - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - MIB2_STATS_NETIF_INC(netif, ifinerrors); - goto free_and_return; - } -#if defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) /* if not, allow all VLANs */ -#ifdef LWIP_HOOK_VLAN_CHECK - if (!LWIP_HOOK_VLAN_CHECK(netif, ethhdr, vlan)) { -#elif defined(ETHARP_VLAN_CHECK_FN) - if (!ETHARP_VLAN_CHECK_FN(ethhdr, vlan)) { -#elif defined(ETHARP_VLAN_CHECK) - if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { -#endif - /* silently ignore this packet: not for our VLAN */ - pbuf_free(p); - return ERR_OK; - } -#endif /* defined(LWIP_HOOK_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK) || defined(ETHARP_VLAN_CHECK_FN) */ - type = vlan->tpid; - ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; - } -#endif /* ETHARP_SUPPORT_VLAN */ - -#if LWIP_ARP_FILTER_NETIF - netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type)); -#endif /* LWIP_ARP_FILTER_NETIF*/ - - if (ethhdr->dest.addr[0] & 1) { - /* this might be a multicast or broadcast packet */ - if (ethhdr->dest.addr[0] == LL_IP4_MULTICAST_ADDR_0) { -#if LWIP_IPV4 - if ((ethhdr->dest.addr[1] == LL_IP4_MULTICAST_ADDR_1) && - (ethhdr->dest.addr[2] == LL_IP4_MULTICAST_ADDR_2)) { - /* mark the pbuf as link-layer multicast */ - p->flags |= PBUF_FLAG_LLMCAST; - } -#endif /* LWIP_IPV4 */ - } -#if LWIP_IPV6 - else if ((ethhdr->dest.addr[0] == LL_IP6_MULTICAST_ADDR_0) && - (ethhdr->dest.addr[1] == LL_IP6_MULTICAST_ADDR_1)) { - /* mark the pbuf as link-layer multicast */ - p->flags |= PBUF_FLAG_LLMCAST; - } -#endif /* LWIP_IPV6 */ - else if (eth_addr_cmp(ðhdr->dest, ðbroadcast)) { - /* mark the pbuf as link-layer broadcast */ - p->flags |= PBUF_FLAG_LLBCAST; - } - } - - switch (type) { -#if LWIP_IPV4 && LWIP_ARP - /* IP packet? */ - case PP_HTONS(ETHTYPE_IP): - if (!(netif->flags & NETIF_FLAG_ETHARP)) { - goto free_and_return; - } - /* skip Ethernet header */ - if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("ethernet_input: IPv4 packet dropped, too short (%"S16_F"/%"S16_F")\n", - p->tot_len, ip_hdr_offset)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); - goto free_and_return; - } else { - /* pass to IP layer */ - ip4_input(p, netif); - } - break; - - case PP_HTONS(ETHTYPE_ARP): - if (!(netif->flags & NETIF_FLAG_ETHARP)) { - goto free_and_return; - } - /* skip Ethernet header */ - if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("ethernet_input: ARP response packet dropped, too short (%"S16_F"/%"S16_F")\n", - p->tot_len, ip_hdr_offset)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("Can't move over header in packet")); - ETHARP_STATS_INC(etharp.lenerr); - ETHARP_STATS_INC(etharp.drop); - goto free_and_return; - } else { - /* pass p to ARP module */ - etharp_input(p, netif); - } - break; -#endif /* LWIP_IPV4 && LWIP_ARP */ -#if PPPOE_SUPPORT - case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ - pppoe_disc_input(netif, p); - break; - - case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ - pppoe_data_input(netif, p); - break; -#endif /* PPPOE_SUPPORT */ - -#if LWIP_IPV6 - case PP_HTONS(ETHTYPE_IPV6): /* IPv6 */ - /* skip Ethernet header */ - if ((p->len < ip_hdr_offset) || pbuf_header(p, (s16_t)-ip_hdr_offset)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("ethernet_input: IPv6 packet dropped, too short (%"S16_F"/%"S16_F")\n", - p->tot_len, ip_hdr_offset)); - goto free_and_return; - } else { - /* pass to IPv6 layer */ - ip6_input(p, netif); - } - break; -#endif /* LWIP_IPV6 */ - - default: -#ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL - if(LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { - break; - } -#endif - ETHARP_STATS_INC(etharp.proterr); - ETHARP_STATS_INC(etharp.drop); - MIB2_STATS_NETIF_INC(netif, ifinunknownprotos); - goto free_and_return; - } - - /* This means the pbuf is freed or consumed, - so the caller doesn't have to free it again */ - return ERR_OK; - -free_and_return: - pbuf_free(p); - return ERR_OK; -} - -/** - * @ingroup ethernet - * Send an ethernet packet on the network using netif->linkoutput(). - * The ethernet header is filled in before sending. - * - * @see LWIP_HOOK_VLAN_SET - * - * @param netif the lwIP network interface on which to send the packet - * @param p the packet to send. pbuf layer must be @ref PBUF_LINK. - * @param src the source MAC address to be copied into the ethernet header - * @param dst the destination MAC address to be copied into the ethernet header - * @param eth_type ethernet type (@ref eth_type) - * @return ERR_OK if the packet was sent, any other err_t on failure - */ -err_t -ethernet_output(struct netif* netif, struct pbuf* p, - const struct eth_addr* src, const struct eth_addr* dst, - u16_t eth_type) -{ - struct eth_hdr* ethhdr; - u16_t eth_type_be = lwip_htons(eth_type); - -#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) - s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type); - if (vlan_prio_vid >= 0) { - struct eth_vlan_hdr* vlanhdr; - - LWIP_ASSERT("prio_vid must be <= 0xFFFF", vlan_prio_vid <= 0xFFFF); - - if (pbuf_header(p, SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) != 0) { - goto pbuf_header_failed; - } - vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR); - vlanhdr->tpid = eth_type_be; - vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); - - eth_type_be = PP_HTONS(ETHTYPE_VLAN); - } else -#endif /* ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET) */ - { - if (pbuf_header(p, SIZEOF_ETH_HDR) != 0) { - goto pbuf_header_failed; - } - } - - ethhdr = (struct eth_hdr*)p->payload; - ethhdr->type = eth_type_be; - ETHADDR32_COPY(ðhdr->dest, dst); - ETHADDR16_COPY(ðhdr->src, src); - - LWIP_ASSERT("netif->hwaddr_len must be 6 for ethernet_output!", - (netif->hwaddr_len == ETH_HWADDR_LEN)); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, - ("ethernet_output: sending packet %p\n", (void *)p)); - - /* send the packet */ - return netif->linkoutput(netif, p); - -pbuf_header_failed: - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, - ("ethernet_output: could not allocate room for header.\n")); - LINK_STATS_INC(link.lenerr); - return ERR_BUF; -} - -#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/components/net/lwip-2.0.2/src/netif/ethernetif.c b/components/net/lwip-2.0.2/src/netif/ethernetif.c deleted file mode 100644 index 0b1943fdff..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ethernetif.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * COPYRIGHT (C) 2006-2018, RT-Thread Development Team - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - * Change Logs: - * Date Author Notes - * 2010-07-07 Bernard fix send mail to mailbox issue. - * 2011-07-30 mbbill port lwIP 1.4.0 to RT-Thread - * 2012-04-10 Bernard add more compatible with RT-Thread. - * 2012-11-12 Bernard The network interface can be initialized - * after lwIP initialization. - * 2013-02-28 aozima fixed list_tcps bug: ipaddr_ntoa isn't reentrant. - * 2016-08-18 Bernard port to lwIP 2.0.0 - * 2020-08-10 lizhirui fixed some problems when this is running on 64-bit cpu - */ - -#include "lwip/opt.h" - -#include "lwip/opt.h" -#include "lwip/debug.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" -#include "lwip/netif.h" -#include "lwip/stats.h" -#include "lwip/tcpip.h" -#include "lwip/dhcp.h" -#include "lwip/netifapi.h" - -#include "netif/etharp.h" -#include "netif/ethernetif.h" - -#include "lwip/inet.h" - -#if LWIP_IPV6 -#include "lwip/ethip6.h" -#endif /* LWIP_IPV6 */ - -#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) -#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) - -#ifndef RT_LWIP_ETHTHREAD_PRIORITY -#define RT_ETHERNETIF_THREAD_PREORITY 0x90 -#else -#define RT_ETHERNETIF_THREAD_PREORITY RT_LWIP_ETHTHREAD_PRIORITY -#endif - -#ifndef LWIP_NO_TX_THREAD -/** - * Tx message structure for Ethernet interface - */ -struct eth_tx_msg -{ - struct netif *netif; - struct pbuf *buf; -}; - -static struct rt_mailbox eth_tx_thread_mb; -static struct rt_thread eth_tx_thread; -#ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE -static char eth_tx_thread_mb_pool[32 * sizeof(rt_ubase_t)]; -static char eth_tx_thread_stack[512]; -#else -static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; -static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; -#endif -#endif - -#ifndef LWIP_NO_RX_THREAD -static struct rt_mailbox eth_rx_thread_mb; -static struct rt_thread eth_rx_thread; -#ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE -static char eth_rx_thread_mb_pool[48 * sizeof(rt_ubase_t)]; -static char eth_rx_thread_stack[1024]; -#else -static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * sizeof(rt_ubase_t)]; -static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; -#endif -#endif - -#ifdef RT_USING_NETDEV - -#include "lwip/ip.h" -#include "lwip/init.h" -#include "lwip/netdb.h" -#include - -static int lwip_netdev_set_up(struct netdev *netif) -{ - netif_set_up((struct netif *)netif->user_data); - return ERR_OK; -} - -static int lwip_netdev_set_down(struct netdev *netif) -{ - netif_set_down((struct netif *)netif->user_data); - return ERR_OK; -} - -static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw) -{ - if (ip_addr && netmask && gw) - { - netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); - } - else - { - if (ip_addr) - { - netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); - } - - if (netmask) - { - netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); - } - - if (gw) - { - netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); - } - } - - return ERR_OK; -} - -#ifdef RT_LWIP_DNS -static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server) -{ - extern void dns_setserver(uint8_t dns_num, const ip_addr_t *dns_server); - dns_setserver(dns_num, dns_server); - return ERR_OK; -} -#endif /* RT_LWIP_DNS */ - -#ifdef RT_LWIP_DHCP -static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled) -{ - netdev_low_level_set_dhcp_status(netif, is_enabled); - - /*add dhcp start or stop must call dhcp_start and dhcp_stop function*/ - if(is_enabled == RT_TRUE) - { - dhcp_start((struct netif *)netif->user_data); - } - else - { - dhcp_stop((struct netif *)netif->user_data); - } - return ERR_OK; -} -#endif /* RT_LWIP_DHCP */ - -#ifdef RT_USING_FINSH -#ifdef RT_LWIP_USING_PING -extern int lwip_ping_recv(int s, int *ttl); -extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size); - -int lwip_netdev_ping(struct netdev *netif, const char *host, size_t data_len, - uint32_t timeout, struct netdev_ping_resp *ping_resp) -{ - int s, ttl, recv_len, result = 0; - int elapsed_time; - rt_tick_t recv_start_tick; -#if LWIP_VERSION_MAJOR >= 2U - struct timeval recv_timeout = { timeout / RT_TICK_PER_SECOND, timeout % RT_TICK_PER_SECOND }; -#else - int recv_timeout = timeout * 1000UL / RT_TICK_PER_SECOND; -#endif - ip_addr_t target_addr; - struct addrinfo hint, *res = RT_NULL; - struct sockaddr_in *h = RT_NULL; - struct in_addr ina; - - RT_ASSERT(netif); - RT_ASSERT(host); - RT_ASSERT(ping_resp); - - rt_memset(&hint, 0x00, sizeof(hint)); - /* convert URL to IP */ - if (lwip_getaddrinfo(host, RT_NULL, &hint, &res) != 0) - { - return -RT_ERROR; - } - SMEMCPY(&h, &res->ai_addr, sizeof(struct sockaddr_in *)); - SMEMCPY(&ina, &h->sin_addr, sizeof(ina)); - lwip_freeaddrinfo(res); - if (inet_aton(inet_ntoa(ina), &target_addr) == 0) - { - return -RT_ERROR; - } - SMEMCPY(&(ping_resp->ip_addr), &target_addr, sizeof(ip_addr_t)); - - /* new a socket */ - if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) - { - return -RT_ERROR; - } - - lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout)); - - if (lwip_ping_send(s, &target_addr, data_len) == ERR_OK) - { - recv_start_tick = rt_tick_get(); - if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) - { - elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND; - ping_resp->data_len = recv_len; - ping_resp->ttl = ttl; - ping_resp->ticks = elapsed_time; - } - else - { - result = -RT_ETIMEOUT; - goto __exit; - } - } - else - { - result = -RT_ETIMEOUT; - goto __exit; - } - -__exit: - lwip_close(s); - - return result; -} -#endif /* RT_LWIP_USING_PING */ - -#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) -void lwip_netdev_netstat(struct netdev *netif) -{ - extern void list_tcps(void); - extern void list_udps(void); - -#ifdef RT_LWIP_TCP - list_tcps(); -#endif -#ifdef RT_LWIP_UDP - list_udps(); -#endif -} -#endif /* RT_LWIP_TCP || RT_LWIP_UDP */ -#endif /* RT_USING_FINSH */ - -static int lwip_netdev_set_default(struct netdev *netif) -{ - netif_set_default((struct netif *)netif->user_data); - return ERR_OK; -} - -const struct netdev_ops lwip_netdev_ops = -{ - lwip_netdev_set_up, - lwip_netdev_set_down, - - lwip_netdev_set_addr_info, -#ifdef RT_LWIP_DNS - lwip_netdev_set_dns_server, -#else - NULL, -#endif /* RT_LWIP_DNS */ - -#ifdef RT_LWIP_DHCP - lwip_netdev_set_dhcp, -#else - NULL, -#endif /* RT_LWIP_DHCP */ - -#ifdef RT_USING_FINSH -#ifdef RT_LWIP_USING_PING - lwip_netdev_ping, -#else - NULL, -#endif /* RT_LWIP_USING_PING */ - -#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) - lwip_netdev_netstat, -#endif /* RT_LWIP_TCP || RT_LWIP_UDP */ -#endif /* RT_USING_FINSH */ - - lwip_netdev_set_default, -}; - -static int netdev_add(struct netif *lwip_netif) -{ -#define LWIP_NETIF_NAME_LEN 2 - int result = 0; - struct netdev *netdev = RT_NULL; - char name[LWIP_NETIF_NAME_LEN + 1] = {0}; - - RT_ASSERT(lwip_netif); - - netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev)); - if (netdev == RT_NULL) - { - return -ERR_IF; - } - -#ifdef SAL_USING_LWIP - extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev); - /* set the lwIP network interface device protocol family information */ - sal_lwip_netdev_set_pf_info(netdev); -#endif /* SAL_USING_LWIP */ - - rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); - result = netdev_register(netdev, name, (void *)lwip_netif); - - /* Update netdev info after registered */ - netdev->flags = lwip_netif->flags; - netdev->mtu = lwip_netif->mtu; - netdev->ops = &lwip_netdev_ops; - netdev->hwaddr_len = lwip_netif->hwaddr_len; - SMEMCPY(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); - netdev->ip_addr = lwip_netif->ip_addr; - netdev->gw = lwip_netif->gw; - netdev->netmask = lwip_netif->netmask; - -#ifdef RT_LWIP_DHCP - netdev_low_level_set_dhcp_status(netdev, RT_TRUE); -#endif - - return result; -} - -static void netdev_del(struct netif *lwip_netif) -{ - char name[LWIP_NETIF_NAME_LEN + 1]; - struct netdev *netdev; - - RT_ASSERT(lwip_netif); - - rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); - netdev = netdev_get_by_name(name); - netdev_unregister(netdev); - rt_free(netdev); -} - -/* synchronize lwIP network interface device and network interface device flags */ -static int netdev_flags_sync(struct netif *lwip_netif) -{ - struct netdev *netdev = NULL; - - RT_ASSERT(lwip_netif); - - netdev = netdev_get_by_name(lwip_netif->name); - if (netdev == RT_NULL) - { - return -ERR_IF; - } - - netdev->flags |= lwip_netif->flags; - - return ERR_OK; -} -#endif /* RT_USING_NETDEV */ - -static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) -{ -#ifndef LWIP_NO_TX_THREAD - struct eth_tx_msg msg; - struct eth_device* enetif; - - RT_ASSERT(netif != RT_NULL); - enetif = (struct eth_device*)netif->state; - - /* send a message to eth tx thread */ - msg.netif = netif; - msg.buf = p; - if (rt_mb_send(ð_tx_thread_mb, (rt_ubase_t) &msg) == RT_EOK) - { - /* waiting for ack */ - rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER); - } -#else - struct eth_device* enetif; - - RT_ASSERT(netif != RT_NULL); - enetif = (struct eth_device*)netif->state; - - if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK) - { - return ERR_IF; - } -#endif - return ERR_OK; -} - -static err_t eth_netif_device_init(struct netif *netif) -{ - struct eth_device *ethif; - -#ifdef RT_USING_NETDEV - /* network interface device register */ - netdev_add(netif); -#endif /* RT_USING_NETDEV */ - - ethif = (struct eth_device*)netif->state; - if (ethif != RT_NULL) - { - rt_device_t device; - - /* get device object */ - device = (rt_device_t) ethif; - if (rt_device_init(device) != RT_EOK) - { - return ERR_IF; - } - - /* copy device flags to netif flags */ - netif->flags = (ethif->flags & 0xff); - -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; - netif->ip6_autoconfig_enabled = 1; - netif_create_ip6_linklocal_address(netif, 1); - -#if LWIP_IPV6_MLD - netif->flags |= NETIF_FLAG_MLD6; - - /* - * For hardware/netifs that implement MAC filtering. - * All-nodes link-local is handled by default, so we must let the hardware know - * to allow multicast packets in. - * Should set mld_mac_filter previously. */ - if (netif->mld_mac_filter != NULL) - { - ip6_addr_t ip6_allnodes_ll; - ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); - netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); - } -#endif /* LWIP_IPV6_MLD */ - -#endif /* LWIP_IPV6 */ - - /* set default netif */ - if (netif_default == RT_NULL) - netif_set_default(ethif->netif); - -#if LWIP_DHCP - /* set interface up */ - netif_set_up(ethif->netif); - /* if this interface uses DHCP, start the DHCP client */ - dhcp_start(ethif->netif); -#else - /* set interface up */ - netif_set_up(ethif->netif); -#endif - - if (ethif->flags & ETHIF_LINK_PHYUP) - { - /* set link_up for this netif */ - netif_set_link_up(ethif->netif); - } - - return ERR_OK; - } - - return ERR_IF; -} - -/* Keep old drivers compatible in RT-Thread */ -rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flags) -{ - struct netif* netif; -#if LWIP_NETIF_HOSTNAME -#define LWIP_HOSTNAME_LEN 16 - char *hostname = RT_NULL; - netif = (struct netif*) rt_calloc (1, sizeof(struct netif) + LWIP_HOSTNAME_LEN); -#else - netif = (struct netif*) rt_calloc (1, sizeof(struct netif)); -#endif - if (netif == RT_NULL) - { - rt_kprintf("malloc netif failed\n"); - return -RT_ERROR; - } - - /* set netif */ - dev->netif = netif; - /* device flags, which will be set to netif flags when initializing */ - dev->flags = flags; - /* link changed status of device */ - dev->link_changed = 0x00; - /* avoid send the same mail to mailbox */ - dev->rx_notice = 0x00; - dev->parent.type = RT_Device_Class_NetIf; - /* register to RT-Thread device manager */ - rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR); - rt_sem_init(&(dev->tx_ack), name, 0, RT_IPC_FLAG_FIFO); - - /* set name */ - netif->name[0] = name[0]; - netif->name[1] = name[1]; - - /* set hw address to 6 */ - netif->hwaddr_len = 6; - /* maximum transfer unit */ - netif->mtu = ETHERNET_MTU; - - /* get hardware MAC address */ - rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr); - - /* set output */ - netif->output = etharp_output; - netif->linkoutput = ethernetif_linkoutput; - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - hostname = (char *)netif + sizeof(struct netif); - rt_sprintf(hostname, "rtthread_%02x%02x", name[0], name[1]); - netif->hostname = hostname; -#endif /* LWIP_NETIF_HOSTNAME */ - - /* if tcp thread has been started up, we add this netif to the system */ - if (rt_thread_find("tcpip") != RT_NULL) - { - ip4_addr_t ipaddr, netmask, gw; - -#if !LWIP_DHCP - ipaddr.addr = inet_addr(RT_LWIP_IPADDR); - gw.addr = inet_addr(RT_LWIP_GWADDR); - netmask.addr = inet_addr(RT_LWIP_MSKADDR); -#else - IP4_ADDR(&ipaddr, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); -#endif - netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, eth_netif_device_init, tcpip_input); - } - -#ifdef RT_USING_NETDEV - /* network interface device flags synchronize */ - netdev_flags_sync(netif); -#endif /* RT_USING_NETDEV */ - - return RT_EOK; -} - -rt_err_t eth_device_init(struct eth_device * dev, const char *name) -{ - rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - -#if LWIP_IGMP - /* IGMP support */ - flags |= NETIF_FLAG_IGMP; -#endif - - return eth_device_init_with_flag(dev, name, flags); -} - -void eth_device_deinit(struct eth_device *dev) -{ - struct netif* netif = dev->netif; - -#if LWIP_DHCP - dhcp_stop(netif); - dhcp_cleanup(netif); -#endif - netif_set_down(netif); - netif_remove(netif); -#ifdef RT_USING_NETDEV - netdev_del(netif); -#endif - rt_device_close(&(dev->parent)); - rt_device_unregister(&(dev->parent)); - rt_sem_detach(&(dev->tx_ack)); - rt_free(netif); -} - -#ifndef LWIP_NO_RX_THREAD -rt_err_t eth_device_ready(struct eth_device* dev) -{ - if (dev->netif) - { - if(dev->rx_notice == RT_FALSE) - { - dev->rx_notice = RT_TRUE; - return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); - } - else - return RT_EOK; - /* post message to Ethernet thread */ - } - else - return -RT_ERROR; /* netif is not initialized yet, just return. */ -} - -rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) -{ - rt_uint32_t level; - - RT_ASSERT(dev != RT_NULL); - - level = rt_hw_interrupt_disable(); - dev->link_changed = 0x01; - if (up == RT_TRUE) - dev->link_status = 0x01; - else - dev->link_status = 0x00; - rt_hw_interrupt_enable(level); - - /* post message to ethernet thread */ - return rt_mb_send(ð_rx_thread_mb, (rt_ubase_t)dev); -} -#else -/* NOTE: please not use it in interrupt when no RxThread exist */ -rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) -{ - if (up == RT_TRUE) - netifapi_netif_set_link_up(dev->netif); - else - netifapi_netif_set_link_down(dev->netif); - - return RT_EOK; -} -#endif - -#ifndef LWIP_NO_TX_THREAD -/* Ethernet Tx Thread */ -static void eth_tx_thread_entry(void* parameter) -{ - struct eth_tx_msg* msg; - - while (1) - { - if (rt_mb_recv(ð_tx_thread_mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK) - { - struct eth_device* enetif; - - RT_ASSERT(msg->netif != RT_NULL); - RT_ASSERT(msg->buf != RT_NULL); - - enetif = (struct eth_device*)msg->netif->state; - if (enetif != RT_NULL) - { - /* call driver's interface */ - if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK) - { - /* transmit eth packet failed */ - } - } - - /* send ACK */ - rt_sem_release(&(enetif->tx_ack)); - } - } -} -#endif - -#ifndef LWIP_NO_RX_THREAD -/* Ethernet Rx Thread */ -static void eth_rx_thread_entry(void* parameter) -{ - struct eth_device* device; - - while (1) - { - if (rt_mb_recv(ð_rx_thread_mb, (rt_ubase_t *)&device, RT_WAITING_FOREVER) == RT_EOK) - { - rt_base_t level; - struct pbuf *p; - - /* check link status */ - if (device->link_changed) - { - int status; - rt_uint32_t level; - - level = rt_hw_interrupt_disable(); - status = device->link_status; - device->link_changed = 0x00; - rt_hw_interrupt_enable(level); - - if (status) - netifapi_netif_set_link_up(device->netif); - else - netifapi_netif_set_link_down(device->netif); - } - - level = rt_hw_interrupt_disable(); - /* 'rx_notice' will be modify in the interrupt or here */ - device->rx_notice = RT_FALSE; - rt_hw_interrupt_enable(level); - - /* receive all of buffer */ - while(1) - { - if(device->eth_rx == RT_NULL) break; - - p = device->eth_rx(&(device->parent)); - if (p != RT_NULL) - { - /* notify to upper layer */ - if( device->netif->input(p, device->netif) != ERR_OK ) - { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n")); - pbuf_free(p); - p = NULL; - } - } - else break; - } - } - else - { - LWIP_ASSERT("Should not happen!\n",0); - } - } -} -#endif - -/* this function does not need, - * use eth_system_device_init_private() - * call by lwip_system_init(). - */ -int eth_system_device_init(void) -{ - return 0; -} - -int eth_system_device_init_private(void) -{ - rt_err_t result = RT_EOK; - - /* initialize Rx thread. */ -#ifndef LWIP_NO_RX_THREAD - /* initialize mailbox and create Ethernet Rx thread */ - result = rt_mb_init(ð_rx_thread_mb, "erxmb", - ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/sizeof(rt_ubase_t), - RT_IPC_FLAG_FIFO); - RT_ASSERT(result == RT_EOK); - - result = rt_thread_init(ð_rx_thread, "erx", eth_rx_thread_entry, RT_NULL, - ð_rx_thread_stack[0], sizeof(eth_rx_thread_stack), - RT_ETHERNETIF_THREAD_PREORITY, 16); - RT_ASSERT(result == RT_EOK); - result = rt_thread_startup(ð_rx_thread); - RT_ASSERT(result == RT_EOK); -#endif - - /* initialize Tx thread */ -#ifndef LWIP_NO_TX_THREAD - /* initialize mailbox and create Ethernet Tx thread */ - result = rt_mb_init(ð_tx_thread_mb, "etxmb", - ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/sizeof(rt_ubase_t), - RT_IPC_FLAG_FIFO); - RT_ASSERT(result == RT_EOK); - - result = rt_thread_init(ð_tx_thread, "etx", eth_tx_thread_entry, RT_NULL, - ð_tx_thread_stack[0], sizeof(eth_tx_thread_stack), - RT_ETHERNETIF_THREAD_PREORITY, 16); - RT_ASSERT(result == RT_EOK); - - result = rt_thread_startup(ð_tx_thread); - RT_ASSERT(result == RT_EOK); -#endif - - return (int)result; -} - -void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) -{ - ip4_addr_t *ip; - ip4_addr_t addr; - struct netif * netif = netif_list; - - if(strlen(netif_name) > sizeof(netif->name)) - { - rt_kprintf("network interface name too long!\r\n"); - return; - } - - while(netif != RT_NULL) - { - if(strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) - break; - - netif = netif->next; - if( netif == RT_NULL ) - { - rt_kprintf("network interface: %s not found!\r\n", netif_name); - return; - } - } - - ip = (ip4_addr_t *)&addr; - - /* set ip address */ - if ((ip_addr != RT_NULL) && ip4addr_aton(ip_addr, &addr)) - { - netif_set_ipaddr(netif, ip); - } - - /* set gateway address */ - if ((gw_addr != RT_NULL) && ip4addr_aton(gw_addr, &addr)) - { - netif_set_gw(netif, ip); - } - - /* set netmask address */ - if ((nm_addr != RT_NULL) && ip4addr_aton(nm_addr, &addr)) - { - netif_set_netmask(netif, ip); - } -} - -#ifdef RT_USING_FINSH -#include -FINSH_FUNCTION_EXPORT(set_if, set network interface address); - -#if LWIP_DNS -#include -void set_dns(uint8_t dns_num, char* dns_server) -{ - ip_addr_t addr; - - if ((dns_server != RT_NULL) && ipaddr_aton(dns_server, &addr)) - { - dns_setserver(dns_num, &addr); - } -} -FINSH_FUNCTION_EXPORT(set_dns, set DNS server address); -#endif - -void list_if(void) -{ - rt_ubase_t index; - struct netif * netif; - - rt_enter_critical(); - - netif = netif_list; - - while( netif != RT_NULL ) - { - rt_kprintf("network interface: %c%c%s\n", - netif->name[0], - netif->name[1], - (netif == netif_default)?" (Default)":""); - rt_kprintf("MTU: %d\n", netif->mtu); - rt_kprintf("MAC: "); - for (index = 0; index < netif->hwaddr_len; index ++) - rt_kprintf("%02x ", netif->hwaddr[index]); - rt_kprintf("\nFLAGS:"); - if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP"); - else rt_kprintf(" DOWN"); - if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP"); - else rt_kprintf(" LINK_DOWN"); - if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP"); - if (netif->flags & NETIF_FLAG_BROADCAST) rt_kprintf(" BROADCAST"); - if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP"); - rt_kprintf("\n"); - rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr))); - rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw))); - rt_kprintf("net mask : %s\n", ipaddr_ntoa(&(netif->netmask))); -#if LWIP_IPV6 - { - ip6_addr_t *addr; - int addr_state; - int i; - - addr = (ip6_addr_t *)&netif->ip6_addr[0]; - addr_state = netif->ip6_addr_state[0]; - - rt_kprintf("\nipv6 link-local: %s state:%02X %s\n", ip6addr_ntoa(addr), - addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); - - for(i=1; iip6_addr[i]; - addr_state = netif->ip6_addr_state[i]; - - rt_kprintf("ipv6[%d] address: %s state:%02X %s\n", i, ip6addr_ntoa(addr), - addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); - } - - } - rt_kprintf("\r\n"); -#endif /* LWIP_IPV6 */ - netif = netif->next; - } - -#if LWIP_DNS - { - const ip_addr_t *ip_addr; - - for(index=0; index -#include - -void list_tcps(void) -{ - rt_uint32_t num = 0; - struct tcp_pcb *pcb; - char local_ip_str[16]; - char remote_ip_str[16]; - - extern struct tcp_pcb *tcp_active_pcbs; - extern union tcp_listen_pcbs_t tcp_listen_pcbs; - extern struct tcp_pcb *tcp_tw_pcbs; - - rt_enter_critical(); - rt_kprintf("Active PCB states:\n"); - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) - { - strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); - strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); - - rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", - num++, - local_ip_str, - pcb->local_port, - remote_ip_str, - pcb->remote_port, - pcb->snd_nxt, - pcb->rcv_nxt); - rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); - } - - rt_kprintf("Listen PCB states:\n"); - num = 0; - for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) - { - rt_kprintf("#%d local port %d ", num++, pcb->local_port); - rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); - } - - rt_kprintf("TIME-WAIT PCB states:\n"); - num = 0; - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) - { - strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); - strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); - - rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", - num++, - local_ip_str, - pcb->local_port, - remote_ip_str, - pcb->remote_port, - pcb->snd_nxt, - pcb->rcv_nxt); - rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); - } - rt_exit_critical(); -} -FINSH_FUNCTION_EXPORT(list_tcps, list all of tcp connections); -#endif /* LWIP_TCP */ - -#if LWIP_UDP -#include "lwip/udp.h" -void list_udps(void) -{ - struct udp_pcb *pcb; - rt_uint32_t num = 0; - char local_ip_str[16]; - char remote_ip_str[16]; - - rt_enter_critical(); - rt_kprintf("Active UDP PCB states:\n"); - for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) - { - strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); - strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); - - rt_kprintf("#%d %d %s:%d <==> %s:%d \n", - num, (int)pcb->flags, - local_ip_str, - pcb->local_port, - remote_ip_str, - pcb->remote_port); - - num++; - } - rt_exit_critical(); -} -FINSH_FUNCTION_EXPORT(list_udps, list all of udp connections); -#endif /* LWIP_UDP */ - -#endif diff --git a/components/net/lwip-2.0.2/src/netif/lowpan6.c b/components/net/lwip-2.0.2/src/netif/lowpan6.c deleted file mode 100644 index 9a84cbccc7..0000000000 --- a/components/net/lwip-2.0.2/src/netif/lowpan6.c +++ /dev/null @@ -1,1193 +0,0 @@ -/** - * @file - * - * 6LowPAN output for IPv6. Uses ND tables for link-layer addressing. Fragments packets to 6LowPAN units. - */ - -/* - * Copyright (c) 2015 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -/** - * @defgroup sixlowpan 6LowPAN netif - * @ingroup addons - * 6LowPAN netif implementation - */ - -#include "netif/lowpan6.h" - -#if LWIP_IPV6 && LWIP_6LOWPAN - -#include "lwip/ip.h" -#include "lwip/pbuf.h" -#include "lwip/ip_addr.h" -#include "lwip/netif.h" -#include "lwip/nd6.h" -#include "lwip/mem.h" -#include "lwip/udp.h" -#include "lwip/tcpip.h" -#include "lwip/snmp.h" - -#include - -struct ieee_802154_addr { - u8_t addr_len; - u8_t addr[8]; -}; - -/** This is a helper struct. - */ -struct lowpan6_reass_helper { - struct pbuf *pbuf; - struct lowpan6_reass_helper *next_packet; - u8_t timer; - struct ieee_802154_addr sender_addr; - u16_t datagram_size; - u16_t datagram_tag; -}; - -static struct lowpan6_reass_helper * reass_list; - -#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 -static ip6_addr_t lowpan6_context[LWIP_6LOWPAN_NUM_CONTEXTS]; -#endif - -static u16_t ieee_802154_pan_id; - -static const struct ieee_802154_addr ieee_802154_broadcast = {2, {0xff, 0xff}}; - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS -static struct ieee_802154_addr short_mac_addr = {2, {0,0}}; -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - -static err_t dequeue_datagram(struct lowpan6_reass_helper *lrh); - -/** - * Periodic timer for 6LowPAN functions: - * - * - Remove incomplete/old packets - */ -void -lowpan6_tmr(void) -{ - struct lowpan6_reass_helper *lrh, *lrh_temp; - - lrh = reass_list; - while (lrh != NULL) { - lrh_temp = lrh->next_packet; - if ((--lrh->timer) == 0) { - dequeue_datagram(lrh); - pbuf_free(lrh->pbuf); - mem_free(lrh); - } - lrh = lrh_temp; - } -} - -/** - * Removes a datagram from the reassembly queue. - **/ -static err_t -dequeue_datagram(struct lowpan6_reass_helper *lrh) -{ - struct lowpan6_reass_helper *lrh_temp; - - if (reass_list == lrh) { - reass_list = reass_list->next_packet; - } else { - lrh_temp = reass_list; - while (lrh_temp != NULL) { - if (lrh_temp->next_packet == lrh) { - lrh_temp->next_packet = lrh->next_packet; - break; - } - lrh_temp = lrh_temp->next_packet; - } - } - - return ERR_OK; -} - -static s8_t -lowpan6_context_lookup(const ip6_addr_t *ip6addr) -{ - s8_t i; - - for (i = 0; i < LWIP_6LOWPAN_NUM_CONTEXTS; i++) { - if (ip6_addr_netcmp(&lowpan6_context[i], ip6addr)) { - return i; - } - } - - return -1; -} - -/* Determine compression mode for unicast address. */ -static s8_t -lowpan6_get_address_mode(const ip6_addr_t *ip6addr, const struct ieee_802154_addr *mac_addr) -{ - if (mac_addr->addr_len == 2) { - if ((ip6addr->addr[2] == (u32_t)PP_HTONL(0x000000ff)) && - ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000))) { - if ((ip6addr->addr[3] & PP_HTONL(0x0000ffff)) == lwip_ntohl((mac_addr->addr[0] << 8) | mac_addr->addr[1])) { - return 3; - } - } - } else if (mac_addr->addr_len == 8) { - if ((ip6addr->addr[2] == lwip_ntohl(((mac_addr->addr[0] ^ 2) << 24) | (mac_addr->addr[1] << 16) | mac_addr->addr[2] << 8 | mac_addr->addr[3])) && - (ip6addr->addr[3] == lwip_ntohl((mac_addr->addr[4] << 24) | (mac_addr->addr[5] << 16) | mac_addr->addr[6] << 8 | mac_addr->addr[7]))) { - return 3; - } - } - - if ((ip6addr->addr[2] == PP_HTONL(0x000000ffUL)) && - ((ip6addr->addr[3] & PP_HTONL(0xffff0000)) == PP_NTOHL(0xfe000000UL))) { - return 2; - } - - return 1; -} - -/* Determine compression mode for multicast address. */ -static s8_t -lowpan6_get_address_mode_mc(const ip6_addr_t *ip6addr) -{ - if ((ip6addr->addr[0] == PP_HTONL(0xff020000)) && - (ip6addr->addr[1] == 0) && - (ip6addr->addr[2] == 0) && - ((ip6addr->addr[3] & PP_HTONL(0xffffff00)) == 0)) { - return 3; - } else if (((ip6addr->addr[0] & PP_HTONL(0xff00ffff)) == PP_HTONL(0xff000000)) && - (ip6addr->addr[1] == 0)) { - if ((ip6addr->addr[2] == 0) && - ((ip6addr->addr[3] & PP_HTONL(0xff000000)) == 0)) { - return 2; - } else if ((ip6addr->addr[2] & PP_HTONL(0xffffff00)) == 0) { - return 1; - } - } - - return 0; -} - -/* - * Encapsulates data into IEEE 802.15.4 frames. - * Fragments an IPv6 datagram into 6LowPAN units, which fit into IEEE 802.15.4 frames. - * If configured, will compress IPv6 and or UDP headers. - * */ -static err_t -lowpan6_frag(struct netif *netif, struct pbuf *p, const struct ieee_802154_addr *src, const struct ieee_802154_addr *dst) -{ - struct pbuf * p_frag; - u16_t frag_len, remaining_len; - u8_t * buffer; - u8_t ieee_header_len; - u8_t lowpan6_header_len; - s8_t i; - static u8_t frame_seq_num; - static u16_t datagram_tag; - u16_t datagram_offset; - err_t err = ERR_IF; - - /* We'll use a dedicated pbuf for building 6LowPAN fragments. */ - p_frag = pbuf_alloc(PBUF_RAW, 127, PBUF_RAM); - if (p_frag == NULL) { - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - return ERR_MEM; - } - - /* Write IEEE 802.15.4 header. */ - buffer = (u8_t*)p_frag->payload; - ieee_header_len = 0; - if (dst == &ieee_802154_broadcast) { - buffer[ieee_header_len++] = 0x01; /* data packet, no ack required. */ - } else { - buffer[ieee_header_len++] = 0x21; /* data packet, ack required. */ - } - buffer[ieee_header_len] = (0x00 << 4); /* 2003 frame version */ - buffer[ieee_header_len] |= (dst->addr_len == 2) ? (0x02 << 2) : (0x03 << 2); /* destination addressing mode */ - buffer[ieee_header_len] |= (src->addr_len == 2) ? (0x02 << 6) : (0x03 << 6); /* source addressing mode */ - ieee_header_len++; - buffer[ieee_header_len++] = frame_seq_num++; - - buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ - buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ - i = dst->addr_len; - while (i-- > 0) { - buffer[ieee_header_len++] = dst->addr[i]; - } - - buffer[ieee_header_len++] = ieee_802154_pan_id & 0xff; /* pan id */ - buffer[ieee_header_len++] = (ieee_802154_pan_id >> 8) & 0xff; /* pan id */ - i = src->addr_len; - while (i-- > 0) { - buffer[ieee_header_len++] = src->addr[i]; - } - -#if LWIP_6LOWPAN_IPHC - /* Perform 6LowPAN IPv6 header compression according to RFC 6282 */ - { - struct ip6_hdr *ip6hdr; - - /* Point to ip6 header and align copies of src/dest addresses. */ - ip6hdr = (struct ip6_hdr *)p->payload; - ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); - ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); - - /* Basic length of 6LowPAN header, set dispatch and clear fields. */ - lowpan6_header_len = 2; - buffer[ieee_header_len] = 0x60; - buffer[ieee_header_len + 1] = 0; - - /* Determine whether there will be a Context Identifier Extension byte or not. - * If so, set it already. */ -#if LWIP_6LOWPAN_NUM_CONTEXTS > 0 - buffer[ieee_header_len + 2] = 0; - - i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_src)); - if (i >= 0) { - /* Stateful source address compression. */ - buffer[ieee_header_len + 1] |= 0x40; - buffer[ieee_header_len + 2] |= (i & 0x0f) << 4; - } - - i = lowpan6_context_lookup(ip_2_ip6(&ip_data.current_iphdr_dest)); - if (i >= 0) { - /* Stateful destination address compression. */ - buffer[ieee_header_len + 1] |= 0x04; - buffer[ieee_header_len + 2] |= i & 0x0f; - } - - if (buffer[ieee_header_len + 2] != 0x00) { - /* Context identifier extension byte is appended. */ - buffer[ieee_header_len + 1] |= 0x80; - lowpan6_header_len++; - } -#endif /* LWIP_6LOWPAN_NUM_CONTEXTS > 0 */ - - /* Determine TF field: Traffic Class, Flow Label */ - if (IP6H_FL(ip6hdr) == 0) { - /* Flow label is elided. */ - buffer[ieee_header_len] |= 0x10; - if (IP6H_TC(ip6hdr) == 0) { - /* Traffic class (ECN+DSCP) elided too. */ - buffer[ieee_header_len] |= 0x08; - } else { - /* Traffic class (ECN+DSCP) appended. */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); - } - } else { - if (((IP6H_TC(ip6hdr) & 0x3f) == 0)) { - /* DSCP portion of Traffic Class is elided, ECN and FL are appended (3 bytes) */ - buffer[ieee_header_len] |= 0x08; - - buffer[ieee_header_len + lowpan6_header_len] = IP6H_TC(ip6hdr) & 0xc0; - buffer[ieee_header_len + lowpan6_header_len++] |= (IP6H_FL(ip6hdr) >> 16) & 0x0f; - buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; - } else { - /* Traffic class and flow label are appended (4 bytes) */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_TC(ip6hdr); - buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 16) & 0x0f; - buffer[ieee_header_len + lowpan6_header_len++] = (IP6H_FL(ip6hdr) >> 8) & 0xff; - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_FL(ip6hdr) & 0xff; - } - } - - /* Compress NH? - * Only if UDP for now. @todo support other NH compression. */ - if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { - buffer[ieee_header_len] |= 0x04; - } else { - /* append nexth. */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_NEXTH(ip6hdr); - } - - /* Compress hop limit? */ - if (IP6H_HOPLIM(ip6hdr) == 255) { - buffer[ieee_header_len] |= 0x03; - } else if (IP6H_HOPLIM(ip6hdr) == 64) { - buffer[ieee_header_len] |= 0x02; - } else if (IP6H_HOPLIM(ip6hdr) == 1) { - buffer[ieee_header_len] |= 0x01; - } else { - /* append hop limit */ - buffer[ieee_header_len + lowpan6_header_len++] = IP6H_HOPLIM(ip6hdr); - } - - /* Compress source address */ - if (((buffer[ieee_header_len + 1] & 0x40) != 0) || - (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_src)))) { - /* Context-based or link-local source address compression. */ - i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_src), src); - buffer[ieee_header_len + 1] |= (i & 0x03) << 4; - if (i == 1) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 16, 8); - lowpan6_header_len += 8; - } else if (i == 2) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 22, 2); - lowpan6_header_len += 2; - } - } else if (ip6_addr_isany(ip_2_ip6(&ip_data.current_iphdr_src))) { - /* Special case: mark SAC and leave SAM=0 */ - buffer[ieee_header_len + 1] |= 0x40; - } else { - /* Append full address. */ - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 8, 16); - lowpan6_header_len += 16; - } - - /* Compress destination address */ - if (ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_dest))) { - /* @todo support stateful multicast address compression */ - - buffer[ieee_header_len + 1] |= 0x08; - - i = lowpan6_get_address_mode_mc(ip_2_ip6(&ip_data.current_iphdr_dest)); - buffer[ieee_header_len + 1] |= i & 0x03; - if (i == 0) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); - lowpan6_header_len += 16; - } else if (i == 1) { - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 35, 5); - lowpan6_header_len += 5; - } else if (i == 2) { - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[25]; - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 37, 3); - lowpan6_header_len += 3; - } else if (i == 3) { - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[39]; - } - } else if (((buffer[ieee_header_len + 1] & 0x04) != 0) || - (ip6_addr_islinklocal(ip_2_ip6(&ip_data.current_iphdr_dest)))) { - /* Context-based or link-local destination address compression. */ - i = lowpan6_get_address_mode(ip_2_ip6(&ip_data.current_iphdr_dest), dst); - buffer[ieee_header_len + 1] |= i & 0x03; - if (i == 1) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 32, 8); - lowpan6_header_len += 8; - } else if (i == 2) { - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 38, 2); - lowpan6_header_len += 2; - } - } else { - /* Append full address. */ - MEMCPY(buffer + ieee_header_len + lowpan6_header_len, (u8_t*)p->payload + 24, 16); - lowpan6_header_len += 16; - } - - /* Move to payload. */ - pbuf_header(p, -IP6_HLEN); - - /* Compress UDP header? */ - if (IP6H_NEXTH(ip6hdr) == IP6_NEXTH_UDP) { - /* @todo support optional checksum compression */ - - buffer[ieee_header_len + lowpan6_header_len] = 0xf0; - - /* determine port compression mode. */ - if ((((u8_t *)p->payload)[0] == 0xf0) && ((((u8_t *)p->payload)[1] & 0xf0) == 0xb0) && - (((u8_t *)p->payload)[2] == 0xf0) && ((((u8_t *)p->payload)[3] & 0xf0) == 0xb0)) { - /* Compress source and dest ports. */ - buffer[ieee_header_len + lowpan6_header_len++] |= 0x03; - buffer[ieee_header_len + lowpan6_header_len++] = ((((u8_t *)p->payload)[1] & 0x0f) << 4) | (((u8_t *)p->payload)[3] & 0x0f); - } else if (((u8_t *)p->payload)[0] == 0xf0) { - /* Compress source port. */ - buffer[ieee_header_len + lowpan6_header_len++] |= 0x02; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; - } else if (((u8_t *)p->payload)[2] == 0xf0) { - /* Compress dest port. */ - buffer[ieee_header_len + lowpan6_header_len++] |= 0x01; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; - } else { - /* append full ports. */ - lowpan6_header_len++; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[0]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[1]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[2]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[3]; - } - - /* elide length and copy checksum */ - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[6]; - buffer[ieee_header_len + lowpan6_header_len++] = ((u8_t *)p->payload)[7]; - - pbuf_header(p, -UDP_HLEN); - } - } - -#else /* LWIP_6LOWPAN_HC */ - /* Send uncompressed IPv6 header with appropriate dispatch byte. */ - lowpan6_header_len = 1; - buffer[ieee_header_len] = 0x41; /* IPv6 dispatch */ -#endif /* LWIP_6LOWPAN_HC */ - - /* Calculate remaining packet length */ - remaining_len = p->tot_len; - - if (remaining_len > 0x7FF) { - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - /* datagram_size must fit into 11 bit */ - pbuf_free(p_frag); - return ERR_VAL; - } - - /* Fragment, or 1 packet? */ - if (remaining_len > (127 - ieee_header_len - lowpan6_header_len - 3)) { /* 127 - header - 1 byte dispatch - 2 bytes CRC */ - /* We must move the 6LowPAN header to make room for the FRAG header. */ - i = lowpan6_header_len; - while (i-- != 0) { - buffer[ieee_header_len + i + 4] = buffer[ieee_header_len + i]; - } - - /* Now we need to fragment the packet. FRAG1 header first */ - buffer[ieee_header_len] = 0xc0 | (((p->tot_len + lowpan6_header_len) >> 8) & 0x7); - buffer[ieee_header_len + 1] = (p->tot_len + lowpan6_header_len) & 0xff; - - datagram_tag++; - buffer[ieee_header_len + 2] = datagram_tag & 0xff; - buffer[ieee_header_len + 3] = (datagram_tag >> 8) & 0xff; - - /* Fragment follows. */ - frag_len = (127 - ieee_header_len - 4 - 2) & 0xf8; - - pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len + 4, frag_len - lowpan6_header_len, 0); - remaining_len -= frag_len - lowpan6_header_len; - datagram_offset = frag_len; - - /* 2 bytes CRC */ -#if LWIP_6LOWPAN_HW_CRC - /* Leave blank, will be filled by HW. */ -#else /* LWIP_6LOWPAN_HW_CRC */ - /* @todo calculate CRC */ -#endif /* LWIP_6LOWPAN_HW_CRC */ - - /* Calculate frame length */ - p_frag->len = p_frag->tot_len = ieee_header_len + 4 + frag_len + 2; /* add 2 dummy bytes for crc*/ - - /* send the packet */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); - LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); - err = netif->linkoutput(netif, p_frag); - - while ((remaining_len > 0) && (err == ERR_OK)) { - /* new frame, new seq num for ACK */ - buffer[2] = frame_seq_num++; - - buffer[ieee_header_len] |= 0x20; /* Change FRAG1 to FRAGN */ - - buffer[ieee_header_len + 4] = (u8_t)(datagram_offset >> 3); /* datagram offset in FRAGN header (datagram_offset is max. 11 bit) */ - - frag_len = (127 - ieee_header_len - 5 - 2) & 0xf8; - if (frag_len > remaining_len) { - frag_len = remaining_len; - } - - pbuf_copy_partial(p, buffer + ieee_header_len + 5, frag_len, p->tot_len - remaining_len); - remaining_len -= frag_len; - datagram_offset += frag_len; - - /* 2 bytes CRC */ -#if LWIP_6LOWPAN_HW_CRC - /* Leave blank, will be filled by HW. */ -#else /* LWIP_6LOWPAN_HW_CRC */ - /* @todo calculate CRC */ -#endif /* LWIP_6LOWPAN_HW_CRC */ - - /* Calculate frame length */ - p_frag->len = p_frag->tot_len = frag_len + 5 + ieee_header_len + 2; - - /* send the packet */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); - LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); - err = netif->linkoutput(netif, p_frag); - } - } else { - /* It fits in one frame. */ - frag_len = remaining_len; - - /* Copy IPv6 packet */ - pbuf_copy_partial(p, buffer + ieee_header_len + lowpan6_header_len, frag_len, 0); - remaining_len = 0; - - /* 2 bytes CRC */ -#if LWIP_6LOWPAN_HW_CRC - /* Leave blank, will be filled by HW. */ -#else /* LWIP_6LOWPAN_HW_CRC */ - /* @todo calculate CRC */ -#endif /* LWIP_6LOWPAN_HW_CRC */ - - /* Calculate frame length */ - p_frag->len = p_frag->tot_len = frag_len + lowpan6_header_len + ieee_header_len + 2; - - /* send the packet */ - MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p_frag->tot_len); - LWIP_DEBUGF(LOWPAN6_DEBUG | LWIP_DBG_TRACE, ("lowpan6_send: sending packet %p\n", (void *)p)); - err = netif->linkoutput(netif, p_frag); - } - - pbuf_free(p_frag); - - return err; -} - -err_t -lowpan6_set_context(u8_t idx, const ip6_addr_t * context) -{ - if (idx >= LWIP_6LOWPAN_NUM_CONTEXTS) { - return ERR_ARG; - } - - ip6_addr_set(&lowpan6_context[idx], context); - - return ERR_OK; -} - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS -err_t -lowpan6_set_short_addr(u8_t addr_high, u8_t addr_low) -{ - short_mac_addr.addr[0] = addr_high; - short_mac_addr.addr[1] = addr_low; - - return ERR_OK; -} -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - -#if LWIP_IPV4 -err_t -lowpan4_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) -{ - (void)netif; - (void)q; - (void)ipaddr; - - return ERR_IF; -} -#endif /* LWIP_IPV4 */ - -/** - * Resolve and fill-in IEEE 802.15.4 address header for outgoing IPv6 packet. - * - * Perform Header Compression and fragment if necessary. - * - * @param netif The lwIP network interface which the IP packet will be sent on. - * @param q The pbuf(s) containing the IP packet to be sent. - * @param ip6addr The IP address of the packet destination. - * - * @return err_t - */ -err_t -lowpan6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) -{ - err_t result; - const u8_t *hwaddr; - struct ieee_802154_addr src, dest; -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS - ip6_addr_t ip6_src; - struct ip6_hdr * ip6_hdr; -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS - /* Check if we can compress source address (use aligned copy) */ - ip6_hdr = (struct ip6_hdr *)q->payload; - ip6_addr_set(&ip6_src, &ip6_hdr->src); - if (lowpan6_get_address_mode(&ip6_src, &short_mac_addr) == 3) { - src.addr_len = 2; - src.addr[0] = short_mac_addr.addr[0]; - src.addr[1] = short_mac_addr.addr[1]; - } else -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - { - src.addr_len = netif->hwaddr_len; - SMEMCPY(src.addr, netif->hwaddr, netif->hwaddr_len); - } - - /* multicast destination IP address? */ - if (ip6_addr_ismulticast(ip6addr)) { - MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); - /* We need to send to the broadcast address.*/ - return lowpan6_frag(netif, q, &src, &ieee_802154_broadcast); - } - - /* We have a unicast destination IP address */ - /* @todo anycast? */ - -#if LWIP_6LOWPAN_INFER_SHORT_ADDRESS - if (src.addr_len == 2) { - /* If source address was compressable to short_mac_addr, and dest has same subnet and - * is also compressable to 2-bytes, assume we can infer dest as a short address too. */ - dest.addr_len = 2; - dest.addr[0] = ((u8_t *)q->payload)[38]; - dest.addr[1] = ((u8_t *)q->payload)[39]; - if ((src.addr_len == 2) && (ip6_addr_netcmp(&ip6_hdr->src, &ip6_hdr->dest)) && - (lowpan6_get_address_mode(ip6addr, &dest) == 3)) { - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - return lowpan6_frag(netif, q, &src, &dest); - } - } -#endif /* LWIP_6LOWPAN_INFER_SHORT_ADDRESS */ - - /* Ask ND6 what to do with the packet. */ - result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); - if (result != ERR_OK) { - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - return result; - } - - /* If no hardware address is returned, nd6 has queued the packet for later. */ - if (hwaddr == NULL) { - return ERR_OK; - } - - /* Send out the packet using the returned hardware address. */ - dest.addr_len = netif->hwaddr_len; - SMEMCPY(dest.addr, hwaddr, netif->hwaddr_len); - MIB2_STATS_NETIF_INC(netif, ifoutucastpkts); - return lowpan6_frag(netif, q, &src, &dest); -} - -static struct pbuf * -lowpan6_decompress(struct pbuf * p, struct ieee_802154_addr * src, struct ieee_802154_addr * dest) -{ - struct pbuf * q; - u8_t * lowpan6_buffer; - s8_t lowpan6_offset; - struct ip6_hdr *ip6hdr; - s8_t i; - s8_t ip6_offset = IP6_HLEN; - - - q = pbuf_alloc(PBUF_IP, p->len + IP6_HLEN + UDP_HLEN, PBUF_POOL); - if (q == NULL) { - pbuf_free(p); - return NULL; - } - - lowpan6_buffer = (u8_t *)p->payload; - ip6hdr = (struct ip6_hdr *)q->payload; - - lowpan6_offset = 2; - if (lowpan6_buffer[1] & 0x80) { - lowpan6_offset++; - } - - /* Set IPv6 version, traffic class and flow label. */ - if ((lowpan6_buffer[0] & 0x18) == 0x00) { - IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset], ((lowpan6_buffer[lowpan6_offset+1] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset+3]); - lowpan6_offset += 4; - } else if ((lowpan6_buffer[0] & 0x18) == 0x08) { - IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset] & 0xc0, ((lowpan6_buffer[lowpan6_offset] & 0x0f) << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset+2]); - lowpan6_offset += 3; - } else if ((lowpan6_buffer[0] & 0x18) == 0x10) { - IP6H_VTCFL_SET(ip6hdr, 6, lowpan6_buffer[lowpan6_offset],0); - lowpan6_offset += 1; - } else if ((lowpan6_buffer[0] & 0x18) == 0x18) { - IP6H_VTCFL_SET(ip6hdr, 6, 0, 0); - } - - /* Set Next Header */ - if ((lowpan6_buffer[0] & 0x04) == 0x00) { - IP6H_NEXTH_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); - } else { - /* We should fill this later with NHC decoding */ - IP6H_NEXTH_SET(ip6hdr, 0); - } - - /* Set Hop Limit */ - if ((lowpan6_buffer[0] & 0x03) == 0x00) { - IP6H_HOPLIM_SET(ip6hdr, lowpan6_buffer[lowpan6_offset++]); - } else if ((lowpan6_buffer[0] & 0x03) == 0x01) { - IP6H_HOPLIM_SET(ip6hdr, 1); - } else if ((lowpan6_buffer[0] & 0x03) == 0x02) { - IP6H_HOPLIM_SET(ip6hdr, 64); - } else if ((lowpan6_buffer[0] & 0x03) == 0x03) { - IP6H_HOPLIM_SET(ip6hdr, 255); - } - - /* Source address decoding. */ - if ((lowpan6_buffer[1] & 0x40) == 0x00) { - /* Stateless compression */ - if ((lowpan6_buffer[1] & 0x30) == 0x00) { - /* copy full address */ - MEMCPY(&ip6hdr->src.addr[0], lowpan6_buffer + lowpan6_offset, 16); - lowpan6_offset += 16; - } else if ((lowpan6_buffer[1] & 0x30) == 0x10) { - ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->src.addr[1] = 0; - MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); - lowpan6_offset += 8; - } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { - ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->src.addr[1] = 0; - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | - lowpan6_buffer[lowpan6_offset+1]); - lowpan6_offset += 2; - } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { - ip6hdr->src.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->src.addr[1] = 0; - if (src->addr_len == 2) { - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); - } else { - ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | - (src->addr[2] << 8) | src->addr[3]); - ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | - (src->addr[6] << 8) | src->addr[7]); - } - } - } else { - /* Stateful compression */ - if ((lowpan6_buffer[1] & 0x30) == 0x00) { - /* ANY address */ - ip6hdr->src.addr[0] = 0; - ip6hdr->src.addr[1] = 0; - ip6hdr->src.addr[2] = 0; - ip6hdr->src.addr[3] = 0; - } else { - /* Set prefix from context info */ - if (lowpan6_buffer[1] & 0x80) { - i = (lowpan6_buffer[2] >> 4) & 0x0f; - } else { - i = 0; - } - if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { - /* Error */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - ip6hdr->src.addr[0] = lowpan6_context[i].addr[0]; - ip6hdr->src.addr[1] = lowpan6_context[i].addr[1]; - } - - if ((lowpan6_buffer[1] & 0x30) == 0x10) { - MEMCPY(&ip6hdr->src.addr[2], lowpan6_buffer + lowpan6_offset, 8); - lowpan6_offset += 8; - } else if ((lowpan6_buffer[1] & 0x30) == 0x20) { - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset+1]); - lowpan6_offset += 2; - } else if ((lowpan6_buffer[1] & 0x30) == 0x30) { - if (src->addr_len == 2) { - ip6hdr->src.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->src.addr[3] = lwip_htonl(0xfe000000UL | (src->addr[0] << 8) | src->addr[1]); - } else { - ip6hdr->src.addr[2] = lwip_htonl(((src->addr[0] ^ 2) << 24) | (src->addr[1] << 16) | (src->addr[2] << 8) | src->addr[3]); - ip6hdr->src.addr[3] = lwip_htonl((src->addr[4] << 24) | (src->addr[5] << 16) | (src->addr[6] << 8) | src->addr[7]); - } - } - } - - /* Destination address decoding. */ - if (lowpan6_buffer[1] & 0x08) { - /* Multicast destination */ - if (lowpan6_buffer[1] & 0x04) { - /* @todo support stateful multicast addressing */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - if ((lowpan6_buffer[1] & 0x03) == 0x00) { - /* copy full address */ - MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); - lowpan6_offset += 16; - } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { - ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | (lowpan6_buffer[lowpan6_offset++] << 16)); - ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); - ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 24) | (lowpan6_buffer[lowpan6_offset + 1] << 16) | (lowpan6_buffer[lowpan6_offset + 2] << 8) | lowpan6_buffer[lowpan6_offset + 3]); - lowpan6_offset += 4; - } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { - ip6hdr->dest.addr[0] = lwip_htonl(0xff000000UL | lowpan6_buffer[lowpan6_offset++]); - ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = 0; - ip6hdr->dest.addr[3] = lwip_htonl((lowpan6_buffer[lowpan6_offset] << 16) | (lowpan6_buffer[lowpan6_offset + 1] << 8) | lowpan6_buffer[lowpan6_offset + 2]); - lowpan6_offset += 3; - } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { - ip6hdr->dest.addr[0] = PP_HTONL(0xff020000UL); - ip6hdr->dest.addr[1] = 0; - ip6hdr->dest.addr[2] = 0; - ip6hdr->dest.addr[3] = lwip_htonl(lowpan6_buffer[lowpan6_offset++]); - } - - } else { - if (lowpan6_buffer[1] & 0x04) { - /* Stateful destination compression */ - /* Set prefix from context info */ - if (lowpan6_buffer[1] & 0x80) { - i = lowpan6_buffer[2] & 0x0f; - } else { - i = 0; - } - if (i >= LWIP_6LOWPAN_NUM_CONTEXTS) { - /* Error */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - ip6hdr->dest.addr[0] = lowpan6_context[i].addr[0]; - ip6hdr->dest.addr[1] = lowpan6_context[i].addr[1]; - } else { - /* Link local address compression */ - ip6hdr->dest.addr[0] = PP_HTONL(0xfe800000UL); - ip6hdr->dest.addr[1] = 0; - } - - if ((lowpan6_buffer[1] & 0x03) == 0x00) { - /* copy full address */ - MEMCPY(&ip6hdr->dest.addr[0], lowpan6_buffer + lowpan6_offset, 16); - lowpan6_offset += 16; - } else if ((lowpan6_buffer[1] & 0x03) == 0x01) { - MEMCPY(&ip6hdr->dest.addr[2], lowpan6_buffer + lowpan6_offset, 8); - lowpan6_offset += 8; - } else if ((lowpan6_buffer[1] & 0x03) == 0x02) { - ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (lowpan6_buffer[lowpan6_offset] << 8) | lowpan6_buffer[lowpan6_offset + 1]); - lowpan6_offset += 2; - } else if ((lowpan6_buffer[1] & 0x03) == 0x03) { - if (dest->addr_len == 2) { - ip6hdr->dest.addr[2] = PP_HTONL(0x000000ffUL); - ip6hdr->dest.addr[3] = lwip_htonl(0xfe000000UL | (dest->addr[0] << 8) | dest->addr[1]); - } else { - ip6hdr->dest.addr[2] = lwip_htonl(((dest->addr[0] ^ 2) << 24) | (dest->addr[1] << 16) | dest->addr[2] << 8 | dest->addr[3]); - ip6hdr->dest.addr[3] = lwip_htonl((dest->addr[4] << 24) | (dest->addr[5] << 16) | dest->addr[6] << 8 | dest->addr[7]); - } - } - } - - - /* Next Header Compression (NHC) decoding? */ - if (lowpan6_buffer[0] & 0x04) { - if ((lowpan6_buffer[lowpan6_offset] & 0xf8) == 0xf0) { - struct udp_hdr *udphdr; - - /* UDP compression */ - IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_UDP); - udphdr = (struct udp_hdr *)((u8_t *)q->payload + ip6_offset); - - if (lowpan6_buffer[lowpan6_offset] & 0x04) { - /* @todo support checksum decompress */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - - /* Decompress ports */ - i = lowpan6_buffer[lowpan6_offset++] & 0x03; - if (i == 0) { - udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 2] << 8 | lowpan6_buffer[lowpan6_offset + 3]); - lowpan6_offset += 4; - } else if (i == 0x01) { - udphdr->src = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - udphdr->dest = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset + 2]); - lowpan6_offset += 3; - } else if (i == 0x02) { - udphdr->src = lwip_htons(0xf000 | lowpan6_buffer[lowpan6_offset]); - udphdr->dest = lwip_htons(lowpan6_buffer[lowpan6_offset + 1] << 8 | lowpan6_buffer[lowpan6_offset + 2]); - lowpan6_offset += 3; - } else if (i == 0x03) { - udphdr->src = lwip_htons(0xf0b0 | ((lowpan6_buffer[lowpan6_offset] >> 4) & 0x0f)); - udphdr->dest = lwip_htons(0xf0b0 | (lowpan6_buffer[lowpan6_offset] & 0x0f)); - lowpan6_offset += 1; - } - - udphdr->chksum = lwip_htons(lowpan6_buffer[lowpan6_offset] << 8 | lowpan6_buffer[lowpan6_offset + 1]); - lowpan6_offset += 2; - udphdr->len = lwip_htons(p->tot_len - lowpan6_offset + UDP_HLEN); - - ip6_offset += UDP_HLEN; - } else { - /* @todo support NHC other than UDP */ - pbuf_free(p); - pbuf_free(q); - return NULL; - } - } - - /* Now we copy leftover contents from p to q, so we have all L2 and L3 headers (and L4?) in a single PBUF. - * Replace p with q, and free p */ - pbuf_header(p, -lowpan6_offset); - MEMCPY((u8_t*)q->payload + ip6_offset, p->payload, p->len); - q->len = q->tot_len = ip6_offset + p->len; - if (p->next != NULL) { - pbuf_cat(q, p->next); - } - p->next = NULL; - pbuf_free(p); - - /* Infer IPv6 payload length for header */ - IP6H_PLEN_SET(ip6hdr, q->tot_len - IP6_HLEN); - - /* all done */ - return q; -} - -err_t -lowpan6_input(struct pbuf * p, struct netif *netif) -{ - u8_t * puc; - s8_t i; - struct ieee_802154_addr src, dest; - u16_t datagram_size, datagram_offset, datagram_tag; - struct lowpan6_reass_helper *lrh, *lrh_temp; - - MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); - - /* Analyze header. @todo validate. */ - puc = (u8_t*)p->payload; - datagram_offset = 5; - if ((puc[1] & 0x0c) == 0x0c) { - dest.addr_len = 8; - for (i = 0; i < 8; i++) { - dest.addr[i] = puc[datagram_offset + 7 - i]; - } - datagram_offset += 8; - } else { - dest.addr_len = 2; - dest.addr[0] = puc[datagram_offset + 1]; - dest.addr[1] = puc[datagram_offset]; - datagram_offset += 2; - } - - datagram_offset += 2; /* skip PAN ID. */ - - if ((puc[1] & 0xc0) == 0xc0) { - src.addr_len = 8; - for (i = 0; i < 8; i++) { - src.addr[i] = puc[datagram_offset + 7 - i]; - } - datagram_offset += 8; - } else { - src.addr_len = 2; - src.addr[0] = puc[datagram_offset + 1]; - src.addr[1] = puc[datagram_offset]; - datagram_offset += 2; - } - - pbuf_header(p, -datagram_offset); /* hide IEEE802.15.4 header. */ - - /* Check dispatch. */ - puc = (u8_t*)p->payload; - - if ((*puc & 0xf8) == 0xc0) { - /* FRAG1 dispatch. add this packet to reassembly list. */ - datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; - datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; - - /* check for duplicate */ - lrh = reass_list; - while (lrh != NULL) { - if ((lrh->sender_addr.addr_len == src.addr_len) && - (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0)) { - /* address match with packet in reassembly. */ - if ((datagram_tag == lrh->datagram_tag) && (datagram_size == lrh->datagram_size)) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - /* duplicate fragment. */ - pbuf_free(p); - return ERR_OK; - } else { - /* We are receiving the start of a new datagram. Discard old one (incomplete). */ - lrh_temp = lrh->next_packet; - dequeue_datagram(lrh); - pbuf_free(lrh->pbuf); - mem_free(lrh); - - /* Check next datagram in queue. */ - lrh = lrh_temp; - } - } else { - /* Check next datagram in queue. */ - lrh = lrh->next_packet; - } - } - - pbuf_header(p, -4); /* hide frag1 dispatch */ - - lrh = (struct lowpan6_reass_helper *) mem_malloc(sizeof(struct lowpan6_reass_helper)); - if (lrh == NULL) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - pbuf_free(p); - return ERR_MEM; - } - - lrh->sender_addr.addr_len = src.addr_len; - for (i = 0; i < src.addr_len; i++) { - lrh->sender_addr.addr[i] = src.addr[i]; - } - lrh->datagram_size = datagram_size; - lrh->datagram_tag = datagram_tag; - lrh->pbuf = p; - lrh->next_packet = reass_list; - lrh->timer = 2; - reass_list = lrh; - - return ERR_OK; - } else if ((*puc & 0xf8) == 0xe0) { - /* FRAGN dispatch, find packet being reassembled. */ - datagram_size = ((u16_t)(puc[0] & 0x07) << 8) | (u16_t)puc[1]; - datagram_tag = ((u16_t)puc[2] << 8) | (u16_t)puc[3]; - datagram_offset = (u16_t)puc[4] << 3; - pbuf_header(p, -5); /* hide frag1 dispatch */ - - for (lrh = reass_list; lrh != NULL; lrh = lrh->next_packet) { - if ((lrh->sender_addr.addr_len == src.addr_len) && - (memcmp(lrh->sender_addr.addr, src.addr, src.addr_len) == 0) && - (datagram_tag == lrh->datagram_tag) && - (datagram_size == lrh->datagram_size)) { - break; - } - } - if (lrh == NULL) { - /* rogue fragment */ - MIB2_STATS_NETIF_INC(netif, ifindiscards); - pbuf_free(p); - return ERR_OK; - } - - if (lrh->pbuf->tot_len < datagram_offset) { - /* duplicate, ignore. */ - pbuf_free(p); - return ERR_OK; - } else if (lrh->pbuf->tot_len > datagram_offset) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - /* We have missed a fragment. Delete whole reassembly. */ - dequeue_datagram(lrh); - pbuf_free(lrh->pbuf); - mem_free(lrh); - pbuf_free(p); - return ERR_OK; - } - pbuf_cat(lrh->pbuf, p); - p = NULL; - - /* is packet now complete?*/ - if (lrh->pbuf->tot_len >= lrh->datagram_size) { - /* dequeue from reass list. */ - dequeue_datagram(lrh); - - /* get pbuf */ - p = lrh->pbuf; - - /* release helper */ - mem_free(lrh); - } else { - return ERR_OK; - } - } - - if (p == NULL) { - return ERR_OK; - } - - /* We have a complete packet, check dispatch for headers. */ - puc = (u8_t*)p->payload; - - if (*puc == 0x41) { - /* This is a complete IPv6 packet, just skip dispatch byte. */ - pbuf_header(p, -1); /* hide dispatch byte. */ - } else if ((*puc & 0xe0 )== 0x60) { - /* IPv6 headers are compressed using IPHC. */ - p = lowpan6_decompress(p, &src, &dest); - if (p == NULL) { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - return ERR_OK; - } - } else { - MIB2_STATS_NETIF_INC(netif, ifindiscards); - pbuf_free(p); - return ERR_OK; - } - - /* @todo: distinguish unicast/multicast */ - MIB2_STATS_NETIF_INC(netif, ifinucastpkts); - - return ip6_input(p, netif); -} - -err_t -lowpan6_if_init(struct netif *netif) -{ - netif->name[0] = 'L'; - netif->name[1] = '6'; -#if LWIP_IPV4 - netif->output = lowpan4_output; -#endif /* LWIP_IPV4 */ - netif->output_ip6 = lowpan6_output; - - MIB2_INIT_NETIF(netif, snmp_ifType_other, 0); - - /* maximum transfer unit */ - netif->mtu = 1280; - - /* broadcast capability */ - netif->flags = NETIF_FLAG_BROADCAST /* | NETIF_FLAG_LOWPAN6 */; - - return ERR_OK; -} - -err_t -lowpan6_set_pan_id(u16_t pan_id) -{ - ieee_802154_pan_id = pan_id; - - return ERR_OK; -} - -#if !NO_SYS -/** - * Pass a received packet to tcpip_thread for input processing - * - * @param p the received packet, p->payload pointing to the - * IEEE 802.15.4 header. - * @param inp the network interface on which the packet was received - */ -err_t -tcpip_6lowpan_input(struct pbuf *p, struct netif *inp) -{ - return tcpip_inpkt(p, inp, lowpan6_input); -} -#endif /* !NO_SYS */ - -#endif /* LWIP_IPV6 && LWIP_6LOWPAN */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/PPPD_FOLLOWUP b/components/net/lwip-2.0.2/src/netif/ppp/PPPD_FOLLOWUP deleted file mode 100644 index c231982ae7..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/PPPD_FOLLOWUP +++ /dev/null @@ -1,473 +0,0 @@ -The lwIP PPP support is based from pppd 2.4.5 (http://ppp.samba.org) with -huge changes to match code size and memory requirements for embedded devices. - -Anyway, pppd has a mature codebase for years and the average commit count -is getting low on their Git repository, meaning that we can follow what -is happening on their side and merge what is relevant for lwIP. - -So, here is the pppd follow up, so that we don't get away too far from pppd. - - -== Patch fetched from from pppd Debian packages == - -This has nothing to do with pppd, but we merged some good patch from -Debian and this is a good place to be. - -- LCP adaptive echo, so that we don't send LCP echo request if we - are receiving data from peer, can be enabled by setting PPP_LCP_ADAPTIVE - to true. - -- IPCP no/replace default route option, were added in the early stage of - the ppp port, but it wasn't really helpful and was disabled when adding - the new API ppp_set_default() call, which gives the lwIP user control over - which one is the default interface, it was actually a requirement if you - are doing PPP over PPP (i.e. PPPoL2TP, VPN link, over PPPoE, ADSL link). - -- using rp-pppoe pppd exits with EXIT_OK after receiving a timeout waiting - for PADO due to no modem attached, bug reported to pppd bug tracker, fixed - in Debian but not in the latest (at the time when the port were started) - pppd release. - - -== Commits on pppd == - -2010-03-06 - Document +ipv6 and ipv6cp-accept-local - e7537958aee79b3f653c601e903cb31d78fb7dcc - -Don't care. - - -2010-03-06 - Install pppol2tp plugins with sane permissions - 406215672cfadc03017341fe03802d1c7294b903 - -Don't care. - - -2010-03-07 - pppd: Terminate correctly if lcp_lowerup delayed calling - fsm_lowerup - 3eb9e810cfa515543655659b72dde30c54fea0a5 - -Merged 2012-05-17. - - -2010-03-07 - rp_pppoe: Copy acName and pppd_pppoe_service after option parsing - cab58617fd9d328029fffabc788020264b4fa91f - -Don't care, is a patch for pppd/plugins/rp-pppoe/plugin.c which is not part -of the port. - - -2010-08-23 - set and reset options to control environment variables - for scripts. - 2b6310fd24dba8e0fca8999916a162f0a1842a84 - -We can't fork processes in embedded, therefore all the pppd process run -feature is disabled in the port, so we don't care about the new -"environment variables" pppd feature. - - -2010-08-23 - Nit: use _exit when exec fails and restrict values to 0-255 - per POSIX. - 2b4ea140432eeba5a007c0d4e6236bd0e0c12ba4 - -Again, we are not running as a heavy process, so all exit() or _exit() calls -were removed. - - -2010-08-23 - Fix quote handling in configuration files to be more like shell - quoting. - 3089132cdf5b58dbdfc2daf08ec5c08eb47f8aca - -We are not parsing config file, all the filesystem I/O stuff were disabled -in our port. - - -2010-08-24 - rp-pppoe: allow MTU to be increased up to 1500 - fd1dcdf758418f040da3ed801ab001b5e46854e7 - -Only concern changes on RP-PPPoE plugin, which we don't use. - - -2010-09-11 - chat: Allow TIMEOUT value to come from environment variable - ae80bf833e48a6202f44a935a68083ae52ad3824 - -See 2b6310fd24dba8e0fca8999916a162f0a1842a84. - - -2011-03-05 - pppdump: Fix printfs with insufficient arguments - 7b8db569642c83ba3283745034f2e2c95e459423 - -pppdump is a ppp tool outside pppd source tree. - - -2012-05-06 - pppd: Don't unconditionally disable VJ compression under Linux - d8a66adf98a0e525cf38031b42098d539da6eeb6 - -Patch for sys-linux.c, which we don't use. - - -2012-05-20 - Remove old version of Linux if_pppol2tp.h - c41092dd4c49267f232f6cba3d31c6c68bfdf68d - -Not in the port. - - -2012-05-20 - pppd: Make MSCHAP-v2 cope better with packet loss - 08ef47ca532294eb428238c831616748940e24a2 - -This is an interesting patch. However it consumes much more memory for -MSCHAP and I am not sure if the benefit worth it. The PPP client can -always start the authentication again if it failed for whatever reason. - - -2012-05-20 - scripts: Make poff ignore extra arguments to pppd - 18f515f32c9f5723a9c2c912601e04335106534b - -Again, we are not running scripts. - - -2012-05-20 - rp-pppoe plugin: Print leading zeros in MAC address - f5dda0cfc220c4b52e26144096d729e27b30f0f7 - -Again, we are not using the RP-PPPoE plugin. - - -2012-05-20 - pppd: Notify IPv6 up/down as we do for IPv4 - 845cda8fa18939cf56e60b073f63a7efa65336fc - -This is just a patch that adds plugins hooks for IPv6, the plugin interface -was disabled because we don't have .so plugins in embedded. - - -2012-05-20 - pppd: Enable IPV6 by default and fix some warnings - 0b6118239615e98959f7e0b4e746bdd197533248 - -Change on Makefile for IPv6, warnings were already cleared during port. - - -2012-05-20 - contrib: Fix pppgetpass.gtk compilation - 80a8e2ce257ca12cce723519a0f20ea1d663b14a - -Change on Makefile, don't care. - - -2012-05-20 - pppd: Don't crash if crypt() returns NULL - 04c4348108d847e034dd91066cc6843f60d71731 - -We are using the PolarSSL DES implementation that does not return NULL. - - -2012-05-20 - pppd: Eliminate some warnings - c44ae5e6a7338c96eb463881fe709b2dfaffe568 - -Again, we are handling compilation warnings on our own. - - -2012-05-20 - rp-pppoe plugin: Import some fixes from rp-pppoe-3.10 - 1817d83e51a411044e730ba89ebdb0480e1c8cd4 - -Once more, we are not using the RP-PPPoE plugin. - - -2013-01-23 - pppd: Clarify circumstances where DNS1/DNS2 environment variables are set - cf2f5c9538b9400ade23446a194729b0a4113b3a - -Documentation only. - - -2013-02-03 - ppp: ignore unrecognised radiusclient configuration directives - 7f736dde0da3c19855997d9e67370e351e15e923 - -Radius plugin, not in the port. - - -2013-02-03 - pppd: Take out unused %r conversion completely - 356d8d558d844412119aa18c8e5a113bc6459c7b - -Merged 2014-04-15. - - -2013-02-03 - pppd: Arrange to use logwtmp from libutil on Linux - 9617a7eb137f4fee62799a677a9ecf8d834db3f5 - -Patch for sys-linux.c, which we don't use. - - -2013-02-03 - pppdump: Eliminate some compiler warnings - 3e3acf1ba2b3046c072a42c19164788a9e419bd1 - -pppdump is a ppp tool outside pppd source tree. - - -2013-02-03 - chat: Correct spelling errors in the man page - 8dea1b969d266ccbf6f3a8c5474eb6dcd8838e3b - -Documentation only. - - -2013-02-03 - pppd: Fix spelling errors in man page - 9e05a25d76b3f83096c661678010320df673df6b - -Documentation only. - - -2013-02-03 - plugins/passprompt: Fix potential out-of-bounds array reference - 8edb889b753056a691a3e4b217a110a35f9fdedb - -Plugin patch, we do not have plugins. - - -2013-02-03 - chat: Fix *roff errors in the man page - a7c3489eeaf44e83ce592143c7c8a5b5c29f4c48 - -Documentation only. - - -2013-03-02 - pppd: Fix man page description of case when remote IP address isn't known - 224841f4799f4f1e2e71bc490c54448d66740f4f - -Documentation only. - - -2013-03-02 - pppd: Add master_detach option - 398ed2585640d198c53e736ee5bbd67f7ce8168e - -Option for multilink support, we do not support multilink and this option -is about detaching from the terminal, which is out of the embedded scope. - - -2013-03-11 - pppd: Default exit status to EXIT_CONNECT_FAILED during connection phase - 225361d64ae737afdc8cb57579a2f33525461bc9 - -Commented out in our port, and already fixed by a previously applied Debian patch. - - -2013-03-11 - pppstats: Fix undefined macro in man page - d16a3985eade5280b8e171f5dd0670a91cba0d39 - -Documentation only. - - -2013-05-11 - plugins/radius: Handle bindaddr keyword in radiusclient.conf - d883b2dbafeed3ebd9d7a56ab1469373bd001a3b - -Radius plugin, not in the port. - - -2013-06-09 - pppoatm: Remove explicit loading of pppoatm kernel module - 52cd43a84bea524033b918b603698104f221bbb7 - -PPPoATM plugin, not in the port. - - -2013-06-09 - pppd: Fix segfault in update_db_entry() - 37476164f15a45015310b9d4b197c2d7db1f7f8f - -We do not use the samba db. - - -2013-06-09 - chat: Fix some text that was intended to be literal - cd9683676618adcee8add2c3cfa3382341b5a1f6 - -Documentation only. - - -2013-06-09 - README.pppoe: Minor semantic fix - b5b8898af6fd3d44e873cfc66810ace5f1f47e17 - -Documentation only. - - -2013-06-10 - radius: Handle additional attributes - 2f581cd986a56f2ec4a95abad4f8297a1b10d7e2 - -Radius plugin, not in the port. - - -2013-06-10 - chat, pppd: Use \e instead of \\ in man pages - 8d6942415d22f6ca4377340ca26e345c3f5fa5db - -Documentation only. - - -2014-01-02 - pppd: Don't crash if NULL pointer passed to vslprintf for %q or %v - 906814431bddeb2061825fa1ebad1a967b6d87a9 - -Merged 2014-04-15. - - -2014-01-02 - pppd: Accept IPCP ConfAck packets containing MS-WINS options - a243f217f1c6ac1aa7793806bc88590d077f490a - -Merged 2014-04-15. - - -2014-01-02 - config: Update Solaris compiler options and enable CHAPMS and IPV6 - 99c46caaed01b7edba87962aa52b77fad61bfd7b - -Solaris port, don't care. - - -2014-01-02 - Update README and patchlevel for 2.4.6 release - 4043750fca36e7e0eb90d702e048ad1da4929418 - -Just release stuff. - - -2014-02-18 - pppd: Add option "stop-bits" to set number of serial port stop bits. - ad993a20ee485f0d0e2ac4105221641b200da6e2 - -Low level serial port, not in the port. - - -2014-03-09 - pppd: Separate IPv6 handling for sifup/sifdown - b04d2dc6df5c6b5650fea44250d58757ee3dac4a - -Reimplemented. - - -2014-03-09 - pppol2tp: Connect up/down events to notifiers and add IPv6 ones - fafbe50251efc7d6b4a8be652d085316e112b34f - -Not in the port. - - -2014-03-09 - pppd: Add declarations to eliminate compile warnings - 50967962addebe15c7a7e63116ff46a0441dc464 - -We are handling compilation warnings on our own - - -2014-03-09 - pppd: Eliminate some unnecessary ifdefs - de8da14d845ee6db9236ccfddabf1d8ebf045ddb - -We mostly did that previously. Anyway, merged 2014-12-24. - - -2014-08-01 - radius: Fix realms-config-file option - 880a81be7c8e0fe8567227bc17a1bff3ea035943 - -Radius plugin, not in the port. - - -2014-08-01 - pppd: Eliminate potential integer overflow in option parsing - 7658e8257183f062dc01f87969c140707c7e52cb - -pppd config file parser, not in the port. - - -2014-08-01 - pppd: Eliminate memory leak with multiple instances of a string option - b94b7fbbaa0589aa6ec5fdc733aeb9ff294d2656 - -pppd config file parser, not in the port. - - -2014-08-01 - pppd: Fix a stack variable overflow in MSCHAP-v2 - 36733a891fb56594fcee580f667b33a64b990981 - -This fixes a bug introduced in 08ef47ca ("pppd: Make MSCHAP-v2 cope better with packet loss"). - -We didn't merge 08ef47ca ;-) - - -2014-08-01 - winbind plugin: Add -DMPPE=1 to eliminate compiler warnings - 2b05e22c62095e97dd0a97e4b5588402c2185071 - -Linux plugin, not in the port. - - -2014-08-09 - Update README and patchlevel for 2.4.7 release - 6e8eaa7a78b31cdab2edf140a9c8afdb02ffaca5 - -Just release stuff. - - -2014-08-10 - abort on errors in subdir builds - 5e90783d11a59268e05f4cfb29ce2343b13e8ab2 - -Linux Makefile, not in the port. - - -2014-06-03 - pppd: add support for defaultroute-metric option - 35e5a569c988b1ff865b02a24d9a727a00db4da9 - -Only necessary for Linux, lwIP does not support route metrics. - - -2014-12-13 - scripts: Avoid killing wrong pppd - 67811a647d399db5d188a242827760615a0f86b5 - -pppd helper script, not in the port. - - -2014-12-20 - pppd: Fix sign-extension when displaying bytes in octal - 5e8c3cb256a7e86e3572a82a75d51c6850efdbdc - -Merged 2016-07-02. - - -2015-03-01 - Suppress false error message on PPPoE disconnect - 219aac3b53d0827549377f1bfe22853ee52d4405 - -PPPoE plugin, not in the port. - - -2015-03-01 - Send PADT on PPPoE disconnect - cd2c14f998c57bbe6a01dc5854f2763c0d7f31fb - -PPPoE plugin, not in the port. And our PPPoE implementation already does -that: pppoe_disconnect() calls pppoe_send_padt(). - - -2015-08-14 - pppd: ipxcp: Prevent buffer overrun on remote router name - fe149de624f96629a7f46732055d8f718c74b856 - -We never ported IPX support. lwIP does not support IPX. - - -2015-03-25 - pppd: Fix ccp_options.mppe type - 234edab99a6bb250cc9ecd384cca27b0c8b475ce - -We found that while working on MPPE support in lwIP, that's our patch ;-) - - -2015-03-24 - pppd: Fix ccp_cilen calculated size if both deflate_correct and deflate_draft are enabled - 094cb8ae4c61db225e67fedadb4964f846dd0c27 - -We found that while working on MPPE support in lwIP, that's our patch ;-) - - -2015-08-14 - Merge branch 'master' of https://github.com/ncopa/ppp - 3a5c9a8fbc8970375cd881151d44e4b6fe249c6a - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'master' of git://github.com/vapier/ppp - 912e4fc6665aca188dced7ea7fdc663ce5a2dd24 - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'bug_fix' of git://github.com/radaiming/ppp - dfd33d7f526ecd7b39dd1bba8101260d02af5ebb - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'master' of git://github.com/pprindeville/ppp - aa4a985f6114d08cf4e47634fb6325da71016473 - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'no-error-on-already-closed' of git://github.com/farnz/ppp - 6edf252483b30dbcdcc5059f01831455365d5b6e - -Merge commit, we don't care. - - -2015-08-14 - Merge branch 'send-padt-on-disconnect' of git://github.com/farnz/ppp - 84684243d651f55f6df69d2a6707b52fbbe62bb9 - -Merge commit, we don't care. diff --git a/components/net/lwip-2.0.2/src/netif/ppp/auth.c b/components/net/lwip-2.0.2/src/netif/ppp/auth.c deleted file mode 100644 index c8673ad0fb..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/auth.c +++ /dev/null @@ -1,2510 +0,0 @@ -/* - * auth.c - PPP authentication and phase control. - * - * Copyright (c) 1993-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Derived from main.c, which is: - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(_PATH_LASTLOG) && defined(__linux__) -#include -#endif - -#include -#include -#include - -#ifdef HAS_SHADOW -#include -#ifndef PW_PPP -#define PW_PPP PW_LOGIN -#endif -#endif - -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#if CCP_SUPPORT -#include "netif/ppp/ccp.h" -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT -#include "netif/ppp/ecp.h" -#endif /* ECP_SUPPORT */ -#include "netif/ppp/ipcp.h" -#if PAP_SUPPORT -#include "netif/ppp/upap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "netif/ppp/chap-new.h" -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#include "netif/ppp/eap.h" -#endif /* EAP_SUPPORT */ -#if CBCP_SUPPORT -#include "netif/ppp/cbcp.h" -#endif - -#if 0 /* UNUSED */ -#include "session.h" -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* Bits in scan_authfile return value */ -#define NONWILD_SERVER 1 -#define NONWILD_CLIENT 2 - -#define ISWILD(word) (word[0] == '*' && word[1] == 0) -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* List of addresses which the peer may use. */ -static struct permitted_ip *addresses[NUM_PPP]; - -/* Wordlist giving addresses which the peer may use - without authenticating itself. */ -static struct wordlist *noauth_addrs; - -/* Remote telephone number, if available */ -char remote_number[MAXNAMELEN]; - -/* Wordlist giving remote telephone numbers which may connect. */ -static struct wordlist *permitted_numbers; - -/* Extra options to apply, from the secrets file entry for the peer. */ -static struct wordlist *extra_options; -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* Set if we require authentication only because we have a default route. */ -static bool default_auth; - -/* Hook to enable a plugin to control the idle time limit */ -int (*idle_time_hook) (struct ppp_idle *) = NULL; - -/* Hook for a plugin to say whether we can possibly authenticate any peer */ -int (*pap_check_hook) (void) = NULL; - -/* Hook for a plugin to check the PAP user and password */ -int (*pap_auth_hook) (char *user, char *passwd, char **msgp, - struct wordlist **paddrs, - struct wordlist **popts) = NULL; - -/* Hook for a plugin to know about the PAP user logout */ -void (*pap_logout_hook) (void) = NULL; - -/* Hook for a plugin to get the PAP password for authenticating us */ -int (*pap_passwd_hook) (char *user, char *passwd) = NULL; - -/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */ -int (*chap_check_hook) (void) = NULL; - -/* Hook for a plugin to get the CHAP password for authenticating us */ -int (*chap_passwd_hook) (char *user, char *passwd) = NULL; - -/* Hook for a plugin to say whether it is OK if the peer - refuses to authenticate. */ -int (*null_auth_hook) (struct wordlist **paddrs, - struct wordlist **popts) = NULL; - -int (*allowed_address_hook) (u32_t addr) = NULL; -#endif /* UNUSED */ - -#ifdef HAVE_MULTILINK -/* Hook for plugin to hear when an interface joins a multilink bundle */ -void (*multilink_join_hook) (void) = NULL; -#endif - -#if PPP_NOTIFY -/* A notifier for when the peer has authenticated itself, - and we are proceeding to the network phase. */ -struct notifier *auth_up_notifier = NULL; - -/* A notifier for when the link goes down. */ -struct notifier *link_down_notifier = NULL; -#endif /* PPP_NOTIFY */ - -/* - * Option variables. - */ -#if 0 /* MOVED TO ppp_settings */ -bool uselogin = 0; /* Use /etc/passwd for checking PAP */ -bool session_mgmt = 0; /* Do session management (login records) */ -bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ -bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ -bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ -bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */ -#if MSCHAP_SUPPORT -bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */ -bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */ -#else /* MSCHAP_SUPPORT */ -bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ -bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ -#endif /* MSCHAP_SUPPORT */ -bool usehostname = 0; /* Use hostname for our_name */ -bool auth_required = 0; /* Always require authentication from peer */ -bool allow_any_ip = 0; /* Allow peer to use any IP address */ -bool explicit_remote = 0; /* User specified explicit remote name */ -bool explicit_user = 0; /* Set if "user" option supplied */ -bool explicit_passwd = 0; /* Set if "password" option supplied */ -char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ -static char *uafname; /* name of most recent +ua file */ - -extern char *crypt (const char *, const char *); -#endif /* UNUSED */ -/* Prototypes for procedures local to this file. */ - -static void network_phase(ppp_pcb *pcb); -#if PPP_IDLETIMELIMIT -static void check_idle(void *arg); -#endif /* PPP_IDLETIMELIMIT */ -#if PPP_MAXCONNECT -static void connect_time_expired(void *arg); -#endif /* PPP_MAXCONNECT */ -#if 0 /* UNUSED */ -static int null_login (int); -/* static int get_pap_passwd (char *); */ -static int have_pap_secret (int *); -static int have_chap_secret (char *, char *, int, int *); -static int have_srp_secret (char *client, char *server, int need_ip, - int *lacks_ipp); -static int ip_addr_check (u32_t, struct permitted_ip *); -static int scan_authfile (FILE *, char *, char *, char *, - struct wordlist **, struct wordlist **, - char *, int); -static void free_wordlist (struct wordlist *); -static void set_allowed_addrs (int, struct wordlist *, struct wordlist *); -static int some_ip_ok (struct wordlist *); -static int setupapfile (char **); -static int privgroup (char **); -static int set_noauth_addr (char **); -static int set_permitted_number (char **); -static void check_access (FILE *, char *); -static int wordlist_count (struct wordlist *); -#endif /* UNUSED */ - -#ifdef MAXOCTETS -static void check_maxoctets (void *); -#endif - -#if PPP_OPTIONS -/* - * Authentication-related options. - */ -option_t auth_options[] = { - { "auth", o_bool, &auth_required, - "Require authentication from peer", OPT_PRIO | 1 }, - { "noauth", o_bool, &auth_required, - "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, - &allow_any_ip }, - { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", - OPT_PRIOSUB | 1, &auth_required }, - { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, - { "require-chap", o_bool, &auth_required, - "Require CHAP authentication from peer", - OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, - &lcp_wantoptions[0].chap_mdtype }, - { "+chap", o_bool, &auth_required, - "Require CHAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5, - &lcp_wantoptions[0].chap_mdtype }, -#if MSCHAP_SUPPORT - { "require-mschap", o_bool, &auth_required, - "Require MS-CHAP authentication from peer", - OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, - &lcp_wantoptions[0].chap_mdtype }, - { "+mschap", o_bool, &auth_required, - "Require MS-CHAP authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT, - &lcp_wantoptions[0].chap_mdtype }, - { "require-mschap-v2", o_bool, &auth_required, - "Require MS-CHAPv2 authentication from peer", - OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, - &lcp_wantoptions[0].chap_mdtype }, - { "+mschap-v2", o_bool, &auth_required, - "Require MS-CHAPv2 authentication from peer", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2, - &lcp_wantoptions[0].chap_mdtype }, -#endif /* MSCHAP_SUPPORT */ -#if 0 - { "refuse-pap", o_bool, &refuse_pap, - "Don't agree to auth to peer with PAP", 1 }, - { "-pap", o_bool, &refuse_pap, - "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, - { "refuse-chap", o_bool, &refuse_chap, - "Don't agree to auth to peer with CHAP", - OPT_A2CLRB | MDTYPE_MD5, - &lcp_allowoptions[0].chap_mdtype }, - { "-chap", o_bool, &refuse_chap, - "Don't allow CHAP authentication with peer", - OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5, - &lcp_allowoptions[0].chap_mdtype }, -#endif -#if MSCHAP_SUPPORT -#if 0 - { "refuse-mschap", o_bool, &refuse_mschap, - "Don't agree to auth to peer with MS-CHAP", - OPT_A2CLRB | MDTYPE_MICROSOFT, - &lcp_allowoptions[0].chap_mdtype }, - { "-mschap", o_bool, &refuse_mschap, - "Don't allow MS-CHAP authentication with peer", - OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT, - &lcp_allowoptions[0].chap_mdtype }, - { "refuse-mschap-v2", o_bool, &refuse_mschap_v2, - "Don't agree to auth to peer with MS-CHAPv2", - OPT_A2CLRB | MDTYPE_MICROSOFT_V2, - &lcp_allowoptions[0].chap_mdtype }, - { "-mschap-v2", o_bool, &refuse_mschap_v2, - "Don't allow MS-CHAPv2 authentication with peer", - OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2, - &lcp_allowoptions[0].chap_mdtype }, -#endif -#endif /* MSCHAP_SUPPORT*/ -#if EAP_SUPPORT - { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap, - "Require EAP authentication from peer", OPT_PRIOSUB | 1, - &auth_required }, -#if 0 - { "refuse-eap", o_bool, &refuse_eap, - "Don't agree to authenticate to peer with EAP", 1 }, -#endif -#endif /* EAP_SUPPORT */ - { "name", o_string, our_name, - "Set local name for authentication", - OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, - - { "+ua", o_special, (void *)setupapfile, - "Get PAP user and password from file", - OPT_PRIO | OPT_A2STRVAL, &uafname }, - -#if 0 - { "user", o_string, user, - "Set name for auth with peer", OPT_PRIO | OPT_STATIC, - &explicit_user, MAXNAMELEN }, - - { "password", o_string, passwd, - "Password for authenticating us to the peer", - OPT_PRIO | OPT_STATIC | OPT_HIDE, - &explicit_passwd, MAXSECRETLEN }, -#endif - - { "usehostname", o_bool, &usehostname, - "Must use hostname for authentication", 1 }, - - { "remotename", o_string, remote_name, - "Set remote name for authentication", OPT_PRIO | OPT_STATIC, - &explicit_remote, MAXNAMELEN }, - - { "login", o_bool, &uselogin, - "Use system password database for PAP", OPT_A2COPY | 1 , - &session_mgmt }, - { "enable-session", o_bool, &session_mgmt, - "Enable session accounting for remote peers", OPT_PRIV | 1 }, - - { "papcrypt", o_bool, &cryptpap, - "PAP passwords are encrypted", 1 }, - - { "privgroup", o_special, (void *)privgroup, - "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, - - { "allow-ip", o_special, (void *)set_noauth_addr, - "Set IP address(es) which can be used without authentication", - OPT_PRIV | OPT_A2LIST }, - - { "remotenumber", o_string, remote_number, - "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC, - NULL, MAXNAMELEN }, - - { "allow-number", o_special, (void *)set_permitted_number, - "Set telephone number(s) which are allowed to connect", - OPT_PRIV | OPT_A2LIST }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -#if 0 /* UNUSED */ -/* - * setupapfile - specifies UPAP info for authenticating with peer. - */ -static int -setupapfile(argv) - char **argv; -{ - FILE *ufile; - int l; - uid_t euid; - char u[MAXNAMELEN], p[MAXSECRETLEN]; - char *fname; - - lcp_allowoptions[0].neg_upap = 1; - - /* open user info file */ - fname = strdup(*argv); - if (fname == NULL) - novm("+ua file name"); - euid = geteuid(); - if (seteuid(getuid()) == -1) { - option_error("unable to reset uid before opening %s: %m", fname); - return 0; - } - ufile = fopen(fname, "r"); - if (seteuid(euid) == -1) - fatal("unable to regain privileges: %m"); - if (ufile == NULL) { - option_error("unable to open user login data file %s", fname); - return 0; - } - check_access(ufile, fname); - uafname = fname; - - /* get username */ - if (fgets(u, MAXNAMELEN - 1, ufile) == NULL - || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) { - fclose(ufile); - option_error("unable to read user login data file %s", fname); - return 0; - } - fclose(ufile); - - /* get rid of newlines */ - l = strlen(u); - if (l > 0 && u[l-1] == '\n') - u[l-1] = 0; - l = strlen(p); - if (l > 0 && p[l-1] == '\n') - p[l-1] = 0; - - if (override_value("user", option_priority, fname)) { - strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user)); - explicit_user = 1; - } - if (override_value("passwd", option_priority, fname)) { - strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd)); - explicit_passwd = 1; - } - - return (1); -} - -/* - * privgroup - allow members of the group to have privileged access. - */ -static int -privgroup(argv) - char **argv; -{ - struct group *g; - int i; - - g = getgrnam(*argv); - if (g == 0) { - option_error("group %s is unknown", *argv); - return 0; - } - for (i = 0; i < ngroups; ++i) { - if (groups[i] == g->gr_gid) { - privileged = 1; - break; - } - } - return 1; -} - - -/* - * set_noauth_addr - set address(es) that can be used without authentication. - * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. - */ -static int -set_noauth_addr(argv) - char **argv; -{ - char *addr = *argv; - int l = strlen(addr) + 1; - struct wordlist *wp; - - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); - if (wp == NULL) - novm("allow-ip argument"); - wp->word = (char *) (wp + 1); - wp->next = noauth_addrs; - MEMCPY(wp->word, addr, l); - noauth_addrs = wp; - return 1; -} - - -/* - * set_permitted_number - set remote telephone number(s) that may connect. - */ -static int -set_permitted_number(argv) - char **argv; -{ - char *number = *argv; - int l = strlen(number) + 1; - struct wordlist *wp; - - wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l); - if (wp == NULL) - novm("allow-number argument"); - wp->word = (char *) (wp + 1); - wp->next = permitted_numbers; - MEMCPY(wp->word, number, l); - permitted_numbers = wp; - return 1; -} -#endif - -/* - * An Open on LCP has requested a change from Dead to Establish phase. - */ -void link_required(ppp_pcb *pcb) { - LWIP_UNUSED_ARG(pcb); -} - -#if 0 -/* - * Bring the link up to the point of being able to do ppp. - */ -void start_link(unit) - int unit; -{ - ppp_pcb *pcb = &ppp_pcb_list[unit]; - char *msg; - - status = EXIT_NEGOTIATION_FAILED; - new_phase(pcb, PPP_PHASE_SERIALCONN); - - hungup = 0; - devfd = the_channel->connect(); - msg = "Connect script failed"; - if (devfd < 0) - goto fail; - - /* set up the serial device as a ppp interface */ - /* - * N.B. we used to do tdb_writelock/tdb_writeunlock around this - * (from establish_ppp to set_ifunit). However, we won't be - * doing the set_ifunit in multilink mode, which is the only time - * we need the atomicity that the tdb_writelock/tdb_writeunlock - * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock. - */ - fd_ppp = the_channel->establish_ppp(devfd); - msg = "ppp establishment failed"; - if (fd_ppp < 0) { - status = EXIT_FATAL_ERROR; - goto disconnect; - } - - if (!demand && ifunit >= 0) - set_ifunit(1); - - /* - * Start opening the connection and wait for - * incoming events (reply, timeout, etc.). - */ - if (ifunit >= 0) - ppp_notice("Connect: %s <--> %s", ifname, ppp_devnam); - else - ppp_notice("Starting negotiation on %s", ppp_devnam); - add_fd(fd_ppp); - - new_phase(pcb, PPP_PHASE_ESTABLISH); - - lcp_lowerup(pcb); - return; - - disconnect: - new_phase(pcb, PPP_PHASE_DISCONNECT); - if (the_channel->disconnect) - the_channel->disconnect(); - - fail: - new_phase(pcb, PPP_PHASE_DEAD); - if (the_channel->cleanup) - (*the_channel->cleanup)(); -} -#endif - -/* - * LCP has terminated the link; go to the Dead phase and take the - * physical layer down. - */ -void link_terminated(ppp_pcb *pcb) { - if (pcb->phase == PPP_PHASE_DEAD -#ifdef HAVE_MULTILINK - || pcb->phase == PPP_PHASE_MASTER -#endif /* HAVE_MULTILINK */ - ) - return; - new_phase(pcb, PPP_PHASE_DISCONNECT); - -#if 0 /* UNUSED */ - if (pap_logout_hook) { - pap_logout_hook(); - } - session_end(devnam); -#endif /* UNUSED */ - - if (!doing_multilink) { - ppp_notice("Connection terminated."); -#if PPP_STATS_SUPPORT - print_link_stats(); -#endif /* PPP_STATS_SUPPORT */ - } else - ppp_notice("Link terminated."); - - lcp_lowerdown(pcb); - - ppp_link_terminated(pcb); -#if 0 - /* - * Delete pid files before disestablishing ppp. Otherwise it - * can happen that another pppd gets the same unit and then - * we delete its pid file. - */ - if (!doing_multilink && !demand) - remove_pidfiles(); - - /* - * If we may want to bring the link up again, transfer - * the ppp unit back to the loopback. Set the - * real serial device back to its normal mode of operation. - */ - if (fd_ppp >= 0) { - remove_fd(fd_ppp); - clean_check(); - the_channel->disestablish_ppp(devfd); - if (doing_multilink) - mp_exit_bundle(); - fd_ppp = -1; - } - if (!hungup) - lcp_lowerdown(pcb); - if (!doing_multilink && !demand) - script_unsetenv("IFNAME"); - - /* - * Run disconnector script, if requested. - * XXX we may not be able to do this if the line has hung up! - */ - if (devfd >= 0 && the_channel->disconnect) { - the_channel->disconnect(); - devfd = -1; - } - if (the_channel->cleanup) - (*the_channel->cleanup)(); - - if (doing_multilink && multilink_master) { - if (!bundle_terminating) - new_phase(pcb, PPP_PHASE_MASTER); - else - mp_bundle_terminated(); - } else - new_phase(pcb, PPP_PHASE_DEAD); -#endif -} - -/* - * LCP has gone down; it will either die or try to re-establish. - */ -void link_down(ppp_pcb *pcb) { -#if PPP_NOTIFY - notify(link_down_notifier, 0); -#endif /* PPP_NOTIFY */ - - if (!doing_multilink) { - upper_layers_down(pcb); - if (pcb->phase != PPP_PHASE_DEAD -#ifdef HAVE_MULTILINK - && pcb->phase != PPP_PHASE_MASTER -#endif /* HAVE_MULTILINK */ - ) - new_phase(pcb, PPP_PHASE_ESTABLISH); - } - /* XXX if doing_multilink, should do something to stop - network-layer traffic on the link */ -} - -void upper_layers_down(ppp_pcb *pcb) { - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol != PPP_LCP && protp->lowerdown != NULL) - (*protp->lowerdown)(pcb); - if (protp->protocol < 0xC000 && protp->close != NULL) - (*protp->close)(pcb, "LCP down"); - } - pcb->num_np_open = 0; - pcb->num_np_up = 0; -} - -/* - * The link is established. - * Proceed to the Dead, Authenticate or Network phase as appropriate. - */ -void link_established(ppp_pcb *pcb) { -#if PPP_AUTH_SUPPORT - int auth; -#if PPP_SERVER -#if PAP_SUPPORT - lcp_options *wo = &pcb->lcp_wantoptions; -#endif /* PAP_SUPPORT */ - lcp_options *go = &pcb->lcp_gotoptions; -#endif /* PPP_SERVER */ - lcp_options *ho = &pcb->lcp_hisoptions; -#endif /* PPP_AUTH_SUPPORT */ - int i; - const struct protent *protp; - - /* - * Tell higher-level protocols that LCP is up. - */ - if (!doing_multilink) { - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol != PPP_LCP - && protp->lowerup != NULL) - (*protp->lowerup)(pcb); - } - -#if PPP_AUTH_SUPPORT -#if PPP_SERVER -#if PPP_ALLOWED_ADDRS - if (!auth_required && noauth_addrs != NULL) - set_allowed_addrs(unit, NULL, NULL); -#endif /* PPP_ALLOWED_ADDRS */ - - if (pcb->settings.auth_required && !(0 -#if PAP_SUPPORT - || go->neg_upap -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - || go->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap -#endif /* EAP_SUPPORT */ - )) { - -#if PPP_ALLOWED_ADDRS - /* - * We wanted the peer to authenticate itself, and it refused: - * if we have some address(es) it can use without auth, fine, - * otherwise treat it as though it authenticated with PAP using - * a username of "" and a password of "". If that's not OK, - * boot it out. - */ - if (noauth_addrs != NULL) { - set_allowed_addrs(unit, NULL, NULL); - } else -#endif /* PPP_ALLOWED_ADDRS */ - if (!pcb->settings.null_login -#if PAP_SUPPORT - || !wo->neg_upap -#endif /* PAP_SUPPORT */ - ) { - ppp_warn("peer refused to authenticate: terminating link"); -#if 0 /* UNUSED */ - status = EXIT_PEER_AUTH_FAILED; -#endif /* UNUSED */ - pcb->err_code = PPPERR_AUTHFAIL; - lcp_close(pcb, "peer refused to authenticate"); - return; - } - } -#endif /* PPP_SERVER */ - - new_phase(pcb, PPP_PHASE_AUTHENTICATE); - auth = 0; -#if PPP_SERVER -#if EAP_SUPPORT - if (go->neg_eap) { - eap_authpeer(pcb, PPP_OUR_NAME); - auth |= EAP_PEER; - } else -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - if (go->neg_chap) { - chap_auth_peer(pcb, PPP_OUR_NAME, CHAP_DIGEST(go->chap_mdtype)); - auth |= CHAP_PEER; - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if (go->neg_upap) { - upap_authpeer(pcb); - auth |= PAP_PEER; - } else -#endif /* PAP_SUPPORT */ - {} -#endif /* PPP_SERVER */ - -#if EAP_SUPPORT - if (ho->neg_eap) { - eap_authwithpeer(pcb, pcb->settings.user); - auth |= EAP_WITHPEER; - } else -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - if (ho->neg_chap) { - chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype)); - auth |= CHAP_WITHPEER; - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if (ho->neg_upap) { - upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd); - auth |= PAP_WITHPEER; - } else -#endif /* PAP_SUPPORT */ - {} - - pcb->auth_pending = auth; - pcb->auth_done = 0; - - if (!auth) -#endif /* PPP_AUTH_SUPPORT */ - network_phase(pcb); -} - -/* - * Proceed to the network phase. - */ -static void network_phase(ppp_pcb *pcb) { -#if CBCP_SUPPORT - ppp_pcb *pcb = &ppp_pcb_list[unit]; -#endif -#if 0 /* UNUSED */ - lcp_options *go = &lcp_gotoptions[unit]; -#endif /* UNUSED */ - -#if 0 /* UNUSED */ - /* Log calling number. */ - if (*remote_number) - ppp_notice("peer from calling number %q authorized", remote_number); -#endif /* UNUSED */ - -#if PPP_NOTIFY - /* - * If the peer had to authenticate, notify it now. - */ - if (0 -#if CHAP_SUPPORT - || go->neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - || go->neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap -#endif /* EAP_SUPPORT */ - ) { - notify(auth_up_notifier, 0); - } -#endif /* PPP_NOTIFY */ - -#if CBCP_SUPPORT - /* - * If we negotiated callback, do it now. - */ - if (go->neg_cbcp) { - new_phase(pcb, PPP_PHASE_CALLBACK); - (*cbcp_protent.open)(pcb); - return; - } -#endif - -#if PPP_OPTIONS - /* - * Process extra options from the secrets file - */ - if (extra_options) { - options_from_list(extra_options, 1); - free_wordlist(extra_options); - extra_options = 0; - } -#endif /* PPP_OPTIONS */ - start_networks(pcb); -} - -void start_networks(ppp_pcb *pcb) { -#if CCP_SUPPORT || ECP_SUPPORT - int i; - const struct protent *protp; -#endif /* CCP_SUPPORT || ECP_SUPPORT */ - - new_phase(pcb, PPP_PHASE_NETWORK); - -#ifdef HAVE_MULTILINK - if (multilink) { - if (mp_join_bundle()) { - if (multilink_join_hook) - (*multilink_join_hook)(); - if (updetach && !nodetach) - detach(); - return; - } - } -#endif /* HAVE_MULTILINK */ - -#ifdef PPP_FILTER - if (!demand) - set_filters(&pass_filter, &active_filter); -#endif -#if CCP_SUPPORT || ECP_SUPPORT - /* Start CCP and ECP */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if ( - (0 -#if ECP_SUPPORT - || protp->protocol == PPP_ECP -#endif /* ECP_SUPPORT */ -#if CCP_SUPPORT - || protp->protocol == PPP_CCP -#endif /* CCP_SUPPORT */ - ) - && protp->open != NULL) - (*protp->open)(pcb); -#endif /* CCP_SUPPORT || ECP_SUPPORT */ - - /* - * Bring up other network protocols iff encryption is not required. - */ - if (1 -#if ECP_SUPPORT - && !ecp_gotoptions[unit].required -#endif /* ECP_SUPPORT */ -#if MPPE_SUPPORT - && !pcb->ccp_gotoptions.mppe -#endif /* MPPE_SUPPORT */ - ) - continue_networks(pcb); -} - -void continue_networks(ppp_pcb *pcb) { - int i; - const struct protent *protp; - - /* - * Start the "real" network protocols. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol < 0xC000 -#if CCP_SUPPORT - && protp->protocol != PPP_CCP -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT - && protp->protocol != PPP_ECP -#endif /* ECP_SUPPORT */ - && protp->open != NULL) { - (*protp->open)(pcb); - ++pcb->num_np_open; - } - - if (pcb->num_np_open == 0) - /* nothing to do */ - lcp_close(pcb, "No network protocols running"); -} - -#if PPP_AUTH_SUPPORT -#if PPP_SERVER -/* - * auth_check_passwd - Check the user name and passwd against configuration. - * - * returns: - * 0: Authentication failed. - * 1: Authentication succeeded. - * In either case, msg points to an appropriate message and msglen to the message len. - */ -int auth_check_passwd(ppp_pcb *pcb, char *auser, int userlen, char *apasswd, int passwdlen, const char **msg, int *msglen) { - int secretuserlen; - int secretpasswdlen; - - if (pcb->settings.user && pcb->settings.passwd) { - secretuserlen = (int)strlen(pcb->settings.user); - secretpasswdlen = (int)strlen(pcb->settings.passwd); - if (secretuserlen == userlen - && secretpasswdlen == passwdlen - && !memcmp(auser, pcb->settings.user, userlen) - && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) { - *msg = "Login ok"; - *msglen = sizeof("Login ok")-1; - return 1; - } - } - - *msg = "Login incorrect"; - *msglen = sizeof("Login incorrect")-1; - return 0; -} - -/* - * The peer has failed to authenticate himself using `protocol'. - */ -void auth_peer_fail(ppp_pcb *pcb, int protocol) { - LWIP_UNUSED_ARG(protocol); - /* - * Authentication failure: take the link down - */ -#if 0 /* UNUSED */ - status = EXIT_PEER_AUTH_FAILED; -#endif /* UNUSED */ - pcb->err_code = PPPERR_AUTHFAIL; - lcp_close(pcb, "Authentication failed"); -} - -/* - * The peer has been successfully authenticated using `protocol'. - */ -void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) { - int bit; -#ifndef HAVE_MULTILINK - LWIP_UNUSED_ARG(name); - LWIP_UNUSED_ARG(namelen); -#endif /* HAVE_MULTILINK */ - - switch (protocol) { -#if CHAP_SUPPORT - case PPP_CHAP: - bit = CHAP_PEER; - switch (prot_flavor) { - case CHAP_MD5: - bit |= CHAP_MD5_PEER; - break; -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - bit |= CHAP_MS_PEER; - break; - case CHAP_MICROSOFT_V2: - bit |= CHAP_MS2_PEER; - break; -#endif /* MSCHAP_SUPPORT */ - default: - break; - } - break; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - case PPP_PAP: - bit = PAP_PEER; - break; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - case PPP_EAP: - bit = EAP_PEER; - break; -#endif /* EAP_SUPPORT */ - default: - ppp_warn("auth_peer_success: unknown protocol %x", protocol); - return; - } - -#ifdef HAVE_MULTILINK - /* - * Save the authenticated name of the peer for later. - */ - if (namelen > (int)sizeof(pcb->peer_authname) - 1) - namelen = (int)sizeof(pcb->peer_authname) - 1; - MEMCPY(pcb->peer_authname, name, namelen); - pcb->peer_authname[namelen] = 0; -#endif /* HAVE_MULTILINK */ -#if 0 /* UNUSED */ - script_setenv("PEERNAME", , 0); -#endif /* UNUSED */ - - /* Save the authentication method for later. */ - pcb->auth_done |= bit; - - /* - * If there is no more authentication still to be done, - * proceed to the network (or callback) phase. - */ - if ((pcb->auth_pending &= ~bit) == 0) - network_phase(pcb); -} -#endif /* PPP_SERVER */ - -/* - * We have failed to authenticate ourselves to the peer using `protocol'. - */ -void auth_withpeer_fail(ppp_pcb *pcb, int protocol) { - LWIP_UNUSED_ARG(protocol); - /* - * We've failed to authenticate ourselves to our peer. - * - * Some servers keep sending CHAP challenges, but there - * is no point in persisting without any way to get updated - * authentication secrets. - * - * He'll probably take the link down, and there's not much - * we can do except wait for that. - */ - pcb->err_code = PPPERR_AUTHFAIL; - lcp_close(pcb, "Failed to authenticate ourselves to peer"); -} - -/* - * We have successfully authenticated ourselves with the peer using `protocol'. - */ -void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) { - int bit; - const char *prot = ""; - - switch (protocol) { -#if CHAP_SUPPORT - case PPP_CHAP: - bit = CHAP_WITHPEER; - prot = "CHAP"; - switch (prot_flavor) { - case CHAP_MD5: - bit |= CHAP_MD5_WITHPEER; - break; -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - bit |= CHAP_MS_WITHPEER; - break; - case CHAP_MICROSOFT_V2: - bit |= CHAP_MS2_WITHPEER; - break; -#endif /* MSCHAP_SUPPORT */ - default: - break; - } - break; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - case PPP_PAP: - bit = PAP_WITHPEER; - prot = "PAP"; - break; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - case PPP_EAP: - bit = EAP_WITHPEER; - prot = "EAP"; - break; -#endif /* EAP_SUPPORT */ - default: - ppp_warn("auth_withpeer_success: unknown protocol %x", protocol); - bit = 0; - /* no break */ - } - - ppp_notice("%s authentication succeeded", prot); - - /* Save the authentication method for later. */ - pcb->auth_done |= bit; - - /* - * If there is no more authentication still being done, - * proceed to the network (or callback) phase. - */ - if ((pcb->auth_pending &= ~bit) == 0) - network_phase(pcb); -} -#endif /* PPP_AUTH_SUPPORT */ - - -/* - * np_up - a network protocol has come up. - */ -void np_up(ppp_pcb *pcb, int proto) { -#if PPP_IDLETIMELIMIT - int tlim; -#endif /* PPP_IDLETIMELIMIT */ - LWIP_UNUSED_ARG(proto); - - if (pcb->num_np_up == 0) { - /* - * At this point we consider that the link has come up successfully. - */ - new_phase(pcb, PPP_PHASE_RUNNING); - -#if PPP_IDLETIMELIMIT -#if 0 /* UNUSED */ - if (idle_time_hook != 0) - tlim = (*idle_time_hook)(NULL); - else -#endif /* UNUSED */ - tlim = pcb->settings.idle_time_limit; - if (tlim > 0) - TIMEOUT(check_idle, (void*)pcb, tlim); -#endif /* PPP_IDLETIMELIMIT */ - -#if PPP_MAXCONNECT - /* - * Set a timeout to close the connection once the maximum - * connect time has expired. - */ - if (pcb->settings.maxconnect > 0) - TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect); -#endif /* PPP_MAXCONNECT */ - -#ifdef MAXOCTETS - if (maxoctets > 0) - TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); -#endif - -#if 0 /* Unused */ - /* - * Detach now, if the updetach option was given. - */ - if (updetach && !nodetach) - detach(); -#endif /* Unused */ - } - ++pcb->num_np_up; -} - -/* - * np_down - a network protocol has gone down. - */ -void np_down(ppp_pcb *pcb, int proto) { - LWIP_UNUSED_ARG(proto); - if (--pcb->num_np_up == 0) { -#if PPP_IDLETIMELIMIT - UNTIMEOUT(check_idle, (void*)pcb); -#endif /* PPP_IDLETIMELIMIT */ -#if PPP_MAXCONNECT - UNTIMEOUT(connect_time_expired, NULL); -#endif /* PPP_MAXCONNECT */ -#ifdef MAXOCTETS - UNTIMEOUT(check_maxoctets, NULL); -#endif - new_phase(pcb, PPP_PHASE_NETWORK); - } -} - -/* - * np_finished - a network protocol has finished using the link. - */ -void np_finished(ppp_pcb *pcb, int proto) { - LWIP_UNUSED_ARG(proto); - if (--pcb->num_np_open <= 0) { - /* no further use for the link: shut up shop. */ - lcp_close(pcb, "No network protocols running"); - } -} - -#ifdef MAXOCTETS -static void -check_maxoctets(arg) - void *arg; -{ -#if PPP_STATS_SUPPORT - unsigned int used; - - update_link_stats(ifunit); - link_stats_valid=0; - - switch(maxoctets_dir) { - case PPP_OCTETS_DIRECTION_IN: - used = link_stats.bytes_in; - break; - case PPP_OCTETS_DIRECTION_OUT: - used = link_stats.bytes_out; - break; - case PPP_OCTETS_DIRECTION_MAXOVERAL: - case PPP_OCTETS_DIRECTION_MAXSESSION: - used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out; - break; - default: - used = link_stats.bytes_in+link_stats.bytes_out; - break; - } - if (used > maxoctets) { - ppp_notice("Traffic limit reached. Limit: %u Used: %u", maxoctets, used); - status = EXIT_TRAFFIC_LIMIT; - lcp_close(pcb, "Traffic limit"); -#if 0 /* UNUSED */ - need_holdoff = 0; -#endif /* UNUSED */ - } else { - TIMEOUT(check_maxoctets, NULL, maxoctets_timeout); - } -#endif /* PPP_STATS_SUPPORT */ -} -#endif /* MAXOCTETS */ - -#if PPP_IDLETIMELIMIT -/* - * check_idle - check whether the link has been idle for long - * enough that we can shut it down. - */ -static void check_idle(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - struct ppp_idle idle; - time_t itime; - int tlim; - - if (!get_idle_time(pcb, &idle)) - return; -#if 0 /* UNUSED */ - if (idle_time_hook != 0) { - tlim = idle_time_hook(&idle); - } else { -#endif /* UNUSED */ - itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); - tlim = pcb->settings.idle_time_limit - itime; -#if 0 /* UNUSED */ - } -#endif /* UNUSED */ - if (tlim <= 0) { - /* link is idle: shut it down. */ - ppp_notice("Terminating connection due to lack of activity."); - pcb->err_code = PPPERR_IDLETIMEOUT; - lcp_close(pcb, "Link inactive"); -#if 0 /* UNUSED */ - need_holdoff = 0; -#endif /* UNUSED */ - } else { - TIMEOUT(check_idle, (void*)pcb, tlim); - } -} -#endif /* PPP_IDLETIMELIMIT */ - -#if PPP_MAXCONNECT -/* - * connect_time_expired - log a message and close the connection. - */ -static void connect_time_expired(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - ppp_info("Connect time expired"); - pcb->err_code = PPPERR_CONNECTTIME; - lcp_close(pcb, "Connect time expired"); /* Close connection */ -} -#endif /* PPP_MAXCONNECT */ - -#if PPP_OPTIONS -/* - * auth_check_options - called to check authentication options. - */ -void -auth_check_options() -{ - lcp_options *wo = &lcp_wantoptions[0]; - int can_auth; - int lacks_ip; - - /* Default our_name to hostname, and user to our_name */ - if (our_name[0] == 0 || usehostname) - strlcpy(our_name, hostname, sizeof(our_name)); - /* If a blank username was explicitly given as an option, trust - the user and don't use our_name */ - if (ppp_settings.user[0] == 0 && !explicit_user) - strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user)); - - /* - * If we have a default route, require the peer to authenticate - * unless the noauth option was given or the real user is root. - */ - if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) { - auth_required = 1; - default_auth = 1; - } - -#if CHAP_SUPPORT - /* If we selected any CHAP flavors, we should probably negotiate it. :-) */ - if (wo->chap_mdtype) - wo->neg_chap = 1; -#endif /* CHAP_SUPPORT */ - - /* If authentication is required, ask peer for CHAP, PAP, or EAP. */ - if (auth_required) { - allow_any_ip = 0; - if (1 -#if CHAP_SUPPORT - && !wo->neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - && !wo->neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - && !wo->neg_eap -#endif /* EAP_SUPPORT */ - ) { -#if CHAP_SUPPORT - wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE; - wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - wo->neg_upap = 1; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - wo->neg_eap = 1; -#endif /* EAP_SUPPORT */ - } - } else { -#if CHAP_SUPPORT - wo->neg_chap = 0; - wo->chap_mdtype = MDTYPE_NONE; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - wo->neg_upap = 0; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - wo->neg_eap = 0; -#endif /* EAP_SUPPORT */ - } - - /* - * Check whether we have appropriate secrets to use - * to authenticate the peer. Note that EAP can authenticate by way - * of a CHAP-like exchanges as well as SRP. - */ - lacks_ip = 0; -#if PAP_SUPPORT - can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip)); -#else - can_auth = 0; -#endif /* PAP_SUPPORT */ - if (!can_auth && (0 -#if CHAP_SUPPORT - || wo->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || wo->neg_eap -#endif /* EAP_SUPPORT */ - )) { -#if CHAP_SUPPORT - can_auth = have_chap_secret((explicit_remote? remote_name: NULL), - our_name, 1, &lacks_ip); -#else - can_auth = 0; -#endif - } - if (!can_auth -#if EAP_SUPPORT - && wo->neg_eap -#endif /* EAP_SUPPORT */ - ) { - can_auth = have_srp_secret((explicit_remote? remote_name: NULL), - our_name, 1, &lacks_ip); - } - - if (auth_required && !can_auth && noauth_addrs == NULL) { - if (default_auth) { - option_error( -"By default the remote system is required to authenticate itself"); - option_error( -"(because this system has a default route to the internet)"); - } else if (explicit_remote) - option_error( -"The remote system (%s) is required to authenticate itself", - remote_name); - else - option_error( -"The remote system is required to authenticate itself"); - option_error( -"but I couldn't find any suitable secret (password) for it to use to do so."); - if (lacks_ip) - option_error( -"(None of the available passwords would let it use an IP address.)"); - - exit(1); - } - - /* - * Early check for remote number authorization. - */ - if (!auth_number()) { - ppp_warn("calling number %q is not authorized", remote_number); - exit(EXIT_CNID_AUTH_FAILED); - } -} -#endif /* PPP_OPTIONS */ - -#if 0 /* UNUSED */ -/* - * auth_reset - called when LCP is starting negotiations to recheck - * authentication options, i.e. whether we have appropriate secrets - * to use for authenticating ourselves and/or the peer. - */ -void -auth_reset(unit) - int unit; -{ - lcp_options *go = &lcp_gotoptions[unit]; - lcp_options *ao = &lcp_allowoptions[unit]; - int hadchap; - - hadchap = -1; - ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL)); - ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2) - && (passwd[0] != 0 || - (hadchap = have_chap_secret(user, (explicit_remote? remote_name: - NULL), 0, NULL))); - ao->neg_eap = !refuse_eap && ( - passwd[0] != 0 || - (hadchap == 1 || (hadchap == -1 && have_chap_secret(user, - (explicit_remote? remote_name: NULL), 0, NULL))) || - have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL)); - - hadchap = -1; - if (go->neg_upap && !uselogin && !have_pap_secret(NULL)) - go->neg_upap = 0; - if (go->neg_chap) { - if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL), - our_name, 1, NULL))) - go->neg_chap = 0; - } - if (go->neg_eap && - (hadchap == 0 || (hadchap == -1 && - !have_chap_secret((explicit_remote? remote_name: NULL), our_name, - 1, NULL))) && - !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1, - NULL)) - go->neg_eap = 0; -} - -/* - * check_passwd - Check the user name and passwd against the PAP secrets - * file. If requested, also check against the system password database, - * and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Authentication failed. - * UPAP_AUTHACK: Authentication succeeded. - * In either case, msg points to an appropriate message. - */ -int -check_passwd(unit, auser, userlen, apasswd, passwdlen, msg) - int unit; - char *auser; - int userlen; - char *apasswd; - int passwdlen; - char **msg; -{ - return UPAP_AUTHNAK; - int ret; - char *filename; - FILE *f; - struct wordlist *addrs = NULL, *opts = NULL; - char passwd[256], user[256]; - char secret[MAXWORDLEN]; - static int attempts = 0; - - /* - * Make copies of apasswd and auser, then null-terminate them. - * If there are unprintable characters in the password, make - * them visible. - */ - slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd); - slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser); - *msg = ""; - - /* - * Check if a plugin wants to handle this. - */ - if (pap_auth_hook) { - ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts); - if (ret >= 0) { - /* note: set_allowed_addrs() saves opts (but not addrs): - don't free it! */ - if (ret) - set_allowed_addrs(unit, addrs, opts); - else if (opts != 0) - free_wordlist(opts); - if (addrs != 0) - free_wordlist(addrs); - BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); - return ret? UPAP_AUTHACK: UPAP_AUTHNAK; - } - } - - /* - * Open the file of pap secrets and scan for a suitable secret - * for authenticating this user. - */ - filename = _PATH_UPAPFILE; - addrs = opts = NULL; - ret = UPAP_AUTHNAK; - f = fopen(filename, "r"); - if (f == NULL) { - ppp_error("Can't open PAP password file %s: %m", filename); - - } else { - check_access(f, filename); - if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) { - ppp_warn("no PAP secret found for %s", user); - } else { - /* - * If the secret is "@login", it means to check - * the password against the login database. - */ - int login_secret = strcmp(secret, "@login") == 0; - ret = UPAP_AUTHACK; - if (uselogin || login_secret) { - /* login option or secret is @login */ - if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) { - ret = UPAP_AUTHNAK; - } - } else if (session_mgmt) { - if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) { - ppp_warn("Peer %q failed PAP Session verification", user); - ret = UPAP_AUTHNAK; - } - } - if (secret[0] != 0 && !login_secret) { - /* password given in pap-secrets - must match */ - if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0) - && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0) - ret = UPAP_AUTHNAK; - } - } - fclose(f); - } - - if (ret == UPAP_AUTHNAK) { - if (**msg == 0) - *msg = "Login incorrect"; - /* - * XXX can we ever get here more than once?? - * Frustrate passwd stealer programs. - * Allow 10 tries, but start backing off after 3 (stolen from login). - * On 10'th, drop the connection. - */ - if (attempts++ >= 10) { - ppp_warn("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user); - lcp_close(pcb, "login failed"); - } - if (attempts > 3) - sleep((u_int) (attempts - 3) * 5); - if (opts != NULL) - free_wordlist(opts); - - } else { - attempts = 0; /* Reset count */ - if (**msg == 0) - *msg = "Login ok"; - set_allowed_addrs(unit, addrs, opts); - } - - if (addrs != NULL) - free_wordlist(addrs); - BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd)); - BZERO(secret, sizeof(secret)); - - return ret; -} - -/* - * null_login - Check if a username of "" and a password of "" are - * acceptable, and iff so, set the list of acceptable IP addresses - * and return 1. - */ -static int -null_login(unit) - int unit; -{ - char *filename; - FILE *f; - int i, ret; - struct wordlist *addrs, *opts; - char secret[MAXWORDLEN]; - - /* - * Check if a plugin wants to handle this. - */ - ret = -1; - if (null_auth_hook) - ret = (*null_auth_hook)(&addrs, &opts); - - /* - * Open the file of pap secrets and scan for a suitable secret. - */ - if (ret <= 0) { - filename = _PATH_UPAPFILE; - addrs = NULL; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - check_access(f, filename); - - i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0); - ret = i >= 0 && secret[0] == 0; - BZERO(secret, sizeof(secret)); - fclose(f); - } - - if (ret) - set_allowed_addrs(unit, addrs, opts); - else if (opts != 0) - free_wordlist(opts); - if (addrs != 0) - free_wordlist(addrs); - - return ret; -} - -/* - * get_pap_passwd - get a password for authenticating ourselves with - * our peer using PAP. Returns 1 on success, 0 if no suitable password - * could be found. - * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null). - */ -static int -get_pap_passwd(passwd) - char *passwd; -{ - char *filename; - FILE *f; - int ret; - char secret[MAXWORDLEN]; - - /* - * Check whether a plugin wants to supply this. - */ - if (pap_passwd_hook) { - ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd); - if (ret >= 0) - return ret; - } - - filename = _PATH_UPAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - check_access(f, filename); - ret = scan_authfile(f, user, - (remote_name[0]? remote_name: NULL), - secret, NULL, NULL, filename, 0); - fclose(f); - if (ret < 0) - return 0; - if (passwd != NULL) - strlcpy(passwd, secret, MAXSECRETLEN); - BZERO(secret, sizeof(secret)); - return 1; -} - -/* - * have_pap_secret - check whether we have a PAP file with any - * secrets that we could possibly use for authenticating the peer. - */ -static int -have_pap_secret(lacks_ipp) - int *lacks_ipp; -{ - FILE *f; - int ret; - char *filename; - struct wordlist *addrs; - - /* let the plugin decide, if there is one */ - if (pap_check_hook) { - ret = (*pap_check_hook)(); - if (ret >= 0) - return ret; - } - - filename = _PATH_UPAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name, - NULL, &addrs, NULL, filename, 0); - fclose(f); - if (ret >= 0 && !some_ip_ok(addrs)) { - if (lacks_ipp != 0) - *lacks_ipp = 1; - ret = -1; - } - if (addrs != 0) - free_wordlist(addrs); - - return ret >= 0; -} - -/* - * have_chap_secret - check whether we have a CHAP file with a - * secret that we could possibly use for authenticating `client' - * on `server'. Either can be the null string, meaning we don't - * know the identity yet. - */ -static int -have_chap_secret(client, server, need_ip, lacks_ipp) - char *client; - char *server; - int need_ip; - int *lacks_ipp; -{ - FILE *f; - int ret; - char *filename; - struct wordlist *addrs; - - if (chap_check_hook) { - ret = (*chap_check_hook)(); - if (ret >= 0) { - return ret; - } - } - - filename = _PATH_CHAPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - if (client != NULL && client[0] == 0) - client = NULL; - else if (server != NULL && server[0] == 0) - server = NULL; - - ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); - fclose(f); - if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { - if (lacks_ipp != 0) - *lacks_ipp = 1; - ret = -1; - } - if (addrs != 0) - free_wordlist(addrs); - - return ret >= 0; -} - -/* - * have_srp_secret - check whether we have a SRP file with a - * secret that we could possibly use for authenticating `client' - * on `server'. Either can be the null string, meaning we don't - * know the identity yet. - */ -static int -have_srp_secret(client, server, need_ip, lacks_ipp) - char *client; - char *server; - int need_ip; - int *lacks_ipp; -{ - FILE *f; - int ret; - char *filename; - struct wordlist *addrs; - - filename = _PATH_SRPFILE; - f = fopen(filename, "r"); - if (f == NULL) - return 0; - - if (client != NULL && client[0] == 0) - client = NULL; - else if (server != NULL && server[0] == 0) - server = NULL; - - ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0); - fclose(f); - if (ret >= 0 && need_ip && !some_ip_ok(addrs)) { - if (lacks_ipp != 0) - *lacks_ipp = 1; - ret = -1; - } - if (addrs != 0) - free_wordlist(addrs); - - return ret >= 0; -} -#endif /* UNUSED */ - -#if PPP_AUTH_SUPPORT -/* - * get_secret - open the CHAP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) { - int len; - LWIP_UNUSED_ARG(server); - LWIP_UNUSED_ARG(am_server); - - if (!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) { - return 0; - } - - len = (int)strlen(pcb->settings.passwd); - if (len > MAXSECRETLEN) { - ppp_error("Secret for %s on %s is too long", client, server); - len = MAXSECRETLEN; - } - - MEMCPY(secret, pcb->settings.passwd, len); - *secret_len = len; - return 1; - -#if 0 /* UNUSED */ - FILE *f; - int ret, len; - char *filename; - struct wordlist *addrs, *opts; - char secbuf[MAXWORDLEN]; - struct wordlist *addrs; - addrs = NULL; - - if (!am_server && ppp_settings.passwd[0] != 0) { - strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf)); - } else if (!am_server && chap_passwd_hook) { - if ( (*chap_passwd_hook)(client, secbuf) < 0) { - ppp_error("Unable to obtain CHAP password for %s on %s from plugin", - client, server); - return 0; - } - } else { - filename = _PATH_CHAPFILE; - addrs = NULL; - secbuf[0] = 0; - - f = fopen(filename, "r"); - if (f == NULL) { - ppp_error("Can't open chap secret file %s: %m", filename); - return 0; - } - check_access(f, filename); - - ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0); - fclose(f); - if (ret < 0) - return 0; - - if (am_server) - set_allowed_addrs(unit, addrs, opts); - else if (opts != 0) - free_wordlist(opts); - if (addrs != 0) - free_wordlist(addrs); - } - - len = strlen(secbuf); - if (len > MAXSECRETLEN) { - ppp_error("Secret for %s on %s is too long", client, server); - len = MAXSECRETLEN; - } - MEMCPY(secret, secbuf, len); - BZERO(secbuf, sizeof(secbuf)); - *secret_len = len; - - return 1; -#endif /* UNUSED */ -} -#endif /* PPP_AUTH_SUPPORT */ - - -#if 0 /* UNUSED */ -/* - * get_srp_secret - open the SRP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int -get_srp_secret(unit, client, server, secret, am_server) - int unit; - char *client; - char *server; - char *secret; - int am_server; -{ - FILE *fp; - int ret; - char *filename; - struct wordlist *addrs, *opts; - - if (!am_server && ppp_settings.passwd[0] != '\0') { - strlcpy(secret, ppp_settings.passwd, MAXWORDLEN); - } else { - filename = _PATH_SRPFILE; - addrs = NULL; - - fp = fopen(filename, "r"); - if (fp == NULL) { - ppp_error("Can't open srp secret file %s: %m", filename); - return 0; - } - check_access(fp, filename); - - secret[0] = '\0'; - ret = scan_authfile(fp, client, server, secret, &addrs, &opts, - filename, am_server); - fclose(fp); - if (ret < 0) - return 0; - - if (am_server) - set_allowed_addrs(unit, addrs, opts); - else if (opts != NULL) - free_wordlist(opts); - if (addrs != NULL) - free_wordlist(addrs); - } - - return 1; -} - -/* - * set_allowed_addrs() - set the list of allowed addresses. - * Also looks for `--' indicating options to apply for this peer - * and leaves the following words in extra_options. - */ -static void -set_allowed_addrs(unit, addrs, opts) - int unit; - struct wordlist *addrs; - struct wordlist *opts; -{ - int n; - struct wordlist *ap, **plink; - struct permitted_ip *ip; - char *ptr_word, *ptr_mask; - struct hostent *hp; - struct netent *np; - u32_t a, mask, ah, offset; - struct ipcp_options *wo = &ipcp_wantoptions[unit]; - u32_t suggested_ip = 0; - - if (addresses[unit] != NULL) - free(addresses[unit]); - addresses[unit] = NULL; - if (extra_options != NULL) - free_wordlist(extra_options); - extra_options = opts; - - /* - * Count the number of IP addresses given. - */ - n = wordlist_count(addrs) + wordlist_count(noauth_addrs); - if (n == 0) - return; - ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip)); - if (ip == 0) - return; - - /* temporarily append the noauth_addrs list to addrs */ - for (plink = &addrs; *plink != NULL; plink = &(*plink)->next) - ; - *plink = noauth_addrs; - - n = 0; - for (ap = addrs; ap != NULL; ap = ap->next) { - /* "-" means no addresses authorized, "*" means any address allowed */ - ptr_word = ap->word; - if (strcmp(ptr_word, "-") == 0) - break; - if (strcmp(ptr_word, "*") == 0) { - ip[n].permit = 1; - ip[n].base = ip[n].mask = 0; - ++n; - break; - } - - ip[n].permit = 1; - if (*ptr_word == '!') { - ip[n].permit = 0; - ++ptr_word; - } - - mask = ~ (u32_t) 0; - offset = 0; - ptr_mask = strchr (ptr_word, '/'); - if (ptr_mask != NULL) { - int bit_count; - char *endp; - - bit_count = (int) strtol (ptr_mask+1, &endp, 10); - if (bit_count <= 0 || bit_count > 32) { - ppp_warn("invalid address length %v in auth. address list", - ptr_mask+1); - continue; - } - bit_count = 32 - bit_count; /* # bits in host part */ - if (*endp == '+') { - offset = ifunit + 1; - ++endp; - } - if (*endp != 0) { - ppp_warn("invalid address length syntax: %v", ptr_mask+1); - continue; - } - *ptr_mask = '\0'; - mask <<= bit_count; - } - - hp = gethostbyname(ptr_word); - if (hp != NULL && hp->h_addrtype == AF_INET) { - a = *(u32_t *)hp->h_addr; - } else { - np = getnetbyname (ptr_word); - if (np != NULL && np->n_addrtype == AF_INET) { - a = lwip_htonl ((u32_t)np->n_net); - if (ptr_mask == NULL) { - /* calculate appropriate mask for net */ - ah = lwip_ntohl(a); - if (IN_CLASSA(ah)) - mask = IN_CLASSA_NET; - else if (IN_CLASSB(ah)) - mask = IN_CLASSB_NET; - else if (IN_CLASSC(ah)) - mask = IN_CLASSC_NET; - } - } else { - a = inet_addr (ptr_word); - } - } - - if (ptr_mask != NULL) - *ptr_mask = '/'; - - if (a == (u32_t)-1L) { - ppp_warn("unknown host %s in auth. address list", ap->word); - continue; - } - if (offset != 0) { - if (offset >= ~mask) { - ppp_warn("interface unit %d too large for subnet %v", - ifunit, ptr_word); - continue; - } - a = lwip_htonl((lwip_ntohl(a) & mask) + offset); - mask = ~(u32_t)0; - } - ip[n].mask = lwip_htonl(mask); - ip[n].base = a & ip[n].mask; - ++n; - if (~mask == 0 && suggested_ip == 0) - suggested_ip = a; - } - *plink = NULL; - - ip[n].permit = 0; /* make the last entry forbid all addresses */ - ip[n].base = 0; /* to terminate the list */ - ip[n].mask = 0; - - addresses[unit] = ip; - - /* - * If the address given for the peer isn't authorized, or if - * the user hasn't given one, AND there is an authorized address - * which is a single host, then use that if we find one. - */ - if (suggested_ip != 0 - && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) { - wo->hisaddr = suggested_ip; - /* - * Do we insist on this address? No, if there are other - * addresses authorized than the suggested one. - */ - if (n > 1) - wo->accept_remote = 1; - } -} - -/* - * auth_ip_addr - check whether the peer is authorized to use - * a given IP address. Returns 1 if authorized, 0 otherwise. - */ -int -auth_ip_addr(unit, addr) - int unit; - u32_t addr; -{ - int ok; - - /* don't allow loopback or multicast address */ - if (bad_ip_adrs(addr)) - return 0; - - if (allowed_address_hook) { - ok = allowed_address_hook(addr); - if (ok >= 0) return ok; - } - - if (addresses[unit] != NULL) { - ok = ip_addr_check(addr, addresses[unit]); - if (ok >= 0) - return ok; - } - - if (auth_required) - return 0; /* no addresses authorized */ - return allow_any_ip || privileged || !have_route_to(addr); -} - -static int -ip_addr_check(addr, addrs) - u32_t addr; - struct permitted_ip *addrs; -{ - for (; ; ++addrs) - if ((addr & addrs->mask) == addrs->base) - return addrs->permit; -} - -/* - * bad_ip_adrs - return 1 if the IP address is one we don't want - * to use, such as an address in the loopback net or a multicast address. - * addr is in network byte order. - */ -int -bad_ip_adrs(addr) - u32_t addr; -{ - addr = lwip_ntohl(addr); - return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET - || IN_MULTICAST(addr) || IN_BADCLASS(addr); -} - -/* - * some_ip_ok - check a wordlist to see if it authorizes any - * IP address(es). - */ -static int -some_ip_ok(addrs) - struct wordlist *addrs; -{ - for (; addrs != 0; addrs = addrs->next) { - if (addrs->word[0] == '-') - break; - if (addrs->word[0] != '!') - return 1; /* some IP address is allowed */ - } - return 0; -} - -/* - * auth_number - check whether the remote number is allowed to connect. - * Returns 1 if authorized, 0 otherwise. - */ -int -auth_number() -{ - struct wordlist *wp = permitted_numbers; - int l; - - /* Allow all if no authorization list. */ - if (!wp) - return 1; - - /* Allow if we have a match in the authorization list. */ - while (wp) { - /* trailing '*' wildcard */ - l = strlen(wp->word); - if ((wp->word)[l - 1] == '*') - l--; - if (!strncasecmp(wp->word, remote_number, l)) - return 1; - wp = wp->next; - } - - return 0; -} - -/* - * check_access - complain if a secret file has too-liberal permissions. - */ -static void -check_access(f, filename) - FILE *f; - char *filename; -{ - struct stat sbuf; - - if (fstat(fileno(f), &sbuf) < 0) { - ppp_warn("cannot stat secret file %s: %m", filename); - } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { - ppp_warn("Warning - secret file %s has world and/or group access", - filename); - } -} - -/* - * scan_authfile - Scan an authorization file for a secret suitable - * for authenticating `client' on `server'. The return value is -1 - * if no secret is found, otherwise >= 0. The return value has - * NONWILD_CLIENT set if the secret didn't have "*" for the client, and - * NONWILD_SERVER set if the secret didn't have "*" for the server. - * Any following words on the line up to a "--" (i.e. address authorization - * info) are placed in a wordlist and returned in *addrs. Any - * following words (extra options) are placed in a wordlist and - * returned in *opts. - * We assume secret is NULL or points to MAXWORDLEN bytes of space. - * Flags are non-zero if we need two colons in the secret in order to - * match. - */ -static int -scan_authfile(f, client, server, secret, addrs, opts, filename, flags) - FILE *f; - char *client; - char *server; - char *secret; - struct wordlist **addrs; - struct wordlist **opts; - char *filename; - int flags; -{ - int newline, xxx; - int got_flag, best_flag; - FILE *sf; - struct wordlist *ap, *addr_list, *alist, **app; - char word[MAXWORDLEN]; - char atfile[MAXWORDLEN]; - char lsecret[MAXWORDLEN]; - char *cp; - - if (addrs != NULL) - *addrs = NULL; - if (opts != NULL) - *opts = NULL; - addr_list = NULL; - if (!getword(f, word, &newline, filename)) - return -1; /* file is empty??? */ - newline = 1; - best_flag = -1; - for (;;) { - /* - * Skip until we find a word at the start of a line. - */ - while (!newline && getword(f, word, &newline, filename)) - ; - if (!newline) - break; /* got to end of file */ - - /* - * Got a client - check if it's a match or a wildcard. - */ - got_flag = 0; - if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) { - newline = 0; - continue; - } - if (!ISWILD(word)) - got_flag = NONWILD_CLIENT; - - /* - * Now get a server and check if it matches. - */ - if (!getword(f, word, &newline, filename)) - break; - if (newline) - continue; - if (!ISWILD(word)) { - if (server != NULL && strcmp(word, server) != 0) - continue; - got_flag |= NONWILD_SERVER; - } - - /* - * Got some sort of a match - see if it's better than what - * we have already. - */ - if (got_flag <= best_flag) - continue; - - /* - * Get the secret. - */ - if (!getword(f, word, &newline, filename)) - break; - if (newline) - continue; - - /* - * SRP-SHA1 authenticator should never be reading secrets from - * a file. (Authenticatee may, though.) - */ - if (flags && ((cp = strchr(word, ':')) == NULL || - strchr(cp + 1, ':') == NULL)) - continue; - - if (secret != NULL) { - /* - * Special syntax: @/pathname means read secret from file. - */ - if (word[0] == '@' && word[1] == '/') { - strlcpy(atfile, word+1, sizeof(atfile)); - if ((sf = fopen(atfile, "r")) == NULL) { - ppp_warn("can't open indirect secret file %s", atfile); - continue; - } - check_access(sf, atfile); - if (!getword(sf, word, &xxx, atfile)) { - ppp_warn("no secret in indirect secret file %s", atfile); - fclose(sf); - continue; - } - fclose(sf); - } - strlcpy(lsecret, word, sizeof(lsecret)); - } - - /* - * Now read address authorization info and make a wordlist. - */ - app = &alist; - for (;;) { - if (!getword(f, word, &newline, filename) || newline) - break; - ap = (struct wordlist *) - malloc(sizeof(struct wordlist) + strlen(word) + 1); - if (ap == NULL) - novm("authorized addresses"); - ap->word = (char *) (ap + 1); - strcpy(ap->word, word); - *app = ap; - app = &ap->next; - } - *app = NULL; - - /* - * This is the best so far; remember it. - */ - best_flag = got_flag; - if (addr_list) - free_wordlist(addr_list); - addr_list = alist; - if (secret != NULL) - strlcpy(secret, lsecret, MAXWORDLEN); - - if (!newline) - break; - } - - /* scan for a -- word indicating the start of options */ - for (app = &addr_list; (ap = *app) != NULL; app = &ap->next) - if (strcmp(ap->word, "--") == 0) - break; - /* ap = start of options */ - if (ap != NULL) { - ap = ap->next; /* first option */ - free(*app); /* free the "--" word */ - *app = NULL; /* terminate addr list */ - } - if (opts != NULL) - *opts = ap; - else if (ap != NULL) - free_wordlist(ap); - if (addrs != NULL) - *addrs = addr_list; - else if (addr_list != NULL) - free_wordlist(addr_list); - - return best_flag; -} - -/* - * wordlist_count - return the number of items in a wordlist - */ -static int -wordlist_count(wp) - struct wordlist *wp; -{ - int n; - - for (n = 0; wp != NULL; wp = wp->next) - ++n; - return n; -} - -/* - * free_wordlist - release memory allocated for a wordlist. - */ -static void -free_wordlist(wp) - struct wordlist *wp; -{ - struct wordlist *next; - - while (wp != NULL) { - next = wp->next; - free(wp); - wp = next; - } -} -#endif /* UNUSED */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/ccp.c b/components/net/lwip-2.0.2/src/netif/ppp/ccp.c deleted file mode 100644 index f8519ebece..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/ccp.c +++ /dev/null @@ -1,1740 +0,0 @@ -/* - * ccp.c - PPP Compression Control Protocol. - * - * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CCP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include -#include - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ccp.h" - -#if MPPE_SUPPORT -#include "netif/ppp/lcp.h" /* lcp_close(), lcp_fsm */ -#include "netif/ppp/mppe.h" /* mppe_init() */ -#endif /* MPPE_SUPPORT */ - -/* - * Unfortunately there is a bug in zlib which means that using a - * size of 8 (window size = 256) for Deflate compression will cause - * buffer overruns and kernel crashes in the deflate module. - * Until this is fixed we only accept sizes in the range 9 .. 15. - * Thanks to James Carlson for pointing this out. - */ -#define DEFLATE_MIN_WORKS 9 - -/* - * Command-line options. - */ -#if PPP_OPTIONS -static int setbsdcomp (char **); -static int setdeflate (char **); -static char bsd_value[8]; -static char deflate_value[8]; - -/* - * Option variables. - */ -#if MPPE_SUPPORT -bool refuse_mppe_stateful = 1; /* Allow stateful mode? */ -#endif /* MPPE_SUPPORT */ - -static option_t ccp_option_list[] = { - { "noccp", o_bool, &ccp_protent.enabled_flag, - "Disable CCP negotiation" }, - { "-ccp", o_bool, &ccp_protent.enabled_flag, - "Disable CCP negotiation", OPT_ALIAS }, - - { "bsdcomp", o_special, (void *)setbsdcomp, - "Request BSD-Compress packet compression", - OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, - { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, - "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].bsd_compress }, - { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, - "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].bsd_compress }, - - { "deflate", o_special, (void *)setdeflate, - "request Deflate compression", - OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, - { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, - "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].deflate }, - { "-deflate", o_bool, &ccp_wantoptions[0].deflate, - "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].deflate }, - - { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, - "don't use draft deflate #", OPT_A2COPY, - &ccp_allowoptions[0].deflate_draft }, - - { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "request Predictor-1", OPT_PRIO | 1 }, - { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].predictor_1 }, - { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, - &ccp_allowoptions[0].predictor_1 }, - -#if MPPE_SUPPORT - /* MPPE options are symmetrical ... we only set wantoptions here */ - { "require-mppe", o_bool, &ccp_wantoptions[0].mppe, - "require MPPE encryption", - OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, - { "+mppe", o_bool, &ccp_wantoptions[0].mppe, - "require MPPE encryption", - OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 }, - { "nomppe", o_bool, &ccp_wantoptions[0].mppe, - "don't allow MPPE encryption", OPT_PRIO }, - { "-mppe", o_bool, &ccp_wantoptions[0].mppe, - "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO }, - - /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */ - { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, - &ccp_wantoptions[0].mppe }, - { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40, - &ccp_wantoptions[0].mppe }, - { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 40-bit encryption", - OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe }, - { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 40-bit encryption", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, - &ccp_wantoptions[0].mppe }, - - { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128, - &ccp_wantoptions[0].mppe }, - { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe, - "require MPPE 128-bit encryption", - OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128, - &ccp_wantoptions[0].mppe }, - { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 128-bit encryption", - OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe }, - { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe, - "don't allow MPPE 128-bit encryption", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, - &ccp_wantoptions[0].mppe }, - - /* strange one; we always request stateless, but will we allow stateful? */ - { "mppe-stateful", o_bool, &refuse_mppe_stateful, - "allow MPPE stateful mode", OPT_PRIO }, - { "nomppe-stateful", o_bool, &refuse_mppe_stateful, - "disallow MPPE stateful mode", OPT_PRIO | 1 }, -#endif /* MPPE_SUPPORT */ - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ccp_init(ppp_pcb *pcb); -static void ccp_open(ppp_pcb *pcb); -static void ccp_close(ppp_pcb *pcb, const char *reason); -static void ccp_lowerup(ppp_pcb *pcb); -static void ccp_lowerdown(ppp_pcb *pcb); -static void ccp_input(ppp_pcb *pcb, u_char *pkt, int len); -static void ccp_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT -static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len); -#endif /* PPP_DATAINPUT */ - -const struct protent ccp_protent = { - PPP_CCP, - ccp_init, - ccp_input, - ccp_protrej, - ccp_lowerup, - ccp_lowerdown, - ccp_open, - ccp_close, -#if PRINTPKT_SUPPORT - ccp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - ccp_datainput, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "CCP", - "Compressed", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ccp_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -/* - * Callbacks for fsm code. - */ -static void ccp_resetci (fsm *); -static int ccp_cilen (fsm *); -static void ccp_addci (fsm *, u_char *, int *); -static int ccp_ackci (fsm *, u_char *, int); -static int ccp_nakci (fsm *, u_char *, int, int); -static int ccp_rejci (fsm *, u_char *, int); -static int ccp_reqci (fsm *, u_char *, int *, int); -static void ccp_up (fsm *); -static void ccp_down (fsm *); -static int ccp_extcode (fsm *, int, int, u_char *, int); -static void ccp_rack_timeout (void *); -static const char *method_name (ccp_options *, ccp_options *); - -static const fsm_callbacks ccp_callbacks = { - ccp_resetci, - ccp_cilen, - ccp_addci, - ccp_ackci, - ccp_nakci, - ccp_rejci, - ccp_reqci, - ccp_up, - ccp_down, - NULL, - NULL, - NULL, - NULL, - ccp_extcode, - "CCP" -}; - -/* - * Do we want / did we get any compression? - */ -static int ccp_anycompress(ccp_options *opt) { - return (0 -#if DEFLATE_SUPPORT - || (opt)->deflate -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - || (opt)->bsd_compress -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - || (opt)->predictor_1 || (opt)->predictor_2 -#endif /* PREDICTOR_SUPPORT */ -#if MPPE_SUPPORT - || (opt)->mppe -#endif /* MPPE_SUPPORT */ - ); -} - -/* - * Local state (mainly for handling reset-reqs and reset-acks). - */ -#define RACK_PENDING 1 /* waiting for reset-ack */ -#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */ - -#define RACKTIMEOUT 1 /* second */ - -#if PPP_OPTIONS -/* - * Option parsing - */ -static int -setbsdcomp(argv) - char **argv; -{ - int rbits, abits; - char *str, *endp; - - str = *argv; - abits = rbits = strtol(str, &endp, 0); - if (endp != str && *endp == ',') { - str = endp + 1; - abits = strtol(str, &endp, 0); - } - if (*endp != 0 || endp == str) { - option_error("invalid parameter '%s' for bsdcomp option", *argv); - return 0; - } - if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)) - || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) { - option_error("bsdcomp option values must be 0 or %d .. %d", - BSD_MIN_BITS, BSD_MAX_BITS); - return 0; - } - if (rbits > 0) { - ccp_wantoptions[0].bsd_compress = 1; - ccp_wantoptions[0].bsd_bits = rbits; - } else - ccp_wantoptions[0].bsd_compress = 0; - if (abits > 0) { - ccp_allowoptions[0].bsd_compress = 1; - ccp_allowoptions[0].bsd_bits = abits; - } else - ccp_allowoptions[0].bsd_compress = 0; - ppp_slprintf(bsd_value, sizeof(bsd_value), - rbits == abits? "%d": "%d,%d", rbits, abits); - - return 1; -} - -static int -setdeflate(argv) - char **argv; -{ - int rbits, abits; - char *str, *endp; - - str = *argv; - abits = rbits = strtol(str, &endp, 0); - if (endp != str && *endp == ',') { - str = endp + 1; - abits = strtol(str, &endp, 0); - } - if (*endp != 0 || endp == str) { - option_error("invalid parameter '%s' for deflate option", *argv); - return 0; - } - if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE)) - || (abits != 0 && (abits < DEFLATE_MIN_SIZE - || abits > DEFLATE_MAX_SIZE))) { - option_error("deflate option values must be 0 or %d .. %d", - DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE); - return 0; - } - if (rbits == DEFLATE_MIN_SIZE || abits == DEFLATE_MIN_SIZE) { - if (rbits == DEFLATE_MIN_SIZE) - rbits = DEFLATE_MIN_WORKS; - if (abits == DEFLATE_MIN_SIZE) - abits = DEFLATE_MIN_WORKS; - warn("deflate option value of %d changed to %d to avoid zlib bug", - DEFLATE_MIN_SIZE, DEFLATE_MIN_WORKS); - } - if (rbits > 0) { - ccp_wantoptions[0].deflate = 1; - ccp_wantoptions[0].deflate_size = rbits; - } else - ccp_wantoptions[0].deflate = 0; - if (abits > 0) { - ccp_allowoptions[0].deflate = 1; - ccp_allowoptions[0].deflate_size = abits; - } else - ccp_allowoptions[0].deflate = 0; - ppp_slprintf(deflate_value, sizeof(deflate_value), - rbits == abits? "%d": "%d,%d", rbits, abits); - - return 1; -} -#endif /* PPP_OPTIONS */ - -/* - * ccp_init - initialize CCP. - */ -static void ccp_init(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - - f->pcb = pcb; - f->protocol = PPP_CCP; - f->callbacks = &ccp_callbacks; - fsm_init(f); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(wo, 0, sizeof(*wo)); - memset(go, 0, sizeof(*go)); - memset(ao, 0, sizeof(*ao)); - memset(ho, 0, sizeof(*ho)); -#endif /* 0 */ - -#if DEFLATE_SUPPORT - wo->deflate = 1; - wo->deflate_size = DEFLATE_MAX_SIZE; - wo->deflate_correct = 1; - wo->deflate_draft = 1; - ao->deflate = 1; - ao->deflate_size = DEFLATE_MAX_SIZE; - ao->deflate_correct = 1; - ao->deflate_draft = 1; -#endif /* DEFLATE_SUPPORT */ - -#if BSDCOMPRESS_SUPPORT - wo->bsd_compress = 1; - wo->bsd_bits = BSD_MAX_BITS; - ao->bsd_compress = 1; - ao->bsd_bits = BSD_MAX_BITS; -#endif /* BSDCOMPRESS_SUPPORT */ - -#if PREDICTOR_SUPPORT - ao->predictor_1 = 1; -#endif /* PREDICTOR_SUPPORT */ -} - -/* - * ccp_open - CCP is allowed to come up. - */ -static void ccp_open(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - ccp_options *go = &pcb->ccp_gotoptions; - - if (f->state != PPP_FSM_OPENED) - ccp_set(pcb, 1, 0, 0, 0); - - /* - * Find out which compressors the kernel supports before - * deciding whether to open in silent mode. - */ - ccp_resetci(f); - if (!ccp_anycompress(go)) - f->flags |= OPT_SILENT; - - fsm_open(f); -} - -/* - * ccp_close - Terminate CCP. - */ -static void ccp_close(ppp_pcb *pcb, const char *reason) { - fsm *f = &pcb->ccp_fsm; - ccp_set(pcb, 0, 0, 0, 0); - fsm_close(f, reason); -} - -/* - * ccp_lowerup - we may now transmit CCP packets. - */ -static void ccp_lowerup(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - fsm_lowerup(f); -} - -/* - * ccp_lowerdown - we may not transmit CCP packets. - */ -static void ccp_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - fsm_lowerdown(f); -} - -/* - * ccp_input - process a received CCP packet. - */ -static void ccp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->ccp_fsm; - ccp_options *go = &pcb->ccp_gotoptions; - int oldstate; - - /* - * Check for a terminate-request so we can print a message. - */ - oldstate = f->state; - fsm_input(f, p, len); - if (oldstate == PPP_FSM_OPENED && p[0] == TERMREQ && f->state != PPP_FSM_OPENED) { - ppp_notice("Compression disabled by peer."); -#if MPPE_SUPPORT - if (go->mppe) { - ppp_error("MPPE disabled, closing LCP"); - lcp_close(pcb, "MPPE disabled by peer"); - } -#endif /* MPPE_SUPPORT */ - } - - /* - * If we get a terminate-ack and we're not asking for compression, - * close CCP. - */ - if (oldstate == PPP_FSM_REQSENT && p[0] == TERMACK - && !ccp_anycompress(go)) - ccp_close(pcb, "No compression negotiated"); -} - -/* - * Handle a CCP-specific code. - */ -static int ccp_extcode(fsm *f, int code, int id, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(len); - - switch (code) { - case CCP_RESETREQ: - if (f->state != PPP_FSM_OPENED) - break; - ccp_reset_comp(pcb); - /* send a reset-ack, which the transmitter will see and - reset its compression state. */ - fsm_sdata(f, CCP_RESETACK, id, NULL, 0); - break; - - case CCP_RESETACK: - if ((pcb->ccp_localstate & RACK_PENDING) && id == f->reqid) { - pcb->ccp_localstate &= ~(RACK_PENDING | RREQ_REPEAT); - UNTIMEOUT(ccp_rack_timeout, f); - ccp_reset_decomp(pcb); - } - break; - - default: - return 0; - } - - return 1; -} - -/* - * ccp_protrej - peer doesn't talk CCP. - */ -static void ccp_protrej(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; -#if MPPE_SUPPORT - ccp_options *go = &pcb->ccp_gotoptions; -#endif /* MPPE_SUPPORT */ - - ccp_set(pcb, 0, 0, 0, 0); - fsm_lowerdown(f); - -#if MPPE_SUPPORT - if (go->mppe) { - ppp_error("MPPE required but peer negotiation failed"); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - } -#endif /* MPPE_SUPPORT */ - -} - -/* - * ccp_resetci - initialize at start of negotiation. - */ -static void ccp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options *wo = &pcb->ccp_wantoptions; -#if MPPE_SUPPORT - ccp_options *ao = &pcb->ccp_allowoptions; -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT - u_char opt_buf[CCP_MAX_OPTION_LENGTH]; -#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ -#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT - int res; -#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ - -#if MPPE_SUPPORT - if (pcb->settings.require_mppe) { - wo->mppe = ao->mppe = - (pcb->settings.refuse_mppe_40 ? 0 : MPPE_OPT_40) - | (pcb->settings.refuse_mppe_128 ? 0 : MPPE_OPT_128); - } -#endif /* MPPE_SUPPORT */ - - *go = *wo; - pcb->ccp_all_rejected = 0; - -#if MPPE_SUPPORT - if (go->mppe) { - int auth_mschap_bits = pcb->auth_done; - int numbits; - - /* - * Start with a basic sanity check: mschap[v2] auth must be in - * exactly one direction. RFC 3079 says that the keys are - * 'derived from the credentials of the peer that initiated the call', - * however the PPP protocol doesn't have such a concept, and pppd - * cannot get this info externally. Instead we do the best we can. - * NB: If MPPE is required, all other compression opts are invalid. - * So, we return right away if we can't do it. - */ - - /* Leave only the mschap auth bits set */ - auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER | - CHAP_MS2_WITHPEER | CHAP_MS2_PEER); - /* Count the mschap auths */ - auth_mschap_bits >>= CHAP_MS_SHIFT; - numbits = 0; - do { - numbits += auth_mschap_bits & 1; - auth_mschap_bits >>= 1; - } while (auth_mschap_bits); - if (numbits > 1) { - ppp_error("MPPE required, but auth done in both directions."); - lcp_close(pcb, "MPPE required but not available"); - return; - } - if (!numbits) { - ppp_error("MPPE required, but MS-CHAP[v2] auth not performed."); - lcp_close(pcb, "MPPE required but not available"); - return; - } - - /* A plugin (eg radius) may not have obtained key material. */ - if (!pcb->mppe_keys_set) { - ppp_error("MPPE required, but keys are not available. " - "Possible plugin problem?"); - lcp_close(pcb, "MPPE required but not available"); - return; - } - - /* LM auth not supported for MPPE */ - if (pcb->auth_done & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { - /* This might be noise */ - if (go->mppe & MPPE_OPT_40) { - ppp_notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); - go->mppe &= ~MPPE_OPT_40; - wo->mppe &= ~MPPE_OPT_40; - } - } - - /* Last check: can we actually negotiate something? */ - if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { - /* Could be misconfig, could be 40-bit disabled above. */ - ppp_error("MPPE required, but both 40-bit and 128-bit disabled."); - lcp_close(pcb, "MPPE required but not available"); - return; - } - - /* sync options */ - ao->mppe = go->mppe; - /* MPPE is not compatible with other compression types */ -#if BSDCOMPRESS_SUPPORT - ao->bsd_compress = go->bsd_compress = 0; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - ao->predictor_1 = go->predictor_1 = 0; - ao->predictor_2 = go->predictor_2 = 0; -#endif /* PREDICTOR_SUPPORT */ -#if DEFLATE_SUPPORT - ao->deflate = go->deflate = 0; -#endif /* DEFLATE_SUPPORT */ - } -#endif /* MPPE_SUPPORT */ - - /* - * Check whether the kernel knows about the various - * compression methods we might request. - */ -#if BSDCOMPRESS_SUPPORT - /* FIXME: we don't need to test if BSD compress is available - * if BSDCOMPRESS_SUPPORT is set, it is. - */ - if (go->bsd_compress) { - opt_buf[0] = CI_BSD_COMPRESS; - opt_buf[1] = CILEN_BSD_COMPRESS; - for (;;) { - if (go->bsd_bits < BSD_MIN_BITS) { - go->bsd_compress = 0; - break; - } - opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); - res = ccp_test(pcb, opt_buf, CILEN_BSD_COMPRESS, 0); - if (res > 0) { - break; - } else if (res < 0) { - go->bsd_compress = 0; - break; - } - go->bsd_bits--; - } - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if DEFLATE_SUPPORT - /* FIXME: we don't need to test if deflate is available - * if DEFLATE_SUPPORT is set, it is. - */ - if (go->deflate) { - if (go->deflate_correct) { - opt_buf[0] = CI_DEFLATE; - opt_buf[1] = CILEN_DEFLATE; - opt_buf[3] = DEFLATE_CHK_SEQUENCE; - for (;;) { - if (go->deflate_size < DEFLATE_MIN_WORKS) { - go->deflate_correct = 0; - break; - } - opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); - res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); - if (res > 0) { - break; - } else if (res < 0) { - go->deflate_correct = 0; - break; - } - go->deflate_size--; - } - } - if (go->deflate_draft) { - opt_buf[0] = CI_DEFLATE_DRAFT; - opt_buf[1] = CILEN_DEFLATE; - opt_buf[3] = DEFLATE_CHK_SEQUENCE; - for (;;) { - if (go->deflate_size < DEFLATE_MIN_WORKS) { - go->deflate_draft = 0; - break; - } - opt_buf[2] = DEFLATE_MAKE_OPT(go->deflate_size); - res = ccp_test(pcb, opt_buf, CILEN_DEFLATE, 0); - if (res > 0) { - break; - } else if (res < 0) { - go->deflate_draft = 0; - break; - } - go->deflate_size--; - } - } - if (!go->deflate_correct && !go->deflate_draft) - go->deflate = 0; - } -#endif /* DEFLATE_SUPPORT */ -#if PREDICTOR_SUPPORT - /* FIXME: we don't need to test if predictor is available, - * if PREDICTOR_SUPPORT is set, it is. - */ - if (go->predictor_1) { - opt_buf[0] = CI_PREDICTOR_1; - opt_buf[1] = CILEN_PREDICTOR_1; - if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) - go->predictor_1 = 0; - } - if (go->predictor_2) { - opt_buf[0] = CI_PREDICTOR_2; - opt_buf[1] = CILEN_PREDICTOR_2; - if (ccp_test(pcb, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) - go->predictor_2 = 0; - } -#endif /* PREDICTOR_SUPPORT */ -} - -/* - * ccp_cilen - Return total length of our configuration info. - */ -static int ccp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - - return 0 -#if BSDCOMPRESS_SUPPORT - + (go->bsd_compress? CILEN_BSD_COMPRESS: 0) -#endif /* BSDCOMPRESS_SUPPORT */ -#if DEFLATE_SUPPORT - + (go->deflate && go->deflate_correct? CILEN_DEFLATE: 0) - + (go->deflate && go->deflate_draft? CILEN_DEFLATE: 0) -#endif /* DEFLATE_SUPPORT */ -#if PREDICTOR_SUPPORT - + (go->predictor_1? CILEN_PREDICTOR_1: 0) - + (go->predictor_2? CILEN_PREDICTOR_2: 0) -#endif /* PREDICTOR_SUPPORT */ -#if MPPE_SUPPORT - + (go->mppe? CILEN_MPPE: 0) -#endif /* MPPE_SUPPORT */ - ; -} - -/* - * ccp_addci - put our requests in a packet. - */ -static void ccp_addci(fsm *f, u_char *p, int *lenp) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - u_char *p0 = p; - - /* - * Add the compression types that we can receive, in decreasing - * preference order. - */ -#if MPPE_SUPPORT - if (go->mppe) { - p[0] = CI_MPPE; - p[1] = CILEN_MPPE; - MPPE_OPTS_TO_CI(go->mppe, &p[2]); - mppe_init(pcb, &pcb->mppe_decomp, go->mppe); - p += CILEN_MPPE; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate) { - if (go->deflate_correct) { - p[0] = CI_DEFLATE; - p[1] = CILEN_DEFLATE; - p[2] = DEFLATE_MAKE_OPT(go->deflate_size); - p[3] = DEFLATE_CHK_SEQUENCE; - p += CILEN_DEFLATE; - } - if (go->deflate_draft) { - p[0] = CI_DEFLATE_DRAFT; - p[1] = CILEN_DEFLATE; - p[2] = p[2 - CILEN_DEFLATE]; - p[3] = DEFLATE_CHK_SEQUENCE; - p += CILEN_DEFLATE; - } - } -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress) { - p[0] = CI_BSD_COMPRESS; - p[1] = CILEN_BSD_COMPRESS; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); - p += CILEN_BSD_COMPRESS; - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - /* XXX Should Predictor 2 be preferable to Predictor 1? */ - if (go->predictor_1) { - p[0] = CI_PREDICTOR_1; - p[1] = CILEN_PREDICTOR_1; - p += CILEN_PREDICTOR_1; - } - if (go->predictor_2) { - p[0] = CI_PREDICTOR_2; - p[1] = CILEN_PREDICTOR_2; - p += CILEN_PREDICTOR_2; - } -#endif /* PREDICTOR_SUPPORT */ - - go->method = (p > p0)? p0[0]: 0; - - *lenp = p - p0; -} - -/* - * ccp_ackci - process a received configure-ack, and return - * 1 iff the packet was OK. - */ -static int ccp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; -#if BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT - u_char *p0 = p; -#endif /* BSDCOMPRESS_SUPPORT || PREDICTOR_SUPPORT */ - -#if MPPE_SUPPORT - if (go->mppe) { - u_char opt_buf[CILEN_MPPE]; - - opt_buf[0] = CI_MPPE; - opt_buf[1] = CILEN_MPPE; - MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); - if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) - return 0; - p += CILEN_MPPE; - len -= CILEN_MPPE; - /* XXX Cope with first/fast ack */ - if (len == 0) - return 1; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate) { - if (len < CILEN_DEFLATE - || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - || p[1] != CILEN_DEFLATE - || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - /* XXX Cope with first/fast ack */ - if (len == 0) - return 1; - if (go->deflate_correct && go->deflate_draft) { - if (len < CILEN_DEFLATE - || p[0] != CI_DEFLATE_DRAFT - || p[1] != CILEN_DEFLATE - || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - } -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress) { - if (len < CILEN_BSD_COMPRESS - || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS - || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) - return 0; - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - if (go->predictor_1) { - if (len < CILEN_PREDICTOR_1 - || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) - return 0; - p += CILEN_PREDICTOR_1; - len -= CILEN_PREDICTOR_1; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } - if (go->predictor_2) { - if (len < CILEN_PREDICTOR_2 - || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) - return 0; - p += CILEN_PREDICTOR_2; - len -= CILEN_PREDICTOR_2; - /* XXX Cope with first/fast ack */ - if (p == p0 && len == 0) - return 1; - } -#endif /* PREDICTOR_SUPPORT */ - - if (len != 0) - return 0; - return 1; -} - -/* - * ccp_nakci - process received configure-nak. - * Returns 1 iff the nak was OK. - */ -static int ccp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options no; /* options we've seen already */ - ccp_options try_; /* options to ask for next time */ - LWIP_UNUSED_ARG(treat_as_reject); -#if !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT - LWIP_UNUSED_ARG(p); - LWIP_UNUSED_ARG(len); -#endif /* !MPPE_SUPPORT && !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ - - memset(&no, 0, sizeof(no)); - try_ = *go; - -#if MPPE_SUPPORT - if (go->mppe && len >= CILEN_MPPE - && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { - no.mppe = 1; - /* - * Peer wants us to use a different strength or other setting. - * Fail if we aren't willing to use his suggestion. - */ - MPPE_CI_TO_OPTS(&p[2], try_.mppe); - if ((try_.mppe & MPPE_OPT_STATEFUL) && pcb->settings.refuse_mppe_stateful) { - ppp_error("Refusing MPPE stateful mode offered by peer"); - try_.mppe = 0; - } else if (((go->mppe | MPPE_OPT_STATEFUL) & try_.mppe) != try_.mppe) { - /* Peer must have set options we didn't request (suggest) */ - try_.mppe = 0; - } - - if (!try_.mppe) { - ppp_error("MPPE required but peer negotiation failed"); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - } - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate && len >= CILEN_DEFLATE - && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) - && p[1] == CILEN_DEFLATE) { - no.deflate = 1; - /* - * Peer wants us to use a different code size or something. - * Stop asking for Deflate if we don't understand his suggestion. - */ - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL - || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS - || p[3] != DEFLATE_CHK_SEQUENCE) - try_.deflate = 0; - else if (DEFLATE_SIZE(p[2]) < go->deflate_size) - try_.deflate_size = DEFLATE_SIZE(p[2]); - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - if (go->deflate_correct && go->deflate_draft - && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT - && p[1] == CILEN_DEFLATE) { - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - } -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress && len >= CILEN_BSD_COMPRESS - && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { - no.bsd_compress = 1; - /* - * Peer wants us to use a different number of bits - * or a different version. - */ - if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) - try_.bsd_compress = 0; - else if (BSD_NBITS(p[2]) < go->bsd_bits) - try_.bsd_bits = BSD_NBITS(p[2]); - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - } -#endif /* BSDCOMPRESS_SUPPORT */ - - /* - * Predictor-1 and 2 have no options, so they can't be Naked. - * - * There may be remaining options but we ignore them. - */ - - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; -} - -/* - * ccp_rejci - reject some of our suggested compression methods. - */ -static int ccp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options try_; /* options to request next time */ - - try_ = *go; - - /* - * Cope with empty configure-rejects by ceasing to send - * configure-requests. - */ - if (len == 0 && pcb->ccp_all_rejected) - return -1; - -#if MPPE_SUPPORT - if (go->mppe && len >= CILEN_MPPE - && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { - ppp_error("MPPE required but peer refused"); - lcp_close(pcb, "MPPE required but peer refused"); - p += CILEN_MPPE; - len -= CILEN_MPPE; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - if (go->deflate_correct && len >= CILEN_DEFLATE - && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { - if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; /* Rej is bad */ - try_.deflate_correct = 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - if (go->deflate_draft && len >= CILEN_DEFLATE - && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { - if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) - || p[3] != DEFLATE_CHK_SEQUENCE) - return 0; /* Rej is bad */ - try_.deflate_draft = 0; - p += CILEN_DEFLATE; - len -= CILEN_DEFLATE; - } - if (!try_.deflate_correct && !try_.deflate_draft) - try_.deflate = 0; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - if (go->bsd_compress && len >= CILEN_BSD_COMPRESS - && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { - if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) - return 0; - try_.bsd_compress = 0; - p += CILEN_BSD_COMPRESS; - len -= CILEN_BSD_COMPRESS; - } -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - if (go->predictor_1 && len >= CILEN_PREDICTOR_1 - && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { - try_.predictor_1 = 0; - p += CILEN_PREDICTOR_1; - len -= CILEN_PREDICTOR_1; - } - if (go->predictor_2 && len >= CILEN_PREDICTOR_2 - && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { - try_.predictor_2 = 0; - p += CILEN_PREDICTOR_2; - len -= CILEN_PREDICTOR_2; - } -#endif /* PREDICTOR_SUPPORT */ - - if (len != 0) - return 0; - - if (f->state != PPP_FSM_OPENED) - *go = try_; - - return 1; -} - -/* - * ccp_reqci - processed a received configure-request. - * Returns CONFACK, CONFNAK or CONFREJ and the packet modified - * appropriately. - */ -static int ccp_reqci(fsm *f, u_char *p, int *lenp, int dont_nak) { - ppp_pcb *pcb = f->pcb; - ccp_options *ho = &pcb->ccp_hisoptions; - ccp_options *ao = &pcb->ccp_allowoptions; - int ret, newret; -#if DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT - int res; - int nb; -#endif /* DEFLATE_SUPPORT || BSDCOMPRESS_SUPPORT */ - u_char *p0, *retp; - int len, clen, type; -#if MPPE_SUPPORT - u8_t rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ - /* CI_MPPE, or due to other options? */ -#endif /* MPPE_SUPPORT */ - - ret = CONFACK; - retp = p0 = p; - len = *lenp; - - memset(ho, 0, sizeof(ccp_options)); - ho->method = (len > 0)? p[0]: 0; - - while (len > 0) { - newret = CONFACK; - if (len < 2 || p[1] < 2 || p[1] > len) { - /* length is bad */ - clen = len; - newret = CONFREJ; - - } else { - type = p[0]; - clen = p[1]; - - switch (type) { -#if MPPE_SUPPORT - case CI_MPPE: - if (!ao->mppe || clen != CILEN_MPPE) { - newret = CONFREJ; - break; - } - MPPE_CI_TO_OPTS(&p[2], ho->mppe); - - /* Nak if anything unsupported or unknown are set. */ - if (ho->mppe & MPPE_OPT_UNSUPPORTED) { - newret = CONFNAK; - ho->mppe &= ~MPPE_OPT_UNSUPPORTED; - } - if (ho->mppe & MPPE_OPT_UNKNOWN) { - newret = CONFNAK; - ho->mppe &= ~MPPE_OPT_UNKNOWN; - } - - /* Check state opt */ - if (ho->mppe & MPPE_OPT_STATEFUL) { - /* - * We can Nak and request stateless, but it's a - * lot easier to just assume the peer will request - * it if he can do it; stateful mode is bad over - * the Internet -- which is where we expect MPPE. - */ - if (pcb->settings.refuse_mppe_stateful) { - ppp_error("Refusing MPPE stateful mode offered by peer"); - newret = CONFREJ; - break; - } - } - - /* Find out which of {S,L} are set. */ - if ((ho->mppe & MPPE_OPT_128) - && (ho->mppe & MPPE_OPT_40)) { - /* Both are set, negotiate the strongest. */ - newret = CONFNAK; - if (ao->mppe & MPPE_OPT_128) - ho->mppe &= ~MPPE_OPT_40; - else if (ao->mppe & MPPE_OPT_40) - ho->mppe &= ~MPPE_OPT_128; - else { - newret = CONFREJ; - break; - } - } else if (ho->mppe & MPPE_OPT_128) { - if (!(ao->mppe & MPPE_OPT_128)) { - newret = CONFREJ; - break; - } - } else if (ho->mppe & MPPE_OPT_40) { - if (!(ao->mppe & MPPE_OPT_40)) { - newret = CONFREJ; - break; - } - } else { - /* Neither are set. */ - /* We cannot accept this. */ - newret = CONFNAK; - /* Give the peer our idea of what can be used, - so it can choose and confirm */ - ho->mppe = ao->mppe; - } - - /* rebuild the opts */ - MPPE_OPTS_TO_CI(ho->mppe, &p[2]); - if (newret == CONFACK) { - int mtu; - - mppe_init(pcb, &pcb->mppe_comp, ho->mppe); - /* - * We need to decrease the interface MTU by MPPE_PAD - * because MPPE frames **grow**. The kernel [must] - * allocate MPPE_PAD extra bytes in xmit buffers. - */ - mtu = netif_get_mtu(pcb); - if (mtu) - netif_set_mtu(pcb, mtu - MPPE_PAD); - else - newret = CONFREJ; - } - - /* - * We have accepted MPPE or are willing to negotiate - * MPPE parameters. A CONFREJ is due to subsequent - * (non-MPPE) processing. - */ - rej_for_ci_mppe = 0; - break; -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (!ao->deflate || clen != CILEN_DEFLATE - || (!ao->deflate_correct && type == CI_DEFLATE) - || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) { - newret = CONFREJ; - break; - } - - ho->deflate = 1; - ho->deflate_size = nb = DEFLATE_SIZE(p[2]); - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL - || p[3] != DEFLATE_CHK_SEQUENCE - || nb > ao->deflate_size || nb < DEFLATE_MIN_WORKS) { - newret = CONFNAK; - if (!dont_nak) { - p[2] = DEFLATE_MAKE_OPT(ao->deflate_size); - p[3] = DEFLATE_CHK_SEQUENCE; - /* fall through to test this #bits below */ - } else - break; - } - - /* - * Check whether we can do Deflate with the window - * size they want. If the window is too big, reduce - * it until the kernel can cope and nak with that. - * We only check this for the first option. - */ - if (p == p0) { - for (;;) { - res = ccp_test(pcb, p, CILEN_DEFLATE, 1); - if (res > 0) - break; /* it's OK now */ - if (res < 0 || nb == DEFLATE_MIN_WORKS || dont_nak) { - newret = CONFREJ; - p[2] = DEFLATE_MAKE_OPT(ho->deflate_size); - break; - } - newret = CONFNAK; - --nb; - p[2] = DEFLATE_MAKE_OPT(nb); - } - } - break; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - case CI_BSD_COMPRESS: - if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { - newret = CONFREJ; - break; - } - - ho->bsd_compress = 1; - ho->bsd_bits = nb = BSD_NBITS(p[2]); - if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION - || nb > ao->bsd_bits || nb < BSD_MIN_BITS) { - newret = CONFNAK; - if (!dont_nak) { - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits); - /* fall through to test this #bits below */ - } else - break; - } - - /* - * Check whether we can do BSD-Compress with the code - * size they want. If the code size is too big, reduce - * it until the kernel can cope and nak with that. - * We only check this for the first option. - */ - if (p == p0) { - for (;;) { - res = ccp_test(pcb, p, CILEN_BSD_COMPRESS, 1); - if (res > 0) - break; - if (res < 0 || nb == BSD_MIN_BITS || dont_nak) { - newret = CONFREJ; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, - ho->bsd_bits); - break; - } - newret = CONFNAK; - --nb; - p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb); - } - } - break; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - case CI_PREDICTOR_1: - if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) { - newret = CONFREJ; - break; - } - - ho->predictor_1 = 1; - if (p == p0 - && ccp_test(pcb, p, CILEN_PREDICTOR_1, 1) <= 0) { - newret = CONFREJ; - } - break; - - case CI_PREDICTOR_2: - if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) { - newret = CONFREJ; - break; - } - - ho->predictor_2 = 1; - if (p == p0 - && ccp_test(pcb, p, CILEN_PREDICTOR_2, 1) <= 0) { - newret = CONFREJ; - } - break; -#endif /* PREDICTOR_SUPPORT */ - - default: - newret = CONFREJ; - } - } - - if (newret == CONFNAK && dont_nak) - newret = CONFREJ; - if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) { - /* we're returning this option */ - if (newret == CONFREJ && ret == CONFNAK) - retp = p0; - ret = newret; - if (p != retp) - MEMCPY(retp, p, clen); - retp += clen; - } - - p += clen; - len -= clen; - } - - if (ret != CONFACK) { - if (ret == CONFREJ && *lenp == retp - p0) - pcb->ccp_all_rejected = 1; - else - *lenp = retp - p0; - } -#if MPPE_SUPPORT - if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) { - ppp_error("MPPE required but peer negotiation failed"); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - } -#endif /* MPPE_SUPPORT */ - return ret; -} - -/* - * Make a string name for a compression method (or 2). - */ -static const char *method_name(ccp_options *opt, ccp_options *opt2) { - static char result[64]; -#if !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT - LWIP_UNUSED_ARG(opt2); -#endif /* !DEFLATE_SUPPORT && !BSDCOMPRESS_SUPPORT */ - - if (!ccp_anycompress(opt)) - return "(none)"; - switch (opt->method) { -#if MPPE_SUPPORT - case CI_MPPE: - { - char *p = result; - char *q = result + sizeof(result); /* 1 past result */ - - ppp_slprintf(p, q - p, "MPPE "); - p += 5; - if (opt->mppe & MPPE_OPT_128) { - ppp_slprintf(p, q - p, "128-bit "); - p += 8; - } - if (opt->mppe & MPPE_OPT_40) { - ppp_slprintf(p, q - p, "40-bit "); - p += 7; - } - if (opt->mppe & MPPE_OPT_STATEFUL) - ppp_slprintf(p, q - p, "stateful"); - else - ppp_slprintf(p, q - p, "stateless"); - - break; - } -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (opt2 != NULL && opt2->deflate_size != opt->deflate_size) - ppp_slprintf(result, sizeof(result), "Deflate%s (%d/%d)", - (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), - opt->deflate_size, opt2->deflate_size); - else - ppp_slprintf(result, sizeof(result), "Deflate%s (%d)", - (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), - opt->deflate_size); - break; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - case CI_BSD_COMPRESS: - if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) - ppp_slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", - opt->bsd_bits, opt2->bsd_bits); - else - ppp_slprintf(result, sizeof(result), "BSD-Compress (%d)", - opt->bsd_bits); - break; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - case CI_PREDICTOR_1: - return "Predictor 1"; - case CI_PREDICTOR_2: - return "Predictor 2"; -#endif /* PREDICTOR_SUPPORT */ - default: - ppp_slprintf(result, sizeof(result), "Method %d", opt->method); - } - return result; -} - -/* - * CCP has come up - inform the kernel driver and log a message. - */ -static void ccp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - ccp_options *go = &pcb->ccp_gotoptions; - ccp_options *ho = &pcb->ccp_hisoptions; - char method1[64]; - - ccp_set(pcb, 1, 1, go->method, ho->method); - if (ccp_anycompress(go)) { - if (ccp_anycompress(ho)) { - if (go->method == ho->method) { - ppp_notice("%s compression enabled", method_name(go, ho)); - } else { - ppp_strlcpy(method1, method_name(go, NULL), sizeof(method1)); - ppp_notice("%s / %s compression enabled", - method1, method_name(ho, NULL)); - } - } else - ppp_notice("%s receive compression enabled", method_name(go, NULL)); - } else if (ccp_anycompress(ho)) - ppp_notice("%s transmit compression enabled", method_name(ho, NULL)); -#if MPPE_SUPPORT - if (go->mppe) { - continue_networks(pcb); /* Bring up IP et al */ - } -#endif /* MPPE_SUPPORT */ -} - -/* - * CCP has gone down - inform the kernel driver. - */ -static void ccp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; -#if MPPE_SUPPORT - ccp_options *go = &pcb->ccp_gotoptions; -#endif /* MPPE_SUPPORT */ - - if (pcb->ccp_localstate & RACK_PENDING) - UNTIMEOUT(ccp_rack_timeout, f); - pcb->ccp_localstate = 0; - ccp_set(pcb, 1, 0, 0, 0); -#if MPPE_SUPPORT - if (go->mppe) { - go->mppe = 0; - if (pcb->lcp_fsm.state == PPP_FSM_OPENED) { - /* If LCP is not already going down, make sure it does. */ - ppp_error("MPPE disabled"); - lcp_close(pcb, "MPPE disabled"); - } - } -#endif /* MPPE_SUPPORT */ -} - -#if PRINTPKT_SUPPORT -/* - * Print the contents of a CCP packet. - */ -static const char* const ccp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", - NULL, NULL, NULL, NULL, NULL, NULL, - "ResetReq", "ResetAck", -}; - -static int ccp_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { - const u_char *p0, *optend; - int code, id, len; - int optlen; - - p0 = p; - if (plen < HEADERLEN) - return 0; - code = p[0]; - id = p[1]; - len = (p[2] << 8) + p[3]; - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ccp_codenames) && ccp_codenames[code-1] != NULL) - printer(arg, " %s", ccp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - p += HEADERLEN; - - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print list of possible compression methods */ - while (len >= 2) { - code = p[0]; - optlen = p[1]; - if (optlen < 2 || optlen > len) - break; - printer(arg, " <"); - len -= optlen; - optend = p + optlen; - switch (code) { -#if MPPE_SUPPORT - case CI_MPPE: - if (optlen >= CILEN_MPPE) { - u_char mppe_opts; - - MPPE_CI_TO_OPTS(&p[2], mppe_opts); - printer(arg, "mppe %s %s %s %s %s %s%s", - (p[2] & MPPE_H_BIT)? "+H": "-H", - (p[5] & MPPE_M_BIT)? "+M": "-M", - (p[5] & MPPE_S_BIT)? "+S": "-S", - (p[5] & MPPE_L_BIT)? "+L": "-L", - (p[5] & MPPE_D_BIT)? "+D": "-D", - (p[5] & MPPE_C_BIT)? "+C": "-C", - (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": ""); - if (mppe_opts & MPPE_OPT_UNKNOWN) - printer(arg, " (%.2x %.2x %.2x %.2x)", - p[2], p[3], p[4], p[5]); - p += CILEN_MPPE; - } - break; -#endif /* MPPE_SUPPORT */ -#if DEFLATE_SUPPORT - case CI_DEFLATE: - case CI_DEFLATE_DRAFT: - if (optlen >= CILEN_DEFLATE) { - printer(arg, "deflate%s %d", - (code == CI_DEFLATE_DRAFT? "(old#)": ""), - DEFLATE_SIZE(p[2])); - if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL) - printer(arg, " method %d", DEFLATE_METHOD(p[2])); - if (p[3] != DEFLATE_CHK_SEQUENCE) - printer(arg, " check %d", p[3]); - p += CILEN_DEFLATE; - } - break; -#endif /* DEFLATE_SUPPORT */ -#if BSDCOMPRESS_SUPPORT - case CI_BSD_COMPRESS: - if (optlen >= CILEN_BSD_COMPRESS) { - printer(arg, "bsd v%d %d", BSD_VERSION(p[2]), - BSD_NBITS(p[2])); - p += CILEN_BSD_COMPRESS; - } - break; -#endif /* BSDCOMPRESS_SUPPORT */ -#if PREDICTOR_SUPPORT - case CI_PREDICTOR_1: - if (optlen >= CILEN_PREDICTOR_1) { - printer(arg, "predictor 1"); - p += CILEN_PREDICTOR_1; - } - break; - case CI_PREDICTOR_2: - if (optlen >= CILEN_PREDICTOR_2) { - printer(arg, "predictor 2"); - p += CILEN_PREDICTOR_2; - } - break; -#endif /* PREDICTOR_SUPPORT */ - default: - break; - } - while (p < optend) - printer(arg, " %.2x", *p++); - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* dump out the rest of the packet in hex */ - while (--len >= 0) - printer(arg, " %.2x", *p++); - - return p - p0; -} -#endif /* PRINTPKT_SUPPORT */ - -#if PPP_DATAINPUT -/* - * We have received a packet that the decompressor failed to - * decompress. Here we would expect to issue a reset-request, but - * Motorola has a patent on resetting the compressor as a result of - * detecting an error in the decompressed data after decompression. - * (See US patent 5,130,993; international patent publication number - * WO 91/10289; Australian patent 73296/91.) - * - * So we ask the kernel whether the error was detected after - * decompression; if it was, we take CCP down, thus disabling - * compression :-(, otherwise we issue the reset-request. - */ -static void ccp_datainput(ppp_pcb *pcb, u_char *pkt, int len) { - fsm *f; -#if MPPE_SUPPORT - ccp_options *go = &pcb->ccp_gotoptions; -#endif /* MPPE_SUPPORT */ - LWIP_UNUSED_ARG(pkt); - LWIP_UNUSED_ARG(len); - - f = &pcb->ccp_fsm; - if (f->state == PPP_FSM_OPENED) { - if (ccp_fatal_error(pcb)) { - /* - * Disable compression by taking CCP down. - */ - ppp_error("Lost compression sync: disabling compression"); - ccp_close(pcb, "Lost compression sync"); -#if MPPE_SUPPORT - /* - * If we were doing MPPE, we must also take the link down. - */ - if (go->mppe) { - ppp_error("Too many MPPE errors, closing LCP"); - lcp_close(pcb, "Too many MPPE errors"); - } -#endif /* MPPE_SUPPORT */ - } else { - /* - * Send a reset-request to reset the peer's compressor. - * We don't do that if we are still waiting for an - * acknowledgement to a previous reset-request. - */ - if (!(pcb->ccp_localstate & RACK_PENDING)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - pcb->ccp_localstate |= RACK_PENDING; - } else - pcb->ccp_localstate |= RREQ_REPEAT; - } - } -} -#endif /* PPP_DATAINPUT */ - -/* - * We have received a packet that the decompressor failed to - * decompress. Issue a reset-request. - */ -void ccp_resetrequest(ppp_pcb *pcb) { - fsm *f = &pcb->ccp_fsm; - - if (f->state != PPP_FSM_OPENED) - return; - - /* - * Send a reset-request to reset the peer's compressor. - * We don't do that if we are still waiting for an - * acknowledgement to a previous reset-request. - */ - if (!(pcb->ccp_localstate & RACK_PENDING)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - pcb->ccp_localstate |= RACK_PENDING; - } else - pcb->ccp_localstate |= RREQ_REPEAT; -} - -/* - * Timeout waiting for reset-ack. - */ -static void ccp_rack_timeout(void *arg) { - fsm *f = (fsm*)arg; - ppp_pcb *pcb = f->pcb; - - if (f->state == PPP_FSM_OPENED && (pcb->ccp_localstate & RREQ_REPEAT)) { - fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0); - TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT); - pcb->ccp_localstate &= ~RREQ_REPEAT; - } else - pcb->ccp_localstate &= ~RACK_PENDING; -} - -#endif /* PPP_SUPPORT && CCP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/chap-md5.c b/components/net/lwip-2.0.2/src/netif/ppp/chap-md5.c deleted file mode 100644 index 88f069f032..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/chap-md5.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * chap-md5.c - New CHAP/MD5 implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/chap-new.h" -#include "netif/ppp/chap-md5.h" -#include "netif/ppp/magic.h" -#include "netif/ppp/pppcrypt.h" - -#define MD5_HASH_SIZE 16 -#define MD5_MIN_CHALLENGE 17 -#define MD5_MAX_CHALLENGE 24 -#define MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE 3 /* 2^3-1 = 7, 17+7 = 24 */ - -#if PPP_SERVER -static void chap_md5_generate_challenge(ppp_pcb *pcb, unsigned char *cp) { - int clen; - LWIP_UNUSED_ARG(pcb); - - clen = MD5_MIN_CHALLENGE + magic_pow(MD5_MIN_MAX_POWER_OF_TWO_CHALLENGE); - *cp++ = clen; - magic_random_bytes(cp, clen); -} - -static int chap_md5_verify_response(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - lwip_md5_context ctx; - unsigned char idbyte = id; - unsigned char hash[MD5_HASH_SIZE]; - int challenge_len, response_len; - LWIP_UNUSED_ARG(name); - LWIP_UNUSED_ARG(pcb); - - challenge_len = *challenge++; - response_len = *response++; - if (response_len == MD5_HASH_SIZE) { - /* Generate hash of ID, secret, challenge */ - lwip_md5_init(&ctx); - lwip_md5_starts(&ctx); - lwip_md5_update(&ctx, &idbyte, 1); - lwip_md5_update(&ctx, secret, secret_len); - lwip_md5_update(&ctx, challenge, challenge_len); - lwip_md5_finish(&ctx, hash); - lwip_md5_free(&ctx); - - /* Test if our hash matches the peer's response */ - if (memcmp(hash, response, MD5_HASH_SIZE) == 0) { - ppp_slprintf(message, message_space, "Access granted"); - return 1; - } - } - ppp_slprintf(message, message_space, "Access denied"); - return 0; -} -#endif /* PPP_SERVER */ - -static void chap_md5_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *private_) { - lwip_md5_context ctx; - unsigned char idbyte = id; - int challenge_len = *challenge++; - LWIP_UNUSED_ARG(our_name); - LWIP_UNUSED_ARG(private_); - LWIP_UNUSED_ARG(pcb); - - lwip_md5_init(&ctx); - lwip_md5_starts(&ctx); - lwip_md5_update(&ctx, &idbyte, 1); - lwip_md5_update(&ctx, (const u_char *)secret, secret_len); - lwip_md5_update(&ctx, challenge, challenge_len); - lwip_md5_finish(&ctx, &response[1]); - lwip_md5_free(&ctx); - response[0] = MD5_HASH_SIZE; -} - -const struct chap_digest_type md5_digest = { - CHAP_MD5, /* code */ -#if PPP_SERVER - chap_md5_generate_challenge, - chap_md5_verify_response, -#endif /* PPP_SERVER */ - chap_md5_make_response, - NULL, /* check_success */ - NULL, /* handle_failure */ -}; - -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/chap-new.c b/components/net/lwip-2.0.2/src/netif/ppp/chap-new.c deleted file mode 100644 index 485122d272..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/chap-new.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * chap-new.c - New CHAP implementation. - * - * Copyright (c) 2003 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#if 0 /* UNUSED */ -#include "session.h" -#endif /* UNUSED */ - -#include "netif/ppp/chap-new.h" -#include "netif/ppp/chap-md5.h" -#if MSCHAP_SUPPORT -#include "netif/ppp/chap_ms.h" -#endif -#include "netif/ppp/magic.h" - -#if 0 /* UNUSED */ -/* Hook for a plugin to validate CHAP challenge */ -int (*chap_verify_hook)(const char *name, const char *ourname, int id, - const struct chap_digest_type *digest, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) = NULL; -#endif /* UNUSED */ - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t chap_option_list[] = { - { "chap-restart", o_int, &chap_timeout_time, - "Set timeout for CHAP", OPT_PRIO }, - { "chap-max-challenge", o_int, &pcb->settings.chap_max_transmits, - "Set max #xmits for challenge", OPT_PRIO }, - { "chap-interval", o_int, &pcb->settings.chap_rechallenge_time, - "Set interval for rechallenge", OPT_PRIO }, - { NULL } -}; -#endif /* PPP_OPTIONS */ - - -/* Values for flags in chap_client_state and chap_server_state */ -#define LOWERUP 1 -#define AUTH_STARTED 2 -#define AUTH_DONE 4 -#define AUTH_FAILED 8 -#define TIMEOUT_PENDING 0x10 -#define CHALLENGE_VALID 0x20 - -/* - * Prototypes. - */ -static void chap_init(ppp_pcb *pcb); -static void chap_lowerup(ppp_pcb *pcb); -static void chap_lowerdown(ppp_pcb *pcb); -#if PPP_SERVER -static void chap_timeout(void *arg); -static void chap_generate_challenge(ppp_pcb *pcb); -static void chap_handle_response(ppp_pcb *pcb, int code, - unsigned char *pkt, int len); -static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, - const struct chap_digest_type *digest, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space); -#endif /* PPP_SERVER */ -static void chap_respond(ppp_pcb *pcb, int id, - unsigned char *pkt, int len); -static void chap_handle_status(ppp_pcb *pcb, int code, int id, - unsigned char *pkt, int len); -static void chap_protrej(ppp_pcb *pcb); -static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen); -#if PRINTPKT_SUPPORT -static int chap_print_pkt(const unsigned char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -/* List of digest types that we know about */ -static const struct chap_digest_type* const chap_digests[] = { - &md5_digest, -#if MSCHAP_SUPPORT - &chapms_digest, - &chapms2_digest, -#endif /* MSCHAP_SUPPORT */ - NULL -}; - -/* - * chap_init - reset to initial state. - */ -static void chap_init(ppp_pcb *pcb) { - LWIP_UNUSED_ARG(pcb); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(&pcb->chap_client, 0, sizeof(chap_client_state)); -#if PPP_SERVER - memset(&pcb->chap_server, 0, sizeof(chap_server_state)); -#endif /* PPP_SERVER */ -#endif /* 0 */ -} - -/* - * chap_lowerup - we can start doing stuff now. - */ -static void chap_lowerup(ppp_pcb *pcb) { - - pcb->chap_client.flags |= LOWERUP; -#if PPP_SERVER - pcb->chap_server.flags |= LOWERUP; - if (pcb->chap_server.flags & AUTH_STARTED) - chap_timeout(pcb); -#endif /* PPP_SERVER */ -} - -static void chap_lowerdown(ppp_pcb *pcb) { - - pcb->chap_client.flags = 0; -#if PPP_SERVER - if (pcb->chap_server.flags & TIMEOUT_PENDING) - UNTIMEOUT(chap_timeout, pcb); - pcb->chap_server.flags = 0; -#endif /* PPP_SERVER */ -} - -#if PPP_SERVER -/* - * chap_auth_peer - Start authenticating the peer. - * If the lower layer is already up, we start sending challenges, - * otherwise we wait for the lower layer to come up. - */ -void chap_auth_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { - const struct chap_digest_type *dp; - int i; - - if (pcb->chap_server.flags & AUTH_STARTED) { - ppp_error("CHAP: peer authentication already started!"); - return; - } - for (i = 0; (dp = chap_digests[i]) != NULL; ++i) - if (dp->code == digest_code) - break; - if (dp == NULL) - ppp_fatal("CHAP digest 0x%x requested but not available", - digest_code); - - pcb->chap_server.digest = dp; - pcb->chap_server.name = our_name; - /* Start with a random ID value */ - pcb->chap_server.id = magic(); - pcb->chap_server.flags |= AUTH_STARTED; - if (pcb->chap_server.flags & LOWERUP) - chap_timeout(pcb); -} -#endif /* PPP_SERVER */ - -/* - * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. - * There isn't much to do until we receive a challenge. - */ -void chap_auth_with_peer(ppp_pcb *pcb, const char *our_name, int digest_code) { - const struct chap_digest_type *dp; - int i; - - if(NULL == our_name) - return; - - if (pcb->chap_client.flags & AUTH_STARTED) { - ppp_error("CHAP: authentication with peer already started!"); - return; - } - for (i = 0; (dp = chap_digests[i]) != NULL; ++i) - if (dp->code == digest_code) - break; - - if (dp == NULL) - ppp_fatal("CHAP digest 0x%x requested but not available", - digest_code); - - pcb->chap_client.digest = dp; - pcb->chap_client.name = our_name; - pcb->chap_client.flags |= AUTH_STARTED; -} - -#if PPP_SERVER -/* - * chap_timeout - It's time to send another challenge to the peer. - * This could be either a retransmission of a previous challenge, - * or a new challenge to start re-authentication. - */ -static void chap_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - struct pbuf *p; - - pcb->chap_server.flags &= ~TIMEOUT_PENDING; - if ((pcb->chap_server.flags & CHALLENGE_VALID) == 0) { - pcb->chap_server.challenge_xmits = 0; - chap_generate_challenge(pcb); - pcb->chap_server.flags |= CHALLENGE_VALID; - } else if (pcb->chap_server.challenge_xmits >= pcb->settings.chap_max_transmits) { - pcb->chap_server.flags &= ~CHALLENGE_VALID; - pcb->chap_server.flags |= AUTH_DONE | AUTH_FAILED; - auth_peer_fail(pcb, PPP_CHAP); - return; - } - - p = pbuf_alloc(PBUF_RAW, (u16_t)(pcb->chap_server.challenge_pktlen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - MEMCPY(p->payload, pcb->chap_server.challenge, pcb->chap_server.challenge_pktlen); - ppp_write(pcb, p); - ++pcb->chap_server.challenge_xmits; - pcb->chap_server.flags |= TIMEOUT_PENDING; - TIMEOUT(chap_timeout, arg, pcb->settings.chap_timeout_time); -} - -/* - * chap_generate_challenge - generate a challenge string and format - * the challenge packet in pcb->chap_server.challenge_pkt. - */ -static void chap_generate_challenge(ppp_pcb *pcb) { - int clen = 1, nlen, len; - unsigned char *p; - - p = pcb->chap_server.challenge; - MAKEHEADER(p, PPP_CHAP); - p += CHAP_HDRLEN; - pcb->chap_server.digest->generate_challenge(pcb, p); - clen = *p; - nlen = strlen(pcb->chap_server.name); - memcpy(p + 1 + clen, pcb->chap_server.name, nlen); - - len = CHAP_HDRLEN + 1 + clen + nlen; - pcb->chap_server.challenge_pktlen = PPP_HDRLEN + len; - - p = pcb->chap_server.challenge + PPP_HDRLEN; - p[0] = CHAP_CHALLENGE; - p[1] = ++pcb->chap_server.id; - p[2] = len >> 8; - p[3] = len; -} - -/* - * chap_handle_response - check the response to our challenge. - */ -static void chap_handle_response(ppp_pcb *pcb, int id, - unsigned char *pkt, int len) { - int response_len, ok, mlen; - const unsigned char *response; - unsigned char *outp; - struct pbuf *p; - const char *name = NULL; /* initialized to shut gcc up */ -#if 0 /* UNUSED */ - int (*verifier)(const char *, const char *, int, const struct chap_digest_type *, - const unsigned char *, const unsigned char *, char *, int); -#endif /* UNUSED */ - char rname[MAXNAMELEN+1]; - char message[256]; - - if ((pcb->chap_server.flags & LOWERUP) == 0) - return; - if (id != pcb->chap_server.challenge[PPP_HDRLEN+1] || len < 2) - return; - if (pcb->chap_server.flags & CHALLENGE_VALID) { - response = pkt; - GETCHAR(response_len, pkt); - len -= response_len + 1; /* length of name */ - name = (char *)pkt + response_len; - if (len < 0) - return; - - if (pcb->chap_server.flags & TIMEOUT_PENDING) { - pcb->chap_server.flags &= ~TIMEOUT_PENDING; - UNTIMEOUT(chap_timeout, pcb); - } -#if PPP_REMOTENAME - if (pcb->settings.explicit_remote) { - name = pcb->remote_name; - } else -#endif /* PPP_REMOTENAME */ - { - /* Null terminate and clean remote name. */ - ppp_slprintf(rname, sizeof(rname), "%.*v", len, name); - name = rname; - } - -#if 0 /* UNUSED */ - if (chap_verify_hook) - verifier = chap_verify_hook; - else - verifier = chap_verify_response; - ok = (*verifier)(name, pcb->chap_server.name, id, pcb->chap_server.digest, - pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, - response, pcb->chap_server.message, sizeof(pcb->chap_server.message)); -#endif /* UNUSED */ - ok = chap_verify_response(pcb, name, pcb->chap_server.name, id, pcb->chap_server.digest, - pcb->chap_server.challenge + PPP_HDRLEN + CHAP_HDRLEN, - response, message, sizeof(message)); -#if 0 /* UNUSED */ - if (!ok || !auth_number()) { -#endif /* UNUSED */ - if (!ok) { - pcb->chap_server.flags |= AUTH_FAILED; - ppp_warn("Peer %q failed CHAP authentication", name); - } - } else if ((pcb->chap_server.flags & AUTH_DONE) == 0) - return; - - /* send the response */ - mlen = strlen(message); - len = CHAP_HDRLEN + mlen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +len), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (unsigned char *)p->payload; - MAKEHEADER(outp, PPP_CHAP); - - outp[0] = (pcb->chap_server.flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; - outp[1] = id; - outp[2] = len >> 8; - outp[3] = len; - if (mlen > 0) - memcpy(outp + CHAP_HDRLEN, message, mlen); - ppp_write(pcb, p); - - if (pcb->chap_server.flags & CHALLENGE_VALID) { - pcb->chap_server.flags &= ~CHALLENGE_VALID; - if (!(pcb->chap_server.flags & AUTH_DONE) && !(pcb->chap_server.flags & AUTH_FAILED)) { - -#if 0 /* UNUSED */ - /* - * Auth is OK, so now we need to check session restrictions - * to ensure everything is OK, but only if we used a - * plugin, and only if we're configured to check. This - * allows us to do PAM checks on PPP servers that - * authenticate against ActiveDirectory, and use AD for - * account info (like when using Winbind integrated with - * PAM). - */ - if (session_mgmt && - session_check(name, NULL, devnam, NULL) == 0) { - pcb->chap_server.flags |= AUTH_FAILED; - ppp_warn("Peer %q failed CHAP Session verification", name); - } -#endif /* UNUSED */ - - } - if (pcb->chap_server.flags & AUTH_FAILED) { - auth_peer_fail(pcb, PPP_CHAP); - } else { - if ((pcb->chap_server.flags & AUTH_DONE) == 0) - auth_peer_success(pcb, PPP_CHAP, - pcb->chap_server.digest->code, - name, strlen(name)); - if (pcb->settings.chap_rechallenge_time) { - pcb->chap_server.flags |= TIMEOUT_PENDING; - TIMEOUT(chap_timeout, pcb, - pcb->settings.chap_rechallenge_time); - } - } - pcb->chap_server.flags |= AUTH_DONE; - } -} - -/* - * chap_verify_response - check whether the peer's response matches - * what we think it should be. Returns 1 if it does (authentication - * succeeded), or 0 if it doesn't. - */ -static int chap_verify_response(ppp_pcb *pcb, const char *name, const char *ourname, int id, - const struct chap_digest_type *digest, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - int ok; - unsigned char secret[MAXSECRETLEN]; - int secret_len; - - /* Get the secret that the peer is supposed to know */ - if (!get_secret(pcb, name, ourname, (char *)secret, &secret_len, 1)) { - ppp_error("No CHAP secret found for authenticating %q", name); - return 0; - } - ok = digest->verify_response(pcb, id, name, secret, secret_len, challenge, - response, message, message_space); - memset(secret, 0, sizeof(secret)); - - return ok; -} -#endif /* PPP_SERVER */ - -/* - * chap_respond - Generate and send a response to a challenge. - */ -static void chap_respond(ppp_pcb *pcb, int id, - unsigned char *pkt, int len) { - int clen, nlen; - int secret_len; - struct pbuf *p; - u_char *outp; - char rname[MAXNAMELEN+1]; - char secret[MAXSECRETLEN+1]; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(RESP_MAX_PKTLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - if ((pcb->chap_client.flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) - return; /* not ready */ - if (len < 2 || len < pkt[0] + 1) - return; /* too short */ - clen = pkt[0]; - nlen = len - (clen + 1); - - /* Null terminate and clean remote name. */ - ppp_slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); - -#if PPP_REMOTENAME - /* Microsoft doesn't send their name back in the PPP packet */ - if (pcb->settings.explicit_remote || (pcb->settings.remote_name[0] != 0 && rname[0] == 0)) - strlcpy(rname, pcb->settings.remote_name, sizeof(rname)); -#endif /* PPP_REMOTENAME */ - - /* get secret for authenticating ourselves with the specified host */ - if (!get_secret(pcb, pcb->chap_client.name, rname, secret, &secret_len, 0)) { - secret_len = 0; /* assume null secret if can't find one */ - ppp_warn("No CHAP secret found for authenticating us to %q", rname); - } - - outp = (u_char*)p->payload; - MAKEHEADER(outp, PPP_CHAP); - outp += CHAP_HDRLEN; - - pcb->chap_client.digest->make_response(pcb, outp, id, pcb->chap_client.name, pkt, - secret, secret_len, pcb->chap_client.priv); - memset(secret, 0, secret_len); - - clen = *outp; - nlen = strlen(pcb->chap_client.name); - memcpy(outp + clen + 1, pcb->chap_client.name, nlen); - - outp = (u_char*)p->payload + PPP_HDRLEN; - len = CHAP_HDRLEN + clen + 1 + nlen; - outp[0] = CHAP_RESPONSE; - outp[1] = id; - outp[2] = len >> 8; - outp[3] = len; - - pbuf_realloc(p, PPP_HDRLEN + len); - ppp_write(pcb, p); -} - -static void chap_handle_status(ppp_pcb *pcb, int code, int id, - unsigned char *pkt, int len) { - const char *msg = NULL; - LWIP_UNUSED_ARG(id); - - if ((pcb->chap_client.flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) - != (AUTH_STARTED|LOWERUP)) - return; - pcb->chap_client.flags |= AUTH_DONE; - - if (code == CHAP_SUCCESS) { - /* used for MS-CHAP v2 mutual auth, yuck */ - if (pcb->chap_client.digest->check_success != NULL) { - if (!(*pcb->chap_client.digest->check_success)(pcb, pkt, len, pcb->chap_client.priv)) - code = CHAP_FAILURE; - } else - msg = "CHAP authentication succeeded"; - } else { - if (pcb->chap_client.digest->handle_failure != NULL) - (*pcb->chap_client.digest->handle_failure)(pcb, pkt, len); - else - msg = "CHAP authentication failed"; - } - if (msg) { - if (len > 0) - ppp_info("%s: %.*v", msg, len, pkt); - else - ppp_info("%s", msg); - } - if (code == CHAP_SUCCESS) - auth_withpeer_success(pcb, PPP_CHAP, pcb->chap_client.digest->code); - else { - pcb->chap_client.flags |= AUTH_FAILED; - ppp_error("CHAP authentication failed"); - auth_withpeer_fail(pcb, PPP_CHAP); - } -} - -static void chap_input(ppp_pcb *pcb, unsigned char *pkt, int pktlen) { - unsigned char code, id; - int len; - - if (pktlen < CHAP_HDRLEN) - return; - GETCHAR(code, pkt); - GETCHAR(id, pkt); - GETSHORT(len, pkt); - if (len < CHAP_HDRLEN || len > pktlen) - return; - len -= CHAP_HDRLEN; - - switch (code) { - case CHAP_CHALLENGE: - chap_respond(pcb, id, pkt, len); - break; -#if PPP_SERVER - case CHAP_RESPONSE: - chap_handle_response(pcb, id, pkt, len); - break; -#endif /* PPP_SERVER */ - case CHAP_FAILURE: - case CHAP_SUCCESS: - chap_handle_status(pcb, code, id, pkt, len); - break; - default: - break; - } -} - -static void chap_protrej(ppp_pcb *pcb) { - -#if PPP_SERVER - if (pcb->chap_server.flags & TIMEOUT_PENDING) { - pcb->chap_server.flags &= ~TIMEOUT_PENDING; - UNTIMEOUT(chap_timeout, pcb); - } - if (pcb->chap_server.flags & AUTH_STARTED) { - pcb->chap_server.flags = 0; - auth_peer_fail(pcb, PPP_CHAP); - } -#endif /* PPP_SERVER */ - if ((pcb->chap_client.flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { - pcb->chap_client.flags &= ~AUTH_STARTED; - ppp_error("CHAP authentication failed due to protocol-reject"); - auth_withpeer_fail(pcb, PPP_CHAP); - } -} - -#if PRINTPKT_SUPPORT -/* - * chap_print_pkt - print the contents of a CHAP packet. - */ -static const char* const chap_code_names[] = { - "Challenge", "Response", "Success", "Failure" -}; - -static int chap_print_pkt(const unsigned char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len; - int clen, nlen; - unsigned char x; - - if (plen < CHAP_HDRLEN) - return 0; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < CHAP_HDRLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(chap_code_names)) - printer(arg, " %s", chap_code_names[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= CHAP_HDRLEN; - switch (code) { - case CHAP_CHALLENGE: - case CHAP_RESPONSE: - if (len < 1) - break; - clen = p[0]; - if (len < clen + 1) - break; - ++p; - nlen = len - clen - 1; - printer(arg, " <"); - for (; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, "%.2x", x); - } - printer(arg, ">, name = "); - ppp_print_string(p, nlen, printer, arg); - break; - case CHAP_FAILURE: - case CHAP_SUCCESS: - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - break; - default: - for (clen = len; clen > 0; --clen) { - GETCHAR(x, p); - printer(arg, " %.2x", x); - } - /* no break */ - } - - return len + CHAP_HDRLEN; -} -#endif /* PRINTPKT_SUPPORT */ - -const struct protent chap_protent = { - PPP_CHAP, - chap_init, - chap_input, - chap_protrej, - chap_lowerup, - chap_lowerdown, - NULL, /* open */ - NULL, /* close */ -#if PRINTPKT_SUPPORT - chap_print_pkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, /* datainput */ -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "CHAP", /* name */ - NULL, /* data_name */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - chap_option_list, - NULL, /* check_options */ -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -#endif /* PPP_SUPPORT && CHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/chap_ms.c b/components/net/lwip-2.0.2/src/netif/ppp/chap_ms.c deleted file mode 100644 index 5a989c9b7e..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/chap_ms.c +++ /dev/null @@ -1,962 +0,0 @@ -/* - * chap_ms.c - Microsoft MS-CHAP compatible implementation. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 - * - * Implemented LANManager type password response to MS-CHAP challenges. - * Now pppd provides both NT style and LANMan style blocks, and the - * prefered is set by option "ms-lanman". Default is to use NT. - * The hash text (StdText) was taken from Win95 RASAPI32.DLL. - * - * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 - */ - -/* - * Modifications by Frank Cusack, frank@google.com, March 2002. - * - * Implemented MS-CHAPv2 functionality, heavily based on sample - * implementation in RFC 2759. Implemented MPPE functionality, - * heavily based on sample implementation in RFC 3079. - * - * Copyright (c) 2002 Google, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/chap-new.h" -#include "netif/ppp/chap_ms.h" -#include "netif/ppp/pppcrypt.h" -#include "netif/ppp/magic.h" -#if MPPE_SUPPORT -#include "netif/ppp/mppe.h" /* For mppe_sha1_pad*, mppe_set_key() */ -#endif /* MPPE_SUPPORT */ - -#define SHA1_SIGNATURE_SIZE 20 -#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */ -#define MAX_NT_PASSWORD 256 /* Max (Unicode) chars in an NT pass */ - -#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */ -#define MS_CHAP2_RESPONSE_LEN 49 /* Response length for MS-CHAPv2 */ -#define MS_AUTH_RESPONSE_LENGTH 40 /* MS-CHAPv2 authenticator response, */ - /* as ASCII */ - -/* Error codes for MS-CHAP failure messages. */ -#define MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS 646 -#define MS_CHAP_ERROR_ACCT_DISABLED 647 -#define MS_CHAP_ERROR_PASSWD_EXPIRED 648 -#define MS_CHAP_ERROR_NO_DIALIN_PERMISSION 649 -#define MS_CHAP_ERROR_AUTHENTICATION_FAILURE 691 -#define MS_CHAP_ERROR_CHANGING_PASSWORD 709 - -/* - * Offsets within the response field for MS-CHAP - */ -#define MS_CHAP_LANMANRESP 0 -#define MS_CHAP_LANMANRESP_LEN 24 -#define MS_CHAP_NTRESP 24 -#define MS_CHAP_NTRESP_LEN 24 -#define MS_CHAP_USENT 48 - -/* - * Offsets within the response field for MS-CHAP2 - */ -#define MS_CHAP2_PEER_CHALLENGE 0 -#define MS_CHAP2_PEER_CHAL_LEN 16 -#define MS_CHAP2_RESERVED_LEN 8 -#define MS_CHAP2_NTRESP 24 -#define MS_CHAP2_NTRESP_LEN 24 -#define MS_CHAP2_FLAGS 48 - -#if MPPE_SUPPORT -#if 0 /* UNUSED */ -/* These values are the RADIUS attribute values--see RFC 2548. */ -#define MPPE_ENC_POL_ENC_ALLOWED 1 -#define MPPE_ENC_POL_ENC_REQUIRED 2 -#define MPPE_ENC_TYPES_RC4_40 2 -#define MPPE_ENC_TYPES_RC4_128 4 - -/* used by plugins (using above values) */ -extern void set_mppe_enc_types(int, int); -#endif /* UNUSED */ -#endif /* MPPE_SUPPORT */ - -/* Are we the authenticator or authenticatee? For MS-CHAPv2 key derivation. */ -#define MS_CHAP2_AUTHENTICATEE 0 -#define MS_CHAP2_AUTHENTICATOR 1 - -static void ascii2unicode (const char[], int, u_char[]); -static void NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]); -static void ChallengeResponse (const u_char *, const u_char *, u_char[24]); -static void ChallengeHash (const u_char[16], const u_char *, const char *, u_char[8]); -static void ChapMS_NT (const u_char *, const char *, int, u_char[24]); -static void ChapMS2_NT (const u_char *, const u_char[16], const char *, const char *, int, - u_char[24]); -static void GenerateAuthenticatorResponsePlain - (const char*, int, u_char[24], const u_char[16], const u_char *, - const char *, u_char[41]); -#ifdef MSLANMAN -static void ChapMS_LANMan (u_char *, char *, int, u_char *); -#endif - -static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], const u_char PeerChallenge[16], - const u_char *rchallenge, const char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]); - -#if MPPE_SUPPORT -static void Set_Start_Key (ppp_pcb *pcb, const u_char *, const char *, int); -static void SetMasterKeys (ppp_pcb *pcb, const char *, int, u_char[24], int); -#endif /* MPPE_SUPPORT */ - -static void ChapMS (ppp_pcb *pcb, const u_char *, const char *, int, u_char *); -static void ChapMS2 (ppp_pcb *pcb, const u_char *, const u_char *, const char *, const char *, int, - u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int); - -#ifdef MSLANMAN -bool ms_lanman = 0; /* Use LanMan password instead of NT */ - /* Has meaning only with MS-CHAP challenges */ -#endif - -#if MPPE_SUPPORT -#ifdef DEBUGMPPEKEY -/* For MPPE debug */ -/* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */ -static char *mschap_challenge = NULL; -/* Use "!@\#$%^&*()_+:3|~" (sans quotes, backslash is to escape #) for ... */ -static char *mschap2_peer_challenge = NULL; -#endif - -#include "netif/ppp/fsm.h" /* Need to poke MPPE options */ -#include "netif/ppp/ccp.h" -#endif /* MPPE_SUPPORT */ - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t chapms_option_list[] = { -#ifdef MSLANMAN - { "ms-lanman", o_bool, &ms_lanman, - "Use LanMan passwd when using MS-CHAP", 1 }, -#endif -#ifdef DEBUGMPPEKEY - { "mschap-challenge", o_string, &mschap_challenge, - "specify CHAP challenge" }, - { "mschap2-peer-challenge", o_string, &mschap2_peer_challenge, - "specify CHAP peer challenge" }, -#endif - { NULL } -}; -#endif /* PPP_OPTIONS */ - -#if PPP_SERVER -/* - * chapms_generate_challenge - generate a challenge for MS-CHAP. - * For MS-CHAP the challenge length is fixed at 8 bytes. - * The length goes in challenge[0] and the actual challenge starts - * at challenge[1]. - */ -static void chapms_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { - LWIP_UNUSED_ARG(pcb); - - *challenge++ = 8; -#ifdef DEBUGMPPEKEY - if (mschap_challenge && strlen(mschap_challenge) == 8) - memcpy(challenge, mschap_challenge, 8); - else -#endif - magic_random_bytes(challenge, 8); -} - -static void chapms2_generate_challenge(ppp_pcb *pcb, unsigned char *challenge) { - LWIP_UNUSED_ARG(pcb); - - *challenge++ = 16; -#ifdef DEBUGMPPEKEY - if (mschap_challenge && strlen(mschap_challenge) == 16) - memcpy(challenge, mschap_challenge, 16); - else -#endif - magic_random_bytes(challenge, 16); -} - -static int chapms_verify_response(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - unsigned char md[MS_CHAP_RESPONSE_LEN]; - int diff; - int challenge_len, response_len; - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(name); - - challenge_len = *challenge++; /* skip length, is 8 */ - response_len = *response++; - if (response_len != MS_CHAP_RESPONSE_LEN) - goto bad; - -#ifndef MSLANMAN - if (!response[MS_CHAP_USENT]) { - /* Should really propagate this into the error packet. */ - ppp_notice("Peer request for LANMAN auth not supported"); - goto bad; - } -#endif - - /* Generate the expected response. */ - ChapMS(pcb, (const u_char *)challenge, (const char *)secret, secret_len, md); - -#ifdef MSLANMAN - /* Determine which part of response to verify against */ - if (!response[MS_CHAP_USENT]) - diff = memcmp(&response[MS_CHAP_LANMANRESP], - &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN); - else -#endif - diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP], - MS_CHAP_NTRESP_LEN); - - if (diff == 0) { - ppp_slprintf(message, message_space, "Access granted"); - return 1; - } - - bad: - /* See comments below for MS-CHAP V2 */ - ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0", - challenge_len, challenge); - return 0; -} - -static int chapms2_verify_response(ppp_pcb *pcb, int id, const char *name, - const unsigned char *secret, int secret_len, - const unsigned char *challenge, const unsigned char *response, - char *message, int message_space) { - unsigned char md[MS_CHAP2_RESPONSE_LEN]; - char saresponse[MS_AUTH_RESPONSE_LENGTH+1]; - int challenge_len, response_len; - LWIP_UNUSED_ARG(id); - - challenge_len = *challenge++; /* skip length, is 16 */ - response_len = *response++; - if (response_len != MS_CHAP2_RESPONSE_LEN) - goto bad; /* not even the right length */ - - /* Generate the expected response and our mutual auth. */ - ChapMS2(pcb, (const u_char*)challenge, (const u_char*)&response[MS_CHAP2_PEER_CHALLENGE], name, - (const char *)secret, secret_len, md, - (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR); - - /* compare MDs and send the appropriate status */ - /* - * Per RFC 2759, success message must be formatted as - * "S= M=" - * where - * is the Authenticator Response (mutual auth) - * is a text message - * - * However, some versions of Windows (win98 tested) do not know - * about the M= part (required per RFC 2759) and flag - * it as an error (reported incorrectly as an encryption error - * to the user). Since the RFC requires it, and it can be - * useful information, we supply it if the peer is a conforming - * system. Luckily (?), win98 sets the Flags field to 0x04 - * (contrary to RFC requirements) so we can use that to - * distinguish between conforming and non-conforming systems. - * - * Special thanks to Alex Swiridov for - * help debugging this. - */ - if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP], - MS_CHAP2_NTRESP_LEN) == 0) { - if (response[MS_CHAP2_FLAGS]) - ppp_slprintf(message, message_space, "S=%s", saresponse); - else - ppp_slprintf(message, message_space, "S=%s M=%s", - saresponse, "Access granted"); - return 1; - } - - bad: - /* - * Failure message must be formatted as - * "E=e R=r C=c V=v M=m" - * where - * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE) - * r = retry (we use 1, ok to retry) - * c = challenge to use for next response, we reuse previous - * v = Change Password version supported, we use 0 - * m = text message - * - * The M=m part is only for MS-CHAPv2. Neither win2k nor - * win98 (others untested) display the message to the user anyway. - * They also both ignore the E=e code. - * - * Note that it's safe to reuse the same challenge as we don't - * actually accept another response based on the error message - * (and no clients try to resend a response anyway). - * - * Basically, this whole bit is useless code, even the small - * implementation here is only because of overspecification. - */ - ppp_slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s", - challenge_len, challenge, "Access denied"); - return 0; -} -#endif /* PPP_SERVER */ - -static void chapms_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *private_) { - LWIP_UNUSED_ARG(id); - LWIP_UNUSED_ARG(our_name); - LWIP_UNUSED_ARG(private_); - challenge++; /* skip length, should be 8 */ - *response++ = MS_CHAP_RESPONSE_LEN; - ChapMS(pcb, challenge, secret, secret_len, response); -} - -static void chapms2_make_response(ppp_pcb *pcb, unsigned char *response, int id, const char *our_name, - const unsigned char *challenge, const char *secret, int secret_len, - unsigned char *private_) { - LWIP_UNUSED_ARG(id); - challenge++; /* skip length, should be 16 */ - *response++ = MS_CHAP2_RESPONSE_LEN; - ChapMS2(pcb, challenge, -#ifdef DEBUGMPPEKEY - mschap2_peer_challenge, -#else - NULL, -#endif - our_name, secret, secret_len, response, private_, - MS_CHAP2_AUTHENTICATEE); -} - -static int chapms2_check_success(ppp_pcb *pcb, unsigned char *msg, int len, unsigned char *private_) { - LWIP_UNUSED_ARG(pcb); - - if ((len < MS_AUTH_RESPONSE_LENGTH + 2) || - strncmp((char *)msg, "S=", 2) != 0) { - /* Packet does not start with "S=" */ - ppp_error("MS-CHAPv2 Success packet is badly formed."); - return 0; - } - msg += 2; - len -= 2; - if (len < MS_AUTH_RESPONSE_LENGTH - || memcmp(msg, private_, MS_AUTH_RESPONSE_LENGTH)) { - /* Authenticator Response did not match expected. */ - ppp_error("MS-CHAPv2 mutual authentication failed."); - return 0; - } - /* Authenticator Response matches. */ - msg += MS_AUTH_RESPONSE_LENGTH; /* Eat it */ - len -= MS_AUTH_RESPONSE_LENGTH; - if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) { - msg += 3; /* Eat the delimiter */ - } else if (len) { - /* Packet has extra text which does not begin " M=" */ - ppp_error("MS-CHAPv2 Success packet is badly formed."); - return 0; - } - return 1; -} - -static void chapms_handle_failure(ppp_pcb *pcb, unsigned char *inp, int len) { - int err; - const char *p; - char msg[64]; - LWIP_UNUSED_ARG(pcb); - - /* We want a null-terminated string for strxxx(). */ - len = LWIP_MIN(len, 63); - MEMCPY(msg, inp, len); - msg[len] = 0; - p = msg; - - /* - * Deal with MS-CHAP formatted failure messages; just print the - * M= part (if any). For MS-CHAP we're not really supposed - * to use M=, but it shouldn't hurt. See - * chapms[2]_verify_response. - */ - if (!strncmp(p, "E=", 2)) - err = strtol(p+2, NULL, 10); /* Remember the error code. */ - else - goto print_msg; /* Message is badly formatted. */ - - if (len && ((p = strstr(p, " M=")) != NULL)) { - /* M= field found. */ - p += 3; - } else { - /* No M=; use the error code. */ - switch (err) { - case MS_CHAP_ERROR_RESTRICTED_LOGON_HOURS: - p = "E=646 Restricted logon hours"; - break; - - case MS_CHAP_ERROR_ACCT_DISABLED: - p = "E=647 Account disabled"; - break; - - case MS_CHAP_ERROR_PASSWD_EXPIRED: - p = "E=648 Password expired"; - break; - - case MS_CHAP_ERROR_NO_DIALIN_PERMISSION: - p = "E=649 No dialin permission"; - break; - - case MS_CHAP_ERROR_AUTHENTICATION_FAILURE: - p = "E=691 Authentication failure"; - break; - - case MS_CHAP_ERROR_CHANGING_PASSWORD: - /* Should never see this, we don't support Change Password. */ - p = "E=709 Error changing password"; - break; - - default: - ppp_error("Unknown MS-CHAP authentication failure: %.*v", - len, inp); - return; - } - } -print_msg: - if (p != NULL) - ppp_error("MS-CHAP authentication failed: %v", p); -} - -static void ChallengeResponse(const u_char *challenge, - const u_char PasswordHash[MD4_SIGNATURE_SIZE], - u_char response[24]) { - u_char ZPasswordHash[21]; - lwip_des_context des; - u_char des_key[8]; - - BZERO(ZPasswordHash, sizeof(ZPasswordHash)); - MEMCPY(ZPasswordHash, PasswordHash, MD4_SIGNATURE_SIZE); - -#if 0 - dbglog("ChallengeResponse - ZPasswordHash %.*B", - sizeof(ZPasswordHash), ZPasswordHash); -#endif - - pppcrypt_56_to_64_bit_key(ZPasswordHash + 0, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, challenge, response +0); - lwip_des_free(&des); - - pppcrypt_56_to_64_bit_key(ZPasswordHash + 7, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, challenge, response +8); - lwip_des_free(&des); - - pppcrypt_56_to_64_bit_key(ZPasswordHash + 14, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, challenge, response +16); - lwip_des_free(&des); - -#if 0 - dbglog("ChallengeResponse - response %.24B", response); -#endif -} - -static void ChallengeHash(const u_char PeerChallenge[16], const u_char *rchallenge, - const char *username, u_char Challenge[8]) { - lwip_sha1_context sha1Context; - u_char sha1Hash[SHA1_SIGNATURE_SIZE]; - const char *user; - - /* remove domain from "domain\username" */ - if ((user = strrchr(username, '\\')) != NULL) - ++user; - else - user = username; - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PeerChallenge, 16); - lwip_sha1_update(&sha1Context, rchallenge, 16); - lwip_sha1_update(&sha1Context, (const unsigned char*)user, strlen(user)); - lwip_sha1_finish(&sha1Context, sha1Hash); - lwip_sha1_free(&sha1Context); - - MEMCPY(Challenge, sha1Hash, 8); -} - -/* - * Convert the ASCII version of the password to Unicode. - * This implicitly supports 8-bit ISO8859/1 characters. - * This gives us the little-endian representation, which - * is assumed by all M$ CHAP RFCs. (Unicode byte ordering - * is machine-dependent.) - */ -static void ascii2unicode(const char ascii[], int ascii_len, u_char unicode[]) { - int i; - - BZERO(unicode, ascii_len * 2); - for (i = 0; i < ascii_len; i++) - unicode[i * 2] = (u_char) ascii[i]; -} - -static void NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]) { - lwip_md4_context md4Context; - - lwip_md4_init(&md4Context); - lwip_md4_starts(&md4Context); - lwip_md4_update(&md4Context, secret, secret_len); - lwip_md4_finish(&md4Context, hash); - lwip_md4_free(&md4Context); -} - -static void ChapMS_NT(const u_char *rchallenge, const char *secret, int secret_len, - u_char NTResponse[24]) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - - /* Hash the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - - ChallengeResponse(rchallenge, PasswordHash, NTResponse); -} - -static void ChapMS2_NT(const u_char *rchallenge, const u_char PeerChallenge[16], const char *username, - const char *secret, int secret_len, u_char NTResponse[24]) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char Challenge[8]; - - ChallengeHash(PeerChallenge, rchallenge, username, Challenge); - - /* Hash the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - - ChallengeResponse(Challenge, PasswordHash, NTResponse); -} - -#ifdef MSLANMAN -static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */ - -static void ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len, - unsigned char *response) { - int i; - u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */ - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - lwip_des_context des; - u_char des_key[8]; - - /* LANMan password is case insensitive */ - BZERO(UcasePassword, sizeof(UcasePassword)); - for (i = 0; i < secret_len; i++) - UcasePassword[i] = (u_char)toupper(secret[i]); - - pppcrypt_56_to_64_bit_key(UcasePassword +0, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, StdText, PasswordHash +0); - lwip_des_free(&des); - - pppcrypt_56_to_64_bit_key(UcasePassword +7, des_key); - lwip_des_init(&des); - lwip_des_setkey_enc(&des, des_key); - lwip_des_crypt_ecb(&des, StdText, PasswordHash +8); - lwip_des_free(&des); - - ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]); -} -#endif - - -static void GenerateAuthenticatorResponse(const u_char PasswordHashHash[MD4_SIGNATURE_SIZE], - u_char NTResponse[24], const u_char PeerChallenge[16], - const u_char *rchallenge, const char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { - /* - * "Magic" constants used in response generation, from RFC 2759. - */ - static const u_char Magic1[39] = /* "Magic server to client signing constant" */ - { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, - 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; - static const u_char Magic2[41] = /* "Pad to make it do more than one iteration" */ - { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, - 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E }; - - int i; - lwip_sha1_context sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; - u_char Challenge[8]; - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, NTResponse, 24); - lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - ChallengeHash(PeerChallenge, rchallenge, username, Challenge); - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, Digest, sizeof(Digest)); - lwip_sha1_update(&sha1Context, Challenge, sizeof(Challenge)); - lwip_sha1_update(&sha1Context, Magic2, sizeof(Magic2)); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - /* Convert to ASCII hex string. */ - for (i = 0; i < LWIP_MAX((MS_AUTH_RESPONSE_LENGTH / 2), (int)sizeof(Digest)); i++) - sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]); -} - - -static void GenerateAuthenticatorResponsePlain( - const char *secret, int secret_len, - u_char NTResponse[24], const u_char PeerChallenge[16], - const u_char *rchallenge, const char *username, - u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; - - /* Hash (x2) the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash(PasswordHash, sizeof(PasswordHash), - PasswordHashHash); - - GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge, - rchallenge, username, authResponse); -} - - -#if MPPE_SUPPORT -/* - * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) - */ -static void Set_Start_Key(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; - lwip_sha1_context sha1Context; - u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - - /* Hash (x2) the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, rchallenge, 8); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - /* Same key in both directions. */ - mppe_set_key(pcb, &pcb->mppe_comp, Digest); - mppe_set_key(pcb, &pcb->mppe_decomp, Digest); - - pcb->mppe_keys_set = 1; -} - -/* - * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) - */ -static void SetMasterKeys(ppp_pcb *pcb, const char *secret, int secret_len, u_char NTResponse[24], int IsServer) { - u_char unicodePassword[MAX_NT_PASSWORD * 2]; - u_char PasswordHash[MD4_SIGNATURE_SIZE]; - u_char PasswordHashHash[MD4_SIGNATURE_SIZE]; - lwip_sha1_context sha1Context; - u_char MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - u_char Digest[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */ - const u_char *s; - - /* "This is the MPPE Master Key" */ - static const u_char Magic1[27] = - { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; - /* "On the client side, this is the send key; " - "on the server side, it is the receive key." */ - static const u_char Magic2[84] = - { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, - 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, - 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x2e }; - /* "On the client side, this is the receive key; " - "on the server side, it is the send key." */ - static const u_char Magic3[84] = - { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, - 0x6b, 0x65, 0x79, 0x2e }; - - /* Hash (x2) the Unicode version of the secret (== password). */ - ascii2unicode(secret, secret_len, unicodePassword); - NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash); - NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash); - - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE); - lwip_sha1_update(&sha1Context, NTResponse, 24); - lwip_sha1_update(&sha1Context, Magic1, sizeof(Magic1)); - lwip_sha1_finish(&sha1Context, MasterKey); - lwip_sha1_free(&sha1Context); - - /* - * generate send key - */ - if (IsServer) - s = Magic3; - else - s = Magic2; - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, MasterKey, 16); - lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); - lwip_sha1_update(&sha1Context, s, 84); - lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - mppe_set_key(pcb, &pcb->mppe_comp, Digest); - - /* - * generate recv key - */ - if (IsServer) - s = Magic2; - else - s = Magic3; - lwip_sha1_init(&sha1Context); - lwip_sha1_starts(&sha1Context); - lwip_sha1_update(&sha1Context, MasterKey, 16); - lwip_sha1_update(&sha1Context, mppe_sha1_pad1, SHA1_PAD_SIZE); - lwip_sha1_update(&sha1Context, s, 84); - lwip_sha1_update(&sha1Context, mppe_sha1_pad2, SHA1_PAD_SIZE); - lwip_sha1_finish(&sha1Context, Digest); - lwip_sha1_free(&sha1Context); - - mppe_set_key(pcb, &pcb->mppe_decomp, Digest); - - pcb->mppe_keys_set = 1; -} - -#endif /* MPPE_SUPPORT */ - - -static void ChapMS(ppp_pcb *pcb, const u_char *rchallenge, const char *secret, int secret_len, - unsigned char *response) { -#if !MPPE_SUPPORT - LWIP_UNUSED_ARG(pcb); -#endif /* !MPPE_SUPPORT */ - BZERO(response, MS_CHAP_RESPONSE_LEN); - - ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]); - -#ifdef MSLANMAN - ChapMS_LANMan(rchallenge, secret, secret_len, - &response[MS_CHAP_LANMANRESP]); - - /* preferred method is set by option */ - response[MS_CHAP_USENT] = !ms_lanman; -#else - response[MS_CHAP_USENT] = 1; -#endif - -#if MPPE_SUPPORT - Set_Start_Key(pcb, rchallenge, secret, secret_len); -#endif /* MPPE_SUPPORT */ -} - - -/* - * If PeerChallenge is NULL, one is generated and the PeerChallenge - * field of response is filled in. Call this way when generating a response. - * If PeerChallenge is supplied, it is copied into the PeerChallenge field. - * Call this way when verifying a response (or debugging). - * Do not call with PeerChallenge = response. - * - * The PeerChallenge field of response is then used for calculation of the - * Authenticator Response. - */ -static void ChapMS2(ppp_pcb *pcb, const u_char *rchallenge, const u_char *PeerChallenge, - const char *user, const char *secret, int secret_len, unsigned char *response, - u_char authResponse[], int authenticator) { - /* ARGSUSED */ - LWIP_UNUSED_ARG(authenticator); -#if !MPPE_SUPPORT - LWIP_UNUSED_ARG(pcb); -#endif /* !MPPE_SUPPORT */ - - BZERO(response, MS_CHAP2_RESPONSE_LEN); - - /* Generate the Peer-Challenge if requested, or copy it if supplied. */ - if (!PeerChallenge) - magic_random_bytes(&response[MS_CHAP2_PEER_CHALLENGE], MS_CHAP2_PEER_CHAL_LEN); - else - MEMCPY(&response[MS_CHAP2_PEER_CHALLENGE], PeerChallenge, - MS_CHAP2_PEER_CHAL_LEN); - - /* Generate the NT-Response */ - ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user, - secret, secret_len, &response[MS_CHAP2_NTRESP]); - - /* Generate the Authenticator Response. */ - GenerateAuthenticatorResponsePlain(secret, secret_len, - &response[MS_CHAP2_NTRESP], - &response[MS_CHAP2_PEER_CHALLENGE], - rchallenge, user, authResponse); - -#if MPPE_SUPPORT - SetMasterKeys(pcb, secret, secret_len, - &response[MS_CHAP2_NTRESP], authenticator); -#endif /* MPPE_SUPPORT */ -} - -#if 0 /* UNUSED */ -#if MPPE_SUPPORT -/* - * Set MPPE options from plugins. - */ -void set_mppe_enc_types(int policy, int types) { - /* Early exit for unknown policies. */ - if (policy != MPPE_ENC_POL_ENC_ALLOWED || - policy != MPPE_ENC_POL_ENC_REQUIRED) - return; - - /* Don't modify MPPE if it's optional and wasn't already configured. */ - if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe) - return; - - /* - * Disable undesirable encryption types. Note that we don't ENABLE - * any encryption types, to avoid overriding manual configuration. - */ - switch(types) { - case MPPE_ENC_TYPES_RC4_40: - ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */ - break; - case MPPE_ENC_TYPES_RC4_128: - ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */ - break; - default: - break; - } -} -#endif /* MPPE_SUPPORT */ -#endif /* UNUSED */ - -const struct chap_digest_type chapms_digest = { - CHAP_MICROSOFT, /* code */ -#if PPP_SERVER - chapms_generate_challenge, - chapms_verify_response, -#endif /* PPP_SERVER */ - chapms_make_response, - NULL, /* check_success */ - chapms_handle_failure, -}; - -const struct chap_digest_type chapms2_digest = { - CHAP_MICROSOFT_V2, /* code */ -#if PPP_SERVER - chapms2_generate_challenge, - chapms2_verify_response, -#endif /* PPP_SERVER */ - chapms2_make_response, - chapms2_check_success, - chapms_handle_failure, -}; - -#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/demand.c b/components/net/lwip-2.0.2/src/netif/ppp/demand.c deleted file mode 100644 index 26c6c30db1..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/demand.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * demand.c - Support routines for demand-dialling. - * - * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef PPP_FILTER -#include -#endif - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/lcp.h" - -char *frame; -int framelen; -int framemax; -int escape_flag; -int flush_flag; -int fcs; - -struct packet { - int length; - struct packet *next; - unsigned char data[1]; -}; - -struct packet *pend_q; -struct packet *pend_qtail; - -static int active_packet (unsigned char *, int); - -/* - * demand_conf - configure the interface for doing dial-on-demand. - */ -void -demand_conf() -{ - int i; - const struct protent *protp; - -/* framemax = lcp_allowoptions[0].mru; - if (framemax < PPP_MRU) */ - framemax = PPP_MRU; - framemax += PPP_HDRLEN + PPP_FCSLEN; - frame = malloc(framemax); - if (frame == NULL) - novm("demand frame"); - framelen = 0; - pend_q = NULL; - escape_flag = 0; - flush_flag = 0; - fcs = PPP_INITFCS; - - netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); - if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 - || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) - fatal("Couldn't set up demand-dialled PPP interface: %m"); - -#ifdef PPP_FILTER - set_filters(&pass_filter, &active_filter); -#endif - - /* - * Call the demand_conf procedure for each protocol that's got one. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - ((*protp->demand_conf)(pcb)); -/* FIXME: find a way to die() here */ -#if 0 - if (!((*protp->demand_conf)(pcb))) - die(1); -#endif -} - - -/* - * demand_block - set each network protocol to block further packets. - */ -void -demand_block() -{ - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); - get_loop_output(); -} - -/* - * demand_discard - set each network protocol to discard packets - * with an error. - */ -void -demand_discard() -{ - struct packet *pkt, *nextpkt; - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); - get_loop_output(); - - /* discard all saved packets */ - for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { - nextpkt = pkt->next; - free(pkt); - } - pend_q = NULL; - framelen = 0; - flush_flag = 0; - escape_flag = 0; - fcs = PPP_INITFCS; -} - -/* - * demand_unblock - set each enabled network protocol to pass packets. - */ -void -demand_unblock() -{ - int i; - const struct protent *protp; - - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->demand_conf != NULL) - sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); -} - -/* - * FCS lookup table as calculated by genfcstab. - */ -static u_short fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -/* - * loop_chars - process characters received from the loopback. - * Calls loop_frame when a complete frame has been accumulated. - * Return value is 1 if we need to bring up the link, 0 otherwise. - */ -int -loop_chars(p, n) - unsigned char *p; - int n; -{ - int c, rv; - - rv = 0; - -/* check for synchronous connection... */ - - if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { - rv = loop_frame(p,n); - return rv; - } - - for (; n > 0; --n) { - c = *p++; - if (c == PPP_FLAG) { - if (!escape_flag && !flush_flag - && framelen > 2 && fcs == PPP_GOODFCS) { - framelen -= 2; - if (loop_frame((unsigned char *)frame, framelen)) - rv = 1; - } - framelen = 0; - flush_flag = 0; - escape_flag = 0; - fcs = PPP_INITFCS; - continue; - } - if (flush_flag) - continue; - if (escape_flag) { - c ^= PPP_TRANS; - escape_flag = 0; - } else if (c == PPP_ESCAPE) { - escape_flag = 1; - continue; - } - if (framelen >= framemax) { - flush_flag = 1; - continue; - } - frame[framelen++] = c; - fcs = PPP_FCS(fcs, c); - } - return rv; -} - -/* - * loop_frame - given a frame obtained from the loopback, - * decide whether to bring up the link or not, and, if we want - * to transmit this frame later, put it on the pending queue. - * Return value is 1 if we need to bring up the link, 0 otherwise. - * We assume that the kernel driver has already applied the - * pass_filter, so we won't get packets it rejected. - * We apply the active_filter to see if we want this packet to - * bring up the link. - */ -int -loop_frame(frame, len) - unsigned char *frame; - int len; -{ - struct packet *pkt; - - /* dbglog("from loop: %P", frame, len); */ - if (len < PPP_HDRLEN) - return 0; - if ((PPP_PROTOCOL(frame) & 0x8000) != 0) - return 0; /* shouldn't get any of these anyway */ - if (!active_packet(frame, len)) - return 0; - - pkt = (struct packet *) malloc(sizeof(struct packet) + len); - if (pkt != NULL) { - pkt->length = len; - pkt->next = NULL; - memcpy(pkt->data, frame, len); - if (pend_q == NULL) - pend_q = pkt; - else - pend_qtail->next = pkt; - pend_qtail = pkt; - } - return 1; -} - -/* - * demand_rexmit - Resend all those frames which we got via the - * loopback, now that the real serial link is up. - */ -void -demand_rexmit(proto, newip) - int proto; - u32_t newip; -{ - struct packet *pkt, *prev, *nextpkt; - unsigned short checksum; - unsigned short pkt_checksum = 0; - unsigned iphdr; - struct timeval tv; - char cv = 0; - char ipstr[16]; - - prev = NULL; - pkt = pend_q; - pend_q = NULL; - tv.tv_sec = 1; - tv.tv_usec = 0; - select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ - for (; pkt != NULL; pkt = nextpkt) { - nextpkt = pkt->next; - if (PPP_PROTOCOL(pkt->data) == proto) { - if ( (proto == PPP_IP) && newip ) { - /* Get old checksum */ - - iphdr = (pkt->data[4] & 15) << 2; - checksum = *((unsigned short *) (pkt->data+14)); - if (checksum == 0xFFFF) { - checksum = 0; - } - - - if (pkt->data[13] == 17) { - pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); - if (pkt_checksum) { - cv = 1; - if (pkt_checksum == 0xFFFF) { - pkt_checksum = 0; - } - } - else { - cv = 0; - } - } - - if (pkt->data[13] == 6) { - pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); - cv = 1; - if (pkt_checksum == 0xFFFF) { - pkt_checksum = 0; - } - } - - /* Delete old Source-IP-Address */ - checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - /* Change Source-IP-Address */ - * ((u32_t *) (pkt->data + 16)) = newip; - - /* Add new Source-IP-Address */ - checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; - pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; - - /* Write new checksum */ - if (!checksum) { - checksum = 0xFFFF; - } - *((unsigned short *) (pkt->data+14)) = checksum; - if (pkt->data[13] == 6) { - *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; - } - if (cv && (pkt->data[13] == 17) ) { - *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; - } - - /* Log Packet */ - strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); - if (pkt->data[13] == 1) { - syslog(LOG_INFO,"Open ICMP %s -> %s\n", - ipstr, - inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); - } else { - syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", - pkt->data[13] == 6 ? "TCP" : "UDP", - ipstr, - ntohs(*( (short *) (pkt->data+iphdr+4))), - inet_ntoa(*( (struct in_addr *) (pkt->data+20))), - ntohs(*( (short *) (pkt->data+iphdr+6)))); - } - } - output(pcb, pkt->data, pkt->length); - free(pkt); - } else { - if (prev == NULL) - pend_q = pkt; - else - prev->next = pkt; - prev = pkt; - } - } - pend_qtail = prev; - if (prev != NULL) - prev->next = NULL; -} - -/* - * Scan a packet to decide whether it is an "active" packet, - * that is, whether it is worth bringing up the link for. - */ -static int -active_packet(p, len) - unsigned char *p; - int len; -{ - int proto, i; - const struct protent *protp; - - if (len < PPP_HDRLEN) - return 0; - proto = PPP_PROTOCOL(p); -#ifdef PPP_FILTER - p[0] = 1; /* outbound packet indicator */ - if ((pass_filter.bf_len != 0 - && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) - || (active_filter.bf_len != 0 - && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { - p[0] = 0xff; - return 0; - } - p[0] = 0xff; -#endif - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { - if (protp->active_pkt == NULL) - return 1; - return (*protp->active_pkt)(p, len); - } - } - return 0; /* not a supported protocol !!?? */ -} - -#endif /* PPP_SUPPORT && DEMAND_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/eap.c b/components/net/lwip-2.0.2/src/netif/ppp/eap.c deleted file mode 100644 index 8fb56368e7..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/eap.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * eap.c - Extensible Authentication Protocol for PPP (RFC 2284) - * - * Copyright (c) 2001 by Sun Microsystems, Inc. - * All rights reserved. - * - * Non-exclusive rights to redistribute, modify, translate, and use - * this software in source and binary forms, in whole or in part, is - * hereby granted, provided that the above copyright notice is - * duplicated in any source form, and that neither the name of the - * copyright holder nor the author is used to endorse or promote - * products derived from this software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Original version by James Carlson - * - * This implementation of EAP supports MD5-Challenge and SRP-SHA1 - * authentication styles. Note that support of MD5-Challenge is a - * requirement of RFC 2284, and that it's essentially just a - * reimplementation of regular RFC 1994 CHAP using EAP messages. - * - * As an authenticator ("server"), there are multiple phases for each - * style. In the first phase of each style, the unauthenticated peer - * name is queried using the EAP Identity request type. If the - * "remotename" option is used, then this phase is skipped, because - * the peer's name is presumed to be known. - * - * For MD5-Challenge, there are two phases, and the second phase - * consists of sending the challenge itself and handling the - * associated response. - * - * For SRP-SHA1, there are four phases. The second sends 's', 'N', - * and 'g'. The reply contains 'A'. The third sends 'B', and the - * reply contains 'M1'. The forth sends the 'M2' value. - * - * As an authenticatee ("client"), there's just a single phase -- - * responding to the queries generated by the peer. EAP is an - * authenticator-driven protocol. - * - * Based on draft-ietf-pppext-eap-srp-03.txt. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && EAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/eap.h" -#include "netif/ppp/magic.h" -#include "netif/ppp/pppcrypt.h" - -#ifdef USE_SRP -#include -#include -#include -#endif /* USE_SRP */ - -#ifndef SHA_DIGESTSIZE -#define SHA_DIGESTSIZE 20 -#endif - -#ifdef USE_SRP -static char *pn_secret = NULL; /* Pseudonym generating secret */ -#endif - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t eap_option_list[] = { - { "eap-restart", o_int, &eap_states[0].es_server.ea_timeout, - "Set retransmit timeout for EAP Requests (server)" }, - { "eap-max-sreq", o_int, &eap_states[0].es_server.ea_maxrequests, - "Set max number of EAP Requests sent (server)" }, - { "eap-timeout", o_int, &eap_states[0].es_client.ea_timeout, - "Set time limit for peer EAP authentication" }, - { "eap-max-rreq", o_int, &eap_states[0].es_client.ea_maxrequests, - "Set max number of EAP Requests allows (client)" }, - { "eap-interval", o_int, &eap_states[0].es_rechallenge, - "Set interval for EAP rechallenge" }, -#ifdef USE_SRP - { "srp-interval", o_int, &eap_states[0].es_lwrechallenge, - "Set interval for SRP lightweight rechallenge" }, - { "srp-pn-secret", o_string, &pn_secret, - "Long term pseudonym generation secret" }, - { "srp-use-pseudonym", o_bool, &eap_states[0].es_usepseudo, - "Use pseudonym if offered one by server", 1 }, -#endif - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points. - */ -static void eap_init(ppp_pcb *pcb); -static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen); -static void eap_protrej(ppp_pcb *pcb); -static void eap_lowerup(ppp_pcb *pcb); -static void eap_lowerdown(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int eap_printpkt(const u_char *inp, int inlen, - void (*)(void *arg, const char *fmt, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -const struct protent eap_protent = { - PPP_EAP, /* protocol number */ - eap_init, /* initialization procedure */ - eap_input, /* process a received packet */ - eap_protrej, /* process a received protocol-reject */ - eap_lowerup, /* lower layer has gone up */ - eap_lowerdown, /* lower layer has gone down */ - NULL, /* open the protocol */ - NULL, /* close the protocol */ -#if PRINTPKT_SUPPORT - eap_printpkt, /* print a packet in readable form */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, /* process a received data packet */ -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "EAP", /* text name of protocol */ - NULL, /* text name of corresponding data protocol */ -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - eap_option_list, /* list of command-line options */ - NULL, /* check requested options; assign defaults */ -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, /* configure interface for demand-dial */ - NULL /* say whether to bring up link for this pkt */ -#endif /* DEMAND_SUPPORT */ -}; - -#ifdef USE_SRP -/* - * A well-known 2048 bit modulus. - */ -static const u_char wkmodulus[] = { - 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, - 0xF1, 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, - 0xAF, 0x72, 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, - 0xFC, 0x31, 0x92, 0x94, 0x3D, 0xB5, 0x60, 0x50, - 0xA3, 0x73, 0x29, 0xCB, 0xB4, 0xA0, 0x99, 0xED, - 0x81, 0x93, 0xE0, 0x75, 0x77, 0x67, 0xA1, 0x3D, - 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, 0x31, 0x0D, - 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, 0x50, - 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, - 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, - 0x66, 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, - 0x29, 0x18, 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, - 0x55, 0xF9, 0x79, 0x93, 0xEC, 0x97, 0x5E, 0xEA, - 0xA8, 0x0D, 0x74, 0x0A, 0xDB, 0xF4, 0xFF, 0x74, - 0x73, 0x59, 0xD0, 0x41, 0xD5, 0xC3, 0x3E, 0xA7, - 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, 0x77, 0x3B, - 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, 0x16, - 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, - 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, - 0x5B, 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, - 0x54, 0x45, 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, - 0x5E, 0xA7, 0x7A, 0x27, 0x75, 0xD2, 0xEC, 0xFA, - 0x03, 0x2C, 0xFB, 0xDB, 0xF5, 0x2F, 0xB3, 0x78, - 0x61, 0x60, 0x27, 0x90, 0x04, 0xE5, 0x7A, 0xE6, - 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, 0x53, 0x29, - 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, 0xD8, - 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, - 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, - 0x94, 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, - 0x35, 0xDE, 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, - 0x9B, 0x65, 0xE3, 0x72, 0xFC, 0xD6, 0x8E, 0xF2, - 0x0F, 0xA7, 0x11, 0x1F, 0x9E, 0x4A, 0xFF, 0x73 -}; -#endif - -#if PPP_SERVER -/* Local forward declarations. */ -static void eap_server_timeout(void *arg); -#endif /* PPP_SERVER */ - -/* - * Convert EAP state code to printable string for debug. - */ -static const char * eap_state_name(enum eap_state_code esc) -{ - static const char *state_names[] = { EAP_STATES }; - - return (state_names[(int)esc]); -} - -/* - * eap_init - Initialize state for an EAP user. This is currently - * called once by main() during start-up. - */ -static void eap_init(ppp_pcb *pcb) { - - BZERO(&pcb->eap, sizeof(eap_state)); -#if PPP_SERVER - pcb->eap.es_server.ea_id = magic(); -#endif /* PPP_SERVER */ -} - -/* - * eap_client_timeout - Give up waiting for the peer to send any - * Request messages. - */ -static void eap_client_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (!eap_client_active(pcb)) - return; - - ppp_error("EAP: timeout waiting for Request from peer"); - auth_withpeer_fail(pcb, PPP_EAP); - pcb->eap.es_client.ea_state = eapBadAuth; -} - -/* - * eap_authwithpeer - Authenticate to our peer (behave as client). - * - * Start client state and wait for requests. This is called only - * after eap_lowerup. - */ -void eap_authwithpeer(ppp_pcb *pcb, const char *localname) { - - if(NULL == localname) - return; - - /* Save the peer name we're given */ - pcb->eap.es_client.ea_name = localname; - pcb->eap.es_client.ea_namelen = strlen(localname); - - pcb->eap.es_client.ea_state = eapListen; - - /* - * Start a timer so that if the other end just goes - * silent, we don't sit here waiting forever. - */ - if (pcb->settings.eap_req_time > 0) - TIMEOUT(eap_client_timeout, pcb, - pcb->settings.eap_req_time); -} - -#if PPP_SERVER -/* - * Format a standard EAP Failure message and send it to the peer. - * (Server operation) - */ -static void eap_send_failure(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_FAILURE, outp); - pcb->eap.es_server.ea_id++; - PUTCHAR(pcb->eap.es_server.ea_id, outp); - PUTSHORT(EAP_HEADERLEN, outp); - - ppp_write(pcb, p); - - pcb->eap.es_server.ea_state = eapBadAuth; - auth_peer_fail(pcb, PPP_EAP); -} - -/* - * Format a standard EAP Success message and send it to the peer. - * (Server operation) - */ -static void eap_send_success(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + EAP_HEADERLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_SUCCESS, outp); - pcb->eap.es_server.ea_id++; - PUTCHAR(pcb->eap.es_server.ea_id, outp); - PUTSHORT(EAP_HEADERLEN, outp); - - ppp_write(pcb, p); - - auth_peer_success(pcb, PPP_EAP, 0, - pcb->eap.es_server.ea_peer, pcb->eap.es_server.ea_peerlen); -} -#endif /* PPP_SERVER */ - -#ifdef USE_SRP -/* - * Set DES key according to pseudonym-generating secret and current - * date. - */ -static bool -pncrypt_setkey(int timeoffs) -{ - struct tm *tp; - char tbuf[9]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - time_t reftime; - - if (pn_secret == NULL) - return (0); - reftime = time(NULL) + timeoffs; - tp = localtime(&reftime); - SHA1Init(&ctxt); - SHA1Update(&ctxt, pn_secret, strlen(pn_secret)); - strftime(tbuf, sizeof (tbuf), "%Y%m%d", tp); - SHA1Update(&ctxt, tbuf, strlen(tbuf)); - SHA1Final(dig, &ctxt); - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - return (DesSetkey(dig)); -} - -static char base64[] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -struct b64state { - u32_t bs_bits; - int bs_offs; -}; - -static int -b64enc(bs, inp, inlen, outp) -struct b64state *bs; -u_char *inp; -int inlen; -u_char *outp; -{ - int outlen = 0; - - while (inlen > 0) { - bs->bs_bits = (bs->bs_bits << 8) | *inp++; - inlen--; - bs->bs_offs += 8; - if (bs->bs_offs >= 24) { - *outp++ = base64[(bs->bs_bits >> 18) & 0x3F]; - *outp++ = base64[(bs->bs_bits >> 12) & 0x3F]; - *outp++ = base64[(bs->bs_bits >> 6) & 0x3F]; - *outp++ = base64[bs->bs_bits & 0x3F]; - outlen += 4; - bs->bs_offs = 0; - bs->bs_bits = 0; - } - } - return (outlen); -} - -static int -b64flush(bs, outp) -struct b64state *bs; -u_char *outp; -{ - int outlen = 0; - - if (bs->bs_offs == 8) { - *outp++ = base64[(bs->bs_bits >> 2) & 0x3F]; - *outp++ = base64[(bs->bs_bits << 4) & 0x3F]; - outlen = 2; - } else if (bs->bs_offs == 16) { - *outp++ = base64[(bs->bs_bits >> 10) & 0x3F]; - *outp++ = base64[(bs->bs_bits >> 4) & 0x3F]; - *outp++ = base64[(bs->bs_bits << 2) & 0x3F]; - outlen = 3; - } - bs->bs_offs = 0; - bs->bs_bits = 0; - return (outlen); -} - -static int -b64dec(bs, inp, inlen, outp) -struct b64state *bs; -u_char *inp; -int inlen; -u_char *outp; -{ - int outlen = 0; - char *cp; - - while (inlen > 0) { - if ((cp = strchr(base64, *inp++)) == NULL) - break; - bs->bs_bits = (bs->bs_bits << 6) | (cp - base64); - inlen--; - bs->bs_offs += 6; - if (bs->bs_offs >= 8) { - *outp++ = bs->bs_bits >> (bs->bs_offs - 8); - outlen++; - bs->bs_offs -= 8; - } - } - return (outlen); -} -#endif /* USE_SRP */ - -#if PPP_SERVER -/* - * Assume that current waiting server state is complete and figure - * next state to use based on available authentication data. 'status' - * indicates if there was an error in handling the last query. It is - * 0 for success and non-zero for failure. - */ -static void eap_figure_next_state(ppp_pcb *pcb, int status) { -#ifdef USE_SRP - unsigned char secbuf[MAXSECRETLEN], clear[8], *sp, *dp; - struct t_pw tpw; - struct t_confent *tce, mytce; - char *cp, *cp2; - struct t_server *ts; - int id, i, plen, toffs; - u_char vals[2]; - struct b64state bs; -#endif /* USE_SRP */ - - pcb->settings.eap_timeout_time = pcb->eap.es_savedtime; - switch (pcb->eap.es_server.ea_state) { - case eapBadAuth: - return; - - case eapIdentify: -#ifdef USE_SRP - /* Discard any previous session. */ - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status != 0) { - pcb->eap.es_server.ea_state = eapBadAuth; - break; - } -#ifdef USE_SRP - /* If we've got a pseudonym, try to decode to real name. */ - if (pcb->eap.es_server.ea_peerlen > SRP_PSEUDO_LEN && - strncmp(pcb->eap.es_server.ea_peer, SRP_PSEUDO_ID, - SRP_PSEUDO_LEN) == 0 && - (pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN) * 3 / 4 < - sizeof (secbuf)) { - BZERO(&bs, sizeof (bs)); - plen = b64dec(&bs, - pcb->eap.es_server.ea_peer + SRP_PSEUDO_LEN, - pcb->eap.es_server.ea_peerlen - SRP_PSEUDO_LEN, - secbuf); - toffs = 0; - for (i = 0; i < 5; i++) { - pncrypt_setkey(toffs); - toffs -= 86400; - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - if (!DesDecrypt(secbuf, clear)) { - ppp_dbglog("no DES here; cannot decode " - "pseudonym"); - return; - } - id = *(unsigned char *)clear; - if (id + 1 <= plen && id + 9 > plen) - break; - } - if (plen % 8 == 0 && i < 5) { - /* - * Note that this is always shorter than the - * original stored string, so there's no need - * to realloc. - */ - if ((i = plen = *(unsigned char *)clear) > 7) - i = 7; - pcb->eap.es_server.ea_peerlen = plen; - dp = (unsigned char *)pcb->eap.es_server.ea_peer; - MEMCPY(dp, clear + 1, i); - plen -= i; - dp += i; - sp = secbuf + 8; - while (plen > 0) { - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - (void) DesDecrypt(sp, dp); - sp += 8; - dp += 8; - plen -= 8; - } - pcb->eap.es_server.ea_peer[ - pcb->eap.es_server.ea_peerlen] = '\0'; - ppp_dbglog("decoded pseudonym to \"%.*q\"", - pcb->eap.es_server.ea_peerlen, - pcb->eap.es_server.ea_peer); - } else { - ppp_dbglog("failed to decode real name"); - /* Stay in eapIdentfy state; requery */ - break; - } - } - /* Look up user in secrets database. */ - if (get_srp_secret(pcb->eap.es_unit, pcb->eap.es_server.ea_peer, - pcb->eap.es_server.ea_name, (char *)secbuf, 1) != 0) { - /* Set up default in case SRP entry is bad */ - pcb->eap.es_server.ea_state = eapMD5Chall; - /* Get t_confent based on index in srp-secrets */ - id = strtol((char *)secbuf, &cp, 10); - if (*cp++ != ':' || id < 0) - break; - if (id == 0) { - mytce.index = 0; - mytce.modulus.data = (u_char *)wkmodulus; - mytce.modulus.len = sizeof (wkmodulus); - mytce.generator.data = (u_char *)"\002"; - mytce.generator.len = 1; - tce = &mytce; - } else if ((tce = gettcid(id)) != NULL) { - /* - * Client will have to verify this modulus/ - * generator combination, and that will take - * a while. Lengthen the timeout here. - */ - if (pcb->settings.eap_timeout_time > 0 && - pcb->settings.eap_timeout_time < 30) - pcb->settings.eap_timeout_time = 30; - } else { - break; - } - if ((cp2 = strchr(cp, ':')) == NULL) - break; - *cp2++ = '\0'; - tpw.pebuf.name = pcb->eap.es_server.ea_peer; - tpw.pebuf.password.len = t_fromb64((char *)tpw.pwbuf, - cp); - tpw.pebuf.password.data = tpw.pwbuf; - tpw.pebuf.salt.len = t_fromb64((char *)tpw.saltbuf, - cp2); - tpw.pebuf.salt.data = tpw.saltbuf; - if ((ts = t_serveropenraw(&tpw.pebuf, tce)) == NULL) - break; - pcb->eap.es_server.ea_session = (void *)ts; - pcb->eap.es_server.ea_state = eapSRP1; - vals[0] = pcb->eap.es_server.ea_id + 1; - vals[1] = EAPT_SRP; - t_serveraddexdata(ts, vals, 2); - /* Generate B; must call before t_servergetkey() */ - t_servergenexp(ts); - break; - } -#endif /* USE_SRP */ - pcb->eap.es_server.ea_state = eapMD5Chall; - break; - - case eapSRP1: -#ifdef USE_SRP - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL && status != 0) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status == 1) { - pcb->eap.es_server.ea_state = eapMD5Chall; - } else if (status != 0 || pcb->eap.es_server.ea_session == NULL) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapSRP2; - } - break; - - case eapSRP2: -#ifdef USE_SRP - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL && status != 0) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status != 0 || pcb->eap.es_server.ea_session == NULL) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapSRP3; - } - break; - - case eapSRP3: - case eapSRP4: -#ifdef USE_SRP - ts = (struct t_server *)pcb->eap.es_server.ea_session; - if (ts != NULL && status != 0) { - t_serverclose(ts); - pcb->eap.es_server.ea_session = NULL; - pcb->eap.es_server.ea_skey = NULL; - } -#endif /* USE_SRP */ - if (status != 0 || pcb->eap.es_server.ea_session == NULL) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapOpen; - } - break; - - case eapMD5Chall: - if (status != 0) { - pcb->eap.es_server.ea_state = eapBadAuth; - } else { - pcb->eap.es_server.ea_state = eapOpen; - } - break; - - default: - pcb->eap.es_server.ea_state = eapBadAuth; - break; - } - if (pcb->eap.es_server.ea_state == eapBadAuth) - eap_send_failure(pcb); -} - -/* - * Format an EAP Request message and send it to the peer. Message - * type depends on current state. (Server operation) - */ -static void eap_send_request(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - u_char *lenloc; - int outlen; - int len; - const char *str; -#ifdef USE_SRP - struct t_server *ts; - u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; - int i, j; - struct b64state b64; - SHA1_CTX ctxt; -#endif /* USE_SRP */ - - /* Handle both initial auth and restart */ - if (pcb->eap.es_server.ea_state < eapIdentify && - pcb->eap.es_server.ea_state != eapInitial) { - pcb->eap.es_server.ea_state = eapIdentify; -#if PPP_REMOTENAME - if (pcb->settings.explicit_remote && pcb->remote_name) { - /* - * If we already know the peer's - * unauthenticated name, then there's no - * reason to ask. Go to next state instead. - */ - int len = (int)strlen(pcb->remote_name); - if (len > MAXNAMELEN) { - len = MAXNAMELEN; - } - MEMCPY(pcb->eap.es_server.ea_peer, pcb->remote_name, len); - pcb->eap.es_server.ea_peer[len] = '\0'; - pcb->eap.es_server.ea_peerlen = len; - eap_figure_next_state(pcb, 0); - } -#endif /* PPP_REMOTENAME */ - } - - if (pcb->settings.eap_max_transmits > 0 && - pcb->eap.es_server.ea_requests >= pcb->settings.eap_max_transmits) { - if (pcb->eap.es_server.ea_responses > 0) - ppp_error("EAP: too many Requests sent"); - else - ppp_error("EAP: no response to Requests"); - eap_send_failure(pcb); - return; - } - - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_REQUEST, outp); - PUTCHAR(pcb->eap.es_server.ea_id, outp); - lenloc = outp; - INCPTR(2, outp); - - switch (pcb->eap.es_server.ea_state) { - case eapIdentify: - PUTCHAR(EAPT_IDENTITY, outp); - str = "Name"; - len = strlen(str); - MEMCPY(outp, str, len); - INCPTR(len, outp); - break; - - case eapMD5Chall: - PUTCHAR(EAPT_MD5CHAP, outp); - /* - * pick a random challenge length between - * EAP_MIN_CHALLENGE_LENGTH and EAP_MAX_CHALLENGE_LENGTH - */ - pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + - magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); - PUTCHAR(pcb->eap.es_challen, outp); - magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); - MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); - INCPTR(pcb->eap.es_challen, outp); - MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); - INCPTR(pcb->eap.es_server.ea_namelen, outp); - break; - -#ifdef USE_SRP - case eapSRP1: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_CHALLENGE, outp); - - PUTCHAR(pcb->eap.es_server.ea_namelen, outp); - MEMCPY(outp, pcb->eap.es_server.ea_name, pcb->eap.es_server.ea_namelen); - INCPTR(pcb->eap.es_server.ea_namelen, outp); - - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - PUTCHAR(ts->s.len, outp); - MEMCPY(outp, ts->s.data, ts->s.len); - INCPTR(ts->s.len, outp); - - if (ts->g.len == 1 && ts->g.data[0] == 2) { - PUTCHAR(0, outp); - } else { - PUTCHAR(ts->g.len, outp); - MEMCPY(outp, ts->g.data, ts->g.len); - INCPTR(ts->g.len, outp); - } - - if (ts->n.len != sizeof (wkmodulus) || - BCMP(ts->n.data, wkmodulus, sizeof (wkmodulus)) != 0) { - MEMCPY(outp, ts->n.data, ts->n.len); - INCPTR(ts->n.len, outp); - } - break; - - case eapSRP2: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_SKEY, outp); - - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - MEMCPY(outp, ts->B.data, ts->B.len); - INCPTR(ts->B.len, outp); - break; - - case eapSRP3: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_SVALIDATOR, outp); - PUTLONG(SRPVAL_EBIT, outp); - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - MEMCPY(outp, t_serverresponse(ts), SHA_DIGESTSIZE); - INCPTR(SHA_DIGESTSIZE, outp); - - if (pncrypt_setkey(0)) { - /* Generate pseudonym */ - optr = outp; - cp = (unsigned char *)pcb->eap.es_server.ea_peer; - if ((j = i = pcb->eap.es_server.ea_peerlen) > 7) - j = 7; - clear[0] = i; - MEMCPY(clear + 1, cp, j); - i -= j; - cp += j; - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - if (!DesEncrypt(clear, cipher)) { - ppp_dbglog("no DES here; not generating pseudonym"); - break; - } - BZERO(&b64, sizeof (b64)); - outp++; /* space for pseudonym length */ - outp += b64enc(&b64, cipher, 8, outp); - while (i >= 8) { - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - (void) DesEncrypt(cp, cipher); - outp += b64enc(&b64, cipher, 8, outp); - cp += 8; - i -= 8; - } - if (i > 0) { - MEMCPY(clear, cp, i); - cp += i; - magic_random_bytes(cp, 8-i); - /* FIXME: if we want to do SRP, we need to find a way to pass the PolarSSL des_context instead of using static memory */ - (void) DesEncrypt(clear, cipher); - outp += b64enc(&b64, cipher, 8, outp); - } - outp += b64flush(&b64, outp); - - /* Set length and pad out to next 20 octet boundary */ - i = outp - optr - 1; - *optr = i; - i %= SHA_DIGESTSIZE; - if (i != 0) { - magic_random_bytes(outp, SHA_DIGESTSIZE-i); - INCPTR(SHA_DIGESTSIZE-i, outp); - } - - /* Obscure the pseudonym with SHA1 hash */ - SHA1Init(&ctxt); - SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); - SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, - pcb->eap.es_server.ea_peerlen); - while (optr < outp) { - SHA1Final(dig, &ctxt); - cp = dig; - while (cp < dig + SHA_DIGESTSIZE) - *optr++ ^= *cp++; - SHA1Init(&ctxt); - SHA1Update(&ctxt, &pcb->eap.es_server.ea_id, 1); - SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, optr - SHA_DIGESTSIZE, - SHA_DIGESTSIZE); - } - } - break; - - case eapSRP4: - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_LWRECHALLENGE, outp); - pcb->eap.es_challen = EAP_MIN_CHALLENGE_LENGTH + - magic_pow(EAP_MIN_MAX_POWER_OF_TWO_CHALLENGE_LENGTH); - magic_random_bytes(pcb->eap.es_challenge, pcb->eap.es_challen); - MEMCPY(outp, pcb->eap.es_challenge, pcb->eap.es_challen); - INCPTR(pcb->eap.es_challen, outp); - break; -#endif /* USE_SRP */ - - default: - return; - } - - outlen = (outp - (unsigned char*)p->payload) - PPP_HDRLEN; - PUTSHORT(outlen, lenloc); - - pbuf_realloc(p, outlen + PPP_HDRLEN); - ppp_write(pcb, p); - - pcb->eap.es_server.ea_requests++; - - if (pcb->settings.eap_timeout_time > 0) - TIMEOUT(eap_server_timeout, pcb, pcb->settings.eap_timeout_time); -} - -/* - * eap_authpeer - Authenticate our peer (behave as server). - * - * Start server state and send first request. This is called only - * after eap_lowerup. - */ -void eap_authpeer(ppp_pcb *pcb, const char *localname) { - - /* Save the name we're given. */ - pcb->eap.es_server.ea_name = localname; - pcb->eap.es_server.ea_namelen = strlen(localname); - - pcb->eap.es_savedtime = pcb->settings.eap_timeout_time; - - /* Lower layer up yet? */ - if (pcb->eap.es_server.ea_state == eapInitial || - pcb->eap.es_server.ea_state == eapPending) { - pcb->eap.es_server.ea_state = eapPending; - return; - } - - pcb->eap.es_server.ea_state = eapPending; - - /* ID number not updated here intentionally; hashed into M1 */ - eap_send_request(pcb); -} - -/* - * eap_server_timeout - Retransmission timer for sending Requests - * expired. - */ -static void eap_server_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (!eap_server_active(pcb)) - return; - - /* EAP ID number must not change on timeout. */ - eap_send_request(pcb); -} - -/* - * When it's time to send rechallenge the peer, this timeout is - * called. Once the rechallenge is successful, the response handler - * will restart the timer. If it fails, then the link is dropped. - */ -static void eap_rechallenge(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->eap.es_server.ea_state != eapOpen && - pcb->eap.es_server.ea_state != eapSRP4) - return; - - pcb->eap.es_server.ea_requests = 0; - pcb->eap.es_server.ea_state = eapIdentify; - eap_figure_next_state(pcb, 0); - pcb->eap.es_server.ea_id++; - eap_send_request(pcb); -} - -static void srp_lwrechallenge(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->eap.es_server.ea_state != eapOpen || - pcb->eap.es_server.ea_type != EAPT_SRP) - return; - - pcb->eap.es_server.ea_requests = 0; - pcb->eap.es_server.ea_state = eapSRP4; - pcb->eap.es_server.ea_id++; - eap_send_request(pcb); -} -#endif /* PPP_SERVER */ - -/* - * eap_lowerup - The lower layer is now up. - * - * This is called before either eap_authpeer or eap_authwithpeer. See - * link_established() in auth.c. All that's necessary here is to - * return to closed state so that those two routines will do the right - * thing. - */ -static void eap_lowerup(ppp_pcb *pcb) { - pcb->eap.es_client.ea_state = eapClosed; -#if PPP_SERVER - pcb->eap.es_server.ea_state = eapClosed; -#endif /* PPP_SERVER */ -} - -/* - * eap_lowerdown - The lower layer is now down. - * - * Cancel all timeouts and return to initial state. - */ -static void eap_lowerdown(ppp_pcb *pcb) { - - if (eap_client_active(pcb) && pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } -#if PPP_SERVER - if (eap_server_active(pcb)) { - if (pcb->settings.eap_timeout_time > 0) { - UNTIMEOUT(eap_server_timeout, pcb); - } - } else { - if ((pcb->eap.es_server.ea_state == eapOpen || - pcb->eap.es_server.ea_state == eapSRP4) && - pcb->eap.es_rechallenge > 0) { - UNTIMEOUT(eap_rechallenge, (void *)pcb); - } - if (pcb->eap.es_server.ea_state == eapOpen && - pcb->eap.es_lwrechallenge > 0) { - UNTIMEOUT(srp_lwrechallenge, (void *)pcb); - } - } - - pcb->eap.es_client.ea_state = pcb->eap.es_server.ea_state = eapInitial; - pcb->eap.es_client.ea_requests = pcb->eap.es_server.ea_requests = 0; -#endif /* PPP_SERVER */ -} - -/* - * eap_protrej - Peer doesn't speak this protocol. - * - * This shouldn't happen. If it does, it represents authentication - * failure. - */ -static void eap_protrej(ppp_pcb *pcb) { - - if (eap_client_active(pcb)) { - ppp_error("EAP authentication failed due to Protocol-Reject"); - auth_withpeer_fail(pcb, PPP_EAP); - } -#if PPP_SERVER - if (eap_server_active(pcb)) { - ppp_error("EAP authentication of peer failed on Protocol-Reject"); - auth_peer_fail(pcb, PPP_EAP); - } -#endif /* PPP_SERVER */ - eap_lowerdown(pcb); -} - -/* - * Format and send a regular EAP Response message. - */ -static void eap_send_response(ppp_pcb *pcb, u_char id, u_char typenum, const u_char *str, int lenstr) { - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + sizeof (u_char) + lenstr; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(typenum, outp); - if (lenstr > 0) { - MEMCPY(outp, str, lenstr); - } - - ppp_write(pcb, p); -} - -/* - * Format and send an MD5-Challenge EAP Response message. - */ -static void eap_chap_response(ppp_pcb *pcb, u_char id, u_char *hash, const char *name, int namelen) { - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + MD5_SIGNATURE_SIZE + - namelen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_MD5CHAP, outp); - PUTCHAR(MD5_SIGNATURE_SIZE, outp); - MEMCPY(outp, hash, MD5_SIGNATURE_SIZE); - INCPTR(MD5_SIGNATURE_SIZE, outp); - if (namelen > 0) { - MEMCPY(outp, name, namelen); - } - - ppp_write(pcb, p); -} - -#ifdef USE_SRP -/* - * Format and send a SRP EAP Response message. - */ -static void -eap_srp_response(esp, id, subtypenum, str, lenstr) -eap_state *esp; -u_char id; -u_char subtypenum; -u_char *str; -int lenstr; -{ - ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + lenstr; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(subtypenum, outp); - if (lenstr > 0) { - MEMCPY(outp, str, lenstr); - } - - ppp_write(pcb, p); -} - -/* - * Format and send a SRP EAP Client Validator Response message. - */ -static void -eap_srpval_response(esp, id, flags, str) -eap_state *esp; -u_char id; -u32_t flags; -u_char *str; -{ - ppp_pcb *pcb = &ppp_pcb_list[pcb->eap.es_unit]; - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char) + sizeof (u32_t) + - SHA_DIGESTSIZE; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_SRP, outp); - PUTCHAR(EAPSRP_CVALIDATOR, outp); - PUTLONG(flags, outp); - MEMCPY(outp, str, SHA_DIGESTSIZE); - - ppp_write(pcb, p); -} -#endif /* USE_SRP */ - -static void eap_send_nak(ppp_pcb *pcb, u_char id, u_char type) { - struct pbuf *p; - u_char *outp; - int msglen; - - msglen = EAP_HEADERLEN + 2 * sizeof (u_char); - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN + msglen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - - MAKEHEADER(outp, PPP_EAP); - - PUTCHAR(EAP_RESPONSE, outp); - PUTCHAR(id, outp); - pcb->eap.es_client.ea_id = id; - PUTSHORT(msglen, outp); - PUTCHAR(EAPT_NAK, outp); - PUTCHAR(type, outp); - - ppp_write(pcb, p); -} - -#ifdef USE_SRP -static char * -name_of_pn_file() -{ - char *user, *path, *file; - struct passwd *pw; - size_t pl; - static bool pnlogged = 0; - - pw = getpwuid(getuid()); - if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) { - errno = EINVAL; - return (NULL); - } - file = _PATH_PSEUDONYM; - pl = strlen(user) + strlen(file) + 2; - path = malloc(pl); - if (path == NULL) - return (NULL); - (void) slprintf(path, pl, "%s/%s", user, file); - if (!pnlogged) { - ppp_dbglog("pseudonym file: %s", path); - pnlogged = 1; - } - return (path); -} - -static int -open_pn_file(modebits) -mode_t modebits; -{ - char *path; - int fd, err; - - if ((path = name_of_pn_file()) == NULL) - return (-1); - fd = open(path, modebits, S_IRUSR | S_IWUSR); - err = errno; - free(path); - errno = err; - return (fd); -} - -static void -remove_pn_file() -{ - char *path; - - if ((path = name_of_pn_file()) != NULL) { - (void) unlink(path); - (void) free(path); - } -} - -static void -write_pseudonym(esp, inp, len, id) -eap_state *esp; -u_char *inp; -int len, id; -{ - u_char val; - u_char *datp, *digp; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - int dsize, fd, olen = len; - - /* - * Do the decoding by working backwards. This eliminates the need - * to save the decoded output in a separate buffer. - */ - val = id; - while (len > 0) { - if ((dsize = len % SHA_DIGESTSIZE) == 0) - dsize = SHA_DIGESTSIZE; - len -= dsize; - datp = inp + len; - SHA1Init(&ctxt); - SHA1Update(&ctxt, &val, 1); - SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, SESSION_KEY_LEN); - if (len > 0) { - SHA1Update(&ctxt, datp, SHA_DIGESTSIZE); - } else { - SHA1Update(&ctxt, pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - } - SHA1Final(dig, &ctxt); - for (digp = dig; digp < dig + SHA_DIGESTSIZE; digp++) - *datp++ ^= *digp; - } - - /* Now check that the result is sane */ - if (olen <= 0 || *inp + 1 > olen) { - ppp_dbglog("EAP: decoded pseudonym is unusable <%.*B>", olen, inp); - return; - } - - /* Save it away */ - fd = open_pn_file(O_WRONLY | O_CREAT | O_TRUNC); - if (fd < 0) { - ppp_dbglog("EAP: error saving pseudonym: %m"); - return; - } - len = write(fd, inp + 1, *inp); - if (close(fd) != -1 && len == *inp) { - ppp_dbglog("EAP: saved pseudonym"); - pcb->eap.es_usedpseudo = 0; - } else { - ppp_dbglog("EAP: failed to save pseudonym"); - remove_pn_file(); - } -} -#endif /* USE_SRP */ - -/* - * eap_request - Receive EAP Request message (client mode). - */ -static void eap_request(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char typenum; - u_char vallen; - int secret_len; - char secret[MAXSECRETLEN]; - char rhostname[MAXNAMELEN]; - lwip_md5_context mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; -#ifdef USE_SRP - struct t_client *tc; - struct t_num sval, gval, Nval, *Ap, Bval; - u_char vals[2]; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; - int fd; -#endif /* USE_SRP */ - - /* - * Note: we update es_client.ea_id *only if* a Response - * message is being generated. Otherwise, we leave it the - * same for duplicate detection purposes. - */ - - pcb->eap.es_client.ea_requests++; - if (pcb->settings.eap_allow_req != 0 && - pcb->eap.es_client.ea_requests > pcb->settings.eap_allow_req) { - ppp_info("EAP: received too many Request messages"); - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } - auth_withpeer_fail(pcb, PPP_EAP); - return; - } - - if (len <= 0) { - ppp_error("EAP: empty Request message discarded"); - return; - } - - GETCHAR(typenum, inp); - len--; - - switch (typenum) { - case EAPT_IDENTITY: - if (len > 0) - ppp_info("EAP: Identity prompt \"%.*q\"", len, inp); -#ifdef USE_SRP - if (pcb->eap.es_usepseudo && - (pcb->eap.es_usedpseudo == 0 || - (pcb->eap.es_usedpseudo == 1 && - id == pcb->eap.es_client.ea_id))) { - pcb->eap.es_usedpseudo = 1; - /* Try to get a pseudonym */ - if ((fd = open_pn_file(O_RDONLY)) >= 0) { - strcpy(rhostname, SRP_PSEUDO_ID); - len = read(fd, rhostname + SRP_PSEUDO_LEN, - sizeof (rhostname) - SRP_PSEUDO_LEN); - /* XXX NAI unsupported */ - if (len > 0) { - eap_send_response(pcb, id, typenum, - rhostname, len + SRP_PSEUDO_LEN); - } - (void) close(fd); - if (len > 0) - break; - } - } - /* Stop using pseudonym now. */ - if (pcb->eap.es_usepseudo && pcb->eap.es_usedpseudo != 2) { - remove_pn_file(); - pcb->eap.es_usedpseudo = 2; - } -#endif /* USE_SRP */ - eap_send_response(pcb, id, typenum, (const u_char*)pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - break; - - case EAPT_NOTIFICATION: - if (len > 0) - ppp_info("EAP: Notification \"%.*q\"", len, inp); - eap_send_response(pcb, id, typenum, NULL, 0); - break; - - case EAPT_NAK: - /* - * Avoid the temptation to send Response Nak in reply - * to Request Nak here. It can only lead to trouble. - */ - ppp_warn("EAP: unexpected Nak in Request; ignored"); - /* Return because we're waiting for something real. */ - return; - - case EAPT_MD5CHAP: - if (len < 1) { - ppp_error("EAP: received MD5-Challenge with no data"); - /* Bogus request; wait for something real. */ - return; - } - GETCHAR(vallen, inp); - len--; - if (vallen < 8 || vallen > len) { - ppp_error("EAP: MD5-Challenge with bad length %d (8..%d)", - vallen, len); - /* Try something better. */ - eap_send_nak(pcb, id, EAPT_SRP); - break; - } - - /* Not so likely to happen. */ - if (vallen >= len + sizeof (rhostname)) { - ppp_dbglog("EAP: trimming really long peer name down"); - MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); - rhostname[sizeof (rhostname) - 1] = '\0'; - } else { - MEMCPY(rhostname, inp + vallen, len - vallen); - rhostname[len - vallen] = '\0'; - } - -#if PPP_REMOTENAME - /* In case the remote doesn't give us his name. */ - if (pcb->settings.explicit_remote || - (pcb->settings.remote_name[0] != '\0' && vallen == len)) - strlcpy(rhostname, pcb->settings.remote_name, sizeof (rhostname)); -#endif /* PPP_REMOTENAME */ - - /* - * Get the secret for authenticating ourselves with - * the specified host. - */ - if (!get_secret(pcb, pcb->eap.es_client.ea_name, - rhostname, secret, &secret_len, 0)) { - ppp_dbglog("EAP: no MD5 secret for auth to %q", rhostname); - eap_send_nak(pcb, id, EAPT_SRP); - break; - } - lwip_md5_init(&mdContext); - lwip_md5_starts(&mdContext); - typenum = id; - lwip_md5_update(&mdContext, &typenum, 1); - lwip_md5_update(&mdContext, (u_char *)secret, secret_len); - BZERO(secret, sizeof (secret)); - lwip_md5_update(&mdContext, inp, vallen); - lwip_md5_finish(&mdContext, hash); - lwip_md5_free(&mdContext); - eap_chap_response(pcb, id, hash, pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - break; - -#ifdef USE_SRP - case EAPT_SRP: - if (len < 1) { - ppp_error("EAP: received empty SRP Request"); - /* Bogus request; wait for something real. */ - return; - } - - /* Get subtype */ - GETCHAR(vallen, inp); - len--; - switch (vallen) { - case EAPSRP_CHALLENGE: - tc = NULL; - if (pcb->eap.es_client.ea_session != NULL) { - tc = (struct t_client *)pcb->eap.es_client. - ea_session; - /* - * If this is a new challenge, then start - * over with a new client session context. - * Otherwise, just resend last response. - */ - if (id != pcb->eap.es_client.ea_id) { - t_clientclose(tc); - pcb->eap.es_client.ea_session = NULL; - tc = NULL; - } - } - /* No session key just yet */ - pcb->eap.es_client.ea_skey = NULL; - if (tc == NULL) { - int rhostnamelen; - - GETCHAR(vallen, inp); - len--; - if (vallen >= len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (name)"); - /* Ignore badly-formed messages */ - return; - } - MEMCPY(rhostname, inp, vallen); - rhostname[vallen] = '\0'; - INCPTR(vallen, inp); - len -= vallen; - - /* - * In case the remote doesn't give us his name, - * use configured name. - */ - if (explicit_remote || - (remote_name[0] != '\0' && vallen == 0)) { - strlcpy(rhostname, remote_name, - sizeof (rhostname)); - } - - rhostnamelen = (int)strlen(rhostname); - if (rhostnamelen > MAXNAMELEN) { - rhostnamelen = MAXNAMELEN; - } - MEMCPY(pcb->eap.es_client.ea_peer, rhostname, rhostnamelen); - pcb->eap.es_client.ea_peer[rhostnamelen] = '\0'; - pcb->eap.es_client.ea_peerlen = rhostnamelen; - - GETCHAR(vallen, inp); - len--; - if (vallen >= len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (s)"); - /* Ignore badly-formed messages */ - return; - } - sval.data = inp; - sval.len = vallen; - INCPTR(vallen, inp); - len -= vallen; - - GETCHAR(vallen, inp); - len--; - if (vallen > len) { - ppp_error("EAP: badly-formed SRP Challenge" - " (g)"); - /* Ignore badly-formed messages */ - return; - } - /* If no generator present, then use value 2 */ - if (vallen == 0) { - gval.data = (u_char *)"\002"; - gval.len = 1; - } else { - gval.data = inp; - gval.len = vallen; - } - INCPTR(vallen, inp); - len -= vallen; - - /* - * If no modulus present, then use well-known - * value. - */ - if (len == 0) { - Nval.data = (u_char *)wkmodulus; - Nval.len = sizeof (wkmodulus); - } else { - Nval.data = inp; - Nval.len = len; - } - tc = t_clientopen(pcb->eap.es_client.ea_name, - &Nval, &gval, &sval); - if (tc == NULL) { - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - pcb->eap.es_client.ea_session = (void *)tc; - - /* Add Challenge ID & type to verifier */ - vals[0] = id; - vals[1] = EAPT_SRP; - t_clientaddexdata(tc, vals, 2); - } - Ap = t_clientgenexp(tc); - eap_srp_response(esp, id, EAPSRP_CKEY, Ap->data, - Ap->len); - break; - - case EAPSRP_SKEY: - tc = (struct t_client *)pcb->eap.es_client.ea_session; - if (tc == NULL) { - ppp_warn("EAP: peer sent Subtype 2 without 1"); - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - if (pcb->eap.es_client.ea_skey != NULL) { - /* - * ID number should not change here. Warn - * if it does (but otherwise ignore). - */ - if (id != pcb->eap.es_client.ea_id) { - ppp_warn("EAP: ID changed from %d to %d " - "in SRP Subtype 2 rexmit", - pcb->eap.es_client.ea_id, id); - } - } else { - if (get_srp_secret(pcb->eap.es_unit, - pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_peer, secret, 0) == 0) { - /* - * Can't work with this peer because - * the secret is missing. Just give - * up. - */ - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - Bval.data = inp; - Bval.len = len; - t_clientpasswd(tc, secret); - BZERO(secret, sizeof (secret)); - pcb->eap.es_client.ea_skey = - t_clientgetkey(tc, &Bval); - if (pcb->eap.es_client.ea_skey == NULL) { - /* Server is rogue; stop now */ - ppp_error("EAP: SRP server is rogue"); - goto client_failure; - } - } - eap_srpval_response(esp, id, SRPVAL_EBIT, - t_clientresponse(tc)); - break; - - case EAPSRP_SVALIDATOR: - tc = (struct t_client *)pcb->eap.es_client.ea_session; - if (tc == NULL || pcb->eap.es_client.ea_skey == NULL) { - ppp_warn("EAP: peer sent Subtype 3 without 1/2"); - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - /* - * If we're already open, then this ought to be a - * duplicate. Otherwise, check that the server is - * who we think it is. - */ - if (pcb->eap.es_client.ea_state == eapOpen) { - if (id != pcb->eap.es_client.ea_id) { - ppp_warn("EAP: ID changed from %d to %d " - "in SRP Subtype 3 rexmit", - pcb->eap.es_client.ea_id, id); - } - } else { - len -= sizeof (u32_t) + SHA_DIGESTSIZE; - if (len < 0 || t_clientverify(tc, inp + - sizeof (u32_t)) != 0) { - ppp_error("EAP: SRP server verification " - "failed"); - goto client_failure; - } - GETLONG(pcb->eap.es_client.ea_keyflags, inp); - /* Save pseudonym if user wants it. */ - if (len > 0 && pcb->eap.es_usepseudo) { - INCPTR(SHA_DIGESTSIZE, inp); - write_pseudonym(esp, inp, len, id); - } - } - /* - * We've verified our peer. We're now mostly done, - * except for waiting on the regular EAP Success - * message. - */ - eap_srp_response(esp, id, EAPSRP_ACK, NULL, 0); - break; - - case EAPSRP_LWRECHALLENGE: - if (len < 4) { - ppp_warn("EAP: malformed Lightweight rechallenge"); - return; - } - SHA1Init(&ctxt); - vals[0] = id; - SHA1Update(&ctxt, vals, 1); - SHA1Update(&ctxt, pcb->eap.es_client.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, inp, len); - SHA1Update(&ctxt, pcb->eap.es_client.ea_name, - pcb->eap.es_client.ea_namelen); - SHA1Final(dig, &ctxt); - eap_srp_response(esp, id, EAPSRP_LWRECHALLENGE, dig, - SHA_DIGESTSIZE); - break; - - default: - ppp_error("EAP: unknown SRP Subtype %d", vallen); - eap_send_nak(pcb, id, EAPT_MD5CHAP); - break; - } - break; -#endif /* USE_SRP */ - - default: - ppp_info("EAP: unknown authentication type %d; Naking", typenum); - eap_send_nak(pcb, id, EAPT_SRP); - break; - } - - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - TIMEOUT(eap_client_timeout, pcb, - pcb->settings.eap_req_time); - } - return; - -#ifdef USE_SRP -client_failure: - pcb->eap.es_client.ea_state = eapBadAuth; - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, (void *)esp); - } - pcb->eap.es_client.ea_session = NULL; - t_clientclose(tc); - auth_withpeer_fail(pcb, PPP_EAP); -#endif /* USE_SRP */ -} - -#if PPP_SERVER -/* - * eap_response - Receive EAP Response message (server mode). - */ -static void eap_response(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char typenum; - u_char vallen; - int secret_len; - char secret[MAXSECRETLEN]; - char rhostname[MAXNAMELEN]; - lwip_md5_context mdContext; - u_char hash[MD5_SIGNATURE_SIZE]; -#ifdef USE_SRP - struct t_server *ts; - struct t_num A; - SHA1_CTX ctxt; - u_char dig[SHA_DIGESTSIZE]; -#endif /* USE_SRP */ - - if (pcb->eap.es_server.ea_id != id) { - ppp_dbglog("EAP: discarding Response %d; expected ID %d", id, - pcb->eap.es_server.ea_id); - return; - } - - pcb->eap.es_server.ea_responses++; - - if (len <= 0) { - ppp_error("EAP: empty Response message discarded"); - return; - } - - GETCHAR(typenum, inp); - len--; - - switch (typenum) { - case EAPT_IDENTITY: - if (pcb->eap.es_server.ea_state != eapIdentify) { - ppp_dbglog("EAP discarding unwanted Identify \"%.q\"", len, - inp); - break; - } - ppp_info("EAP: unauthenticated peer name \"%.*q\"", len, inp); - if (len > MAXNAMELEN) { - len = MAXNAMELEN; - } - MEMCPY(pcb->eap.es_server.ea_peer, inp, len); - pcb->eap.es_server.ea_peer[len] = '\0'; - pcb->eap.es_server.ea_peerlen = len; - eap_figure_next_state(pcb, 0); - break; - - case EAPT_NOTIFICATION: - ppp_dbglog("EAP unexpected Notification; response discarded"); - break; - - case EAPT_NAK: - if (len < 1) { - ppp_info("EAP: Nak Response with no suggested protocol"); - eap_figure_next_state(pcb, 1); - break; - } - - GETCHAR(vallen, inp); - len--; - - if ( -#if PPP_REMOTENAME - !pcb->explicit_remote && -#endif /* PPP_REMOTENAME */ - pcb->eap.es_server.ea_state == eapIdentify){ - /* Peer cannot Nak Identify Request */ - eap_figure_next_state(pcb, 1); - break; - } - - switch (vallen) { - case EAPT_SRP: - /* Run through SRP validator selection again. */ - pcb->eap.es_server.ea_state = eapIdentify; - eap_figure_next_state(pcb, 0); - break; - - case EAPT_MD5CHAP: - pcb->eap.es_server.ea_state = eapMD5Chall; - break; - - default: - ppp_dbglog("EAP: peer requesting unknown Type %d", vallen); - switch (pcb->eap.es_server.ea_state) { - case eapSRP1: - case eapSRP2: - case eapSRP3: - pcb->eap.es_server.ea_state = eapMD5Chall; - break; - case eapMD5Chall: - case eapSRP4: - pcb->eap.es_server.ea_state = eapIdentify; - eap_figure_next_state(pcb, 0); - break; - default: - break; - } - break; - } - break; - - case EAPT_MD5CHAP: - if (pcb->eap.es_server.ea_state != eapMD5Chall) { - ppp_error("EAP: unexpected MD5-Response"); - eap_figure_next_state(pcb, 1); - break; - } - if (len < 1) { - ppp_error("EAP: received MD5-Response with no data"); - eap_figure_next_state(pcb, 1); - break; - } - GETCHAR(vallen, inp); - len--; - if (vallen != 16 || vallen > len) { - ppp_error("EAP: MD5-Response with bad length %d", vallen); - eap_figure_next_state(pcb, 1); - break; - } - - /* Not so likely to happen. */ - if (vallen >= len + sizeof (rhostname)) { - ppp_dbglog("EAP: trimming really long peer name down"); - MEMCPY(rhostname, inp + vallen, sizeof (rhostname) - 1); - rhostname[sizeof (rhostname) - 1] = '\0'; - } else { - MEMCPY(rhostname, inp + vallen, len - vallen); - rhostname[len - vallen] = '\0'; - } - -#if PPP_REMOTENAME - /* In case the remote doesn't give us his name. */ - if (explicit_remote || - (remote_name[0] != '\0' && vallen == len)) - strlcpy(rhostname, remote_name, sizeof (rhostname)); -#endif /* PPP_REMOTENAME */ - - /* - * Get the secret for authenticating the specified - * host. - */ - if (!get_secret(pcb, rhostname, - pcb->eap.es_server.ea_name, secret, &secret_len, 1)) { - ppp_dbglog("EAP: no MD5 secret for auth of %q", rhostname); - eap_send_failure(pcb); - break; - } - lwip_md5_init(&mdContext); - lwip_md5_starts(&mdContext); - lwip_md5_update(&mdContext, &pcb->eap.es_server.ea_id, 1); - lwip_md5_update(&mdContext, (u_char *)secret, secret_len); - BZERO(secret, sizeof (secret)); - lwip_md5_update(&mdContext, pcb->eap.es_challenge, pcb->eap.es_challen); - lwip_md5_finish(&mdContext, hash); - lwip_md5_free(&mdContext); - if (BCMP(hash, inp, MD5_SIGNATURE_SIZE) != 0) { - eap_send_failure(pcb); - break; - } - pcb->eap.es_server.ea_type = EAPT_MD5CHAP; - eap_send_success(pcb); - eap_figure_next_state(pcb, 0); - if (pcb->eap.es_rechallenge != 0) - TIMEOUT(eap_rechallenge, pcb, pcb->eap.es_rechallenge); - break; - -#ifdef USE_SRP - case EAPT_SRP: - if (len < 1) { - ppp_error("EAP: empty SRP Response"); - eap_figure_next_state(pcb, 1); - break; - } - GETCHAR(typenum, inp); - len--; - switch (typenum) { - case EAPSRP_CKEY: - if (pcb->eap.es_server.ea_state != eapSRP1) { - ppp_error("EAP: unexpected SRP Subtype 1 Response"); - eap_figure_next_state(pcb, 1); - break; - } - A.data = inp; - A.len = len; - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - pcb->eap.es_server.ea_skey = t_servergetkey(ts, &A); - if (pcb->eap.es_server.ea_skey == NULL) { - /* Client's A value is bogus; terminate now */ - ppp_error("EAP: bogus A value from client"); - eap_send_failure(pcb); - } else { - eap_figure_next_state(pcb, 0); - } - break; - - case EAPSRP_CVALIDATOR: - if (pcb->eap.es_server.ea_state != eapSRP2) { - ppp_error("EAP: unexpected SRP Subtype 2 Response"); - eap_figure_next_state(pcb, 1); - break; - } - if (len < sizeof (u32_t) + SHA_DIGESTSIZE) { - ppp_error("EAP: M1 length %d < %d", len, - sizeof (u32_t) + SHA_DIGESTSIZE); - eap_figure_next_state(pcb, 1); - break; - } - GETLONG(pcb->eap.es_server.ea_keyflags, inp); - ts = (struct t_server *)pcb->eap.es_server.ea_session; - assert(ts != NULL); - if (t_serververify(ts, inp)) { - ppp_info("EAP: unable to validate client identity"); - eap_send_failure(pcb); - break; - } - eap_figure_next_state(pcb, 0); - break; - - case EAPSRP_ACK: - if (pcb->eap.es_server.ea_state != eapSRP3) { - ppp_error("EAP: unexpected SRP Subtype 3 Response"); - eap_send_failure(esp); - break; - } - pcb->eap.es_server.ea_type = EAPT_SRP; - eap_send_success(pcb, esp); - eap_figure_next_state(pcb, 0); - if (pcb->eap.es_rechallenge != 0) - TIMEOUT(eap_rechallenge, pcb, - pcb->eap.es_rechallenge); - if (pcb->eap.es_lwrechallenge != 0) - TIMEOUT(srp_lwrechallenge, pcb, - pcb->eap.es_lwrechallenge); - break; - - case EAPSRP_LWRECHALLENGE: - if (pcb->eap.es_server.ea_state != eapSRP4) { - ppp_info("EAP: unexpected SRP Subtype 4 Response"); - return; - } - if (len != SHA_DIGESTSIZE) { - ppp_error("EAP: bad Lightweight rechallenge " - "response"); - return; - } - SHA1Init(&ctxt); - vallen = id; - SHA1Update(&ctxt, &vallen, 1); - SHA1Update(&ctxt, pcb->eap.es_server.ea_skey, - SESSION_KEY_LEN); - SHA1Update(&ctxt, pcb->eap.es_challenge, pcb->eap.es_challen); - SHA1Update(&ctxt, pcb->eap.es_server.ea_peer, - pcb->eap.es_server.ea_peerlen); - SHA1Final(dig, &ctxt); - if (BCMP(dig, inp, SHA_DIGESTSIZE) != 0) { - ppp_error("EAP: failed Lightweight rechallenge"); - eap_send_failure(pcb); - break; - } - pcb->eap.es_server.ea_state = eapOpen; - if (pcb->eap.es_lwrechallenge != 0) - TIMEOUT(srp_lwrechallenge, esp, - pcb->eap.es_lwrechallenge); - break; - } - break; -#endif /* USE_SRP */ - - default: - /* This can't happen. */ - ppp_error("EAP: unknown Response type %d; ignored", typenum); - return; - } - - if (pcb->settings.eap_timeout_time > 0) { - UNTIMEOUT(eap_server_timeout, pcb); - } - - if (pcb->eap.es_server.ea_state != eapBadAuth && - pcb->eap.es_server.ea_state != eapOpen) { - pcb->eap.es_server.ea_id++; - eap_send_request(pcb); - } -} -#endif /* PPP_SERVER */ - -/* - * eap_success - Receive EAP Success message (client mode). - */ -static void eap_success(ppp_pcb *pcb, u_char *inp, int id, int len) { - LWIP_UNUSED_ARG(id); - - if (pcb->eap.es_client.ea_state != eapOpen && !eap_client_active(pcb)) { - ppp_dbglog("EAP unexpected success message in state %s (%d)", - eap_state_name(pcb->eap.es_client.ea_state), - pcb->eap.es_client.ea_state); - return; - } - - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } - - if (len > 0) { - /* This is odd. The spec doesn't allow for this. */ - PRINTMSG(inp, len); - } - - pcb->eap.es_client.ea_state = eapOpen; - auth_withpeer_success(pcb, PPP_EAP, 0); -} - -/* - * eap_failure - Receive EAP Failure message (client mode). - */ -static void eap_failure(ppp_pcb *pcb, u_char *inp, int id, int len) { - LWIP_UNUSED_ARG(id); - - if (!eap_client_active(pcb)) { - ppp_dbglog("EAP unexpected failure message in state %s (%d)", - eap_state_name(pcb->eap.es_client.ea_state), - pcb->eap.es_client.ea_state); - } - - if (pcb->settings.eap_req_time > 0) { - UNTIMEOUT(eap_client_timeout, pcb); - } - - if (len > 0) { - /* This is odd. The spec doesn't allow for this. */ - PRINTMSG(inp, len); - } - - pcb->eap.es_client.ea_state = eapBadAuth; - - ppp_error("EAP: peer reports authentication failure"); - auth_withpeer_fail(pcb, PPP_EAP); -} - -/* - * eap_input - Handle received EAP message. - */ -static void eap_input(ppp_pcb *pcb, u_char *inp, int inlen) { - u_char code, id; - int len; - - /* - * Parse header (code, id and length). If packet too short, - * drop it. - */ - if (inlen < EAP_HEADERLEN) { - ppp_error("EAP: packet too short: %d < %d", inlen, EAP_HEADERLEN); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < EAP_HEADERLEN || len > inlen) { - ppp_error("EAP: packet has illegal length field %d (%d..%d)", len, - EAP_HEADERLEN, inlen); - return; - } - len -= EAP_HEADERLEN; - - /* Dispatch based on message code */ - switch (code) { - case EAP_REQUEST: - eap_request(pcb, inp, id, len); - break; - -#if PPP_SERVER - case EAP_RESPONSE: - eap_response(pcb, inp, id, len); - break; -#endif /* PPP_SERVER */ - - case EAP_SUCCESS: - eap_success(pcb, inp, id, len); - break; - - case EAP_FAILURE: - eap_failure(pcb, inp, id, len); - break; - - default: /* XXX Need code reject */ - /* Note: it's not legal to send EAP Nak here. */ - ppp_warn("EAP: unknown code %d received", code); - break; - } -} - -#if PRINTPKT_SUPPORT -/* - * eap_printpkt - print the contents of an EAP packet. - */ -static const char* const eap_codenames[] = { - "Request", "Response", "Success", "Failure" -}; - -static const char* const eap_typenames[] = { - "Identity", "Notification", "Nak", "MD5-Challenge", - "OTP", "Generic-Token", NULL, NULL, - "RSA", "DSS", "KEA", "KEA-Validate", - "TLS", "Defender", "Windows 2000", "Arcot", - "Cisco", "Nokia", "SRP" -}; - -static int eap_printpkt(const u_char *inp, int inlen, void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len, rtype, vallen; - const u_char *pstart; - u32_t uval; - - if (inlen < EAP_HEADERLEN) - return (0); - pstart = inp; - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < EAP_HEADERLEN || len > inlen) - return (0); - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(eap_codenames)) - printer(arg, " %s", eap_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= EAP_HEADERLEN; - switch (code) { - case EAP_REQUEST: - if (len < 1) { - printer(arg, " "); - break; - } - GETCHAR(rtype, inp); - len--; - if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) - printer(arg, " %s", eap_typenames[rtype-1]); - else - printer(arg, " type=0x%x", rtype); - switch (rtype) { - case EAPT_IDENTITY: - case EAPT_NOTIFICATION: - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } else { - printer(arg, " "); - } - break; - - case EAPT_MD5CHAP: - if (len <= 0) - break; - GETCHAR(vallen, inp); - len--; - if (vallen > len) - goto truncated; - printer(arg, " ", vallen, inp); - INCPTR(vallen, inp); - len -= vallen; - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } else { - printer(arg, " "); - } - break; - - case EAPT_SRP: - if (len < 3) - goto truncated; - GETCHAR(vallen, inp); - len--; - printer(arg, "-%d", vallen); - switch (vallen) { - case EAPSRP_CHALLENGE: - GETCHAR(vallen, inp); - len--; - if (vallen >= len) - goto truncated; - if (vallen > 0) { - printer(arg, " "); - } else { - printer(arg, " "); - } - INCPTR(vallen, inp); - len -= vallen; - GETCHAR(vallen, inp); - len--; - if (vallen >= len) - goto truncated; - printer(arg, " ", vallen, inp); - INCPTR(vallen, inp); - len -= vallen; - GETCHAR(vallen, inp); - len--; - if (vallen > len) - goto truncated; - if (vallen == 0) { - printer(arg, " "); - } else { - printer(arg, " ", vallen, inp); - } - INCPTR(vallen, inp); - len -= vallen; - if (len == 0) { - printer(arg, " "); - } else { - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - } - break; - - case EAPSRP_SKEY: - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - break; - - case EAPSRP_SVALIDATOR: - if (len < (int)sizeof (u32_t)) - break; - GETLONG(uval, inp); - len -= sizeof (u32_t); - if (uval & SRPVAL_EBIT) { - printer(arg, " E"); - uval &= ~SRPVAL_EBIT; - } - if (uval != 0) { - printer(arg, " f<%X>", uval); - } - if ((vallen = len) > SHA_DIGESTSIZE) - vallen = SHA_DIGESTSIZE; - printer(arg, " ", len, inp, - len < SHA_DIGESTSIZE ? "?" : ""); - INCPTR(vallen, inp); - len -= vallen; - if (len > 0) { - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - } - break; - - case EAPSRP_LWRECHALLENGE: - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - break; - default: - break; - } - break; - default: - break; - } - break; - - case EAP_RESPONSE: - if (len < 1) - break; - GETCHAR(rtype, inp); - len--; - if (rtype >= 1 && rtype <= (int)LWIP_ARRAYSIZE(eap_typenames)) - printer(arg, " %s", eap_typenames[rtype-1]); - else - printer(arg, " type=0x%x", rtype); - switch (rtype) { - case EAPT_IDENTITY: - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } - break; - - case EAPT_NAK: - if (len <= 0) { - printer(arg, " "); - break; - } - GETCHAR(rtype, inp); - len--; - printer(arg, " = 1 && rtype < (int)LWIP_ARRAYSIZE(eap_typenames)) - printer(arg, " (%s)", eap_typenames[rtype-1]); - printer(arg, ">"); - break; - - case EAPT_MD5CHAP: - if (len <= 0) { - printer(arg, " "); - break; - } - GETCHAR(vallen, inp); - len--; - if (vallen > len) - goto truncated; - printer(arg, " ", vallen, inp); - INCPTR(vallen, inp); - len -= vallen; - if (len > 0) { - printer(arg, " "); - INCPTR(len, inp); - len = 0; - } else { - printer(arg, " "); - } - break; - - case EAPT_SRP: - if (len < 1) - goto truncated; - GETCHAR(vallen, inp); - len--; - printer(arg, "-%d", vallen); - switch (vallen) { - case EAPSRP_CKEY: - printer(arg, " ", len, inp); - INCPTR(len, inp); - len = 0; - break; - - case EAPSRP_CVALIDATOR: - if (len < (int)sizeof (u32_t)) - break; - GETLONG(uval, inp); - len -= sizeof (u32_t); - if (uval & SRPVAL_EBIT) { - printer(arg, " E"); - uval &= ~SRPVAL_EBIT; - } - if (uval != 0) { - printer(arg, " f<%X>", uval); - } - printer(arg, " ", len, inp, - len == SHA_DIGESTSIZE ? "" : "?"); - INCPTR(len, inp); - len = 0; - break; - - case EAPSRP_ACK: - break; - - case EAPSRP_LWRECHALLENGE: - printer(arg, " ", len, inp, - len == SHA_DIGESTSIZE ? "" : "?"); - if ((vallen = len) > SHA_DIGESTSIZE) - vallen = SHA_DIGESTSIZE; - INCPTR(vallen, inp); - len -= vallen; - break; - default: - break; - } - break; - default: - break; - } - break; - - case EAP_SUCCESS: /* No payload expected for these! */ - case EAP_FAILURE: - default: - break; - - truncated: - printer(arg, " "); - break; - } - - if (len > 8) - printer(arg, "%8B...", inp); - else if (len > 0) - printer(arg, "%.*B", len, inp); - INCPTR(len, inp); - - return (inp - pstart); -} -#endif /* PRINTPKT_SUPPORT */ - -#endif /* PPP_SUPPORT && EAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/ecp.c b/components/net/lwip-2.0.2/src/netif/ppp/ecp.c deleted file mode 100644 index 4d84f60931..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/ecp.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * ecp.c - PPP Encryption Control Protocol. - * - * Copyright (c) 2002 Google, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Derived from ccp.c, which is: - * - * Copyright (c) 1994-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && ECP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ecp.h" - -#if PPP_OPTIONS -static option_t ecp_option_list[] = { - { "noecp", o_bool, &ecp_protent.enabled_flag, - "Disable ECP negotiation" }, - { "-ecp", o_bool, &ecp_protent.enabled_flag, - "Disable ECP negotiation", OPT_ALIAS }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ecp_init (int unit); -/* -static void ecp_open (int unit); -static void ecp_close (int unit, char *); -static void ecp_lowerup (int unit); -static void ecp_lowerdown (int); -static void ecp_input (int unit, u_char *pkt, int len); -static void ecp_protrej (int unit); -*/ -#if PRINTPKT_SUPPORT -static int ecp_printpkt (const u_char *pkt, int len, - void (*printer) (void *, char *, ...), - void *arg); -#endif /* PRINTPKT_SUPPORT */ -/* -static void ecp_datainput (int unit, u_char *pkt, int len); -*/ - -const struct protent ecp_protent = { - PPP_ECP, - ecp_init, - NULL, /* ecp_input, */ - NULL, /* ecp_protrej, */ - NULL, /* ecp_lowerup, */ - NULL, /* ecp_lowerdown, */ - NULL, /* ecp_open, */ - NULL, /* ecp_close, */ -#if PRINTPKT_SUPPORT - ecp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, /* ecp_datainput, */ -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "ECP", - "Encrypted", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ecp_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -fsm ecp_fsm[NUM_PPP]; -ecp_options ecp_wantoptions[NUM_PPP]; /* what to request the peer to use */ -ecp_options ecp_gotoptions[NUM_PPP]; /* what the peer agreed to do */ -ecp_options ecp_allowoptions[NUM_PPP]; /* what we'll agree to do */ -ecp_options ecp_hisoptions[NUM_PPP]; /* what we agreed to do */ - -static const fsm_callbacks ecp_callbacks = { - NULL, /* ecp_resetci, */ - NULL, /* ecp_cilen, */ - NULL, /* ecp_addci, */ - NULL, /* ecp_ackci, */ - NULL, /* ecp_nakci, */ - NULL, /* ecp_rejci, */ - NULL, /* ecp_reqci, */ - NULL, /* ecp_up, */ - NULL, /* ecp_down, */ - NULL, - NULL, - NULL, - NULL, - NULL, /* ecp_extcode, */ - "ECP" -}; - -/* - * ecp_init - initialize ECP. - */ -static void -ecp_init(unit) - int unit; -{ - fsm *f = &ecp_fsm[unit]; - - f->unit = unit; - f->protocol = PPP_ECP; - f->callbacks = &ecp_callbacks; - fsm_init(f); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(&ecp_wantoptions[unit], 0, sizeof(ecp_options)); - memset(&ecp_gotoptions[unit], 0, sizeof(ecp_options)); - memset(&ecp_allowoptions[unit], 0, sizeof(ecp_options)); - memset(&ecp_hisoptions[unit], 0, sizeof(ecp_options)); -#endif /* 0 */ - -} - - -#if PRINTPKT_SUPPORT -static int -ecp_printpkt(p, plen, printer, arg) - const u_char *p; - int plen; - void (*printer) (void *, char *, ...); - void *arg; -{ - return 0; -} -#endif /* PRINTPKT_SUPPORT */ - -#endif /* PPP_SUPPORT && ECP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/eui64.c b/components/net/lwip-2.0.2/src/netif/ppp/eui64.c deleted file mode 100644 index 01493bc1f8..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/eui64.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * eui64.c - EUI64 routines for IPv6CP. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: eui64.c,v 1.6 2002/12/04 23:03:32 paulus Exp $ - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/eui64.h" - -/* - * eui64_ntoa - Make an ascii representation of an interface identifier - */ -char *eui64_ntoa(eui64_t e) { - static char buf[20]; - - sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x", - e.e8[0], e.e8[1], e.e8[2], e.e8[3], - e.e8[4], e.e8[5], e.e8[6], e.e8[7]); - return buf; -} - -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/fsm.c b/components/net/lwip-2.0.2/src/netif/ppp/fsm.c deleted file mode 100644 index 81eba11602..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/fsm.c +++ /dev/null @@ -1,799 +0,0 @@ -/* - * fsm.c - {Link, IP} Control Protocol Finite State Machine. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - * Randomize fsm id on link/init. - * Deal with variable outgoing MTU. - */ - -#if 0 /* UNUSED */ -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" - -static void fsm_timeout (void *); -static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len); -static void fsm_rconfack(fsm *f, int id, u_char *inp, int len); -static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len); -static void fsm_rtermreq(fsm *f, int id, u_char *p, int len); -static void fsm_rtermack(fsm *f); -static void fsm_rcoderej(fsm *f, u_char *inp, int len); -static void fsm_sconfreq(fsm *f, int retransmit); - -#define PROTO_NAME(f) ((f)->callbacks->proto_name) - -/* - * fsm_init - Initialize fsm. - * - * Initialize fsm state. - */ -void fsm_init(fsm *f) { - ppp_pcb *pcb = f->pcb; - f->state = PPP_FSM_INITIAL; - f->flags = 0; - f->id = 0; /* XXX Start with random id? */ - f->maxnakloops = pcb->settings.fsm_max_nak_loops; - f->term_reason_len = 0; -} - - -/* - * fsm_lowerup - The lower layer is up. - */ -void fsm_lowerup(fsm *f) { - switch( f->state ){ - case PPP_FSM_INITIAL: - f->state = PPP_FSM_CLOSED; - break; - - case PPP_FSM_STARTING: - if( f->flags & OPT_SILENT ) - f->state = PPP_FSM_STOPPED; - else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - } - break; - - default: - FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_lowerdown - The lower layer is down. - * - * Cancel all timeouts and inform upper layers. - */ -void fsm_lowerdown(fsm *f) { - switch( f->state ){ - case PPP_FSM_CLOSED: - f->state = PPP_FSM_INITIAL; - break; - - case PPP_FSM_STOPPED: - f->state = PPP_FSM_STARTING; - if( f->callbacks->starting ) - (*f->callbacks->starting)(f); - break; - - case PPP_FSM_CLOSING: - f->state = PPP_FSM_INITIAL; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case PPP_FSM_STOPPING: - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - f->state = PPP_FSM_STARTING; - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - break; - - case PPP_FSM_OPENED: - if( f->callbacks->down ) - (*f->callbacks->down)(f); - f->state = PPP_FSM_STARTING; - break; - - default: - FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_open - Link is allowed to come up. - */ -void fsm_open(fsm *f) { - switch( f->state ){ - case PPP_FSM_INITIAL: - f->state = PPP_FSM_STARTING; - if( f->callbacks->starting ) - (*f->callbacks->starting)(f); - break; - - case PPP_FSM_CLOSED: - if( f->flags & OPT_SILENT ) - f->state = PPP_FSM_STOPPED; - else { - /* Send an initial configure-request */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - } - break; - - case PPP_FSM_CLOSING: - f->state = PPP_FSM_STOPPING; - /* fall through */ - /* no break */ - case PPP_FSM_STOPPED: - case PPP_FSM_OPENED: - if( f->flags & OPT_RESTART ){ - fsm_lowerdown(f); - fsm_lowerup(f); - } - break; - default: - break; - } -} - -/* - * terminate_layer - Start process of shutting down the FSM - * - * Cancel any timeout running, notify upper layers we're done, and - * send a terminate-request message as configured. - */ -static void terminate_layer(fsm *f, int nextstate) { - ppp_pcb *pcb = f->pcb; - - if( f->state != PPP_FSM_OPENED ) - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - else if( f->callbacks->down ) - (*f->callbacks->down)(f); /* Inform upper layers we're down */ - - /* Init restart counter and send Terminate-Request */ - f->retransmits = pcb->settings.fsm_max_term_transmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (const u_char *) f->term_reason, f->term_reason_len); - - if (f->retransmits == 0) { - /* - * User asked for no terminate requests at all; just close it. - * We've already fired off one Terminate-Request just to be nice - * to the peer, but we're not going to wait for a reply. - */ - f->state = nextstate == PPP_FSM_CLOSING ? PPP_FSM_CLOSED : PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - return; - } - - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); - --f->retransmits; - - f->state = nextstate; -} - -/* - * fsm_close - Start closing connection. - * - * Cancel timeouts and either initiate close or possibly go directly to - * the PPP_FSM_CLOSED state. - */ -void fsm_close(fsm *f, const char *reason) { - f->term_reason = reason; - f->term_reason_len = (reason == NULL? 0: LWIP_MIN(strlen(reason), 0xFF) ); - switch( f->state ){ - case PPP_FSM_STARTING: - f->state = PPP_FSM_INITIAL; - break; - case PPP_FSM_STOPPED: - f->state = PPP_FSM_CLOSED; - break; - case PPP_FSM_STOPPING: - f->state = PPP_FSM_CLOSING; - break; - - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - case PPP_FSM_OPENED: - terminate_layer(f, PPP_FSM_CLOSING); - break; - default: - break; - } -} - - -/* - * fsm_timeout - Timeout expired. - */ -static void fsm_timeout(void *arg) { - fsm *f = (fsm *) arg; - ppp_pcb *pcb = f->pcb; - - switch (f->state) { - case PPP_FSM_CLOSING: - case PPP_FSM_STOPPING: - if( f->retransmits <= 0 ){ - /* - * We've waited for an ack long enough. Peer probably heard us. - */ - f->state = (f->state == PPP_FSM_CLOSING)? PPP_FSM_CLOSED: PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - } else { - /* Send Terminate-Request */ - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (const u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); - --f->retransmits; - } - break; - - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - if (f->retransmits <= 0) { - ppp_warn("%s: timeout sending Config-Requests", PROTO_NAME(f)); - f->state = PPP_FSM_STOPPED; - if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) - (*f->callbacks->finished)(f); - - } else { - /* Retransmit the configure-request */ - if (f->callbacks->retransmit) - (*f->callbacks->retransmit)(f); - fsm_sconfreq(f, 1); /* Re-send Configure-Request */ - if( f->state == PPP_FSM_ACKRCVD ) - f->state = PPP_FSM_REQSENT; - } - break; - - default: - FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_input - Input packet. - */ -void fsm_input(fsm *f, u_char *inpacket, int l) { - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < HEADERLEN) { - FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol)); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < HEADERLEN) { - FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol)); - return; - } - if (len > l) { - FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol)); - return; - } - len -= HEADERLEN; /* subtract header length */ - - if( f->state == PPP_FSM_INITIAL || f->state == PPP_FSM_STARTING ){ - FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.", - f->protocol, f->state)); - return; - } - - /* - * Action depends on code. - */ - switch (code) { - case CONFREQ: - fsm_rconfreq(f, id, inp, len); - break; - - case CONFACK: - fsm_rconfack(f, id, inp, len); - break; - - case CONFNAK: - case CONFREJ: - fsm_rconfnakrej(f, code, id, inp, len); - break; - - case TERMREQ: - fsm_rtermreq(f, id, inp, len); - break; - - case TERMACK: - fsm_rtermack(f); - break; - - case CODEREJ: - fsm_rcoderej(f, inp, len); - break; - - default: - if( !f->callbacks->extcode - || !(*f->callbacks->extcode)(f, code, id, inp, len) ) - fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); - break; - } -} - - -/* - * fsm_rconfreq - Receive Configure-Request. - */ -static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { - int code, reject_if_disagree; - - switch( f->state ){ - case PPP_FSM_CLOSED: - /* Go away, we're closed */ - fsm_sdata(f, TERMACK, id, NULL, 0); - return; - case PPP_FSM_CLOSING: - case PPP_FSM_STOPPING: - return; - - case PPP_FSM_OPENED: - /* Go down and restart negotiation */ - if( f->callbacks->down ) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_STOPPED: - /* Negotiation started by our peer */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } - - /* - * Pass the requested configuration options - * to protocol-specific code for checking. - */ - if (f->callbacks->reqci){ /* Check CI */ - reject_if_disagree = (f->nakloops >= f->maxnakloops); - code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree); - } else if (len) - code = CONFREJ; /* Reject all CI */ - else - code = CONFACK; - - /* send the Ack, Nak or Rej to the peer */ - fsm_sdata(f, code, id, inp, len); - - if (code == CONFACK) { - if (f->state == PPP_FSM_ACKRCVD) { - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = PPP_FSM_OPENED; - if (f->callbacks->up) - (*f->callbacks->up)(f); /* Inform upper layers */ - } else - f->state = PPP_FSM_ACKSENT; - f->nakloops = 0; - - } else { - /* we sent CONFACK or CONFREJ */ - if (f->state != PPP_FSM_ACKRCVD) - f->state = PPP_FSM_REQSENT; - if( code == CONFNAK ) - ++f->nakloops; - } -} - - -/* - * fsm_rconfack - Receive Configure-Ack. - */ -static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { - ppp_pcb *pcb = f->pcb; - - if (id != f->reqid || f->seen_ack) /* Expected id? */ - return; /* Nope, toss... */ - if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): - (len == 0)) ){ - /* Ack is bad - ignore it */ - ppp_error("Received bad configure-ack: %P", inp, len); - return; - } - f->seen_ack = 1; - f->rnakloops = 0; - - switch (f->state) { - case PPP_FSM_CLOSED: - case PPP_FSM_STOPPED: - fsm_sdata(f, TERMACK, id, NULL, 0); - break; - - case PPP_FSM_REQSENT: - f->state = PPP_FSM_ACKRCVD; - f->retransmits = pcb->settings.fsm_max_conf_req_transmits; - break; - - case PPP_FSM_ACKRCVD: - /* Huh? an extra valid Ack? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - f->state = PPP_FSM_OPENED; - f->retransmits = pcb->settings.fsm_max_conf_req_transmits; - if (f->callbacks->up) - (*f->callbacks->up)(f); /* Inform upper layers */ - break; - - case PPP_FSM_OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } -} - - -/* - * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. - */ -static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { - int ret; - int treat_as_reject; - - if (id != f->reqid || f->seen_ack) /* Expected id? */ - return; /* Nope, toss... */ - - if (code == CONFNAK) { - ++f->rnakloops; - treat_as_reject = (f->rnakloops >= f->maxnakloops); - if (f->callbacks->nakci == NULL - || !(ret = f->callbacks->nakci(f, inp, len, treat_as_reject))) { - ppp_error("Received bad configure-nak: %P", inp, len); - return; - } - } else { - f->rnakloops = 0; - if (f->callbacks->rejci == NULL - || !(ret = f->callbacks->rejci(f, inp, len))) { - ppp_error("Received bad configure-rej: %P", inp, len); - return; - } - } - - f->seen_ack = 1; - - switch (f->state) { - case PPP_FSM_CLOSED: - case PPP_FSM_STOPPED: - fsm_sdata(f, TERMACK, id, NULL, 0); - break; - - case PPP_FSM_REQSENT: - case PPP_FSM_ACKSENT: - /* They didn't agree to what we wanted - try another request */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - if (ret < 0) - f->state = PPP_FSM_STOPPED; /* kludge for stopping CCP */ - else - fsm_sconfreq(f, 0); /* Send Configure-Request */ - break; - - case PPP_FSM_ACKRCVD: - /* Got a Nak/reject when we had already had an Ack?? oh well... */ - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_OPENED: - /* Go down and restart negotiation */ - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); /* Send initial Configure-Request */ - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } -} - - -/* - * fsm_rtermreq - Receive Terminate-Req. - */ -static void fsm_rtermreq(fsm *f, int id, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - - switch (f->state) { - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - f->state = PPP_FSM_REQSENT; /* Start over but keep trying */ - break; - - case PPP_FSM_OPENED: - if (len > 0) { - ppp_info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p); - } else - ppp_info("%s terminated by peer", PROTO_NAME(f)); - f->retransmits = 0; - f->state = PPP_FSM_STOPPING; - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); - break; - default: - break; - } - - fsm_sdata(f, TERMACK, id, NULL, 0); -} - - -/* - * fsm_rtermack - Receive Terminate-Ack. - */ -static void fsm_rtermack(fsm *f) { - switch (f->state) { - case PPP_FSM_CLOSING: - UNTIMEOUT(fsm_timeout, f); - f->state = PPP_FSM_CLOSED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - case PPP_FSM_STOPPING: - UNTIMEOUT(fsm_timeout, f); - f->state = PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case PPP_FSM_ACKRCVD: - f->state = PPP_FSM_REQSENT; - break; - - case PPP_FSM_OPENED: - if (f->callbacks->down) - (*f->callbacks->down)(f); /* Inform upper layers */ - fsm_sconfreq(f, 0); - f->state = PPP_FSM_REQSENT; - break; - default: - break; - } -} - - -/* - * fsm_rcoderej - Receive an Code-Reject. - */ -static void fsm_rcoderej(fsm *f, u_char *inp, int len) { - u_char code, id; - - if (len < HEADERLEN) { - FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - ppp_warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id); - - if( f->state == PPP_FSM_ACKRCVD ) - f->state = PPP_FSM_REQSENT; -} - - -/* - * fsm_protreject - Peer doesn't speak this protocol. - * - * Treat this as a catastrophic error (RXJ-). - */ -void fsm_protreject(fsm *f) { - switch( f->state ){ - case PPP_FSM_CLOSING: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - /* no break */ - case PPP_FSM_CLOSED: - f->state = PPP_FSM_CLOSED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case PPP_FSM_STOPPING: - case PPP_FSM_REQSENT: - case PPP_FSM_ACKRCVD: - case PPP_FSM_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - /* no break */ - case PPP_FSM_STOPPED: - f->state = PPP_FSM_STOPPED; - if( f->callbacks->finished ) - (*f->callbacks->finished)(f); - break; - - case PPP_FSM_OPENED: - terminate_layer(f, PPP_FSM_STOPPING); - break; - - default: - FSMDEBUG(("%s: Protocol-reject event in state %d!", - PROTO_NAME(f), f->state)); - /* no break */ - } -} - - -/* - * fsm_sconfreq - Send a Configure-Request. - */ -static void fsm_sconfreq(fsm *f, int retransmit) { - ppp_pcb *pcb = f->pcb; - struct pbuf *p; - u_char *outp; - int cilen; - - if( f->state != PPP_FSM_REQSENT && f->state != PPP_FSM_ACKRCVD && f->state != PPP_FSM_ACKSENT ){ - /* Not currently negotiating - reset options */ - if( f->callbacks->resetci ) - (*f->callbacks->resetci)(f); - f->nakloops = 0; - f->rnakloops = 0; - } - - if( !retransmit ){ - /* New request - reset retransmission counter, use new ID */ - f->retransmits = pcb->settings.fsm_max_conf_req_transmits; - f->reqid = ++f->id; - } - - f->seen_ack = 0; - - /* - * Make up the request packet - */ - if( f->callbacks->cilen && f->callbacks->addci ){ - cilen = (*f->callbacks->cilen)(f); - if( cilen > pcb->peer_mru - HEADERLEN ) - cilen = pcb->peer_mru - HEADERLEN; - } else - cilen = 0; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(cilen + HEADERLEN + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - /* send the request to our peer */ - outp = (u_char*)p->payload; - MAKEHEADER(outp, f->protocol); - PUTCHAR(CONFREQ, outp); - PUTCHAR(f->reqid, outp); - PUTSHORT(cilen + HEADERLEN, outp); - if (cilen != 0) { - (*f->callbacks->addci)(f, outp, &cilen); - LWIP_ASSERT("cilen == p->len - HEADERLEN - PPP_HDRLEN", cilen == p->len - HEADERLEN - PPP_HDRLEN); - } - - ppp_write(pcb, p); - - /* start the retransmit timer */ - --f->retransmits; - TIMEOUT(fsm_timeout, f, pcb->settings.fsm_timeout_time); -} - - -/* - * fsm_sdata - Send some data. - * - * Used for all packets sent to our peer by this module. - */ -void fsm_sdata(fsm *f, u_char code, u_char id, const u_char *data, int datalen) { - ppp_pcb *pcb = f->pcb; - struct pbuf *p; - u_char *outp; - int outlen; - - /* Adjust length to be smaller than MTU */ - if (datalen > pcb->peer_mru - HEADERLEN) - datalen = pcb->peer_mru - HEADERLEN; - outlen = datalen + HEADERLEN; - - p = pbuf_alloc(PBUF_RAW, (u16_t)(outlen + PPP_HDRLEN), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - if (datalen) /* && data != outp + PPP_HDRLEN + HEADERLEN) -- was only for fsm_sconfreq() */ - MEMCPY(outp + PPP_HDRLEN + HEADERLEN, data, datalen); - MAKEHEADER(outp, f->protocol); - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - ppp_write(pcb, p); -} - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/ipcp.c b/components/net/lwip-2.0.2/src/netif/ppp/ipcp.c deleted file mode 100644 index b7c766eb0b..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/ipcp.c +++ /dev/null @@ -1,2418 +0,0 @@ -/* - * ipcp.c - PPP IP Control Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/ipcp.h" - -#if 0 /* UNUSED */ -/* global vars */ -u32_t netmask = 0; /* IP netmask to set on interface */ -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */ -#endif /* UNUSED */ - -#if 0 /* moved to ppp_settings */ -bool noremoteip = 0; /* Let him have no IP address */ -#endif /* moved to ppp_setting */ - -#if 0 /* UNUSED */ -/* Hook for a plugin to know when IP protocol has come up */ -void (*ip_up_hook) (void) = NULL; - -/* Hook for a plugin to know when IP protocol has come down */ -void (*ip_down_hook) (void) = NULL; - -/* Hook for a plugin to choose the remote IP address */ -void (*ip_choose_hook) (u32_t *) = NULL; -#endif /* UNUSED */ - -#if PPP_NOTIFY -/* Notifiers for when IPCP goes up and down */ -struct notifier *ip_up_notifier = NULL; -struct notifier *ip_down_notifier = NULL; -#endif /* PPP_NOTIFY */ - -/* local vars */ -#if 0 /* moved to ppp_pcb */ -static int default_route_set[NUM_PPP]; /* Have set up a default route */ -static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ -static int ipcp_is_up; /* have called np_up() */ -static int ipcp_is_open; /* haven't called np_finished() */ -static bool ask_for_local; /* request our address from peer */ -#endif /* moved to ppp_pcb */ -#if 0 /* UNUSED */ -static char vj_value[8]; /* string form of vj option value */ -static char netmask_str[20]; /* string form of netmask value */ -#endif /* UNUSED */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipcp_resetci(fsm *f); /* Reset our CI */ -static int ipcp_cilen(fsm *f); /* Return length of our CI */ -static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ -static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ -static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */ -static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ -static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ -static void ipcp_up(fsm *f); /* We're UP */ -static void ipcp_down(fsm *f); /* We're DOWN */ -static void ipcp_finished(fsm *f); /* Don't need lower layer */ - -static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ - ipcp_resetci, /* Reset our Configuration Information */ - ipcp_cilen, /* Length of our Configuration Information */ - ipcp_addci, /* Add our Configuration Information */ - ipcp_ackci, /* ACK our Configuration Information */ - ipcp_nakci, /* NAK our Configuration Information */ - ipcp_rejci, /* Reject our Configuration Information */ - ipcp_reqci, /* Request peer's Configuration Information */ - ipcp_up, /* Called when fsm reaches OPENED state */ - ipcp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPCP" /* String name of protocol */ -}; - -/* - * Command-line options. - */ -#if PPP_OPTIONS -static int setvjslots (char **); -static int setdnsaddr (char **); -static int setwinsaddr (char **); -static int setnetmask (char **); -int setipaddr (char *, char **, int); - -static void printipaddr (option_t *, void (*)(void *, char *,...),void *); - -static option_t ipcp_option_list[] = { - { "noip", o_bool, &ipcp_protent.enabled_flag, - "Disable IP and IPCP" }, - { "-ip", o_bool, &ipcp_protent.enabled_flag, - "Disable IP and IPCP", OPT_ALIAS }, - - { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, - "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, - { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, - "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, - &ipcp_allowoptions[0].neg_vj }, - - { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, - "Disable VJ connection-ID compression", OPT_A2CLR, - &ipcp_allowoptions[0].cflag }, - { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, - "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, - &ipcp_allowoptions[0].cflag }, - - { "vj-max-slots", o_special, (void *)setvjslots, - "Set maximum VJ header slots", - OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, - - { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, - "Accept peer's address for us", 1 }, - { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, - "Accept peer's address for it", 1 }, - - { "ipparam", o_string, &ipparam, - "Set ip script parameter", OPT_PRIO }, - - { "noipdefault", o_bool, &disable_defaultip, - "Don't use name for default IP adrs", 1 }, - - { "ms-dns", 1, (void *)setdnsaddr, - "DNS address for the peer's use" }, - { "ms-wins", 1, (void *)setwinsaddr, - "Nameserver for SMB over TCP/IP for peer" }, - - { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, - "Set timeout for IPCP", OPT_PRIO }, - { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs", OPT_PRIO }, - { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs", OPT_PRIO }, - { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, - "Set max #conf-naks for IPCP", OPT_PRIO }, - - { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, - "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, - { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, - "disable defaultroute option", OPT_A2CLR, - &ipcp_wantoptions[0].default_route }, - { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, - "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, - &ipcp_wantoptions[0].default_route }, - - { "replacedefaultroute", o_bool, - &ipcp_wantoptions[0].replace_default_route, - "Replace default route", 1 - }, - { "noreplacedefaultroute", o_bool, - &ipcp_allowoptions[0].replace_default_route, - "Never replace default route", OPT_A2COPY, - &ipcp_wantoptions[0].replace_default_route }, - { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, - "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, - { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, - "disable proxyarp option", OPT_A2CLR, - &ipcp_wantoptions[0].proxy_arp }, - { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, - "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, - &ipcp_wantoptions[0].proxy_arp }, - - { "usepeerdns", o_bool, &usepeerdns, - "Ask peer for DNS address(es)", 1 }, - - { "netmask", o_special, (void *)setnetmask, - "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, - - { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs, - "Disable old-style IP-Addresses usage", OPT_A2CLR, - &ipcp_allowoptions[0].old_addrs }, - { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr, - "Disable IP-Address usage", OPT_A2CLR, - &ipcp_allowoptions[0].neg_addr }, - - { "noremoteip", o_bool, &noremoteip, - "Allow peer to have no IP address", 1 }, - - { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr, - "Don't send our IP address to peer", OPT_A2CLR, - &ipcp_wantoptions[0].old_addrs}, - - { "IP addresses", o_wild, (void *) &setipaddr, - "set local and remote IP addresses", - OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ipcp_init(ppp_pcb *pcb); -static void ipcp_open(ppp_pcb *pcb); -static void ipcp_close(ppp_pcb *pcb, const char *reason); -static void ipcp_lowerup(ppp_pcb *pcb); -static void ipcp_lowerdown(ppp_pcb *pcb); -static void ipcp_input(ppp_pcb *pcb, u_char *p, int len); -static void ipcp_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int ipcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS -static void ip_check_options (void); -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT -static int ip_demand_conf (int); -static int ip_active_pkt (u_char *, int); -#endif /* DEMAND_SUPPORT */ -#if 0 /* UNUSED */ -static void create_resolv (u32_t, u32_t); -#endif /* UNUSED */ - -const struct protent ipcp_protent = { - PPP_IPCP, - ipcp_init, - ipcp_input, - ipcp_protrej, - ipcp_lowerup, - ipcp_lowerdown, - ipcp_open, - ipcp_close, -#if PRINTPKT_SUPPORT - ipcp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "IPCP", - "IP", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ipcp_option_list, - ip_check_options, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - ip_demand_conf, - ip_active_pkt -#endif /* DEMAND_SUPPORT */ -}; - -static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute); - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ -#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ -#define CILEN_ADDR 6 /* new-style single address option */ -#define CILEN_ADDRS 10 /* old-style dual address option */ - - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -#if 0 /* UNUSED, already defined by lwIP */ -/* - * Make a string representation of a network IP address. - */ -char * -ip_ntoa(ipaddr) -u32_t ipaddr; -{ - static char b[64]; - - slprintf(b, sizeof(b), "%I", ipaddr); - return b; -} -#endif /* UNUSED, already defined by lwIP */ - -/* - * Option parsing. - */ -#if PPP_OPTIONS -/* - * setvjslots - set maximum number of connection slots for VJ compression - */ -static int -setvjslots(argv) - char **argv; -{ - int value; - - if (!int_option(*argv, &value)) - return 0; - - if (value < 2 || value > 16) { - option_error("vj-max-slots value must be between 2 and 16"); - return 0; - } - ipcp_wantoptions [0].maxslotindex = - ipcp_allowoptions[0].maxslotindex = value - 1; - slprintf(vj_value, sizeof(vj_value), "%d", value); - return 1; -} - -/* - * setdnsaddr - set the dns address(es) - */ -static int -setdnsaddr(argv) - char **argv; -{ - u32_t dns; - struct hostent *hp; - - dns = inet_addr(*argv); - if (dns == (u32_t) -1) { - if ((hp = gethostbyname(*argv)) == NULL) { - option_error("invalid address parameter '%s' for ms-dns option", - *argv); - return 0; - } - dns = *(u32_t *)hp->h_addr; - } - - /* We take the last 2 values given, the 2nd-last as the primary - and the last as the secondary. If only one is given it - becomes both primary and secondary. */ - if (ipcp_allowoptions[0].dnsaddr[1] == 0) - ipcp_allowoptions[0].dnsaddr[0] = dns; - else - ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; - - /* always set the secondary address value. */ - ipcp_allowoptions[0].dnsaddr[1] = dns; - - return (1); -} - -/* - * setwinsaddr - set the wins address(es) - * This is primrarly used with the Samba package under UNIX or for pointing - * the caller to the existing WINS server on a Windows NT platform. - */ -static int -setwinsaddr(argv) - char **argv; -{ - u32_t wins; - struct hostent *hp; - - wins = inet_addr(*argv); - if (wins == (u32_t) -1) { - if ((hp = gethostbyname(*argv)) == NULL) { - option_error("invalid address parameter '%s' for ms-wins option", - *argv); - return 0; - } - wins = *(u32_t *)hp->h_addr; - } - - /* We take the last 2 values given, the 2nd-last as the primary - and the last as the secondary. If only one is given it - becomes both primary and secondary. */ - if (ipcp_allowoptions[0].winsaddr[1] == 0) - ipcp_allowoptions[0].winsaddr[0] = wins; - else - ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; - - /* always set the secondary address value. */ - ipcp_allowoptions[0].winsaddr[1] = wins; - - return (1); -} - -/* - * setipaddr - Set the IP address - * If doit is 0, the call is to check whether this option is - * potentially an IP address specification. - * Not static so that plugins can call it to set the addresses - */ -int -setipaddr(arg, argv, doit) - char *arg; - char **argv; - int doit; -{ - struct hostent *hp; - char *colon; - u32_t local, remote; - ipcp_options *wo = &ipcp_wantoptions[0]; - static int prio_local = 0, prio_remote = 0; - - /* - * IP address pair separated by ":". - */ - if ((colon = strchr(arg, ':')) == NULL) - return 0; - if (!doit) - return 1; - - /* - * If colon first character, then no local addr. - */ - if (colon != arg && option_priority >= prio_local) { - *colon = '\0'; - if ((local = inet_addr(arg)) == (u32_t) -1) { - if ((hp = gethostbyname(arg)) == NULL) { - option_error("unknown host: %s", arg); - return 0; - } - local = *(u32_t *)hp->h_addr; - } - if (bad_ip_adrs(local)) { - option_error("bad local IP address %s", ip_ntoa(local)); - return 0; - } - if (local != 0) - wo->ouraddr = local; - *colon = ':'; - prio_local = option_priority; - } - - /* - * If colon last character, then no remote addr. - */ - if (*++colon != '\0' && option_priority >= prio_remote) { - if ((remote = inet_addr(colon)) == (u32_t) -1) { - if ((hp = gethostbyname(colon)) == NULL) { - option_error("unknown host: %s", colon); - return 0; - } - remote = *(u32_t *)hp->h_addr; - if (remote_name[0] == 0) - strlcpy(remote_name, colon, sizeof(remote_name)); - } - if (bad_ip_adrs(remote)) { - option_error("bad remote IP address %s", ip_ntoa(remote)); - return 0; - } - if (remote != 0) - wo->hisaddr = remote; - prio_remote = option_priority; - } - - return 1; -} - -static void -printipaddr(opt, printer, arg) - option_t *opt; - void (*printer) (void *, char *, ...); - void *arg; -{ - ipcp_options *wo = &ipcp_wantoptions[0]; - - if (wo->ouraddr != 0) - printer(arg, "%I", wo->ouraddr); - printer(arg, ":"); - if (wo->hisaddr != 0) - printer(arg, "%I", wo->hisaddr); -} - -/* - * setnetmask - set the netmask to be used on the interface. - */ -static int -setnetmask(argv) - char **argv; -{ - u32_t mask; - int n; - char *p; - - /* - * Unfortunately, if we use inet_addr, we can't tell whether - * a result of all 1s is an error or a valid 255.255.255.255. - */ - p = *argv; - n = parse_dotted_ip(p, &mask); - - mask = lwip_htonl(mask); - - if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { - option_error("invalid netmask value '%s'", *argv); - return 0; - } - - netmask = mask; - slprintf(netmask_str, sizeof(netmask_str), "%I", mask); - - return (1); -} - -int -parse_dotted_ip(p, vp) - char *p; - u32_t *vp; -{ - int n; - u32_t v, b; - char *endp, *p0 = p; - - v = 0; - for (n = 3;; --n) { - b = strtoul(p, &endp, 0); - if (endp == p) - return 0; - if (b > 255) { - if (n < 3) - return 0; - /* accept e.g. 0xffffff00 */ - *vp = b; - return endp - p0; - } - v |= b << (n * 8); - p = endp; - if (n == 0) - break; - if (*p != '.') - return 0; - ++p; - } - *vp = v; - return p - p0; -} -#endif /* PPP_OPTIONS */ - -/* - * ipcp_init - Initialize IPCP. - */ -static void ipcp_init(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - - ipcp_options *wo = &pcb->ipcp_wantoptions; - ipcp_options *ao = &pcb->ipcp_allowoptions; - - f->pcb = pcb; - f->protocol = PPP_IPCP; - f->callbacks = &ipcp_callbacks; - fsm_init(f); - - /* - * Some 3G modems use repeated IPCP NAKs as a way of stalling - * until they can contact a server on the network, so we increase - * the default number of NAKs we accept before we start treating - * them as rejects. - */ - f->maxnakloops = 100; - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); -#endif /* 0 */ - - wo->neg_addr = wo->old_addrs = 1; -#if VJ_SUPPORT - wo->neg_vj = 1; - wo->vj_protocol = IPCP_VJ_COMP; - wo->maxslotindex = MAX_STATES - 1; /* really max index */ - wo->cflag = 1; -#endif /* VJ_SUPPORT */ - -#if 0 /* UNUSED */ - /* wanting default route by default */ - wo->default_route = 1; -#endif /* UNUSED */ - - ao->neg_addr = ao->old_addrs = 1; -#if VJ_SUPPORT - /* max slots and slot-id compression are currently hardwired in */ - /* ppp_if.c to 16 and 1, this needs to be changed (among other */ - /* things) gmc */ - - ao->neg_vj = 1; - ao->maxslotindex = MAX_STATES - 1; - ao->cflag = 1; -#endif /* #if VJ_SUPPORT */ - -#if 0 /* UNUSED */ - /* - * XXX These control whether the user may use the proxyarp - * and defaultroute options. - */ - ao->proxy_arp = 1; - ao->default_route = 1; -#endif /* UNUSED */ -} - - -/* - * ipcp_open - IPCP is allowed to come up. - */ -static void ipcp_open(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_open(f); - pcb->ipcp_is_open = 1; -} - - -/* - * ipcp_close - Take IPCP down. - */ -static void ipcp_close(ppp_pcb *pcb, const char *reason) { - fsm *f = &pcb->ipcp_fsm; - fsm_close(f, reason); -} - - -/* - * ipcp_lowerup - The lower layer is up. - */ -static void ipcp_lowerup(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_lowerup(f); -} - - -/* - * ipcp_lowerdown - The lower layer is down. - */ -static void ipcp_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_lowerdown(f); -} - - -/* - * ipcp_input - Input IPCP packet. - */ -static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->ipcp_fsm; - fsm_input(f, p, len); -} - - -/* - * ipcp_protrej - A Protocol-Reject was received for IPCP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void ipcp_protrej(ppp_pcb *pcb) { - fsm *f = &pcb->ipcp_fsm; - fsm_lowerdown(f); -} - - -/* - * ipcp_resetci - Reset our CI. - * Called by fsm_sconfreq, Send Configure Request. - */ -static void ipcp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipcp_options *wo = &pcb->ipcp_wantoptions; - ipcp_options *go = &pcb->ipcp_gotoptions; - ipcp_options *ao = &pcb->ipcp_allowoptions; - - wo->req_addr = (wo->neg_addr || wo->old_addrs) && - (ao->neg_addr || ao->old_addrs); - if (wo->ouraddr == 0) - wo->accept_local = 1; - if (wo->hisaddr == 0) - wo->accept_remote = 1; -#if LWIP_DNS - wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */ -#endif /* LWIP_DNS */ - *go = *wo; - if (!pcb->ask_for_local) - go->ouraddr = 0; -#if 0 /* UNUSED */ - if (ip_choose_hook) { - ip_choose_hook(&wo->hisaddr); - if (wo->hisaddr) { - wo->accept_remote = 0; - } - } -#endif /* UNUSED */ - BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options)); -} - - -/* - * ipcp_cilen - Return length of our CI. - * Called by fsm_sconfreq, Send Configure Request. - */ -static int ipcp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; -#if VJ_SUPPORT - ipcp_options *wo = &pcb->ipcp_wantoptions; -#endif /* VJ_SUPPORT */ - ipcp_options *ho = &pcb->ipcp_hisoptions; - -#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0) -#if VJ_SUPPORT -#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0) -#endif /* VJ_SUPPORT */ -#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0) -#if LWIP_DNS -#define LENCIDNS(neg) LENCIADDR(neg) -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ -#define LENCIWINS(neg) LENCIADDR(neg) -#endif /* UNUSED - WINS */ - - /* - * First see if we want to change our options to the old - * forms because we have received old forms from the peer. - */ - if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs) - go->neg_addr = 0; - -#if VJ_SUPPORT - if (wo->neg_vj && !go->neg_vj && !go->old_vj) { - /* try an older style of VJ negotiation */ - /* use the old style only if the peer did */ - if (ho->neg_vj && ho->old_vj) { - go->neg_vj = 1; - go->old_vj = 1; - go->vj_protocol = ho->vj_protocol; - } - } -#endif /* VJ_SUPPORT */ - - return (LENCIADDRS(!go->neg_addr && go->old_addrs) + -#if VJ_SUPPORT - LENCIVJ(go->neg_vj, go->old_vj) + -#endif /* VJ_SUPPORT */ - LENCIADDR(go->neg_addr) + -#if LWIP_DNS - LENCIDNS(go->req_dns1) + - LENCIDNS(go->req_dns2) + -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - LENCIWINS(go->winsaddr[0]) + - LENCIWINS(go->winsaddr[1]) + -#endif /* UNUSED - WINS */ - 0); -} - - -/* - * ipcp_addci - Add our desired CIs to a packet. - * Called by fsm_sconfreq, Send Configure Request. - */ -static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - int len = *lenp; - -#define ADDCIADDRS(opt, neg, val1, val2) \ - if (neg) { \ - if (len >= CILEN_ADDRS) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDRS, ucp); \ - l = lwip_ntohl(val1); \ - PUTLONG(l, ucp); \ - l = lwip_ntohl(val2); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDRS; \ - } else \ - go->old_addrs = 0; \ - } - -#if VJ_SUPPORT -#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - if (!old) { \ - PUTCHAR(maxslotindex, ucp); \ - PUTCHAR(cflag, ucp); \ - } \ - len -= vjlen; \ - } else \ - neg = 0; \ - } -#endif /* VJ_SUPPORT */ - -#define ADDCIADDR(opt, neg, val) \ - if (neg) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = lwip_ntohl(val); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else \ - neg = 0; \ - } - -#if LWIP_DNS -#define ADDCIDNS(opt, neg, addr) \ - if (neg) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = lwip_ntohl(addr); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else \ - neg = 0; \ - } -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ -#define ADDCIWINS(opt, addr) \ - if (addr) { \ - if (len >= CILEN_ADDR) { \ - u32_t l; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_ADDR, ucp); \ - l = lwip_ntohl(addr); \ - PUTLONG(l, ucp); \ - len -= CILEN_ADDR; \ - } else \ - addr = 0; \ - } -#endif /* UNUSED - WINS */ - - ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, - go->hisaddr); - -#if VJ_SUPPORT - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); -#endif /* VJ_SUPPORT */ - - ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); - -#if LWIP_DNS - ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); - - ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]); - - ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]); -#endif /* UNUSED - WINS */ - - *lenp -= len; -} - - -/* - * ipcp_ackci - Ack our CIs. - * Called by fsm_rconfack, Receive Configure ACK. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int ipcp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - u_short cilen, citype; - u32_t cilong; -#if VJ_SUPPORT - u_short cishort; - u_char cimaxslotindex, cicflag; -#endif /* VJ_SUPPORT */ - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#define ACKCIADDRS(opt, neg, val1, val2) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDRS) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDRS || \ - citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (val1 != cilong) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (val2 != cilong) \ - goto bad; \ - } - -#if VJ_SUPPORT -#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \ - if (neg) { \ - int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \ - if ((len -= vjlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslotindex) \ - goto bad; \ - GETCHAR(cicflag, p); \ - if (cicflag != cflag) \ - goto bad; \ - } \ - } -#endif /* VJ_SUPPORT */ - -#define ACKCIADDR(opt, neg, val) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || \ - citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (val != cilong) \ - goto bad; \ - } - -#if LWIP_DNS -#define ACKCIDNS(opt, neg, addr) \ - if (neg) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (addr != cilong) \ - goto bad; \ - } -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ -#define ACKCIWINS(opt, addr) \ - if (addr) { \ - u32_t l; \ - if ((len -= CILEN_ADDR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_ADDR || citype != opt) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - if (addr != cilong) \ - goto bad; \ - } -#endif /* UNUSED - WINS */ - - ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr, - go->hisaddr); - -#if VJ_SUPPORT - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); -#endif /* VJ_SUPPORT */ - - ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr); - -#if LWIP_DNS - ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]); - - ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]); -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]); - - ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]); -#endif /* UNUSED - WINS */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); - -bad: - IPCPDEBUG(("ipcp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPCP is in the OPENED state. - * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - u_char citype, cilen, *next; -#if VJ_SUPPORT - u_char cimaxslotindex, cicflag; - u_short cishort; -#endif /* VJ_SUPPORT */ - u32_t ciaddr1, ciaddr2, l; -#if LWIP_DNS - u32_t cidnsaddr; -#endif /* LWIP_DNS */ - ipcp_options no; /* options we've seen Naks for */ - ipcp_options try_; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try_ = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIADDRS(opt, neg, code) \ - if ((neg) && \ - (cilen = p[1]) == CILEN_ADDRS && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - ciaddr1 = lwip_htonl(l); \ - GETLONG(l, p); \ - ciaddr2 = lwip_htonl(l); \ - no.old_addrs = 1; \ - code \ - } - -#if VJ_SUPPORT -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#endif /* VJ_SUPPORT */ - -#define NAKCIADDR(opt, neg, code) \ - if (go->neg && \ - (cilen = p[1]) == CILEN_ADDR && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - ciaddr1 = lwip_htonl(l); \ - no.neg = 1; \ - code \ - } - -#if LWIP_DNS -#define NAKCIDNS(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cidnsaddr = lwip_htonl(l); \ - no.neg = 1; \ - code \ - } -#endif /* LWIP_DNS */ - - /* - * Accept the peer's idea of {our,his} address, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, - if (treat_as_reject) { - try_.old_addrs = 0; - } else { - if (go->accept_local && ciaddr1) { - /* take his idea of our address */ - try_.ouraddr = ciaddr1; - } - if (go->accept_remote && ciaddr2) { - /* take his idea of his address */ - try_.hisaddr = ciaddr2; - } - } - ); - -#if VJ_SUPPORT - /* - * Accept the peer's value of maxslotindex provided that it - * is less than what we asked for. Turn off slot-ID compression - * if the peer wants. Send old-style compress-type option if - * the peer wants. - */ - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - if (treat_as_reject) { - try_.neg_vj = 0; - } else if (cilen == CILEN_VJ) { - GETCHAR(cimaxslotindex, p); - GETCHAR(cicflag, p); - if (cishort == IPCP_VJ_COMP) { - try_.old_vj = 0; - if (cimaxslotindex < go->maxslotindex) - try_.maxslotindex = cimaxslotindex; - if (!cicflag) - try_.cflag = 0; - } else { - try_.neg_vj = 0; - } - } else { - if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) { - try_.old_vj = 1; - try_.vj_protocol = cishort; - } else { - try_.neg_vj = 0; - } - } - ); -#endif /* VJ_SUPPORT */ - - NAKCIADDR(CI_ADDR, neg_addr, - if (treat_as_reject) { - try_.neg_addr = 0; - try_.old_addrs = 0; - } else if (go->accept_local && ciaddr1) { - /* take his idea of our address */ - try_.ouraddr = ciaddr1; - } - ); - -#if LWIP_DNS - NAKCIDNS(CI_MS_DNS1, req_dns1, - if (treat_as_reject) { - try_.req_dns1 = 0; - } else { - try_.dnsaddr[0] = cidnsaddr; - } - ); - - NAKCIDNS(CI_MS_DNS2, req_dns2, - if (treat_as_reject) { - try_.req_dns2 = 0; - } else { - try_.dnsaddr[1] = cidnsaddr; - } - ); -#endif /* #if LWIP_DNS */ - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about IP addresses, we comply. - * If they want us to ask for compression, we refuse. - * If they want us to ask for ms-dns, we do that, since some - * peers get huffy if we don't. - */ - while (len >= CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) - goto bad; - next = p + cilen - 2; - - switch (citype) { -#if VJ_SUPPORT - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) - goto bad; - no.neg_vj = 1; - break; -#endif /* VJ_SUPPORT */ - case CI_ADDRS: - if ((!go->neg_addr && go->old_addrs) || no.old_addrs - || cilen != CILEN_ADDRS) - goto bad; - try_.neg_addr = 0; - GETLONG(l, p); - ciaddr1 = lwip_htonl(l); - if (ciaddr1 && go->accept_local) - try_.ouraddr = ciaddr1; - GETLONG(l, p); - ciaddr2 = lwip_htonl(l); - if (ciaddr2 && go->accept_remote) - try_.hisaddr = ciaddr2; - no.old_addrs = 1; - break; - case CI_ADDR: - if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) - goto bad; - try_.old_addrs = 0; - GETLONG(l, p); - ciaddr1 = lwip_htonl(l); - if (ciaddr1 && go->accept_local) - try_.ouraddr = ciaddr1; - if (try_.ouraddr != 0) - try_.neg_addr = 1; - no.neg_addr = 1; - break; -#if LWIP_DNS - case CI_MS_DNS1: - if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR) - goto bad; - GETLONG(l, p); - try_.dnsaddr[0] = lwip_htonl(l); - try_.req_dns1 = 1; - no.req_dns1 = 1; - break; - case CI_MS_DNS2: - if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR) - goto bad; - GETLONG(l, p); - try_.dnsaddr[1] = lwip_htonl(l); - try_.req_dns2 = 1; - no.req_dns2 = 1; - break; -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - case CI_MS_WINS1: - case CI_MS_WINS2: - if (cilen != CILEN_ADDR) - goto bad; - GETLONG(l, p); - ciaddr1 = lwip_htonl(l); - if (ciaddr1) - try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1; - break; -#endif /* UNUSED - WINS */ - default: - break; - } - p = next; - } - - /* - * OK, the Nak is good. Now we can update state. - * If there are any remaining options, we ignore them. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - - return 1; - -bad: - IPCPDEBUG(("ipcp_nakci: received bad Nak!")); - return 0; -} - - -/* - * ipcp_rejci - Reject some of our CIs. - * Callback from fsm_rconfnakrej. - */ -static int ipcp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipcp_options *go = &pcb->ipcp_gotoptions; - u_char cilen; -#if VJ_SUPPORT - u_char cimaxslotindex, ciflag; - u_short cishort; -#endif /* VJ_SUPPORT */ - u32_t cilong; - ipcp_options try_; /* options to request next time */ - - try_ = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIADDRS(opt, neg, val1, val2) \ - if ((neg) && \ - (cilen = p[1]) == CILEN_ADDRS && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val1) \ - goto bad; \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val2) \ - goto bad; \ - try_.old_addrs = 0; \ - } - -#if VJ_SUPPORT -#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \ - if (go->neg && \ - p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - if (!old) { \ - GETCHAR(cimaxslotindex, p); \ - if (cimaxslotindex != maxslot) \ - goto bad; \ - GETCHAR(ciflag, p); \ - if (ciflag != cflag) \ - goto bad; \ - } \ - try_.neg = 0; \ - } -#endif /* VJ_SUPPORT */ - -#define REJCIADDR(opt, neg, val) \ - if (go->neg && \ - (cilen = p[1]) == CILEN_ADDR && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != val) \ - goto bad; \ - try_.neg = 0; \ - } - -#if LWIP_DNS -#define REJCIDNS(opt, neg, dnsaddr) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != dnsaddr) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ -#define REJCIWINS(opt, addr) \ - if (addr && \ - ((cilen = p[1]) == CILEN_ADDR) && \ - len >= cilen && \ - p[0] == opt) { \ - u32_t l; \ - len -= cilen; \ - INCPTR(2, p); \ - GETLONG(l, p); \ - cilong = lwip_htonl(l); \ - /* Check rejected value. */ \ - if (cilong != addr) \ - goto bad; \ - try_.winsaddr[opt == CI_MS_WINS2] = 0; \ - } -#endif /* UNUSED - WINS */ - - REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, - go->ouraddr, go->hisaddr); - -#if VJ_SUPPORT - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj, - go->maxslotindex, go->cflag); -#endif /* VJ_SUPPORT */ - - REJCIADDR(CI_ADDR, neg_addr, go->ouraddr); - -#if LWIP_DNS - REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]); - - REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]); -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - REJCIWINS(CI_MS_WINS1, go->winsaddr[0]); - - REJCIWINS(CI_MS_WINS2, go->winsaddr[1]); -#endif /* UNUSED - WINS */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; - -bad: - IPCPDEBUG(("ipcp_rejci: received bad Reject!")); - return 0; -} - - -/* - * ipcp_reqci - Check the peer's requested CIs and send appropriate response. - * Callback from fsm_rconfreq, Receive Configure Request - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - * - * inp = Requested CIs - * len = Length of requested CIs - */ -static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { - ppp_pcb *pcb = f->pcb; - ipcp_options *wo = &pcb->ipcp_wantoptions; - ipcp_options *ho = &pcb->ipcp_hisoptions; - ipcp_options *ao = &pcb->ipcp_allowoptions; - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ -#if VJ_SUPPORT - u_short cishort; /* Parsed short value */ -#endif /* VJ_SUPPORT */ - u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ -#if VJ_SUPPORT - u_char maxslotindex, cflag; -#endif /* VJ_SUPPORT */ -#if LWIP_DNS - int d; -#endif /* LWIP_DNS */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPCPDEBUG(("ipcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_ADDRS: - if (!ao->old_addrs || ho->neg_addr || - cilen != CILEN_ADDRS) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = lwip_htonl(tl); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * If neither we nor he knows his address, reject the option. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - /* - * If he doesn't know our address, or if we both have our address - * but disagree about it, then NAK it with our idea. - */ - GETLONG(tl, p); /* Parse desination address (ours) */ - ciaddr2 = lwip_htonl(tl); - if (ciaddr2 != wo->ouraddr) { - if (ciaddr2 == 0 || !wo->accept_local) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(wo->ouraddr); - PUTLONG(tl, p); - } - } else { - wo->ouraddr = ciaddr2; /* accept peer's idea */ - } - } - - ho->old_addrs = 1; - ho->hisaddr = ciaddr1; - ho->ouraddr = ciaddr2; - break; - - case CI_ADDR: - if (!ao->neg_addr || ho->old_addrs || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no address, or if we both have his address but - * disagree about it, then NAK it with our idea. - * In particular, if we don't know his address, but he does, - * then accept it. - */ - GETLONG(tl, p); /* Parse source address (his) */ - ciaddr1 = lwip_htonl(tl); - if (ciaddr1 != wo->hisaddr - && (ciaddr1 == 0 || !wo->accept_remote)) { - orc = CONFNAK; - if (!reject_if_disagree) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(wo->hisaddr); - PUTLONG(tl, p); - } - } else if (ciaddr1 == 0 && wo->hisaddr == 0) { - /* - * Don't ACK an address of 0.0.0.0 - reject it instead. - */ - orc = CONFREJ; - wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ - break; - } - - ho->neg_addr = 1; - ho->hisaddr = ciaddr1; - break; - -#if LWIP_DNS - case CI_MS_DNS1: - case CI_MS_DNS2: - /* Microsoft primary or secondary DNS request */ - d = citype == CI_MS_DNS2; - - /* If we do not have a DNS address then we cannot send it */ - if (ao->dnsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (lwip_htonl(tl) != ao->dnsaddr[d]) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(ao->dnsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; -#endif /* LWIP_DNS */ - -#if 0 /* UNUSED - WINS */ - case CI_MS_WINS1: - case CI_MS_WINS2: - /* Microsoft primary or secondary WINS request */ - d = citype == CI_MS_WINS2; - - /* If we do not have a DNS address then we cannot send it */ - if (ao->winsaddr[d] == 0 || - cilen != CILEN_ADDR) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETLONG(tl, p); - if (lwip_htonl(tl) != ao->winsaddr[d]) { - DECPTR(sizeof(u32_t), p); - tl = lwip_ntohl(ao->winsaddr[d]); - PUTLONG(tl, p); - orc = CONFNAK; - } - break; -#endif /* UNUSED - WINS */ - -#if VJ_SUPPORT - case CI_COMPRESSTYPE: - if (!ao->neg_vj || - (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) { - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - - if (!(cishort == IPCP_VJ_COMP || - (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { - orc = CONFREJ; - break; - } - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - if (cilen == CILEN_VJ) { - GETCHAR(maxslotindex, p); - if (maxslotindex > ao->maxslotindex) { - orc = CONFNAK; - if (!reject_if_disagree){ - DECPTR(1, p); - PUTCHAR(ao->maxslotindex, p); - } - } - GETCHAR(cflag, p); - if (cflag && !ao->cflag) { - orc = CONFNAK; - if (!reject_if_disagree){ - DECPTR(1, p); - PUTCHAR(wo->cflag, p); - } - } - ho->maxslotindex = maxslotindex; - ho->cflag = cflag; - } else { - ho->old_vj = 1; - ho->maxslotindex = MAX_STATES - 1; - ho->cflag = 1; - } - break; -#endif /* VJ_SUPPORT */ - - default: - orc = CONFREJ; - break; - } -endswitch: - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - MEMCPY(ucp, cip, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their address, and they didn't send their address, then we - * send a NAK with a CI_ADDR option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs && - wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) { - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_addr = 0; /* don't ask again */ - } - PUTCHAR(CI_ADDR, ucp); - PUTCHAR(CILEN_ADDR, ucp); - tl = lwip_ntohl(wo->hisaddr); - PUTLONG(tl, ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -#if 0 /* UNUSED */ -/* - * ip_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void -ip_check_options() -{ - struct hostent *hp; - u32_t local; - ipcp_options *wo = &ipcp_wantoptions[0]; - - /* - * Default our local IP address based on our hostname. - * If local IP address already given, don't bother. - */ - if (wo->ouraddr == 0 && !disable_defaultip) { - /* - * Look up our hostname (possibly with domain name appended) - * and take the first IP address as our local IP address. - * If there isn't an IP address for our hostname, too bad. - */ - wo->accept_local = 1; /* don't insist on this default value */ - if ((hp = gethostbyname(hostname)) != NULL) { - local = *(u32_t *)hp->h_addr; - if (local != 0 && !bad_ip_adrs(local)) - wo->ouraddr = local; - } - } - ask_for_local = wo->ouraddr != 0 || !disable_defaultip; -} -#endif /* UNUSED */ - -#if DEMAND_SUPPORT -/* - * ip_demand_conf - configure the interface as though - * IPCP were up, for use with dial-on-demand. - */ -static int -ip_demand_conf(u) - int u; -{ - ppp_pcb *pcb = &ppp_pcb_list[u]; - ipcp_options *wo = &ipcp_wantoptions[u]; - - if (wo->hisaddr == 0 && !pcb->settings.noremoteip) { - /* make up an arbitrary address for the peer */ - wo->hisaddr = lwip_htonl(0x0a707070 + ifunit); - wo->accept_remote = 1; - } - if (wo->ouraddr == 0) { - /* make up an arbitrary address for us */ - wo->ouraddr = lwip_htonl(0x0a404040 + ifunit); - wo->accept_local = 1; - ask_for_local = 0; /* don't tell the peer this address */ - } - if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr))) - return 0; - if (!sifup(pcb)) - return 0; - if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE)) - return 0; -#if 0 /* UNUSED */ - if (wo->default_route) - if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr, - wo->replace_default_route)) - default_route_set[u] = 1; -#endif /* UNUSED */ -#if 0 /* UNUSED - PROXY ARP */ - if (wo->proxy_arp) - if (sifproxyarp(pcb, wo->hisaddr)) - proxy_arp_set[u] = 1; -#endif /* UNUSED - PROXY ARP */ - - ppp_notice("local IP address %I", wo->ouraddr); - if (wo->hisaddr) - ppp_notice("remote IP address %I", wo->hisaddr); - - return 1; -} -#endif /* DEMAND_SUPPORT */ - -/* - * ipcp_up - IPCP has come UP. - * - * Configure the IP network interface appropriately and bring it up. - */ -static void ipcp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - u32_t mask; - ipcp_options *ho = &pcb->ipcp_hisoptions; - ipcp_options *go = &pcb->ipcp_gotoptions; - ipcp_options *wo = &pcb->ipcp_wantoptions; - - IPCPDEBUG(("ipcp: up")); - - /* - * We must have a non-zero IP address for both ends of the link. - */ - if (!ho->neg_addr && !ho->old_addrs) - ho->hisaddr = wo->hisaddr; - - if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs) - && wo->ouraddr != 0) { - ppp_error("Peer refused to agree to our IP address"); - ipcp_close(f->pcb, "Refused our IP address"); - return; - } - if (go->ouraddr == 0) { - ppp_error("Could not determine local IP address"); - ipcp_close(f->pcb, "Could not determine local IP address"); - return; - } - if (ho->hisaddr == 0 && !pcb->settings.noremoteip) { - ho->hisaddr = lwip_htonl(0x0a404040); - ppp_warn("Could not determine remote IP address: defaulting to %I", - ho->hisaddr); - } -#if 0 /* UNUSED */ - script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); - if (ho->hisaddr != 0) - script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); -#endif /* UNUSED */ - -#if LWIP_DNS - if (!go->req_dns1) - go->dnsaddr[0] = 0; - if (!go->req_dns2) - go->dnsaddr[1] = 0; -#if 0 /* UNUSED */ - if (go->dnsaddr[0]) - script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); - if (go->dnsaddr[1]) - script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); -#endif /* UNUSED */ - if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) { - sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); -#if 0 /* UNUSED */ - script_setenv("USEPEERDNS", "1", 0); - create_resolv(go->dnsaddr[0], go->dnsaddr[1]); -#endif /* UNUSED */ - } -#endif /* LWIP_DNS */ - - /* - * Check that the peer is allowed to use the IP address it wants. - */ - if (ho->hisaddr != 0) { - u32_t addr = lwip_ntohl(ho->hisaddr); - if ((addr >> IP_CLASSA_NSHIFT) == IP_LOOPBACKNET - || IP_MULTICAST(addr) || IP_BADCLASS(addr) - /* - * For now, consider that PPP in server mode with peer required - * to authenticate must provide the peer IP address, reject any - * IP address wanted by peer different than the one we wanted. - */ -#if PPP_SERVER && PPP_AUTH_SUPPORT - || (pcb->settings.auth_required && wo->hisaddr != ho->hisaddr) -#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */ - ) { - ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); - ipcp_close(pcb, "Unauthorized remote IP address"); - return; - } - } -#if 0 /* Unused */ - /* Upstream checking code */ - if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) { - ppp_error("Peer is not authorized to use remote address %I", ho->hisaddr); - ipcp_close(f->unit, "Unauthorized remote IP address"); - return; - } -#endif /* Unused */ - -#if VJ_SUPPORT - /* set tcp compression */ - sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex); -#endif /* VJ_SUPPORT */ - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, the interface is already - * configured, so we put out any saved-up packets, then set the - * interface to pass IP packets. - */ - if (demand) { - if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { - ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr, - wo->replace_default_route); - if (go->ouraddr != wo->ouraddr) { - ppp_warn("Local IP address changed to %I", go->ouraddr); - script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); - wo->ouraddr = go->ouraddr; - } else - script_unsetenv("OLDIPLOCAL"); - if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) { - ppp_warn("Remote IP address changed to %I", ho->hisaddr); - script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); - wo->hisaddr = ho->hisaddr; - } else - script_unsetenv("OLDIPREMOTE"); - - /* Set the interface to the new addresses */ - mask = get_mask(go->ouraddr); - if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { -#if PPP_DEBUG - ppp_warn("Interface configuration failed"); -#endif /* PPP_DEBUG */ - ipcp_close(f->unit, "Interface configuration failed"); - return; - } - - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) - if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, - wo->replace_default_route)) - default_route_set[f->unit] = 1; - -#if 0 /* UNUSED - PROXY ARP */ - /* Make a proxy ARP entry if requested. */ - if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp) - if (sifproxyarp(pcb, ho->hisaddr)) - proxy_arp_set[f->unit] = 1; -#endif /* UNUSED - PROXY ARP */ - - } - demand_rexmit(PPP_IP,go->ouraddr); - sifnpmode(pcb, PPP_IP, NPMODE_PASS); - - } else -#endif /* DEMAND_SUPPORT */ - { - /* - * Set IP addresses and (if specified) netmask. - */ - mask = get_mask(go->ouraddr); - -#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { -#if PPP_DEBUG - ppp_warn("Interface configuration failed"); -#endif /* PPP_DEBUG */ - ipcp_close(f->pcb, "Interface configuration failed"); - return; - } -#endif - - /* bring the interface up for IP */ - if (!sifup(pcb)) { -#if PPP_DEBUG - ppp_warn("Interface failed to come up"); -#endif /* PPP_DEBUG */ - ipcp_close(f->pcb, "Interface configuration failed"); - return; - } - -#if (defined(SVR4) && (defined(SNI) || defined(__USLC__))) - if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) { -#if PPP_DEBUG - ppp_warn("Interface configuration failed"); -#endif /* PPP_DEBUG */ - ipcp_close(f->unit, "Interface configuration failed"); - return; - } -#endif -#if DEMAND_SUPPORT - sifnpmode(pcb, PPP_IP, NPMODE_PASS); -#endif /* DEMAND_SUPPORT */ - -#if 0 /* UNUSED */ - /* assign a default route through the interface if required */ - if (wo->default_route) - if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr, - wo->replace_default_route)) - pcb->default_route_set = 1; -#endif /* UNUSED */ - -#if 0 /* UNUSED - PROXY ARP */ - /* Make a proxy ARP entry if requested. */ - if (ho->hisaddr != 0 && wo->proxy_arp) - if (sifproxyarp(pcb, ho->hisaddr)) - pcb->proxy_arp_set = 1; -#endif /* UNUSED - PROXY ARP */ - - wo->ouraddr = go->ouraddr; - - ppp_notice("local IP address %I", go->ouraddr); - if (ho->hisaddr != 0) - ppp_notice("remote IP address %I", ho->hisaddr); -#if LWIP_DNS - if (go->dnsaddr[0]) - ppp_notice("primary DNS address %I", go->dnsaddr[0]); - if (go->dnsaddr[1]) - ppp_notice("secondary DNS address %I", go->dnsaddr[1]); -#endif /* LWIP_DNS */ - } - -#if PPP_STATS_SUPPORT - reset_link_stats(f->unit); -#endif /* PPP_STATS_SUPPORT */ - - np_up(pcb, PPP_IP); - pcb->ipcp_is_up = 1; - -#if PPP_NOTIFY - notify(ip_up_notifier, 0); -#endif /* PPP_NOTIFY */ -#if 0 /* UNUSED */ - if (ip_up_hook) - ip_up_hook(); -#endif /* UNUSED */ -} - - -/* - * ipcp_down - IPCP has gone DOWN. - * - * Take the IP network interface down, clear its addresses - * and delete routes through it. - */ -static void ipcp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipcp_options *ho = &pcb->ipcp_hisoptions; - ipcp_options *go = &pcb->ipcp_gotoptions; - - IPCPDEBUG(("ipcp: down")); -#if PPP_STATS_SUPPORT - /* XXX a bit IPv4-centric here, we only need to get the stats - * before the interface is marked down. */ - /* XXX more correct: we must get the stats before running the notifiers, - * at least for the radius plugin */ - update_link_stats(f->unit); -#endif /* PPP_STATS_SUPPORT */ -#if PPP_NOTIFY - notify(ip_down_notifier, 0); -#endif /* PPP_NOTIFY */ -#if 0 /* UNUSED */ - if (ip_down_hook) - ip_down_hook(); -#endif /* UNUSED */ - if (pcb->ipcp_is_up) { - pcb->ipcp_is_up = 0; - np_down(pcb, PPP_IP); - } -#if VJ_SUPPORT - sifvjcomp(pcb, 0, 0, 0); -#endif /* VJ_SUPPORT */ - -#if PPP_STATS_SUPPORT - print_link_stats(); /* _after_ running the notifiers and ip_down_hook(), - * because print_link_stats() sets link_stats_valid - * to 0 (zero) */ -#endif /* PPP_STATS_SUPPORT */ - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, set the interface - * to queue up outgoing packets (for now). - */ - if (demand) { - sifnpmode(pcb, PPP_IP, NPMODE_QUEUE); - } else -#endif /* DEMAND_SUPPORT */ - { -#if DEMAND_SUPPORT - sifnpmode(pcb, PPP_IP, NPMODE_DROP); -#endif /* DEMAND_SUPPORT */ - sifdown(pcb); - ipcp_clear_addrs(pcb, go->ouraddr, - ho->hisaddr, 0); -#if LWIP_DNS - cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]); -#endif /* LWIP_DNS */ - } -} - - -/* - * ipcp_clear_addrs() - clear the interface addresses, routes, - * proxy arp entries, etc. - */ -static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) { - LWIP_UNUSED_ARG(replacedefaultroute); - -#if 0 /* UNUSED - PROXY ARP */ - if (pcb->proxy_arp_set) { - cifproxyarp(pcb, hisaddr); - pcb->proxy_arp_set = 0; - } -#endif /* UNUSED - PROXY ARP */ -#if 0 /* UNUSED */ - /* If replacedefaultroute, sifdefaultroute will be called soon - * with replacedefaultroute set and that will overwrite the current - * default route. This is the case only when doing demand, otherwise - * during demand, this cifdefaultroute would restore the old default - * route which is not what we want in this case. In the non-demand - * case, we'll delete the default route and restore the old if there - * is one saved by an sifdefaultroute with replacedefaultroute. - */ - if (!replacedefaultroute && pcb->default_route_set) { - cifdefaultroute(pcb, ouraddr, hisaddr); - pcb->default_route_set = 0; - } -#endif /* UNUSED */ - cifaddr(pcb, ouraddr, hisaddr); -} - - -/* - * ipcp_finished - possibly shut down the lower layers. - */ -static void ipcp_finished(fsm *f) { - ppp_pcb *pcb = f->pcb; - if (pcb->ipcp_is_open) { - pcb->ipcp_is_open = 0; - np_finished(pcb, PPP_IP); - } -} - - -#if 0 /* UNUSED */ -/* - * create_resolv - create the replacement resolv.conf file - */ -static void -create_resolv(peerdns1, peerdns2) - u32_t peerdns1, peerdns2; -{ - -} -#endif /* UNUSED */ - -#if PRINTPKT_SUPPORT -/* - * ipcp_printpkt - print the contents of an IPCP packet. - */ -static const char* const ipcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int ipcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len, olen; - const u_char *pstart, *optend; -#if VJ_SUPPORT - u_short cishort; -#endif /* VJ_SUPPORT */ - u32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipcp_codenames)) - printer(arg, " %s", ipcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_ADDRS: - if (olen == CILEN_ADDRS) { - p += 2; - GETLONG(cilong, p); - printer(arg, "addrs %I", lwip_htonl(cilong)); - GETLONG(cilong, p); - printer(arg, " %I", lwip_htonl(cilong)); - } - break; -#if VJ_SUPPORT - case CI_COMPRESSTYPE: - if (olen >= CILEN_COMPRESS) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "compress "); - switch (cishort) { - case IPCP_VJ_COMP: - printer(arg, "VJ"); - break; - case IPCP_VJ_COMP_OLD: - printer(arg, "old-VJ"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; -#endif /* VJ_SUPPORT */ - case CI_ADDR: - if (olen == CILEN_ADDR) { - p += 2; - GETLONG(cilong, p); - printer(arg, "addr %I", lwip_htonl(cilong)); - } - break; -#if LWIP_DNS - case CI_MS_DNS1: - case CI_MS_DNS2: - p += 2; - GETLONG(cilong, p); - printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2), - htonl(cilong)); - break; -#endif /* LWIP_DNS */ -#if 0 /* UNUSED - WINS */ - case CI_MS_WINS1: - case CI_MS_WINS2: - p += 2; - GETLONG(cilong, p); - printer(arg, "ms-wins %I", lwip_htonl(cilong)); - break; -#endif /* UNUSED - WINS */ - default: - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -#if DEMAND_SUPPORT -/* - * ip_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP_HDRLEN 20 /* bytes */ -#define IP_OFFMASK 0x1fff -#ifndef IPPROTO_TCP -#define IPPROTO_TCP 6 -#endif -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define net_short(x) (((x)[0] << 8) + (x)[1]) -#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF) -#define get_ipoff(x) net_short((unsigned char *)(x) + 6) -#define get_ipproto(x) (((unsigned char *)(x))[9]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int -ip_active_pkt(pkt, len) - u_char *pkt; - int len; -{ - u_char *tcp; - int hlen; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP_HDRLEN) - return 0; - if ((get_ipoff(pkt) & IP_OFFMASK) != 0) - return 0; - if (get_ipproto(pkt) != IPPROTO_TCP) - return 1; - hlen = get_iphl(pkt) * 4; - if (len < hlen + TCP_HDRLEN) - return 0; - tcp = pkt + hlen; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) - return 0; - return 1; -} -#endif /* DEMAND_SUPPORT */ - -#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/ipv6cp.c b/components/net/lwip-2.0.2/src/netif/ppp/ipv6cp.c deleted file mode 100644 index 11c18df743..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/ipv6cp.c +++ /dev/null @@ -1,1533 +0,0 @@ -/* - * ipv6cp.c - PPP IPV6 Control Protocol. - * - * Copyright (c) 1999 Tommi Komulainen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Tommi Komulainen - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* Original version, based on RFC2023 : - - Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE, - Alain.Durand@imag.fr, IMAG, - Jean-Luc.Richier@imag.fr, IMAG-LSR. - - Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt - Économique ayant pour membres BULL S.A. et l'INRIA). - - Ce logiciel informatique est disponible aux conditions - usuelles dans la recherche, c'est-à-dire qu'il peut - être utilisé, copié, modifié, distribué à l'unique - condition que ce texte soit conservé afin que - l'origine de ce logiciel soit reconnue. - - Le nom de l'Institut National de Recherche en Informatique - et en Automatique (INRIA), de l'IMAG, ou d'une personne morale - ou physique ayant participé à l'élaboration de ce logiciel ne peut - être utilisé sans son accord préalable explicite. - - Ce logiciel est fourni tel quel sans aucune garantie, - support ou responsabilité d'aucune sorte. - Ce logiciel est dérivé de sources d'origine - "University of California at Berkeley" et - "Digital Equipment Corporation" couvertes par des copyrights. - - L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG) - est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National - Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant - sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR). - - This work has been done in the context of GIE DYADE (joint R & D venture - between BULL S.A. and INRIA). - - This software is available with usual "research" terms - with the aim of retain credits of the software. - Permission to use, copy, modify and distribute this software for any - purpose and without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies, - and the name of INRIA, IMAG, or any contributor not be used in advertising - or publicity pertaining to this material without the prior explicit - permission. The software is provided "as is" without any - warranties, support or liabilities of any kind. - This software is derived from source code from - "University of California at Berkeley" and - "Digital Equipment Corporation" protected by copyrights. - - Grenoble's Institute of Computer Science and Applied Mathematics (IMAG) - is a federation of seven research units funded by the CNRS, National - Polytechnic Institute of Grenoble and University Joseph Fourier. - The research unit in Software, Systems, Networks (LSR) is member of IMAG. -*/ - -/* - * Derived from : - * - * - * ipcp.c - PPP IP Control Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $Id: ipv6cp.c,v 1.21 2005/08/25 23:59:34 paulus Exp $ - */ - -/* - * @todo: - * - * Proxy Neighbour Discovery. - * - * Better defines for selecting the ordering of - * interface up / set address. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPP_IPV6_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/fsm.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/ipv6cp.h" -#include "netif/ppp/magic.h" - -/* global vars */ -#if 0 /* UNUSED */ -int no_ifaceid_neg = 0; -#endif /* UNUSED */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void ipv6cp_resetci(fsm *f); /* Reset our CI */ -static int ipv6cp_cilen(fsm *f); /* Return length of our CI */ -static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */ -static int ipv6cp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ -static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ -static int ipv6cp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ -static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */ -static void ipv6cp_up(fsm *f); /* We're UP */ -static void ipv6cp_down(fsm *f); /* We're DOWN */ -static void ipv6cp_finished(fsm *f); /* Don't need lower layer */ - -static const fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ - ipv6cp_resetci, /* Reset our Configuration Information */ - ipv6cp_cilen, /* Length of our Configuration Information */ - ipv6cp_addci, /* Add our Configuration Information */ - ipv6cp_ackci, /* ACK our Configuration Information */ - ipv6cp_nakci, /* NAK our Configuration Information */ - ipv6cp_rejci, /* Reject our Configuration Information */ - ipv6cp_reqci, /* Request peer's Configuration Information */ - ipv6cp_up, /* Called when fsm reaches OPENED state */ - ipv6cp_down, /* Called when fsm leaves OPENED state */ - NULL, /* Called when we want the lower layer up */ - ipv6cp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - NULL, /* Called to handle protocol-specific codes */ - "IPV6CP" /* String name of protocol */ -}; - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static int setifaceid(char **arg)); -static void printifaceid(option_t *, - void (*)(void *, char *, ...), void *)); - -static option_t ipv6cp_option_list[] = { - { "ipv6", o_special, (void *)setifaceid, - "Set interface identifiers for IPV6", - OPT_A2PRINTER, (void *)printifaceid }, - - { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, - { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, - { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, - - { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, - "Accept peer's interface identifier for us", 1 }, - - { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, - "Use (default) IPv4 address as interface identifier", 1 }, - - { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, - "Use uniquely-available persistent value for link local address", 1 }, - - { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, - "Set timeout for IPv6CP", OPT_PRIO }, - { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs", OPT_PRIO }, - { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs", OPT_PRIO }, - { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, - "Set max #conf-naks for IPv6CP", OPT_PRIO }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points from main code. - */ -static void ipv6cp_init(ppp_pcb *pcb); -static void ipv6cp_open(ppp_pcb *pcb); -static void ipv6cp_close(ppp_pcb *pcb, const char *reason); -static void ipv6cp_lowerup(ppp_pcb *pcb); -static void ipv6cp_lowerdown(ppp_pcb *pcb); -static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len); -static void ipv6cp_protrej(ppp_pcb *pcb); -#if PPP_OPTIONS -static void ipv6_check_options(void); -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT -static int ipv6_demand_conf(int u); -#endif /* DEMAND_SUPPORT */ -#if PRINTPKT_SUPPORT -static int ipv6cp_printpkt(const u_char *p, int plen, - void (*printer)(void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ -#if DEMAND_SUPPORT -static int ipv6_active_pkt(u_char *pkt, int len); -#endif /* DEMAND_SUPPORT */ - -const struct protent ipv6cp_protent = { - PPP_IPV6CP, - ipv6cp_init, - ipv6cp_input, - ipv6cp_protrej, - ipv6cp_lowerup, - ipv6cp_lowerdown, - ipv6cp_open, - ipv6cp_close, -#if PRINTPKT_SUPPORT - ipv6cp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "IPV6CP", - "IPV6", -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - ipv6cp_option_list, - ipv6_check_options, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - ipv6_demand_conf, - ipv6_active_pkt -#endif /* DEMAND_SUPPORT */ -}; - -static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid); -#if 0 /* UNUSED */ -static void ipv6cp_script(char *)); -static void ipv6cp_script_done(void *)); -#endif /* UNUSED */ - -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */ -#define CILEN_IFACEID 10 /* RFC2472, interface identifier */ - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -#if 0 /* UNUSED */ -/* - * This state variable is used to ensure that we don't - * run an ipcp-up/down script while one is already running. - */ -static enum script_state { - s_down, - s_up, -} ipv6cp_script_state; -static pid_t ipv6cp_script_pid; -#endif /* UNUSED */ - -static char *llv6_ntoa(eui64_t ifaceid); - -#if PPP_OPTIONS -/* - * setifaceid - set the interface identifiers manually - */ -static int -setifaceid(argv) - char **argv; -{ - char *comma, *arg, c; - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - struct in6_addr addr; - static int prio_local, prio_remote; - -#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \ - (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) ) - - arg = *argv; - if ((comma = strchr(arg, ',')) == NULL) - comma = arg + strlen(arg); - - /* - * If comma first character, then no local identifier - */ - if (comma != arg) { - c = *comma; - *comma = '\0'; - - if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) { - option_error("Illegal interface identifier (local): %s", arg); - return 0; - } - - if (option_priority >= prio_local) { - eui64_copy(addr.s6_addr32[2], wo->ourid); - wo->opt_local = 1; - prio_local = option_priority; - } - *comma = c; - } - - /* - * If comma last character, the no remote identifier - */ - if (*comma != 0 && *++comma != '\0') { - if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) { - option_error("Illegal interface identifier (remote): %s", comma); - return 0; - } - if (option_priority >= prio_remote) { - eui64_copy(addr.s6_addr32[2], wo->hisid); - wo->opt_remote = 1; - prio_remote = option_priority; - } - } - - if (override_value("+ipv6", option_priority, option_source)) - ipv6cp_protent.enabled_flag = 1; - return 1; -} - -static void -printifaceid(opt, printer, arg) - option_t *opt; - void (*printer)(void *, char *, ...)); - void *arg; -{ - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - - if (wo->opt_local) - printer(arg, "%s", llv6_ntoa(wo->ourid)); - printer(arg, ","); - if (wo->opt_remote) - printer(arg, "%s", llv6_ntoa(wo->hisid)); -} -#endif /* PPP_OPTIONS */ - -/* - * Make a string representation of a network address. - */ -static char * -llv6_ntoa(eui64_t ifaceid) -{ - static char b[26]; - - sprintf(b, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", - ifaceid.e8[0], ifaceid.e8[1], ifaceid.e8[2], ifaceid.e8[3], - ifaceid.e8[4], ifaceid.e8[5], ifaceid.e8[6], ifaceid.e8[7]); - - return b; -} - - -/* - * ipv6cp_init - Initialize IPV6CP. - */ -static void ipv6cp_init(ppp_pcb *pcb) { - fsm *f = &pcb->ipv6cp_fsm; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; - - f->pcb = pcb; - f->protocol = PPP_IPV6CP; - f->callbacks = &ipv6cp_callbacks; - fsm_init(f); - -#if 0 /* Not necessary, everything is cleared in ppp_new() */ - memset(wo, 0, sizeof(*wo)); - memset(ao, 0, sizeof(*ao)); -#endif /* 0 */ - - wo->accept_local = 1; - wo->neg_ifaceid = 1; - ao->neg_ifaceid = 1; - -#ifdef IPV6CP_COMP - wo->neg_vj = 1; - ao->neg_vj = 1; - wo->vj_protocol = IPV6CP_COMP; -#endif - -} - - -/* - * ipv6cp_open - IPV6CP is allowed to come up. - */ -static void ipv6cp_open(ppp_pcb *pcb) { - fsm_open(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_close - Take IPV6CP down. - */ -static void ipv6cp_close(ppp_pcb *pcb, const char *reason) { - fsm_close(&pcb->ipv6cp_fsm, reason); -} - - -/* - * ipv6cp_lowerup - The lower layer is up. - */ -static void ipv6cp_lowerup(ppp_pcb *pcb) { - fsm_lowerup(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_lowerdown - The lower layer is down. - */ -static void ipv6cp_lowerdown(ppp_pcb *pcb) { - fsm_lowerdown(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_input - Input IPV6CP packet. - */ -static void ipv6cp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm_input(&pcb->ipv6cp_fsm, p, len); -} - - -/* - * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP. - * - * Pretend the lower layer went down, so we shut up. - */ -static void ipv6cp_protrej(ppp_pcb *pcb) { - fsm_lowerdown(&pcb->ipv6cp_fsm); -} - - -/* - * ipv6cp_resetci - Reset our CI. - */ -static void ipv6cp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; - - wo->req_ifaceid = wo->neg_ifaceid && ao->neg_ifaceid; - - if (!wo->opt_local) { - eui64_magic_nz(wo->ourid); - } - - *go = *wo; - eui64_zero(go->hisid); /* last proposed interface identifier */ -} - - -/* - * ipv6cp_cilen - Return length of our CI. - */ -static int ipv6cp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - -#ifdef IPV6CP_COMP -#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0) -#endif /* IPV6CP_COMP */ -#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0) - - return (LENCIIFACEID(go->neg_ifaceid) + -#ifdef IPV6CP_COMP - LENCIVJ(go->neg_vj) + -#endif /* IPV6CP_COMP */ - 0); -} - - -/* - * ipv6cp_addci - Add our desired CIs to a packet. - */ -static void ipv6cp_addci(fsm *f, u_char *ucp, int *lenp) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - int len = *lenp; - -#ifdef IPV6CP_COMP -#define ADDCIVJ(opt, neg, val) \ - if (neg) { \ - int vjlen = CILEN_COMPRESS; \ - if (len >= vjlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(vjlen, ucp); \ - PUTSHORT(val, ucp); \ - len -= vjlen; \ - } else \ - neg = 0; \ - } -#endif /* IPV6CP_COMP */ - -#define ADDCIIFACEID(opt, neg, val1) \ - if (neg) { \ - int idlen = CILEN_IFACEID; \ - if (len >= idlen) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(idlen, ucp); \ - eui64_put(val1, ucp); \ - len -= idlen; \ - } else \ - neg = 0; \ - } - - ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); - -#ifdef IPV6CP_COMP - ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); -#endif /* IPV6CP_COMP */ - - *lenp -= len; -} - - -/* - * ipv6cp_ackci - Ack our CIs. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int ipv6cp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_short cilen, citype; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - - /* - * CIs must be in exactly the same order that we sent... - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ - -#ifdef IPV6CP_COMP -#define ACKCIVJ(opt, neg, val) \ - if (neg) { \ - int vjlen = CILEN_COMPRESS; \ - if ((len -= vjlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != vjlen || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } -#endif /* IPV6CP_COMP */ - -#define ACKCIIFACEID(opt, neg, val1) \ - if (neg) { \ - int idlen = CILEN_IFACEID; \ - if ((len -= idlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != idlen || \ - citype != opt) \ - goto bad; \ - eui64_get(ifaceid, p); \ - if (! eui64_equals(val1, ifaceid)) \ - goto bad; \ - } - - ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid); - -#ifdef IPV6CP_COMP - ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol); -#endif /* IPV6CP_COMP */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); - -bad: - IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!")); - return (0); -} - -/* - * ipv6cp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if IPV6CP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int ipv6cp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_char citype, cilen, *next; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - ipv6cp_options no; /* options we've seen Naks for */ - ipv6cp_options try_; /* options to request next time */ - - BZERO(&no, sizeof(no)); - try_ = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIIFACEID(opt, neg, code) \ - if (go->neg && \ - len >= (cilen = CILEN_IFACEID) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - eui64_get(ifaceid, p); \ - no.neg = 1; \ - code \ - } - -#ifdef IPV6CP_COMP -#define NAKCIVJ(opt, neg, code) \ - if (go->neg && \ - ((cilen = p[1]) == CILEN_COMPRESS) && \ - len >= cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#endif /* IPV6CP_COMP */ - - /* - * Accept the peer's idea of {our,his} interface identifier, if different - * from our idea, only if the accept_{local,remote} flag is set. - */ - NAKCIIFACEID(CI_IFACEID, neg_ifaceid, - if (treat_as_reject) { - try_.neg_ifaceid = 0; - } else if (go->accept_local) { - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->hisid)) /* bad luck */ - eui64_magic(ifaceid); - try_.ourid = ifaceid; - IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid))); - } - ); - -#ifdef IPV6CP_COMP - NAKCIVJ(CI_COMPRESSTYPE, neg_vj, - { - if (cishort == IPV6CP_COMP && !treat_as_reject) { - try_.vj_protocol = cishort; - } else { - try_.neg_vj = 0; - } - } - ); -#endif /* IPV6CP_COMP */ - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If they want to negotiate about interface identifier, we comply. - * If they want us to ask for compression, we refuse. - */ - while (len >= CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if ( cilen < CILEN_VOID || (len -= cilen) < 0 ) - goto bad; - next = p + cilen - 2; - - switch (citype) { -#ifdef IPV6CP_COMP - case CI_COMPRESSTYPE: - if (go->neg_vj || no.neg_vj || - (cilen != CILEN_COMPRESS)) - goto bad; - no.neg_vj = 1; - break; -#endif /* IPV6CP_COMP */ - case CI_IFACEID: - if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID) - goto bad; - try_.neg_ifaceid = 1; - eui64_get(ifaceid, p); - if (go->accept_local) { - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->hisid)) /* bad luck */ - eui64_magic(ifaceid); - try_.ourid = ifaceid; - } - no.neg_ifaceid = 1; - break; - default: - break; - } - p = next; - } - - /* If there is still anything left, this packet is bad. */ - if (len != 0) - goto bad; - - /* - * OK, the Nak is good. Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - - return 1; - -bad: - IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!")); - return 0; -} - - -/* - * ipv6cp_rejci - Reject some of our CIs. - */ -static int ipv6cp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_char cilen; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - ipv6cp_options try_; /* options to request next time */ - - try_ = *go; - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIIFACEID(opt, neg, val1) \ - if (go->neg && \ - len >= (cilen = CILEN_IFACEID) && \ - p[1] == cilen && \ - p[0] == opt) { \ - len -= cilen; \ - INCPTR(2, p); \ - eui64_get(ifaceid, p); \ - /* Check rejected value. */ \ - if (! eui64_equals(ifaceid, val1)) \ - goto bad; \ - try_.neg = 0; \ - } - -#ifdef IPV6CP_COMP -#define REJCIVJ(opt, neg, val) \ - if (go->neg && \ - p[1] == CILEN_COMPRESS && \ - len >= p[1] && \ - p[0] == opt) { \ - len -= p[1]; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* IPV6CP_COMP */ - - REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid); - -#ifdef IPV6CP_COMP - REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol); -#endif /* IPV6CP_COMP */ - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; - -bad: - IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!")); - return 0; -} - - -/* - * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - * - * inp = Requested CIs - * len = Length of requested CIs - * - */ -static int ipv6cp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; - ipv6cp_options *ao = &pcb->ipv6cp_allowoptions; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - u_char *cip, *next; /* Pointer to current and next CIs */ - u_short cilen, citype; /* Parsed len, type */ -#ifdef IPV6CP_COMP - u_short cishort; /* Parsed short value */ -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; /* Parsed interface identifier */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ - int l = *len; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_IFACEID: - IPV6CPDEBUG(("ipv6cp: received interface identifier ")); - - if (!ao->neg_ifaceid || - cilen != CILEN_IFACEID) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - - /* - * If he has no interface identifier, or if we both have same - * identifier then NAK it with new idea. - * In particular, if we don't know his identifier, but he does, - * then accept it. - */ - eui64_get(ifaceid, p); - IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid))); - if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) { - orc = CONFREJ; /* Reject CI */ - break; - } - if (!eui64_iszero(wo->hisid) && - !eui64_equals(ifaceid, wo->hisid) && - eui64_iszero(go->hisid)) { - - orc = CONFNAK; - ifaceid = wo->hisid; - go->hisid = ifaceid; - DECPTR(sizeof(ifaceid), p); - eui64_put(ifaceid, p); - } else - if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) { - orc = CONFNAK; - if (eui64_iszero(go->hisid)) /* first time, try option */ - ifaceid = wo->hisid; - while (eui64_iszero(ifaceid) || - eui64_equals(ifaceid, go->ourid)) /* bad luck */ - eui64_magic(ifaceid); - go->hisid = ifaceid; - DECPTR(sizeof(ifaceid), p); - eui64_put(ifaceid, p); - } - - ho->neg_ifaceid = 1; - ho->hisid = ifaceid; - break; - -#ifdef IPV6CP_COMP - case CI_COMPRESSTYPE: - IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE ")); - if (!ao->neg_vj || - (cilen != CILEN_COMPRESS)) { - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - IPV6CPDEBUG(("(%d)", cishort)); - - if (!(cishort == IPV6CP_COMP)) { - orc = CONFREJ; - break; - } - - ho->neg_vj = 1; - ho->vj_protocol = cishort; - break; -#endif /* IPV6CP_COMP */ - - default: - orc = CONFREJ; - break; - } - -endswitch: - IPV6CPDEBUG((" (%s)\n", CODENAME(orc))); - - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ - orc = CONFREJ; /* Get tough if so */ - else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } - } - } - - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ - rc = CONFREJ; - ucp = inp; /* Backup */ - } - - /* Need to move CI? */ - if (ucp != cip) - MEMCPY(ucp, cip, cilen); /* Move it */ - - /* Update output pointer */ - INCPTR(cilen, ucp); - } - - /* - * If we aren't rejecting this packet, and we want to negotiate - * their identifier and they didn't send their identifier, then we - * send a NAK with a CI_IFACEID option appended. We assume the - * input buffer is long enough that we can append the extra - * option safely. - */ - if (rc != CONFREJ && !ho->neg_ifaceid && - wo->req_ifaceid && !reject_if_disagree) { - if (rc == CONFACK) { - rc = CONFNAK; - ucp = inp; /* reset pointer */ - wo->req_ifaceid = 0; /* don't ask again */ - } - PUTCHAR(CI_IFACEID, ucp); - PUTCHAR(CILEN_IFACEID, ucp); - eui64_put(wo->hisid, ucp); - } - - *len = ucp - inp; /* Compute output length */ - IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc))); - return (rc); /* Return final code */ -} - -#if PPP_OPTIONS -/* - * ipv6_check_options - check that any IP-related options are OK, - * and assign appropriate defaults. - */ -static void ipv6_check_options() { - ipv6cp_options *wo = &ipv6cp_wantoptions[0]; - - if (!ipv6cp_protent.enabled_flag) - return; - - /* - * Persistent link-local id is only used when user has not explicitly - * configure/hard-code the id - */ - if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) { - - /* - * On systems where there are no Ethernet interfaces used, there - * may be other ways to obtain a persistent id. Right now, it - * will fall back to using magic [see eui64_magic] below when - * an EUI-48 from MAC address can't be obtained. Other possibilities - * include obtaining EEPROM serial numbers, or some other unique - * yet persistent number. On Sparc platforms, this is possible, - * but too bad there's no standards yet for x86 machines. - */ - if (ether_to_eui64(&wo->ourid)) { - wo->opt_local = 1; - } - } - - if (!wo->opt_local) { /* init interface identifier */ - if (wo->use_ip && eui64_iszero(wo->ourid)) { - eui64_setlo32(wo->ourid, lwip_ntohl(ipcp_wantoptions[0].ouraddr)); - if (!eui64_iszero(wo->ourid)) - wo->opt_local = 1; - } - - while (eui64_iszero(wo->ourid)) - eui64_magic(wo->ourid); - } - - if (!wo->opt_remote) { - if (wo->use_ip && eui64_iszero(wo->hisid)) { - eui64_setlo32(wo->hisid, lwip_ntohl(ipcp_wantoptions[0].hisaddr)); - if (!eui64_iszero(wo->hisid)) - wo->opt_remote = 1; - } - } - - if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) { - option_error("local/remote LL address required for demand-dialling\n"); - exit(1); - } -} -#endif /* PPP_OPTIONS */ - -#if DEMAND_SUPPORT -/* - * ipv6_demand_conf - configure the interface as though - * IPV6CP were up, for use with dial-on-demand. - */ -static int ipv6_demand_conf(int u) { - ipv6cp_options *wo = &ipv6cp_wantoptions[u]; - - if (!sif6up(u)) - return 0; - - if (!sif6addr(u, wo->ourid, wo->hisid)) - return 0; - - if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE)) - return 0; - - ppp_notice("ipv6_demand_conf"); - ppp_notice("local LL address %s", llv6_ntoa(wo->ourid)); - ppp_notice("remote LL address %s", llv6_ntoa(wo->hisid)); - - return 1; -} -#endif /* DEMAND_SUPPORT */ - - -/* - * ipv6cp_up - IPV6CP has come UP. - * - * Configure the IPv6 network interface appropriately and bring it up. - */ -static void ipv6cp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *wo = &pcb->ipv6cp_wantoptions; - ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - - IPV6CPDEBUG(("ipv6cp: up")); - - /* - * We must have a non-zero LL address for both ends of the link. - */ - if (!ho->neg_ifaceid) - ho->hisid = wo->hisid; - -#if 0 /* UNUSED */ - if(!no_ifaceid_neg) { -#endif /* UNUSED */ - if (eui64_iszero(ho->hisid)) { - ppp_error("Could not determine remote LL address"); - ipv6cp_close(f->pcb, "Could not determine remote LL address"); - return; - } - if (eui64_iszero(go->ourid)) { - ppp_error("Could not determine local LL address"); - ipv6cp_close(f->pcb, "Could not determine local LL address"); - return; - } - if (eui64_equals(go->ourid, ho->hisid)) { - ppp_error("local and remote LL addresses are equal"); - ipv6cp_close(f->pcb, "local and remote LL addresses are equal"); - return; - } -#if 0 /* UNUSED */ - } -#endif /* UNUSED */ -#if 0 /* UNUSED */ - script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); - script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); -#endif /* UNUSED */ - -#ifdef IPV6CP_COMP - /* set tcp compression */ - sif6comp(f->unit, ho->neg_vj); -#endif - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, the interface is already - * configured, so we put out any saved-up packets, then set the - * interface to pass IPv6 packets. - */ - if (demand) { - if (! eui64_equals(go->ourid, wo->ourid) || - ! eui64_equals(ho->hisid, wo->hisid)) { - if (! eui64_equals(go->ourid, wo->ourid)) - warn("Local LL address changed to %s", - llv6_ntoa(go->ourid)); - if (! eui64_equals(ho->hisid, wo->hisid)) - warn("Remote LL address changed to %s", - llv6_ntoa(ho->hisid)); - ipv6cp_clear_addrs(f->pcb, go->ourid, ho->hisid); - - /* Set the interface to the new addresses */ - if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { - if (debug) - warn("sif6addr failed"); - ipv6cp_close(f->unit, "Interface configuration failed"); - return; - } - - } - demand_rexmit(PPP_IPV6); - sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS); - - } else -#endif /* DEMAND_SUPPORT */ - { - /* - * Set LL addresses - */ - if (!sif6addr(f->pcb, go->ourid, ho->hisid)) { - PPPDEBUG(LOG_DEBUG, ("sif6addr failed")); - ipv6cp_close(f->pcb, "Interface configuration failed"); - return; - } - - /* bring the interface up for IPv6 */ - if (!sif6up(f->pcb)) { - PPPDEBUG(LOG_DEBUG, ("sif6up failed (IPV6)")); - ipv6cp_close(f->pcb, "Interface configuration failed"); - return; - } -#if DEMAND_SUPPORT - sifnpmode(f->pcb, PPP_IPV6, NPMODE_PASS); -#endif /* DEMAND_SUPPORT */ - - ppp_notice("local LL address %s", llv6_ntoa(go->ourid)); - ppp_notice("remote LL address %s", llv6_ntoa(ho->hisid)); - } - - np_up(f->pcb, PPP_IPV6); - pcb->ipv6cp_is_up = 1; - -#if 0 /* UNUSED */ - /* - * Execute the ipv6-up script, like this: - * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL - */ - if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) { - ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); - } -#endif /* UNUSED */ -} - - -/* - * ipv6cp_down - IPV6CP has gone DOWN. - * - * Take the IPv6 network interface down, clear its addresses - * and delete routes through it. - */ -static void ipv6cp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; - ipv6cp_options *go = &pcb->ipv6cp_gotoptions; - ipv6cp_options *ho = &pcb->ipv6cp_hisoptions; - - IPV6CPDEBUG(("ipv6cp: down")); -#if PPP_STATS_SUPPORT - update_link_stats(f->unit); -#endif /* PPP_STATS_SUPPORT */ - if (pcb->ipv6cp_is_up) { - pcb->ipv6cp_is_up = 0; - np_down(f->pcb, PPP_IPV6); - } -#ifdef IPV6CP_COMP - sif6comp(f->unit, 0); -#endif - -#if DEMAND_SUPPORT - /* - * If we are doing dial-on-demand, set the interface - * to queue up outgoing packets (for now). - */ - if (demand) { - sifnpmode(f->pcb, PPP_IPV6, NPMODE_QUEUE); - } else -#endif /* DEMAND_SUPPORT */ - { -#if DEMAND_SUPPORT - sifnpmode(f->pcb, PPP_IPV6, NPMODE_DROP); -#endif /* DEMAND_SUPPORT */ - ipv6cp_clear_addrs(f->pcb, - go->ourid, - ho->hisid); - sif6down(f->pcb); - } - -#if 0 /* UNUSED */ - /* Execute the ipv6-down script */ - if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) { - ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); - } -#endif /* UNUSED */ -} - - -/* - * ipv6cp_clear_addrs() - clear the interface addresses, routes, - * proxy neighbour discovery entries, etc. - */ -static void ipv6cp_clear_addrs(ppp_pcb *pcb, eui64_t ourid, eui64_t hisid) { - cif6addr(pcb, ourid, hisid); -} - - -/* - * ipv6cp_finished - possibly shut down the lower layers. - */ -static void ipv6cp_finished(fsm *f) { - np_finished(f->pcb, PPP_IPV6); -} - - -#if 0 /* UNUSED */ -/* - * ipv6cp_script_done - called when the ipv6-up or ipv6-down script - * has finished. - */ -static void -ipv6cp_script_done(arg) - void *arg; -{ - ipv6cp_script_pid = 0; - switch (ipv6cp_script_state) { - case s_up: - if (ipv6cp_fsm[0].state != PPP_FSM_OPENED) { - ipv6cp_script_state = s_down; - ipv6cp_script(_PATH_IPV6DOWN); - } - break; - case s_down: - if (ipv6cp_fsm[0].state == PPP_FSM_OPENED) { - ipv6cp_script_state = s_up; - ipv6cp_script(_PATH_IPV6UP); - } - break; - } -} - - -/* - * ipv6cp_script - Execute a script with arguments - * interface-name tty-name speed local-LL remote-LL. - */ -static void -ipv6cp_script(script) - char *script; -{ - char strspeed[32], strlocal[32], strremote[32]; - char *argv[8]; - - sprintf(strspeed, "%d", baud_rate); - strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid)); - strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid)); - - argv[0] = script; - argv[1] = ifname; - argv[2] = devnam; - argv[3] = strspeed; - argv[4] = strlocal; - argv[5] = strremote; - argv[6] = ipparam; - argv[7] = NULL; - - ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, - NULL, 0); -} -#endif /* UNUSED */ - -#if PRINTPKT_SUPPORT -/* - * ipv6cp_printpkt - print the contents of an IPV6CP packet. - */ -static const char* const ipv6cp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej" -}; - -static int ipv6cp_printpkt(const u_char *p, int plen, - void (*printer)(void *, const char *, ...), void *arg) { - int code, id, len, olen; - const u_char *pstart, *optend; -#ifdef IPV6CP_COMP - u_short cishort; -#endif /* IPV6CP_COMP */ - eui64_t ifaceid; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipv6cp_codenames)) - printer(arg, " %s", ipv6cp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { -#ifdef IPV6CP_COMP - case CI_COMPRESSTYPE: - if (olen >= CILEN_COMPRESS) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "compress "); - printer(arg, "0x%x", cishort); - } - break; -#endif /* IPV6CP_COMP */ - case CI_IFACEID: - if (olen == CILEN_IFACEID) { - p += 2; - eui64_get(ifaceid, p); - printer(arg, "addr %s", llv6_ntoa(ifaceid)); - } - break; - default: - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -#if DEMAND_SUPPORT -/* - * ipv6_active_pkt - see if this IP packet is worth bringing the link up for. - * We don't bring the link up for IP fragments or for TCP FIN packets - * with no data. - */ -#define IP6_HDRLEN 40 /* bytes */ -#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */ -#define TCP_HDRLEN 20 -#define TH_FIN 0x01 - -/* - * We use these macros because the IP header may be at an odd address, - * and some compilers might use word loads to get th_off or ip_hl. - */ - -#define get_ip6nh(x) (((unsigned char *)(x))[6]) -#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4) -#define get_tcpflags(x) (((unsigned char *)(x))[13]) - -static int ipv6_active_pkt(u_char *pkt, int len) { - u_char *tcp; - - len -= PPP_HDRLEN; - pkt += PPP_HDRLEN; - if (len < IP6_HDRLEN) - return 0; - if (get_ip6nh(pkt) == IP6_NHDR_FRAG) - return 0; - if (get_ip6nh(pkt) != IPPROTO_TCP) - return 1; - if (len < IP6_HDRLEN + TCP_HDRLEN) - return 0; - tcp = pkt + IP6_HDRLEN; - if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4) - return 0; - return 1; -} -#endif /* DEMAND_SUPPORT */ - -#endif /* PPP_SUPPORT && PPP_IPV6_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/lcp.c b/components/net/lwip-2.0.2/src/netif/ppp/lcp.c deleted file mode 100644 index 90ed183b75..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/lcp.c +++ /dev/null @@ -1,2790 +0,0 @@ -/* - * lcp.c - PPP Link Control Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - */ - -#if 0 /* UNUSED */ -#include -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#if CHAP_SUPPORT -#include "netif/ppp/chap-new.h" -#endif /* CHAP_SUPPORT */ -#include "netif/ppp/magic.h" - -/* - * When the link comes up we want to be able to wait for a short while, - * or until seeing some input from the peer, before starting to send - * configure-requests. We do this by delaying the fsm_lowerup call. - */ -/* steal a bit in fsm flags word */ -#define DELAYED_UP 0x80 - -static void lcp_delayed_up(void *arg); - -/* - * LCP-related command-line options. - */ -#if 0 /* UNUSED */ -int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ -int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -/* options */ -static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ -static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ -#endif /* UNUSED */ - -#if 0 /* UNUSED */ -#if PPP_LCP_ADAPTIVE -bool lcp_echo_adaptive = 0; /* request echo only if the link was idle */ -#endif -bool lax_recv = 0; /* accept control chars in asyncmap */ -bool noendpoint = 0; /* don't send/accept endpoint discriminator */ -#endif /* UNUSED */ - -#if PPP_OPTIONS -static int noopt (char **); -#endif /* PPP_OPTIONS */ - -#ifdef HAVE_MULTILINK -static int setendpoint (char **); -static void printendpoint (option_t *, void (*)(void *, char *, ...), - void *); -#endif /* HAVE_MULTILINK */ - -#if PPP_OPTIONS -static option_t lcp_option_list[] = { - /* LCP options */ - { "-all", o_special_noarg, (void *)noopt, - "Don't request/allow any LCP options" }, - - { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, - "Disable address/control compression", - OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, - { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, - "Disable address/control compression", - OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, - - { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, - "Set asyncmap (for received packets)", - OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, - { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, - "Set asyncmap (for received packets)", - OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, - { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, - "Disable asyncmap negotiation", - OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, - &lcp_allowoptions[0].neg_asyncmap }, - { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, - "Disable asyncmap negotiation", - OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, - &lcp_allowoptions[0].neg_asyncmap }, - - { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, - "Disable magic number negotiation (looped-back line detection)", - OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, - { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, - "Disable magic number negotiation (looped-back line detection)", - OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, - - { "mru", o_int, &lcp_wantoptions[0].mru, - "Set MRU (maximum received packet size) for negotiation", - OPT_PRIO, &lcp_wantoptions[0].neg_mru }, - { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, - "Disable MRU negotiation (use default 1500)", - OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, - { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, - "Disable MRU negotiation (use default 1500)", - OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, - - { "mtu", o_int, &lcp_allowoptions[0].mru, - "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, - - { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, - "Disable protocol field compression", - OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, - { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, - "Disable protocol field compression", - OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, - - { "passive", o_bool, &lcp_wantoptions[0].passive, - "Set passive mode", 1 }, - { "-p", o_bool, &lcp_wantoptions[0].passive, - "Set passive mode", OPT_ALIAS | 1 }, - - { "silent", o_bool, &lcp_wantoptions[0].silent, - "Set silent mode", 1 }, - - { "lcp-echo-failure", o_int, &lcp_echo_fails, - "Set number of consecutive echo failures to indicate link failure", - OPT_PRIO }, - { "lcp-echo-interval", o_int, &lcp_echo_interval, - "Set time in seconds between LCP echo requests", OPT_PRIO }, -#if PPP_LCP_ADAPTIVE - { "lcp-echo-adaptive", o_bool, &lcp_echo_adaptive, - "Suppress LCP echo requests if traffic was received", 1 }, -#endif - { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, - "Set time in seconds between LCP retransmissions", OPT_PRIO }, - { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, - "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, - { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, - "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, - { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, - "Set limit on number of LCP configure-naks", OPT_PRIO }, - - { "receive-all", o_bool, &lax_recv, - "Accept all received control characters", 1 }, - -#ifdef HAVE_MULTILINK - { "mrru", o_int, &lcp_wantoptions[0].mrru, - "Maximum received packet size for multilink bundle", - OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, - - { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, - "Use short sequence numbers in multilink headers", - OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, - { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, - "Don't use short sequence numbers in multilink headers", - OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, - - { "endpoint", o_special, (void *) setendpoint, - "Endpoint discriminator for multilink", - OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, -#endif /* HAVE_MULTILINK */ - - { "noendpoint", o_bool, &noendpoint, - "Don't send or accept multilink endpoint discriminator", 1 }, - - {NULL} -}; -#endif /* PPP_OPTIONS */ - -/* - * Callbacks for fsm code. (CI = Configuration Information) - */ -static void lcp_resetci(fsm *f); /* Reset our CI */ -static int lcp_cilen(fsm *f); /* Return length of our CI */ -static void lcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI to pkt */ -static int lcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */ -static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject); /* Peer nak'd our CI */ -static int lcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */ -static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree); /* Rcv peer CI */ -static void lcp_up(fsm *f); /* We're UP */ -static void lcp_down(fsm *f); /* We're DOWN */ -static void lcp_starting (fsm *); /* We need lower layer up */ -static void lcp_finished (fsm *); /* We need lower layer down */ -static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len); -static void lcp_rprotrej(fsm *f, u_char *inp, int len); - -/* - * routines to send LCP echos to peer - */ - -static void lcp_echo_lowerup(ppp_pcb *pcb); -static void lcp_echo_lowerdown(ppp_pcb *pcb); -static void LcpEchoTimeout(void *arg); -static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len); -static void LcpSendEchoRequest(fsm *f); -static void LcpLinkFailure(fsm *f); -static void LcpEchoCheck(fsm *f); - -static const fsm_callbacks lcp_callbacks = { /* LCP callback routines */ - lcp_resetci, /* Reset our Configuration Information */ - lcp_cilen, /* Length of our Configuration Information */ - lcp_addci, /* Add our Configuration Information */ - lcp_ackci, /* ACK our Configuration Information */ - lcp_nakci, /* NAK our Configuration Information */ - lcp_rejci, /* Reject our Configuration Information */ - lcp_reqci, /* Request peer's Configuration Information */ - lcp_up, /* Called when fsm reaches OPENED state */ - lcp_down, /* Called when fsm leaves OPENED state */ - lcp_starting, /* Called when we want the lower layer up */ - lcp_finished, /* Called when we want the lower layer down */ - NULL, /* Called when Protocol-Reject received */ - NULL, /* Retransmission is necessary */ - lcp_extcode, /* Called to handle LCP-specific codes */ - "LCP" /* String name of protocol */ -}; - -/* - * Protocol entry points. - * Some of these are called directly. - */ - -static void lcp_init(ppp_pcb *pcb); -static void lcp_input(ppp_pcb *pcb, u_char *p, int len); -static void lcp_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int lcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -const struct protent lcp_protent = { - PPP_LCP, - lcp_init, - lcp_input, - lcp_protrej, - lcp_lowerup, - lcp_lowerdown, - lcp_open, - lcp_close, -#if PRINTPKT_SUPPORT - lcp_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "LCP", - NULL, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - lcp_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -/* - * Length of each type of configuration option (in octets) - */ -#define CILEN_VOID 2 -#define CILEN_CHAR 3 -#define CILEN_SHORT 4 /* CILEN_VOID + 2 */ -#if CHAP_SUPPORT -#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */ -#endif /* CHAP_SUPPORT */ -#define CILEN_LONG 6 /* CILEN_VOID + 4 */ -#if LQR_SUPPORT -#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */ -#endif /* LQR_SUPPORT */ -#define CILEN_CBCP 3 - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - -#if PPP_OPTIONS -/* - * noopt - Disable all options (why?). - */ -static int -noopt(argv) - char **argv; -{ - BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options)); - BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options)); - - return (1); -} -#endif /* PPP_OPTIONS */ - -#ifdef HAVE_MULTILINK -static int -setendpoint(argv) - char **argv; -{ - if (str_to_epdisc(&lcp_wantoptions[0].endpoint, *argv)) { - lcp_wantoptions[0].neg_endpoint = 1; - return 1; - } - option_error("Can't parse '%s' as an endpoint discriminator", *argv); - return 0; -} - -static void -printendpoint(opt, printer, arg) - option_t *opt; - void (*printer) (void *, char *, ...); - void *arg; -{ - printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); -} -#endif /* HAVE_MULTILINK */ - -/* - * lcp_init - Initialize LCP. - */ -static void lcp_init(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - lcp_options *wo = &pcb->lcp_wantoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - - f->pcb = pcb; - f->protocol = PPP_LCP; - f->callbacks = &lcp_callbacks; - - fsm_init(f); - - BZERO(wo, sizeof(*wo)); - wo->neg_mru = 1; - wo->mru = PPP_DEFMRU; - wo->neg_asyncmap = 1; - wo->neg_magicnumber = 1; - wo->neg_pcompression = 1; - wo->neg_accompression = 1; - - BZERO(ao, sizeof(*ao)); - ao->neg_mru = 1; - ao->mru = PPP_MAXMRU; - ao->neg_asyncmap = 1; -#if CHAP_SUPPORT - ao->neg_chap = 1; - ao->chap_mdtype = CHAP_MDTYPE_SUPPORTED; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - ao->neg_upap = 1; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - ao->neg_eap = 1; -#endif /* EAP_SUPPORT */ - ao->neg_magicnumber = 1; - ao->neg_pcompression = 1; - ao->neg_accompression = 1; - ao->neg_endpoint = 1; -} - - -/* - * lcp_open - LCP is allowed to come up. - */ -void lcp_open(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - lcp_options *wo = &pcb->lcp_wantoptions; - - f->flags &= ~(OPT_PASSIVE | OPT_SILENT); - if (wo->passive) - f->flags |= OPT_PASSIVE; - if (wo->silent) - f->flags |= OPT_SILENT; - fsm_open(f); -} - - -/* - * lcp_close - Take LCP down. - */ -void lcp_close(ppp_pcb *pcb, const char *reason) { - fsm *f = &pcb->lcp_fsm; - int oldstate; - - if (pcb->phase != PPP_PHASE_DEAD -#ifdef HAVE_MULTILINK - && pcb->phase != PPP_PHASE_MASTER -#endif /* HAVE_MULTILINK */ - ) - new_phase(pcb, PPP_PHASE_TERMINATE); - - if (f->flags & DELAYED_UP) { - UNTIMEOUT(lcp_delayed_up, f); - f->state = PPP_FSM_STOPPED; - } - oldstate = f->state; - - fsm_close(f, reason); - if (oldstate == PPP_FSM_STOPPED && (f->flags & (OPT_PASSIVE|OPT_SILENT|DELAYED_UP))) { - /* - * This action is not strictly according to the FSM in RFC1548, - * but it does mean that the program terminates if you do a - * lcp_close() when a connection hasn't been established - * because we are in passive/silent mode or because we have - * delayed the fsm_lowerup() call and it hasn't happened yet. - */ - f->flags &= ~DELAYED_UP; - lcp_finished(f); - } -} - - -/* - * lcp_lowerup - The lower layer is up. - */ -void lcp_lowerup(ppp_pcb *pcb) { - lcp_options *wo = &pcb->lcp_wantoptions; - fsm *f = &pcb->lcp_fsm; - /* - * Don't use A/C or protocol compression on transmission, - * but accept A/C and protocol compressed packets - * if we are going to ask for A/C and protocol compression. - */ - if (ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0) < 0 - || ppp_recv_config(pcb, PPP_MRU, (pcb->settings.lax_recv? 0: 0xffffffff), - wo->neg_pcompression, wo->neg_accompression) < 0) - return; - pcb->peer_mru = PPP_MRU; - - if (pcb->settings.listen_time != 0) { - f->flags |= DELAYED_UP; - TIMEOUTMS(lcp_delayed_up, f, pcb->settings.listen_time); - } else - fsm_lowerup(f); -} - - -/* - * lcp_lowerdown - The lower layer is down. - */ -void lcp_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - - if (f->flags & DELAYED_UP) { - f->flags &= ~DELAYED_UP; - UNTIMEOUT(lcp_delayed_up, f); - } else - fsm_lowerdown(f); -} - - -/* - * lcp_delayed_up - Bring the lower layer up now. - */ -static void lcp_delayed_up(void *arg) { - fsm *f = (fsm*)arg; - - if (f->flags & DELAYED_UP) { - f->flags &= ~DELAYED_UP; - fsm_lowerup(f); - } -} - - -/* - * lcp_input - Input LCP packet. - */ -static void lcp_input(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->lcp_fsm; - - if (f->flags & DELAYED_UP) { - f->flags &= ~DELAYED_UP; - UNTIMEOUT(lcp_delayed_up, f); - fsm_lowerup(f); - } - fsm_input(f, p, len); -} - -/* - * lcp_extcode - Handle a LCP-specific code. - */ -static int lcp_extcode(fsm *f, int code, int id, u_char *inp, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char *magp; - - switch( code ){ - case PROTREJ: - lcp_rprotrej(f, inp, len); - break; - - case ECHOREQ: - if (f->state != PPP_FSM_OPENED) - break; - magp = inp; - PUTLONG(go->magicnumber, magp); - fsm_sdata(f, ECHOREP, id, inp, len); - break; - - case ECHOREP: - lcp_received_echo_reply(f, id, inp, len); - break; - - case DISCREQ: - case IDENTIF: - case TIMEREM: - break; - - default: - return 0; - } - return 1; -} - - -/* - * lcp_rprotrej - Receive an Protocol-Reject. - * - * Figure out which protocol is rejected and inform it. - */ -static void lcp_rprotrej(fsm *f, u_char *inp, int len) { - int i; - const struct protent *protp; - u_short prot; -#if PPP_PROTOCOLNAME - const char *pname; -#endif /* PPP_PROTOCOLNAME */ - - if (len < 2) { - LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!")); - return; - } - - GETSHORT(prot, inp); - - /* - * Protocol-Reject packets received in any state other than the LCP - * OPENED state SHOULD be silently discarded. - */ - if( f->state != PPP_FSM_OPENED ){ - LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state)); - return; - } - -#if PPP_PROTOCOLNAME - pname = protocol_name(prot); -#endif /* PPP_PROTOCOLNAME */ - - /* - * Upcall the proper Protocol-Reject routine. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (protp->protocol == prot) { -#if PPP_PROTOCOLNAME - if (pname != NULL) - ppp_dbglog("Protocol-Reject for '%s' (0x%x) received", pname, - prot); - else -#endif /* PPP_PROTOCOLNAME */ - ppp_dbglog("Protocol-Reject for 0x%x received", prot); - (*protp->protrej)(f->pcb); - return; - } - -#if PPP_PROTOCOLNAME - if (pname != NULL) - ppp_warn("Protocol-Reject for unsupported protocol '%s' (0x%x)", pname, - prot); - else -#endif /* #if PPP_PROTOCOLNAME */ - ppp_warn("Protocol-Reject for unsupported protocol 0x%x", prot); -} - - -/* - * lcp_protrej - A Protocol-Reject was received. - */ -/*ARGSUSED*/ -static void lcp_protrej(ppp_pcb *pcb) { - /* - * Can't reject LCP! - */ - ppp_error("Received Protocol-Reject for LCP!"); - fsm_protreject(&pcb->lcp_fsm); -} - - -/* - * lcp_sprotrej - Send a Protocol-Reject for some protocol. - */ -void lcp_sprotrej(ppp_pcb *pcb, u_char *p, int len) { - fsm *f = &pcb->lcp_fsm; - /* - * Send back the protocol and the information field of the - * rejected packet. We only get here if LCP is in the OPENED state. - */ -#if 0 - p += 2; - len -= 2; -#endif - - fsm_sdata(f, PROTREJ, ++f->id, - p, len); -} - - -/* - * lcp_resetci - Reset our CI. - */ -static void lcp_resetci(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *wo = &pcb->lcp_wantoptions; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - -#if PPP_AUTH_SUPPORT - - /* note: default value is true for allow options */ - if (pcb->settings.user && pcb->settings.passwd) { -#if PAP_SUPPORT - if (pcb->settings.refuse_pap) { - ao->neg_upap = 0; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (pcb->settings.refuse_chap) { - ao->chap_mdtype &= ~MDTYPE_MD5; - } -#if MSCHAP_SUPPORT - if (pcb->settings.refuse_mschap) { - ao->chap_mdtype &= ~MDTYPE_MICROSOFT; - } - if (pcb->settings.refuse_mschap_v2) { - ao->chap_mdtype &= ~MDTYPE_MICROSOFT_V2; - } -#endif /* MSCHAP_SUPPORT */ - ao->neg_chap = (ao->chap_mdtype != MDTYPE_NONE); -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - if (pcb->settings.refuse_eap) { - ao->neg_eap = 0; - } -#endif /* EAP_SUPPORT */ - -#if PPP_SERVER - /* note: default value is false for wanted options */ - if (pcb->settings.auth_required) { -#if PAP_SUPPORT - if (!pcb->settings.refuse_pap) { - wo->neg_upap = 1; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (!pcb->settings.refuse_chap) { - wo->chap_mdtype |= MDTYPE_MD5; - } -#if MSCHAP_SUPPORT - if (!pcb->settings.refuse_mschap) { - wo->chap_mdtype |= MDTYPE_MICROSOFT; - } - if (!pcb->settings.refuse_mschap_v2) { - wo->chap_mdtype |= MDTYPE_MICROSOFT_V2; - } -#endif /* MSCHAP_SUPPORT */ - wo->neg_chap = (wo->chap_mdtype != MDTYPE_NONE); -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - if (!pcb->settings.refuse_eap) { - wo->neg_eap = 1; - } -#endif /* EAP_SUPPORT */ - } -#endif /* PPP_SERVER */ - - } else { -#if PAP_SUPPORT - ao->neg_upap = 0; -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - ao->neg_chap = 0; - ao->chap_mdtype = MDTYPE_NONE; -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - ao->neg_eap = 0; -#endif /* EAP_SUPPORT */ - } - - PPPDEBUG(LOG_DEBUG, ("ppp: auth protocols:")); -#if PAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" PAP=%d", ao->neg_upap)); -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" CHAP=%d CHAP_MD5=%d", ao->neg_chap, !!(ao->chap_mdtype&MDTYPE_MD5))); -#if MSCHAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" CHAP_MS=%d CHAP_MS2=%d", !!(ao->chap_mdtype&MDTYPE_MICROSOFT), !!(ao->chap_mdtype&MDTYPE_MICROSOFT_V2))); -#endif /* MSCHAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - PPPDEBUG(LOG_DEBUG, (" EAP=%d", ao->neg_eap)); -#endif /* EAP_SUPPORT */ - PPPDEBUG(LOG_DEBUG, ("\n")); - -#endif /* PPP_AUTH_SUPPORT */ - - wo->magicnumber = magic(); - wo->numloops = 0; - *go = *wo; -#ifdef HAVE_MULTILINK - if (!multilink) { - go->neg_mrru = 0; -#endif /* HAVE_MULTILINK */ - go->neg_ssnhf = 0; - go->neg_endpoint = 0; -#ifdef HAVE_MULTILINK - } -#endif /* HAVE_MULTILINK */ - if (pcb->settings.noendpoint) - ao->neg_endpoint = 0; - pcb->peer_mru = PPP_MRU; -#if 0 /* UNUSED */ - auth_reset(pcb); -#endif /* UNUSED */ -} - - -/* - * lcp_cilen - Return length of our CI. - */ -static int lcp_cilen(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - -#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0) -#if CHAP_SUPPORT -#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0) -#endif /* CHAP_SUPPORT */ -#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0) -#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0) -#if LQR_SUPPORT -#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0) -#endif /* LQR_SUPPORT */ -#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0) - /* - * NB: we only ask for one of CHAP, UPAP, or EAP, even if we will - * accept more than one. We prefer EAP first, then CHAP, then - * PAP. - */ - return (LENCISHORT(go->neg_mru && go->mru != PPP_DEFMRU) + - LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) + -#if EAP_SUPPORT - LENCISHORT(go->neg_eap) + -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT - LENCICHAP(!go->neg_eap && go->neg_chap) + -#endif /* EAP_SUPPORT */ -#if !EAP_SUPPORT - LENCICHAP(go->neg_chap) + -#endif /* !EAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT && CHAP_SUPPORT - LENCISHORT(!go->neg_eap && !go->neg_chap && go->neg_upap) + -#endif /* EAP_SUPPORT && CHAP_SUPPORT */ -#if EAP_SUPPORT && !CHAP_SUPPORT - LENCISHORT(!go->neg_eap && go->neg_upap) + -#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ -#if !EAP_SUPPORT && CHAP_SUPPORT - LENCISHORT(!go->neg_chap && go->neg_upap) + -#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ -#if !EAP_SUPPORT && !CHAP_SUPPORT - LENCISHORT(go->neg_upap) + -#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT - LENCILQR(go->neg_lqr) + -#endif /* LQR_SUPPORT */ - LENCICBCP(go->neg_cbcp) + - LENCILONG(go->neg_magicnumber) + - LENCIVOID(go->neg_pcompression) + - LENCIVOID(go->neg_accompression) + -#ifdef HAVE_MULTILINK - LENCISHORT(go->neg_mrru) + -#endif /* HAVE_MULTILINK */ - LENCIVOID(go->neg_ssnhf) + - (go->neg_endpoint? CILEN_CHAR + go->endpoint.length: 0)); -} - - -/* - * lcp_addci - Add our desired CIs to a packet. - */ -static void lcp_addci(fsm *f, u_char *ucp, int *lenp) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char *start_ucp = ucp; - -#define ADDCIVOID(opt, neg) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_VOID, ucp); \ - } -#define ADDCISHORT(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_SHORT, ucp); \ - PUTSHORT(val, ucp); \ - } -#if CHAP_SUPPORT -#define ADDCICHAP(opt, neg, val) \ - if (neg) { \ - PUTCHAR((opt), ucp); \ - PUTCHAR(CILEN_CHAP, ucp); \ - PUTSHORT(PPP_CHAP, ucp); \ - PUTCHAR((CHAP_DIGEST(val)), ucp); \ - } -#endif /* CHAP_SUPPORT */ -#define ADDCILONG(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LONG, ucp); \ - PUTLONG(val, ucp); \ - } -#if LQR_SUPPORT -#define ADDCILQR(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_LQR, ucp); \ - PUTSHORT(PPP_LQR, ucp); \ - PUTLONG(val, ucp); \ - } -#endif /* LQR_SUPPORT */ -#define ADDCICHAR(opt, neg, val) \ - if (neg) { \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAR, ucp); \ - PUTCHAR(val, ucp); \ - } -#define ADDCIENDP(opt, neg, class, val, len) \ - if (neg) { \ - int i; \ - PUTCHAR(opt, ucp); \ - PUTCHAR(CILEN_CHAR + len, ucp); \ - PUTCHAR(class, ucp); \ - for (i = 0; i < len; ++i) \ - PUTCHAR(val[i], ucp); \ - } - - ADDCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); - ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, - go->asyncmap); -#if EAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT - ADDCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); -#endif /* EAP_SUPPORT */ -#if !EAP_SUPPORT - ADDCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); -#endif /* !EAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT && CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && CHAP_SUPPORT */ -#if EAP_SUPPORT && !CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ -#if !EAP_SUPPORT && CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ -#if !EAP_SUPPORT && !CHAP_SUPPORT - ADDCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT - ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); -#endif /* LQR_SUPPORT */ - ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression); -#ifdef HAVE_MULTILINK - ADDCISHORT(CI_MRRU, go->neg_mrru, go->mrru); -#endif - ADDCIVOID(CI_SSNHF, go->neg_ssnhf); - ADDCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, - go->endpoint.value, go->endpoint.length); - - if (ucp - start_ucp != *lenp) { - /* this should never happen, because peer_mtu should be 1500 */ - ppp_error("Bug in lcp_addci: wrong length"); - } -} - - -/* - * lcp_ackci - Ack our CIs. - * This should not modify any state if the Ack is bad. - * - * Returns: - * 0 - Ack was bad. - * 1 - Ack was good. - */ -static int lcp_ackci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char cilen, citype, cichar; - u_short cishort; - u32_t cilong; - - /* - * CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define ACKCIVOID(opt, neg) \ - if (neg) { \ - if ((len -= CILEN_VOID) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_VOID || \ - citype != opt) \ - goto bad; \ - } -#define ACKCISHORT(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_SHORT) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_SHORT || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != val) \ - goto bad; \ - } -#define ACKCICHAR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_CHAR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAR || \ - citype != opt) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != val) \ - goto bad; \ - } -#if CHAP_SUPPORT -#define ACKCICHAP(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_CHAP) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAP || \ - citype != (opt)) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != PPP_CHAP) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != (CHAP_DIGEST(val))) \ - goto bad; \ - } -#endif /* CHAP_SUPPORT */ -#define ACKCILONG(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LONG) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LONG || \ - citype != opt) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } -#if LQR_SUPPORT -#define ACKCILQR(opt, neg, val) \ - if (neg) { \ - if ((len -= CILEN_LQR) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_LQR || \ - citype != opt) \ - goto bad; \ - GETSHORT(cishort, p); \ - if (cishort != PPP_LQR) \ - goto bad; \ - GETLONG(cilong, p); \ - if (cilong != val) \ - goto bad; \ - } -#endif /* LQR_SUPPORT */ -#define ACKCIENDP(opt, neg, class, val, vlen) \ - if (neg) { \ - int i; \ - if ((len -= CILEN_CHAR + vlen) < 0) \ - goto bad; \ - GETCHAR(citype, p); \ - GETCHAR(cilen, p); \ - if (cilen != CILEN_CHAR + vlen || \ - citype != opt) \ - goto bad; \ - GETCHAR(cichar, p); \ - if (cichar != class) \ - goto bad; \ - for (i = 0; i < vlen; ++i) { \ - GETCHAR(cichar, p); \ - if (cichar != val[i]) \ - goto bad; \ - } \ - } - - ACKCISHORT(CI_MRU, go->neg_mru && go->mru != PPP_DEFMRU, go->mru); - ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF, - go->asyncmap); -#if EAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, go->neg_eap, PPP_EAP); -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT - ACKCICHAP(CI_AUTHTYPE, !go->neg_eap && go->neg_chap, go->chap_mdtype); -#endif /* EAP_SUPPORT */ -#if !EAP_SUPPORT - ACKCICHAP(CI_AUTHTYPE, go->neg_chap, go->chap_mdtype); -#endif /* !EAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT /* cannot be improved, embedding a directive within macro arguments is not portable */ -#if EAP_SUPPORT && CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && CHAP_SUPPORT */ -#if EAP_SUPPORT && !CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, !go->neg_eap && go->neg_upap, PPP_PAP); -#endif /* EAP_SUPPORT && !CHAP_SUPPORT */ -#if !EAP_SUPPORT && CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && CHAP_SUPPORT */ -#if !EAP_SUPPORT && !CHAP_SUPPORT - ACKCISHORT(CI_AUTHTYPE, go->neg_upap, PPP_PAP); -#endif /* !EAP_SUPPORT && !CHAP_SUPPORT */ -#endif /* PAP_SUPPORT */ -#if LQR_SUPPORT - ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); -#endif /* LQR_SUPPORT */ - ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT); - ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); - ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); - ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression); -#ifdef HAVE_MULTILINK - ACKCISHORT(CI_MRRU, go->neg_mrru, go->mrru); -#endif /* HAVE_MULTILINK */ - ACKCIVOID(CI_SSNHF, go->neg_ssnhf); - ACKCIENDP(CI_EPDISC, go->neg_endpoint, go->endpoint.class_, - go->endpoint.value, go->endpoint.length); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - return (1); -bad: - LCPDEBUG(("lcp_acki: received bad Ack!")); - return (0); -} - - -/* - * lcp_nakci - Peer has sent a NAK for some of our CIs. - * This should not modify any state if the Nak is bad - * or if LCP is in the OPENED state. - * - * Returns: - * 0 - Nak was bad. - * 1 - Nak was good. - */ -static int lcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *wo = &pcb->lcp_wantoptions; - u_char citype, cichar, *next; - u_short cishort; - u32_t cilong; - lcp_options no; /* options we've seen Naks for */ - lcp_options try_; /* options to request next time */ - int looped_back = 0; - int cilen; - - BZERO(&no, sizeof(no)); - try_ = *go; - - /* - * Any Nak'd CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define NAKCIVOID(opt, neg) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - no.neg = 1; \ - try_.neg = 0; \ - } -#if CHAP_SUPPORT -#define NAKCICHAP(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#endif /* CHAP_SUPPORT */ -#define NAKCICHAR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_CHAR && \ - p[1] == CILEN_CHAR && \ - p[0] == opt) { \ - len -= CILEN_CHAR; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - no.neg = 1; \ - code \ - } -#define NAKCISHORT(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - no.neg = 1; \ - code \ - } -#define NAKCILONG(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } -#if LQR_SUPPORT -#define NAKCILQR(opt, neg, code) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - no.neg = 1; \ - code \ - } -#endif /* LQR_SUPPORT */ -#define NAKCIENDP(opt, neg) \ - if (go->neg && \ - len >= CILEN_CHAR && \ - p[0] == opt && \ - p[1] >= CILEN_CHAR && \ - p[1] <= len) { \ - len -= p[1]; \ - INCPTR(p[1], p); \ - no.neg = 1; \ - try_.neg = 0; \ - } - - /* - * NOTE! There must be no assignments to individual fields of *go in - * the code below. Any such assignment is a BUG! - */ - /* - * We don't care if they want to send us smaller packets than - * we want. Therefore, accept any MRU less than what we asked for, - * but then ignore the new value when setting the MRU in the kernel. - * If they send us a bigger MRU than what we asked, accept it, up to - * the limit of the default MRU we'd get if we didn't negotiate. - */ - if (go->neg_mru && go->mru != PPP_DEFMRU) { - NAKCISHORT(CI_MRU, neg_mru, - if (cishort <= wo->mru || cishort <= PPP_DEFMRU) - try_.mru = cishort; - ); - } - - /* - * Add any characters they want to our (receive-side) asyncmap. - */ - if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) { - NAKCILONG(CI_ASYNCMAP, neg_asyncmap, - try_.asyncmap = go->asyncmap | cilong; - ); - } - - /* - * If they've nak'd our authentication-protocol, check whether - * they are proposing a different protocol, or a different - * hash algorithm for CHAP. - */ - if ((0 -#if CHAP_SUPPORT - || go->neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - || go->neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap -#endif /* EAP_SUPPORT */ - ) - && len >= CILEN_SHORT - && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) { - cilen = p[1]; - len -= cilen; -#if CHAP_SUPPORT - no.neg_chap = go->neg_chap; -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - no.neg_upap = go->neg_upap; -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - no.neg_eap = go->neg_eap; -#endif /* EAP_SUPPORT */ - INCPTR(2, p); - GETSHORT(cishort, p); - -#if PAP_SUPPORT - if (cishort == PPP_PAP && cilen == CILEN_SHORT) { -#if EAP_SUPPORT - /* If we were asking for EAP, then we need to stop that. */ - if (go->neg_eap) - try_.neg_eap = 0; - else -#endif /* EAP_SUPPORT */ - -#if CHAP_SUPPORT - /* If we were asking for CHAP, then we need to stop that. */ - if (go->neg_chap) - try_.neg_chap = 0; - else -#endif /* CHAP_SUPPORT */ - - /* - * If we weren't asking for CHAP or EAP, then we were asking for - * PAP, in which case this Nak is bad. - */ - goto bad; - } else -#endif /* PAP_SUPPORT */ - -#if CHAP_SUPPORT - if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { - GETCHAR(cichar, p); -#if EAP_SUPPORT - /* Stop asking for EAP, if we were. */ - if (go->neg_eap) { - try_.neg_eap = 0; - /* Try to set up to use their suggestion, if possible */ - if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) - try_.chap_mdtype = CHAP_MDTYPE_D(cichar); - } else -#endif /* EAP_SUPPORT */ - if (go->neg_chap) { - /* - * We were asking for our preferred algorithm, they must - * want something different. - */ - if (cichar != CHAP_DIGEST(go->chap_mdtype)) { - if (CHAP_CANDIGEST(go->chap_mdtype, cichar)) { - /* Use their suggestion if we support it ... */ - try_.chap_mdtype = CHAP_MDTYPE_D(cichar); - } else { - /* ... otherwise, try our next-preferred algorithm. */ - try_.chap_mdtype &= ~(CHAP_MDTYPE(try_.chap_mdtype)); - if (try_.chap_mdtype == MDTYPE_NONE) /* out of algos */ - try_.neg_chap = 0; - } - } else { - /* - * Whoops, they Nak'd our algorithm of choice - * but then suggested it back to us. - */ - goto bad; - } - } else { - /* - * Stop asking for PAP if we were asking for it. - */ -#if PAP_SUPPORT - try_.neg_upap = 0; -#endif /* PAP_SUPPORT */ - } - - } else -#endif /* CHAP_SUPPORT */ - { - -#if EAP_SUPPORT - /* - * If we were asking for EAP, and they're Conf-Naking EAP, - * well, that's just strange. Nobody should do that. - */ - if (cishort == PPP_EAP && cilen == CILEN_SHORT && go->neg_eap) - ppp_dbglog("Unexpected Conf-Nak for EAP"); - - /* - * We don't recognize what they're suggesting. - * Stop asking for what we were asking for. - */ - if (go->neg_eap) - try_.neg_eap = 0; - else -#endif /* EAP_SUPPORT */ - -#if CHAP_SUPPORT - if (go->neg_chap) - try_.neg_chap = 0; - else -#endif /* CHAP_SUPPORT */ - -#if PAP_SUPPORT - if(1) - try_.neg_upap = 0; - else -#endif /* PAP_SUPPORT */ - {} - - p += cilen - CILEN_SHORT; - } - } - -#if LQR_SUPPORT - /* - * If they can't cope with our link quality protocol, we'll have - * to stop asking for LQR. We haven't got any other protocol. - * If they Nak the reporting period, take their value XXX ? - */ - NAKCILQR(CI_QUALITY, neg_lqr, - if (cishort != PPP_LQR) - try_.neg_lqr = 0; - else - try_.lqr_period = cilong; - ); -#endif /* LQR_SUPPORT */ - - /* - * Only implementing CBCP...not the rest of the callback options - */ - NAKCICHAR(CI_CALLBACK, neg_cbcp, - try_.neg_cbcp = 0; - (void)cichar; /* if CHAP support is not compiled, cichar is set but not used, which makes some compilers complaining */ - ); - - /* - * Check for a looped-back line. - */ - NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, - try_.magicnumber = magic(); - looped_back = 1; - ); - - /* - * Peer shouldn't send Nak for protocol compression or - * address/control compression requests; they should send - * a Reject instead. If they send a Nak, treat it as a Reject. - */ - NAKCIVOID(CI_PCOMPRESSION, neg_pcompression); - NAKCIVOID(CI_ACCOMPRESSION, neg_accompression); - -#ifdef HAVE_MULTILINK - /* - * Nak for MRRU option - accept their value if it is smaller - * than the one we want. - */ - if (go->neg_mrru) { - NAKCISHORT(CI_MRRU, neg_mrru, - if (treat_as_reject) - try_.neg_mrru = 0; - else if (cishort <= wo->mrru) - try_.mrru = cishort; - ); - } -#else /* HAVE_MULTILINK */ - LWIP_UNUSED_ARG(treat_as_reject); -#endif /* HAVE_MULTILINK */ - - /* - * Nak for short sequence numbers shouldn't be sent, treat it - * like a reject. - */ - NAKCIVOID(CI_SSNHF, neg_ssnhf); - - /* - * Nak of the endpoint discriminator option is not permitted, - * treat it like a reject. - */ - NAKCIENDP(CI_EPDISC, neg_endpoint); - - /* - * There may be remaining CIs, if the peer is requesting negotiation - * on an option that we didn't include in our request packet. - * If we see an option that we requested, or one we've already seen - * in this packet, then this packet is bad. - * If we wanted to respond by starting to negotiate on the requested - * option(s), we could, but we don't, because except for the - * authentication type and quality protocol, if we are not negotiating - * an option, it is because we were told not to. - * For the authentication type, the Nak from the peer means - * `let me authenticate myself with you' which is a bit pointless. - * For the quality protocol, the Nak means `ask me to send you quality - * reports', but if we didn't ask for them, we don't want them. - * An option we don't recognize represents the peer asking to - * negotiate some option we don't support, so ignore it. - */ - while (len >= CILEN_VOID) { - GETCHAR(citype, p); - GETCHAR(cilen, p); - if (cilen < CILEN_VOID || (len -= cilen) < 0) - goto bad; - next = p + cilen - 2; - - switch (citype) { - case CI_MRU: - if ((go->neg_mru && go->mru != PPP_DEFMRU) - || no.neg_mru || cilen != CILEN_SHORT) - goto bad; - GETSHORT(cishort, p); - if (cishort < PPP_DEFMRU) { - try_.neg_mru = 1; - try_.mru = cishort; - } - break; - case CI_ASYNCMAP: - if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) - || no.neg_asyncmap || cilen != CILEN_LONG) - goto bad; - break; - case CI_AUTHTYPE: - if (0 -#if CHAP_SUPPORT - || go->neg_chap || no.neg_chap -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - || go->neg_upap || no.neg_upap -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - || go->neg_eap || no.neg_eap -#endif /* EAP_SUPPORT */ - ) - goto bad; - break; - case CI_MAGICNUMBER: - if (go->neg_magicnumber || no.neg_magicnumber || - cilen != CILEN_LONG) - goto bad; - break; - case CI_PCOMPRESSION: - if (go->neg_pcompression || no.neg_pcompression - || cilen != CILEN_VOID) - goto bad; - break; - case CI_ACCOMPRESSION: - if (go->neg_accompression || no.neg_accompression - || cilen != CILEN_VOID) - goto bad; - break; -#if LQR_SUPPORT - case CI_QUALITY: - if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) - goto bad; - break; -#endif /* LQR_SUPPORT */ -#ifdef HAVE_MULTILINK - case CI_MRRU: - if (go->neg_mrru || no.neg_mrru || cilen != CILEN_SHORT) - goto bad; - break; -#endif /* HAVE_MULTILINK */ - case CI_SSNHF: - if (go->neg_ssnhf || no.neg_ssnhf || cilen != CILEN_VOID) - goto bad; - try_.neg_ssnhf = 1; - break; - case CI_EPDISC: - if (go->neg_endpoint || no.neg_endpoint || cilen < CILEN_CHAR) - goto bad; - break; - default: - break; - } - p = next; - } - - /* - * OK, the Nak is good. Now we can update state. - * If there are any options left we ignore them. - */ - if (f->state != PPP_FSM_OPENED) { - if (looped_back) { - if (++try_.numloops >= pcb->settings.lcp_loopbackfail) { - ppp_notice("Serial line is looped back."); - pcb->err_code = PPPERR_LOOPBACK; - lcp_close(f->pcb, "Loopback detected"); - } - } else - try_.numloops = 0; - *go = try_; - } - - return 1; - -bad: - LCPDEBUG(("lcp_nakci: received bad Nak!")); - return 0; -} - - -/* - * lcp_rejci - Peer has Rejected some of our CIs. - * This should not modify any state if the Reject is bad - * or if LCP is in the OPENED state. - * - * Returns: - * 0 - Reject was bad. - * 1 - Reject was good. - */ -static int lcp_rejci(fsm *f, u_char *p, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u_char cichar; - u_short cishort; - u32_t cilong; - lcp_options try_; /* options to request next time */ - - try_ = *go; - - /* - * Any Rejected CIs must be in exactly the same order that we sent. - * Check packet length and CI length at each step. - * If we find any deviations, then this packet is bad. - */ -#define REJCIVOID(opt, neg) \ - if (go->neg && \ - len >= CILEN_VOID && \ - p[1] == CILEN_VOID && \ - p[0] == opt) { \ - len -= CILEN_VOID; \ - INCPTR(CILEN_VOID, p); \ - try_.neg = 0; \ - } -#define REJCISHORT(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_SHORT && \ - p[1] == CILEN_SHORT && \ - p[0] == opt) { \ - len -= CILEN_SHORT; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - /* Check rejected value. */ \ - if (cishort != val) \ - goto bad; \ - try_.neg = 0; \ - } - -#if CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - try_.neg_eap = try_.neg_upap = 0; \ - } -#endif /* CHAP_SUPPORT && EAP_SUPPORT && PAP_SUPPORT */ - -#if CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - try_.neg_upap = 0; \ - } -#endif /* CHAP_SUPPORT && !EAP_SUPPORT && PAP_SUPPORT */ - -#if CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - try_.neg_eap = 0; \ - } -#endif /* CHAP_SUPPORT && EAP_SUPPORT && !PAP_SUPPORT */ - -#if CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT -#define REJCICHAP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CHAP && \ - p[1] == CILEN_CHAP && \ - p[0] == opt) { \ - len -= CILEN_CHAP; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if ((cishort != PPP_CHAP) || (cichar != (CHAP_DIGEST(val)))) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* CHAP_SUPPORT && !EAP_SUPPORT && !PAP_SUPPORT */ - -#define REJCILONG(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LONG && \ - p[1] == CILEN_LONG && \ - p[0] == opt) { \ - len -= CILEN_LONG; \ - INCPTR(2, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cilong != val) \ - goto bad; \ - try_.neg = 0; \ - } -#if LQR_SUPPORT -#define REJCILQR(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_LQR && \ - p[1] == CILEN_LQR && \ - p[0] == opt) { \ - len -= CILEN_LQR; \ - INCPTR(2, p); \ - GETSHORT(cishort, p); \ - GETLONG(cilong, p); \ - /* Check rejected value. */ \ - if (cishort != PPP_LQR || cilong != val) \ - goto bad; \ - try_.neg = 0; \ - } -#endif /* LQR_SUPPORT */ -#define REJCICBCP(opt, neg, val) \ - if (go->neg && \ - len >= CILEN_CBCP && \ - p[1] == CILEN_CBCP && \ - p[0] == opt) { \ - len -= CILEN_CBCP; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - /* Check rejected value. */ \ - if (cichar != val) \ - goto bad; \ - try_.neg = 0; \ - } -#define REJCIENDP(opt, neg, class, val, vlen) \ - if (go->neg && \ - len >= CILEN_CHAR + vlen && \ - p[0] == opt && \ - p[1] == CILEN_CHAR + vlen) { \ - int i; \ - len -= CILEN_CHAR + vlen; \ - INCPTR(2, p); \ - GETCHAR(cichar, p); \ - if (cichar != class) \ - goto bad; \ - for (i = 0; i < vlen; ++i) { \ - GETCHAR(cichar, p); \ - if (cichar != val[i]) \ - goto bad; \ - } \ - try_.neg = 0; \ - } - - REJCISHORT(CI_MRU, neg_mru, go->mru); - REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); -#if EAP_SUPPORT - REJCISHORT(CI_AUTHTYPE, neg_eap, PPP_EAP); - if (!go->neg_eap) { -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - REJCICHAP(CI_AUTHTYPE, neg_chap, go->chap_mdtype); - if (!go->neg_chap) { -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - } -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - } -#endif /* EAP_SUPPORT */ -#if LQR_SUPPORT - REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); -#endif /* LQR_SUPPORT */ - REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT); - REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); - REJCIVOID(CI_PCOMPRESSION, neg_pcompression); - REJCIVOID(CI_ACCOMPRESSION, neg_accompression); -#ifdef HAVE_MULTILINK - REJCISHORT(CI_MRRU, neg_mrru, go->mrru); -#endif /* HAVE_MULTILINK */ - REJCIVOID(CI_SSNHF, neg_ssnhf); - REJCIENDP(CI_EPDISC, neg_endpoint, go->endpoint.class_, - go->endpoint.value, go->endpoint.length); - - /* - * If there are any remaining CIs, then this packet is bad. - */ - if (len != 0) - goto bad; - /* - * Now we can update state. - */ - if (f->state != PPP_FSM_OPENED) - *go = try_; - return 1; - -bad: - LCPDEBUG(("lcp_rejci: received bad Reject!")); - return 0; -} - - -/* - * lcp_reqci - Check the peer's requested CIs and send appropriate response. - * - * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified - * appropriately. If reject_if_disagree is non-zero, doesn't return - * CONFNAK; returns CONFREJ if it can't return CONFACK. - * - * inp = Requested CIs - * lenp = Length of requested CIs - */ -static int lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *ho = &pcb->lcp_hisoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - u_char *cip, *next; /* Pointer to current and next CIs */ - int cilen, citype, cichar; /* Parsed len, type, char value */ - u_short cishort; /* Parsed short value */ - u32_t cilong; /* Parse long value */ - int rc = CONFACK; /* Final packet return code */ - int orc; /* Individual option return code */ - u_char *p; /* Pointer to next char to parse */ - u_char *rejp; /* Pointer to next char in reject frame */ - struct pbuf *nakp; /* Nak buffer */ - u_char *nakoutp; /* Pointer to next char in Nak frame */ - int l = *lenp; /* Length left */ - - /* - * Reset all his options. - */ - BZERO(ho, sizeof(*ho)); - - /* - * Process all his options. - */ - next = inp; - nakp = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_CTRL_PBUF_MAX_SIZE), PPP_CTRL_PBUF_TYPE); - if(NULL == nakp) - return 0; - if(nakp->tot_len != nakp->len) { - pbuf_free(nakp); - return 0; - } - - nakoutp = (u_char*)nakp->payload; - rejp = inp; - while (l) { - orc = CONFACK; /* Assume success */ - cip = p = next; /* Remember begining of CI */ - if (l < 2 || /* Not enough data for CI header or */ - p[1] < 2 || /* CI length too small or */ - p[1] > l) { /* CI length too big? */ - LCPDEBUG(("lcp_reqci: bad CI length!")); - orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ - l = 0; /* Don't loop again */ - citype = 0; - goto endswitch; - } - GETCHAR(citype, p); /* Parse CI type */ - GETCHAR(cilen, p); /* Parse CI length */ - l -= cilen; /* Adjust remaining length */ - next += cilen; /* Step to next CI */ - - switch (citype) { /* Check CI type */ - case CI_MRU: - if (!ao->neg_mru || /* Allow option? */ - cilen != CILEN_SHORT) { /* Check CI length */ - orc = CONFREJ; /* Reject CI */ - break; - } - GETSHORT(cishort, p); /* Parse MRU */ - - /* - * He must be able to receive at least our minimum. - * No need to check a maximum. If he sends a large number, - * we'll just ignore it. - */ - if (cishort < PPP_MINMRU) { - orc = CONFNAK; /* Nak CI */ - PUTCHAR(CI_MRU, nakoutp); - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_MINMRU, nakoutp); /* Give him a hint */ - break; - } - ho->neg_mru = 1; /* Remember he sent MRU */ - ho->mru = cishort; /* And remember value */ - break; - - case CI_ASYNCMAP: - if (!ao->neg_asyncmap || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - - /* - * Asyncmap must have set at least the bits - * which are set in lcp_allowoptions[unit].asyncmap. - */ - if ((ao->asyncmap & ~cilong) != 0) { - orc = CONFNAK; - PUTCHAR(CI_ASYNCMAP, nakoutp); - PUTCHAR(CILEN_LONG, nakoutp); - PUTLONG(ao->asyncmap | cilong, nakoutp); - break; - } - ho->neg_asyncmap = 1; - ho->asyncmap = cilong; - break; - - case CI_AUTHTYPE: - if (cilen < CILEN_SHORT || - !(0 -#if PAP_SUPPORT - || ao->neg_upap -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - || ao->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || ao->neg_eap -#endif /* EAP_SUPPORT */ - )) { - /* - * Reject the option if we're not willing to authenticate. - */ - ppp_dbglog("No auth is possible"); - orc = CONFREJ; - break; - } - GETSHORT(cishort, p); - - /* - * Authtype must be PAP, CHAP, or EAP. - * - * Note: if more than one of ao->neg_upap, ao->neg_chap, and - * ao->neg_eap are set, and the peer sends a Configure-Request - * with two or more authenticate-protocol requests, then we will - * reject the second request. - * Whether we end up doing CHAP, UPAP, or EAP depends then on - * the ordering of the CIs in the peer's Configure-Request. - */ - -#if PAP_SUPPORT - if (cishort == PPP_PAP) { - /* we've already accepted CHAP or EAP */ - if (0 -#if CHAP_SUPPORT - || ho->neg_chap -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || ho->neg_eap -#endif /* EAP_SUPPORT */ - || cilen != CILEN_SHORT) { - LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_upap) { /* we don't want to do PAP */ - orc = CONFNAK; /* NAK it and suggest CHAP or EAP */ - PUTCHAR(CI_AUTHTYPE, nakoutp); -#if EAP_SUPPORT - if (ao->neg_eap) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_EAP, nakoutp); - } else { -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - } -#endif /* EAP_SUPPORT */ - break; - } - ho->neg_upap = 1; - break; - } -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - if (cishort == PPP_CHAP) { - /* we've already accepted PAP or EAP */ - if ( -#if PAP_SUPPORT - ho->neg_upap || -#endif /* PAP_SUPPORT */ -#if EAP_SUPPORT - ho->neg_eap || -#endif /* EAP_SUPPORT */ - cilen != CILEN_CHAP) { - LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_chap) { /* we don't want to do CHAP */ - orc = CONFNAK; /* NAK it and suggest EAP or PAP */ - PUTCHAR(CI_AUTHTYPE, nakoutp); - PUTCHAR(CILEN_SHORT, nakoutp); -#if EAP_SUPPORT - if (ao->neg_eap) { - PUTSHORT(PPP_EAP, nakoutp); - } else -#endif /* EAP_SUPPORT */ -#if PAP_SUPPORT - if(1) { - PUTSHORT(PPP_PAP, nakoutp); - } - else -#endif /* PAP_SUPPORT */ - {} - break; - } - GETCHAR(cichar, p); /* get digest type */ - if (!(CHAP_CANDIGEST(ao->chap_mdtype, cichar))) { - /* - * We can't/won't do the requested type, - * suggest something else. - */ - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakoutp); - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); - break; - } - ho->chap_mdtype = CHAP_MDTYPE_D(cichar); /* save md type */ - ho->neg_chap = 1; - break; - } -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - if (cishort == PPP_EAP) { - /* we've already accepted CHAP or PAP */ - if ( -#if CHAP_SUPPORT - ho->neg_chap || -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - ho->neg_upap || -#endif /* PAP_SUPPORT */ - cilen != CILEN_SHORT) { - LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE EAP, rejecting...")); - orc = CONFREJ; - break; - } - if (!ao->neg_eap) { /* we don't want to do EAP */ - orc = CONFNAK; /* NAK it and suggest CHAP or PAP */ - PUTCHAR(CI_AUTHTYPE, nakoutp); -#if CHAP_SUPPORT - if (ao->neg_chap) { - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if(1) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_PAP, nakoutp); - } else -#endif /* PAP_SUPPORT */ - {} - break; - } - ho->neg_eap = 1; - break; - } -#endif /* EAP_SUPPORT */ - - /* - * We don't recognize the protocol they're asking for. - * Nak it with something we're willing to do. - * (At this point we know ao->neg_upap || ao->neg_chap || - * ao->neg_eap.) - */ - orc = CONFNAK; - PUTCHAR(CI_AUTHTYPE, nakoutp); - -#if EAP_SUPPORT - if (ao->neg_eap) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_EAP, nakoutp); - } else -#endif /* EAP_SUPPORT */ -#if CHAP_SUPPORT - if (ao->neg_chap) { - PUTCHAR(CILEN_CHAP, nakoutp); - PUTSHORT(PPP_CHAP, nakoutp); - PUTCHAR(CHAP_DIGEST(ao->chap_mdtype), nakoutp); - } else -#endif /* CHAP_SUPPORT */ -#if PAP_SUPPORT - if(1) { - PUTCHAR(CILEN_SHORT, nakoutp); - PUTSHORT(PPP_PAP, nakoutp); - } else -#endif /* PAP_SUPPORT */ - {} - break; - -#if LQR_SUPPORT - case CI_QUALITY: - if (!ao->neg_lqr || - cilen != CILEN_LQR) { - orc = CONFREJ; - break; - } - - GETSHORT(cishort, p); - GETLONG(cilong, p); - - /* - * Check the protocol and the reporting period. - * XXX When should we Nak this, and what with? - */ - if (cishort != PPP_LQR) { - orc = CONFNAK; - PUTCHAR(CI_QUALITY, nakoutp); - PUTCHAR(CILEN_LQR, nakoutp); - PUTSHORT(PPP_LQR, nakoutp); - PUTLONG(ao->lqr_period, nakoutp); - break; - } - break; -#endif /* LQR_SUPPORT */ - - case CI_MAGICNUMBER: - if (!(ao->neg_magicnumber || go->neg_magicnumber) || - cilen != CILEN_LONG) { - orc = CONFREJ; - break; - } - GETLONG(cilong, p); - - /* - * He must have a different magic number. - */ - if (go->neg_magicnumber && - cilong == go->magicnumber) { - cilong = magic(); /* Don't put magic() inside macro! */ - orc = CONFNAK; - PUTCHAR(CI_MAGICNUMBER, nakoutp); - PUTCHAR(CILEN_LONG, nakoutp); - PUTLONG(cilong, nakoutp); - break; - } - ho->neg_magicnumber = 1; - ho->magicnumber = cilong; - break; - - - case CI_PCOMPRESSION: - if (!ao->neg_pcompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_pcompression = 1; - break; - - case CI_ACCOMPRESSION: - if (!ao->neg_accompression || - cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_accompression = 1; - break; - -#ifdef HAVE_MULTILINK - case CI_MRRU: - if (!ao->neg_mrru - || !multilink - || cilen != CILEN_SHORT) { - orc = CONFREJ; - break; - } - - GETSHORT(cishort, p); - /* possibly should insist on a minimum/maximum MRRU here */ - ho->neg_mrru = 1; - ho->mrru = cishort; - break; -#endif /* HAVE_MULTILINK */ - - case CI_SSNHF: - if (!ao->neg_ssnhf -#ifdef HAVE_MULTILINK - || !multilink -#endif /* HAVE_MULTILINK */ - || cilen != CILEN_VOID) { - orc = CONFREJ; - break; - } - ho->neg_ssnhf = 1; - break; - - case CI_EPDISC: - if (!ao->neg_endpoint || - cilen < CILEN_CHAR || - cilen > CILEN_CHAR + MAX_ENDP_LEN) { - orc = CONFREJ; - break; - } - GETCHAR(cichar, p); - cilen -= CILEN_CHAR; - ho->neg_endpoint = 1; - ho->endpoint.class_ = cichar; - ho->endpoint.length = cilen; - MEMCPY(ho->endpoint.value, p, cilen); - INCPTR(cilen, p); - break; - - default: - LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype)); - orc = CONFREJ; - break; - } - -endswitch: - if (orc == CONFACK && /* Good CI */ - rc != CONFACK) /* but prior CI wasnt? */ - continue; /* Don't send this one */ - - if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree /* Getting fed up with sending NAKs? */ - && citype != CI_MAGICNUMBER) { - orc = CONFREJ; /* Get tough if so */ - } else { - if (rc == CONFREJ) /* Rejecting prior CI? */ - continue; /* Don't send this one */ - rc = CONFNAK; - } - } - if (orc == CONFREJ) { /* Reject this CI */ - rc = CONFREJ; - if (cip != rejp) /* Need to move rejected CI? */ - MEMCPY(rejp, cip, cilen); /* Move it */ - INCPTR(cilen, rejp); /* Update output pointer */ - } - } - - /* - * If we wanted to send additional NAKs (for unsent CIs), the - * code would go here. The extra NAKs would go at *nakoutp. - * At present there are no cases where we want to ask the - * peer to negotiate an option. - */ - - switch (rc) { - case CONFACK: - *lenp = next - inp; - break; - case CONFNAK: - /* - * Copy the Nak'd options from the nak buffer to the caller's buffer. - */ - *lenp = nakoutp - (u_char*)nakp->payload; - MEMCPY(inp, nakp->payload, *lenp); - break; - case CONFREJ: - *lenp = rejp - inp; - break; - default: - break; - } - - pbuf_free(nakp); - LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc))); - return (rc); /* Return final code */ -} - - -/* - * lcp_up - LCP has come UP. - */ -static void lcp_up(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *wo = &pcb->lcp_wantoptions; - lcp_options *ho = &pcb->lcp_hisoptions; - lcp_options *go = &pcb->lcp_gotoptions; - lcp_options *ao = &pcb->lcp_allowoptions; - int mtu, mru; - - if (!go->neg_magicnumber) - go->magicnumber = 0; - if (!ho->neg_magicnumber) - ho->magicnumber = 0; - - /* - * Set our MTU to the smaller of the MTU we wanted and - * the MRU our peer wanted. If we negotiated an MRU, - * set our MRU to the larger of value we wanted and - * the value we got in the negotiation. - * Note on the MTU: the link MTU can be the MRU the peer wanted, - * the interface MTU is set to the lowest of that, the - * MTU we want to use, and our link MRU. - */ - mtu = ho->neg_mru? ho->mru: PPP_MRU; - mru = go->neg_mru? LWIP_MAX(wo->mru, go->mru): PPP_MRU; -#ifdef HAVE_MULTILINK - if (!(multilink && go->neg_mrru && ho->neg_mrru)) -#endif /* HAVE_MULTILINK */ - netif_set_mtu(pcb, LWIP_MIN(LWIP_MIN(mtu, mru), ao->mru)); - ppp_send_config(pcb, mtu, - (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), - ho->neg_pcompression, ho->neg_accompression); - ppp_recv_config(pcb, mru, - (pcb->settings.lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff), - go->neg_pcompression, go->neg_accompression); - - if (ho->neg_mru) - pcb->peer_mru = ho->mru; - - lcp_echo_lowerup(f->pcb); /* Enable echo messages */ - - link_established(pcb); -} - - -/* - * lcp_down - LCP has gone DOWN. - * - * Alert other protocols. - */ -static void lcp_down(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - - lcp_echo_lowerdown(f->pcb); - - link_down(pcb); - - ppp_send_config(pcb, PPP_MRU, 0xffffffff, 0, 0); - ppp_recv_config(pcb, PPP_MRU, - (go->neg_asyncmap? go->asyncmap: 0xffffffff), - go->neg_pcompression, go->neg_accompression); - pcb->peer_mru = PPP_MRU; -} - - -/* - * lcp_starting - LCP needs the lower layer up. - */ -static void lcp_starting(fsm *f) { - ppp_pcb *pcb = f->pcb; - link_required(pcb); -} - - -/* - * lcp_finished - LCP has finished with the lower layer. - */ -static void lcp_finished(fsm *f) { - ppp_pcb *pcb = f->pcb; - link_terminated(pcb); -} - - -#if PRINTPKT_SUPPORT -/* - * lcp_printpkt - print the contents of an LCP packet. - */ -static const char* const lcp_codenames[] = { - "ConfReq", "ConfAck", "ConfNak", "ConfRej", - "TermReq", "TermAck", "CodeRej", "ProtRej", - "EchoReq", "EchoRep", "DiscReq", "Ident", - "TimeRem" -}; - -static int lcp_printpkt(const u_char *p, int plen, - void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len, olen, i; - const u_char *pstart, *optend; - u_short cishort; - u32_t cilong; - - if (plen < HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames)) - printer(arg, " %s", lcp_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= HEADERLEN; - switch (code) { - case CONFREQ: - case CONFACK: - case CONFNAK: - case CONFREJ: - /* print option list */ - while (len >= 2) { - GETCHAR(code, p); - GETCHAR(olen, p); - p -= 2; - if (olen < 2 || olen > len) { - break; - } - printer(arg, " <"); - len -= olen; - optend = p + olen; - switch (code) { - case CI_MRU: - if (olen == CILEN_SHORT) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "mru %d", cishort); - } - break; - case CI_ASYNCMAP: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "asyncmap 0x%x", cilong); - } - break; - case CI_AUTHTYPE: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "auth "); - GETSHORT(cishort, p); - switch (cishort) { -#if PAP_SUPPORT - case PPP_PAP: - printer(arg, "pap"); - break; -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - case PPP_CHAP: - printer(arg, "chap"); - if (p < optend) { - switch (*p) { - case CHAP_MD5: - printer(arg, " MD5"); - ++p; - break; -#if MSCHAP_SUPPORT - case CHAP_MICROSOFT: - printer(arg, " MS"); - ++p; - break; - - case CHAP_MICROSOFT_V2: - printer(arg, " MS-v2"); - ++p; - break; -#endif /* MSCHAP_SUPPORT */ - default: - break; - } - } - break; -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - case PPP_EAP: - printer(arg, "eap"); - break; -#endif /* EAP_SUPPORT */ - default: - printer(arg, "0x%x", cishort); - } - } - break; -#if LQR_SUPPORT - case CI_QUALITY: - if (olen >= CILEN_SHORT) { - p += 2; - printer(arg, "quality "); - GETSHORT(cishort, p); - switch (cishort) { - case PPP_LQR: - printer(arg, "lqr"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; -#endif /* LQR_SUPPORT */ - case CI_CALLBACK: - if (olen >= CILEN_CHAR) { - p += 2; - printer(arg, "callback "); - GETCHAR(cishort, p); - switch (cishort) { - case CBCP_OPT: - printer(arg, "CBCP"); - break; - default: - printer(arg, "0x%x", cishort); - } - } - break; - case CI_MAGICNUMBER: - if (olen == CILEN_LONG) { - p += 2; - GETLONG(cilong, p); - printer(arg, "magic 0x%x", cilong); - } - break; - case CI_PCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "pcomp"); - } - break; - case CI_ACCOMPRESSION: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "accomp"); - } - break; - case CI_MRRU: - if (olen == CILEN_SHORT) { - p += 2; - GETSHORT(cishort, p); - printer(arg, "mrru %d", cishort); - } - break; - case CI_SSNHF: - if (olen == CILEN_VOID) { - p += 2; - printer(arg, "ssnhf"); - } - break; - case CI_EPDISC: -#ifdef HAVE_MULTILINK - if (olen >= CILEN_CHAR) { - struct epdisc epd; - p += 2; - GETCHAR(epd.class, p); - epd.length = olen - CILEN_CHAR; - if (epd.length > MAX_ENDP_LEN) - epd.length = MAX_ENDP_LEN; - if (epd.length > 0) { - MEMCPY(epd.value, p, epd.length); - p += epd.length; - } - printer(arg, "endpoint [%s]", epdisc_to_str(&epd)); - } -#else - printer(arg, "endpoint"); -#endif - break; - default: - break; - } - while (p < optend) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - printer(arg, ">"); - } - break; - - case TERMACK: - case TERMREQ: - if (len > 0 && *p >= ' ' && *p < 0x7f) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - - case ECHOREQ: - case ECHOREP: - case DISCREQ: - if (len >= 4) { - GETLONG(cilong, p); - printer(arg, " magic=0x%x", cilong); - len -= 4; - } - break; - - case IDENTIF: - case TIMEREM: - if (len >= 4) { - GETLONG(cilong, p); - printer(arg, " magic=0x%x", cilong); - len -= 4; - } - if (code == TIMEREM) { - if (len < 4) - break; - GETLONG(cilong, p); - printer(arg, " seconds=%u", cilong); - len -= 4; - } - if (len > 0) { - printer(arg, " "); - ppp_print_string(p, len, printer, arg); - p += len; - len = 0; - } - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (i = 0; i < len && i < 32; ++i) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - if (i < len) { - printer(arg, " ..."); - p += len - i; - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -/* - * Time to shut down the link because there is nothing out there. - */ - -static void LcpLinkFailure(fsm *f) { - ppp_pcb *pcb = f->pcb; - if (f->state == PPP_FSM_OPENED) { - ppp_info("No response to %d echo-requests", pcb->lcp_echos_pending); - ppp_notice("Serial link appears to be disconnected."); - pcb->err_code = PPPERR_PEERDEAD; - lcp_close(pcb, "Peer not responding"); - } -} - -/* - * Timer expired for the LCP echo requests from this process. - */ - -static void LcpEchoCheck(fsm *f) { - ppp_pcb *pcb = f->pcb; - - LcpSendEchoRequest (f); - if (f->state != PPP_FSM_OPENED) - return; - - /* - * Start the timer for the next interval. - */ - if (pcb->lcp_echo_timer_running) - ppp_warn("assertion lcp_echo_timer_running==0 failed"); - TIMEOUT (LcpEchoTimeout, f, pcb->settings.lcp_echo_interval); - pcb->lcp_echo_timer_running = 1; -} - -/* - * LcpEchoTimeout - Timer expired on the LCP echo - */ - -static void LcpEchoTimeout(void *arg) { - fsm *f = (fsm*)arg; - ppp_pcb *pcb = f->pcb; - if (pcb->lcp_echo_timer_running != 0) { - pcb->lcp_echo_timer_running = 0; - LcpEchoCheck ((fsm *) arg); - } -} - -/* - * LcpEchoReply - LCP has received a reply to the echo - */ - -static void lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u32_t magic_val; - LWIP_UNUSED_ARG(id); - - /* Check the magic number - don't count replies from ourselves. */ - if (len < 4) { - ppp_dbglog("lcp: received short Echo-Reply, length %d", len); - return; - } - GETLONG(magic_val, inp); - if (go->neg_magicnumber - && magic_val == go->magicnumber) { - ppp_warn("appear to have received our own echo-reply!"); - return; - } - - /* Reset the number of outstanding echo frames */ - pcb->lcp_echos_pending = 0; -} - -/* - * LcpSendEchoRequest - Send an echo request frame to the peer - */ - -static void LcpSendEchoRequest(fsm *f) { - ppp_pcb *pcb = f->pcb; - lcp_options *go = &pcb->lcp_gotoptions; - u32_t lcp_magic; - u_char pkt[4], *pktp; - - /* - * Detect the failure of the peer at this point. - */ - if (pcb->settings.lcp_echo_fails != 0) { - if (pcb->lcp_echos_pending >= pcb->settings.lcp_echo_fails) { - LcpLinkFailure(f); - pcb->lcp_echos_pending = 0; - } - } - -#if PPP_LCP_ADAPTIVE - /* - * If adaptive echos have been enabled, only send the echo request if - * no traffic was received since the last one. - */ - if (pcb->settings.lcp_echo_adaptive) { - static unsigned int last_pkts_in = 0; - -#if PPP_STATS_SUPPORT - update_link_stats(f->unit); - link_stats_valid = 0; -#endif /* PPP_STATS_SUPPORT */ - - if (link_stats.pkts_in != last_pkts_in) { - last_pkts_in = link_stats.pkts_in; - return; - } - } -#endif - - /* - * Make and send the echo request frame. - */ - if (f->state == PPP_FSM_OPENED) { - lcp_magic = go->magicnumber; - pktp = pkt; - PUTLONG(lcp_magic, pktp); - fsm_sdata(f, ECHOREQ, pcb->lcp_echo_number++, pkt, pktp - pkt); - ++pcb->lcp_echos_pending; - } -} - -/* - * lcp_echo_lowerup - Start the timer for the LCP frame - */ - -static void lcp_echo_lowerup(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - - /* Clear the parameters for generating echo frames */ - pcb->lcp_echos_pending = 0; - pcb->lcp_echo_number = 0; - pcb->lcp_echo_timer_running = 0; - - /* If a timeout interval is specified then start the timer */ - if (pcb->settings.lcp_echo_interval != 0) - LcpEchoCheck (f); -} - -/* - * lcp_echo_lowerdown - Stop the timer for the LCP frame - */ - -static void lcp_echo_lowerdown(ppp_pcb *pcb) { - fsm *f = &pcb->lcp_fsm; - - if (pcb->lcp_echo_timer_running != 0) { - UNTIMEOUT (LcpEchoTimeout, f); - pcb->lcp_echo_timer_running = 0; - } -} - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/magic.c b/components/net/lwip-2.0.2/src/netif/ppp/magic.c deleted file mode 100644 index d0d87c5e55..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/magic.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * magic.c - PPP Magic Number routines. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/***************************************************************************** -* randm.c - Random number generator program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* Copyright (c) 1998 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 98-06-03 Guy Lancaster , Global Election Systems Inc. -* Extracted from avos. -*****************************************************************************/ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/magic.h" - -#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ - -#include "netif/ppp/pppcrypt.h" - -#define MD5_HASH_SIZE 16 -static char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */ -static long magic_randcount; /* Pseudo-random incrementer */ -static u32_t magic_randomseed; /* Seed used for random number generation. */ - -/* - * Churn the randomness pool on a random event. Call this early and often - * on random and semi-random system events to build randomness in time for - * usage. For randomly timed events, pass a null pointer and a zero length - * and this will use the system timer and other sources to add randomness. - * If new random data is available, pass a pointer to that and it will be - * included. - * - * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 - */ -static void magic_churnrand(char *rand_data, u32_t rand_len) { - lwip_md5_context md5_ctx; - - /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); - if (rand_data) { - lwip_md5_update(&md5_ctx, (u_char *)rand_data, rand_len); - } else { - struct { - /* INCLUDE fields for any system sources of randomness */ - u32_t jiffies; -#ifdef LWIP_RAND - u32_t rand; -#endif /* LWIP_RAND */ - } sys_data; - magic_randomseed += sys_jiffies(); - sys_data.jiffies = magic_randomseed; -#ifdef LWIP_RAND - sys_data.rand = LWIP_RAND(); -#endif /* LWIP_RAND */ - /* Load sys_data fields here. */ - lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); - } - lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool); - lwip_md5_free(&md5_ctx); -/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ -} - -/* - * Initialize the random number generator. - */ -void magic_init(void) { - magic_churnrand(NULL, 0); -} - -/* - * Randomize our random seed value. - */ -void magic_randomize(void) { - magic_churnrand(NULL, 0); -} - -/* - * magic_random_bytes - Fill a buffer with random bytes. - * - * Use the random pool to generate random data. This degrades to pseudo - * random when used faster than randomness is supplied using magic_churnrand(). - * Note: It's important that there be sufficient randomness in magic_randpool - * before this is called for otherwise the range of the result may be - * narrow enough to make a search feasible. - * - * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 - * - * XXX Why does he not just call magic_churnrand() for each block? Probably - * so that you don't ever publish the seed which could possibly help - * predict future values. - * XXX Why don't we preserve md5 between blocks and just update it with - * magic_randcount each time? Probably there is a weakness but I wish that - * it was documented. - */ -void magic_random_bytes(unsigned char *buf, u32_t buf_len) { - lwip_md5_context md5_ctx; - u_char tmp[MD5_HASH_SIZE]; - u32_t n; - - while (buf_len > 0) { - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); - lwip_md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount)); - lwip_md5_finish(&md5_ctx, tmp); - lwip_md5_free(&md5_ctx); - magic_randcount++; - n = LWIP_MIN(buf_len, MD5_HASH_SIZE); - MEMCPY(buf, tmp, n); - buf += n; - buf_len -= n; - } -} - -/* - * Return a new random number. - */ -u32_t magic(void) { - u32_t new_rand; - - magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); - - return new_rand; -} - -#else /* PPP_MD5_RANDM */ - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ -#ifndef LWIP_RAND -static int magic_randomized; /* Set when truely randomized. */ -#endif /* LWIP_RAND */ -static u32_t magic_randomseed; /* Seed used for random number generation. */ - - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ - -/* - * Initialize the random number generator. - * - * Here we attempt to compute a random number seed but even if - * it isn't random, we'll randomize it later. - * - * The current method uses the fields from the real time clock, - * the idle process counter, the millisecond counter, and the - * hardware timer tick counter. When this is invoked - * in startup(), then the idle counter and timer values may - * repeat after each boot and the real time clock may not be - * operational. Thus we call it again on the first random - * event. - */ -void magic_init(void) { - magic_randomseed += sys_jiffies(); -#ifndef LWIP_RAND - /* Initialize the Borland random number generator. */ - srand((unsigned)magic_randomseed); -#endif /* LWIP_RAND */ -} - -/* - * magic_init - Initialize the magic number generator. - * - * Randomize our random seed value. Here we use the fact that - * this function is called at *truely random* times by the polling - * and network functions. Here we only get 16 bits of new random - * value but we use the previous value to randomize the other 16 - * bits. - */ -void magic_randomize(void) { -#ifndef LWIP_RAND - if (!magic_randomized) { - magic_randomized = !0; - magic_init(); - /* The initialization function also updates the seed. */ - } else { -#endif /* LWIP_RAND */ - magic_randomseed += sys_jiffies(); -#ifndef LWIP_RAND - } -#endif /* LWIP_RAND */ -} - -/* - * Return a new random number. - * - * Here we use the Borland rand() function to supply a pseudo random - * number which we make truely random by combining it with our own - * seed which is randomized by truely random events. - * Thus the numbers will be truely random unless there have been no - * operator or network events in which case it will be pseudo random - * seeded by the real time clock. - */ -u32_t magic(void) { -#ifdef LWIP_RAND - return LWIP_RAND() + magic_randomseed; -#else /* LWIP_RAND */ - return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; -#endif /* LWIP_RAND */ -} - -/* - * magic_random_bytes - Fill a buffer with random bytes. - */ -void magic_random_bytes(unsigned char *buf, u32_t buf_len) { - u32_t new_rand, n; - - while (buf_len > 0) { - new_rand = magic(); - n = LWIP_MIN(buf_len, sizeof(new_rand)); - MEMCPY(buf, &new_rand, n); - buf += n; - buf_len -= n; - } -} -#endif /* PPP_MD5_RANDM */ - -/* - * Return a new random number between 0 and (2^pow)-1 included. - */ -u32_t magic_pow(u8_t pow) { - return magic() & ~(~0UL<. - * Copyright (c) 2002,2003,2004 Google, Inc. - * All rights reserved. - * - * License: - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. - * - * Changelog: - * 08/12/05 - Matt Domsch - * Only need extra skb padding on transmit, not receive. - * 06/18/04 - Matt Domsch , Oleg Makarenko - * Use Linux kernel 2.6 arc4 and sha1 routines rather than - * providing our own. - * 2/15/04 - TS: added #include and testing for Kernel - * version before using - * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are - * deprecated in 2.6 - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MPPE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/err.h" - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/ccp.h" -#include "netif/ppp/mppe.h" -#include "netif/ppp/pppdebug.h" -#include "netif/ppp/pppcrypt.h" - -#define SHA1_SIGNATURE_SIZE 20 - -/* ppp_mppe_state.bits definitions */ -#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ -#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ -#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ -#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ - -#define MPPE_BIT_FLUSHED MPPE_BIT_A -#define MPPE_BIT_ENCRYPTED MPPE_BIT_D - -#define MPPE_BITS(p) ((p)[0] & 0xf0) -#define MPPE_CCOUNT(p) ((((p)[0] & 0x0f) << 8) + (p)[1]) -#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ - -#define MPPE_OVHD 2 /* MPPE overhead/packet */ -#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ - -/* - * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. - * Well, not what's written there, but rather what they meant. - */ -static void mppe_rekey(ppp_mppe_state * state, int initial_key) -{ - lwip_sha1_context sha1_ctx; - u8_t sha1_digest[SHA1_SIGNATURE_SIZE]; - - /* - * Key Derivation, from RFC 3078, RFC 3079. - * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. - */ - lwip_sha1_init(&sha1_ctx); - lwip_sha1_starts(&sha1_ctx); - lwip_sha1_update(&sha1_ctx, state->master_key, state->keylen); - lwip_sha1_update(&sha1_ctx, mppe_sha1_pad1, SHA1_PAD_SIZE); - lwip_sha1_update(&sha1_ctx, state->session_key, state->keylen); - lwip_sha1_update(&sha1_ctx, mppe_sha1_pad2, SHA1_PAD_SIZE); - lwip_sha1_finish(&sha1_ctx, sha1_digest); - lwip_sha1_free(&sha1_ctx); - MEMCPY(state->session_key, sha1_digest, state->keylen); - - if (!initial_key) { - lwip_arc4_init(&state->arc4); - lwip_arc4_setup(&state->arc4, sha1_digest, state->keylen); - lwip_arc4_crypt(&state->arc4, state->session_key, state->keylen); - lwip_arc4_free(&state->arc4); - } - if (state->keylen == 8) { - /* See RFC 3078 */ - state->session_key[0] = 0xd1; - state->session_key[1] = 0x26; - state->session_key[2] = 0x9e; - } - lwip_arc4_init(&state->arc4); - lwip_arc4_setup(&state->arc4, state->session_key, state->keylen); -} - -/* - * Set key, used by MSCHAP before mppe_init() is actually called by CCP so we - * don't have to keep multiple copies of keys. - */ -void mppe_set_key(ppp_pcb *pcb, ppp_mppe_state *state, u8_t *key) { - LWIP_UNUSED_ARG(pcb); - MEMCPY(state->master_key, key, MPPE_MAX_KEY_LEN); -} - -/* - * Initialize (de)compressor state. - */ -void -mppe_init(ppp_pcb *pcb, ppp_mppe_state *state, u8_t options) -{ -#if PPP_DEBUG - const u8_t *debugstr = (const u8_t*)"mppe_comp_init"; - if (&pcb->mppe_decomp == state) { - debugstr = (const u8_t*)"mppe_decomp_init"; - } -#endif /* PPP_DEBUG */ - - /* Save keys. */ - MEMCPY(state->session_key, state->master_key, sizeof(state->master_key)); - - if (options & MPPE_OPT_128) - state->keylen = 16; - else if (options & MPPE_OPT_40) - state->keylen = 8; - else { - PPPDEBUG(LOG_DEBUG, ("%s[%d]: unknown key length\n", debugstr, - pcb->netif->num)); - lcp_close(pcb, "MPPE required but peer negotiation failed"); - return; - } - if (options & MPPE_OPT_STATEFUL) - state->stateful = 1; - - /* Generate the initial session key. */ - mppe_rekey(state, 1); - -#if PPP_DEBUG - { - int i; - char mkey[sizeof(state->master_key) * 2 + 1]; - char skey[sizeof(state->session_key) * 2 + 1]; - - PPPDEBUG(LOG_DEBUG, ("%s[%d]: initialized with %d-bit %s mode\n", - debugstr, pcb->netif->num, (state->keylen == 16) ? 128 : 40, - (state->stateful) ? "stateful" : "stateless")); - - for (i = 0; i < (int)sizeof(state->master_key); i++) - sprintf(mkey + i * 2, "%02x", state->master_key[i]); - for (i = 0; i < (int)sizeof(state->session_key); i++) - sprintf(skey + i * 2, "%02x", state->session_key[i]); - PPPDEBUG(LOG_DEBUG, - ("%s[%d]: keys: master: %s initial session: %s\n", - debugstr, pcb->netif->num, mkey, skey)); - } -#endif /* PPP_DEBUG */ - - /* - * Initialize the coherency count. The initial value is not specified - * in RFC 3078, but we can make a reasonable assumption that it will - * start at 0. Setting it to the max here makes the comp/decomp code - * do the right thing (determined through experiment). - */ - state->ccount = MPPE_CCOUNT_SPACE - 1; - - /* - * Note that even though we have initialized the key table, we don't - * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. - */ - state->bits = MPPE_BIT_ENCRYPTED; -} - -/* - * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), - * tell the compressor to rekey. Note that we MUST NOT rekey for - * every CCP Reset-Request; we only rekey on the next xmit packet. - * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. - * So, rekeying for every CCP Reset-Request is broken as the peer will not - * know how many times we've rekeyed. (If we rekey and THEN get another - * CCP Reset-Request, we must rekey again.) - */ -void mppe_comp_reset(ppp_pcb *pcb, ppp_mppe_state *state) -{ - LWIP_UNUSED_ARG(pcb); - state->bits |= MPPE_BIT_FLUSHED; -} - -/* - * Compress (encrypt) a packet. - * It's strange to call this a compressor, since the output is always - * MPPE_OVHD + 2 bytes larger than the input. - */ -err_t -mppe_compress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb, u16_t protocol) -{ - struct pbuf *n, *np; - u8_t *pl; - err_t err; - - LWIP_UNUSED_ARG(pcb); - - /* TCP stack requires that we don't change the packet payload, therefore we copy - * the whole packet before encryption. - */ - np = pbuf_alloc(PBUF_RAW, MPPE_OVHD + sizeof(protocol) + (*pb)->tot_len, PBUF_POOL); - if (!np) { - return ERR_MEM; - } - - /* Hide MPPE header + protocol */ - pbuf_header(np, -(s16_t)(MPPE_OVHD + sizeof(protocol))); - - if ((err = pbuf_copy(np, *pb)) != ERR_OK) { - pbuf_free(np); - return err; - } - - /* Reveal MPPE header + protocol */ - pbuf_header(np, (s16_t)(MPPE_OVHD + sizeof(protocol))); - - *pb = np; - pl = (u8_t*)np->payload; - - state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; - PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: ccount %d\n", pcb->netif->num, state->ccount)); - /* FIXME: use PUT* macros */ - pl[0] = state->ccount>>8; - pl[1] = state->ccount; - - if (!state->stateful || /* stateless mode */ - ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ - (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ - /* We must rekey */ - if (state->stateful) { - PPPDEBUG(LOG_DEBUG, ("mppe_compress[%d]: rekeying\n", pcb->netif->num)); - } - mppe_rekey(state, 0); - state->bits |= MPPE_BIT_FLUSHED; - } - pl[0] |= state->bits; - state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ - pl += MPPE_OVHD; - - /* Add protocol */ - /* FIXME: add PFC support */ - pl[0] = protocol >> 8; - pl[1] = protocol; - - /* Hide MPPE header */ - pbuf_header(np, -(s16_t)MPPE_OVHD); - - /* Encrypt packet */ - for (n = np; n != NULL; n = n->next) { - lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); - if (n->tot_len == n->len) { - break; - } - } - - /* Reveal MPPE header */ - pbuf_header(np, (s16_t)MPPE_OVHD); - - return ERR_OK; -} - -/* - * We received a CCP Reset-Ack. Just ignore it. - */ -void mppe_decomp_reset(ppp_pcb *pcb, ppp_mppe_state *state) -{ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(state); - return; -} - -/* - * Decompress (decrypt) an MPPE packet. - */ -err_t -mppe_decompress(ppp_pcb *pcb, ppp_mppe_state *state, struct pbuf **pb) -{ - struct pbuf *n0 = *pb, *n; - u8_t *pl; - u16_t ccount; - u8_t flushed; - - /* MPPE Header */ - if (n0->len < MPPE_OVHD) { - PPPDEBUG(LOG_DEBUG, - ("mppe_decompress[%d]: short pkt (%d)\n", - pcb->netif->num, n0->len)); - state->sanity_errors += 100; - goto sanity_error; - } - - pl = (u8_t*)n0->payload; - flushed = MPPE_BITS(pl) & MPPE_BIT_FLUSHED; - ccount = MPPE_CCOUNT(pl); - PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: ccount %d\n", - pcb->netif->num, ccount)); - - /* sanity checks -- terminate with extreme prejudice */ - if (!(MPPE_BITS(pl) & MPPE_BIT_ENCRYPTED)) { - PPPDEBUG(LOG_DEBUG, - ("mppe_decompress[%d]: ENCRYPTED bit not set!\n", - pcb->netif->num)); - state->sanity_errors += 100; - goto sanity_error; - } - if (!state->stateful && !flushed) { - PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set in " - "stateless mode!\n", pcb->netif->num)); - state->sanity_errors += 100; - goto sanity_error; - } - if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { - PPPDEBUG(LOG_DEBUG, ("mppe_decompress[%d]: FLUSHED bit not set on " - "flag packet!\n", pcb->netif->num)); - state->sanity_errors += 100; - goto sanity_error; - } - - /* - * Check the coherency count. - */ - - if (!state->stateful) { - /* Discard late packet */ - if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE > MPPE_CCOUNT_SPACE / 2) { - state->sanity_errors++; - goto sanity_error; - } - - /* RFC 3078, sec 8.1. Rekey for every packet. */ - while (state->ccount != ccount) { - mppe_rekey(state, 0); - state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; - } - } else { - /* RFC 3078, sec 8.2. */ - if (!state->discard) { - /* normal state */ - state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; - if (ccount != state->ccount) { - /* - * (ccount > state->ccount) - * Packet loss detected, enter the discard state. - * Signal the peer to rekey (by sending a CCP Reset-Request). - */ - state->discard = 1; - ccp_resetrequest(pcb); - return ERR_BUF; - } - } else { - /* discard state */ - if (!flushed) { - /* ccp.c will be silent (no additional CCP Reset-Requests). */ - return ERR_BUF; - } else { - /* Rekey for every missed "flag" packet. */ - while ((ccount & ~0xff) != - (state->ccount & ~0xff)) { - mppe_rekey(state, 0); - state->ccount = - (state->ccount + - 256) % MPPE_CCOUNT_SPACE; - } - - /* reset */ - state->discard = 0; - state->ccount = ccount; - /* - * Another problem with RFC 3078 here. It implies that the - * peer need not send a Reset-Ack packet. But RFC 1962 - * requires it. Hopefully, M$ does send a Reset-Ack; even - * though it isn't required for MPPE synchronization, it is - * required to reset CCP state. - */ - } - } - if (flushed) - mppe_rekey(state, 0); - } - - /* Hide MPPE header */ - pbuf_header(n0, -(s16_t)(MPPE_OVHD)); - - /* Decrypt the packet. */ - for (n = n0; n != NULL; n = n->next) { - lwip_arc4_crypt(&state->arc4, (u8_t*)n->payload, n->len); - if (n->tot_len == n->len) { - break; - } - } - - /* good packet credit */ - state->sanity_errors >>= 1; - - return ERR_OK; - -sanity_error: - if (state->sanity_errors >= SANITY_MAX) { - /* - * Take LCP down if the peer is sending too many bogons. - * We don't want to do this for a single or just a few - * instances since it could just be due to packet corruption. - */ - lcp_close(pcb, "Too many MPPE errors"); - } - return ERR_BUF; -} - -#endif /* PPP_SUPPORT && MPPE_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/multilink.c b/components/net/lwip-2.0.2/src/netif/ppp/multilink.c deleted file mode 100644 index 62014e8c87..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/multilink.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * multilink.c - support routines for multilink. - * - * Copyright (c) 2000-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && defined(HAVE_MULTILINK) /* don't build if not configured for use in lwipopts.h */ - -/* Multilink support - * - * Multilink uses Samba TDB (Trivial Database Library), which - * we cannot port, because it needs a filesystem. - * - * We have to choose between doing a memory-shared TDB-clone, - * or dropping multilink support at all. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/tdb.h" - -bool endpoint_specified; /* user gave explicit endpoint discriminator */ -char *bundle_id; /* identifier for our bundle */ -char *blinks_id; /* key for the list of links */ -bool doing_multilink; /* multilink was enabled and agreed to */ -bool multilink_master; /* we own the multilink bundle */ - -extern TDB_CONTEXT *pppdb; -extern char db_key[]; - -static void make_bundle_links (int append); -static void remove_bundle_link (void); -static void iterate_bundle_links (void (*func) (char *)); - -static int get_default_epdisc (struct epdisc *); -static int parse_num (char *str, const char *key, int *valp); -static int owns_unit (TDB_DATA pid, int unit); - -#define set_ip_epdisc(ep, addr) do { \ - ep->length = 4; \ - ep->value[0] = addr >> 24; \ - ep->value[1] = addr >> 16; \ - ep->value[2] = addr >> 8; \ - ep->value[3] = addr; \ -} while (0) - -#define LOCAL_IP_ADDR(addr) \ - (((addr) & 0xff000000) == 0x0a000000 /* 10.x.x.x */ \ - || ((addr) & 0xfff00000) == 0xac100000 /* 172.16.x.x */ \ - || ((addr) & 0xffff0000) == 0xc0a80000) /* 192.168.x.x */ - -#define process_exists(n) (kill((n), 0) == 0 || errno != ESRCH) - -void -mp_check_options() -{ - lcp_options *wo = &lcp_wantoptions[0]; - lcp_options *ao = &lcp_allowoptions[0]; - - doing_multilink = 0; - if (!multilink) - return; - /* if we're doing multilink, we have to negotiate MRRU */ - if (!wo->neg_mrru) { - /* mrru not specified, default to mru */ - wo->mrru = wo->mru; - wo->neg_mrru = 1; - } - ao->mrru = ao->mru; - ao->neg_mrru = 1; - - if (!wo->neg_endpoint && !noendpoint) { - /* get a default endpoint value */ - wo->neg_endpoint = get_default_epdisc(&wo->endpoint); - } -} - -/* - * Make a new bundle or join us to an existing bundle - * if we are doing multilink. - */ -int -mp_join_bundle() -{ - lcp_options *go = &lcp_gotoptions[0]; - lcp_options *ho = &lcp_hisoptions[0]; - lcp_options *ao = &lcp_allowoptions[0]; - int unit, pppd_pid; - int l, mtu; - char *p; - TDB_DATA key, pid, rec; - - if (doing_multilink) { - /* have previously joined a bundle */ - if (!go->neg_mrru || !ho->neg_mrru) { - notice("oops, didn't get multilink on renegotiation"); - lcp_close(pcb, "multilink required"); - return 0; - } - /* XXX should check the peer_authname and ho->endpoint - are the same as previously */ - return 0; - } - - if (!go->neg_mrru || !ho->neg_mrru) { - /* not doing multilink */ - if (go->neg_mrru) - notice("oops, multilink negotiated only for receive"); - mtu = ho->neg_mru? ho->mru: PPP_MRU; - if (mtu > ao->mru) - mtu = ao->mru; - if (demand) { - /* already have a bundle */ - cfg_bundle(0, 0, 0, 0); - netif_set_mtu(pcb, mtu); - return 0; - } - make_new_bundle(0, 0, 0, 0); - set_ifunit(1); - netif_set_mtu(pcb, mtu); - return 0; - } - - doing_multilink = 1; - - /* - * Find the appropriate bundle or join a new one. - * First we make up a name for the bundle. - * The length estimate is worst-case assuming every - * character has to be quoted. - */ - l = 4 * strlen(peer_authname) + 10; - if (ho->neg_endpoint) - l += 3 * ho->endpoint.length + 8; - if (bundle_name) - l += 3 * strlen(bundle_name) + 2; - bundle_id = malloc(l); - if (bundle_id == 0) - novm("bundle identifier"); - - p = bundle_id; - p += slprintf(p, l-1, "BUNDLE=\"%q\"", peer_authname); - if (ho->neg_endpoint || bundle_name) - *p++ = '/'; - if (ho->neg_endpoint) - p += slprintf(p, bundle_id+l-p, "%s", - epdisc_to_str(&ho->endpoint)); - if (bundle_name) - p += slprintf(p, bundle_id+l-p, "/%v", bundle_name); - - /* Make the key for the list of links belonging to the bundle */ - l = p - bundle_id; - blinks_id = malloc(l + 7); - if (blinks_id == NULL) - novm("bundle links key"); - slprintf(blinks_id, l + 7, "BUNDLE_LINKS=%s", bundle_id + 7); - - /* - * For demand mode, we only need to configure the bundle - * and attach the link. - */ - mtu = LWIP_MIN(ho->mrru, ao->mru); - if (demand) { - cfg_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); - netif_set_mtu(pcb, mtu); - script_setenv("BUNDLE", bundle_id + 7, 1); - return 0; - } - - /* - * Check if the bundle ID is already in the database. - */ - unit = -1; - lock_db(); - key.dptr = bundle_id; - key.dsize = p - bundle_id; - pid = tdb_fetch(pppdb, key); - if (pid.dptr != NULL) { - /* bundle ID exists, see if the pppd record exists */ - rec = tdb_fetch(pppdb, pid); - if (rec.dptr != NULL && rec.dsize > 0) { - /* make sure the string is null-terminated */ - rec.dptr[rec.dsize-1] = 0; - /* parse the interface number */ - parse_num(rec.dptr, "IFNAME=ppp", &unit); - /* check the pid value */ - if (!parse_num(rec.dptr, "PPPD_PID=", &pppd_pid) - || !process_exists(pppd_pid) - || !owns_unit(pid, unit)) - unit = -1; - free(rec.dptr); - } - free(pid.dptr); - } - - if (unit >= 0) { - /* attach to existing unit */ - if (bundle_attach(unit)) { - set_ifunit(0); - script_setenv("BUNDLE", bundle_id + 7, 0); - make_bundle_links(1); - unlock_db(); - info("Link attached to %s", ifname); - return 1; - } - /* attach failed because bundle doesn't exist */ - } - - /* we have to make a new bundle */ - make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf); - set_ifunit(1); - netif_set_mtu(pcb, mtu); - script_setenv("BUNDLE", bundle_id + 7, 1); - make_bundle_links(pcb); - unlock_db(); - info("New bundle %s created", ifname); - multilink_master = 1; - return 0; -} - -void mp_exit_bundle() -{ - lock_db(); - remove_bundle_link(); - unlock_db(); -} - -static void sendhup(char *str) -{ - int pid; - - if (parse_num(str, "PPPD_PID=", &pid) && pid != getpid()) { - if (debug) - dbglog("sending SIGHUP to process %d", pid); - kill(pid, SIGHUP); - } -} - -void mp_bundle_terminated() -{ - TDB_DATA key; - - bundle_terminating = 1; - upper_layers_down(pcb); - notice("Connection terminated."); -#if PPP_STATS_SUPPORT - print_link_stats(); -#endif /* PPP_STATS_SUPPORT */ - if (!demand) { - remove_pidfiles(); - script_unsetenv("IFNAME"); - } - - lock_db(); - destroy_bundle(); - iterate_bundle_links(sendhup); - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - tdb_delete(pppdb, key); - unlock_db(); - - new_phase(PPP_PHASE_DEAD); - - doing_multilink = 0; - multilink_master = 0; -} - -static void make_bundle_links(int append) -{ - TDB_DATA key, rec; - char *p; - char entry[32]; - int l; - - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - slprintf(entry, sizeof(entry), "%s;", db_key); - p = entry; - if (append) { - rec = tdb_fetch(pppdb, key); - if (rec.dptr != NULL && rec.dsize > 0) { - rec.dptr[rec.dsize-1] = 0; - if (strstr(rec.dptr, db_key) != NULL) { - /* already in there? strange */ - warn("link entry already exists in tdb"); - return; - } - l = rec.dsize + strlen(entry); - p = malloc(l); - if (p == NULL) - novm("bundle link list"); - slprintf(p, l, "%s%s", rec.dptr, entry); - } else { - warn("bundle link list not found"); - } - if (rec.dptr != NULL) - free(rec.dptr); - } - rec.dptr = p; - rec.dsize = strlen(p) + 1; - if (tdb_store(pppdb, key, rec, TDB_REPLACE)) - error("couldn't %s bundle link list", - append? "update": "create"); - if (p != entry) - free(p); -} - -static void remove_bundle_link() -{ - TDB_DATA key, rec; - char entry[32]; - char *p, *q; - int l; - - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - slprintf(entry, sizeof(entry), "%s;", db_key); - - rec = tdb_fetch(pppdb, key); - if (rec.dptr == NULL || rec.dsize <= 0) { - if (rec.dptr != NULL) - free(rec.dptr); - return; - } - rec.dptr[rec.dsize-1] = 0; - p = strstr(rec.dptr, entry); - if (p != NULL) { - q = p + strlen(entry); - l = strlen(q) + 1; - memmove(p, q, l); - rec.dsize = p - rec.dptr + l; - if (tdb_store(pppdb, key, rec, TDB_REPLACE)) - error("couldn't update bundle link list (removal)"); - } - free(rec.dptr); -} - -static void iterate_bundle_links(void (*func)(char *)) -{ - TDB_DATA key, rec, pp; - char *p, *q; - - key.dptr = blinks_id; - key.dsize = strlen(blinks_id); - rec = tdb_fetch(pppdb, key); - if (rec.dptr == NULL || rec.dsize <= 0) { - error("bundle link list not found (iterating list)"); - if (rec.dptr != NULL) - free(rec.dptr); - return; - } - p = rec.dptr; - p[rec.dsize-1] = 0; - while ((q = strchr(p, ';')) != NULL) { - *q = 0; - key.dptr = p; - key.dsize = q - p; - pp = tdb_fetch(pppdb, key); - if (pp.dptr != NULL && pp.dsize > 0) { - pp.dptr[pp.dsize-1] = 0; - func(pp.dptr); - } - if (pp.dptr != NULL) - free(pp.dptr); - p = q + 1; - } - free(rec.dptr); -} - -static int -parse_num(str, key, valp) - char *str; - const char *key; - int *valp; -{ - char *p, *endp; - int i; - - p = strstr(str, key); - if (p != 0) { - p += strlen(key); - i = strtol(p, &endp, 10); - if (endp != p && (*endp == 0 || *endp == ';')) { - *valp = i; - return 1; - } - } - return 0; -} - -/* - * Check whether the pppd identified by `key' still owns ppp unit `unit'. - */ -static int -owns_unit(key, unit) - TDB_DATA key; - int unit; -{ - char ifkey[32]; - TDB_DATA kd, vd; - int ret = 0; - - slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit); - kd.dptr = ifkey; - kd.dsize = strlen(ifkey); - vd = tdb_fetch(pppdb, kd); - if (vd.dptr != NULL) { - ret = vd.dsize == key.dsize - && memcmp(vd.dptr, key.dptr, vd.dsize) == 0; - free(vd.dptr); - } - return ret; -} - -static int -get_default_epdisc(ep) - struct epdisc *ep; -{ - char *p; - struct hostent *hp; - u32_t addr; - - /* First try for an ethernet MAC address */ - p = get_first_ethernet(); - if (p != 0 && get_if_hwaddr(ep->value, p) >= 0) { - ep->class = EPD_MAC; - ep->length = 6; - return 1; - } - - /* see if our hostname corresponds to a reasonable IP address */ - hp = gethostbyname(hostname); - if (hp != NULL) { - addr = *(u32_t *)hp->h_addr; - if (!bad_ip_adrs(addr)) { - addr = lwip_ntohl(addr); - if (!LOCAL_IP_ADDR(addr)) { - ep->class = EPD_IP; - set_ip_epdisc(ep, addr); - return 1; - } - } - } - - return 0; -} - -/* - * epdisc_to_str - make a printable string from an endpoint discriminator. - */ - -static char *endp_class_names[] = { - "null", "local", "IP", "MAC", "magic", "phone" -}; - -char * -epdisc_to_str(ep) - struct epdisc *ep; -{ - static char str[MAX_ENDP_LEN*3+8]; - u_char *p = ep->value; - int i, mask = 0; - char *q, c, c2; - - if (ep->class == EPD_NULL && ep->length == 0) - return "null"; - if (ep->class == EPD_IP && ep->length == 4) { - u32_t addr; - - GETLONG(addr, p); - slprintf(str, sizeof(str), "IP:%I", lwip_htonl(addr)); - return str; - } - - c = ':'; - c2 = '.'; - if (ep->class == EPD_MAC && ep->length == 6) - c2 = ':'; - else if (ep->class == EPD_MAGIC && (ep->length % 4) == 0) - mask = 3; - q = str; - if (ep->class <= EPD_PHONENUM) - q += slprintf(q, sizeof(str)-1, "%s", - endp_class_names[ep->class]); - else - q += slprintf(q, sizeof(str)-1, "%d", ep->class); - c = ':'; - for (i = 0; i < ep->length && i < MAX_ENDP_LEN; ++i) { - if ((i & mask) == 0) { - *q++ = c; - c = c2; - } - q += slprintf(q, str + sizeof(str) - q, "%.2x", ep->value[i]); - } - return str; -} - -static int hexc_val(int c) -{ - if (c >= 'a') - return c - 'a' + 10; - if (c >= 'A') - return c - 'A' + 10; - return c - '0'; -} - -int -str_to_epdisc(ep, str) - struct epdisc *ep; - char *str; -{ - int i, l; - char *p, *endp; - - for (i = EPD_NULL; i <= EPD_PHONENUM; ++i) { - int sl = strlen(endp_class_names[i]); - if (strncasecmp(str, endp_class_names[i], sl) == 0) { - str += sl; - break; - } - } - if (i > EPD_PHONENUM) { - /* not a class name, try a decimal class number */ - i = strtol(str, &endp, 10); - if (endp == str) - return 0; /* can't parse class number */ - str = endp; - } - ep->class = i; - if (*str == 0) { - ep->length = 0; - return 1; - } - if (*str != ':' && *str != '.') - return 0; - ++str; - - if (i == EPD_IP) { - u32_t addr; - i = parse_dotted_ip(str, &addr); - if (i == 0 || str[i] != 0) - return 0; - set_ip_epdisc(ep, addr); - return 1; - } - if (i == EPD_MAC && get_if_hwaddr(ep->value, str) >= 0) { - ep->length = 6; - return 1; - } - - p = str; - for (l = 0; l < MAX_ENDP_LEN; ++l) { - if (*str == 0) - break; - if (p <= str) - for (p = str; isxdigit(*p); ++p) - ; - i = p - str; - if (i == 0) - return 0; - ep->value[l] = hexc_val(*str++); - if ((i & 1) == 0) - ep->value[l] = (ep->value[l] << 4) + hexc_val(*str++); - if (*str == ':' || *str == '.') - ++str; - } - if (*str != 0 || (ep->class == EPD_MAC && l != 6)) - return 0; - ep->length = l; - return 1; -} - -#endif /* PPP_SUPPORT && HAVE_MULTILINK */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/README b/components/net/lwip-2.0.2/src/netif/ppp/polarssl/README deleted file mode 100644 index 3fdf159ec1..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/README +++ /dev/null @@ -1,22 +0,0 @@ -About PolarSSL files into lwIP PPP support ------------------------------------------- - -This folder contains some files fetched from the latest BSD release of -the PolarSSL project (PolarSSL 0.10.1-bsd) for ciphers and encryption -methods we need for lwIP PPP support. - -The PolarSSL files were cleaned to contain only the necessary struct -fields and functions needed for lwIP. - -The PolarSSL API was not changed at all, so if you are already using -PolarSSL you can choose to skip the compilation of the included PolarSSL -library into lwIP. - -If you are not using the embedded copy you must include external -libraries into your arch/cc.h port file. - -Beware of the stack requirements which can be a lot larger if you are not -using our cleaned PolarSSL library. - - -PolarSSL project website: http://polarssl.org/ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/arc4.c b/components/net/lwip-2.0.2/src/netif/ppp/polarssl/arc4.c deleted file mode 100644 index 6e17ec421b..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/arc4.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * An implementation of the ARCFOUR algorithm - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The ARCFOUR algorithm was publicly disclosed on 94/09. - * - * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_ARC4 - -#include "netif/ppp/polarssl/arc4.h" -/* - * ARC4 key schedule - */ -void arc4_setup( arc4_context *ctx, unsigned char *key, int keylen ) -{ - int i, j, k, a; - unsigned char *m; - - ctx->x = 0; - ctx->y = 0; - m = ctx->m; - - for( i = 0; i < 256; i++ ) - m[i] = (unsigned char) i; - - j = k = 0; - - for( i = 0; i < 256; i++, k++ ) - { - if( k >= keylen ) k = 0; - - a = m[i]; - j = ( j + a + key[k] ) & 0xFF; - m[i] = m[j]; - m[j] = (unsigned char) a; - } -} - -/* - * ARC4 cipher function - */ -void arc4_crypt( arc4_context *ctx, unsigned char *buf, int buflen ) -{ - int i, x, y, a, b; - unsigned char *m; - - x = ctx->x; - y = ctx->y; - m = ctx->m; - - for( i = 0; i < buflen; i++ ) - { - x = ( x + 1 ) & 0xFF; a = m[x]; - y = ( y + a ) & 0xFF; b = m[y]; - - m[x] = (unsigned char) b; - m[y] = (unsigned char) a; - - buf[i] = (unsigned char) - ( buf[i] ^ m[(unsigned char)( a + b )] ); - } - - ctx->x = x; - ctx->y = y; -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/des.c b/components/net/lwip-2.0.2/src/netif/ppp/polarssl/des.c deleted file mode 100644 index 9a89d007bd..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/des.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * FIPS-46-3 compliant Triple-DES implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * DES, on which TDES is based, was originally designed by Horst Feistel - * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). - * - * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES - -#include "netif/ppp/polarssl/des.h" - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Expanded DES S-boxes - */ -static const unsigned long SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const unsigned long SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const unsigned long SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const unsigned long SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const unsigned long SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const unsigned long SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const unsigned long SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const unsigned long SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* - * PC1: left and right halves bit-swap - */ -static const unsigned long LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const unsigned long RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Initial Permutation macro - */ -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* - * Final Permutation macro - */ -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* - * DES round macro - */ -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; } - -static void des_setkey( unsigned long SK[32], unsigned char key[8] ) -{ - int i; - unsigned long X, Y, T; - - GET_ULONG_BE( X, key, 0 ); - GET_ULONG_BE( Y, key, 4 ); - - /* - * Permuted Choice 1 - */ - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* - * calculate subkeys - */ - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } -} - -/* - * DES key schedule (56-bit, encryption) - */ -void des_setkey_enc( des_context *ctx, unsigned char key[8] ) -{ - des_setkey( ctx->sk, key ); -} - -/* - * DES key schedule (56-bit, decryption) - */ -void des_setkey_dec( des_context *ctx, unsigned char key[8] ) -{ - int i; - - des_setkey( ctx->sk, key ); - - for( i = 0; i < 16; i += 2 ) - { - SWAP( ctx->sk[i ], ctx->sk[30 - i] ); - SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); - } -} - -/* - * DES-ECB block encryption/decryption - */ -void des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - unsigned long X, Y, T, *SK; - - SK = ctx->sk; - - GET_ULONG_BE( X, input, 0 ); - GET_ULONG_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_ULONG_BE( Y, output, 0 ); - PUT_ULONG_BE( X, output, 4 ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_DES */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/md4.c b/components/net/lwip-2.0.2/src/netif/ppp/polarssl/md4.c deleted file mode 100644 index b1701a07b9..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/md4.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * RFC 1186/1320 compliant MD4 implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The MD4 algorithm was designed by Ron Rivest in 1990. - * - * http://www.ietf.org/rfc/rfc1186.txt - * http://www.ietf.org/rfc/rfc1320.txt - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 - -#include "netif/ppp/polarssl/md4.h" - -#include - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -/* - * MD4 context setup - */ -void md4_starts( md4_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -static void md4_process( md4_context *ctx, const unsigned char data[64] ) -{ - unsigned long X[16], A, B, C, D; - - GET_ULONG_LE( X[ 0], data, 0 ); - GET_ULONG_LE( X[ 1], data, 4 ); - GET_ULONG_LE( X[ 2], data, 8 ); - GET_ULONG_LE( X[ 3], data, 12 ); - GET_ULONG_LE( X[ 4], data, 16 ); - GET_ULONG_LE( X[ 5], data, 20 ); - GET_ULONG_LE( X[ 6], data, 24 ); - GET_ULONG_LE( X[ 7], data, 28 ); - GET_ULONG_LE( X[ 8], data, 32 ); - GET_ULONG_LE( X[ 9], data, 36 ); - GET_ULONG_LE( X[10], data, 40 ); - GET_ULONG_LE( X[11], data, 44 ); - GET_ULONG_LE( X[12], data, 48 ); - GET_ULONG_LE( X[13], data, 52 ); - GET_ULONG_LE( X[14], data, 56 ); - GET_ULONG_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x, y, z) ((x & y) | ((~x) & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 1], 7 ); - P( C, D, A, B, X[ 2], 11 ); - P( B, C, D, A, X[ 3], 19 ); - P( A, B, C, D, X[ 4], 3 ); - P( D, A, B, C, X[ 5], 7 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[ 7], 19 ); - P( A, B, C, D, X[ 8], 3 ); - P( D, A, B, C, X[ 9], 7 ); - P( C, D, A, B, X[10], 11 ); - P( B, C, D, A, X[11], 19 ); - P( A, B, C, D, X[12], 3 ); - P( D, A, B, C, X[13], 7 ); - P( C, D, A, B, X[14], 11 ); - P( B, C, D, A, X[15], 19 ); - -#undef P -#undef F - -#define F(x,y,z) ((x & y) | (x & z) | (y & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 4], 5 ); - P( C, D, A, B, X[ 8], 9 ); - P( B, C, D, A, X[12], 13 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 5], 5 ); - P( C, D, A, B, X[ 9], 9 ); - P( B, C, D, A, X[13], 13 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[ 6], 5 ); - P( C, D, A, B, X[10], 9 ); - P( B, C, D, A, X[14], 13 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[ 7], 5 ); - P( C, D, A, B, X[11], 9 ); - P( B, C, D, A, X[15], 13 ); - -#undef P -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 8], 9 ); - P( C, D, A, B, X[ 4], 11 ); - P( B, C, D, A, X[12], 15 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[10], 9 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[14], 15 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 9], 9 ); - P( C, D, A, B, X[ 5], 11 ); - P( B, C, D, A, X[13], 15 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[11], 9 ); - P( C, D, A, B, X[ 7], 11 ); - P( B, C, D, A, X[15], 15 ); - -#undef F -#undef P - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/* - * MD4 process buffer - */ -void md4_update( md4_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, fill ); - md4_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - md4_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, ilen ); - } -} - -static const unsigned char md4_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD4 final digest - */ -void md4_finish( md4_context *ctx, unsigned char output[16] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - md4_update( ctx, md4_padding, padn ); - md4_update( ctx, msglen, 8 ); - - PUT_ULONG_LE( ctx->state[0], output, 0 ); - PUT_ULONG_LE( ctx->state[1], output, 4 ); - PUT_ULONG_LE( ctx->state[2], output, 8 ); - PUT_ULONG_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD4( input buffer ) - */ -void md4( unsigned char *input, int ilen, unsigned char output[16] ) -{ - md4_context ctx; - - md4_starts( &ctx ); - md4_update( &ctx, input, ilen ); - md4_finish( &ctx, output ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD4 */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/md5.c b/components/net/lwip-2.0.2/src/netif/ppp/polarssl/md5.c deleted file mode 100644 index 1ec4d81a69..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/md5.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * RFC 1321 compliant MD5 implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The MD5 algorithm was designed by Ron Rivest in 1991. - * - * http://www.ietf.org/rfc/rfc1321.txt - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 - -#include "netif/ppp/polarssl/md5.h" - -#include - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_ULONG_LE -#define GET_ULONG_LE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] ) \ - | ( (unsigned long) (b)[(i) + 1] << 8 ) \ - | ( (unsigned long) (b)[(i) + 2] << 16 ) \ - | ( (unsigned long) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_ULONG_LE -#define PUT_ULONG_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -/* - * MD5 context setup - */ -void md5_starts( md5_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -static void md5_process( md5_context *ctx, const unsigned char data[64] ) -{ - unsigned long X[16], A, B, C, D; - - GET_ULONG_LE( X[ 0], data, 0 ); - GET_ULONG_LE( X[ 1], data, 4 ); - GET_ULONG_LE( X[ 2], data, 8 ); - GET_ULONG_LE( X[ 3], data, 12 ); - GET_ULONG_LE( X[ 4], data, 16 ); - GET_ULONG_LE( X[ 5], data, 20 ); - GET_ULONG_LE( X[ 6], data, 24 ); - GET_ULONG_LE( X[ 7], data, 28 ); - GET_ULONG_LE( X[ 8], data, 32 ); - GET_ULONG_LE( X[ 9], data, 36 ); - GET_ULONG_LE( X[10], data, 40 ); - GET_ULONG_LE( X[11], data, 44 ); - GET_ULONG_LE( X[12], data, 48 ); - GET_ULONG_LE( X[13], data, 52 ); - GET_ULONG_LE( X[14], data, 56 ); - GET_ULONG_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a,b,c,d,k,s,t) \ -{ \ - a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P( A, B, C, D, 0, 7, 0xD76AA478 ); - P( D, A, B, C, 1, 12, 0xE8C7B756 ); - P( C, D, A, B, 2, 17, 0x242070DB ); - P( B, C, D, A, 3, 22, 0xC1BDCEEE ); - P( A, B, C, D, 4, 7, 0xF57C0FAF ); - P( D, A, B, C, 5, 12, 0x4787C62A ); - P( C, D, A, B, 6, 17, 0xA8304613 ); - P( B, C, D, A, 7, 22, 0xFD469501 ); - P( A, B, C, D, 8, 7, 0x698098D8 ); - P( D, A, B, C, 9, 12, 0x8B44F7AF ); - P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); - P( B, C, D, A, 11, 22, 0x895CD7BE ); - P( A, B, C, D, 12, 7, 0x6B901122 ); - P( D, A, B, C, 13, 12, 0xFD987193 ); - P( C, D, A, B, 14, 17, 0xA679438E ); - P( B, C, D, A, 15, 22, 0x49B40821 ); - -#undef F - -#define F(x,y,z) (y ^ (z & (x ^ y))) - - P( A, B, C, D, 1, 5, 0xF61E2562 ); - P( D, A, B, C, 6, 9, 0xC040B340 ); - P( C, D, A, B, 11, 14, 0x265E5A51 ); - P( B, C, D, A, 0, 20, 0xE9B6C7AA ); - P( A, B, C, D, 5, 5, 0xD62F105D ); - P( D, A, B, C, 10, 9, 0x02441453 ); - P( C, D, A, B, 15, 14, 0xD8A1E681 ); - P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); - P( A, B, C, D, 9, 5, 0x21E1CDE6 ); - P( D, A, B, C, 14, 9, 0xC33707D6 ); - P( C, D, A, B, 3, 14, 0xF4D50D87 ); - P( B, C, D, A, 8, 20, 0x455A14ED ); - P( A, B, C, D, 13, 5, 0xA9E3E905 ); - P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); - P( C, D, A, B, 7, 14, 0x676F02D9 ); - P( B, C, D, A, 12, 20, 0x8D2A4C8A ); - -#undef F - -#define F(x,y,z) (x ^ y ^ z) - - P( A, B, C, D, 5, 4, 0xFFFA3942 ); - P( D, A, B, C, 8, 11, 0x8771F681 ); - P( C, D, A, B, 11, 16, 0x6D9D6122 ); - P( B, C, D, A, 14, 23, 0xFDE5380C ); - P( A, B, C, D, 1, 4, 0xA4BEEA44 ); - P( D, A, B, C, 4, 11, 0x4BDECFA9 ); - P( C, D, A, B, 7, 16, 0xF6BB4B60 ); - P( B, C, D, A, 10, 23, 0xBEBFBC70 ); - P( A, B, C, D, 13, 4, 0x289B7EC6 ); - P( D, A, B, C, 0, 11, 0xEAA127FA ); - P( C, D, A, B, 3, 16, 0xD4EF3085 ); - P( B, C, D, A, 6, 23, 0x04881D05 ); - P( A, B, C, D, 9, 4, 0xD9D4D039 ); - P( D, A, B, C, 12, 11, 0xE6DB99E5 ); - P( C, D, A, B, 15, 16, 0x1FA27CF8 ); - P( B, C, D, A, 2, 23, 0xC4AC5665 ); - -#undef F - -#define F(x,y,z) (y ^ (x | ~z)) - - P( A, B, C, D, 0, 6, 0xF4292244 ); - P( D, A, B, C, 7, 10, 0x432AFF97 ); - P( C, D, A, B, 14, 15, 0xAB9423A7 ); - P( B, C, D, A, 5, 21, 0xFC93A039 ); - P( A, B, C, D, 12, 6, 0x655B59C3 ); - P( D, A, B, C, 3, 10, 0x8F0CCC92 ); - P( C, D, A, B, 10, 15, 0xFFEFF47D ); - P( B, C, D, A, 1, 21, 0x85845DD1 ); - P( A, B, C, D, 8, 6, 0x6FA87E4F ); - P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); - P( C, D, A, B, 6, 15, 0xA3014314 ); - P( B, C, D, A, 13, 21, 0x4E0811A1 ); - P( A, B, C, D, 4, 6, 0xF7537E82 ); - P( D, A, B, C, 11, 10, 0xBD3AF235 ); - P( C, D, A, B, 2, 15, 0x2AD7D2BB ); - P( B, C, D, A, 9, 21, 0xEB86D391 ); - -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} - -/* - * MD5 process buffer - */ -void md5_update( md5_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, fill ); - md5_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - md5_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, ilen ); - } -} - -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD5 final digest - */ -void md5_finish( md5_context *ctx, unsigned char output[16] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_LE( low, msglen, 0 ); - PUT_ULONG_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - md5_update( ctx, md5_padding, padn ); - md5_update( ctx, msglen, 8 ); - - PUT_ULONG_LE( ctx->state[0], output, 0 ); - PUT_ULONG_LE( ctx->state[1], output, 4 ); - PUT_ULONG_LE( ctx->state[2], output, 8 ); - PUT_ULONG_LE( ctx->state[3], output, 12 ); -} - -/* - * output = MD5( input buffer ) - */ -void md5( unsigned char *input, int ilen, unsigned char output[16] ) -{ - md5_context ctx; - - md5_starts( &ctx ); - md5_update( &ctx, input, ilen ); - md5_finish( &ctx, output ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_MD5 */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/sha1.c b/components/net/lwip-2.0.2/src/netif/ppp/polarssl/sha1.c deleted file mode 100644 index c2192eac54..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/polarssl/sha1.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * FIPS-180-1 compliant SHA-1 implementation - * - * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine - * - * Copyright (C) 2009 Paul Bakker - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the names of PolarSSL or XySSL nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * The SHA-1 standard was published by NIST in 1993. - * - * http://www.itl.nist.gov/fipspubs/fip180-1.htm - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 - -#include "netif/ppp/polarssl/sha1.h" - -#include - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_ULONG_BE -#define GET_ULONG_BE(n,b,i) \ -{ \ - (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ - | ( (unsigned long) (b)[(i) + 1] << 16 ) \ - | ( (unsigned long) (b)[(i) + 2] << 8 ) \ - | ( (unsigned long) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_ULONG_BE -#define PUT_ULONG_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * SHA-1 context setup - */ -void sha1_starts( sha1_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) -{ - unsigned long temp, W[16], A, B, C, D, E; - - GET_ULONG_BE( W[ 0], data, 0 ); - GET_ULONG_BE( W[ 1], data, 4 ); - GET_ULONG_BE( W[ 2], data, 8 ); - GET_ULONG_BE( W[ 3], data, 12 ); - GET_ULONG_BE( W[ 4], data, 16 ); - GET_ULONG_BE( W[ 5], data, 20 ); - GET_ULONG_BE( W[ 6], data, 24 ); - GET_ULONG_BE( W[ 7], data, 28 ); - GET_ULONG_BE( W[ 8], data, 32 ); - GET_ULONG_BE( W[ 9], data, 36 ); - GET_ULONG_BE( W[10], data, 40 ); - GET_ULONG_BE( W[11], data, 44 ); - GET_ULONG_BE( W[12], data, 48 ); - GET_ULONG_BE( W[13], data, 52 ); - GET_ULONG_BE( W[14], data, 56 ); - GET_ULONG_BE( W[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) \ -( \ - temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ - W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ - ( W[t & 0x0F] = S(temp,1) ) \ -) - -#define P(a,b,c,d,e,x) \ -{ \ - e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P( A, B, C, D, E, W[0] ); - P( E, A, B, C, D, W[1] ); - P( D, E, A, B, C, W[2] ); - P( C, D, E, A, B, W[3] ); - P( B, C, D, E, A, W[4] ); - P( A, B, C, D, E, W[5] ); - P( E, A, B, C, D, W[6] ); - P( D, E, A, B, C, W[7] ); - P( C, D, E, A, B, W[8] ); - P( B, C, D, E, A, W[9] ); - P( A, B, C, D, E, W[10] ); - P( E, A, B, C, D, W[11] ); - P( D, E, A, B, C, W[12] ); - P( C, D, E, A, B, W[13] ); - P( B, C, D, E, A, W[14] ); - P( A, B, C, D, E, W[15] ); - P( E, A, B, C, D, R(16) ); - P( D, E, A, B, C, R(17) ); - P( C, D, E, A, B, R(18) ); - P( B, C, D, E, A, R(19) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P( A, B, C, D, E, R(20) ); - P( E, A, B, C, D, R(21) ); - P( D, E, A, B, C, R(22) ); - P( C, D, E, A, B, R(23) ); - P( B, C, D, E, A, R(24) ); - P( A, B, C, D, E, R(25) ); - P( E, A, B, C, D, R(26) ); - P( D, E, A, B, C, R(27) ); - P( C, D, E, A, B, R(28) ); - P( B, C, D, E, A, R(29) ); - P( A, B, C, D, E, R(30) ); - P( E, A, B, C, D, R(31) ); - P( D, E, A, B, C, R(32) ); - P( C, D, E, A, B, R(33) ); - P( B, C, D, E, A, R(34) ); - P( A, B, C, D, E, R(35) ); - P( E, A, B, C, D, R(36) ); - P( D, E, A, B, C, R(37) ); - P( C, D, E, A, B, R(38) ); - P( B, C, D, E, A, R(39) ); - -#undef K -#undef F - -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P( A, B, C, D, E, R(40) ); - P( E, A, B, C, D, R(41) ); - P( D, E, A, B, C, R(42) ); - P( C, D, E, A, B, R(43) ); - P( B, C, D, E, A, R(44) ); - P( A, B, C, D, E, R(45) ); - P( E, A, B, C, D, R(46) ); - P( D, E, A, B, C, R(47) ); - P( C, D, E, A, B, R(48) ); - P( B, C, D, E, A, R(49) ); - P( A, B, C, D, E, R(50) ); - P( E, A, B, C, D, R(51) ); - P( D, E, A, B, C, R(52) ); - P( C, D, E, A, B, R(53) ); - P( B, C, D, E, A, R(54) ); - P( A, B, C, D, E, R(55) ); - P( E, A, B, C, D, R(56) ); - P( D, E, A, B, C, R(57) ); - P( C, D, E, A, B, R(58) ); - P( B, C, D, E, A, R(59) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P( A, B, C, D, E, R(60) ); - P( E, A, B, C, D, R(61) ); - P( D, E, A, B, C, R(62) ); - P( C, D, E, A, B, R(63) ); - P( B, C, D, E, A, R(64) ); - P( A, B, C, D, E, R(65) ); - P( E, A, B, C, D, R(66) ); - P( D, E, A, B, C, R(67) ); - P( C, D, E, A, B, R(68) ); - P( B, C, D, E, A, R(69) ); - P( A, B, C, D, E, R(70) ); - P( E, A, B, C, D, R(71) ); - P( D, E, A, B, C, R(72) ); - P( C, D, E, A, B, R(73) ); - P( B, C, D, E, A, R(74) ); - P( A, B, C, D, E, R(75) ); - P( E, A, B, C, D, R(76) ); - P( D, E, A, B, C, R(77) ); - P( C, D, E, A, B, R(78) ); - P( B, C, D, E, A, R(79) ); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} - -/* - * SHA-1 process buffer - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, int ilen ) -{ - int fill; - unsigned long left; - - if( ilen <= 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (unsigned long) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, fill ); - sha1_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - sha1_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - MEMCPY( (void *) (ctx->buffer + left), - input, ilen ); - } -} - -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-1 final digest - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ) -{ - unsigned long last, padn; - unsigned long high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_ULONG_BE( high, msglen, 0 ); - PUT_ULONG_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - sha1_update( ctx, sha1_padding, padn ); - sha1_update( ctx, msglen, 8 ); - - PUT_ULONG_BE( ctx->state[0], output, 0 ); - PUT_ULONG_BE( ctx->state[1], output, 4 ); - PUT_ULONG_BE( ctx->state[2], output, 8 ); - PUT_ULONG_BE( ctx->state[3], output, 12 ); - PUT_ULONG_BE( ctx->state[4], output, 16 ); -} - -/* - * output = SHA-1( input buffer ) - */ -void sha1( unsigned char *input, int ilen, unsigned char output[20] ) -{ - sha1_context ctx; - - sha1_starts( &ctx ); - sha1_update( &ctx, input, ilen ); - sha1_finish( &ctx, output ); -} - -#endif /* PPP_SUPPORT && LWIP_INCLUDED_POLARSSL_SHA1 */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/ppp.c b/components/net/lwip-2.0.2/src/netif/ppp/ppp.c deleted file mode 100644 index 8b77765e5a..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/ppp.c +++ /dev/null @@ -1,1647 +0,0 @@ -/***************************************************************************** -* ppp.c - Network Point to Point Protocol program file. -* -* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. -* portions Copyright (c) 1997 by Global Election Systems Inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 03-01-01 Marc Boucher -* Ported to lwIP. -* 97-11-05 Guy Lancaster , Global Election Systems Inc. -* Original. -*****************************************************************************/ - -/* - * ppp_defs.h - PPP definitions. - * - * if_pppvar.h - private structures and declarations for PPP. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - */ - -/* - * if_ppp.h - Point-to-Point Protocol definitions. - * - * Copyright (c) 1989 Carnegie Mellon University. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by Carnegie Mellon University. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/** - * @defgroup ppp PPP netif - * @ingroup addons - * @verbinclude "ppp.txt" - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/sys.h" -#include "lwip/tcpip.h" -#include "lwip/api.h" -#include "lwip/snmp.h" -#include "lwip/ip4.h" /* for ip4_input() */ -#if PPP_IPV6_SUPPORT -#include "lwip/ip6.h" /* for ip6_input() */ -#endif /* PPP_IPV6_SUPPORT */ -#include "lwip/dns.h" - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/pppos.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/magic.h" - -#if PAP_SUPPORT -#include "netif/ppp/upap.h" -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT -#include "netif/ppp/chap-new.h" -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT -#include "netif/ppp/eap.h" -#endif /* EAP_SUPPORT */ -#if CCP_SUPPORT -#include "netif/ppp/ccp.h" -#endif /* CCP_SUPPORT */ -#if MPPE_SUPPORT -#include "netif/ppp/mppe.h" -#endif /* MPPE_SUPPORT */ -#if ECP_SUPPORT -#include "netif/ppp/ecp.h" -#endif /* EAP_SUPPORT */ -#if VJ_SUPPORT -#include "netif/ppp/vj.h" -#endif /* VJ_SUPPORT */ -#if PPP_IPV4_SUPPORT -#include "netif/ppp/ipcp.h" -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT -#include "netif/ppp/ipv6cp.h" -#endif /* PPP_IPV6_SUPPORT */ - -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ - -/* Memory pools */ -#if PPPOS_SUPPORT -LWIP_MEMPOOL_PROTOTYPE(PPPOS_PCB); -#endif -#if PPPOE_SUPPORT -LWIP_MEMPOOL_PROTOTYPE(PPPOE_IF); -#endif -#if PPPOL2TP_SUPPORT -LWIP_MEMPOOL_PROTOTYPE(PPPOL2TP_PCB); -#endif -#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE -LWIP_MEMPOOL_PROTOTYPE(PPPAPI_MSG); -#endif -LWIP_MEMPOOL_DECLARE(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") - -/* FIXME: add stats per PPP session */ -#if PPP_STATS_SUPPORT -static struct timeval start_time; /* Time when link was started. */ -static struct pppd_stats old_link_stats; -struct pppd_stats link_stats; -unsigned link_connect_time; -int link_stats_valid; -#endif /* PPP_STATS_SUPPORT */ - -/* - * PPP Data Link Layer "protocol" table. - * One entry per supported protocol. - * The last entry must be NULL. - */ -const struct protent* const protocols[] = { - &lcp_protent, -#if PAP_SUPPORT - &pap_protent, -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - &chap_protent, -#endif /* CHAP_SUPPORT */ -#if CBCP_SUPPORT - &cbcp_protent, -#endif /* CBCP_SUPPORT */ -#if PPP_IPV4_SUPPORT - &ipcp_protent, -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - &ipv6cp_protent, -#endif /* PPP_IPV6_SUPPORT */ -#if CCP_SUPPORT - &ccp_protent, -#endif /* CCP_SUPPORT */ -#if ECP_SUPPORT - &ecp_protent, -#endif /* ECP_SUPPORT */ -#ifdef AT_CHANGE - &atcp_protent, -#endif /* AT_CHANGE */ -#if EAP_SUPPORT - &eap_protent, -#endif /* EAP_SUPPORT */ - NULL -}; - -/* Prototypes for procedures local to this file. */ -static void ppp_do_connect(void *arg); -static err_t ppp_netif_init_cb(struct netif *netif); -#if LWIP_IPV4 -static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr); -#endif /* LWIP_IPV4 */ -#if PPP_IPV6_SUPPORT -static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr); -#endif /* PPP_IPV6_SUPPORT */ -static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol); - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ -#if PPP_AUTH_SUPPORT -void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { -#if PAP_SUPPORT - pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - pcb->settings.refuse_chap = !(authtype & PPPAUTHTYPE_CHAP); -#if MSCHAP_SUPPORT - pcb->settings.refuse_mschap = !(authtype & PPPAUTHTYPE_MSCHAP); - pcb->settings.refuse_mschap_v2 = !(authtype & PPPAUTHTYPE_MSCHAP_V2); -#endif /* MSCHAP_SUPPORT */ -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - pcb->settings.refuse_eap = !(authtype & PPPAUTHTYPE_EAP); -#endif /* EAP_SUPPORT */ - pcb->settings.user = user; - pcb->settings.passwd = passwd; -} -#endif /* PPP_AUTH_SUPPORT */ - -#if MPPE_SUPPORT -/* Set MPPE configuration */ -void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { - if (flags == PPP_MPPE_DISABLE) { - pcb->settings.require_mppe = 0; - return; - } - - pcb->settings.require_mppe = 1; - pcb->settings.refuse_mppe_stateful = !(flags & PPP_MPPE_ALLOW_STATEFUL); - pcb->settings.refuse_mppe_40 = !!(flags & PPP_MPPE_REFUSE_40); - pcb->settings.refuse_mppe_128 = !!(flags & PPP_MPPE_REFUSE_128); -} -#endif /* MPPE_SUPPORT */ - -#if PPP_NOTIFY_PHASE -void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { - pcb->notify_phase_cb = notify_phase_cb; - notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); -} -#endif /* PPP_NOTIFY_PHASE */ - -/* - * Initiate a PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * Holdoff is the time to wait (in seconds) before initiating - * the connection. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { - if (pcb->phase != PPP_PHASE_DEAD) { - return ERR_ALREADY; - } - - PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); - - if (holdoff == 0) { - ppp_do_connect(pcb); - return ERR_OK; - } - - new_phase(pcb, PPP_PHASE_HOLDOFF); - sys_timeout((u32_t)(holdoff*1000), ppp_do_connect, pcb); - return ERR_OK; -} - -#if PPP_SERVER -/* - * Listen for an incoming PPP connection. - * - * This can only be called if PPP is in the dead phase. - * - * If this port connects to a modem, the modem connection must be - * established before calling this. - */ -err_t ppp_listen(ppp_pcb *pcb) { - if (pcb->phase != PPP_PHASE_DEAD) { - return ERR_ALREADY; - } - - PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); - - if (pcb->link_cb->listen) { - new_phase(pcb, PPP_PHASE_INITIALIZE); - pcb->link_cb->listen(pcb, pcb->link_ctx_cb); - return ERR_OK; - } - return ERR_IF; -} -#endif /* PPP_SERVER */ - -/* - * Initiate the end of a PPP connection. - * Any outstanding packets in the queues are dropped. - * - * Setting nocarrier to 1 close the PPP connection without initiating the - * shutdown procedure. Always using nocarrier = 0 is still recommended, - * this is going to take a little longer time if your link is down, but - * is a safer choice for the PPP state machine. - * - * Return 0 on success, an error code on failure. - */ -err_t -ppp_close(ppp_pcb *pcb, u8_t nocarrier) -{ - pcb->err_code = PPPERR_USER; - - /* holdoff phase, cancel the reconnection */ - if (pcb->phase == PPP_PHASE_HOLDOFF) { - sys_untimeout(ppp_do_connect, pcb); - new_phase(pcb, PPP_PHASE_DEAD); - } - - /* dead phase, nothing to do, call the status callback to be consistent */ - if (pcb->phase == PPP_PHASE_DEAD) { - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); - return ERR_OK; - } - - /* Already terminating, nothing to do */ - if (pcb->phase >= PPP_PHASE_TERMINATE) { - return ERR_INPROGRESS; - } - - /* LCP not open, close link protocol */ - if (pcb->phase < PPP_PHASE_ESTABLISH) { - new_phase(pcb, PPP_PHASE_DISCONNECT); - ppp_link_terminated(pcb); - return ERR_OK; - } - - /* - * Only accept carrier lost signal on the stable running phase in order - * to prevent changing the PPP phase FSM in transition phases. - * - * Always using nocarrier = 0 is still recommended, this is going to - * take a little longer time, but is a safer choice from FSM point of view. - */ - if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { - PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); - lcp_lowerdown(pcb); - /* forced link termination, this will force link protocol to disconnect. */ - link_terminated(pcb); - return ERR_OK; - } - - /* Disconnect */ - PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); - /* LCP soft close request. */ - lcp_close(pcb, "User request"); - return ERR_OK; -} - -/* - * Release the control block. - * - * This can only be called if PPP is in the dead phase. - * - * You must use ppp_close() before if you wish to terminate - * an established PPP session. - * - * Return 0 on success, an error code on failure. - */ -err_t ppp_free(ppp_pcb *pcb) { - err_t err; - if (pcb->phase != PPP_PHASE_DEAD) { - return ERR_CONN; - } - - PPPDEBUG(LOG_DEBUG, ("ppp_free[%d]\n", pcb->netif->num)); - - netif_remove(pcb->netif); - - err = pcb->link_cb->free(pcb, pcb->link_ctx_cb); - - LWIP_MEMPOOL_FREE(PPP_PCB, pcb); - return err; -} - -/* Get and set parameters for the given connection. - * Return 0 on success, an error code on failure. */ -err_t -ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) -{ - if (pcb == NULL) { - return ERR_VAL; - } - - switch(cmd) { - case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ - if (!arg) { - goto fail; - } - *(int *)arg = (int)(0 -#if PPP_IPV4_SUPPORT - || pcb->if4_up -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - || pcb->if6_up -#endif /* PPP_IPV6_SUPPORT */ - ); - return ERR_OK; - - case PPPCTLG_ERRCODE: /* Get the PPP error code. */ - if (!arg) { - goto fail; - } - *(int *)arg = (int)(pcb->err_code); - return ERR_OK; - - default: - goto fail; - } - -fail: - return ERR_VAL; -} - - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ - -static void ppp_do_connect(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); - - new_phase(pcb, PPP_PHASE_INITIALIZE); - pcb->link_cb->connect(pcb, pcb->link_ctx_cb); -} - -/* - * ppp_netif_init_cb - netif init callback - */ -static err_t ppp_netif_init_cb(struct netif *netif) { - netif->name[0] = 'p'; - netif->name[1] = 'p'; -#if LWIP_IPV4 - /* FIXME: change that when netif_null_output_ip4() will materialize */ - netif->output = ppp_netif_output_ip4; -#endif /* LWIP_IPV4 */ -#if PPP_IPV6_SUPPORT - netif->output_ip6 = ppp_netif_output_ip6; -#endif /* PPP_IPV6_SUPPORT */ - netif->flags = NETIF_FLAG_UP; -#if LWIP_NETIF_HOSTNAME - /* @todo: Initialize interface hostname */ - /* netif_set_hostname(netif, "lwip"); */ -#endif /* LWIP_NETIF_HOSTNAME */ - return ERR_OK; -} - -#if LWIP_IPV4 -/* - * Send an IPv4 packet on the given connection. - */ -static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr) { - LWIP_UNUSED_ARG(ipaddr); -#if PPP_IPV4_SUPPORT - return ppp_netif_output(netif, pb, PPP_IP); -#else /* PPP_IPV4_SUPPORT */ - LWIP_UNUSED_ARG(netif); - LWIP_UNUSED_ARG(pb); - return ERR_IF; -#endif /* PPP_IPV4_SUPPORT */ -} -#endif /* LWIP_IPV4 */ - -#if PPP_IPV6_SUPPORT -/* - * Send an IPv6 packet on the given connection. - */ -static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr) { - LWIP_UNUSED_ARG(ipaddr); - return ppp_netif_output(netif, pb, PPP_IPV6); -} -#endif /* PPP_IPV6_SUPPORT */ - -static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol) { - ppp_pcb *pcb = (ppp_pcb*)netif->state; - err_t err; - struct pbuf *fpb = NULL; - - /* Check that the link is up. */ - if (0 -#if PPP_IPV4_SUPPORT - || (protocol == PPP_IP && !pcb->if4_up) -#endif /* PPP_IPV4_SUPPORT */ -#if PPP_IPV6_SUPPORT - || (protocol == PPP_IPV6 && !pcb->if6_up) -#endif /* PPP_IPV6_SUPPORT */ - ) { - PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->netif->num)); - goto err_rte_drop; - } - -#if MPPE_SUPPORT - /* If MPPE is required, refuse any IP packet until we are able to crypt them. */ - if (pcb->settings.require_mppe && pcb->ccp_transmit_method != CI_MPPE) { - PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: MPPE required, not up\n", pcb->netif->num)); - goto err_rte_drop; - } -#endif /* MPPE_SUPPORT */ - -#if VJ_SUPPORT - /* - * Attempt Van Jacobson header compression if VJ is configured and - * this is an IP packet. - */ - if (protocol == PPP_IP && pcb->vj_enabled) { - switch (vj_compress_tcp(&pcb->vj_comp, &pb)) { - case TYPE_IP: - /* No change... - protocol = PPP_IP; */ - break; - case TYPE_COMPRESSED_TCP: - /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free - * our duplicated pbuf later */ - fpb = pb; - protocol = PPP_VJC_COMP; - break; - case TYPE_UNCOMPRESSED_TCP: - /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free - * our duplicated pbuf later */ - fpb = pb; - protocol = PPP_VJC_UNCOMP; - break; - default: - PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->netif->num)); - LINK_STATS_INC(link.proterr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(pcb->netif, ifoutdiscards); - return ERR_VAL; - } - } -#endif /* VJ_SUPPORT */ - -#if CCP_SUPPORT - switch (pcb->ccp_transmit_method) { - case 0: - break; /* Don't compress */ -#if MPPE_SUPPORT - case CI_MPPE: - if ((err = mppe_compress(pcb, &pcb->mppe_comp, &pb, protocol)) != ERR_OK) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); - goto err; - } - /* if VJ compressor returned a new allocated pbuf, free it */ - if (fpb) { - pbuf_free(fpb); - } - /* mppe_compress() returns a new allocated pbuf, indicate we should free - * our duplicated pbuf later */ - fpb = pb; - protocol = PPP_COMP; - break; -#endif /* MPPE_SUPPORT */ - default: - PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: bad CCP transmit method\n", pcb->netif->num)); - goto err_rte_drop; /* Cannot really happen, we only negotiate what we are able to do */ - } -#endif /* CCP_SUPPORT */ - - err = pcb->link_cb->netif_output(pcb, pcb->link_ctx_cb, pb, protocol); - goto err; - -err_rte_drop: - err = ERR_RTE; - LINK_STATS_INC(link.rterr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(netif, ifoutdiscards); -err: - if (fpb) { - pbuf_free(fpb); - } - return err; -} - -/************************************/ -/*** PRIVATE FUNCTION DEFINITIONS ***/ -/************************************/ - -/* Initialize the PPP subsystem. */ -int ppp_init(void) -{ -#if PPPOS_SUPPORT - LWIP_MEMPOOL_INIT(PPPOS_PCB); -#endif -#if PPPOE_SUPPORT - LWIP_MEMPOOL_INIT(PPPOE_IF); -#endif -#if PPPOL2TP_SUPPORT - LWIP_MEMPOOL_INIT(PPPOL2TP_PCB); -#endif -#if LWIP_PPP_API && LWIP_MPU_COMPATIBLE - LWIP_MEMPOOL_INIT(PPPAPI_MSG); -#endif - - LWIP_MEMPOOL_INIT(PPP_PCB); - - /* - * Initialize magic number generator now so that protocols may - * use magic numbers in initialization. - */ - magic_init(); - - return 0; -} - -/* - * Create a new PPP control block. - * - * This initializes the PPP control block but does not - * attempt to negotiate the LCP session. - * - * Return a new PPP connection control block pointer - * on success or a null pointer on failure. - */ -ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { - ppp_pcb *pcb; - const struct protent *protp; - int i; - - /* PPP is single-threaded: without a callback, - * there is no way to know when the link is up. */ - if (link_status_cb == NULL) { - return NULL; - } - - pcb = (ppp_pcb*)LWIP_MEMPOOL_ALLOC(PPP_PCB); - if (pcb == NULL) { - return NULL; - } - - memset(pcb, 0, sizeof(ppp_pcb)); - - /* default configuration */ -#if PAP_SUPPORT - pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; - pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; -#if PPP_SERVER - pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; -#endif /* PPP_SERVER */ -#endif /* PAP_SUPPORT */ - -#if CHAP_SUPPORT - pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; - pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; -#if PPP_SERVER - pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; -#endif /* PPP_SERVER */ -#endif /* CHAP_SUPPPORT */ - -#if EAP_SUPPORT - pcb->settings.eap_req_time = EAP_DEFREQTIME; - pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; -#if PPP_SERVER - pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; - pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; -#endif /* PPP_SERVER */ -#endif /* EAP_SUPPORT */ - - pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; - pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; - pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; - - pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; - pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; - pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; - pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; - - pcb->netif = pppif; - MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); - if (!netif_add(pcb->netif, -#if LWIP_IPV4 - IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4, -#endif /* LWIP_IPV4 */ - (void *)pcb, ppp_netif_init_cb, NULL)) { - LWIP_MEMPOOL_FREE(PPP_PCB, pcb); - PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); - return NULL; - } - - pcb->link_cb = callbacks; - pcb->link_ctx_cb = link_ctx_cb; - pcb->link_status_cb = link_status_cb; - pcb->ctx_cb = ctx_cb; - - /* - * Initialize each protocol. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - (*protp->init)(pcb); - } - - new_phase(pcb, PPP_PHASE_DEAD); - return pcb; -} - -/** Initiate LCP open request */ -void ppp_start(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); - - /* Clean data not taken care by anything else, mostly shared data. */ -#if PPP_STATS_SUPPORT - link_stats_valid = 0; -#endif /* PPP_STATS_SUPPORT */ -#if MPPE_SUPPORT - pcb->mppe_keys_set = 0; - memset(&pcb->mppe_comp, 0, sizeof(pcb->mppe_comp)); - memset(&pcb->mppe_decomp, 0, sizeof(pcb->mppe_decomp)); -#endif /* MPPE_SUPPORT */ -#if VJ_SUPPORT - vj_compress_init(&pcb->vj_comp); -#endif /* VJ_SUPPORT */ - - /* Start protocol */ - new_phase(pcb, PPP_PHASE_ESTABLISH); - lcp_open(pcb); - lcp_lowerup(pcb); - PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); -} - -/** Called when link failed to setup */ -void ppp_link_failed(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_link_failed[%d]\n", pcb->netif->num)); - new_phase(pcb, PPP_PHASE_DEAD); - pcb->err_code = PPPERR_OPEN; - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); -} - -/** Called when link is normally down (i.e. it was asked to end) */ -void ppp_link_end(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_link_end[%d]\n", pcb->netif->num)); - new_phase(pcb, PPP_PHASE_DEAD); - if (pcb->err_code == PPPERR_NONE) { - pcb->err_code = PPPERR_CONNECT; - } - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); -} - -/* - * Pass the processed input packet to the appropriate handler. - * This function and all handlers run in the context of the tcpip_thread - */ -void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { - u16_t protocol; -#if PPP_DEBUG && PPP_PROTOCOLNAME - const char *pname; -#endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ - - magic_randomize(); - - if (pb->len < 2) { - PPPDEBUG(LOG_ERR, ("ppp_input[%d]: packet too short\n", pcb->netif->num)); - goto drop; - } - protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; - -#if PRINTPKT_SUPPORT - ppp_dump_packet(pcb, "rcvd", (unsigned char *)pb->payload, pb->len); -#endif /* PRINTPKT_SUPPORT */ - - pbuf_header(pb, -(s16_t)sizeof(protocol)); - - LINK_STATS_INC(link.recv); - MIB2_STATS_NETIF_INC(pcb->netif, ifinucastpkts); - MIB2_STATS_NETIF_ADD(pcb->netif, ifinoctets, pb->tot_len); - - /* - * Toss all non-LCP packets unless LCP is OPEN. - */ - if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { - ppp_dbglog("Discarded non-LCP packet when LCP not open"); - goto drop; - } - - /* - * Until we get past the authentication phase, toss all packets - * except LCP, LQR and authentication packets. - */ - if (pcb->phase <= PPP_PHASE_AUTHENTICATE - && !(protocol == PPP_LCP -#if LQR_SUPPORT - || protocol == PPP_LQR -#endif /* LQR_SUPPORT */ -#if PAP_SUPPORT - || protocol == PPP_PAP -#endif /* PAP_SUPPORT */ -#if CHAP_SUPPORT - || protocol == PPP_CHAP -#endif /* CHAP_SUPPORT */ -#if EAP_SUPPORT - || protocol == PPP_EAP -#endif /* EAP_SUPPORT */ - )) { - ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); - goto drop; - } - -#if CCP_SUPPORT -#if MPPE_SUPPORT - /* - * MPPE is required and unencrypted data has arrived (this - * should never happen!). We should probably drop the link if - * the protocol is in the range of what should be encrypted. - * At the least, we drop this packet. - */ - if (pcb->settings.require_mppe && protocol != PPP_COMP && protocol < 0x8000) { - PPPDEBUG(LOG_ERR, ("ppp_input[%d]: MPPE required, received unencrypted data!\n", pcb->netif->num)); - goto drop; - } -#endif /* MPPE_SUPPORT */ - - if (protocol == PPP_COMP) { - u8_t *pl; - - switch (pcb->ccp_receive_method) { -#if MPPE_SUPPORT - case CI_MPPE: - if (mppe_decompress(pcb, &pcb->mppe_decomp, &pb) != ERR_OK) { - goto drop; - } - break; -#endif /* MPPE_SUPPORT */ - default: - PPPDEBUG(LOG_ERR, ("ppp_input[%d]: bad CCP receive method\n", pcb->netif->num)); - goto drop; /* Cannot really happen, we only negotiate what we are able to do */ - } - - /* Assume no PFC */ - if (pb->len < 2) { - goto drop; - } - - /* Extract and hide protocol (do PFC decompression if necessary) */ - pl = (u8_t*)pb->payload; - if (pl[0] & 0x01) { - protocol = pl[0]; - pbuf_header(pb, -(s16_t)1); - } else { - protocol = (pl[0] << 8) | pl[1]; - pbuf_header(pb, -(s16_t)2); - } - } -#endif /* CCP_SUPPORT */ - - switch(protocol) { - -#if PPP_IPV4_SUPPORT - case PPP_IP: /* Internet Protocol */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - ip4_input(pb, pcb->netif); - return; -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT - case PPP_IPV6: /* Internet Protocol Version 6 */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - ip6_input(pb, pcb->netif); - return; -#endif /* PPP_IPV6_SUPPORT */ - -#if VJ_SUPPORT - case PPP_VJC_COMP: /* VJ compressed TCP */ - /* - * Clip off the VJ header and prepend the rebuilt TCP/IP header and - * pass the result to IP. - */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - if (pcb->vj_enabled && vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { - ip4_input(pb, pcb->netif); - return; - } - /* Something's wrong so drop it. */ - PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->netif->num)); - break; - - case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ - /* - * Process the TCP/IP header for VJ header compression and then pass - * the packet to IP. - */ - PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); - if (pcb->vj_enabled && vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { - ip4_input(pb, pcb->netif); - return; - } - /* Something's wrong so drop it. */ - PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); - break; -#endif /* VJ_SUPPORT */ - - default: { - int i; - const struct protent *protp; - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; (protp = protocols[i]) != NULL; ++i) { - if (protp->protocol == protocol) { - pb = ppp_singlebuf(pb); - (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); - goto out; - } -#if 0 /* UNUSED - * - * This is actually a (hacked?) way for the Linux kernel to pass a data - * packet to pppd. pppd in normal condition only do signaling - * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. - * - * We don't even need this interface, which is only there because of PPP - * interface limitation between Linux kernel and pppd. For MPPE, which uses - * CCP to negotiate although it is not really a (de)compressor, we added - * ccp_resetrequest() in CCP and MPPE input data flow is calling either - * ccp_resetrequest() or lcp_close() if the issue is, respectively, non-fatal - * or fatal, this is what ccp_datainput() really do. - */ - if (protocol == (protp->protocol & ~0x8000) - && protp->datainput != NULL) { - (*protp->datainput)(pcb, pb->payload, pb->len); - goto out; - } -#endif /* UNUSED */ - } - -#if PPP_DEBUG -#if PPP_PROTOCOLNAME - pname = protocol_name(protocol); - if (pname != NULL) { - ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); - } else -#endif /* PPP_PROTOCOLNAME */ - ppp_warn("Unsupported protocol 0x%x received", protocol); -#endif /* PPP_DEBUG */ - pbuf_header(pb, (s16_t)sizeof(protocol)); - lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); - } - break; - } - -drop: - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(pcb->netif, ifindiscards); - -out: - pbuf_free(pb); -} - -/* merge a pbuf chain into one pbuf */ -struct pbuf *ppp_singlebuf(struct pbuf *p) { - struct pbuf *q, *b; - u8_t *pl; - - if(p->tot_len == p->len) { - return p; - } - - q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if(!q) { - PPPDEBUG(LOG_ERR, - ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); - return p; /* live dangerously */ - } - - for(b = p, pl = (u8_t*)q->payload; b != NULL; b = b->next) { - MEMCPY(pl, b->payload, b->len); - pl += b->len; - } - - pbuf_free(p); - - return q; -} - -/* - * Write a pbuf to a ppp link, only used from PPP functions - * to send PPP packets. - * - * IPv4 and IPv6 packets from lwIP are sent, respectively, - * with ppp_netif_output_ip4() and ppp_netif_output_ip6() - * functions (which are callbacks of the netif PPP interface). - */ -err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { -#if PRINTPKT_SUPPORT - ppp_dump_packet(pcb, "sent", (unsigned char *)p->payload+2, p->len-2); -#endif /* PRINTPKT_SUPPORT */ - return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); -} - -void ppp_link_terminated(ppp_pcb *pcb) { - PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]\n", pcb->netif->num)); - pcb->link_cb->disconnect(pcb, pcb->link_ctx_cb); - PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]: finished.\n", pcb->netif->num)); -} - - -/************************************************************************ - * Functions called by various PPP subsystems to configure - * the PPP interface or change the PPP phase. - */ - -/* - * new_phase - signal the start of a new phase of pppd's operation. - */ -void new_phase(ppp_pcb *pcb, int p) { - pcb->phase = p; - PPPDEBUG(LOG_DEBUG, ("ppp phase changed[%d]: phase=%d\n", pcb->netif->num, pcb->phase)); -#if PPP_NOTIFY_PHASE - if (pcb->notify_phase_cb != NULL) { - pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); - } -#endif /* PPP_NOTIFY_PHASE */ -} - -/* - * ppp_send_config - configure the transmit-side characteristics of - * the ppp interface. - */ -int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { - LWIP_UNUSED_ARG(mtu); - /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ - - if (pcb->link_cb->send_config) { - pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); - } - - PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); - return 0; -} - -/* - * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. - */ -int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { - LWIP_UNUSED_ARG(mru); - - if (pcb->link_cb->recv_config) { - pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); - } - - PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); - return 0; -} - -#if PPP_IPV4_SUPPORT -/* - * sifaddr - Config the interface IP addresses and netmask. - */ -int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask) { - ip4_addr_t ip, nm, gw; - - ip4_addr_set_u32(&ip, our_adr); - ip4_addr_set_u32(&nm, netmask); - ip4_addr_set_u32(&gw, his_adr); - netif_set_addr(pcb->netif, &ip, &nm, &gw); - return 1; -} - -/******************************************************************** - * - * cifaddr - Clear the interface IP addresses, and delete routes - * through the interface if possible. - */ -int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { - LWIP_UNUSED_ARG(our_adr); - LWIP_UNUSED_ARG(his_adr); - - netif_set_addr(pcb->netif, IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4); - return 1; -} - -#if 0 /* UNUSED - PROXY ARP */ -/******************************************************************** - * - * sifproxyarp - Make a proxy ARP entry for the peer. - */ - -int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(his_adr); - return 0; -} - -/******************************************************************** - * - * cifproxyarp - Delete the proxy ARP entry for the peer. - */ - -int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(his_adr); - return 0; -} -#endif /* UNUSED - PROXY ARP */ - -#if LWIP_DNS -/* - * sdns - Config the DNS servers - */ -int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { - ip_addr_t ns; - LWIP_UNUSED_ARG(pcb); - - ip_addr_set_ip4_u32(&ns, ns1); - dns_setserver(0, &ns); - ip_addr_set_ip4_u32(&ns, ns2); - dns_setserver(1, &ns); - return 1; -} - -/******************************************************************** - * - * cdns - Clear the DNS servers - */ -int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { - const ip_addr_t *nsa; - ip_addr_t nsb; - LWIP_UNUSED_ARG(pcb); - - nsa = dns_getserver(0); - ip_addr_set_ip4_u32(&nsb, ns1); - if (ip_addr_cmp(nsa, &nsb)) { - dns_setserver(0, IP_ADDR_ANY); - } - nsa = dns_getserver(1); - ip_addr_set_ip4_u32(&nsb, ns2); - if (ip_addr_cmp(nsa, &nsb)) { - dns_setserver(1, IP_ADDR_ANY); - } - return 1; -} -#endif /* LWIP_DNS */ - -#if VJ_SUPPORT -/******************************************************************** - * - * sifvjcomp - config tcp header compression - */ -int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { - pcb->vj_enabled = vjcomp; - pcb->vj_comp.compressSlot = cidcomp; - pcb->vj_comp.maxSlotIndex = maxcid; - PPPDEBUG(LOG_INFO, ("sifvjcomp[%d]: VJ compress enable=%d slot=%d max slot=%d\n", - pcb->netif->num, vjcomp, cidcomp, maxcid)); - return 0; -} -#endif /* VJ_SUPPORT */ - -/* - * sifup - Config the interface up and enable IP packets to pass. - */ -int sifup(ppp_pcb *pcb) { - pcb->if4_up = 1; - pcb->err_code = PPPERR_NONE; - netif_set_link_up(pcb->netif); - - PPPDEBUG(LOG_DEBUG, ("sifup[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); - return 1; -} - -/******************************************************************** - * - * sifdown - Disable the indicated protocol and config the interface - * down if there are no remaining protocols. - */ -int sifdown(ppp_pcb *pcb) { - - pcb->if4_up = 0; - - if (1 -#if PPP_IPV6_SUPPORT - /* set the interface down if IPv6 is down as well */ - && !pcb->if6_up -#endif /* PPP_IPV6_SUPPORT */ - ) { - /* make sure the netif link callback is called */ - netif_set_link_down(pcb->netif); - } - PPPDEBUG(LOG_DEBUG, ("sifdown[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - return 1; -} - -/******************************************************************** - * - * Return user specified netmask, modified by any mask we might determine - * for address `addr' (in network byte order). - * Here we scan through the system's list of interfaces, looking for - * any non-point-to-point interfaces which might appear to be on the same - * network as `addr'. If we find any, we OR in their netmask to the - * user-specified netmask. - */ -u32_t get_mask(u32_t addr) { -#if 0 - u32_t mask, nmask; - - addr = lwip_htonl(addr); - if (IP_CLASSA(addr)) { /* determine network mask for address class */ - nmask = IP_CLASSA_NET; - } else if (IP_CLASSB(addr)) { - nmask = IP_CLASSB_NET; - } else { - nmask = IP_CLASSC_NET; - } - - /* class D nets are disallowed by bad_ip_adrs */ - mask = PP_HTONL(0xffffff00UL) | lwip_htonl(nmask); - - /* XXX - * Scan through the system's network interfaces. - * Get each netmask and OR them into our mask. - */ - /* return mask; */ - return mask; -#endif /* 0 */ - LWIP_UNUSED_ARG(addr); - return IPADDR_BROADCAST; -} -#endif /* PPP_IPV4_SUPPORT */ - -#if PPP_IPV6_SUPPORT -#define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ - ip6.addr[0] = PP_HTONL(0xfe800000); \ - ip6.addr[1] = 0; \ - eui64_copy(eui64, ip6.addr[2]); \ - } while (0) - -/******************************************************************** - * - * sif6addr - Config the interface with an IPv6 link-local address - */ -int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { - ip6_addr_t ip6; - LWIP_UNUSED_ARG(his_eui64); - - IN6_LLADDR_FROM_EUI64(ip6, our_eui64); - netif_ip6_addr_set(pcb->netif, 0, &ip6); - netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_PREFERRED); - /* FIXME: should we add an IPv6 static neighbor using his_eui64 ? */ - return 1; -} - -/******************************************************************** - * - * cif6addr - Remove IPv6 address from interface - */ -int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { - LWIP_UNUSED_ARG(our_eui64); - LWIP_UNUSED_ARG(his_eui64); - - netif_ip6_addr_set(pcb->netif, 0, IP6_ADDR_ANY6); - netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_INVALID); - return 1; -} - -/* - * sif6up - Config the interface up and enable IPv6 packets to pass. - */ -int sif6up(ppp_pcb *pcb) { - - pcb->if6_up = 1; - pcb->err_code = PPPERR_NONE; - netif_set_link_up(pcb->netif); - - PPPDEBUG(LOG_DEBUG, ("sif6up[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); - return 1; -} - -/******************************************************************** - * - * sif6down - Disable the indicated protocol and config the interface - * down if there are no remaining protocols. - */ -int sif6down(ppp_pcb *pcb) { - - pcb->if6_up = 0; - - if (1 -#if PPP_IPV4_SUPPORT - /* set the interface down if IPv4 is down as well */ - && !pcb->if4_up -#endif /* PPP_IPV4_SUPPORT */ - ) { - /* make sure the netif link callback is called */ - netif_set_link_down(pcb->netif); - } - PPPDEBUG(LOG_DEBUG, ("sif6down[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); - return 1; -} -#endif /* PPP_IPV6_SUPPORT */ - -#if DEMAND_SUPPORT -/* - * sifnpmode - Set the mode for handling packets for a given NP. - */ -int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(proto); - LWIP_UNUSED_ARG(mode); - return 0; -} -#endif /* DEMAND_SUPPORT */ - -/* - * netif_set_mtu - set the MTU on the PPP network interface. - */ -void netif_set_mtu(ppp_pcb *pcb, int mtu) { - - pcb->netif->mtu = mtu; - PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); -} - -/* - * netif_get_mtu - get PPP interface MTU - */ -int netif_get_mtu(ppp_pcb *pcb) { - - return pcb->netif->mtu; -} - -#if CCP_SUPPORT -#if 0 /* unused */ -/* - * ccp_test - whether a given compression method is acceptable for use. - */ -int -ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit) -{ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(opt_ptr); - LWIP_UNUSED_ARG(opt_len); - LWIP_UNUSED_ARG(for_transmit); - return -1; -} -#endif /* unused */ - -/* - * ccp_set - inform about the current state of CCP. - */ -void -ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method) -{ - LWIP_UNUSED_ARG(isopen); - LWIP_UNUSED_ARG(isup); - pcb->ccp_receive_method = receive_method; - pcb->ccp_transmit_method = transmit_method; - PPPDEBUG(LOG_DEBUG, ("ccp_set[%d]: is_open=%d, is_up=%d, receive_method=%u, transmit_method=%u\n", - pcb->netif->num, isopen, isup, receive_method, transmit_method)); -} - -void -ccp_reset_comp(ppp_pcb *pcb) -{ - switch (pcb->ccp_transmit_method) { -#if MPPE_SUPPORT - case CI_MPPE: - mppe_comp_reset(pcb, &pcb->mppe_comp); - break; -#endif /* MPPE_SUPPORT */ - default: - break; - } -} - -void -ccp_reset_decomp(ppp_pcb *pcb) -{ - switch (pcb->ccp_receive_method) { -#if MPPE_SUPPORT - case CI_MPPE: - mppe_decomp_reset(pcb, &pcb->mppe_decomp); - break; -#endif /* MPPE_SUPPORT */ - default: - break; - } -} - -#if 0 /* unused */ -/* - * ccp_fatal_error - returns 1 if decompression was disabled as a - * result of an error detected after decompression of a packet, - * 0 otherwise. This is necessary because of patent nonsense. - */ -int -ccp_fatal_error(ppp_pcb *pcb) -{ - LWIP_UNUSED_ARG(pcb); - return 1; -} -#endif /* unused */ -#endif /* CCP_SUPPORT */ - -#if PPP_IDLETIMELIMIT -/******************************************************************** - * - * get_idle_time - return how long the link has been idle. - */ -int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { - /* FIXME: add idle time support and make it optional */ - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(ip); - return 1; -} -#endif /* PPP_IDLETIMELIMIT */ - -#if DEMAND_SUPPORT -/******************************************************************** - * - * get_loop_output - get outgoing packets from the ppp device, - * and detect when we want to bring the real link up. - * Return value is 1 if we need to bring up the link, 0 otherwise. - */ -int get_loop_output(void) { - return 0; -} -#endif /* DEMAND_SUPPORT */ - -#if PPP_PROTOCOLNAME -/* List of protocol names, to make our messages a little more informative. */ -struct protocol_list { - u_short proto; - const char *name; -} const protocol_list[] = { - { 0x21, "IP" }, - { 0x23, "OSI Network Layer" }, - { 0x25, "Xerox NS IDP" }, - { 0x27, "DECnet Phase IV" }, - { 0x29, "Appletalk" }, - { 0x2b, "Novell IPX" }, - { 0x2d, "VJ compressed TCP/IP" }, - { 0x2f, "VJ uncompressed TCP/IP" }, - { 0x31, "Bridging PDU" }, - { 0x33, "Stream Protocol ST-II" }, - { 0x35, "Banyan Vines" }, - { 0x39, "AppleTalk EDDP" }, - { 0x3b, "AppleTalk SmartBuffered" }, - { 0x3d, "Multi-Link" }, - { 0x3f, "NETBIOS Framing" }, - { 0x41, "Cisco Systems" }, - { 0x43, "Ascom Timeplex" }, - { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, - { 0x47, "DCA Remote Lan" }, - { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, - { 0x4b, "SNA over 802.2" }, - { 0x4d, "SNA" }, - { 0x4f, "IP6 Header Compression" }, - { 0x51, "KNX Bridging Data" }, - { 0x53, "Encryption" }, - { 0x55, "Individual Link Encryption" }, - { 0x57, "IPv6" }, - { 0x59, "PPP Muxing" }, - { 0x5b, "Vendor-Specific Network Protocol" }, - { 0x61, "RTP IPHC Full Header" }, - { 0x63, "RTP IPHC Compressed TCP" }, - { 0x65, "RTP IPHC Compressed non-TCP" }, - { 0x67, "RTP IPHC Compressed UDP 8" }, - { 0x69, "RTP IPHC Compressed RTP 8" }, - { 0x6f, "Stampede Bridging" }, - { 0x73, "MP+" }, - { 0xc1, "NTCITS IPI" }, - { 0xfb, "single-link compression" }, - { 0xfd, "Compressed Datagram" }, - { 0x0201, "802.1d Hello Packets" }, - { 0x0203, "IBM Source Routing BPDU" }, - { 0x0205, "DEC LANBridge100 Spanning Tree" }, - { 0x0207, "Cisco Discovery Protocol" }, - { 0x0209, "Netcs Twin Routing" }, - { 0x020b, "STP - Scheduled Transfer Protocol" }, - { 0x020d, "EDP - Extreme Discovery Protocol" }, - { 0x0211, "Optical Supervisory Channel Protocol" }, - { 0x0213, "Optical Supervisory Channel Protocol" }, - { 0x0231, "Luxcom" }, - { 0x0233, "Sigma Network Systems" }, - { 0x0235, "Apple Client Server Protocol" }, - { 0x0281, "MPLS Unicast" }, - { 0x0283, "MPLS Multicast" }, - { 0x0285, "IEEE p1284.4 standard - data packets" }, - { 0x0287, "ETSI TETRA Network Protocol Type 1" }, - { 0x0289, "Multichannel Flow Treatment Protocol" }, - { 0x2063, "RTP IPHC Compressed TCP No Delta" }, - { 0x2065, "RTP IPHC Context State" }, - { 0x2067, "RTP IPHC Compressed UDP 16" }, - { 0x2069, "RTP IPHC Compressed RTP 16" }, - { 0x4001, "Cray Communications Control Protocol" }, - { 0x4003, "CDPD Mobile Network Registration Protocol" }, - { 0x4005, "Expand accelerator protocol" }, - { 0x4007, "ODSICP NCP" }, - { 0x4009, "DOCSIS DLL" }, - { 0x400B, "Cetacean Network Detection Protocol" }, - { 0x4021, "Stacker LZS" }, - { 0x4023, "RefTek Protocol" }, - { 0x4025, "Fibre Channel" }, - { 0x4027, "EMIT Protocols" }, - { 0x405b, "Vendor-Specific Protocol (VSP)" }, - { 0x8021, "Internet Protocol Control Protocol" }, - { 0x8023, "OSI Network Layer Control Protocol" }, - { 0x8025, "Xerox NS IDP Control Protocol" }, - { 0x8027, "DECnet Phase IV Control Protocol" }, - { 0x8029, "Appletalk Control Protocol" }, - { 0x802b, "Novell IPX Control Protocol" }, - { 0x8031, "Bridging NCP" }, - { 0x8033, "Stream Protocol Control Protocol" }, - { 0x8035, "Banyan Vines Control Protocol" }, - { 0x803d, "Multi-Link Control Protocol" }, - { 0x803f, "NETBIOS Framing Control Protocol" }, - { 0x8041, "Cisco Systems Control Protocol" }, - { 0x8043, "Ascom Timeplex" }, - { 0x8045, "Fujitsu LBLB Control Protocol" }, - { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, - { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, - { 0x804b, "SNA over 802.2 Control Protocol" }, - { 0x804d, "SNA Control Protocol" }, - { 0x804f, "IP6 Header Compression Control Protocol" }, - { 0x8051, "KNX Bridging Control Protocol" }, - { 0x8053, "Encryption Control Protocol" }, - { 0x8055, "Individual Link Encryption Control Protocol" }, - { 0x8057, "IPv6 Control Protocol" }, - { 0x8059, "PPP Muxing Control Protocol" }, - { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, - { 0x806f, "Stampede Bridging Control Protocol" }, - { 0x8073, "MP+ Control Protocol" }, - { 0x80c1, "NTCITS IPI Control Protocol" }, - { 0x80fb, "Single Link Compression Control Protocol" }, - { 0x80fd, "Compression Control Protocol" }, - { 0x8207, "Cisco Discovery Protocol Control" }, - { 0x8209, "Netcs Twin Routing" }, - { 0x820b, "STP - Control Protocol" }, - { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, - { 0x8235, "Apple Client Server Protocol Control" }, - { 0x8281, "MPLSCP" }, - { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, - { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, - { 0x8289, "Multichannel Flow Treatment Protocol" }, - { 0xc021, "Link Control Protocol" }, - { 0xc023, "Password Authentication Protocol" }, - { 0xc025, "Link Quality Report" }, - { 0xc027, "Shiva Password Authentication Protocol" }, - { 0xc029, "CallBack Control Protocol (CBCP)" }, - { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, - { 0xc02d, "BAP" }, - { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, - { 0xc081, "Container Control Protocol" }, - { 0xc223, "Challenge Handshake Authentication Protocol" }, - { 0xc225, "RSA Authentication Protocol" }, - { 0xc227, "Extensible Authentication Protocol" }, - { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, - { 0xc26f, "Stampede Bridging Authorization Protocol" }, - { 0xc281, "Proprietary Authentication Protocol" }, - { 0xc283, "Proprietary Authentication Protocol" }, - { 0xc481, "Proprietary Node ID Authentication Protocol" }, - { 0, NULL }, -}; - -/* - * protocol_name - find a name for a PPP protocol. - */ -const char * protocol_name(int proto) { - const struct protocol_list *lp; - - for (lp = protocol_list; lp->proto != 0; ++lp) { - if (proto == lp->proto) { - return lp->name; - } - } - return NULL; -} -#endif /* PPP_PROTOCOLNAME */ - -#if PPP_STATS_SUPPORT - -/* ---- Note on PPP Stats support ---- - * - * The one willing link stats support should add the get_ppp_stats() - * to fetch statistics from lwIP. - */ - -/* - * reset_link_stats - "reset" stats when link goes up. - */ -void reset_link_stats(int u) { - if (!get_ppp_stats(u, &old_link_stats)) { - return; - } - gettimeofday(&start_time, NULL); -} - -/* - * update_link_stats - get stats at link termination. - */ -void update_link_stats(int u) { - struct timeval now; - char numbuf[32]; - - if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) { - return; - } - link_connect_time = now.tv_sec - start_time.tv_sec; - link_stats_valid = 1; - - link_stats.bytes_in -= old_link_stats.bytes_in; - link_stats.bytes_out -= old_link_stats.bytes_out; - link_stats.pkts_in -= old_link_stats.pkts_in; - link_stats.pkts_out -= old_link_stats.pkts_out; -} - -void print_link_stats() { - /* - * Print connect time and statistics. - */ - if (link_stats_valid) { - int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ - info("Connect time %d.%d minutes.", t/10, t%10); - info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); - link_stats_valid = 0; - } -} -#endif /* PPP_STATS_SUPPORT */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/pppapi.c b/components/net/lwip-2.0.2/src/netif/ppp/pppapi.c deleted file mode 100644 index 947f7ba8c1..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/pppapi.c +++ /dev/null @@ -1,427 +0,0 @@ -/** - * @file - * Point To Point Protocol Sequential API module - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" - -#if LWIP_PPP_API /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/pppapi.h" -#include "lwip/priv/tcpip_priv.h" -#include "netif/ppp/pppoe.h" -#include "netif/ppp/pppol2tp.h" -#include "netif/ppp/pppos.h" - -#if LWIP_MPU_COMPATIBLE -LWIP_MEMPOOL_DECLARE(PPPAPI_MSG, MEMP_NUM_PPP_API_MSG, sizeof(struct pppapi_msg), "PPPAPI_MSG") -#endif - -#define PPPAPI_VAR_REF(name) API_VAR_REF(name) -#define PPPAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct pppapi_msg, name) -#define PPPAPI_VAR_ALLOC(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, ERR_MEM) -#define PPPAPI_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, NULL) -#define PPPAPI_VAR_FREE(name) API_VAR_FREE_POOL(PPPAPI_MSG, name) - -/** - * Call ppp_set_default() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_set_default(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - ppp_set_default(msg->msg.ppp); - return ERR_OK; -} - -/** - * Call ppp_set_default() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_set_default(ppp_pcb *pcb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - err = tcpip_api_call(pppapi_do_ppp_set_default, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -#if PPP_NOTIFY_PHASE -/** - * Call ppp_set_notify_phase_callback() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_set_notify_phase_callback(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - ppp_set_notify_phase_callback(msg->msg.ppp, msg->msg.msg.setnotifyphasecb.notify_phase_cb); - return ERR_OK; -} - -/** - * Call ppp_set_notify_phase_callback() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.setnotifyphasecb.notify_phase_cb = notify_phase_cb; - err = tcpip_api_call(pppapi_do_ppp_set_notify_phase_callback, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} -#endif /* PPP_NOTIFY_PHASE */ - - -#if PPPOS_SUPPORT -/** - * Call pppos_create() inside the tcpip_thread context. - */ -static err_t -pppapi_do_pppos_create(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - msg->msg.ppp = pppos_create(msg->msg.msg.serialcreate.pppif, msg->msg.msg.serialcreate.output_cb, - msg->msg.msg.serialcreate.link_status_cb, msg->msg.msg.serialcreate.ctx_cb); - return ERR_OK; -} - -/** - * Call pppos_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - ppp_pcb* result; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC_RETURN_NULL(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = NULL; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.pppif = pppif; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.output_cb = output_cb; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.link_status_cb = link_status_cb; - PPPAPI_VAR_REF(msg).msg.msg.serialcreate.ctx_cb = ctx_cb; - tcpip_api_call(pppapi_do_pppos_create, &PPPAPI_VAR_REF(msg).call); - result = PPPAPI_VAR_REF(msg).msg.ppp; - PPPAPI_VAR_FREE(msg); - return result; -} -#endif /* PPPOS_SUPPORT */ - - -#if PPPOE_SUPPORT -/** - * Call pppoe_create() inside the tcpip_thread context. - */ -static err_t -pppapi_do_pppoe_create(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - msg->msg.ppp = pppoe_create(msg->msg.msg.ethernetcreate.pppif, msg->msg.msg.ethernetcreate.ethif, - msg->msg.msg.ethernetcreate.service_name, msg->msg.msg.ethernetcreate.concentrator_name, - msg->msg.msg.ethernetcreate.link_status_cb, msg->msg.msg.ethernetcreate.ctx_cb); - return ERR_OK; -} - -/** - * Call pppoe_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppoe_create(struct netif *pppif, struct netif *ethif, const char *service_name, - const char *concentrator_name, ppp_link_status_cb_fn link_status_cb, - void *ctx_cb) -{ - ppp_pcb* result; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC_RETURN_NULL(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = NULL; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.pppif = pppif; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ethif = ethif; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.service_name = service_name; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.concentrator_name = concentrator_name; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.link_status_cb = link_status_cb; - PPPAPI_VAR_REF(msg).msg.msg.ethernetcreate.ctx_cb = ctx_cb; - tcpip_api_call(pppapi_do_pppoe_create, &PPPAPI_VAR_REF(msg).call); - result = PPPAPI_VAR_REF(msg).msg.ppp; - PPPAPI_VAR_FREE(msg); - return result; -} -#endif /* PPPOE_SUPPORT */ - - -#if PPPOL2TP_SUPPORT -/** - * Call pppol2tp_create() inside the tcpip_thread context. - */ -static err_t -pppapi_do_pppol2tp_create(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - msg->msg.ppp = pppol2tp_create(msg->msg.msg.l2tpcreate.pppif, - msg->msg.msg.l2tpcreate.netif, API_EXPR_REF(msg->msg.msg.l2tpcreate.ipaddr), msg->msg.msg.l2tpcreate.port, -#if PPPOL2TP_AUTH_SUPPORT - msg->msg.msg.l2tpcreate.secret, - msg->msg.msg.l2tpcreate.secret_len, -#else /* PPPOL2TP_AUTH_SUPPORT */ - NULL, - 0, -#endif /* PPPOL2TP_AUTH_SUPPORT */ - msg->msg.msg.l2tpcreate.link_status_cb, msg->msg.msg.l2tpcreate.ctx_cb); - return ERR_OK; -} - -/** - * Call pppol2tp_create() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -ppp_pcb* -pppapi_pppol2tp_create(struct netif *pppif, struct netif *netif, ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - ppp_pcb* result; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC_RETURN_NULL(msg); -#if !PPPOL2TP_AUTH_SUPPORT - LWIP_UNUSED_ARG(secret); - LWIP_UNUSED_ARG(secret_len); -#endif /* !PPPOL2TP_AUTH_SUPPORT */ - - PPPAPI_VAR_REF(msg).msg.ppp = NULL; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.pppif = pppif; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.netif = netif; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ipaddr = PPPAPI_VAR_REF(ipaddr); - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.port = port; -#if PPPOL2TP_AUTH_SUPPORT - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret = secret; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.secret_len = secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.link_status_cb = link_status_cb; - PPPAPI_VAR_REF(msg).msg.msg.l2tpcreate.ctx_cb = ctx_cb; - tcpip_api_call(pppapi_do_pppol2tp_create, &PPPAPI_VAR_REF(msg).call); - result = PPPAPI_VAR_REF(msg).msg.ppp; - PPPAPI_VAR_FREE(msg); - return result; -} -#endif /* PPPOL2TP_SUPPORT */ - - -/** - * Call ppp_connect() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_connect(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_connect(msg->msg.ppp, msg->msg.msg.connect.holdoff); -} - -/** - * Call ppp_connect() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_connect(ppp_pcb *pcb, u16_t holdoff) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.connect.holdoff = holdoff; - err = tcpip_api_call(pppapi_do_ppp_connect, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -#if PPP_SERVER -/** - * Call ppp_listen() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_listen(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_listen(msg->msg.ppp); -} - -/** - * Call ppp_listen() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_listen(ppp_pcb *pcb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - err = tcpip_api_call(pppapi_do_ppp_listen, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} -#endif /* PPP_SERVER */ - - -/** - * Call ppp_close() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_close(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_close(msg->msg.ppp, msg->msg.msg.close.nocarrier); -} - -/** - * Call ppp_close() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_close(ppp_pcb *pcb, u8_t nocarrier) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.close.nocarrier = nocarrier; - err = tcpip_api_call(pppapi_do_ppp_close, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -/** - * Call ppp_free() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_free(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_free(msg->msg.ppp); -} - -/** - * Call ppp_free() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_free(ppp_pcb *pcb) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - err = tcpip_api_call(pppapi_do_ppp_free, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - - -/** - * Call ppp_ioctl() inside the tcpip_thread context. - */ -static err_t -pppapi_do_ppp_ioctl(struct tcpip_api_call_data *m) -{ - /* cast through void* to silence alignment warnings. - * We know it works because the structs have been instantiated as struct pppapi_msg */ - struct pppapi_msg *msg = (struct pppapi_msg *)(void*)m; - - return ppp_ioctl(msg->msg.ppp, msg->msg.msg.ioctl.cmd, msg->msg.msg.ioctl.arg); -} - -/** - * Call ppp_ioctl() in a thread-safe way by running that function inside the - * tcpip_thread context. - */ -err_t -pppapi_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) -{ - err_t err; - PPPAPI_VAR_DECLARE(msg); - PPPAPI_VAR_ALLOC(msg); - - PPPAPI_VAR_REF(msg).msg.ppp = pcb; - PPPAPI_VAR_REF(msg).msg.msg.ioctl.cmd = cmd; - PPPAPI_VAR_REF(msg).msg.msg.ioctl.arg = arg; - err = tcpip_api_call(pppapi_do_ppp_ioctl, &PPPAPI_VAR_REF(msg).call); - PPPAPI_VAR_FREE(msg); - return err; -} - -#endif /* LWIP_PPP_API */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/pppcrypt.c b/components/net/lwip-2.0.2/src/netif/ppp/pppcrypt.c deleted file mode 100644 index 82d78c13ac..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/pppcrypt.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * pppcrypt.c - PPP/DES linkage for MS-CHAP and EAP SRP-SHA1 - * - * Extracted from chap_ms.c by James Carlson. - * - * Copyright (c) 1995 Eric Rosenquist. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && MSCHAP_SUPPORT /* don't build if not necessary */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/pppcrypt.h" - - -static u_char pppcrypt_get_7bits(u_char *input, int startBit) { - unsigned int word; - - word = (unsigned)input[startBit / 8] << 8; - word |= (unsigned)input[startBit / 8 + 1]; - - word >>= 15 - (startBit % 8 + 7); - - return word & 0xFE; -} - -/* IN 56 bit DES key missing parity bits - * OUT 64 bit DES key with parity bits added - */ -void pppcrypt_56_to_64_bit_key(u_char *key, u_char * des_key) { - des_key[0] = pppcrypt_get_7bits(key, 0); - des_key[1] = pppcrypt_get_7bits(key, 7); - des_key[2] = pppcrypt_get_7bits(key, 14); - des_key[3] = pppcrypt_get_7bits(key, 21); - des_key[4] = pppcrypt_get_7bits(key, 28); - des_key[5] = pppcrypt_get_7bits(key, 35); - des_key[6] = pppcrypt_get_7bits(key, 42); - des_key[7] = pppcrypt_get_7bits(key, 49); -} - -#endif /* PPP_SUPPORT && MSCHAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/pppoe.c b/components/net/lwip-2.0.2/src/netif/ppp/pppoe.c deleted file mode 100644 index eabfa4d041..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/pppoe.c +++ /dev/null @@ -1,1191 +0,0 @@ -/***************************************************************************** -* pppoe.c - PPP Over Ethernet implementation for lwIP. -* -* Copyright (c) 2006 by Marc Boucher, Services Informatiques (MBSI) inc. -* -* The authors hereby grant permission to use, copy, modify, distribute, -* and license this software and its documentation for any purpose, provided -* that existing copyright notices are retained in all copies and that this -* notice and the following disclaimer are included verbatim in any -* distributions. No written agreement, license, or royalty fee is required -* for any of the authorized uses. -* -* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -****************************************************************************** -* REVISION HISTORY -* -* 06-01-01 Marc Boucher -* Ported to lwIP. -*****************************************************************************/ - - - -/* based on NetBSD: if_pppoe.c,v 1.64 2006/01/31 23:50:15 martin Exp */ - -/*- - * Copyright (c) 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Martin Husemann . - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "lwip/timeouts.h" -#include "lwip/memp.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" - -#include "netif/ethernet.h" -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/pppoe.h" - -/* Memory pool */ -LWIP_MEMPOOL_DECLARE(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") - -/* Add a 16 bit unsigned value to a buffer pointed to by PTR */ -#define PPPOE_ADD_16(PTR, VAL) \ - *(PTR)++ = (u8_t)((VAL) / 256); \ - *(PTR)++ = (u8_t)((VAL) % 256) - -/* Add a complete PPPoE header to the buffer pointed to by PTR */ -#define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ - *(PTR)++ = PPPOE_VERTYPE; \ - *(PTR)++ = (CODE); \ - PPPOE_ADD_16(PTR, SESS); \ - PPPOE_ADD_16(PTR, LEN) - -#define PPPOE_DISC_TIMEOUT (5*1000) /* base for quick timeout calculation */ -#define PPPOE_SLOW_RETRY (60*1000) /* persistent retry interval */ -#define PPPOE_DISC_MAXPADI 4 /* retry PADI four times (quickly) */ -#define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ - -#ifdef PPPOE_SERVER -#error "PPPOE_SERVER is not yet supported under lwIP!" -/* from if_spppsubr.c */ -#define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ -#endif - -#define PPPOE_ERRORSTRING_LEN 64 - - -/* callbacks called from PPP core */ -static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); -static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); -static void pppoe_connect(ppp_pcb *ppp, void *ctx); -static void pppoe_disconnect(ppp_pcb *ppp, void *ctx); -static err_t pppoe_destroy(ppp_pcb *ppp, void *ctx); - -/* management routines */ -static void pppoe_abort_connect(struct pppoe_softc *); -#if 0 /* UNUSED */ -static void pppoe_clear_softc(struct pppoe_softc *, const char *); -#endif /* UNUSED */ - -/* internal timeout handling */ -static void pppoe_timeout(void *); - -/* sending actual protocol controll packets */ -static err_t pppoe_send_padi(struct pppoe_softc *); -static err_t pppoe_send_padr(struct pppoe_softc *); -#ifdef PPPOE_SERVER -static err_t pppoe_send_pado(struct pppoe_softc *); -static err_t pppoe_send_pads(struct pppoe_softc *); -#endif -static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); - -/* internal helper functions */ -static err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb); -static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif); -static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif); - -/** linked list of created pppoe interfaces */ -static struct pppoe_softc *pppoe_softc_list; - -/* Callbacks structure for PPP core */ -static const struct link_callbacks pppoe_callbacks = { - pppoe_connect, -#if PPP_SERVER - NULL, -#endif /* PPP_SERVER */ - pppoe_disconnect, - pppoe_destroy, - pppoe_write, - pppoe_netif_output, - NULL, - NULL -}; - -/* - * Create a new PPP Over Ethernet (PPPoE) connection. - * - * Return 0 on success, an error code on failure. - */ -ppp_pcb *pppoe_create(struct netif *pppif, - struct netif *ethif, - const char *service_name, const char *concentrator_name, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - ppp_pcb *ppp; - struct pppoe_softc *sc; - LWIP_UNUSED_ARG(service_name); - LWIP_UNUSED_ARG(concentrator_name); - - sc = (struct pppoe_softc *)LWIP_MEMPOOL_ALLOC(PPPOE_IF); - if (sc == NULL) { - return NULL; - } - - ppp = ppp_new(pppif, &pppoe_callbacks, sc, link_status_cb, ctx_cb); - if (ppp == NULL) { - LWIP_MEMPOOL_FREE(PPPOE_IF, sc); - return NULL; - } - - memset(sc, 0, sizeof(struct pppoe_softc)); - sc->pcb = ppp; - sc->sc_ethif = ethif; - /* put the new interface at the head of the list */ - sc->next = pppoe_softc_list; - pppoe_softc_list = sc; - return ppp; -} - -/* Called by PPP core */ -static err_t pppoe_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - struct pbuf *ph; /* Ethernet + PPPoE header */ - err_t ret; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - /* skip address & flags */ - pbuf_header(p, -(s16_t)2); - - ph = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); - if(!ph) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(p); - return ERR_MEM; - } - - pbuf_header(ph, -(s16_t)PPPOE_HEADERLEN); /* hide PPPoE header */ - pbuf_cat(ph, p); -#if MIB2_STATS - tot_len = ph->tot_len; -#endif /* MIB2_STATS */ - - ret = pppoe_xmit(sc, ph); - if (ret != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ret; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -/* Called by PPP core */ -static err_t pppoe_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - struct pbuf *pb; - u8_t *pl; - err_t err; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - /* @todo: try to use pbuf_header() here! */ - pb = pbuf_alloc(PBUF_LINK, PPPOE_HEADERLEN + sizeof(protocol), PBUF_RAM); - if(!pb) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ERR_MEM; - } - - pbuf_header(pb, -(s16_t)PPPOE_HEADERLEN); - - pl = (u8_t*)pb->payload; - PUTSHORT(protocol, pl); - - pbuf_chain(pb, p); -#if MIB2_STATS - tot_len = pb->tot_len; -#endif /* MIB2_STATS */ - - if( (err = pppoe_xmit(sc, pb)) != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return err; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -static err_t -pppoe_destroy(ppp_pcb *ppp, void *ctx) -{ - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - struct pppoe_softc **copp, *freep; - LWIP_UNUSED_ARG(ppp); - - sys_untimeout(pppoe_timeout, sc); - - /* remove interface from list */ - for (copp = &pppoe_softc_list; (freep = *copp); copp = &freep->next) { - if (freep == sc) { - *copp = freep->next; - break; - } - } - -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name) { - mem_free(sc->sc_concentrator_name); - } - if (sc->sc_service_name) { - mem_free(sc->sc_service_name); - } -#endif /* PPPOE_TODO */ - LWIP_MEMPOOL_FREE(PPPOE_IF, sc); - - return ERR_OK; -} - -/* - * Find the interface handling the specified session. - * Note: O(number of sessions open), this is a client-side only, mean - * and lean implementation, so number of open sessions typically should - * be 1. - */ -static struct pppoe_softc* pppoe_find_softc_by_session(u_int session, struct netif *rcvif) { - struct pppoe_softc *sc; - - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { - if (sc->sc_state == PPPOE_STATE_SESSION - && sc->sc_session == session - && sc->sc_ethif == rcvif) { - return sc; - } - } - return NULL; -} - -/* Check host unique token passed and return appropriate softc pointer, - * or NULL if token is bogus. */ -static struct pppoe_softc* pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { - struct pppoe_softc *sc, *t; - - if (len != sizeof sc) { - return NULL; - } - MEMCPY(&t, token, len); - - for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { - if (sc == t) { - break; - } - } - - if (sc == NULL) { - PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); - return NULL; - } - - /* should be safe to access *sc now */ - if (sc->sc_state < PPPOE_STATE_PADI_SENT || sc->sc_state >= PPPOE_STATE_SESSION) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": host unique tag found, but it belongs to a connection in state %d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_state)); - return NULL; - } - if (sc->sc_ethif != rcvif) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": wrong interface, not accepting host unique\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - return NULL; - } - return sc; -} - -/* analyze and handle a single received packet while not in session state */ -void -pppoe_disc_input(struct netif *netif, struct pbuf *pb) -{ - u16_t tag, len; - u16_t session, plen; - struct pppoe_softc *sc; -#if PPP_DEBUG - const char *err_msg = NULL; -#endif /* PPP_DEBUG */ - u8_t *ac_cookie; - u16_t ac_cookie_len; -#ifdef PPPOE_SERVER - u8_t *hunique; - size_t hunique_len; -#endif - struct pppoehdr *ph; - struct pppoetag pt; - int off, err; - struct eth_hdr *ethhdr; - - /* don't do anything if there is not a single PPPoE instance */ - if (pppoe_softc_list == NULL) { - pbuf_free(pb); - return; - } - - pb = ppp_singlebuf(pb); - - if (pb->len < sizeof(*ethhdr)) { - goto done; - } - ethhdr = (struct eth_hdr *)pb->payload; - off = sizeof(*ethhdr); - - ac_cookie = NULL; - ac_cookie_len = 0; -#ifdef PPPOE_SERVER - hunique = NULL; - hunique_len = 0; -#endif - session = 0; - if (pb->len - off < (u16_t)PPPOE_HEADERLEN) { - PPPDEBUG(LOG_DEBUG, ("pppoe: packet too short: %d\n", pb->len)); - goto done; - } - - ph = (struct pppoehdr *) (ethhdr + 1); - if (ph->vertype != PPPOE_VERTYPE) { - PPPDEBUG(LOG_DEBUG, ("pppoe: unknown version/type packet: 0x%x\n", ph->vertype)); - goto done; - } - session = lwip_ntohs(ph->session); - plen = lwip_ntohs(ph->plen); - off += sizeof(*ph); - - if (plen + off > pb->len) { - PPPDEBUG(LOG_DEBUG, ("pppoe: packet content does not fit: data available = %d, packet size = %u\n", - pb->len - off, plen)); - goto done; - } - if(pb->tot_len == pb->len) { - pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ - } - tag = 0; - len = 0; - sc = NULL; - while (off + sizeof(pt) <= pb->len) { - MEMCPY(&pt, (u8_t*)pb->payload + off, sizeof(pt)); - tag = lwip_ntohs(pt.tag); - len = lwip_ntohs(pt.len); - if (off + sizeof(pt) + len > pb->len) { - PPPDEBUG(LOG_DEBUG, ("pppoe: tag 0x%x len 0x%x is too long\n", tag, len)); - goto done; - } - switch (tag) { - case PPPOE_TAG_EOL: - goto breakbreak; - case PPPOE_TAG_SNAME: - break; /* ignored */ - case PPPOE_TAG_ACNAME: - break; /* ignored */ - case PPPOE_TAG_HUNIQUE: - if (sc != NULL) { - break; - } -#ifdef PPPOE_SERVER - hunique = (u8_t*)pb->payload + off + sizeof(pt); - hunique_len = len; -#endif - sc = pppoe_find_softc_by_hunique((u8_t*)pb->payload + off + sizeof(pt), len, netif); - break; - case PPPOE_TAG_ACCOOKIE: - if (ac_cookie == NULL) { - if (len > PPPOE_MAX_AC_COOKIE_LEN) { - PPPDEBUG(LOG_DEBUG, ("pppoe: AC cookie is too long: len = %d, max = %d\n", len, PPPOE_MAX_AC_COOKIE_LEN)); - goto done; - } - ac_cookie = (u8_t*)pb->payload + off + sizeof(pt); - ac_cookie_len = len; - } - break; -#if PPP_DEBUG - case PPPOE_TAG_SNAME_ERR: - err_msg = "SERVICE NAME ERROR"; - break; - case PPPOE_TAG_ACSYS_ERR: - err_msg = "AC SYSTEM ERROR"; - break; - case PPPOE_TAG_GENERIC_ERR: - err_msg = "GENERIC ERROR"; - break; -#endif /* PPP_DEBUG */ - default: - break; - } -#if PPP_DEBUG - if (err_msg != NULL) { - char error_tmp[PPPOE_ERRORSTRING_LEN]; - u16_t error_len = LWIP_MIN(len, sizeof(error_tmp)-1); - strncpy(error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); - error_tmp[error_len] = '\0'; - if (sc) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": %s: %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err_msg, error_tmp)); - } else { - PPPDEBUG(LOG_DEBUG, ("pppoe: %s: %s\n", err_msg, error_tmp)); - } - } -#endif /* PPP_DEBUG */ - off += sizeof(pt) + len; - } - -breakbreak:; - switch (ph->code) { - case PPPOE_CODE_PADI: -#ifdef PPPOE_SERVER - /* - * got service name, concentrator name, and/or host unique. - * ignore if we have no interfaces with IFF_PASSIVE|IFF_UP. - */ - if (LIST_EMPTY(&pppoe_softc_list)) { - goto done; - } - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { - if (!(sc->sc_sppp.pp_if.if_flags & IFF_UP)) { - continue; - } - if (!(sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { - continue; - } - if (sc->sc_state == PPPOE_STATE_INITIAL) { - break; - } - } - if (sc == NULL) { - /* PPPDEBUG(LOG_DEBUG, ("pppoe: free passive interface is not found\n")); */ - goto done; - } - if (hunique) { - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - } - sc->sc_hunique = mem_malloc(hunique_len); - if (sc->sc_hunique == NULL) { - goto done; - } - sc->sc_hunique_len = hunique_len; - MEMCPY(sc->sc_hunique, hunique, hunique_len); - } - MEMCPY(&sc->sc_dest, eh->ether_shost, sizeof sc->sc_dest); - sc->sc_state = PPPOE_STATE_PADO_SENT; - pppoe_send_pado(sc); - break; -#endif /* PPPOE_SERVER */ - case PPPOE_CODE_PADR: -#ifdef PPPOE_SERVER - /* - * get sc from ac_cookie if IFF_PASSIVE - */ - if (ac_cookie == NULL) { - /* be quiet if there is not a single pppoe instance */ - PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but not includes ac_cookie\n")); - goto done; - } - sc = pppoe_find_softc_by_hunique(ac_cookie, ac_cookie_len, netif); - if (sc == NULL) { - /* be quiet if there is not a single pppoe instance */ - if (!LIST_EMPTY(&pppoe_softc_list)) { - PPPDEBUG(LOG_DEBUG, ("pppoe: received PADR but could not find request for it\n")); - } - goto done; - } - if (sc->sc_state != PPPOE_STATE_PADO_SENT) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADR\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - goto done; - } - if (hunique) { - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - } - sc->sc_hunique = mem_malloc(hunique_len); - if (sc->sc_hunique == NULL) { - goto done; - } - sc->sc_hunique_len = hunique_len; - MEMCPY(sc->sc_hunique, hunique, hunique_len); - } - pppoe_send_pads(sc); - sc->sc_state = PPPOE_STATE_SESSION; - ppp_start(sc->pcb); /* notify upper layers */ - break; -#else - /* ignore, we are no access concentrator */ - goto done; -#endif /* PPPOE_SERVER */ - case PPPOE_CODE_PADO: - if (sc == NULL) { - /* be quiet if there is not a single pppoe instance */ - if (pppoe_softc_list != NULL) { - PPPDEBUG(LOG_DEBUG, ("pppoe: received PADO but could not find request for it\n")); - } - goto done; - } - if (sc->sc_state != PPPOE_STATE_PADI_SENT) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": received unexpected PADO\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - goto done; - } - if (ac_cookie) { - sc->sc_ac_cookie_len = ac_cookie_len; - MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); - } - MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); - sys_untimeout(pppoe_timeout, sc); - sc->sc_padr_retried = 0; - sc->sc_state = PPPOE_STATE_PADR_SENT; - if ((err = pppoe_send_padr(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); - break; - case PPPOE_CODE_PADS: - if (sc == NULL) { - goto done; - } - sc->sc_session = session; - sys_untimeout(pppoe_timeout, sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); - sc->sc_state = PPPOE_STATE_SESSION; - ppp_start(sc->pcb); /* notify upper layers */ - break; - case PPPOE_CODE_PADT: - /* Don't disconnect here, we let the LCP Echo/Reply find the fact - * that PPP session is down. Asking the PPP stack to end the session - * require strict checking about the PPP phase to prevent endless - * disconnection loops. - */ -#if 0 /* UNUSED */ - if (sc == NULL) { /* PADT frames are rarely sent with a hunique tag, this is actually almost always true */ - goto done; - } - pppoe_clear_softc(sc, "received PADT"); -#endif /* UNUSED */ - break; - default: - if(sc) { - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - (u16_t)ph->code, session)); - } else { - PPPDEBUG(LOG_DEBUG, ("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session)); - } - break; - } - -done: - pbuf_free(pb); - return; -} - -void -pppoe_data_input(struct netif *netif, struct pbuf *pb) -{ - u16_t session, plen; - struct pppoe_softc *sc; - struct pppoehdr *ph; -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - u8_t shost[ETHER_ADDR_LEN]; -#endif - -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - MEMCPY(shost, ((struct eth_hdr *)pb->payload)->src.addr, sizeof(shost)); -#endif - if (pbuf_header(pb, -(s16_t)sizeof(struct eth_hdr)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); - LINK_STATS_INC(link.lenerr); - goto drop; - } - - if (pb->len < sizeof(*ph)) { - PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: could not get PPPoE header\n")); - goto drop; - } - ph = (struct pppoehdr *)pb->payload; - - if (ph->vertype != PPPOE_VERTYPE) { - PPPDEBUG(LOG_DEBUG, ("pppoe (data): unknown version/type packet: 0x%x\n", ph->vertype)); - goto drop; - } - if (ph->code != 0) { - goto drop; - } - - session = lwip_ntohs(ph->session); - sc = pppoe_find_softc_by_session(session, netif); - if (sc == NULL) { -#ifdef PPPOE_TERM_UNKNOWN_SESSIONS - PPPDEBUG(LOG_DEBUG, ("pppoe: input for unknown session 0x%x, sending PADT\n", session)); - pppoe_send_padt(netif, session, shost); -#endif - goto drop; - } - - plen = lwip_ntohs(ph->plen); - - if (pbuf_header(pb, -(s16_t)(PPPOE_HEADERLEN)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); - LINK_STATS_INC(link.lenerr); - goto drop; - } - - PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - pb->len, plen)); - - if (pb->tot_len < plen) { - goto drop; - } - - /* Dispatch the packet thereby consuming it. */ - ppp_input(sc->pcb, pb); - return; - -drop: - pbuf_free(pb); -} - -static err_t -pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) -{ - struct eth_hdr *ethhdr; - u16_t etype; - err_t res; - - /* make room for Ethernet header - should not fail */ - if (pbuf_header(pb, (s16_t)(sizeof(struct eth_hdr))) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_output: could not allocate room for Ethernet header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - ethhdr = (struct eth_hdr *)pb->payload; - etype = sc->sc_state == PPPOE_STATE_SESSION ? ETHTYPE_PPPOE : ETHTYPE_PPPOEDISC; - ethhdr->type = lwip_htons(etype); - MEMCPY(ðhdr->dest.addr, &sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); - MEMCPY(ðhdr->src.addr, &sc->sc_ethif->hwaddr, sizeof(ethhdr->src.addr)); - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, - sc->sc_state, sc->sc_session, - sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], - pb->tot_len)); - - res = sc->sc_ethif->linkoutput(sc->sc_ethif, pb); - - pbuf_free(pb); - - return res; -} - -static err_t -pppoe_send_padi(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - int len; -#ifdef PPPOE_TODO - int l1 = 0, l2 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ - - /* calculate length of frame (excluding ethernet header + pppoe header) */ - len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - l1 = (int)strlen(sc->sc_service_name); - len += l1; - } - if (sc->sc_concentrator_name != NULL) { - l2 = (int)strlen(sc->sc_concentrator_name); - len += 2 + 2 + l2; - } -#endif /* PPPOE_TODO */ - LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", - sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else -#endif /* PPPOE_TODO */ - { - PPPOE_ADD_16(p, 0); - } -#ifdef PPPOE_TODO - if (sc->sc_concentrator_name != NULL) { - PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); - PPPOE_ADD_16(p, l2); - MEMCPY(p, sc->sc_concentrator_name, l2); - p += l2; - } -#endif /* PPPOE_TODO */ - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof sc); - - /* send pkt */ - return pppoe_output(sc, pb); -} - -static void -pppoe_timeout(void *arg) -{ - u32_t retry_wait; - int err; - struct pppoe_softc *sc = (struct pppoe_softc*)arg; - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - - switch (sc->sc_state) { - case PPPOE_STATE_PADI_SENT: - /* - * We have two basic ways of retrying: - * - Quick retry mode: try a few times in short sequence - * - Slow retry mode: we already had a connection successfully - * established and will try infinitely (without user - * intervention) - * We only enter slow retry mode if IFF_LINK1 (aka autodial) - * is not set. - */ - if (sc->sc_padi_retried < 0xff) { - sc->sc_padi_retried++; - } - if (!sc->pcb->settings.persist && sc->sc_padi_retried >= PPPOE_DISC_MAXPADI) { -#if 0 - if ((sc->sc_sppp.pp_if.if_flags & IFF_LINK1) == 0) { - /* slow retry mode */ - retry_wait = PPPOE_SLOW_RETRY; - } else -#endif - { - pppoe_abort_connect(sc); - return; - } - } - /* initialize for quick retry mode */ - retry_wait = LWIP_MIN(PPPOE_DISC_TIMEOUT * sc->sc_padi_retried, PPPOE_SLOW_RETRY); - if ((err = pppoe_send_padi(sc)) != 0) { - sc->sc_padi_retried--; - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(retry_wait, pppoe_timeout, sc); - break; - - case PPPOE_STATE_PADR_SENT: - sc->sc_padr_retried++; - if (sc->sc_padr_retried >= PPPOE_DISC_MAXPADR) { - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - sc->sc_state = PPPOE_STATE_PADI_SENT; - sc->sc_padr_retried = 0; - if ((err = pppoe_send_padi(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); - return; - } - if ((err = pppoe_send_padr(sc)) != 0) { - sc->sc_padr_retried--; - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); - break; - default: - return; /* all done, work in peace */ - } -} - -/* Start a connection (i.e. initiate discovery phase) */ -static void -pppoe_connect(ppp_pcb *ppp, void *ctx) -{ - err_t err; - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - lcp_options *lcp_wo; - lcp_options *lcp_ao; -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_options *ipcp_wo; - ipcp_options *ipcp_ao; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - sc->sc_session = 0; - sc->sc_ac_cookie_len = 0; - sc->sc_padi_retried = 0; - sc->sc_padr_retried = 0; - /* changed to real address later */ - MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); -#ifdef PPPOE_SERVER - /* wait PADI if IFF_PASSIVE */ - if ((sc->sc_sppp.pp_if.if_flags & IFF_PASSIVE)) { - return 0; - } -#endif - - lcp_wo = &ppp->lcp_wantoptions; - lcp_wo->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ - lcp_wo->neg_asyncmap = 0; - lcp_wo->neg_pcompression = 0; - lcp_wo->neg_accompression = 0; - lcp_wo->passive = 0; - lcp_wo->silent = 0; - - lcp_ao = &ppp->lcp_allowoptions; - lcp_ao->mru = sc->sc_ethif->mtu-PPPOE_HEADERLEN-2; /* two byte PPP protocol discriminator, then IP data */ - lcp_ao->neg_asyncmap = 0; - lcp_ao->neg_pcompression = 0; - lcp_ao->neg_accompression = 0; - -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_wo = &ppp->ipcp_wantoptions; - ipcp_wo->neg_vj = 0; - ipcp_wo->old_vj = 0; - - ipcp_ao = &ppp->ipcp_allowoptions; - ipcp_ao->neg_vj = 0; - ipcp_ao->old_vj = 0; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - /* save state, in case we fail to send PADI */ - sc->sc_state = PPPOE_STATE_PADI_SENT; - if ((err = pppoe_send_padi(sc)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - } - sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); -} - -/* disconnect */ -static void -pppoe_disconnect(ppp_pcb *ppp, void *ctx) -{ - struct pppoe_softc *sc = (struct pppoe_softc *)ctx; - - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - if (sc->sc_state == PPPOE_STATE_SESSION) { - pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); - } - - /* stop any timer, disconnect can be called while initiating is in progress */ - sys_untimeout(pppoe_timeout, sc); - sc->sc_state = PPPOE_STATE_INITIAL; -#ifdef PPPOE_SERVER - if (sc->sc_hunique) { - mem_free(sc->sc_hunique); - sc->sc_hunique = NULL; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ - } - sc->sc_hunique_len = 0; /* probably not necessary, if state is initial we shouldn't have to access hunique anyway */ -#endif - ppp_link_end(ppp); /* notify upper layers */ - return; -} - -/* Connection attempt aborted */ -static void -pppoe_abort_connect(struct pppoe_softc *sc) -{ - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": could not establish connection\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - sc->sc_state = PPPOE_STATE_INITIAL; - ppp_link_failed(sc->pcb); /* notify upper layers */ -} - -/* Send a PADR packet */ -static err_t -pppoe_send_padr(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len; -#ifdef PPPOE_TODO - size_t l1 = 0; /* XXX: gcc */ -#endif /* PPPOE_TODO */ - - len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ - l1 = strlen(sc->sc_service_name); - len += l1; - } -#endif /* PPPOE_TODO */ - if (sc->sc_ac_cookie_len > 0) { - len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ - } - LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", - sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); -#ifdef PPPOE_TODO - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else -#endif /* PPPOE_TODO */ - { - PPPOE_ADD_16(p, 0); - } - if (sc->sc_ac_cookie_len > 0) { - PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); - PPPOE_ADD_16(p, sc->sc_ac_cookie_len); - MEMCPY(p, sc->sc_ac_cookie, sc->sc_ac_cookie_len); - p += sc->sc_ac_cookie_len; - } - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof sc); - - return pppoe_output(sc, pb); -} - -/* send a PADT packet */ -static err_t -pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) -{ - struct pbuf *pb; - struct eth_hdr *ethhdr; - err_t res; - u8_t *p; - - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - pbuf_header(pb, (s16_t)sizeof(struct eth_hdr)); - ethhdr = (struct eth_hdr *)pb->payload; - ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); - MEMCPY(ðhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); - MEMCPY(ðhdr->src.addr, &outgoing_if->hwaddr, sizeof(ethhdr->src.addr)); - - p = (u8_t*)(ethhdr + 1); - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADT, session, 0); - - res = outgoing_if->linkoutput(outgoing_if, pb); - - pbuf_free(pb); - - return res; -} - -#ifdef PPPOE_SERVER -static err_t -pppoe_send_pado(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len; - - /* calc length */ - len = 0; - /* include ac_cookie */ - len += 2 + 2 + sizeof(sc); - /* include hunique */ - len += 2 + 2 + sc->sc_hunique_len; - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); - PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); - PPPOE_ADD_16(p, sizeof(sc)); - MEMCPY(p, &sc, sizeof(sc)); - p += sizeof(sc); - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sc->sc_hunique_len); - MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); - return pppoe_output(sc, pb); -} - -static err_t -pppoe_send_pads(struct pppoe_softc *sc) -{ - struct pbuf *pb; - u8_t *p; - size_t len, l1 = 0; /* XXX: gcc */ - - sc->sc_session = mono_time.tv_sec % 0xff + 1; - /* calc length */ - len = 0; - /* include hunique */ - len += 2 + 2 + 2 + 2 + sc->sc_hunique_len; /* service name, host unique*/ - if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ - l1 = strlen(sc->sc_service_name); - len += l1; - } - pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HEADERLEN + len), PBUF_RAM); - if (!pb) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); - PPPOE_ADD_16(p, PPPOE_TAG_SNAME); - if (sc->sc_service_name != NULL) { - PPPOE_ADD_16(p, l1); - MEMCPY(p, sc->sc_service_name, l1); - p += l1; - } else { - PPPOE_ADD_16(p, 0); - } - PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); - PPPOE_ADD_16(p, sc->sc_hunique_len); - MEMCPY(p, sc->sc_hunique, sc->sc_hunique_len); - return pppoe_output(sc, pb); -} -#endif - -static err_t -pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) -{ - u8_t *p; - size_t len; - - len = pb->tot_len; - - /* make room for PPPoE header - should not fail */ - if (pbuf_header(pb, (s16_t)(PPPOE_HEADERLEN)) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for PPPoE header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - - p = (u8_t*)pb->payload; - PPPOE_ADD_HEADER(p, 0, sc->sc_session, len); - - return pppoe_output(sc, pb); -} - -#if 0 /*def PFIL_HOOKS*/ -static int -pppoe_ifattach_hook(void *arg, struct pbuf **mp, struct netif *ifp, int dir) -{ - struct pppoe_softc *sc; - int s; - - if (mp != (struct pbuf **)PFIL_IFNET_DETACH) { - return 0; - } - - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { - if (sc->sc_ethif != ifp) { - continue; - } - if (sc->sc_sppp.pp_if.if_flags & IFF_UP) { - sc->sc_sppp.pp_if.if_flags &= ~(IFF_UP|IFF_RUNNING); - PPPDEBUG(LOG_DEBUG, ("%c%c%"U16_F": ethernet interface detached, going down\n", - sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); - } - sc->sc_ethif = NULL; - pppoe_clear_softc(sc, "ethernet interface detached"); - } - - return 0; -} -#endif - -#if 0 /* UNUSED */ -static void -pppoe_clear_softc(struct pppoe_softc *sc, const char *message) -{ - LWIP_UNUSED_ARG(message); - - /* stop timer */ - sys_untimeout(pppoe_timeout, sc); - PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); - sc->sc_state = PPPOE_STATE_INITIAL; - ppp_link_end(sc->pcb); /* notify upper layers - /!\ dangerous /!\ - see pppoe_disc_input() */ -} -#endif /* UNUSED */ -#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/pppol2tp.c b/components/net/lwip-2.0.2/src/netif/ppp/pppol2tp.c deleted file mode 100644 index d44471e25f..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/pppol2tp.c +++ /dev/null @@ -1,1131 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Layer 2 Tunneling Protocol program file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -/* - * L2TP Support status: - * - * Supported: - * - L2TPv2 (PPP over L2TP, a.k.a. UDP tunnels) - * - LAC - * - * Not supported: - * - LNS (require PPP server support) - * - L2TPv3 ethernet pseudowires - * - L2TPv3 VLAN pseudowire - * - L2TPv3 PPP pseudowires - * - L2TPv3 IP encapsulation - * - L2TPv3 IP pseudowire - * - L2TP tunnel switching - http://tools.ietf.org/html/draft-ietf-l2tpext-tunnel-switching-08 - * - Multiple tunnels per UDP socket, as well as multiple sessions per tunnel - * - Hidden AVPs - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOL2TP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/err.h" -#include "lwip/memp.h" -#include "lwip/netif.h" -#include "lwip/udp.h" -#include "lwip/snmp.h" - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/lcp.h" -#include "netif/ppp/ipcp.h" -#include "netif/ppp/pppol2tp.h" -#include "netif/ppp/pppcrypt.h" -#include "netif/ppp/magic.h" - -/* Memory pool */ -LWIP_MEMPOOL_DECLARE(PPPOL2TP_PCB, MEMP_NUM_PPPOL2TP_INTERFACES, sizeof(pppol2tp_pcb), "PPPOL2TP_PCB") - -/* callbacks called from PPP core */ -static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); -static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol); -static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx); /* Destroy a L2TP control block */ -static void pppol2tp_connect(ppp_pcb *ppp, void *ctx); /* Be a LAC, connect to a LNS. */ -static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx); /* Disconnect */ - - /* Prototypes for procedures local to this file. */ -static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); -static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr); -static void pppol2tp_timeout(void *arg); -static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp); -static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp); -static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns); -static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb); -static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb); - -/* Callbacks structure for PPP core */ -static const struct link_callbacks pppol2tp_callbacks = { - pppol2tp_connect, -#if PPP_SERVER - NULL, -#endif /* PPP_SERVER */ - pppol2tp_disconnect, - pppol2tp_destroy, - pppol2tp_write, - pppol2tp_netif_output, - NULL, - NULL -}; - - -/* Create a new L2TP session. */ -ppp_pcb *pppol2tp_create(struct netif *pppif, - struct netif *netif, const ip_addr_t *ipaddr, u16_t port, - const u8_t *secret, u8_t secret_len, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { - ppp_pcb *ppp; - pppol2tp_pcb *l2tp; - struct udp_pcb *udp; -#if !PPPOL2TP_AUTH_SUPPORT - LWIP_UNUSED_ARG(secret); - LWIP_UNUSED_ARG(secret_len); -#endif /* !PPPOL2TP_AUTH_SUPPORT */ - - if (ipaddr == NULL) { - goto ipaddr_check_failed; - } - - l2tp = (pppol2tp_pcb *)LWIP_MEMPOOL_ALLOC(PPPOL2TP_PCB); - if (l2tp == NULL) { - goto memp_malloc_l2tp_failed; - } - - udp = udp_new_ip_type(IP_GET_TYPE(ipaddr)); - if (udp == NULL) { - goto udp_new_failed; - } - udp_recv(udp, pppol2tp_input, l2tp); - - ppp = ppp_new(pppif, &pppol2tp_callbacks, l2tp, link_status_cb, ctx_cb); - if (ppp == NULL) { - goto ppp_new_failed; - } - - memset(l2tp, 0, sizeof(pppol2tp_pcb)); - l2tp->phase = PPPOL2TP_STATE_INITIAL; - l2tp->ppp = ppp; - l2tp->udp = udp; - l2tp->netif = netif; - ip_addr_copy(l2tp->remote_ip, *ipaddr); - l2tp->remote_port = port; -#if PPPOL2TP_AUTH_SUPPORT - l2tp->secret = secret; - l2tp->secret_len = secret_len; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - return ppp; - -ppp_new_failed: - udp_remove(udp); -udp_new_failed: - LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); -memp_malloc_l2tp_failed: -ipaddr_check_failed: - return NULL; -} - -/* Called by PPP core */ -static err_t pppol2tp_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - struct pbuf *ph; /* UDP + L2TP header */ - err_t ret; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - ph = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(PPPOL2TP_OUTPUT_DATA_HEADER_LEN), PBUF_RAM); - if(!ph) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(p); - return ERR_MEM; - } - - pbuf_header(ph, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); /* hide L2TP header */ - pbuf_cat(ph, p); -#if MIB2_STATS - tot_len = ph->tot_len; -#endif /* MIB2_STATS */ - - ret = pppol2tp_xmit(l2tp, ph); - if (ret != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ret; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, (u16_t)tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -/* Called by PPP core */ -static err_t pppol2tp_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *p, u_short protocol) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - struct pbuf *pb; - u8_t *pl; - err_t err; -#if MIB2_STATS - u16_t tot_len; -#else /* MIB2_STATS */ - LWIP_UNUSED_ARG(ppp); -#endif /* MIB2_STATS */ - - /* @todo: try to use pbuf_header() here! */ - pb = pbuf_alloc(PBUF_TRANSPORT, PPPOL2TP_OUTPUT_DATA_HEADER_LEN + sizeof(protocol), PBUF_RAM); - if(!pb) { - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.proterr); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ERR_MEM; - } - - pbuf_header(pb, -(s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN); - - pl = (u8_t*)pb->payload; - PUTSHORT(protocol, pl); - - pbuf_chain(pb, p); -#if MIB2_STATS - tot_len = pb->tot_len; -#endif /* MIB2_STATS */ - - if( (err = pppol2tp_xmit(l2tp, pb)) != ERR_OK) { - LINK_STATS_INC(link.err); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return err; - } - - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - return ERR_OK; -} - -/* Destroy a L2TP control block */ -static err_t pppol2tp_destroy(ppp_pcb *ppp, void *ctx) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - LWIP_UNUSED_ARG(ppp); - - sys_untimeout(pppol2tp_timeout, l2tp); - udp_remove(l2tp->udp); - LWIP_MEMPOOL_FREE(PPPOL2TP_PCB, l2tp); - return ERR_OK; -} - -/* Be a LAC, connect to a LNS. */ -static void pppol2tp_connect(ppp_pcb *ppp, void *ctx) { - err_t err; - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - lcp_options *lcp_wo; - lcp_options *lcp_ao; -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_options *ipcp_wo; - ipcp_options *ipcp_ao; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - l2tp->tunnel_port = l2tp->remote_port; - l2tp->our_ns = 0; - l2tp->peer_nr = 0; - l2tp->peer_ns = 0; - l2tp->source_tunnel_id = 0; - l2tp->remote_tunnel_id = 0; - l2tp->source_session_id = 0; - l2tp->remote_session_id = 0; - /* l2tp->*_retried are cleared when used */ - - lcp_wo = &ppp->lcp_wantoptions; - lcp_wo->mru = PPPOL2TP_DEFMRU; - lcp_wo->neg_asyncmap = 0; - lcp_wo->neg_pcompression = 0; - lcp_wo->neg_accompression = 0; - lcp_wo->passive = 0; - lcp_wo->silent = 0; - - lcp_ao = &ppp->lcp_allowoptions; - lcp_ao->mru = PPPOL2TP_DEFMRU; - lcp_ao->neg_asyncmap = 0; - lcp_ao->neg_pcompression = 0; - lcp_ao->neg_accompression = 0; - -#if PPP_IPV4_SUPPORT && VJ_SUPPORT - ipcp_wo = &ppp->ipcp_wantoptions; - ipcp_wo->neg_vj = 0; - ipcp_wo->old_vj = 0; - - ipcp_ao = &ppp->ipcp_allowoptions; - ipcp_ao->neg_vj = 0; - ipcp_ao->old_vj = 0; -#endif /* PPP_IPV4_SUPPORT && VJ_SUPPORT */ - - /* Listen to a random source port, we need to do that instead of using udp_connect() - * because the L2TP LNS might answer with its own random source port (!= 1701) - */ -#if LWIP_IPV6 - if (IP_IS_V6_VAL(l2tp->udp->local_ip)) { - udp_bind(l2tp->udp, IP6_ADDR_ANY, 0); - } else -#endif /* LWIP_IPV6 */ - udp_bind(l2tp->udp, IP_ADDR_ANY, 0); - -#if PPPOL2TP_AUTH_SUPPORT - /* Generate random vector */ - if (l2tp->secret != NULL) { - magic_random_bytes(l2tp->secret_rv, sizeof(l2tp->secret_rv)); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - do { - l2tp->remote_tunnel_id = magic(); - } while(l2tp->remote_tunnel_id == 0); - /* save state, in case we fail to send SCCRQ */ - l2tp->sccrq_retried = 0; - l2tp->phase = PPPOL2TP_STATE_SCCRQ_SENT; - if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); - } - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); -} - -/* Disconnect */ -static void pppol2tp_disconnect(ppp_pcb *ppp, void *ctx) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb *)ctx; - - l2tp->our_ns++; - pppol2tp_send_stopccn(l2tp, l2tp->our_ns); - - /* stop any timer, disconnect can be called while initiating is in progress */ - sys_untimeout(pppol2tp_timeout, l2tp); - l2tp->phase = PPPOL2TP_STATE_INITIAL; - ppp_link_end(ppp); /* notify upper layers */ -} - -/* UDP Callback for incoming IPv4 L2TP frames */ -static void pppol2tp_input(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; - u16_t hflags, hlen, len=0, tunnel_id=0, session_id=0, ns=0, nr=0, offset=0; - u8_t *inp; - LWIP_UNUSED_ARG(pcb); - - /* we can't unbound a UDP pcb, thus we can still receive UDP frames after the link is closed */ - if (l2tp->phase < PPPOL2TP_STATE_SCCRQ_SENT) { - goto free_and_return; - } - - if (!ip_addr_cmp(&l2tp->remote_ip, addr)) { - goto free_and_return; - } - - /* discard packet if port mismatch, but only if we received a SCCRP */ - if (l2tp->phase > PPPOL2TP_STATE_SCCRQ_SENT && l2tp->tunnel_port != port) { - goto free_and_return; - } - - /* printf("-----------\nL2TP INPUT, %d\n", p->len); */ - - /* L2TP header */ - if (p->len < sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id) ) { - goto packet_too_short; - } - - inp = (u8_t*)p->payload; - GETSHORT(hflags, inp); - - if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { - /* check mandatory flags for a control packet */ - if ( (hflags & PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY) != PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for control packet not set\n")); - goto free_and_return; - } - /* check forbidden flags for a control packet */ - if (hflags & PPPOL2TP_HEADERFLAG_CONTROL_FORBIDDEN) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: forbidden header flags for control packet found\n")); - goto free_and_return; - } - } else { - /* check mandatory flags for a data packet */ - if ( (hflags & PPPOL2TP_HEADERFLAG_DATA_MANDATORY) != PPPOL2TP_HEADERFLAG_DATA_MANDATORY) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: mandatory header flags for data packet not set\n")); - goto free_and_return; - } - } - - /* Expected header size */ - hlen = sizeof(hflags) + sizeof(tunnel_id) + sizeof(session_id); - if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { - hlen += sizeof(len); - } - if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { - hlen += sizeof(ns) + sizeof(nr); - } - if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { - hlen += sizeof(offset); - } - if (p->len < hlen) { - goto packet_too_short; - } - - if (hflags & PPPOL2TP_HEADERFLAG_LENGTH) { - GETSHORT(len, inp); - if (p->len < len || len < hlen) { - goto packet_too_short; - } - } - GETSHORT(tunnel_id, inp); - GETSHORT(session_id, inp); - if (hflags & PPPOL2TP_HEADERFLAG_SEQUENCE) { - GETSHORT(ns, inp); - GETSHORT(nr, inp); - } - if (hflags & PPPOL2TP_HEADERFLAG_OFFSET) { - GETSHORT(offset, inp) - if (offset > 4096) { /* don't be fooled with large offset which might overflow hlen */ - PPPDEBUG(LOG_DEBUG, ("pppol2tp: strange packet received, offset=%d\n", offset)); - goto free_and_return; - } - hlen += offset; - if (p->len < hlen) { - goto packet_too_short; - } - INCPTR(offset, inp); - } - - /* printf("HLEN = %d\n", hlen); */ - - /* skip L2TP header */ - if (pbuf_header(p, -(s16_t)hlen) != 0) { - goto free_and_return; - } - - /* printf("LEN=%d, TUNNEL_ID=%d, SESSION_ID=%d, NS=%d, NR=%d, OFFSET=%d\n", len, tunnel_id, session_id, ns, nr, offset); */ - PPPDEBUG(LOG_DEBUG, ("pppol2tp: input packet, len=%"U16_F", tunnel=%"U16_F", session=%"U16_F", ns=%"U16_F", nr=%"U16_F"\n", - len, tunnel_id, session_id, ns, nr)); - - /* Control packet */ - if (hflags & PPPOL2TP_HEADERFLAG_CONTROL) { - pppol2tp_dispatch_control_packet(l2tp, port, p, ns, nr); - goto free_and_return; - } - - /* Data packet */ - if(l2tp->phase != PPPOL2TP_STATE_DATA) { - goto free_and_return; - } - if(tunnel_id != l2tp->remote_tunnel_id) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: tunnel ID mismatch, assigned=%d, received=%d\n", l2tp->remote_tunnel_id, tunnel_id)); - goto free_and_return; - } - if(session_id != l2tp->remote_session_id) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: session ID mismatch, assigned=%d, received=%d\n", l2tp->remote_session_id, session_id)); - goto free_and_return; - } - /* - * skip address & flags if necessary - * - * RFC 2661 does not specify whether the PPP frame in the L2TP payload should - * have a HDLC header or not. We handle both cases for compatibility. - */ - if (p->len >= 2) { - GETSHORT(hflags, inp); - if (hflags == 0xff03) { - pbuf_header(p, -(s16_t)2); - } - } - /* Dispatch the packet thereby consuming it. */ - ppp_input(l2tp->ppp, p); - return; - -packet_too_short: - PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); -free_and_return: - pbuf_free(p); -} - -/* L2TP Control packet entry point */ -static void pppol2tp_dispatch_control_packet(pppol2tp_pcb *l2tp, u16_t port, struct pbuf *p, u16_t ns, u16_t nr) { - u8_t *inp; - u16_t avplen, avpflags, vendorid, attributetype, messagetype=0; - err_t err; -#if PPPOL2TP_AUTH_SUPPORT - lwip_md5_context md5_ctx; - u8_t md5_hash[16]; - u8_t challenge_id = 0; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - l2tp->peer_nr = nr; - l2tp->peer_ns = ns; - /* printf("L2TP CTRL INPUT, ns=%d, nr=%d, len=%d\n", ns, nr, p->len); */ - - /* Handle the special case of the ICCN acknowledge */ - if (l2tp->phase == PPPOL2TP_STATE_ICCN_SENT && l2tp->peer_nr > l2tp->our_ns) { - l2tp->phase = PPPOL2TP_STATE_DATA; - } - - /* ZLB packets */ - if (p->tot_len == 0) { - return; - } - - p = ppp_singlebuf(p); - inp = (u8_t*)p->payload; - /* Decode AVPs */ - while (p->len > 0) { - if (p->len < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype) ) { - goto packet_too_short; - } - GETSHORT(avpflags, inp); - avplen = avpflags & PPPOL2TP_AVPHEADERFLAG_LENGTHMASK; - /* printf("AVPLEN = %d\n", avplen); */ - if (p->len < avplen || avplen < sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) { - goto packet_too_short; - } - GETSHORT(vendorid, inp); - GETSHORT(attributetype, inp); - avplen -= sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype); - - /* Message type must be the first AVP */ - if (messagetype == 0) { - if (attributetype != 0 || vendorid != 0 || avplen != sizeof(messagetype) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: message type must be the first AVP\n")); - return; - } - GETSHORT(messagetype, inp); - /* printf("Message type = %d\n", messagetype); */ - switch(messagetype) { - /* Start Control Connection Reply */ - case PPPOL2TP_MESSAGETYPE_SCCRP: - /* Only accept SCCRP packet if we sent a SCCRQ */ - if (l2tp->phase != PPPOL2TP_STATE_SCCRQ_SENT) { - goto send_zlb; - } - break; - /* Incoming Call Reply */ - case PPPOL2TP_MESSAGETYPE_ICRP: - /* Only accept ICRP packet if we sent a IRCQ */ - if (l2tp->phase != PPPOL2TP_STATE_ICRQ_SENT) { - goto send_zlb; - } - break; - /* Stop Control Connection Notification */ - case PPPOL2TP_MESSAGETYPE_STOPCCN: - pppol2tp_send_zlb(l2tp, l2tp->our_ns); /* Ack the StopCCN before we switch to down state */ - if (l2tp->phase < PPPOL2TP_STATE_DATA) { - pppol2tp_abort_connect(l2tp); - } else if (l2tp->phase == PPPOL2TP_STATE_DATA) { - /* Don't disconnect here, we let the LCP Echo/Reply find the fact - * that PPP session is down. Asking the PPP stack to end the session - * require strict checking about the PPP phase to prevent endless - * disconnection loops. - */ - } - return; - default: - break; - } - goto nextavp; - } - - /* Skip proprietary L2TP extensions */ - if (vendorid != 0) { - goto skipavp; - } - - switch (messagetype) { - /* Start Control Connection Reply */ - case PPPOL2TP_MESSAGETYPE_SCCRP: - switch (attributetype) { - case PPPOL2TP_AVPTYPE_TUNNELID: - if (avplen != sizeof(l2tp->source_tunnel_id) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign tunnel ID length check failed\n")); - return; - } - GETSHORT(l2tp->source_tunnel_id, inp); - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned tunnel ID %"U16_F"\n", l2tp->source_tunnel_id)); - goto nextavp; -#if PPPOL2TP_AUTH_SUPPORT - case PPPOL2TP_AVPTYPE_CHALLENGE: - if (avplen == 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Challenge length check failed\n")); - return; - } - if (l2tp->secret == NULL) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge from peer and no secret key available\n")); - pppol2tp_abort_connect(l2tp); - return; - } - /* Generate hash of ID, secret, challenge */ - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - challenge_id = PPPOL2TP_MESSAGETYPE_SCCCN; - lwip_md5_update(&md5_ctx, &challenge_id, 1); - lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); - lwip_md5_update(&md5_ctx, inp, avplen); - lwip_md5_finish(&md5_ctx, l2tp->challenge_hash); - lwip_md5_free(&md5_ctx); - l2tp->send_challenge = 1; - goto skipavp; - case PPPOL2TP_AVPTYPE_CHALLENGERESPONSE: - if (avplen != PPPOL2TP_AVPTYPE_CHALLENGERESPONSE_SIZE) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Challenge Response length check failed\n")); - return; - } - /* Generate hash of ID, secret, challenge */ - lwip_md5_init(&md5_ctx); - lwip_md5_starts(&md5_ctx); - challenge_id = PPPOL2TP_MESSAGETYPE_SCCRP; - lwip_md5_update(&md5_ctx, &challenge_id, 1); - lwip_md5_update(&md5_ctx, l2tp->secret, l2tp->secret_len); - lwip_md5_update(&md5_ctx, l2tp->secret_rv, sizeof(l2tp->secret_rv)); - lwip_md5_finish(&md5_ctx, md5_hash); - lwip_md5_free(&md5_ctx); - if ( memcmp(inp, md5_hash, sizeof(md5_hash)) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Received challenge response from peer and secret key do not match\n")); - pppol2tp_abort_connect(l2tp); - return; - } - goto skipavp; -#endif /* PPPOL2TP_AUTH_SUPPORT */ - default: - break; - } - break; - /* Incoming Call Reply */ - case PPPOL2TP_MESSAGETYPE_ICRP: - switch (attributetype) { - case PPPOL2TP_AVPTYPE_SESSIONID: - if (avplen != sizeof(l2tp->source_session_id) ) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: AVP Assign session ID length check failed\n")); - return; - } - GETSHORT(l2tp->source_session_id, inp); - PPPDEBUG(LOG_DEBUG, ("pppol2tp: Assigned session ID %"U16_F"\n", l2tp->source_session_id)); - goto nextavp; - default: - break; - } - break; - default: - break; - } - -skipavp: - INCPTR(avplen, inp); -nextavp: - /* printf("AVP Found, vendor=%d, attribute=%d, len=%d\n", vendorid, attributetype, avplen); */ - /* next AVP */ - if (pbuf_header(p, -(s16_t)(avplen + sizeof(avpflags) + sizeof(vendorid) + sizeof(attributetype)) ) != 0) { - return; - } - } - - switch(messagetype) { - /* Start Control Connection Reply */ - case PPPOL2TP_MESSAGETYPE_SCCRP: - do { - l2tp->remote_session_id = magic(); - } while(l2tp->remote_session_id == 0); - l2tp->tunnel_port = port; /* LNS server might have chosen its own local port */ - l2tp->icrq_retried = 0; - l2tp->phase = PPPOL2TP_STATE_ICRQ_SENT; - l2tp->our_ns++; - if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); - } - l2tp->our_ns++; - if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); - } - sys_untimeout(pppol2tp_timeout, l2tp); - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - /* Incoming Call Reply */ - case PPPOL2TP_MESSAGETYPE_ICRP: - l2tp->iccn_retried = 0; - l2tp->phase = PPPOL2TP_STATE_ICCN_SENT; - l2tp->our_ns++; - ppp_start(l2tp->ppp); /* notify upper layers */ - if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); - } - sys_untimeout(pppol2tp_timeout, l2tp); - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - /* Unhandled packet, send ZLB ACK */ - default: - goto send_zlb; - } - return; - -send_zlb: - pppol2tp_send_zlb(l2tp, l2tp->our_ns); - return; -packet_too_short: - PPPDEBUG(LOG_DEBUG, ("pppol2tp: packet too short: %d\n", p->len)); -} - -/* L2TP Timeout handler */ -static void pppol2tp_timeout(void *arg) { - pppol2tp_pcb *l2tp = (pppol2tp_pcb*)arg; - err_t err; - u32_t retry_wait; - - PPPDEBUG(LOG_DEBUG, ("pppol2tp: timeout\n")); - - switch (l2tp->phase) { - case PPPOL2TP_STATE_SCCRQ_SENT: - /* backoff wait */ - if (l2tp->sccrq_retried < 0xff) { - l2tp->sccrq_retried++; - } - if (!l2tp->ppp->settings.persist && l2tp->sccrq_retried >= PPPOL2TP_MAXSCCRQ) { - pppol2tp_abort_connect(l2tp); - return; - } - retry_wait = LWIP_MIN(PPPOL2TP_CONTROL_TIMEOUT * l2tp->sccrq_retried, PPPOL2TP_SLOW_RETRY); - PPPDEBUG(LOG_DEBUG, ("pppol2tp: sccrq_retried=%d\n", l2tp->sccrq_retried)); - if ((err = pppol2tp_send_sccrq(l2tp)) != 0) { - l2tp->sccrq_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCRQ, error=%d\n", err)); - } - sys_timeout(retry_wait, pppol2tp_timeout, l2tp); - break; - - case PPPOL2TP_STATE_ICRQ_SENT: - l2tp->icrq_retried++; - if (l2tp->icrq_retried >= PPPOL2TP_MAXICRQ) { - pppol2tp_abort_connect(l2tp); - return; - } - PPPDEBUG(LOG_DEBUG, ("pppol2tp: icrq_retried=%d\n", l2tp->icrq_retried)); - if (l2tp->peer_nr <= l2tp->our_ns -1) { /* the SCCCN was not acknowledged */ - if ((err = pppol2tp_send_scccn(l2tp, l2tp->our_ns -1)) != 0) { - l2tp->icrq_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send SCCCN, error=%d\n", err)); - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - } - } - if ((err = pppol2tp_send_icrq(l2tp, l2tp->our_ns)) != 0) { - l2tp->icrq_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICRQ, error=%d\n", err)); - } - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - - case PPPOL2TP_STATE_ICCN_SENT: - l2tp->iccn_retried++; - if (l2tp->iccn_retried >= PPPOL2TP_MAXICCN) { - pppol2tp_abort_connect(l2tp); - return; - } - PPPDEBUG(LOG_DEBUG, ("pppol2tp: iccn_retried=%d\n", l2tp->iccn_retried)); - if ((err = pppol2tp_send_iccn(l2tp, l2tp->our_ns)) != 0) { - l2tp->iccn_retried--; - PPPDEBUG(LOG_DEBUG, ("pppol2tp: failed to send ICCN, error=%d\n", err)); - } - sys_timeout(PPPOL2TP_CONTROL_TIMEOUT, pppol2tp_timeout, l2tp); - break; - - default: - return; /* all done, work in peace */ - } -} - -/* Connection attempt aborted */ -static void pppol2tp_abort_connect(pppol2tp_pcb *l2tp) { - PPPDEBUG(LOG_DEBUG, ("pppol2tp: could not establish connection\n")); - l2tp->phase = PPPOL2TP_STATE_INITIAL; - ppp_link_failed(l2tp->ppp); /* notify upper layers */ -} - -/* Initiate a new tunnel */ -static err_t pppol2tp_send_sccrq(pppol2tp_pcb *l2tp) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8 +8 +10 +10 +6+sizeof(PPPOL2TP_HOSTNAME)-1 +6+sizeof(PPPOL2TP_VENDORNAME)-1 +8 +8; -#if PPPOL2TP_AUTH_SUPPORT - if (l2tp->secret != NULL) { - len += 6 + sizeof(l2tp->secret_rv); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(0, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(0, p); /* NS Sequence number - to peer */ - PUTSHORT(0, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCRQ, p); /* Attribute value: Message type: SCCRQ */ - - /* AVP - L2TP Version */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_VERSION, p); /* Attribute type: Version */ - PUTSHORT(PPPOL2TP_VERSION, p); /* Attribute value: L2TP Version */ - - /* AVP - Framing capabilities */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGCAPABILITIES, p); /* Attribute type: Framing capabilities */ - PUTLONG(PPPOL2TP_FRAMINGCAPABILITIES, p); /* Attribute value: Framing capabilities */ - - /* AVP - Bearer capabilities */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_BEARERCAPABILITIES, p); /* Attribute type: Bearer capabilities */ - PUTLONG(PPPOL2TP_BEARERCAPABILITIES, p); /* Attribute value: Bearer capabilities */ - - /* AVP - Host name */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6+sizeof(PPPOL2TP_HOSTNAME)-1, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_HOSTNAME, p); /* Attribute type: Hostname */ - MEMCPY(p, PPPOL2TP_HOSTNAME, sizeof(PPPOL2TP_HOSTNAME)-1); /* Attribute value: Hostname */ - INCPTR(sizeof(PPPOL2TP_HOSTNAME)-1, p); - - /* AVP - Vendor name */ - PUTSHORT(6+sizeof(PPPOL2TP_VENDORNAME)-1, p); /* len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_VENDORNAME, p); /* Attribute type: Vendor name */ - MEMCPY(p, PPPOL2TP_VENDORNAME, sizeof(PPPOL2TP_VENDORNAME)-1); /* Attribute value: Vendor name */ - INCPTR(sizeof(PPPOL2TP_VENDORNAME)-1, p); - - /* AVP - Assign tunnel ID */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ - PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ - - /* AVP - Receive window size */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_RECEIVEWINDOWSIZE, p); /* Attribute type: Receive window size */ - PUTSHORT(PPPOL2TP_RECEIVEWINDOWSIZE, p); /* Attribute value: Receive window size */ - -#if PPPOL2TP_AUTH_SUPPORT - /* AVP - Challenge */ - if (l2tp->secret != NULL) { - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->secret_rv), p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGE, p); /* Attribute type: Challenge */ - MEMCPY(p, l2tp->secret_rv, sizeof(l2tp->secret_rv)); /* Attribute value: Random vector */ - INCPTR(sizeof(l2tp->secret_rv), p); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Complete tunnel establishment */ -static err_t pppol2tp_send_scccn(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8; -#if PPPOL2TP_AUTH_SUPPORT - if (l2tp->send_challenge) { - len += 6 + sizeof(l2tp->challenge_hash); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_SCCCN, p); /* Attribute value: Message type: SCCCN */ - -#if PPPOL2TP_AUTH_SUPPORT - /* AVP - Challenge response */ - if (l2tp->send_challenge) { - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 6 + sizeof(l2tp->challenge_hash), p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_CHALLENGERESPONSE, p); /* Attribute type: Challenge response */ - MEMCPY(p, l2tp->challenge_hash, sizeof(l2tp->challenge_hash)); /* Attribute value: Computed challenge */ - INCPTR(sizeof(l2tp->challenge_hash), p); - } -#endif /* PPPOL2TP_AUTH_SUPPORT */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Initiate a new session */ -static err_t pppol2tp_send_icrq(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - u32_t serialnumber; - - /* calculate UDP packet length */ - len = 12 +8 +8 +10; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_ICRQ, p); /* Attribute value: Message type: ICRQ */ - - /* AVP - Assign session ID */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_SESSIONID, p); /* Attribute type: Session ID */ - PUTSHORT(l2tp->remote_session_id, p); /* Attribute value: Session ID */ - - /* AVP - Call Serial Number */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_CALLSERIALNUMBER, p); /* Attribute type: Serial number */ - serialnumber = magic(); - PUTLONG(serialnumber, p); /* Attribute value: Serial number */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Complete tunnel establishment */ -static err_t pppol2tp_send_iccn(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8 +10 +10; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(l2tp->source_session_id, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_ICCN, p); /* Attribute value: Message type: ICCN */ - - /* AVP - Framing type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_FRAMINGTYPE, p); /* Attribute type: Framing type */ - PUTLONG(PPPOL2TP_FRAMINGTYPE, p); /* Attribute value: Framing type */ - - /* AVP - TX Connect speed */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 10, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_TXCONNECTSPEED, p); /* Attribute type: TX Connect speed */ - PUTLONG(PPPOL2TP_TXCONNECTSPEED, p); /* Attribute value: TX Connect speed */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Send a ZLB ACK packet */ -static err_t pppol2tp_send_zlb(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - return pppol2tp_udp_send(l2tp, pb); -} - -/* Send a StopCCN packet */ -static err_t pppol2tp_send_stopccn(pppol2tp_pcb *l2tp, u16_t ns) { - struct pbuf *pb; - u8_t *p; - u16_t len; - - /* calculate UDP packet length */ - len = 12 +8 +8 +8; - - /* allocate a buffer */ - pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pb == NULL) { - return ERR_MEM; - } - LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); - - p = (u8_t*)pb->payload; - /* fill in pkt */ - /* L2TP control header */ - PUTSHORT(PPPOL2TP_HEADERFLAG_CONTROL_MANDATORY, p); - PUTSHORT(len, p); /* Length */ - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(0, p); /* Session Id */ - PUTSHORT(ns, p); /* NS Sequence number - to peer */ - PUTSHORT(l2tp->peer_ns+1, p); /* NR Sequence number - expected for peer */ - - /* AVP - Message type */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_MESSAGE, p); /* Attribute type: Message Type */ - PUTSHORT(PPPOL2TP_MESSAGETYPE_STOPCCN, p); /* Attribute value: Message type: StopCCN */ - - /* AVP - Assign tunnel ID */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_TUNNELID, p); /* Attribute type: Tunnel ID */ - PUTSHORT(l2tp->remote_tunnel_id, p); /* Attribute value: Tunnel ID */ - - /* AVP - Result code */ - PUTSHORT(PPPOL2TP_AVPHEADERFLAG_MANDATORY + 8, p); /* Mandatory flag + len field */ - PUTSHORT(0, p); /* Vendor ID */ - PUTSHORT(PPPOL2TP_AVPTYPE_RESULTCODE, p); /* Attribute type: Result code */ - PUTSHORT(PPPOL2TP_RESULTCODE, p); /* Attribute value: Result code */ - - return pppol2tp_udp_send(l2tp, pb); -} - -static err_t pppol2tp_xmit(pppol2tp_pcb *l2tp, struct pbuf *pb) { - u8_t *p; - - /* make room for L2TP header - should not fail */ - if (pbuf_header(pb, (s16_t)PPPOL2TP_OUTPUT_DATA_HEADER_LEN) != 0) { - /* bail out */ - PPPDEBUG(LOG_ERR, ("pppol2tp: pppol2tp_pcb: could not allocate room for L2TP header\n")); - LINK_STATS_INC(link.lenerr); - pbuf_free(pb); - return ERR_BUF; - } - - p = (u8_t*)pb->payload; - PUTSHORT(PPPOL2TP_HEADERFLAG_DATA_MANDATORY, p); - PUTSHORT(l2tp->source_tunnel_id, p); /* Tunnel Id */ - PUTSHORT(l2tp->source_session_id, p); /* Session Id */ - - return pppol2tp_udp_send(l2tp, pb); -} - -static err_t pppol2tp_udp_send(pppol2tp_pcb *l2tp, struct pbuf *pb) { - err_t err; - if (l2tp->netif) { - err = udp_sendto_if(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port, l2tp->netif); - } else { - err = udp_sendto(l2tp->udp, pb, &l2tp->remote_ip, l2tp->tunnel_port); - } - pbuf_free(pb); - return err; -} - -#endif /* PPP_SUPPORT && PPPOL2TP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/pppos.c b/components/net/lwip-2.0.2/src/netif/ppp/pppos.c deleted file mode 100644 index fb48df4eb8..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/pppos.c +++ /dev/null @@ -1,875 +0,0 @@ -/** - * @file - * Network Point to Point Protocol over Serial file. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PPPOS_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/arch.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" -#include "lwip/memp.h" -#include "lwip/netif.h" -#include "lwip/snmp.h" -#include "lwip/priv/tcpip_priv.h" -#include "lwip/api.h" -#include "lwip/ip4.h" /* for ip4_input() */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/pppos.h" -#include "netif/ppp/vj.h" - -/* Memory pool */ -LWIP_MEMPOOL_DECLARE(PPPOS_PCB, MEMP_NUM_PPPOS_INTERFACES, sizeof(pppos_pcb), "PPPOS_PCB") - -/* callbacks called from PPP core */ -static err_t pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p); -static err_t pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol); -static void pppos_connect(ppp_pcb *ppp, void *ctx); -#if PPP_SERVER -static void pppos_listen(ppp_pcb *ppp, void *ctx); -#endif /* PPP_SERVER */ -static void pppos_disconnect(ppp_pcb *ppp, void *ctx); -static err_t pppos_destroy(ppp_pcb *ppp, void *ctx); -static void pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); -static void pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp); - -/* Prototypes for procedures local to this file. */ -#if PPP_INPROC_IRQ_SAFE -static void pppos_input_callback(void *arg); -#endif /* PPP_INPROC_IRQ_SAFE */ -static void pppos_input_free_current_packet(pppos_pcb *pppos); -static void pppos_input_drop(pppos_pcb *pppos); -static err_t pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs); -static err_t pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs); - -/* Callbacks structure for PPP core */ -static const struct link_callbacks pppos_callbacks = { - pppos_connect, -#if PPP_SERVER - pppos_listen, -#endif /* PPP_SERVER */ - pppos_disconnect, - pppos_destroy, - pppos_write, - pppos_netif_output, - pppos_send_config, - pppos_recv_config -}; - -/* PPP's Asynchronous-Control-Character-Map. The mask array is used - * to select the specific bit for a character. */ -#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & 1 << (c & 0x07)) - -#if PPP_FCS_TABLE -/* - * FCS lookup table as calculated by genfcstab. - */ -static const u16_t fcstab[256] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; -#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) -#else /* PPP_FCS_TABLE */ -/* The HDLC polynomial: X**0 + X**5 + X**12 + X**16 (0x8408) */ -#define PPP_FCS_POLYNOMIAL 0x8408 -static u16_t -ppp_get_fcs(u8_t byte) -{ - unsigned int octet; - int bit; - octet = byte; - for (bit = 8; bit-- > 0; ) { - octet = (octet & 0x01) ? ((octet >> 1) ^ PPP_FCS_POLYNOMIAL) : (octet >> 1); - } - return octet & 0xffff; -} -#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_get_fcs(((fcs) ^ (c)) & 0xff)) -#endif /* PPP_FCS_TABLE */ - -/* - * Values for FCS calculations. - */ -#define PPP_INITFCS 0xffff /* Initial FCS value */ -#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ - -#if PPP_INPROC_IRQ_SAFE -#define PPPOS_DECL_PROTECT(lev) SYS_ARCH_DECL_PROTECT(lev) -#define PPPOS_PROTECT(lev) SYS_ARCH_PROTECT(lev) -#define PPPOS_UNPROTECT(lev) SYS_ARCH_UNPROTECT(lev) -#else -#define PPPOS_DECL_PROTECT(lev) -#define PPPOS_PROTECT(lev) -#define PPPOS_UNPROTECT(lev) -#endif /* PPP_INPROC_IRQ_SAFE */ - - -/* - * Create a new PPP connection using the given serial I/O device. - * - * Return 0 on success, an error code on failure. - */ -ppp_pcb *pppos_create(struct netif *pppif, pppos_output_cb_fn output_cb, - ppp_link_status_cb_fn link_status_cb, void *ctx_cb) -{ - pppos_pcb *pppos; - ppp_pcb *ppp; - - pppos = (pppos_pcb *)LWIP_MEMPOOL_ALLOC(PPPOS_PCB); - if (pppos == NULL) { - return NULL; - } - - ppp = ppp_new(pppif, &pppos_callbacks, pppos, link_status_cb, ctx_cb); - if (ppp == NULL) { - LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); - return NULL; - } - - memset(pppos, 0, sizeof(pppos_pcb)); - pppos->ppp = ppp; - pppos->output_cb = output_cb; - return ppp; -} - -/* Called by PPP core */ -static err_t -pppos_write(ppp_pcb *ppp, void *ctx, struct pbuf *p) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - u8_t *s; - struct pbuf *nb; - u16_t n; - u16_t fcs_out; - err_t err; - LWIP_UNUSED_ARG(ppp); - - /* Grab an output buffer. */ - nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (nb == NULL) { - PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: alloc fail\n", ppp->netif->num)); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(p); - return ERR_MEM; - } - - /* If the link has been idle, we'll send a fresh flag character to - * flush any noise. */ - err = ERR_OK; - if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { - err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); - } - - /* Load output buffer. */ - fcs_out = PPP_INITFCS; - s = (u8_t*)p->payload; - n = p->len; - while (n-- > 0) { - err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); - } - - err = pppos_output_last(pppos, err, nb, &fcs_out); - if (err == ERR_OK) { - PPPDEBUG(LOG_INFO, ("pppos_write[%d]: len=%d\n", ppp->netif->num, p->len)); - } else { - PPPDEBUG(LOG_WARNING, ("pppos_write[%d]: output failed len=%d\n", ppp->netif->num, p->len)); - } - pbuf_free(p); - return err; -} - -/* Called by PPP core */ -static err_t -pppos_netif_output(ppp_pcb *ppp, void *ctx, struct pbuf *pb, u16_t protocol) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - struct pbuf *nb, *p; - u16_t fcs_out; - err_t err; - LWIP_UNUSED_ARG(ppp); - - /* Grab an output buffer. */ - nb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); - if (nb == NULL) { - PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: alloc fail\n", ppp->netif->num)); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - return ERR_MEM; - } - - /* If the link has been idle, we'll send a fresh flag character to - * flush any noise. */ - err = ERR_OK; - if ((sys_now() - pppos->last_xmit) >= PPP_MAXIDLEFLAG) { - err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); - } - - fcs_out = PPP_INITFCS; - if (!pppos->accomp) { - err = pppos_output_append(pppos, err, nb, PPP_ALLSTATIONS, 1, &fcs_out); - err = pppos_output_append(pppos, err, nb, PPP_UI, 1, &fcs_out); - } - if (!pppos->pcomp || protocol > 0xFF) { - err = pppos_output_append(pppos, err, nb, (protocol >> 8) & 0xFF, 1, &fcs_out); - } - err = pppos_output_append(pppos, err, nb, protocol & 0xFF, 1, &fcs_out); - - /* Load packet. */ - for(p = pb; p; p = p->next) { - u16_t n = p->len; - u8_t *s = (u8_t*)p->payload; - - while (n-- > 0) { - err = pppos_output_append(pppos, err, nb, *s++, 1, &fcs_out); - } - } - - err = pppos_output_last(pppos, err, nb, &fcs_out); - if (err == ERR_OK) { - PPPDEBUG(LOG_INFO, ("pppos_netif_output[%d]: proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); - } else { - PPPDEBUG(LOG_WARNING, ("pppos_netif_output[%d]: output failed proto=0x%"X16_F", len = %d\n", ppp->netif->num, protocol, pb->tot_len)); - } - return err; -} - -static void -pppos_connect(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - -#if PPP_INPROC_IRQ_SAFE - /* input pbuf left over from last session? */ - pppos_input_free_current_packet(pppos); -#endif /* PPP_INPROC_IRQ_SAFE */ - - /* reset PPPoS control block to its initial state */ - memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); - - /* - * Default the in and out accm so that escape and flag characters - * are always escaped. - */ - pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ - pppos->out_accm[15] = 0x60; - PPPOS_PROTECT(lev); - pppos->open = 1; - PPPOS_UNPROTECT(lev); - - /* - * Start the connection and handle incoming events (packet or timeout). - */ - PPPDEBUG(LOG_INFO, ("pppos_connect: unit %d: connecting\n", ppp->netif->num)); - ppp_start(ppp); /* notify upper layers */ -} - -#if PPP_SERVER -static void -pppos_listen(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - -#if PPP_INPROC_IRQ_SAFE - /* input pbuf left over from last session? */ - pppos_input_free_current_packet(pppos); -#endif /* PPP_INPROC_IRQ_SAFE */ - - /* reset PPPoS control block to its initial state */ - memset(&pppos->last_xmit, 0, sizeof(pppos_pcb) - offsetof(pppos_pcb, last_xmit)); - - /* - * Default the in and out accm so that escape and flag characters - * are always escaped. - */ - pppos->in_accm[15] = 0x60; /* no need to protect since RX is not running */ - pppos->out_accm[15] = 0x60; - PPPOS_PROTECT(lev); - pppos->open = 1; - PPPOS_UNPROTECT(lev); - - /* - * Wait for something to happen. - */ - PPPDEBUG(LOG_INFO, ("pppos_listen: unit %d: listening\n", ppp->netif->num)); - ppp_start(ppp); /* notify upper layers */ -} -#endif /* PPP_SERVER */ - -static void -pppos_disconnect(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - - PPPOS_PROTECT(lev); - pppos->open = 0; - PPPOS_UNPROTECT(lev); - - /* If PPP_INPROC_IRQ_SAFE is used we cannot call - * pppos_input_free_current_packet() here because - * rx IRQ might still call pppos_input(). - */ -#if !PPP_INPROC_IRQ_SAFE - /* input pbuf left ? */ - pppos_input_free_current_packet(pppos); -#endif /* !PPP_INPROC_IRQ_SAFE */ - - ppp_link_end(ppp); /* notify upper layers */ -} - -static err_t -pppos_destroy(ppp_pcb *ppp, void *ctx) -{ - pppos_pcb *pppos = (pppos_pcb *)ctx; - LWIP_UNUSED_ARG(ppp); - -#if PPP_INPROC_IRQ_SAFE - /* input pbuf left ? */ - pppos_input_free_current_packet(pppos); -#endif /* PPP_INPROC_IRQ_SAFE */ - - LWIP_MEMPOOL_FREE(PPPOS_PCB, pppos); - return ERR_OK; -} - -#if !NO_SYS && !PPP_INPROC_IRQ_SAFE -/** Pass received raw characters to PPPoS to be decoded through lwIP TCPIP thread. - * - * @param ppp PPP descriptor index, returned by pppos_create() - * @param s received data - * @param l length of received data - */ -err_t -pppos_input_tcpip(ppp_pcb *ppp, u8_t *s, int l) -{ - struct pbuf *p; - err_t err; - - p = pbuf_alloc(PBUF_RAW, l, PBUF_POOL); - if (!p) { - return ERR_MEM; - } - pbuf_take(p, s, l); - - err = tcpip_inpkt(p, ppp_netif(ppp), pppos_input_sys); - if (err != ERR_OK) { - pbuf_free(p); - } - return err; -} - -/* called from TCPIP thread */ -err_t pppos_input_sys(struct pbuf *p, struct netif *inp) { - ppp_pcb *ppp = (ppp_pcb*)inp->state; - struct pbuf *n; - - for (n = p; n; n = n->next) { - pppos_input(ppp, (u8_t*)n->payload, n->len); - } - pbuf_free(p); - return ERR_OK; -} -#endif /* !NO_SYS && !PPP_INPROC_IRQ_SAFE */ - -/** PPPoS input helper struct, must be packed since it is stored - * to pbuf->payload, which might be unaligned. */ -#if PPP_INPROC_IRQ_SAFE -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct pppos_input_header { - PACK_STRUCT_FIELD(ppp_pcb *ppp); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif -#endif /* PPP_INPROC_IRQ_SAFE */ - -/** Pass received raw characters to PPPoS to be decoded. - * - * @param ppp PPP descriptor index, returned by pppos_create() - * @param s received data - * @param l length of received data - */ -void -pppos_input(ppp_pcb *ppp, u8_t *s, int l) -{ - pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb; - struct pbuf *next_pbuf; - u8_t cur_char; - u8_t escaped; - PPPOS_DECL_PROTECT(lev); - - PPPDEBUG(LOG_DEBUG, ("pppos_input[%d]: got %d bytes\n", ppp->netif->num, l)); - while (l-- > 0) { - cur_char = *s++; - - PPPOS_PROTECT(lev); - /* ppp_input can disconnect the interface, we need to abort to prevent a memory - * leak if there are remaining bytes because pppos_connect and pppos_listen - * functions expect input buffer to be free. Furthermore there are no real - * reason to continue reading bytes if we are disconnected. - */ - if (!pppos->open) { - PPPOS_UNPROTECT(lev); - return; - } - escaped = ESCAPE_P(pppos->in_accm, cur_char); - PPPOS_UNPROTECT(lev); - /* Handle special characters. */ - if (escaped) { - /* Check for escape sequences. */ - /* XXX Note that this does not handle an escaped 0x5d character which - * would appear as an escape character. Since this is an ASCII ']' - * and there is no reason that I know of to escape it, I won't complicate - * the code to handle this case. GLL */ - if (cur_char == PPP_ESCAPE) { - pppos->in_escaped = 1; - /* Check for the flag character. */ - } else if (cur_char == PPP_FLAG) { - /* If this is just an extra flag character, ignore it. */ - if (pppos->in_state <= PDADDRESS) { - /* ignore it */; - /* If we haven't received the packet header, drop what has come in. */ - } else if (pppos->in_state < PDDATA) { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Dropping incomplete packet %d\n", - ppp->netif->num, pppos->in_state)); - LINK_STATS_INC(link.lenerr); - pppos_input_drop(pppos); - /* If the fcs is invalid, drop the packet. */ - } else if (pppos->in_fcs != PPP_GOODFCS) { - PPPDEBUG(LOG_INFO, - ("pppos_input[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", - ppp->netif->num, pppos->in_fcs, pppos->in_protocol)); - /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ - LINK_STATS_INC(link.chkerr); - pppos_input_drop(pppos); - /* Otherwise it's a good packet so pass it on. */ - } else { - struct pbuf *inp; - /* Trim off the checksum. */ - if(pppos->in_tail->len > 2) { - pppos->in_tail->len -= 2; - - pppos->in_tail->tot_len = pppos->in_tail->len; - if (pppos->in_tail != pppos->in_head) { - pbuf_cat(pppos->in_head, pppos->in_tail); - } - } else { - pppos->in_tail->tot_len = pppos->in_tail->len; - if (pppos->in_tail != pppos->in_head) { - pbuf_cat(pppos->in_head, pppos->in_tail); - } - - pbuf_realloc(pppos->in_head, pppos->in_head->tot_len - 2); - } - - /* Dispatch the packet thereby consuming it. */ - inp = pppos->in_head; - /* Packet consumed, release our references. */ - pppos->in_head = NULL; - pppos->in_tail = NULL; -#if IP_FORWARD || LWIP_IPV6_FORWARD - /* hide the room for Ethernet forwarding header */ - pbuf_header(inp, -(s16_t)(PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)); -#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ -#if PPP_INPROC_IRQ_SAFE - if(tcpip_callback_with_block(pppos_input_callback, inp, 0) != ERR_OK) { - PPPDEBUG(LOG_ERR, ("pppos_input[%d]: tcpip_callback() failed, dropping packet\n", ppp->netif->num)); - pbuf_free(inp); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); - } -#else /* PPP_INPROC_IRQ_SAFE */ - ppp_input(ppp, inp); -#endif /* PPP_INPROC_IRQ_SAFE */ - } - - /* Prepare for a new packet. */ - pppos->in_fcs = PPP_INITFCS; - pppos->in_state = PDADDRESS; - pppos->in_escaped = 0; - /* Other characters are usually control characters that may have - * been inserted by the physical layer so here we just drop them. */ - } else { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Dropping ACCM char <%d>\n", ppp->netif->num, cur_char)); - } - /* Process other characters. */ - } else { - /* Unencode escaped characters. */ - if (pppos->in_escaped) { - pppos->in_escaped = 0; - cur_char ^= PPP_TRANS; - } - - /* Process character relative to current state. */ - switch(pppos->in_state) { - case PDIDLE: /* Idle state - waiting. */ - /* Drop the character if it's not 0xff - * we would have processed a flag character above. */ - if (cur_char != PPP_ALLSTATIONS) { - break; - } - /* no break */ - /* Fall through */ - - case PDSTART: /* Process start flag. */ - /* Prepare for a new packet. */ - pppos->in_fcs = PPP_INITFCS; - /* no break */ - /* Fall through */ - - case PDADDRESS: /* Process address field. */ - if (cur_char == PPP_ALLSTATIONS) { - pppos->in_state = PDCONTROL; - break; - } - /* no break */ - - /* Else assume compressed address and control fields so - * fall through to get the protocol... */ - case PDCONTROL: /* Process control field. */ - /* If we don't get a valid control code, restart. */ - if (cur_char == PPP_UI) { - pppos->in_state = PDPROTOCOL1; - break; - } - /* no break */ - -#if 0 - else { - PPPDEBUG(LOG_WARNING, - ("pppos_input[%d]: Invalid control <%d>\n", ppp->netif->num, cur_char)); - pppos->in_state = PDSTART; - } -#endif - case PDPROTOCOL1: /* Process protocol field 1. */ - /* If the lower bit is set, this is the end of the protocol - * field. */ - if (cur_char & 1) { - pppos->in_protocol = cur_char; - pppos->in_state = PDDATA; - } else { - pppos->in_protocol = (u16_t)cur_char << 8; - pppos->in_state = PDPROTOCOL2; - } - break; - case PDPROTOCOL2: /* Process protocol field 2. */ - pppos->in_protocol |= cur_char; - pppos->in_state = PDDATA; - break; - case PDDATA: /* Process data byte. */ - /* Make space to receive processed data. */ - if (pppos->in_tail == NULL || pppos->in_tail->len == PBUF_POOL_BUFSIZE) { - u16_t pbuf_alloc_len; - if (pppos->in_tail != NULL) { - pppos->in_tail->tot_len = pppos->in_tail->len; - if (pppos->in_tail != pppos->in_head) { - pbuf_cat(pppos->in_head, pppos->in_tail); - /* give up the in_tail reference now */ - pppos->in_tail = NULL; - } - } - /* If we haven't started a packet, we need a packet header. */ - pbuf_alloc_len = 0; -#if IP_FORWARD || LWIP_IPV6_FORWARD - /* If IP forwarding is enabled we are reserving PBUF_LINK_ENCAPSULATION_HLEN - * + PBUF_LINK_HLEN bytes so the packet is being allocated with enough header - * space to be forwarded (to Ethernet for example). - */ - if (pppos->in_head == NULL) { - pbuf_alloc_len = PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN; - } -#endif /* IP_FORWARD || LWIP_IPV6_FORWARD */ - next_pbuf = pbuf_alloc(PBUF_RAW, pbuf_alloc_len, PBUF_POOL); - if (next_pbuf == NULL) { - /* No free buffers. Drop the input packet and let the - * higher layers deal with it. Continue processing - * the received pbuf chain in case a new packet starts. */ - PPPDEBUG(LOG_ERR, ("pppos_input[%d]: NO FREE PBUFS!\n", ppp->netif->num)); - LINK_STATS_INC(link.memerr); - pppos_input_drop(pppos); - pppos->in_state = PDSTART; /* Wait for flag sequence. */ - break; - } - if (pppos->in_head == NULL) { - u8_t *payload = ((u8_t*)next_pbuf->payload) + pbuf_alloc_len; -#if PPP_INPROC_IRQ_SAFE - ((struct pppos_input_header*)payload)->ppp = ppp; - payload += sizeof(struct pppos_input_header); - next_pbuf->len += sizeof(struct pppos_input_header); -#endif /* PPP_INPROC_IRQ_SAFE */ - next_pbuf->len += sizeof(pppos->in_protocol); - *(payload++) = pppos->in_protocol >> 8; - *(payload) = pppos->in_protocol & 0xFF; - pppos->in_head = next_pbuf; - } - pppos->in_tail = next_pbuf; - } - /* Load character into buffer. */ - ((u8_t*)pppos->in_tail->payload)[pppos->in_tail->len++] = cur_char; - break; - default: - break; - } - - /* update the frame check sequence number. */ - pppos->in_fcs = PPP_FCS(pppos->in_fcs, cur_char); - } - } /* while (l-- > 0), all bytes processed */ -} - -#if PPP_INPROC_IRQ_SAFE -/* PPPoS input callback using one input pointer - */ -static void pppos_input_callback(void *arg) { - struct pbuf *pb = (struct pbuf*)arg; - ppp_pcb *ppp; - - ppp = ((struct pppos_input_header*)pb->payload)->ppp; - if(pbuf_header(pb, -(s16_t)sizeof(struct pppos_input_header))) { - LWIP_ASSERT("pbuf_header failed\n", 0); - goto drop; - } - - /* Dispatch the packet thereby consuming it. */ - ppp_input(ppp, pb); - return; - -drop: - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifindiscards); - pbuf_free(pb); -} -#endif /* PPP_INPROC_IRQ_SAFE */ - -static void -pppos_send_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) -{ - int i; - pppos_pcb *pppos = (pppos_pcb *)ctx; - LWIP_UNUSED_ARG(ppp); - - pppos->pcomp = pcomp; - pppos->accomp = accomp; - - /* Load the ACCM bits for the 32 control codes. */ - for (i = 0; i < 32/8; i++) { - pppos->out_accm[i] = (u8_t)((accm >> (8 * i)) & 0xFF); - } - - PPPDEBUG(LOG_INFO, ("pppos_send_config[%d]: out_accm=%X %X %X %X\n", - pppos->ppp->netif->num, - pppos->out_accm[0], pppos->out_accm[1], pppos->out_accm[2], pppos->out_accm[3])); -} - -static void -pppos_recv_config(ppp_pcb *ppp, void *ctx, u32_t accm, int pcomp, int accomp) -{ - int i; - pppos_pcb *pppos = (pppos_pcb *)ctx; - PPPOS_DECL_PROTECT(lev); - LWIP_UNUSED_ARG(ppp); - LWIP_UNUSED_ARG(pcomp); - LWIP_UNUSED_ARG(accomp); - - /* Load the ACCM bits for the 32 control codes. */ - PPPOS_PROTECT(lev); - for (i = 0; i < 32 / 8; i++) { - pppos->in_accm[i] = (u8_t)(accm >> (i * 8)); - } - PPPOS_UNPROTECT(lev); - - PPPDEBUG(LOG_INFO, ("pppos_recv_config[%d]: in_accm=%X %X %X %X\n", - pppos->ppp->netif->num, - pppos->in_accm[0], pppos->in_accm[1], pppos->in_accm[2], pppos->in_accm[3])); -} - -/* - * Drop the input packet. - */ -static void -pppos_input_free_current_packet(pppos_pcb *pppos) -{ - if (pppos->in_head != NULL) { - if (pppos->in_tail && (pppos->in_tail != pppos->in_head)) { - pbuf_free(pppos->in_tail); - } - pbuf_free(pppos->in_head); - pppos->in_head = NULL; - } - pppos->in_tail = NULL; -} - -/* - * Drop the input packet and increase error counters. - */ -static void -pppos_input_drop(pppos_pcb *pppos) -{ - if (pppos->in_head != NULL) { -#if 0 - PPPDEBUG(LOG_INFO, ("pppos_input_drop: %d:%.*H\n", pppos->in_head->len, min(60, pppos->in_head->len * 2), pppos->in_head->payload)); -#endif - PPPDEBUG(LOG_INFO, ("pppos_input_drop: pbuf len=%d, addr %p\n", pppos->in_head->len, (void*)pppos->in_head)); - } - pppos_input_free_current_packet(pppos); -#if VJ_SUPPORT - vj_uncompress_err(&pppos->ppp->vj_comp); -#endif /* VJ_SUPPORT */ - - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(pppos->ppp->netif, ifindiscards); -} - -/* - * pppos_output_append - append given character to end of given pbuf. - * If out_accm is not 0 and the character needs to be escaped, do so. - * If pbuf is full, send the pbuf and reuse it. - * Return the current pbuf. - */ -static err_t -pppos_output_append(pppos_pcb *pppos, err_t err, struct pbuf *nb, u8_t c, u8_t accm, u16_t *fcs) -{ - if (err != ERR_OK) { - return err; - } - - /* Make sure there is room for the character and an escape code. - * Sure we don't quite fill the buffer if the character doesn't - * get escaped but is one character worth complicating this? */ - if ((PBUF_POOL_BUFSIZE - nb->len) < 2) { - u32_t l = pppos->output_cb(pppos->ppp, (u8_t*)nb->payload, nb->len, pppos->ppp->ctx_cb); - if (l != nb->len) { - return ERR_IF; - } - nb->len = 0; - } - - /* Update FCS before checking for special characters. */ - if (fcs) { - *fcs = PPP_FCS(*fcs, c); - } - - /* Copy to output buffer escaping special characters. */ - if (accm && ESCAPE_P(pppos->out_accm, c)) { - *((u8_t*)nb->payload + nb->len++) = PPP_ESCAPE; - *((u8_t*)nb->payload + nb->len++) = c ^ PPP_TRANS; - } else { - *((u8_t*)nb->payload + nb->len++) = c; - } - - return ERR_OK; -} - -static err_t -pppos_output_last(pppos_pcb *pppos, err_t err, struct pbuf *nb, u16_t *fcs) -{ - ppp_pcb *ppp = pppos->ppp; - - /* Add FCS and trailing flag. */ - err = pppos_output_append(pppos, err, nb, ~(*fcs) & 0xFF, 1, NULL); - err = pppos_output_append(pppos, err, nb, (~(*fcs) >> 8) & 0xFF, 1, NULL); - err = pppos_output_append(pppos, err, nb, PPP_FLAG, 0, NULL); - - if (err != ERR_OK) { - goto failed; - } - - /* Send remaining buffer if not empty */ - if (nb->len > 0) { - u32_t l = pppos->output_cb(ppp, (u8_t*)nb->payload, nb->len, ppp->ctx_cb); - if (l != nb->len) { - err = ERR_IF; - goto failed; - } - } - - pppos->last_xmit = sys_now(); - MIB2_STATS_NETIF_ADD(ppp->netif, ifoutoctets, nb->tot_len); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutucastpkts); - LINK_STATS_INC(link.xmit); - pbuf_free(nb); - return ERR_OK; - -failed: - pppos->last_xmit = 0; /* prepend PPP_FLAG to next packet */ - LINK_STATS_INC(link.err); - LINK_STATS_INC(link.drop); - MIB2_STATS_NETIF_INC(ppp->netif, ifoutdiscards); - pbuf_free(nb); - return err; -} - -#endif /* PPP_SUPPORT && PPPOS_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/upap.c b/components/net/lwip-2.0.2/src/netif/ppp/upap.c deleted file mode 100644 index d00c2d76e5..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/upap.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * upap.c - User/Password Authentication Protocol. - * - * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The name "Carnegie Mellon University" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For permission or any legal - * details, please contact - * Office of Technology Transfer - * Carnegie Mellon University - * 5000 Forbes Avenue - * Pittsburgh, PA 15213-3890 - * (412) 268-4387, fax: (412) 268-7395 - * tech-transfer@andrew.cmu.edu - * - * 4. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Computing Services - * at Carnegie Mellon University (http://www.cmu.edu/computing/)." - * - * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE - * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -/* - * @todo: - */ - -#if 0 /* UNUSED */ -#include -#include -#endif /* UNUSED */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/upap.h" - -#if PPP_OPTIONS -/* - * Command-line options. - */ -static option_t pap_option_list[] = { - { "hide-password", o_bool, &hide_password, - "Don't output passwords to log", OPT_PRIO | 1 }, - { "show-password", o_bool, &hide_password, - "Show password string in debug log messages", OPT_PRIOSUB | 0 }, - - { "pap-restart", o_int, &upap[0].us_timeouttime, - "Set retransmit timeout for PAP", OPT_PRIO }, - { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, - "Set max number of transmissions for auth-reqs", OPT_PRIO }, - { "pap-timeout", o_int, &upap[0].us_reqtimeout, - "Set time limit for peer PAP authentication", OPT_PRIO }, - - { NULL } -}; -#endif /* PPP_OPTIONS */ - -/* - * Protocol entry points. - */ -static void upap_init(ppp_pcb *pcb); -static void upap_lowerup(ppp_pcb *pcb); -static void upap_lowerdown(ppp_pcb *pcb); -static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l); -static void upap_protrej(ppp_pcb *pcb); -#if PRINTPKT_SUPPORT -static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg); -#endif /* PRINTPKT_SUPPORT */ - -const struct protent pap_protent = { - PPP_PAP, - upap_init, - upap_input, - upap_protrej, - upap_lowerup, - upap_lowerdown, - NULL, - NULL, -#if PRINTPKT_SUPPORT - upap_printpkt, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_DATAINPUT - NULL, -#endif /* PPP_DATAINPUT */ -#if PRINTPKT_SUPPORT - "PAP", - NULL, -#endif /* PRINTPKT_SUPPORT */ -#if PPP_OPTIONS - pap_option_list, - NULL, -#endif /* PPP_OPTIONS */ -#if DEMAND_SUPPORT - NULL, - NULL -#endif /* DEMAND_SUPPORT */ -}; - -static void upap_timeout(void *arg); -#if PPP_SERVER -static void upap_reqtimeout(void *arg); -static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len); -#endif /* PPP_SERVER */ -static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len); -static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len); -static void upap_sauthreq(ppp_pcb *pcb); -#if PPP_SERVER -static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen); -#endif /* PPP_SERVER */ - - -/* - * upap_init - Initialize a UPAP unit. - */ -static void upap_init(ppp_pcb *pcb) { - pcb->upap.us_user = NULL; - pcb->upap.us_userlen = 0; - pcb->upap.us_passwd = NULL; - pcb->upap.us_passwdlen = 0; - pcb->upap.us_clientstate = UPAPCS_INITIAL; -#if PPP_SERVER - pcb->upap.us_serverstate = UPAPSS_INITIAL; -#endif /* PPP_SERVER */ - pcb->upap.us_id = 0; -} - - -/* - * upap_authwithpeer - Authenticate us with our peer (start client). - * - * Set new state and send authenticate's. - */ -void upap_authwithpeer(ppp_pcb *pcb, const char *user, const char *password) { - - if(!user || !password) - return; - - /* Save the username and password we're given */ - pcb->upap.us_user = user; - pcb->upap.us_userlen = LWIP_MIN(strlen(user), 0xff); - pcb->upap.us_passwd = password; - pcb->upap.us_passwdlen = LWIP_MIN(strlen(password), 0xff); - pcb->upap.us_transmits = 0; - - /* Lower layer up yet? */ - if (pcb->upap.us_clientstate == UPAPCS_INITIAL || - pcb->upap.us_clientstate == UPAPCS_PENDING) { - pcb->upap.us_clientstate = UPAPCS_PENDING; - return; - } - - upap_sauthreq(pcb); /* Start protocol */ -} - -#if PPP_SERVER -/* - * upap_authpeer - Authenticate our peer (start server). - * - * Set new state. - */ -void upap_authpeer(ppp_pcb *pcb) { - - /* Lower layer up yet? */ - if (pcb->upap.us_serverstate == UPAPSS_INITIAL || - pcb->upap.us_serverstate == UPAPSS_PENDING) { - pcb->upap.us_serverstate = UPAPSS_PENDING; - return; - } - - pcb->upap.us_serverstate = UPAPSS_LISTEN; - if (pcb->settings.pap_req_timeout > 0) - TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); -} -#endif /* PPP_SERVER */ - -/* - * upap_timeout - Retransmission timer for sending auth-reqs expired. - */ -static void upap_timeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) - return; - - if (pcb->upap.us_transmits >= pcb->settings.pap_max_transmits) { - /* give up in disgust */ - ppp_error("No response to PAP authenticate-requests"); - pcb->upap.us_clientstate = UPAPCS_BADAUTH; - auth_withpeer_fail(pcb, PPP_PAP); - return; - } - - upap_sauthreq(pcb); /* Send Authenticate-Request */ -} - - -#if PPP_SERVER -/* - * upap_reqtimeout - Give up waiting for the peer to send an auth-req. - */ -static void upap_reqtimeout(void *arg) { - ppp_pcb *pcb = (ppp_pcb*)arg; - - if (pcb->upap.us_serverstate != UPAPSS_LISTEN) - return; /* huh?? */ - - auth_peer_fail(pcb, PPP_PAP); - pcb->upap.us_serverstate = UPAPSS_BADAUTH; -} -#endif /* PPP_SERVER */ - - -/* - * upap_lowerup - The lower layer is up. - * - * Start authenticating if pending. - */ -static void upap_lowerup(ppp_pcb *pcb) { - - if (pcb->upap.us_clientstate == UPAPCS_INITIAL) - pcb->upap.us_clientstate = UPAPCS_CLOSED; - else if (pcb->upap.us_clientstate == UPAPCS_PENDING) { - upap_sauthreq(pcb); /* send an auth-request */ - } - -#if PPP_SERVER - if (pcb->upap.us_serverstate == UPAPSS_INITIAL) - pcb->upap.us_serverstate = UPAPSS_CLOSED; - else if (pcb->upap.us_serverstate == UPAPSS_PENDING) { - pcb->upap.us_serverstate = UPAPSS_LISTEN; - if (pcb->settings.pap_req_timeout > 0) - TIMEOUT(upap_reqtimeout, pcb, pcb->settings.pap_req_timeout); - } -#endif /* PPP_SERVER */ -} - - -/* - * upap_lowerdown - The lower layer is down. - * - * Cancel all timeouts. - */ -static void upap_lowerdown(ppp_pcb *pcb) { - - if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ - UNTIMEOUT(upap_timeout, pcb); /* Cancel timeout */ -#if PPP_SERVER - if (pcb->upap.us_serverstate == UPAPSS_LISTEN && pcb->settings.pap_req_timeout > 0) - UNTIMEOUT(upap_reqtimeout, pcb); -#endif /* PPP_SERVER */ - - pcb->upap.us_clientstate = UPAPCS_INITIAL; -#if PPP_SERVER - pcb->upap.us_serverstate = UPAPSS_INITIAL; -#endif /* PPP_SERVER */ -} - - -/* - * upap_protrej - Peer doesn't speak this protocol. - * - * This shouldn't happen. In any case, pretend lower layer went down. - */ -static void upap_protrej(ppp_pcb *pcb) { - - if (pcb->upap.us_clientstate == UPAPCS_AUTHREQ) { - ppp_error("PAP authentication failed due to protocol-reject"); - auth_withpeer_fail(pcb, PPP_PAP); - } -#if PPP_SERVER - if (pcb->upap.us_serverstate == UPAPSS_LISTEN) { - ppp_error("PAP authentication of peer failed (protocol-reject)"); - auth_peer_fail(pcb, PPP_PAP); - } -#endif /* PPP_SERVER */ - upap_lowerdown(pcb); -} - - -/* - * upap_input - Input UPAP packet. - */ -static void upap_input(ppp_pcb *pcb, u_char *inpacket, int l) { - u_char *inp; - u_char code, id; - int len; - - /* - * Parse header (code, id and length). - * If packet too short, drop it. - */ - inp = inpacket; - if (l < UPAP_HEADERLEN) { - UPAPDEBUG(("pap_input: rcvd short header.")); - return; - } - GETCHAR(code, inp); - GETCHAR(id, inp); - GETSHORT(len, inp); - if (len < UPAP_HEADERLEN) { - UPAPDEBUG(("pap_input: rcvd illegal length.")); - return; - } - if (len > l) { - UPAPDEBUG(("pap_input: rcvd short packet.")); - return; - } - len -= UPAP_HEADERLEN; - - /* - * Action depends on code. - */ - switch (code) { - case UPAP_AUTHREQ: -#if PPP_SERVER - upap_rauthreq(pcb, inp, id, len); -#endif /* PPP_SERVER */ - break; - - case UPAP_AUTHACK: - upap_rauthack(pcb, inp, id, len); - break; - - case UPAP_AUTHNAK: - upap_rauthnak(pcb, inp, id, len); - break; - - default: /* XXX Need code reject */ - break; - } -} - -#if PPP_SERVER -/* - * upap_rauth - Receive Authenticate. - */ -static void upap_rauthreq(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char ruserlen, rpasswdlen; - char *ruser; - char *rpasswd; - char rhostname[256]; - int retcode; - const char *msg; - int msglen; - - if (pcb->upap.us_serverstate < UPAPSS_LISTEN) - return; - - /* - * If we receive a duplicate authenticate-request, we are - * supposed to return the same status as for the first request. - */ - if (pcb->upap.us_serverstate == UPAPSS_OPEN) { - upap_sresp(pcb, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ - return; - } - if (pcb->upap.us_serverstate == UPAPSS_BADAUTH) { - upap_sresp(pcb, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ - return; - } - - /* - * Parse user/passwd. - */ - if (len < 1) { - UPAPDEBUG(("pap_rauth: rcvd short packet.")); - return; - } - GETCHAR(ruserlen, inp); - len -= sizeof (u_char) + ruserlen + sizeof (u_char); - if (len < 0) { - UPAPDEBUG(("pap_rauth: rcvd short packet.")); - return; - } - ruser = (char *) inp; - INCPTR(ruserlen, inp); - GETCHAR(rpasswdlen, inp); - if (len < rpasswdlen) { - UPAPDEBUG(("pap_rauth: rcvd short packet.")); - return; - } - - rpasswd = (char *) inp; - - /* - * Check the username and password given. - */ - retcode = UPAP_AUTHNAK; - if (auth_check_passwd(pcb, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen)) { - retcode = UPAP_AUTHACK; - } - BZERO(rpasswd, rpasswdlen); - -#if 0 /* UNUSED */ - /* - * Check remote number authorization. A plugin may have filled in - * the remote number or added an allowed number, and rather than - * return an authenticate failure, is leaving it for us to verify. - */ - if (retcode == UPAP_AUTHACK) { - if (!auth_number()) { - /* We do not want to leak info about the pap result. */ - retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ - warn("calling number %q is not authorized", remote_number); - } - } - - msglen = strlen(msg); - if (msglen > 255) - msglen = 255; -#endif /* UNUSED */ - - upap_sresp(pcb, retcode, id, msg, msglen); - - /* Null terminate and clean remote name. */ - ppp_slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); - - if (retcode == UPAP_AUTHACK) { - pcb->upap.us_serverstate = UPAPSS_OPEN; - ppp_notice("PAP peer authentication succeeded for %q", rhostname); - auth_peer_success(pcb, PPP_PAP, 0, ruser, ruserlen); - } else { - pcb->upap.us_serverstate = UPAPSS_BADAUTH; - ppp_warn("PAP peer authentication failed for %q", rhostname); - auth_peer_fail(pcb, PPP_PAP); - } - - if (pcb->settings.pap_req_timeout > 0) - UNTIMEOUT(upap_reqtimeout, pcb); -} -#endif /* PPP_SERVER */ - -/* - * upap_rauthack - Receive Authenticate-Ack. - */ -static void upap_rauthack(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char msglen; - char *msg; - LWIP_UNUSED_ARG(id); - - if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ - return; - - /* - * Parse message. - */ - if (len < 1) { - UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); - } else { - GETCHAR(msglen, inp); - if (msglen > 0) { - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG(("pap_rauthack: rcvd short packet.")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - } - } - - pcb->upap.us_clientstate = UPAPCS_OPEN; - - auth_withpeer_success(pcb, PPP_PAP, 0); -} - - -/* - * upap_rauthnak - Receive Authenticate-Nak. - */ -static void upap_rauthnak(ppp_pcb *pcb, u_char *inp, int id, int len) { - u_char msglen; - char *msg; - LWIP_UNUSED_ARG(id); - - if (pcb->upap.us_clientstate != UPAPCS_AUTHREQ) /* XXX */ - return; - - /* - * Parse message. - */ - if (len < 1) { - UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); - } else { - GETCHAR(msglen, inp); - if (msglen > 0) { - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - } - } - - pcb->upap.us_clientstate = UPAPCS_BADAUTH; - - ppp_error("PAP authentication failed"); - auth_withpeer_fail(pcb, PPP_PAP); -} - - -/* - * upap_sauthreq - Send an Authenticate-Request. - */ -static void upap_sauthreq(ppp_pcb *pcb) { - struct pbuf *p; - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + - pcb->upap.us_userlen + pcb->upap.us_passwdlen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(UPAP_AUTHREQ, outp); - PUTCHAR(++pcb->upap.us_id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(pcb->upap.us_userlen, outp); - MEMCPY(outp, pcb->upap.us_user, pcb->upap.us_userlen); - INCPTR(pcb->upap.us_userlen, outp); - PUTCHAR(pcb->upap.us_passwdlen, outp); - MEMCPY(outp, pcb->upap.us_passwd, pcb->upap.us_passwdlen); - - ppp_write(pcb, p); - - TIMEOUT(upap_timeout, pcb, pcb->settings.pap_timeout_time); - ++pcb->upap.us_transmits; - pcb->upap.us_clientstate = UPAPCS_AUTHREQ; -} - -#if PPP_SERVER -/* - * upap_sresp - Send a response (ack or nak). - */ -static void upap_sresp(ppp_pcb *pcb, u_char code, u_char id, const char *msg, int msglen) { - struct pbuf *p; - u_char *outp; - int outlen; - - outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; - p = pbuf_alloc(PBUF_RAW, (u16_t)(PPP_HDRLEN +outlen), PPP_CTRL_PBUF_TYPE); - if(NULL == p) - return; - if(p->tot_len != p->len) { - pbuf_free(p); - return; - } - - outp = (u_char*)p->payload; - MAKEHEADER(outp, PPP_PAP); - - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - PUTCHAR(msglen, outp); - MEMCPY(outp, msg, msglen); - - ppp_write(pcb, p); -} -#endif /* PPP_SERVER */ - -#if PRINTPKT_SUPPORT -/* - * upap_printpkt - print the contents of a PAP packet. - */ -static const char* const upap_codenames[] = { - "AuthReq", "AuthAck", "AuthNak" -}; - -static int upap_printpkt(const u_char *p, int plen, void (*printer) (void *, const char *, ...), void *arg) { - int code, id, len; - int mlen, ulen, wlen; - const u_char *user, *pwd, *msg; - const u_char *pstart; - - if (plen < UPAP_HEADERLEN) - return 0; - pstart = p; - GETCHAR(code, p); - GETCHAR(id, p); - GETSHORT(len, p); - if (len < UPAP_HEADERLEN || len > plen) - return 0; - - if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(upap_codenames)) - printer(arg, " %s", upap_codenames[code-1]); - else - printer(arg, " code=0x%x", code); - printer(arg, " id=0x%x", id); - len -= UPAP_HEADERLEN; - switch (code) { - case UPAP_AUTHREQ: - if (len < 1) - break; - ulen = p[0]; - if (len < ulen + 2) - break; - wlen = p[ulen + 1]; - if (len < ulen + wlen + 2) - break; - user = (const u_char *) (p + 1); - pwd = (const u_char *) (p + ulen + 2); - p += ulen + wlen + 2; - len -= ulen + wlen + 2; - printer(arg, " user="); - ppp_print_string(user, ulen, printer, arg); - printer(arg, " password="); -/* FIXME: require ppp_pcb struct as printpkt() argument */ -#if 0 - if (!pcb->settings.hide_password) -#endif - ppp_print_string(pwd, wlen, printer, arg); -#if 0 - else - printer(arg, ""); -#endif - break; - case UPAP_AUTHACK: - case UPAP_AUTHNAK: - if (len < 1) - break; - mlen = p[0]; - if (len < mlen + 1) - break; - msg = (const u_char *) (p + 1); - p += mlen + 1; - len -= mlen + 1; - printer(arg, " "); - ppp_print_string(msg, mlen, printer, arg); - break; - default: - break; - } - - /* print the rest of the bytes in the packet */ - for (; len > 0; --len) { - GETCHAR(code, p); - printer(arg, " %.2x", code); - } - - return p - pstart; -} -#endif /* PRINTPKT_SUPPORT */ - -#endif /* PPP_SUPPORT && PAP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/utils.c b/components/net/lwip-2.0.2/src/netif/ppp/utils.c deleted file mode 100644 index 008c63375a..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/utils.c +++ /dev/null @@ -1,959 +0,0 @@ -/* - * utils.c - various utility functions used in pppd. - * - * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. The name(s) of the authors of this software must not be used to - * endorse or promote products derived from this software without - * prior written permission. - * - * 3. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by Paul Mackerras - * ". - * - * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#if 0 /* UNUSED */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef SVR4 -#include -#endif -#endif /* UNUSED */ - -#include /* isdigit() */ - -#include "netif/ppp/ppp_impl.h" - -#include "netif/ppp/fsm.h" -#include "netif/ppp/lcp.h" - -#if defined(SUNOS4) -extern char *strerror(); -#endif - -static void ppp_logit(int level, const char *fmt, va_list args); -static void ppp_log_write(int level, char *buf); -#if PRINTPKT_SUPPORT -static void ppp_vslp_printer(void *arg, const char *fmt, ...); -static void ppp_format_packet(const u_char *p, int len, - void (*printer) (void *, const char *, ...), void *arg); - -struct buffer_info { - char *ptr; - int len; -}; -#endif /* PRINTPKT_SUPPORT */ - -/* - * ppp_strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, - * always leaves destination null-terminated (for len > 0). - */ -size_t ppp_strlcpy(char *dest, const char *src, size_t len) { - size_t ret = strlen(src); - - if (len != 0) { - if (ret < len) - strcpy(dest, src); - else { - strncpy(dest, src, len - 1); - dest[len-1] = 0; - } - } - return ret; -} - -/* - * ppp_strlcat - like strcat/strncat, doesn't overflow destination buffer, - * always leaves destination null-terminated (for len > 0). - */ -size_t ppp_strlcat(char *dest, const char *src, size_t len) { - size_t dlen = strlen(dest); - - return dlen + ppp_strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); -} - - -/* - * ppp_slprintf - format a message into a buffer. Like sprintf except we - * also specify the length of the output buffer, and we handle - * %m (error message), %v (visible string), - * %q (quoted string), %t (current time) and %I (IP address) formats. - * Doesn't do floating-point formats. - * Returns the number of chars put into buf. - */ -int ppp_slprintf(char *buf, int buflen, const char *fmt, ...) { - va_list args; - int n; - - va_start(args, fmt); - n = ppp_vslprintf(buf, buflen, fmt, args); - va_end(args); - return n; -} - -/* - * ppp_vslprintf - like ppp_slprintf, takes a va_list instead of a list of args. - */ -#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) - -int ppp_vslprintf(char *buf, int buflen, const char *fmt, va_list args) { - int c, i, n; - int width, prec, fillch; - int base, len, neg, quoted; - unsigned long val = 0; - const char *f; - char *str, *buf0; - const unsigned char *p; - char num[32]; -#if 0 /* need port */ - time_t t; -#endif /* need port */ - u32_t ip; - static char hexchars[] = "0123456789abcdef"; -#if PRINTPKT_SUPPORT - struct buffer_info bufinfo; -#endif /* PRINTPKT_SUPPORT */ - - buf0 = buf; - --buflen; - while (buflen > 0) { - for (f = fmt; *f != '%' && *f != 0; ++f) - ; - if (f > fmt) { - len = f - fmt; - if (len > buflen) - len = buflen; - memcpy(buf, fmt, len); - buf += len; - buflen -= len; - fmt = f; - } - if (*fmt == 0) - break; - c = *++fmt; - width = 0; - prec = -1; - fillch = ' '; - if (c == '0') { - fillch = '0'; - c = *++fmt; - } - if (c == '*') { - width = va_arg(args, int); - c = *++fmt; - } else { - while (isdigit(c)) { - width = width * 10 + c - '0'; - c = *++fmt; - } - } - if (c == '.') { - c = *++fmt; - if (c == '*') { - prec = va_arg(args, int); - c = *++fmt; - } else { - prec = 0; - while (isdigit(c)) { - prec = prec * 10 + c - '0'; - c = *++fmt; - } - } - } - str = 0; - base = 0; - neg = 0; - ++fmt; - switch (c) { - case 'l': - c = *fmt++; - switch (c) { - case 'd': - val = va_arg(args, long); - if ((long)val < 0) { - neg = 1; - val = (unsigned long)-(long)val; - } - base = 10; - break; - case 'u': - val = va_arg(args, unsigned long); - base = 10; - break; - default: - OUTCHAR('%'); - OUTCHAR('l'); - --fmt; /* so %lz outputs %lz etc. */ - continue; - } - break; - case 'd': - i = va_arg(args, int); - if (i < 0) { - neg = 1; - val = -i; - } else - val = i; - base = 10; - break; - case 'u': - val = va_arg(args, unsigned int); - base = 10; - break; - case 'o': - val = va_arg(args, unsigned int); - base = 8; - break; - case 'x': - case 'X': - val = va_arg(args, unsigned int); - base = 16; - break; -#if 0 /* unused (and wrong on LLP64 systems) */ - case 'p': - val = (unsigned long) va_arg(args, void *); - base = 16; - neg = 2; - break; -#endif /* unused (and wrong on LLP64 systems) */ - case 's': - str = va_arg(args, char *); - break; - case 'c': - num[0] = va_arg(args, int); - num[1] = 0; - str = num; - break; -#if 0 /* do we always have strerror() in embedded ? */ - case 'm': - str = strerror(errno); - break; -#endif /* do we always have strerror() in embedded ? */ - case 'I': - ip = va_arg(args, u32_t); - ip = lwip_ntohl(ip); - ppp_slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, - (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); - str = num; - break; -#if 0 /* need port */ - case 't': - time(&t); - str = ctime(&t); - str += 4; /* chop off the day name */ - str[15] = 0; /* chop off year and newline */ - break; -#endif /* need port */ - case 'v': /* "visible" string */ - case 'q': /* quoted string */ - quoted = c == 'q'; - p = va_arg(args, unsigned char *); - if (p == NULL) - p = (const unsigned char *)""; - if (fillch == '0' && prec >= 0) { - n = prec; - } else { - n = strlen((const char *)p); - if (prec >= 0 && n > prec) - n = prec; - } - while (n > 0 && buflen > 0) { - c = *p++; - --n; - if (!quoted && c >= 0x80) { - OUTCHAR('M'); - OUTCHAR('-'); - c -= 0x80; - } - if (quoted && (c == '"' || c == '\\')) - OUTCHAR('\\'); - if (c < 0x20 || (0x7f <= c && c < 0xa0)) { - if (quoted) { - OUTCHAR('\\'); - switch (c) { - case '\t': OUTCHAR('t'); break; - case '\n': OUTCHAR('n'); break; - case '\b': OUTCHAR('b'); break; - case '\f': OUTCHAR('f'); break; - default: - OUTCHAR('x'); - OUTCHAR(hexchars[c >> 4]); - OUTCHAR(hexchars[c & 0xf]); - } - } else { - if (c == '\t') - OUTCHAR(c); - else { - OUTCHAR('^'); - OUTCHAR(c ^ 0x40); - } - } - } else - OUTCHAR(c); - } - continue; -#if PRINTPKT_SUPPORT - case 'P': /* print PPP packet */ - bufinfo.ptr = buf; - bufinfo.len = buflen + 1; - p = va_arg(args, unsigned char *); - n = va_arg(args, int); - ppp_format_packet(p, n, ppp_vslp_printer, &bufinfo); - buf = bufinfo.ptr; - buflen = bufinfo.len - 1; - continue; -#endif /* PRINTPKT_SUPPORT */ - case 'B': - p = va_arg(args, unsigned char *); - for (n = prec; n > 0; --n) { - c = *p++; - if (fillch == ' ') - OUTCHAR(' '); - OUTCHAR(hexchars[(c >> 4) & 0xf]); - OUTCHAR(hexchars[c & 0xf]); - } - continue; - default: - *buf++ = '%'; - if (c != '%') - --fmt; /* so %z outputs %z etc. */ - --buflen; - continue; - } - if (base != 0) { - str = num + sizeof(num); - *--str = 0; - while (str > num + neg) { - *--str = hexchars[val % base]; - val = val / base; - if (--prec <= 0 && val == 0) - break; - } - switch (neg) { - case 1: - *--str = '-'; - break; - case 2: - *--str = 'x'; - *--str = '0'; - break; - default: - break; - } - len = num + sizeof(num) - 1 - str; - } else { - len = strlen(str); - if (prec >= 0 && len > prec) - len = prec; - } - if (width > 0) { - if (width > buflen) - width = buflen; - if ((n = width - len) > 0) { - buflen -= n; - for (; n > 0; --n) - *buf++ = fillch; - } - } - if (len > buflen) - len = buflen; - memcpy(buf, str, len); - buf += len; - buflen -= len; - } - *buf = 0; - return buf - buf0; -} - -#if PRINTPKT_SUPPORT -/* - * vslp_printer - used in processing a %P format - */ -static void ppp_vslp_printer(void *arg, const char *fmt, ...) { - int n; - va_list pvar; - struct buffer_info *bi; - - va_start(pvar, fmt); - bi = (struct buffer_info *) arg; - n = ppp_vslprintf(bi->ptr, bi->len, fmt, pvar); - va_end(pvar); - - bi->ptr += n; - bi->len -= n; -} -#endif /* PRINTPKT_SUPPORT */ - -#if 0 /* UNUSED */ -/* - * log_packet - format a packet and log it. - */ - -void -log_packet(p, len, prefix, level) - u_char *p; - int len; - char *prefix; - int level; -{ - init_pr_log(prefix, level); - ppp_format_packet(p, len, pr_log, &level); - end_pr_log(); -} -#endif /* UNUSED */ - -#if PRINTPKT_SUPPORT -/* - * ppp_format_packet - make a readable representation of a packet, - * calling `printer(arg, format, ...)' to output it. - */ -static void ppp_format_packet(const u_char *p, int len, - void (*printer) (void *, const char *, ...), void *arg) { - int i, n; - u_short proto; - const struct protent *protp; - - if (len >= 2) { - GETSHORT(proto, p); - len -= 2; - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (proto == protp->protocol) - break; - if (protp != NULL) { - printer(arg, "[%s", protp->name); - n = (*protp->printpkt)(p, len, printer, arg); - printer(arg, "]"); - p += n; - len -= n; - } else { - for (i = 0; (protp = protocols[i]) != NULL; ++i) - if (proto == (protp->protocol & ~0x8000)) - break; - if (protp != 0 && protp->data_name != 0) { - printer(arg, "[%s data]", protp->data_name); - if (len > 8) - printer(arg, "%.8B ...", p); - else - printer(arg, "%.*B", len, p); - len = 0; - } else - printer(arg, "[proto=0x%x]", proto); - } - } - - if (len > 32) - printer(arg, "%.32B ...", p); - else - printer(arg, "%.*B", len, p); -} -#endif /* PRINTPKT_SUPPORT */ - -#if 0 /* UNUSED */ -/* - * init_pr_log, end_pr_log - initialize and finish use of pr_log. - */ - -static char line[256]; /* line to be logged accumulated here */ -static char *linep; /* current pointer within line */ -static int llevel; /* level for logging */ - -void -init_pr_log(prefix, level) - const char *prefix; - int level; -{ - linep = line; - if (prefix != NULL) { - ppp_strlcpy(line, prefix, sizeof(line)); - linep = line + strlen(line); - } - llevel = level; -} - -void -end_pr_log() -{ - if (linep != line) { - *linep = 0; - ppp_log_write(llevel, line); - } -} - -/* - * pr_log - printer routine for outputting to log - */ -void -pr_log (void *arg, const char *fmt, ...) -{ - int l, n; - va_list pvar; - char *p, *eol; - char buf[256]; - - va_start(pvar, fmt); - n = ppp_vslprintf(buf, sizeof(buf), fmt, pvar); - va_end(pvar); - - p = buf; - eol = strchr(buf, '\n'); - if (linep != line) { - l = (eol == NULL)? n: eol - buf; - if (linep + l < line + sizeof(line)) { - if (l > 0) { - memcpy(linep, buf, l); - linep += l; - } - if (eol == NULL) - return; - p = eol + 1; - eol = strchr(p, '\n'); - } - *linep = 0; - ppp_log_write(llevel, line); - linep = line; - } - - while (eol != NULL) { - *eol = 0; - ppp_log_write(llevel, p); - p = eol + 1; - eol = strchr(p, '\n'); - } - - /* assumes sizeof(buf) <= sizeof(line) */ - l = buf + n - p; - if (l > 0) { - memcpy(line, p, n); - linep = line + l; - } -} -#endif /* UNUSED */ - -/* - * ppp_print_string - print a readable representation of a string using - * printer. - */ -void ppp_print_string(const u_char *p, int len, void (*printer) (void *, const char *, ...), void *arg) { - int c; - - printer(arg, "\""); - for (; len > 0; --len) { - c = *p++; - if (' ' <= c && c <= '~') { - if (c == '\\' || c == '"') - printer(arg, "\\"); - printer(arg, "%c", c); - } else { - switch (c) { - case '\n': - printer(arg, "\\n"); - break; - case '\r': - printer(arg, "\\r"); - break; - case '\t': - printer(arg, "\\t"); - break; - default: - printer(arg, "\\%.3o", (u8_t)c); - /* no break */ - } - } - } - printer(arg, "\""); -} - -/* - * ppp_logit - does the hard work for fatal et al. - */ -static void ppp_logit(int level, const char *fmt, va_list args) { - char buf[1024]; - - ppp_vslprintf(buf, sizeof(buf), fmt, args); - ppp_log_write(level, buf); -} - -static void ppp_log_write(int level, char *buf) { - LWIP_UNUSED_ARG(level); /* necessary if PPPDEBUG is defined to an empty function */ - LWIP_UNUSED_ARG(buf); - PPPDEBUG(level, ("%s\n", buf) ); -#if 0 - if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { - int n = strlen(buf); - - if (n > 0 && buf[n-1] == '\n') - --n; - if (write(log_to_fd, buf, n) != n - || write(log_to_fd, "\n", 1) != 1) - log_to_fd = -1; - } -#endif -} - -/* - * ppp_fatal - log an error message and die horribly. - */ -void ppp_fatal(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_ERR, fmt, pvar); - va_end(pvar); - - LWIP_ASSERT("ppp_fatal", 0); /* as promised */ -} - -/* - * ppp_error - log an error message. - */ -void ppp_error(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_ERR, fmt, pvar); - va_end(pvar); -#if 0 /* UNUSED */ - ++error_count; -#endif /* UNUSED */ -} - -/* - * ppp_warn - log a warning message. - */ -void ppp_warn(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_WARNING, fmt, pvar); - va_end(pvar); -} - -/* - * ppp_notice - log a notice-level message. - */ -void ppp_notice(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_NOTICE, fmt, pvar); - va_end(pvar); -} - -/* - * ppp_info - log an informational message. - */ -void ppp_info(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_INFO, fmt, pvar); - va_end(pvar); -} - -/* - * ppp_dbglog - log a debug message. - */ -void ppp_dbglog(const char *fmt, ...) { - va_list pvar; - - va_start(pvar, fmt); - ppp_logit(LOG_DEBUG, fmt, pvar); - va_end(pvar); -} - -#if PRINTPKT_SUPPORT -/* - * ppp_dump_packet - print out a packet in readable form if it is interesting. - * Assumes len >= PPP_HDRLEN. - */ -void ppp_dump_packet(ppp_pcb *pcb, const char *tag, unsigned char *p, int len) { - int proto; - - /* - * don't print data packets, i.e. IPv4, IPv6, VJ, and compressed packets. - */ - proto = (p[0] << 8) + p[1]; - if (proto < 0xC000 && (proto & ~0x8000) == proto) - return; - - /* - * don't print valid LCP echo request/reply packets if the link is up. - */ - if (proto == PPP_LCP && pcb->phase == PPP_PHASE_RUNNING && len >= 2 + HEADERLEN) { - unsigned char *lcp = p + 2; - int l = (lcp[2] << 8) + lcp[3]; - - if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP) - && l >= HEADERLEN && l <= len - 2) - return; - } - - ppp_dbglog("%s %P", tag, p, len); -} -#endif /* PRINTPKT_SUPPORT */ - -#if 0 /* Unused */ - -/* - * complete_read - read a full `count' bytes from fd, - * unless end-of-file or an error other than EINTR is encountered. - */ -ssize_t -complete_read(int fd, void *buf, size_t count) -{ - size_t done; - ssize_t nb; - char *ptr = buf; - - for (done = 0; done < count; ) { - nb = read(fd, ptr, count - done); - if (nb < 0) { - if (errno == EINTR) - continue; - return -1; - } - if (nb == 0) - break; - done += nb; - ptr += nb; - } - return done; -} - -/* Procedures for locking the serial device using a lock file. */ -#ifndef LOCK_DIR -#ifdef __linux__ -#define LOCK_DIR "/var/lock" -#else -#ifdef SVR4 -#define LOCK_DIR "/var/spool/locks" -#else -#define LOCK_DIR "/var/spool/lock" -#endif -#endif -#endif /* LOCK_DIR */ - -static char lock_file[MAXPATHLEN]; - -/* - * lock - create a lock file for the named device - */ -int -lock(dev) - char *dev; -{ -#ifdef LOCKLIB - int result; - - result = mklock (dev, (void *) 0); - if (result == 0) { - ppp_strlcpy(lock_file, dev, sizeof(lock_file)); - return 0; - } - - if (result > 0) - ppp_notice("Device %s is locked by pid %d", dev, result); - else - ppp_error("Can't create lock file %s", lock_file); - return -1; - -#else /* LOCKLIB */ - - char lock_buffer[12]; - int fd, pid, n; - -#ifdef SVR4 - struct stat sbuf; - - if (stat(dev, &sbuf) < 0) { - ppp_error("Can't get device number for %s: %m", dev); - return -1; - } - if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { - ppp_error("Can't lock %s: not a character device", dev); - return -1; - } - ppp_slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", - LOCK_DIR, major(sbuf.st_dev), - major(sbuf.st_rdev), minor(sbuf.st_rdev)); -#else - char *p; - char lockdev[MAXPATHLEN]; - - if ((p = strstr(dev, "dev/")) != NULL) { - dev = p + 4; - strncpy(lockdev, dev, MAXPATHLEN-1); - lockdev[MAXPATHLEN-1] = 0; - while ((p = strrchr(lockdev, '/')) != NULL) { - *p = '_'; - } - dev = lockdev; - } else - if ((p = strrchr(dev, '/')) != NULL) - dev = p + 1; - - ppp_slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); -#endif - - while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { - if (errno != EEXIST) { - ppp_error("Can't create lock file %s: %m", lock_file); - break; - } - - /* Read the lock file to find out who has the device locked. */ - fd = open(lock_file, O_RDONLY, 0); - if (fd < 0) { - if (errno == ENOENT) /* This is just a timing problem. */ - continue; - ppp_error("Can't open existing lock file %s: %m", lock_file); - break; - } -#ifndef LOCK_BINARY - n = read(fd, lock_buffer, 11); -#else - n = read(fd, &pid, sizeof(pid)); -#endif /* LOCK_BINARY */ - close(fd); - fd = -1; - if (n <= 0) { - ppp_error("Can't read pid from lock file %s", lock_file); - break; - } - - /* See if the process still exists. */ -#ifndef LOCK_BINARY - lock_buffer[n] = 0; - pid = atoi(lock_buffer); -#endif /* LOCK_BINARY */ - if (pid == getpid()) - return 1; /* somebody else locked it for us */ - if (pid == 0 - || (kill(pid, 0) == -1 && errno == ESRCH)) { - if (unlink (lock_file) == 0) { - ppp_notice("Removed stale lock on %s (pid %d)", dev, pid); - continue; - } - ppp_warn("Couldn't remove stale lock on %s", dev); - } else - ppp_notice("Device %s is locked by pid %d", dev, pid); - break; - } - - if (fd < 0) { - lock_file[0] = 0; - return -1; - } - - pid = getpid(); -#ifndef LOCK_BINARY - ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); - write (fd, lock_buffer, 11); -#else - write(fd, &pid, sizeof (pid)); -#endif - close(fd); - return 0; - -#endif -} - -/* - * relock - called to update our lockfile when we are about to detach, - * thus changing our pid (we fork, the child carries on, and the parent dies). - * Note that this is called by the parent, with pid equal to the pid - * of the child. This avoids a potential race which would exist if - * we had the child rewrite the lockfile (the parent might die first, - * and another process could think the lock was stale if it checked - * between when the parent died and the child rewrote the lockfile). - */ -int -relock(pid) - int pid; -{ -#ifdef LOCKLIB - /* XXX is there a way to do this? */ - return -1; -#else /* LOCKLIB */ - - int fd; - char lock_buffer[12]; - - if (lock_file[0] == 0) - return -1; - fd = open(lock_file, O_WRONLY, 0); - if (fd < 0) { - ppp_error("Couldn't reopen lock file %s: %m", lock_file); - lock_file[0] = 0; - return -1; - } - -#ifndef LOCK_BINARY - ppp_slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); - write (fd, lock_buffer, 11); -#else - write(fd, &pid, sizeof(pid)); -#endif /* LOCK_BINARY */ - close(fd); - return 0; - -#endif /* LOCKLIB */ -} - -/* - * unlock - remove our lockfile - */ -void -unlock() -{ - if (lock_file[0]) { -#ifdef LOCKLIB - (void) rmlock(lock_file, (void *) 0); -#else - unlink(lock_file); -#endif - lock_file[0] = 0; - } -} - -#endif /* Unused */ - -#endif /* PPP_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/ppp/vj.c b/components/net/lwip-2.0.2/src/netif/ppp/vj.c deleted file mode 100644 index 168c340055..0000000000 --- a/components/net/lwip-2.0.2/src/netif/ppp/vj.c +++ /dev/null @@ -1,695 +0,0 @@ -/* - * Routines to compress and uncompess tcp packets (for transmission - * over low speed serial lines. - * - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989: - * Initial distribution. - * - * Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au, - * so that the entire packet being decompressed doesn't have - * to be in contiguous memory (just the compressed header). - * - * Modified March 1998 by Guy Lancaster, glanca@gesn.com, - * for a 16 bit processor. - */ - -#include "netif/ppp/ppp_opts.h" -#if PPP_SUPPORT && VJ_SUPPORT /* don't build if not configured for use in lwipopts.h */ - -#include "netif/ppp/ppp_impl.h" -#include "netif/ppp/pppdebug.h" - -#include "netif/ppp/vj.h" - -#include - -#if LINK_STATS -#define INCR(counter) ++comp->stats.counter -#else -#define INCR(counter) -#endif - -void -vj_compress_init(struct vjcompress *comp) -{ - u8_t i; - struct cstate *tstate = comp->tstate; - -#if MAX_SLOTS == 0 - memset((char *)comp, 0, sizeof(*comp)); -#endif - comp->maxSlotIndex = MAX_SLOTS - 1; - comp->compressSlot = 0; /* Disable slot ID compression by default. */ - for (i = MAX_SLOTS - 1; i > 0; --i) { - tstate[i].cs_id = i; - tstate[i].cs_next = &tstate[i - 1]; - } - tstate[0].cs_next = &tstate[MAX_SLOTS - 1]; - tstate[0].cs_id = 0; - comp->last_cs = &tstate[0]; - comp->last_recv = 255; - comp->last_xmit = 255; - comp->flags = VJF_TOSS; -} - - -/* ENCODE encodes a number that is known to be non-zero. ENCODEZ - * checks for zero (since zero has to be encoded in the long, 3 byte - * form). - */ -#define ENCODE(n) { \ - if ((u16_t)(n) >= 256) { \ - *cp++ = 0; \ - cp[1] = (u8_t)(n); \ - cp[0] = (u8_t)((n) >> 8); \ - cp += 2; \ - } else { \ - *cp++ = (u8_t)(n); \ - } \ -} -#define ENCODEZ(n) { \ - if ((u16_t)(n) >= 256 || (u16_t)(n) == 0) { \ - *cp++ = 0; \ - cp[1] = (u8_t)(n); \ - cp[0] = (u8_t)((n) >> 8); \ - cp += 2; \ - } else { \ - *cp++ = (u8_t)(n); \ - } \ -} - -#define DECODEL(f) { \ - if (*cp == 0) {\ - u32_t tmp_ = lwip_ntohl(f) + ((cp[1] << 8) | cp[2]); \ - (f) = lwip_htonl(tmp_); \ - cp += 3; \ - } else { \ - u32_t tmp_ = lwip_ntohl(f) + (u32_t)*cp++; \ - (f) = lwip_htonl(tmp_); \ - } \ -} - -#define DECODES(f) { \ - if (*cp == 0) {\ - u16_t tmp_ = lwip_ntohs(f) + (((u16_t)cp[1] << 8) | cp[2]); \ - (f) = lwip_htons(tmp_); \ - cp += 3; \ - } else { \ - u16_t tmp_ = lwip_ntohs(f) + (u16_t)*cp++; \ - (f) = lwip_htons(tmp_); \ - } \ -} - -#define DECODEU(f) { \ - if (*cp == 0) {\ - (f) = lwip_htons(((u16_t)cp[1] << 8) | cp[2]); \ - cp += 3; \ - } else { \ - (f) = lwip_htons((u16_t)*cp++); \ - } \ -} - -/* Helper structures for unaligned *u32_t and *u16_t accesses */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct vj_u32_t { - PACK_STRUCT_FIELD(u32_t v); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct vj_u16_t { - PACK_STRUCT_FIELD(u16_t v); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* - * vj_compress_tcp - Attempt to do Van Jacobson header compression on a - * packet. This assumes that nb and comp are not null and that the first - * buffer of the chain contains a valid IP header. - * Return the VJ type code indicating whether or not the packet was - * compressed. - */ -u8_t -vj_compress_tcp(struct vjcompress *comp, struct pbuf **pb) -{ - struct pbuf *np = *pb; - struct ip_hdr *ip = (struct ip_hdr *)np->payload; - struct cstate *cs = comp->last_cs->cs_next; - u16_t ilen = IPH_HL(ip); - u16_t hlen; - struct tcp_hdr *oth; - struct tcp_hdr *th; - u16_t deltaS, deltaA = 0; - u32_t deltaL; - u32_t changes = 0; - u8_t new_seq[16]; - u8_t *cp = new_seq; - - /* - * Check that the packet is IP proto TCP. - */ - if (IPH_PROTO(ip) != IP_PROTO_TCP) { - return (TYPE_IP); - } - - /* - * Bail if this is an IP fragment or if the TCP packet isn't - * `compressible' (i.e., ACK isn't set or some other control bit is - * set). - */ - if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || np->tot_len < 40) { - return (TYPE_IP); - } - th = (struct tcp_hdr *)&((struct vj_u32_t*)ip)[ilen]; - if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { - return (TYPE_IP); - } - - /* Check that the TCP/IP headers are contained in the first buffer. */ - hlen = ilen + TCPH_HDRLEN(th); - hlen <<= 2; - if (np->len < hlen) { - PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); - return (TYPE_IP); - } - - /* TCP stack requires that we don't change the packet payload, therefore we copy - * the whole packet before compression. */ - np = pbuf_alloc(PBUF_RAW, np->tot_len, PBUF_POOL); - if (!np) { - return (TYPE_IP); - } - - if (pbuf_copy(np, *pb) != ERR_OK) { - pbuf_free(np); - return (TYPE_IP); - } - - *pb = np; - ip = (struct ip_hdr *)np->payload; - - /* - * Packet is compressible -- we're going to send either a - * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need - * to locate (or create) the connection state. Special case the - * most recently used connection since it's most likely to be used - * again & we don't have to do any reordering if it's used. - */ - INCR(vjs_packets); - if (!ip4_addr_cmp(&ip->src, &cs->cs_ip.src) - || !ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) - || (*(struct vj_u32_t*)th).v != (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { - /* - * Wasn't the first -- search for it. - * - * States are kept in a circularly linked list with - * last_cs pointing to the end of the list. The - * list is kept in lru order by moving a state to the - * head of the list whenever it is referenced. Since - * the list is short and, empirically, the connection - * we want is almost always near the front, we locate - * states via linear search. If we don't find a state - * for the datagram, the oldest state is (re-)used. - */ - struct cstate *lcs; - struct cstate *lastcs = comp->last_cs; - - do { - lcs = cs; cs = cs->cs_next; - INCR(vjs_searches); - if (ip4_addr_cmp(&ip->src, &cs->cs_ip.src) - && ip4_addr_cmp(&ip->dest, &cs->cs_ip.dest) - && (*(struct vj_u32_t*)th).v == (((struct vj_u32_t*)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]).v) { - goto found; - } - } while (cs != lastcs); - - /* - * Didn't find it -- re-use oldest cstate. Send an - * uncompressed packet that tells the other side what - * connection number we're using for this conversation. - * Note that since the state list is circular, the oldest - * state points to the newest and we only need to set - * last_cs to update the lru linkage. - */ - INCR(vjs_misses); - comp->last_cs = lcs; - goto uncompressed; - - found: - /* - * Found it -- move to the front on the connection list. - */ - if (cs == lastcs) { - comp->last_cs = lcs; - } else { - lcs->cs_next = cs->cs_next; - cs->cs_next = lastcs->cs_next; - lastcs->cs_next = cs; - } - } - - oth = (struct tcp_hdr *)&((struct vj_u32_t*)&cs->cs_ip)[ilen]; - deltaS = ilen; - - /* - * Make sure that only what we expect to change changed. The first - * line of the `if' checks the IP protocol version, header length & - * type of service. The 2nd line checks the "Don't fragment" bit. - * The 3rd line checks the time-to-live and protocol (the protocol - * check is unnecessary but costless). The 4th line checks the TCP - * header length. The 5th line checks IP options, if any. The 6th - * line checks TCP options, if any. If any of these things are - * different between the previous & current datagram, we send the - * current datagram `uncompressed'. - */ - if ((((struct vj_u16_t*)ip)[0]).v != (((struct vj_u16_t*)&cs->cs_ip)[0]).v - || (((struct vj_u16_t*)ip)[3]).v != (((struct vj_u16_t*)&cs->cs_ip)[3]).v - || (((struct vj_u16_t*)ip)[4]).v != (((struct vj_u16_t*)&cs->cs_ip)[4]).v - || TCPH_HDRLEN(th) != TCPH_HDRLEN(oth) - || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) - || (TCPH_HDRLEN(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_HDRLEN(th) - 5) << 2))) { - goto uncompressed; - } - - /* - * Figure out which of the changing fields changed. The - * receiver expects changes in the order: urgent, window, - * ack, seq (the order minimizes the number of temporaries - * needed in this section of code). - */ - if (TCPH_FLAGS(th) & TCP_URG) { - deltaS = lwip_ntohs(th->urgp); - ENCODEZ(deltaS); - changes |= NEW_U; - } else if (th->urgp != oth->urgp) { - /* argh! URG not set but urp changed -- a sensible - * implementation should never do this but RFC793 - * doesn't prohibit the change so we have to deal - * with it. */ - goto uncompressed; - } - - if ((deltaS = (u16_t)(lwip_ntohs(th->wnd) - lwip_ntohs(oth->wnd))) != 0) { - ENCODE(deltaS); - changes |= NEW_W; - } - - if ((deltaL = lwip_ntohl(th->ackno) - lwip_ntohl(oth->ackno)) != 0) { - if (deltaL > 0xffff) { - goto uncompressed; - } - deltaA = (u16_t)deltaL; - ENCODE(deltaA); - changes |= NEW_A; - } - - if ((deltaL = lwip_ntohl(th->seqno) - lwip_ntohl(oth->seqno)) != 0) { - if (deltaL > 0xffff) { - goto uncompressed; - } - deltaS = (u16_t)deltaL; - ENCODE(deltaS); - changes |= NEW_S; - } - - switch(changes) { - case 0: - /* - * Nothing changed. If this packet contains data and the - * last one didn't, this is probably a data packet following - * an ack (normal on an interactive connection) and we send - * it compressed. Otherwise it's probably a retransmit, - * retransmitted ack or window probe. Send it uncompressed - * in case the other side missed the compressed version. - */ - if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && - lwip_ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { - break; - } - /* no break */ - /* fall through */ - - case SPECIAL_I: - case SPECIAL_D: - /* - * actual changes match one of our special case encodings -- - * send packet uncompressed. - */ - goto uncompressed; - - case NEW_S|NEW_A: - if (deltaS == deltaA && deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { - /* special case for echoed terminal traffic */ - changes = SPECIAL_I; - cp = new_seq; - } - break; - - case NEW_S: - if (deltaS == lwip_ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { - /* special case for data xfer */ - changes = SPECIAL_D; - cp = new_seq; - } - break; - default: - break; - } - - deltaS = (u16_t)(lwip_ntohs(IPH_ID(ip)) - lwip_ntohs(IPH_ID(&cs->cs_ip))); - if (deltaS != 1) { - ENCODEZ(deltaS); - changes |= NEW_I; - } - if (TCPH_FLAGS(th) & TCP_PSH) { - changes |= TCP_PUSH_BIT; - } - /* - * Grab the cksum before we overwrite it below. Then update our - * state with this packet's header. - */ - deltaA = lwip_ntohs(th->chksum); - MEMCPY(&cs->cs_ip, ip, hlen); - - /* - * We want to use the original packet as our compressed packet. - * (cp - new_seq) is the number of bytes we need for compressed - * sequence numbers. In addition we need one byte for the change - * mask, one for the connection id and two for the tcp checksum. - * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how - * many bytes of the original packet to toss so subtract the two to - * get the new packet size. - */ - deltaS = (u16_t)(cp - new_seq); - if (!comp->compressSlot || comp->last_xmit != cs->cs_id) { - comp->last_xmit = cs->cs_id; - hlen -= deltaS + 4; - if (pbuf_header(np, -(s16_t)hlen)){ - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - } - cp = (u8_t*)np->payload; - *cp++ = (u8_t)(changes | NEW_C); - *cp++ = cs->cs_id; - } else { - hlen -= deltaS + 3; - if (pbuf_header(np, -(s16_t)hlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - } - cp = (u8_t*)np->payload; - *cp++ = (u8_t)changes; - } - *cp++ = (u8_t)(deltaA >> 8); - *cp++ = (u8_t)deltaA; - MEMCPY(cp, new_seq, deltaS); - INCR(vjs_compressed); - return (TYPE_COMPRESSED_TCP); - - /* - * Update connection state cs & send uncompressed packet (that is, - * a regular ip/tcp packet but with the 'conversation id' we hope - * to use on future compressed packets in the protocol field). - */ -uncompressed: - MEMCPY(&cs->cs_ip, ip, hlen); - IPH_PROTO_SET(ip, cs->cs_id); - comp->last_xmit = cs->cs_id; - return (TYPE_UNCOMPRESSED_TCP); -} - -/* - * Called when we may have missed a packet. - */ -void -vj_uncompress_err(struct vjcompress *comp) -{ - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); -} - -/* - * "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP. - * Return 0 on success, -1 on failure. - */ -int -vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) -{ - u32_t hlen; - struct cstate *cs; - struct ip_hdr *ip; - - ip = (struct ip_hdr *)nb->payload; - hlen = IPH_HL(ip) << 2; - if (IPH_PROTO(ip) >= MAX_SLOTS - || hlen + sizeof(struct tcp_hdr) > nb->len - || (hlen += TCPH_HDRLEN(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) - > nb->len - || hlen > MAX_HDR) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", - IPH_PROTO(ip), hlen, nb->len)); - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); - return -1; - } - cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; - comp->flags &=~ VJF_TOSS; - IPH_PROTO_SET(ip, IP_PROTO_TCP); - MEMCPY(&cs->cs_ip, ip, hlen); - cs->cs_hlen = (u16_t)hlen; - INCR(vjs_uncompressedin); - return 0; -} - -/* - * Uncompress a packet of type TYPE_COMPRESSED_TCP. - * The packet is composed of a buffer chain and the first buffer - * must contain an accurate chain length. - * The first buffer must include the entire compressed TCP/IP header. - * This procedure replaces the compressed header with the uncompressed - * header and returns the length of the VJ header. - */ -int -vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) -{ - u8_t *cp; - struct tcp_hdr *th; - struct cstate *cs; - struct vj_u16_t *bp; - struct pbuf *n0 = *nb; - u32_t tmp; - u32_t vjlen, hlen, changes; - - INCR(vjs_compressedin); - cp = (u8_t*)n0->payload; - changes = *cp++; - if (changes & NEW_C) { - /* - * Make sure the state index is in range, then grab the state. - * If we have a good state index, clear the 'discard' flag. - */ - if (*cp >= MAX_SLOTS) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); - goto bad; - } - - comp->flags &=~ VJF_TOSS; - comp->last_recv = *cp++; - } else { - /* - * this packet has an implicit state index. If we've - * had a line error since the last time we got an - * explicit state index, we have to toss the packet. - */ - if (comp->flags & VJF_TOSS) { - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); - INCR(vjs_tossed); - return (-1); - } - } - cs = &comp->rstate[comp->last_recv]; - hlen = IPH_HL(&cs->cs_ip) << 2; - th = (struct tcp_hdr *)&((u8_t*)&cs->cs_ip)[hlen]; - th->chksum = lwip_htons((*cp << 8) | cp[1]); - cp += 2; - if (changes & TCP_PUSH_BIT) { - TCPH_SET_FLAG(th, TCP_PSH); - } else { - TCPH_UNSET_FLAG(th, TCP_PSH); - } - - switch (changes & SPECIALS_MASK) { - case SPECIAL_I: - { - u32_t i = lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - /* some compilers can't nest inline assembler.. */ - tmp = lwip_ntohl(th->ackno) + i; - th->ackno = lwip_htonl(tmp); - tmp = lwip_ntohl(th->seqno) + i; - th->seqno = lwip_htonl(tmp); - } - break; - - case SPECIAL_D: - /* some compilers can't nest inline assembler.. */ - tmp = lwip_ntohl(th->seqno) + lwip_ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; - th->seqno = lwip_htonl(tmp); - break; - - default: - if (changes & NEW_U) { - TCPH_SET_FLAG(th, TCP_URG); - DECODEU(th->urgp); - } else { - TCPH_UNSET_FLAG(th, TCP_URG); - } - if (changes & NEW_W) { - DECODES(th->wnd); - } - if (changes & NEW_A) { - DECODEL(th->ackno); - } - if (changes & NEW_S) { - DECODEL(th->seqno); - } - break; - } - if (changes & NEW_I) { - DECODES(cs->cs_ip._id); - } else { - IPH_ID_SET(&cs->cs_ip, lwip_ntohs(IPH_ID(&cs->cs_ip)) + 1); - IPH_ID_SET(&cs->cs_ip, lwip_htons(IPH_ID(&cs->cs_ip))); - } - - /* - * At this point, cp points to the first byte of data in the - * packet. Fill in the IP total length and update the IP - * header checksum. - */ - vjlen = (u16_t)(cp - (u8_t*)n0->payload); - if (n0->len < vjlen) { - /* - * We must have dropped some characters (crc should detect - * this but the old slip framing won't) - */ - PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", - n0->len, vjlen)); - goto bad; - } - -#if BYTE_ORDER == LITTLE_ENDIAN - tmp = n0->tot_len - vjlen + cs->cs_hlen; - IPH_LEN_SET(&cs->cs_ip, lwip_htons((u16_t)tmp)); -#else - IPH_LEN_SET(&cs->cs_ip, lwip_htons(n0->tot_len - vjlen + cs->cs_hlen)); -#endif - - /* recompute the ip header checksum */ - bp = (struct vj_u16_t*) &cs->cs_ip; - IPH_CHKSUM_SET(&cs->cs_ip, 0); - for (tmp = 0; hlen > 0; hlen -= 2) { - tmp += (*bp++).v; - } - tmp = (tmp & 0xffff) + (tmp >> 16); - tmp = (tmp & 0xffff) + (tmp >> 16); - IPH_CHKSUM_SET(&cs->cs_ip, (u16_t)(~tmp)); - - /* Remove the compressed header and prepend the uncompressed header. */ - if (pbuf_header(n0, -(s16_t)vjlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - goto bad; - } - - if(LWIP_MEM_ALIGN(n0->payload) != n0->payload) { - struct pbuf *np, *q; - u8_t *bufptr; - -#if IP_FORWARD - /* If IP forwarding is enabled we are using a PBUF_LINK packet type so - * the packet is being allocated with enough header space to be - * forwarded (to Ethernet for example). - */ - np = pbuf_alloc(PBUF_LINK, n0->len + cs->cs_hlen, PBUF_POOL); -#else /* IP_FORWARD */ - np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); -#endif /* IP_FORWARD */ - if(!np) { - PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); - goto bad; - } - - if (pbuf_header(np, -(s16_t)cs->cs_hlen)) { - /* Can we cope with this failing? Just assert for now */ - LWIP_ASSERT("pbuf_header failed\n", 0); - goto bad; - } - - bufptr = (u8_t*)n0->payload; - for(q = np; q != NULL; q = q->next) { - MEMCPY(q->payload, bufptr, q->len); - bufptr += q->len; - } - - if(n0->next) { - pbuf_chain(np, n0->next); - pbuf_dechain(n0); - } - pbuf_free(n0); - n0 = np; - } - - if (pbuf_header(n0, (s16_t)cs->cs_hlen)) { - struct pbuf *np; - - LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); - np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); - if(!np) { - PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); - goto bad; - } - pbuf_cat(np, n0); - n0 = np; - } - LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen); - MEMCPY(n0->payload, &cs->cs_ip, cs->cs_hlen); - - *nb = n0; - - return vjlen; - -bad: - comp->flags |= VJF_TOSS; - INCR(vjs_errorin); - return (-1); -} - -#endif /* PPP_SUPPORT && VJ_SUPPORT */ diff --git a/components/net/lwip-2.0.2/src/netif/slipif.c b/components/net/lwip-2.0.2/src/netif/slipif.c deleted file mode 100644 index 6eb83c35a4..0000000000 --- a/components/net/lwip-2.0.2/src/netif/slipif.c +++ /dev/null @@ -1,555 +0,0 @@ -/** - * @file - * SLIP Interface - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is built upon the file: src/arch/rtxc/netif/sioslip.c - * - * Author: Magnus Ivarsson - * Simon Goldschmidt - */ - - -/** - * @defgroup slipif SLIP netif - * @ingroup addons - * - * This is an arch independent SLIP netif. The specific serial hooks must be - * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send - * - * Usage: This netif can be used in three ways:\n - * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() - * until data is received.\n - * 2) In your main loop, call slipif_poll() to check for new RX bytes, - * completed packets are fed into netif->input().\n - * 3) Call slipif_received_byte[s]() from your serial RX ISR and - * slipif_process_rxqueue() from your main loop. ISR level decodes - * packets and puts completed packets on a queue which is fed into - * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for - * pbuf_alloc to work on ISR level!). - * - */ - -#include "netif/slipif.h" -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/sys.h" -#include "lwip/sio.h" - -#define SLIP_END 0xC0 /* 0300: start and end of every packet */ -#define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ -#define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ -#define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ - -/** Maximum packet size that is received by this netif */ -#ifndef SLIP_MAX_SIZE -#define SLIP_MAX_SIZE 1500 -#endif - -/** Define this to the interface speed for SNMP - * (sio_fd is the sio_fd_t returned by sio_open). - * The default value of zero means 'unknown'. - */ -#ifndef SLIP_SIO_SPEED -#define SLIP_SIO_SPEED(sio_fd) 0 -#endif - -enum slipif_recv_state { - SLIP_RECV_NORMAL, - SLIP_RECV_ESCAPE -}; - -struct slipif_priv { - sio_fd_t sd; - /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ - struct pbuf *p, *q; - u8_t state; - u16_t i, recved; -#if SLIP_RX_FROM_ISR - struct pbuf *rxpackets; -#endif -}; - -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chain packet to send - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t -slipif_output(struct netif *netif, struct pbuf *p) -{ - struct slipif_priv *priv; - struct pbuf *q; - u16_t i; - u8_t c; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - LWIP_ASSERT("p != NULL", (p != NULL)); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); - priv = (struct slipif_priv *)netif->state; - - /* Send pbuf out on the serial I/O device. */ - /* Start with packet delimiter. */ - sio_send(SLIP_END, priv->sd); - - for (q = p; q != NULL; q = q->next) { - for (i = 0; i < q->len; i++) { - c = ((u8_t *)q->payload)[i]; - switch (c) { - case SLIP_END: - /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ - sio_send(SLIP_ESC, priv->sd); - sio_send(SLIP_ESC_END, priv->sd); - break; - case SLIP_ESC: - /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ - sio_send(SLIP_ESC, priv->sd); - sio_send(SLIP_ESC_ESC, priv->sd); - break; - default: - /* normal byte - no need for escaping */ - sio_send(c, priv->sd); - break; - } - } - } - /* End with packet delimiter. */ - sio_send(SLIP_END, priv->sd); - return ERR_OK; -} - -#if LWIP_IPV4 -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chain packet to send - * @param ipaddr the ip address to send the packet to (not used for slipif) - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t -slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(ipaddr); - return slipif_output(netif, p); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Send a pbuf doing the necessary SLIP encapsulation - * - * Uses the serial layer's sio_send() - * - * @param netif the lwip network interface structure for this slipif - * @param p the pbuf chain packet to send - * @param ipaddr the ip address to send the packet to (not used for slipif) - * @return always returns ERR_OK since the serial layer does not provide return values - */ -static err_t -slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) -{ - LWIP_UNUSED_ARG(ipaddr); - return slipif_output(netif, p); -} -#endif /* LWIP_IPV6 */ - -/** - * Handle the incoming SLIP stream character by character - * - * @param netif the lwip network interface structure for this slipif - * @param c received character (multiple calls to this function will - * return a complete packet, NULL is returned before - used for polling) - * @return The IP packet when SLIP_END is received - */ -static struct pbuf* -slipif_rxbyte(struct netif *netif, u8_t c) -{ - struct slipif_priv *priv; - struct pbuf *t; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - switch (priv->state) { - case SLIP_RECV_NORMAL: - switch (c) { - case SLIP_END: - if (priv->recved > 0) { - /* Received whole packet. */ - /* Trim the pbuf to the size of the received packet. */ - pbuf_realloc(priv->q, priv->recved); - - LINK_STATS_INC(link.recv); - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); - t = priv->q; - priv->p = priv->q = NULL; - priv->i = priv->recved = 0; - return t; - } - return NULL; - case SLIP_ESC: - priv->state = SLIP_RECV_ESCAPE; - return NULL; - default: - break; - } /* end switch (c) */ - break; - case SLIP_RECV_ESCAPE: - /* un-escape END or ESC bytes, leave other bytes - (although that would be a protocol error) */ - switch (c) { - case SLIP_ESC_END: - c = SLIP_END; - break; - case SLIP_ESC_ESC: - c = SLIP_ESC; - break; - default: - break; - } - priv->state = SLIP_RECV_NORMAL; - break; - default: - break; - } /* end switch (priv->state) */ - - /* byte received, packet not yet completely received */ - if (priv->p == NULL) { - /* allocate a new pbuf */ - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); - priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); - - if (priv->p == NULL) { - LINK_STATS_INC(link.drop); - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); - /* don't process any further since we got no pbuf to receive to */ - return NULL; - } - - if (priv->q != NULL) { - /* 'chain' the pbuf to the existing chain */ - pbuf_cat(priv->q, priv->p); - } else { - /* p is the first pbuf in the chain */ - priv->q = priv->p; - } - } - - /* this automatically drops bytes if > SLIP_MAX_SIZE */ - if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { - ((u8_t *)priv->p->payload)[priv->i] = c; - priv->recved++; - priv->i++; - if (priv->i >= priv->p->len) { - /* on to the next pbuf */ - priv->i = 0; - if (priv->p->next != NULL && priv->p->next->len > 0) { - /* p is a chain, on to the next in the chain */ - priv->p = priv->p->next; - } else { - /* p is a single pbuf, set it to NULL so next time a new - * pbuf is allocated */ - priv->p = NULL; - } - } - } - return NULL; -} - -/** Like slipif_rxbyte, but passes completed packets to netif->input - * - * @param netif The lwip network interface structure for this slipif - * @param c received character - */ -static void -slipif_rxbyte_input(struct netif *netif, u8_t c) -{ - struct pbuf *p; - p = slipif_rxbyte(netif, c); - if (p != NULL) { - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - } -} - -#if SLIP_USE_RX_THREAD -/** - * The SLIP input thread. - * - * Feed the IP layer with incoming packets - * - * @param nf the lwip network interface structure for this slipif - */ -static void -slipif_loop_thread(void *nf) -{ - u8_t c; - struct netif *netif = (struct netif *)nf; - struct slipif_priv *priv = (struct slipif_priv *)netif->state; - - while (1) { - if (sio_read(priv->sd, &c, 1) > 0) { - slipif_rxbyte_input(netif, c); - } - } -} -#endif /* SLIP_USE_RX_THREAD */ - -/** - * SLIP netif initialization - * - * Call the arch specific sio_open and remember - * the opened device in the state field of the netif. - * - * @param netif the lwip network interface structure for this slipif - * @return ERR_OK if serial line could be opened, - * ERR_MEM if no memory could be allocated, - * ERR_IF is serial line couldn't be opened - * - * @note netif->num must contain the number of the serial port to open - * (0 by default). If netif->state is != NULL, it is interpreted as an - * u8_t pointer pointing to the serial port number instead of netif->num. - * - */ -err_t -slipif_init(struct netif *netif) -{ - struct slipif_priv *priv; - u8_t sio_num; - - LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); - - /* Allocate private data */ - priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); - if (!priv) { - return ERR_MEM; - } - - netif->name[0] = 's'; - netif->name[1] = 'l'; -#if LWIP_IPV4 - netif->output = slipif_output_v4; -#endif /* LWIP_IPV4 */ -#if LWIP_IPV6 - netif->output_ip6 = slipif_output_v6; -#endif /* LWIP_IPV6 */ - netif->mtu = SLIP_MAX_SIZE; - - /* netif->state or netif->num contain the port number */ - if (netif->state != NULL) { - sio_num = *(u8_t*)netif->state; - } else { - sio_num = netif->num; - } - /* Try to open the serial port. */ - priv->sd = sio_open(sio_num); - if (!priv->sd) { - /* Opening the serial port failed. */ - mem_free(priv); - return ERR_IF; - } - - /* Initialize private data */ - priv->p = NULL; - priv->q = NULL; - priv->state = SLIP_RECV_NORMAL; - priv->i = 0; - priv->recved = 0; -#if SLIP_RX_FROM_ISR - priv->rxpackets = NULL; -#endif - - netif->state = priv; - - /* initialize the snmp variables and counters inside the struct netif */ - MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); - -#if SLIP_USE_RX_THREAD - /* Create a thread to poll the serial line. */ - sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, - SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); -#endif /* SLIP_USE_RX_THREAD */ - return ERR_OK; -} - -/** - * Polls the serial device and feeds the IP layer with incoming packets. - * - * @param netif The lwip network interface structure for this slipif - */ -void -slipif_poll(struct netif *netif) -{ - u8_t c; - struct slipif_priv *priv; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - while (sio_tryread(priv->sd, &c, 1) > 0) { - slipif_rxbyte_input(netif, c); - } -} - -#if SLIP_RX_FROM_ISR -/** - * Feeds the IP layer with incoming packets that were receive - * - * @param netif The lwip network interface structure for this slipif - */ -void -slipif_process_rxqueue(struct netif *netif) -{ - struct slipif_priv *priv; - SYS_ARCH_DECL_PROTECT(old_level); - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - priv = (struct slipif_priv *)netif->state; - - SYS_ARCH_PROTECT(old_level); - while (priv->rxpackets != NULL) { - struct pbuf *p = priv->rxpackets; -#if SLIP_RX_QUEUE - /* dequeue packet */ - struct pbuf *q = p; - while ((q->len != q->tot_len) && (q->next != NULL)) { - q = q->next; - } - priv->rxpackets = q->next; - q->next = NULL; -#else /* SLIP_RX_QUEUE */ - priv->rxpackets = NULL; -#endif /* SLIP_RX_QUEUE */ - SYS_ARCH_UNPROTECT(old_level); - if (netif->input(p, netif) != ERR_OK) { - pbuf_free(p); - } - SYS_ARCH_PROTECT(old_level); - } -} - -/** Like slipif_rxbyte, but queues completed packets. - * - * @param netif The lwip network interface structure for this slipif - * @param data Received serial byte - */ -static void -slipif_rxbyte_enqueue(struct netif *netif, u8_t data) -{ - struct pbuf *p; - struct slipif_priv *priv = (struct slipif_priv *)netif->state; - SYS_ARCH_DECL_PROTECT(old_level); - - p = slipif_rxbyte(netif, data); - if (p != NULL) { - SYS_ARCH_PROTECT(old_level); - if (priv->rxpackets != NULL) { -#if SLIP_RX_QUEUE - /* queue multiple pbufs */ - struct pbuf *q = p; - while (q->next != NULL) { - q = q->next; - } - q->next = p; - } else { -#else /* SLIP_RX_QUEUE */ - pbuf_free(priv->rxpackets); - } - { -#endif /* SLIP_RX_QUEUE */ - priv->rxpackets = p; - } - SYS_ARCH_UNPROTECT(old_level); - } -} - -/** - * Process a received byte, completed packets are put on a queue that is - * fed into IP through slipif_process_rxqueue(). - * - * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - */ -void -slipif_received_byte(struct netif *netif, u8_t data) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - slipif_rxbyte_enqueue(netif, data); -} - -/** - * Process multiple received byte, completed packets are put on a queue that is - * fed into IP through slipif_process_rxqueue(). - * - * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. - * - * @param netif The lwip network interface structure for this slipif - * @param data received character - * @param len Number of received characters - */ -void -slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) -{ - u8_t i; - u8_t *rxdata = data; - LWIP_ASSERT("netif != NULL", (netif != NULL)); - LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); - - for (i = 0; i < len; i++, rxdata++) { - slipif_rxbyte_enqueue(netif, *rxdata); - } -} -#endif /* SLIP_RX_FROM_ISR */ diff --git a/components/net/lwip-2.0.2/test/fuzz/Makefile b/components/net/lwip-2.0.2/test/fuzz/Makefile deleted file mode 100644 index 67ffb1957e..0000000000 --- a/components/net/lwip-2.0.2/test/fuzz/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (c) 2001, 2002 Swedish Institute of Computer Science. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -# OF SUCH DAMAGE. -# -# This file is part of the lwIP TCP/IP stack. -# -# Author: Adam Dunkels -# - -all compile: lwip_fuzz -.PHONY: all clean - -CC=afl-gcc -LDFLAGS=-lm -CFLAGS=-O0 - -CONTRIBDIR=../../../lwip-contrib -include $(CONTRIBDIR)/ports/unix/Common.mk - -clean: - rm -f *.o $(LWIPLIBCOMMON) lwip_fuzz *.s .depend* *.core core - -depend dep: .depend - -include .depend - -.depend: fuzz.c $(LWIPFILES) $(APPFILES) - $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend - -lwip_fuzz: .depend $(LWIPLIBCOMMON) fuzz.o - $(CC) $(CFLAGS) -o lwip_fuzz fuzz.o $(LWIPLIBCOMMON) $(LDFLAGS) diff --git a/components/net/lwip-2.0.2/test/fuzz/README b/components/net/lwip-2.0.2/test/fuzz/README deleted file mode 100644 index 1d1e3d8deb..0000000000 --- a/components/net/lwip-2.0.2/test/fuzz/README +++ /dev/null @@ -1,34 +0,0 @@ - -Fuzzing the lwIP stack (afl-fuzz requires linux/unix or similar) - -This directory contains a small app that reads Ethernet frames from stdin and -processes them. It is used together with the 'american fuzzy lop' tool (found -at http://lcamtuf.coredump.cx/afl/) and the sample inputs to test how -unexpected inputs are handled. The afl tool will read the known inputs, and -try to modify them to exercise as many code paths as possible, by instrumenting -the code and keeping track of which code is executed. - -Just running make will produce the test program. - -Then run afl with: - -afl-fuzz -i inputs/ -o output ./lwip_fuzz - -and it should start working. It will probably complain about CPU scheduler, -set AFL_SKIP_CPUFREQ=1 to ignore it. -If it complains about invalid "/proc/sys/kernel/core_pattern" setting, try -executing "sudo bash -c 'echo core > /proc/sys/kernel/core_pattern'". - -The input is split into different subdirectories since they test different -parts of the code, and since you want to run one instance of afl-fuzz on each -core. - -When afl finds a crash or a hang, the input that caused it will be placed in -the output directory. If you have hexdump and text2pcap tools installed, -running output_to_pcap.sh will create pcap files for each input -file to simplify viewing in wireshark. - -The lwipopts.h file needs to have checksum checking off, otherwise almost every -packet will be discarded because of that. The other options can be tuned to -expose different parts of the code. - diff --git a/components/net/lwip-2.0.2/test/fuzz/config.h b/components/net/lwip-2.0.2/test/fuzz/config.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/components/net/lwip-2.0.2/test/fuzz/fuzz.c b/components/net/lwip-2.0.2/test/fuzz/fuzz.c deleted file mode 100644 index a9157f1385..0000000000 --- a/components/net/lwip-2.0.2/test/fuzz/fuzz.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "lwip/init.h" -#include "lwip/netif.h" -#include "netif/etharp.h" -#if LWIP_IPV6 -#include "lwip/ethip6.h" -#include "lwip/nd6.h" -#endif -#include -#include - -/* no-op send function */ -static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) -{ - LWIP_UNUSED_ARG(netif); - LWIP_UNUSED_ARG(p); - return ERR_OK; -} - -static err_t testif_init(struct netif *netif) -{ - netif->name[0] = 'f'; - netif->name[1] = 'z'; - netif->output = etharp_output; - netif->linkoutput = lwip_tx_func; - netif->mtu = 1500; - netif->hwaddr_len = 6; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - - netif->hwaddr[0] = 0x00; - netif->hwaddr[1] = 0x23; - netif->hwaddr[2] = 0xC1; - netif->hwaddr[3] = 0xDE; - netif->hwaddr[4] = 0xD0; - netif->hwaddr[5] = 0x0D; - -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; - netif->ip6_autoconfig_enabled = 1; - netif_create_ip6_linklocal_address(netif, 1); - netif->flags |= NETIF_FLAG_MLD6; -#endif - - return ERR_OK; -} - -static void input_pkt(struct netif *netif, const u8_t *data, size_t len) -{ - struct pbuf *p, *q; - err_t err; - - LWIP_ASSERT("pkt too big", len <= 0xFFFF); - p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); - LWIP_ASSERT("alloc failed", p); - for(q = p; q != NULL; q = q->next) { - MEMCPY(q->payload, data, q->len); - data += q->len; - } - err = netif->input(p, netif); - if (err != ERR_OK) { - pbuf_free(p); - } -} - -int main(int argc, char** argv) -{ - struct netif net_test; - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - u8_t pktbuf[2000]; - size_t len; - - lwip_init(); - - IP4_ADDR(&addr, 172, 30, 115, 84); - IP4_ADDR(&netmask, 255, 255, 255, 0); - IP4_ADDR(&gw, 172, 30, 115, 1); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - -#if LWIP_IPV6 - nd6_tmr(); /* tick nd to join multicast groups */ -#endif - - if(argc > 1) { - FILE* f; - const char* filename; - printf("reading input from file... "); - fflush(stdout); - filename = argv[1]; - LWIP_ASSERT("invalid filename", filename != NULL); - f = fopen(filename, "rb"); - LWIP_ASSERT("open failed", f != NULL); - len = fread(pktbuf, 1, sizeof(pktbuf), f); - fclose(f); - printf("testing file: \"%s\"...\r\n", filename); - } else { - len = fread(pktbuf, 1, sizeof(pktbuf), stdin); - } - input_pkt(&net_test, pktbuf, len); - - return 0; -} diff --git a/components/net/lwip-2.0.2/test/fuzz/lwipopts.h b/components/net/lwip-2.0.2/test/fuzz/lwipopts.h deleted file mode 100644 index 4aff09bad6..0000000000 --- a/components/net/lwip-2.0.2/test/fuzz/lwipopts.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_LWIPOPTS_H__ -#define LWIP_HDR_LWIPOPTS_H__ - -/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 1 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 -#define SYS_LIGHTWEIGHT_PROT 0 - -#define LWIP_IPV6 1 -#define IPV6_FRAG_COPYHEADER 1 -#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 0 - -/* Enable DHCP to test it */ -#define LWIP_DHCP 1 - -/* Turn off checksum verification of fuzzed data */ -#define CHECKSUM_CHECK_IP 0 -#define CHECKSUM_CHECK_UDP 0 -#define CHECKSUM_CHECK_TCP 0 -#define CHECKSUM_CHECK_ICMP 0 -#define CHECKSUM_CHECK_ICMP6 0 - -/* Minimal changes to opt.h required for tcp unit tests: */ -#define MEM_SIZE 16000 -#define TCP_SND_QUEUELEN 40 -#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN -#define TCP_SND_BUF (12 * TCP_MSS) -#define TCP_WND (10 * TCP_MSS) -#define LWIP_WND_SCALE 1 -#define TCP_RCV_SCALE 0 -#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ - -/* Minimal changes to opt.h required for etharp unit tests: */ -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 - -#endif /* LWIP_HDR_LWIPOPTS_H__ */ diff --git a/components/net/lwip-2.0.2/test/fuzz/output_to_pcap.sh b/components/net/lwip-2.0.2/test/fuzz/output_to_pcap.sh deleted file mode 100644 index c999ff0392..0000000000 --- a/components/net/lwip-2.0.2/test/fuzz/output_to_pcap.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -if [ -z "$1" ] -then - echo "This script will make pcap files from the afl-fuzz crash/hang files" - echo "It needs hexdump and text2pcap" - echo "Please give output directory as argument" - exit 2 -fi - -for i in `ls $1/crashes/id*` -do - PCAPNAME=`echo $i | grep pcap` - if [ -z "$PCAPNAME" ]; then - hexdump -C $i > $1/$$.tmp - text2pcap $1/$$.tmp ${i}.pcap - fi -done -for i in `ls $1/hangs/id*` -do - PCAPNAME=`echo $i | grep pcap` - if [ -z "$PCAPNAME" ]; then - hexdump -C $i > $1/$$.tmp - text2pcap $1/$$.tmp ${i}.pcap - fi -done -rm -f $1/$$.tmp - -echo -echo "Created pcap files:" -ls $1/*/*.pcap diff --git a/components/net/lwip-2.0.2/test/unit/core/test_mem.c b/components/net/lwip-2.0.2/test/unit/core/test_mem.c deleted file mode 100644 index 66b4877e3f..0000000000 --- a/components/net/lwip-2.0.2/test/unit/core/test_mem.c +++ /dev/null @@ -1,121 +0,0 @@ -#include "test_mem.h" - -#include "lwip/mem.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !MEM_STATS -#error "This tests needs MEM-statistics enabled" -#endif -#if LWIP_DNS -#error "This test needs DNS turned off (as it mallocs on init)" -#endif - -/* Setups/teardown functions */ - -static void -mem_setup(void) -{ -} - -static void -mem_teardown(void) -{ -} - - -/* Test functions */ - -/** Call mem_malloc, mem_free and mem_trim and check stats */ -START_TEST(test_mem_one) -{ -#define SIZE1 16 -#define SIZE1_2 12 -#define SIZE2 16 - void *p1, *p2; - mem_size_t s1, s2; - LWIP_UNUSED_ARG(_i); - - fail_unless(lwip_stats.mem.used == 0); - - p1 = mem_malloc(SIZE1); - fail_unless(p1 != NULL); - fail_unless(lwip_stats.mem.used >= SIZE1); - s1 = lwip_stats.mem.used; - - p2 = mem_malloc(SIZE2); - fail_unless(p2 != NULL); - fail_unless(lwip_stats.mem.used >= SIZE2 + s1); - s2 = lwip_stats.mem.used; - - mem_trim(p1, SIZE1_2); - - mem_free(p2); - fail_unless(lwip_stats.mem.used <= s2 - SIZE2); - - mem_free(p1); - fail_unless(lwip_stats.mem.used == 0); -} -END_TEST - -static void malloc_keep_x(int x, int num, int size, int freestep) -{ - int i; - void* p[16]; - LWIP_ASSERT("invalid size", size >= 0 && size < (mem_size_t)-1); - memset(p, 0, sizeof(p)); - for(i = 0; i < num && i < 16; i++) { - p[i] = mem_malloc((mem_size_t)size); - fail_unless(p[i] != NULL); - } - for(i = 0; i < num && i < 16; i += freestep) { - if (i == x) { - continue; - } - mem_free(p[i]); - p[i] = NULL; - } - for(i = 0; i < num && i < 16; i++) { - if (i == x) { - continue; - } - if (p[i] != NULL) { - mem_free(p[i]); - p[i] = NULL; - } - } - fail_unless(p[x] != NULL); - mem_free(p[x]); -} - -START_TEST(test_mem_random) -{ - const int num = 16; - int x; - int size; - int freestep; - LWIP_UNUSED_ARG(_i); - - fail_unless(lwip_stats.mem.used == 0); - - for (x = 0; x < num; x++) { - for (size = 1; size < 32; size++) { - for (freestep = 1; freestep <= 3; freestep++) { - fail_unless(lwip_stats.mem.used == 0); - malloc_keep_x(x, num, size, freestep); - fail_unless(lwip_stats.mem.used == 0); - } - } - } -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -mem_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_mem_one), - TESTFUNC(test_mem_random) - }; - return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/core/test_mem.h b/components/net/lwip-2.0.2/test/unit/core/test_mem.h deleted file mode 100644 index 325134c30a..0000000000 --- a/components/net/lwip-2.0.2/test/unit/core/test_mem.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_MEM_H -#define LWIP_HDR_TEST_MEM_H - -#include "../lwip_check.h" - -Suite *mem_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/core/test_pbuf.c b/components/net/lwip-2.0.2/test/unit/core/test_pbuf.c deleted file mode 100644 index 9315c4c635..0000000000 --- a/components/net/lwip-2.0.2/test/unit/core/test_pbuf.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "test_pbuf.h" - -#include "lwip/pbuf.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !MEM_STATS ||!MEMP_STATS -#error "This tests needs MEM- and MEMP-statistics enabled" -#endif -#if LWIP_DNS -#error "This test needs DNS turned off (as it mallocs on init)" -#endif -#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE -#error "This test needs TCP OOSEQ queueing and window scaling enabled" -#endif - -/* Setups/teardown functions */ - -static void -pbuf_setup(void) -{ -} - -static void -pbuf_teardown(void) -{ -} - - -#define TESTBUFSIZE_1 65535 -#define TESTBUFSIZE_2 65530 -#define TESTBUFSIZE_3 50050 -static u8_t testbuf_1[TESTBUFSIZE_1]; -static u8_t testbuf_1a[TESTBUFSIZE_1]; -static u8_t testbuf_2[TESTBUFSIZE_2]; -static u8_t testbuf_2a[TESTBUFSIZE_2]; -static u8_t testbuf_3[TESTBUFSIZE_3]; -static u8_t testbuf_3a[TESTBUFSIZE_3]; - -/* Test functions */ - -/** Call pbuf_copy on a pbuf with zero length */ -START_TEST(test_pbuf_copy_zero_pbuf) -{ - struct pbuf *p1, *p2, *p3; - err_t err; - LWIP_UNUSED_ARG(_i); - - fail_unless(lwip_stats.mem.used == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); - - p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM); - fail_unless(p1 != NULL); - fail_unless(p1->ref == 1); - - p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL); - fail_unless(p2 != NULL); - fail_unless(p2->ref == 1); - p2->len = p2->tot_len = 0; - - pbuf_cat(p1, p2); - fail_unless(p1->ref == 1); - fail_unless(p2->ref == 1); - - p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL); - err = pbuf_copy(p3, p1); - fail_unless(err == ERR_VAL); - - pbuf_free(p1); - pbuf_free(p3); - fail_unless(lwip_stats.mem.used == 0); - - fail_unless(lwip_stats.mem.used == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); -} -END_TEST - -START_TEST(test_pbuf_split_64k_on_small_pbufs) -{ - struct pbuf *p, *rest=NULL; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL); - pbuf_split_64k(p, &rest); - fail_unless(p->tot_len == 1); - pbuf_free(p); -} -END_TEST - -START_TEST(test_pbuf_queueing_bigger_than_64k) -{ - int i; - err_t err; - struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL; - LWIP_UNUSED_ARG(_i); - - for(i = 0; i < TESTBUFSIZE_1; i++) { - testbuf_1[i] = (u8_t)rand(); - } - for(i = 0; i < TESTBUFSIZE_2; i++) { - testbuf_2[i] = (u8_t)rand(); - } - for(i = 0; i < TESTBUFSIZE_3; i++) { - testbuf_3[i] = (u8_t)rand(); - } - - p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL); - fail_unless(p1 != NULL); - p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL); - fail_unless(p2 != NULL); - p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL); - fail_unless(p3 != NULL); - err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1); - fail_unless(err == ERR_OK); - err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2); - fail_unless(err == ERR_OK); - err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3); - fail_unless(err == ERR_OK); - - pbuf_cat(p1, p2); - pbuf_cat(p1, p3); - - pbuf_split_64k(p1, &rest2); - fail_unless(p1->tot_len == TESTBUFSIZE_1); - fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF)); - pbuf_split_64k(rest2, &rest3); - fail_unless(rest2->tot_len == TESTBUFSIZE_2); - fail_unless(rest3->tot_len == TESTBUFSIZE_3); - - pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0); - pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0); - pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0); - for(i = 0; i < TESTBUFSIZE_1; i++) - fail_unless(testbuf_1[i] == testbuf_1a[i]); - for(i = 0; i < TESTBUFSIZE_2; i++) - fail_unless(testbuf_2[i] == testbuf_2a[i]); - for(i = 0; i < TESTBUFSIZE_3; i++) - fail_unless(testbuf_3[i] == testbuf_3a[i]); - - pbuf_free(p1); - pbuf_free(rest2); - pbuf_free(rest3); -} -END_TEST - -/* Test for bug that writing with pbuf_take_at() did nothing - * and returned ERR_OK when writing at beginning of a pbuf - * in the chain. - */ -START_TEST(test_pbuf_take_at_edge) -{ - err_t res; - u8_t *out; - int i; - u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 }; - struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); - struct pbuf *q = p->next; - LWIP_UNUSED_ARG(_i); - /* alloc big enough to get a chain of pbufs */ - fail_if(p->tot_len == p->len); - memset(p->payload, 0, p->len); - memset(q->payload, 0, q->len); - - /* copy data to the beginning of first pbuf */ - res = pbuf_take_at(p, &testdata, sizeof(testdata), 0); - fail_unless(res == ERR_OK); - - out = (u8_t*)p->payload; - for (i = 0; i < (int)sizeof(testdata); i++) { - fail_unless(out[i] == testdata[i], - "Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]); - } - - /* copy data to the just before end of first pbuf */ - res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1); - fail_unless(res == ERR_OK); - - out = (u8_t*)p->payload; - fail_unless(out[p->len - 1] == testdata[0], - "Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]); - out = (u8_t*)q->payload; - for (i = 1; i < (int)sizeof(testdata); i++) { - fail_unless(out[i-1] == testdata[i], - "Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]); - } - - /* copy data to the beginning of second pbuf */ - res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len); - fail_unless(res == ERR_OK); - - out = (u8_t*)p->payload; - for (i = 0; i < (int)sizeof(testdata); i++) { - fail_unless(out[i] == testdata[i], - "Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]); - } -} -END_TEST - -/* Verify pbuf_put_at()/pbuf_get_at() when using - * offsets equal to beginning of new pbuf in chain - */ -START_TEST(test_pbuf_get_put_at_edge) -{ - u8_t *out; - u8_t testdata = 0x01; - u8_t getdata; - struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL); - struct pbuf *q = p->next; - LWIP_UNUSED_ARG(_i); - /* alloc big enough to get a chain of pbufs */ - fail_if(p->tot_len == p->len); - memset(p->payload, 0, p->len); - memset(q->payload, 0, q->len); - - /* put byte at the beginning of second pbuf */ - pbuf_put_at(p, p->len, testdata); - - out = (u8_t*)q->payload; - fail_unless(*out == testdata, - "Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata); - - getdata = pbuf_get_at(p, p->len); - fail_unless(*out == getdata, - "pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out); -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -pbuf_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_pbuf_copy_zero_pbuf), - TESTFUNC(test_pbuf_split_64k_on_small_pbufs), - TESTFUNC(test_pbuf_queueing_bigger_than_64k), - TESTFUNC(test_pbuf_take_at_edge), - TESTFUNC(test_pbuf_get_put_at_edge) - }; - return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/core/test_pbuf.h b/components/net/lwip-2.0.2/test/unit/core/test_pbuf.h deleted file mode 100644 index da7730a4c8..0000000000 --- a/components/net/lwip-2.0.2/test/unit/core/test_pbuf.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_PBUF_H -#define LWIP_HDR_TEST_PBUF_H - -#include "../lwip_check.h" - -Suite *pbuf_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.c b/components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.c deleted file mode 100644 index 47aaa08420..0000000000 --- a/components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.c +++ /dev/null @@ -1,1024 +0,0 @@ -#include "test_dhcp.h" - -#include "lwip/netif.h" -#include "lwip/dhcp.h" -#include "lwip/prot/dhcp.h" -#include "lwip/etharp.h" -#include "netif/ethernet.h" - -struct netif net_test; - -static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - -static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 }; - -static u8_t dhcp_offer[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ - 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ - 0x08, 0x00, /* Protocol: IP */ - 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ - 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ - - 0x02, /* Type == Boot reply */ - 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ - 0x00, /* 0 hops */ - 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ - 0x00, 0x00, /* 0 seconds elapsed */ - 0x00, 0x00, /* Flags (unicast) */ - 0x00, 0x00, 0x00, 0x00, /* Client ip */ - 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ - 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ - 0x00, 0x00, 0x00, 0x00, /* relay agent */ - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ - - /* Empty server name and boot file name */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ - 0x35, 0x01, 0x02, /* Message type: Offer */ - 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ - 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ - 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ - 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ - 0xff, /* End option */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ -}; - -static u8_t dhcp_ack[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ - 0x00, 0x0f, 0xEE, 0x30, 0xAB, 0x22, /* From remote host */ - 0x08, 0x00, /* Proto IP */ - 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ - 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ - 0x02, /* Bootp reply */ - 0x01, 0x06, /* Hw type Eth, len 6 */ - 0x00, /* 0 hops */ - 0xAA, 0xAA, 0xAA, 0xAA, - 0x00, 0x00, /* 0 seconds elapsed */ - 0x00, 0x00, /* Flags (unicast) */ - 0x00, 0x00, 0x00, 0x00, /* Client IP */ - 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ - 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server IP */ - 0x00, 0x00, 0x00, 0x00, /* Relay agent */ - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Macaddr + padding */ - - /* Empty server name and boot file name */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - - 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ - 0x35, 0x01, 0x05, /* Dhcp message type ack */ - 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server identifier */ - 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ - 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ - 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Netmask */ - 0xff, /* End marker */ - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ -}; - -static const u8_t arpreply[] = { - 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* dst mac */ - 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* src mac */ - 0x08, 0x06, /* proto arp */ - 0x00, 0x01, /* hw eth */ - 0x08, 0x00, /* proto ip */ - 0x06, /* hw addr len 6 */ - 0x04, /* proto addr len 4 */ - 0x00, 0x02, /* arp reply */ - 0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* sender mac */ - 0xc3, 0xaa, 0xbd, 0xc8, /* sender ip */ - 0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* target mac */ - 0x00, 0x00, 0x00, 0x00, /* target ip */ -}; - -static int txpacket; -static enum tcase { - TEST_LWIP_DHCP, - TEST_LWIP_DHCP_NAK, - TEST_LWIP_DHCP_RELAY, - TEST_LWIP_DHCP_NAK_NO_ENDMARKER, - TEST_LWIP_DHCP_INVALID_OVERLOAD -} tcase; - -static int debug = 0; -static void setdebug(int a) {debug = a;} - -static int tick = 0; -static void tick_lwip(void) -{ - tick++; - if (tick % 5 == 0) { - dhcp_fine_tmr(); - } - if (tick % 600 == 0) { - dhcp_coarse_tmr(); - } -} - -static void send_pkt(struct netif *netif, const u8_t *data, size_t len) -{ - struct pbuf *p, *q; - LWIP_ASSERT("pkt too big", len <= 0xFFFF); - p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL); - - if (debug) { - /* Dump data */ - u32_t i; - printf("RX data (len %d)", p->tot_len); - for (i = 0; i < len; i++) { - printf(" %02X", data[i]); - } - printf("\n"); - } - - fail_unless(p != NULL); - for(q = p; q != NULL; q = q->next) { - memcpy(q->payload, data, q->len); - data += q->len; - } - netif->input(p, netif); -} - -static err_t lwip_tx_func(struct netif *netif, struct pbuf *p); - -static err_t testif_init(struct netif *netif) -{ - netif->name[0] = 'c'; - netif->name[1] = 'h'; - netif->output = etharp_output; - netif->linkoutput = lwip_tx_func; - netif->mtu = 1500; - netif->hwaddr_len = 6; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; - - netif->hwaddr[0] = 0x00; - netif->hwaddr[1] = 0x23; - netif->hwaddr[2] = 0xC1; - netif->hwaddr[3] = 0xDE; - netif->hwaddr[4] = 0xD0; - netif->hwaddr[5] = 0x0D; - - return ERR_OK; -} - -static void dhcp_setup(void) -{ - txpacket = 0; -} - -static void dhcp_teardown(void) -{ -} - -static void check_pkt(struct pbuf *p, u32_t pos, const u8_t *mem, u32_t len) -{ - u8_t *data; - - fail_if((pos + len) > p->tot_len); - while (pos > p->len && p->next) { - pos -= p->len; - p = p->next; - } - fail_if(p == NULL); - fail_unless(pos + len <= p->len); /* All data we seek within same pbuf */ - - data = (u8_t*)p->payload; - fail_if(memcmp(&data[pos], mem, len), "data at pos %d, len %d in packet %d did not match", pos, len, txpacket); -} - -static void check_pkt_fuzzy(struct pbuf *p, u32_t startpos, const u8_t *mem, u32_t len) -{ - int found; - u32_t i; - u8_t *data; - - fail_if((startpos + len) > p->tot_len); - while (startpos > p->len && p->next) { - startpos -= p->len; - p = p->next; - } - fail_if(p == NULL); - fail_unless(startpos + len <= p->len); /* All data we seek within same pbuf */ - - found = 0; - data = (u8_t*)p->payload; - for (i = startpos; i <= (p->len - len); i++) { - if (memcmp(&data[i], mem, len) == 0) { - found = 1; - break; - } - } - fail_unless(found); -} - -static err_t lwip_tx_func(struct netif *netif, struct pbuf *p) -{ - fail_unless(netif == &net_test); - txpacket++; - - if (debug) { - struct pbuf *pp = p; - /* Dump data */ - printf("TX data (pkt %d, len %d, tick %d)", txpacket, p->tot_len, tick); - do { - int i; - for (i = 0; i < pp->len; i++) { - printf(" %02X", ((u8_t *) pp->payload)[i]); - } - if (pp->next) { - pp = pp->next; - } - } while (pp->next); - printf("\n"); - } - - switch (tcase) { - case TEST_LWIP_DHCP: - switch (txpacket) { - case 1: - case 2: - { - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - /* Check dchp message type, can be at different positions */ - if (txpacket == 1) { - u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; - check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); - } else if (txpacket == 2) { - u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; - u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* Ask for offered IP */ - - check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); - check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); - } - break; - } - case 3: - case 4: - case 5: - { - const u8_t arpproto[] = { 0x08, 0x06 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ - break; - } - default: - fail(); - break; - } - break; - - case TEST_LWIP_DHCP_NAK: - { - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const u8_t dhcp_nak_opt[] = { 0x35, 0x01, 0x04 }; - const u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* offered IP */ - - fail_unless(txpacket == 4); - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - check_pkt_fuzzy(p, 282, dhcp_nak_opt, sizeof(dhcp_nak_opt)); /* NAK the ack */ - - check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); - break; - } - - case TEST_LWIP_DHCP_RELAY: - switch (txpacket) { - case 1: - case 2: - { - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - /* Check dchp message type, can be at different positions */ - if (txpacket == 1) { - u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 }; - check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt)); - } else if (txpacket == 2) { - u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; - u8_t requested_ipaddr[] = { 0x32, 0x04, 0x4f, 0x8a, 0x33, 0x05 }; /* Ask for offered IP */ - - check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); - check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr)); - } - break; - } - case 3: - case 4: - case 5: - case 6: - { - const u8_t arpproto[] = { 0x08, 0x06 }; - - check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */ - break; - } - case 7: - { - const u8_t fake_arp[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab }; - const u8_t ipproto[] = { 0x08, 0x00 }; - const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */ - const u8_t ipaddrs[] = { 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 }; - - check_pkt(p, 0, fake_arp, 6); /* eth level dest: broadcast */ - check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */ - - check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */ - - check_pkt(p, 42, bootp_start, sizeof(bootp_start)); - - check_pkt(p, 53, ipaddrs, sizeof(ipaddrs)); - - check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */ - - check_pkt(p, 278, magic_cookie, sizeof(magic_cookie)); - - /* Check dchp message type, can be at different positions */ - check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt)); - break; - } - default: - fail(); - break; - } - break; - - default: - break; - } - - return ERR_OK; -} - -/* - * Test basic happy flow DHCP session. - * Validate that xid is checked. - */ -START_TEST(test_dhcp) -{ - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - int i; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_offer[46], &xid, 4); - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_ack[46], &xid, 4); - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - for (i = 0; i < 20; i++) { - tick_lwip(); - } - fail_unless(txpacket == 5, "TX %d packets, expected 5", txpacket); /* ARP requests sent */ - - /* Interface up */ - fail_unless(netif_is_up(&net_test)); - - /* Now it should have taken the IP */ - IP4_ADDR(&addr, 195, 170, 189, 200); - IP4_ADDR(&netmask, 255, 255, 255, 0); - IP4_ADDR(&gw, 195, 170, 189, 171); - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - netif_remove(&net_test); -} -END_TEST - -/* - * Test that IP address is not taken and NAK is sent if someone - * replies to ARP requests for the offered address. - */ -START_TEST(test_dhcp_nak) -{ - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_offer[46], &xid, 4); - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - fail_unless(txpacket == 2); /* DHCP request sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_ack[46], &xid, 4); - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack)); - - fail_unless(txpacket == 3); /* ARP request sent */ - - tcase = TEST_LWIP_DHCP_NAK; /* Switch testcase */ - - /* Send arp reply, mark offered IP as taken */ - send_pkt(&net_test, arpreply, sizeof(arpreply)); - - fail_unless(txpacket == 4); /* DHCP nak sent */ - - netif_remove(&net_test); -} -END_TEST - -/* - * Test case based on captured data where - * replies are sent from a different IP than the - * one the client unicasted to. - */ -START_TEST(test_dhcp_relayed) -{ - u8_t relay_offer[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, - 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, - 0x08, 0x00, 0x45, 0x00, - 0x01, 0x38, 0xfd, 0x53, 0x00, 0x00, 0x40, 0x11, - 0x78, 0x46, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, - 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, - 0xb6, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, - 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, - 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, - 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x02, 0x36, - 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff - }; - - u8_t relay_ack1[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22, - 0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00, - 0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11, - 0x78, 0x44, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, - 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35, - 0xb6, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, - 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, - 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, - 0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x05, 0x36, - 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff - }; - - u8_t relay_ack2[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, - 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, - 0x08, 0x00, 0x45, 0x00, - 0x01, 0x38, 0xfa, 0x18, 0x00, 0x00, 0x40, 0x11, - 0x7b, 0x81, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a, - 0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x49, 0x8b, - 0x6e, 0xab, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8a, - 0x33, 0x05, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, - 0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08, - 0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1, - 0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04, - 0x00, 0x00, 0x54, 0x60, 0x35, 0x01, 0x05, 0x36, - 0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff }; - - const u8_t arp_resp[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* DEST */ - 0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, /* SRC */ - 0x08, 0x06, /* Type: ARP */ - 0x00, 0x01, /* HW: Ethernet */ - 0x08, 0x00, /* PROTO: IP */ - 0x06, /* HW size */ - 0x04, /* PROTO size */ - 0x00, 0x02, /* OPCODE: Reply */ - - 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, /* Target MAC */ - 0x4f, 0x8a, 0x32, 0x01, /* Target IP */ - - 0x00, 0x23, 0xc1, 0x00, 0x06, 0x50, /* src mac */ - 0x4f, 0x8a, 0x33, 0x05, /* src ip */ - - /* Padding follows.. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }; - - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - int i; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP_RELAY; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, relay_offer, sizeof(relay_offer)); - - /* request sent? */ - fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket); - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, relay_ack1, sizeof(relay_ack1)); - - for (i = 0; i < 25; i++) { - tick_lwip(); - } - fail_unless(txpacket == 5, "txpkt should be 5, is %d", txpacket); /* ARP requests sent */ - - /* Interface up */ - fail_unless(netif_is_up(&net_test)); - - /* Now it should have taken the IP */ - IP4_ADDR(&addr, 79, 138, 51, 5); - IP4_ADDR(&netmask, 255, 255, 254, 0); - IP4_ADDR(&gw, 79, 138, 50, 1); - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 5, "txpacket = %d", txpacket); - - for (i = 0; i < 108000 - 25; i++) { - tick_lwip(); - } - - fail_unless(netif_is_up(&net_test)); - fail_unless(txpacket == 6, "txpacket = %d", txpacket); - - /* We need to send arp response here.. */ - - send_pkt(&net_test, arp_resp, sizeof(arp_resp)); - - fail_unless(txpacket == 7, "txpacket = %d", txpacket); - fail_unless(netif_is_up(&net_test)); - - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, relay_ack2, sizeof(relay_ack2)); - - for (i = 0; i < 100000; i++) { - tick_lwip(); - } - - fail_unless(txpacket == 7, "txpacket = %d", txpacket); - - netif_remove(&net_test); - -} -END_TEST - -START_TEST(test_dhcp_nak_no_endmarker) -{ - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - - u8_t dhcp_nack_no_endmarker[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x54, 0x75, - 0xd0, 0x26, 0xd0, 0x0d, 0x08, 0x00, 0x45, 0x00, - 0x01, 0x15, 0x38, 0x86, 0x00, 0x00, 0xff, 0x11, - 0xc0, 0xa8, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x01, - 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x7a, 0xcb, - 0xba, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, - 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, - 0x53, 0x63, 0x35, 0x01, 0x06, 0x36, 0x04, 0xc0, - 0xa8, 0x01, 0x01, 0x31, 0xef, 0xad, 0x72, 0x31, - 0x43, 0x4e, 0x44, 0x30, 0x32, 0x35, 0x30, 0x43, - 0x52, 0x47, 0x44, 0x38, 0x35, 0x36, 0x3c, 0x08, - 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, - 0x37, 0x0d, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, - 0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xfc, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x71, - 0xf3, 0x5b, 0xe2, 0x71, 0x2e, 0x01, 0x08, 0x03, - 0x04, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xeb, 0x1e, - 0x44, 0xec, 0xeb, 0x1e, 0x30, 0x37, 0x0c, 0x01, - 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, - 0x79, 0xf9, 0x2b, 0xff, 0x25, 0xc0, 0x09, 0xd6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP_NAK_NO_ENDMARKER; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */ - memcpy(&dhcp_offer[46], &xid, 4); - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - - fail_unless(txpacket == 1); /* Nothing more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */ - send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer)); - - fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); - - fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */ - send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker)); - - /* NAK should put us in another state for a while, no other way detecting it */ - fail_unless(netif_dhcp_data(&net_test)->state != DHCP_STATE_REQUESTING); - - netif_remove(&net_test); -} -END_TEST - -START_TEST(test_dhcp_invalid_overload) -{ - u8_t dhcp_offer_invalid_overload[] = { - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */ - 0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */ - 0x08, 0x00, /* Protocol: IP */ - 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */ - 0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */ - - 0x02, /* Type == Boot reply */ - 0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */ - 0x00, /* 0 hops */ - 0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */ - 0x00, 0x00, /* 0 seconds elapsed */ - 0x00, 0x00, /* Flags (unicast) */ - 0x00, 0x00, 0x00, 0x00, /* Client ip */ - 0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */ - 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */ - 0x00, 0x00, 0x00, 0x00, /* relay agent */ - 0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */ - - /* Empty server name */ - 0x34, 0x01, 0x02, 0xff, /* Overload: SNAME + END */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Empty boot file name */ - 0x34, 0x01, 0x01, 0xff, /* Overload FILE + END */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x63, 0x82, 0x53, 0x63, /* Magic cookie */ - 0x35, 0x01, 0x02, /* Message type: Offer */ - 0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */ - 0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */ - 0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */ - 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */ - 0x34, 0x01, 0x03, /* Overload: FILE + SNAME */ - 0xff, /* End option */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */ - }; - ip4_addr_t addr; - ip4_addr_t netmask; - ip4_addr_t gw; - u32_t xid; - LWIP_UNUSED_ARG(_i); - - tcase = TEST_LWIP_DHCP_INVALID_OVERLOAD; - setdebug(0); - - IP4_ADDR(&addr, 0, 0, 0, 0); - IP4_ADDR(&netmask, 0, 0, 0, 0); - IP4_ADDR(&gw, 0, 0, 0, 0); - - netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input); - netif_set_up(&net_test); - - dhcp_start(&net_test); - - fail_unless(txpacket == 1); /* DHCP discover sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); - memcpy(&dhcp_offer_invalid_overload[46], &xid, 4); /* insert correct transaction id */ - dhcp_offer_invalid_overload[311] = 3; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - fail_unless(txpacket == 1); /* Nothing more sent */ - - dhcp_offer_invalid_overload[311] = 2; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - fail_unless(txpacket == 1); /* Nothing more sent */ - - dhcp_offer_invalid_overload[311] = 1; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload)); - /* IP addresses should be zero */ - fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t))); - fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t))); - fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t))); - fail_unless(txpacket == 1); /* Nothing more sent */ - - dhcp_offer_invalid_overload[311] = 0; - send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer)); - - fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING); - - fail_unless(txpacket == 2); /* No more sent */ - xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */ - - netif_remove(&net_test); -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -dhcp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_dhcp), - TESTFUNC(test_dhcp_nak), - TESTFUNC(test_dhcp_relayed), - TESTFUNC(test_dhcp_nak_no_endmarker), - TESTFUNC(test_dhcp_invalid_overload) - }; - return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.h b/components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.h deleted file mode 100644 index 0d88fa1b69..0000000000 --- a/components/net/lwip-2.0.2/test/unit/dhcp/test_dhcp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_DHCP_H -#define LWIP_HDR_TEST_DHCP_H - -#include "../lwip_check.h" - -Suite* dhcp_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/etharp/test_etharp.c b/components/net/lwip-2.0.2/test/unit/etharp/test_etharp.c deleted file mode 100644 index 59d73b9b45..0000000000 --- a/components/net/lwip-2.0.2/test/unit/etharp/test_etharp.c +++ /dev/null @@ -1,269 +0,0 @@ -#include "test_etharp.h" - -#include "lwip/udp.h" -#include "lwip/etharp.h" -#include "netif/ethernet.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS -#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled" -#endif -#if !ETHARP_SUPPORT_STATIC_ENTRIES -#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled" -#endif - -static struct netif test_netif; -static ip4_addr_t test_ipaddr, test_netmask, test_gw; -struct eth_addr test_ethaddr = {{1,1,1,1,1,1}}; -struct eth_addr test_ethaddr2 = {{1,1,1,1,1,2}}; -struct eth_addr test_ethaddr3 = {{1,1,1,1,1,3}}; -struct eth_addr test_ethaddr4 = {{1,1,1,1,1,4}}; -static int linkoutput_ctr; - -/* Helper functions */ -static void -etharp_remove_all(void) -{ - int i; - /* call etharp_tmr often enough to have all entries cleaned */ - for(i = 0; i < 0xff; i++) { - etharp_tmr(); - } -} - -static err_t -default_netif_linkoutput(struct netif *netif, struct pbuf *p) -{ - fail_unless(netif == &test_netif); - fail_unless(p != NULL); - linkoutput_ctr++; - return ERR_OK; -} - -static err_t -default_netif_init(struct netif *netif) -{ - fail_unless(netif != NULL); - netif->linkoutput = default_netif_linkoutput; - netif->output = etharp_output; - netif->mtu = 1500; - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - netif->hwaddr_len = ETHARP_HWADDR_LEN; - return ERR_OK; -} - -static void -default_netif_add(void) -{ - IP4_ADDR(&test_gw, 192,168,0,1); - IP4_ADDR(&test_ipaddr, 192,168,0,1); - IP4_ADDR(&test_netmask, 255,255,0,0); - - fail_unless(netif_default == NULL); - netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask, - &test_gw, NULL, default_netif_init, NULL)); - netif_set_up(&test_netif); -} - -static void -default_netif_remove(void) -{ - fail_unless(netif_default == &test_netif); - netif_remove(&test_netif); -} - -static void -create_arp_response(ip4_addr_t *adr) -{ - int k; - struct eth_hdr *ethhdr; - struct etharp_hdr *etharphdr; - struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM); - if(p == NULL) { - FAIL_RET(); - } - ethhdr = (struct eth_hdr*)p->payload; - etharphdr = (struct etharp_hdr*)(ethhdr + 1); - - ethhdr->dest = test_ethaddr; - ethhdr->src = test_ethaddr2; - ethhdr->type = htons(ETHTYPE_ARP); - - etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1); - etharphdr->proto = htons(ETHTYPE_IP); - etharphdr->hwlen = ETHARP_HWADDR_LEN; - etharphdr->protolen = sizeof(ip4_addr_t); - etharphdr->opcode = htons(ARP_REPLY); - - SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t)); - SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_addr_t)); - - k = 6; - while(k > 0) { - k--; - /* Write the ARP MAC-Addresses */ - etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k]; - etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k]; - /* Write the Ethernet MAC-Addresses */ - ethhdr->dest.addr[k] = test_ethaddr.addr[k]; - ethhdr->src.addr[k] = test_ethaddr2.addr[k]; - } - - ethernet_input(p, &test_netif); -} - -/* Setups/teardown functions */ - -static void -etharp_setup(void) -{ - etharp_remove_all(); - default_netif_add(); -} - -static void -etharp_teardown(void) -{ - etharp_remove_all(); - default_netif_remove(); -} - - -/* Test functions */ - -START_TEST(test_etharp_table) -{ -#if ETHARP_SUPPORT_STATIC_ENTRIES - err_t err; -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - s8_t idx; - const ip4_addr_t *unused_ipaddr; - struct eth_addr *unused_ethaddr; - struct udp_pcb* pcb; - LWIP_UNUSED_ARG(_i); - - if (netif_default != &test_netif) { - fail("This test needs a default netif"); - } - - linkoutput_ctr = 0; - - pcb = udp_new(); - fail_unless(pcb != NULL); - if (pcb != NULL) { - ip4_addr_t adrs[ARP_TABLE_SIZE + 2]; - int i; - for(i = 0; i < ARP_TABLE_SIZE + 2; i++) { - IP4_ADDR(&adrs[i], 192,168,0,i+2); - } - /* fill ARP-table with dynamic entries */ - for(i = 0; i < ARP_TABLE_SIZE; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); - fail_unless(p != NULL); - if (p != NULL) { - err_t err2; - ip_addr_t dst; - ip_addr_copy_from_ip4(dst, adrs[i]); - err2 = udp_sendto(pcb, p, &dst, 123); - fail_unless(err2 == ERR_OK); - /* etharp request sent? */ - fail_unless(linkoutput_ctr == (2*i) + 1); - pbuf_free(p); - - /* create an ARP response */ - create_arp_response(&adrs[i]); - /* queued UDP packet sent? */ - fail_unless(linkoutput_ctr == (2*i) + 2); - - idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == i); - etharp_tmr(); - } - } - linkoutput_ctr = 0; -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* create one static entry */ - err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - fail_unless(linkoutput_ctr == 0); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - - linkoutput_ctr = 0; - /* fill ARP-table with dynamic entries */ - for(i = 0; i < ARP_TABLE_SIZE; i++) { - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM); - fail_unless(p != NULL); - if (p != NULL) { - err_t err2; - ip_addr_t dst; - ip_addr_copy_from_ip4(dst, adrs[i]); - err2 = udp_sendto(pcb, p, &dst, 123); - fail_unless(err2 == ERR_OK); - /* etharp request sent? */ - fail_unless(linkoutput_ctr == (2*i) + 1); - pbuf_free(p); - - /* create an ARP response */ - create_arp_response(&adrs[i]); - /* queued UDP packet sent? */ - fail_unless(linkoutput_ctr == (2*i) + 2); - - idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr); - if (i < ARP_TABLE_SIZE - 1) { - fail_unless(idx == i+1); - } else { - /* the last entry must not overwrite the static entry! */ - fail_unless(idx == 1); - } - etharp_tmr(); - } - } -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* create a second static entry */ - err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 2); - /* and remove it again */ - err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == -1); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - - /* check that static entries don't time out */ - etharp_remove_all(); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == 0); - -#if ETHARP_SUPPORT_STATIC_ENTRIES - /* remove the first static entry */ - err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]); - fail_unless(err == ERR_OK); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == -1); - idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr); - fail_unless(idx == -1); -#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ - - udp_remove(pcb); - } -} -END_TEST - - -/** Create the suite including all tests for this module */ -Suite * -etharp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_etharp_table) - }; - return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/etharp/test_etharp.h b/components/net/lwip-2.0.2/test/unit/etharp/test_etharp.h deleted file mode 100644 index 2dd772d8d0..0000000000 --- a/components/net/lwip-2.0.2/test/unit/etharp/test_etharp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_ETHARP_H -#define LWIP_HDR_TEST_ETHARP_H - -#include "../lwip_check.h" - -Suite* etharp_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/lwip_check.h b/components/net/lwip-2.0.2/test/unit/lwip_check.h deleted file mode 100644 index 0c218d1d16..0000000000 --- a/components/net/lwip-2.0.2/test/unit/lwip_check.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef LWIP_HDR_LWIP_CHECK_H -#define LWIP_HDR_LWIP_CHECK_H - -/* Common header file for lwIP unit tests using the check framework */ - -#include -#include -#include - -#define FAIL_RET() do { fail(); return; } while(0) -#define EXPECT(x) fail_unless(x) -#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0) -#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0) -#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL) - -typedef struct { - TFun func; - const char *name; -} testfunc; - -#define TESTFUNC(x) {(x), "" # x "" } - -/* Modified function from check.h, supplying function name */ -#define tcase_add_named_test(tc,tf) \ - _tcase_add_test((tc),(tf).func,(tf).name,0, 0, 0, 1) - -/** typedef for a function returning a test suite */ -typedef Suite* (suite_getter_fn)(void); - -/** Create a test suite */ -Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown); - -#ifdef LWIP_UNITTESTS_LIB -int lwip_unittests_run(void) -#endif - -#endif /* LWIP_HDR_LWIP_CHECK_H */ diff --git a/components/net/lwip-2.0.2/test/unit/lwip_unittests.c b/components/net/lwip-2.0.2/test/unit/lwip_unittests.c deleted file mode 100644 index 46fd4308e1..0000000000 --- a/components/net/lwip-2.0.2/test/unit/lwip_unittests.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "lwip_check.h" - -#include "udp/test_udp.h" -#include "tcp/test_tcp.h" -#include "tcp/test_tcp_oos.h" -#include "core/test_mem.h" -#include "core/test_pbuf.h" -#include "etharp/test_etharp.h" -#include "dhcp/test_dhcp.h" -#include "mdns/test_mdns.h" - -#include "lwip/init.h" - -Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown) -{ - size_t i; - Suite *s = suite_create(name); - - for(i = 0; i < num_tests; i++) { - TCase *tc_core = tcase_create(name); - if ((setup != NULL) || (teardown != NULL)) { - tcase_add_checked_fixture(tc_core, setup, teardown); - } - tcase_add_named_test(tc_core, tests[i]); - suite_add_tcase(s, tc_core); - } - return s; -} - -#ifdef LWIP_UNITTESTS_LIB -int lwip_unittests_run(void) -#else -int main(void) -#endif -{ - int number_failed; - SRunner *sr; - size_t i; - suite_getter_fn* suites[] = { - udp_suite, - tcp_suite, - tcp_oos_suite, - mem_suite, - pbuf_suite, - etharp_suite, - dhcp_suite, - mdns_suite - }; - size_t num = sizeof(suites)/sizeof(void*); - LWIP_ASSERT("No suites defined", num > 0); - - lwip_init(); - - sr = srunner_create((suites[0])()); - for(i = 1; i < num; i++) { - srunner_add_suite(sr, ((suite_getter_fn*)suites[i])()); - } - -#ifdef LWIP_UNITTESTS_NOFORK - srunner_set_fork_status(sr, CK_NOFORK); -#endif -#ifdef LWIP_UNITTESTS_FORK - srunner_set_fork_status(sr, CK_FORK); -#endif - - srunner_run_all(sr, CK_NORMAL); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/components/net/lwip-2.0.2/test/unit/lwipopts.h b/components/net/lwip-2.0.2/test/unit/lwipopts.h deleted file mode 100644 index 25252b426c..0000000000 --- a/components/net/lwip-2.0.2/test/unit/lwipopts.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_LWIPOPTS_H -#define LWIP_HDR_LWIPOPTS_H - -/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ -#define NO_SYS 1 -#define SYS_LIGHTWEIGHT_PROT 0 -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 - -/* Enable DHCP to test it, disable UDP checksum to easier inject packets */ -#define LWIP_DHCP 1 - -/* Minimal changes to opt.h required for tcp unit tests: */ -#define MEM_SIZE 16000 -#define TCP_SND_QUEUELEN 40 -#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN -#define TCP_SND_BUF (12 * TCP_MSS) -#define TCP_WND (10 * TCP_MSS) -#define LWIP_WND_SCALE 1 -#define TCP_RCV_SCALE 0 -#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */ - -/* Enable IGMP and MDNS for MDNS tests */ -#define LWIP_IGMP 1 -#define LWIP_MDNS_RESPONDER 1 -#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER) - -/* Minimal changes to opt.h required for etharp unit tests: */ -#define ETHARP_SUPPORT_STATIC_ENTRIES 1 - -#endif /* LWIP_HDR_LWIPOPTS_H */ diff --git a/components/net/lwip-2.0.2/test/unit/mdns/test_mdns.c b/components/net/lwip-2.0.2/test/unit/mdns/test_mdns.c deleted file mode 100644 index ca9be64ea1..0000000000 --- a/components/net/lwip-2.0.2/test/unit/mdns/test_mdns.c +++ /dev/null @@ -1,915 +0,0 @@ -/* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "test_mdns.h" - -#include "lwip/pbuf.h" -#include "lwip/apps/mdns.h" -#include "lwip/apps/mdns_priv.h" - -START_TEST(readname_basic) -{ - static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(data)); - fail_if(memcmp(&domain.name, data, sizeof(data))); -} -END_TEST - -START_TEST(readname_anydata) -{ - static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(data)); - fail_if(memcmp(&domain.name, data, sizeof(data))); -} -END_TEST - -START_TEST(readname_short_buf) -{ - static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_long_label) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', - 0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', - 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_overflow) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_earlier) -{ - static const u8_t data[] = { - /* Some padding needed, not supported to jump to bytes containing dns header */ - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab, - /* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 20, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_jump_earlier_jump) -{ - static const u8_t data[] = { - /* Some padding needed, not supported to jump to bytes containing dns header */ - /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, - /* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10, - /* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16 - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0x18, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_jump_maxdepth) -{ - static const u8_t data[] = { - /* Some padding needed, not supported to jump to bytes containing dns header */ - /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2, - /* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03, - /* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10, - /* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00, - /* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0, - /* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28 - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', - 0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's', - 0x04, 'n', 'a', 'm', 'e', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0x30, &domain); - pbuf_free(p); - fail_unless(offset == sizeof(data)); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_jump_later) -{ - static const u8_t data[] = { - /* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40, - /* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab - }; - static const u8_t fullname[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == 13); - fail_unless(domain.length == sizeof(fullname)); - - fail_if(memcmp(&domain.name, fullname, sizeof(fullname))); -} -END_TEST - -START_TEST(readname_half_jump) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_toolong) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 0, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_loop_label) -{ - static const u8_t data[] = { - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 10, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(readname_jump_loop_jump) -{ - static const u8_t data[] = { - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - offset = mdns_readname(p, 10, &domain); - pbuf_free(p); - fail_unless(offset == MDNS_READNAME_ERROR); -} -END_TEST - -START_TEST(add_label_basic) -{ - static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 }; - struct mdns_domain domain; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - fail_unless(domain.length == sizeof(data)); - fail_if(memcmp(&domain.name, data, sizeof(data))); -} -END_TEST - -START_TEST(add_label_long_label) -{ - static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-"; - struct mdns_domain domain; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, toolong, (u8_t)strlen(toolong)); - fail_unless(res == ERR_VAL); -} -END_TEST - -START_TEST(add_label_full) -{ - static const char *label = "0123456789abcdef0123456789abcdef"; - struct mdns_domain domain; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 33); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 66); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 99); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 132); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 165); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 198); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label)); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, 25); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, 24); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 231); - res = mdns_domain_add_label(&domain, label, 23); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 255); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - fail_unless(domain.length == 256); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_VAL); - fail_unless(domain.length == 256); -} -END_TEST - -START_TEST(domain_eq_basic) -{ - static const u8_t data[] = { - 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 - }; - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - fail_unless(domain1.length == sizeof(data)); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_diff) -{ - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "base", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_if(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_case) -{ - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, "MulTI", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "casT", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_anydata) -{ - static const u8_t data1[] = { 0x05, 0xcc, 0xdc, 0x00, 0xa0 }; - static const u8_t data2[] = { 0x7f, 0x8c, 0x01, 0xff, 0xcf }; - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - res = mdns_domain_add_label(&domain1, (const char*)data1, sizeof(data1)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, (const char*)data2, sizeof(data2)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, NULL, 0); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - res = mdns_domain_add_label(&domain2, (const char*)data1, sizeof(data1)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "casT", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, (const char*)data2, sizeof(data2)); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, NULL, 0); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(domain_eq_length) -{ - struct mdns_domain domain1, domain2; - err_t res; - LWIP_UNUSED_ARG(_i); - - memset(&domain1, 0, sizeof(domain1)); - memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN)); - res = mdns_domain_add_label(&domain1, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain1, "cast", 4); - fail_unless(res == ERR_OK); - - memset(&domain2, 0, sizeof(domain2)); - memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN)); - res = mdns_domain_add_label(&domain2, "multi", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain2, "cast", 4); - fail_unless(res == ERR_OK); - - fail_unless(mdns_domain_eq(&domain1, &domain2)); -} -END_TEST - -START_TEST(compress_full_match) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 0 bytes, then a jump to addr 2 */ - fail_unless(length == 0); - fail_unless(offset == 2); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_full_match_subset) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 0 bytes, then a jump to addr 5 */ - fail_unless(length == 0); - fail_unless(offset == 5); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_full_match_jump) -{ - static const u8_t data[] = { - /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, - /* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 0x20; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 0 bytes, then a jump to addr 0x20 */ - fail_unless(length == 0); - fail_unless(offset == 0x20); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_no_match) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write all bytes, no jump */ - fail_unless(length == domain.length); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_2nd_label) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "lwip", 4); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 5 bytes, then a jump to addr 9 */ - fail_unless(length == 5); - fail_unless(offset == 9); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_2nd_label_short) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 5 bytes, then a jump to addr 7 */ - fail_unless(length == 7); - fail_unless(offset == 7); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_jump_to_jump) -{ - static const u8_t data[] = { - /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00, - /* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 0x20; - length = mdns_compress_domain(p, &offset, &domain); - /* Dont compress if jump would be to a jump */ - fail_unless(length == domain.length); - - offset = 0x10; - length = mdns_compress_domain(p, &offset, &domain); - /* Write 7 bytes, then a jump to addr 0x15 */ - fail_unless(length == 7); - fail_unless(offset == 0x15); - - pbuf_free(p); -} -END_TEST - -START_TEST(compress_long_match) -{ - static const u8_t data[] = { - 0x00, 0x00, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00 - }; - struct pbuf *p; - struct mdns_domain domain; - u16_t offset; - u16_t length; - err_t res; - LWIP_UNUSED_ARG(_i); - - p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM); - p->payload = (void *)(size_t)data; - fail_if(p == NULL); - - memset(&domain, 0, sizeof(domain)); - res = mdns_domain_add_label(&domain, "foobar", 6); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, "local", 5); - fail_unless(res == ERR_OK); - res = mdns_domain_add_label(&domain, NULL, 0); - fail_unless(res == ERR_OK); - - offset = 2; - length = mdns_compress_domain(p, &offset, &domain); - fail_unless(length == domain.length); - - pbuf_free(p); -} -END_TEST - -Suite* mdns_suite(void) -{ - testfunc tests[] = { - TESTFUNC(readname_basic), - TESTFUNC(readname_anydata), - TESTFUNC(readname_short_buf), - TESTFUNC(readname_long_label), - TESTFUNC(readname_overflow), - TESTFUNC(readname_jump_earlier), - TESTFUNC(readname_jump_earlier_jump), - TESTFUNC(readname_jump_maxdepth), - TESTFUNC(readname_jump_later), - TESTFUNC(readname_half_jump), - TESTFUNC(readname_jump_toolong), - TESTFUNC(readname_jump_loop_label), - TESTFUNC(readname_jump_loop_jump), - - TESTFUNC(add_label_basic), - TESTFUNC(add_label_long_label), - TESTFUNC(add_label_full), - - TESTFUNC(domain_eq_basic), - TESTFUNC(domain_eq_diff), - TESTFUNC(domain_eq_case), - TESTFUNC(domain_eq_anydata), - TESTFUNC(domain_eq_length), - - TESTFUNC(compress_full_match), - TESTFUNC(compress_full_match_subset), - TESTFUNC(compress_full_match_jump), - TESTFUNC(compress_no_match), - TESTFUNC(compress_2nd_label), - TESTFUNC(compress_2nd_label_short), - TESTFUNC(compress_jump_to_jump), - TESTFUNC(compress_long_match), - }; - return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL); -} diff --git a/components/net/lwip-2.0.2/test/unit/mdns/test_mdns.h b/components/net/lwip-2.0.2/test/unit/mdns/test_mdns.h deleted file mode 100644 index c3df339140..0000000000 --- a/components/net/lwip-2.0.2/test/unit/mdns/test_mdns.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_MDNS_H__ -#define LWIP_HDR_TEST_MDNS_H__ - -#include "../lwip_check.h" - -Suite* mdns_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.c b/components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.c deleted file mode 100644 index 64121ca8f3..0000000000 --- a/components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.c +++ /dev/null @@ -1,314 +0,0 @@ -#include "tcp_helper.h" - -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" -#include "lwip/pbuf.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip_addr.h" - -#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS -#error "This tests needs TCP- and MEMP-statistics enabled" -#endif - -/** Remove all pcbs on the given list. */ -static void -tcp_remove(struct tcp_pcb* pcb_list) -{ - struct tcp_pcb *pcb = pcb_list; - struct tcp_pcb *pcb2; - - while(pcb != NULL) { - pcb2 = pcb; - pcb = pcb->next; - tcp_abort(pcb2); - } -} - -/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */ -void -tcp_remove_all(void) -{ - tcp_remove(tcp_listen_pcbs.pcbs); - tcp_remove(tcp_active_pcbs); - tcp_remove(tcp_tw_pcbs); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_SEG) == 0); - fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0); -} - -/** Create a TCP segment usable for passing to tcp_input */ -static struct pbuf* -tcp_create_segment_wnd(ip_addr_t* src_ip, ip_addr_t* dst_ip, - u16_t src_port, u16_t dst_port, void* data, size_t data_len, - u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd) -{ - struct pbuf *p, *q; - struct ip_hdr* iphdr; - struct tcp_hdr* tcphdr; - u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len); - LWIP_ASSERT("data_len too big", data_len <= 0xFFFF); - - p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL); - EXPECT_RETNULL(p != NULL); - /* first pbuf must be big enough to hold the headers */ - EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); - if (data_len > 0) { - /* first pbuf must be big enough to hold at least 1 data byte, too */ - EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr))); - } - - for(q = p; q != NULL; q = q->next) { - memset(q->payload, 0, q->len); - } - - iphdr = (struct ip_hdr*)p->payload; - /* fill IP header */ - iphdr->dest.addr = ip_2_ip4(dst_ip)->addr; - iphdr->src.addr = ip_2_ip4(src_ip)->addr; - IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); - IPH_TOS_SET(iphdr, 0); - IPH_LEN_SET(iphdr, htons(p->tot_len)); - IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); - - /* let p point to TCP header */ - pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); - - tcphdr = (struct tcp_hdr*)p->payload; - tcphdr->src = htons(src_port); - tcphdr->dest = htons(dst_port); - tcphdr->seqno = htonl(seqno); - tcphdr->ackno = htonl(ackno); - TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4); - TCPH_FLAGS_SET(tcphdr, headerflags); - tcphdr->wnd = htons(wnd); - - if (data_len > 0) { - /* let p point to TCP data */ - pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr)); - /* copy data */ - pbuf_take(p, data, (u16_t)data_len); - /* let p point to TCP header again */ - pbuf_header(p, sizeof(struct tcp_hdr)); - } - - /* calculate checksum */ - - tcphdr->chksum = ip_chksum_pseudo(p, - IP_PROTO_TCP, p->tot_len, src_ip, dst_ip); - - pbuf_header(p, sizeof(struct ip_hdr)); - - return p; -} - -/** Create a TCP segment usable for passing to tcp_input */ -struct pbuf* -tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, - u16_t src_port, u16_t dst_port, void* data, size_t data_len, - u32_t seqno, u32_t ackno, u8_t headerflags) -{ - return tcp_create_segment_wnd(src_ip, dst_ip, src_port, dst_port, data, - data_len, seqno, ackno, headerflags, TCP_WND); -} - -/** Create a TCP segment usable for passing to tcp_input - * - IP-addresses, ports, seqno and ackno are taken from pcb - * - seqno and ackno can be altered with an offset - */ -struct pbuf* -tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset, - u32_t ackno_offset, u8_t headerflags) -{ - return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, - data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags); -} - -/** Create a TCP segment usable for passing to tcp_input - * - IP-addresses, ports, seqno and ackno are taken from pcb - * - seqno and ackno can be altered with an offset - * - TCP window can be adjusted - */ -struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, - u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd) -{ - return tcp_create_segment_wnd(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port, - data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags, wnd); -} - -/** Safely bring a tcp_pcb into the requested state */ -void -tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, - ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port) -{ - u32_t iss; - - /* @todo: are these all states? */ - /* @todo: remove from previous list */ - pcb->state = state; - - iss = tcp_next_iss(pcb); - pcb->snd_wl2 = iss; - pcb->snd_nxt = iss; - pcb->lastack = iss; - pcb->snd_lbb = iss; - - if (state == ESTABLISHED) { - TCP_REG(&tcp_active_pcbs, pcb); - ip_addr_copy(pcb->local_ip, *local_ip); - pcb->local_port = local_port; - ip_addr_copy(pcb->remote_ip, *remote_ip); - pcb->remote_port = remote_port; - } else if(state == LISTEN) { - TCP_REG(&tcp_listen_pcbs.pcbs, pcb); - ip_addr_copy(pcb->local_ip, *local_ip); - pcb->local_port = local_port; - } else if(state == TIME_WAIT) { - TCP_REG(&tcp_tw_pcbs, pcb); - ip_addr_copy(pcb->local_ip, *local_ip); - pcb->local_port = local_port; - ip_addr_copy(pcb->remote_ip, *remote_ip); - pcb->remote_port = remote_port; - } else { - fail(); - } -} - -void -test_tcp_counters_err(void* arg, err_t err) -{ - struct test_tcp_counters* counters = (struct test_tcp_counters*)arg; - EXPECT_RET(arg != NULL); - counters->err_calls++; - counters->last_err = err; -} - -static void -test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p) -{ - struct pbuf* q; - u32_t i, received; - if(counters->expected_data == NULL) { - /* no data to compare */ - return; - } - EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len); - received = counters->recved_bytes; - for(q = p; q != NULL; q = q->next) { - char *data = (char*)q->payload; - for(i = 0; i < q->len; i++) { - EXPECT_RET(data[i] == counters->expected_data[received]); - received++; - } - } - EXPECT(received == counters->recved_bytes + p->tot_len); -} - -err_t -test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err) -{ - struct test_tcp_counters* counters = (struct test_tcp_counters*)arg; - EXPECT_RETX(arg != NULL, ERR_OK); - EXPECT_RETX(pcb != NULL, ERR_OK); - EXPECT_RETX(err == ERR_OK, ERR_OK); - - if (p != NULL) { - if (counters->close_calls == 0) { - counters->recv_calls++; - test_tcp_counters_check_rxdata(counters, p); - counters->recved_bytes += p->tot_len; - } else { - counters->recv_calls_after_close++; - counters->recved_bytes_after_close += p->tot_len; - } - pbuf_free(p); - } else { - counters->close_calls++; - } - EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0); - return ERR_OK; -} - -/** Allocate a pcb and set up the test_tcp_counters_* callbacks */ -struct tcp_pcb* -test_tcp_new_counters_pcb(struct test_tcp_counters* counters) -{ - struct tcp_pcb* pcb = tcp_new(); - if (pcb != NULL) { - /* set up args and callbacks */ - tcp_arg(pcb, counters); - tcp_recv(pcb, test_tcp_counters_recv); - tcp_err(pcb, test_tcp_counters_err); - pcb->snd_wnd = TCP_WND; - pcb->snd_wnd_max = TCP_WND; - } - return pcb; -} - -/** Calls tcp_input() after adjusting current_iphdr_dest */ -void test_tcp_input(struct pbuf *p, struct netif *inp) -{ - struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; - /* these lines are a hack, don't use them as an example :-) */ - ip_addr_copy_from_ip4(*ip_current_dest_addr(), iphdr->dest); - ip_addr_copy_from_ip4(*ip_current_src_addr(), iphdr->src); - ip_current_netif() = inp; - ip_data.current_ip4_header = iphdr; - - /* since adding IPv6, p->payload must point to tcp header, not ip header */ - pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); - - tcp_input(p, inp); - - ip_addr_set_zero(ip_current_dest_addr()); - ip_addr_set_zero(ip_current_src_addr()); - ip_current_netif() = NULL; - ip_data.current_ip4_header = NULL; -} - -static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p, - const ip4_addr_t *ipaddr) -{ - struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state; - LWIP_UNUSED_ARG(ipaddr); - if (txcounters != NULL) - { - txcounters->num_tx_calls++; - txcounters->num_tx_bytes += p->tot_len; - if (txcounters->copy_tx_packets) { - struct pbuf *p_copy = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); - err_t err; - EXPECT(p_copy != NULL); - err = pbuf_copy(p_copy, p); - EXPECT(err == ERR_OK); - if (txcounters->tx_packets == NULL) { - txcounters->tx_packets = p_copy; - } else { - pbuf_cat(txcounters->tx_packets, p_copy); - } - } - } - return ERR_OK; -} - -void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, - ip_addr_t *ip_addr, ip_addr_t *netmask) -{ - struct netif *n; - memset(netif, 0, sizeof(struct netif)); - if (txcounters != NULL) { - memset(txcounters, 0, sizeof(struct test_tcp_txcounters)); - netif->state = txcounters; - } - netif->output = test_tcp_netif_output; - netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; - ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask)); - ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr)); - for (n = netif_list; n != NULL; n = n->next) { - if (n == netif) { - return; - } - } - netif->next = NULL; - netif_list = netif; -} diff --git a/components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.h b/components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.h deleted file mode 100644 index 04974818e7..0000000000 --- a/components/net/lwip-2.0.2/test/unit/tcp/tcp_helper.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef LWIP_HDR_TCP_HELPER_H -#define LWIP_HDR_TCP_HELPER_H - -#include "../lwip_check.h" -#include "lwip/arch.h" -#include "lwip/tcp.h" -#include "lwip/netif.h" - -/* counters used for test_tcp_counters_* callback functions */ -struct test_tcp_counters { - u32_t recv_calls; - u32_t recved_bytes; - u32_t recv_calls_after_close; - u32_t recved_bytes_after_close; - u32_t close_calls; - u32_t err_calls; - err_t last_err; - char* expected_data; - u32_t expected_data_len; -}; - -struct test_tcp_txcounters { - u32_t num_tx_calls; - u32_t num_tx_bytes; - u8_t copy_tx_packets; - struct pbuf *tx_packets; -}; - -/* Helper functions */ -void tcp_remove_all(void); - -struct pbuf* tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip, - u16_t src_port, u16_t dst_port, void* data, size_t data_len, - u32_t seqno, u32_t ackno, u8_t headerflags); -struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, - u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags); -struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len, - u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd); -void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip, - ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port); -void test_tcp_counters_err(void* arg, err_t err); -err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err); - -struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters); - -void test_tcp_input(struct pbuf *p, struct netif *inp); - -void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, - ip_addr_t *ip_addr, ip_addr_t *netmask); - - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp.c b/components/net/lwip-2.0.2/test/unit/tcp/test_tcp.c deleted file mode 100644 index d99b807d96..0000000000 --- a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp.c +++ /dev/null @@ -1,744 +0,0 @@ -#include "test_tcp.h" - -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" -#include "tcp_helper.h" -#include "lwip/inet_chksum.h" - -#ifdef _MSC_VER -#pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */ -#endif - -#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS -#error "This tests needs TCP- and MEMP-statistics enabled" -#endif -#if TCP_SND_BUF <= TCP_WND -#error "This tests needs TCP_SND_BUF to be > TCP_WND" -#endif - -static u8_t test_tcp_timer; - -/* our own version of tcp_tmr so we can reset fast/slow timer state */ -static void -test_tcp_tmr(void) -{ - tcp_fasttmr(); - if (++test_tcp_timer & 1) { - tcp_slowtmr(); - } -} - -/* Setups/teardown functions */ - -static void -tcp_setup(void) -{ - /* reset iss to default (6510) */ - tcp_ticks = 0; - tcp_ticks = 0 - (tcp_next_iss(NULL) - 6510); - tcp_next_iss(NULL); - tcp_ticks = 0; - - test_tcp_timer = 0; - tcp_remove_all(); -} - -static void -tcp_teardown(void) -{ - netif_list = NULL; - netif_default = NULL; - tcp_remove_all(); -} - - -/* Test functions */ - -/** Call tcp_new() and tcp_abort() and test memp stats */ -START_TEST(test_tcp_new_abort) -{ - struct tcp_pcb* pcb; - LWIP_UNUSED_ARG(_i); - - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); - - pcb = tcp_new(); - fail_unless(pcb != NULL); - if (pcb != NULL) { - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); - } -} -END_TEST - -/** Create an ESTABLISHED pcb and check if receive callback is called */ -START_TEST(test_tcp_recv_inseq) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - char data[] = {1, 2, 3, 4}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - struct test_tcp_txcounters txcounters; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create a segment */ - p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); - EXPECT(p != NULL); - if (p != NULL) { - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == data_len); - EXPECT(counters.err_calls == 0); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -/** Check that we handle malformed tcp headers, and discard the pbuf(s) */ -START_TEST(test_tcp_malformed_header) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - char data[] = {1, 2, 3, 4}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len, chksum; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - struct test_tcp_txcounters txcounters; - struct tcp_hdr *hdr; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create a segment */ - p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); - - pbuf_header(p, -(s16_t)sizeof(struct ip_hdr)); - - hdr = (struct tcp_hdr *)p->payload; - TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1); - - hdr->chksum = 0; - - chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len, - &remote_ip, &local_ip); - - hdr->chksum = chksum; - - pbuf_header(p, sizeof(struct ip_hdr)); - - EXPECT(p != NULL); - EXPECT(p->next == NULL); - if (p != NULL) { - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - - -/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. - * At the end, send more data. */ -START_TEST(test_tcp_fast_retx_recover) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - char data1[] = { 1, 2, 3, 4}; - char data2[] = { 5, 6, 7, 8}; - char data3[] = { 9, 10, 11, 12}; - char data4[] = {13, 14, 15, 16}; - char data5[] = {17, 18, 19, 20}; - char data6[TCP_MSS] = {21, 22, 23, 24}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = pcb->snd_wnd; - - /* send data1 */ - err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT_RET(txcounters.num_tx_calls == 1); - EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); - memset(&txcounters, 0, sizeof(txcounters)); - /* "recv" ACK for data1 */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(pcb->unacked == NULL); - /* send data2 */ - err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT_RET(txcounters.num_tx_calls == 1); - EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr)); - memset(&txcounters, 0, sizeof(txcounters)); - /* duplicate ACK for data1 (data2 is lost) */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(pcb->dupacks == 1); - /* send data3 */ - err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* nagle enabled, no tx calls */ - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(txcounters.num_tx_bytes == 0); - memset(&txcounters, 0, sizeof(txcounters)); - /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(pcb->dupacks == 2); - /* queue data4, don't send it (unsent-oversize is != 0) */ - err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - /*EXPECT_RET(txcounters.num_tx_calls == 1);*/ - EXPECT_RET(pcb->dupacks == 3); - memset(&txcounters, 0, sizeof(txcounters)); - /* @todo: check expected data?*/ - - /* send data5, not output yet */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - /*err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK);*/ - EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(txcounters.num_tx_bytes == 0); - memset(&txcounters, 0, sizeof(txcounters)); - { - int i = 0; - do - { - err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY); - i++; - }while(err == ERR_OK); - EXPECT_RET(err != ERR_OK); - } - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /*EXPECT_RET(txcounters.num_tx_calls == 0); - EXPECT_RET(txcounters.num_tx_bytes == 0);*/ - memset(&txcounters, 0, sizeof(txcounters)); - - /* send even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - - /* send ACKs for data2 and data3 */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK); - EXPECT_RET(p != NULL); - test_tcp_input(p, &netif); - /*EXPECT_RET(txcounters.num_tx_calls == 0);*/ - - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - /* ...and even more data */ - err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - -#if 0 - /* create expected segment */ - p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0); - EXPECT_RET(p != NULL); - if (p != NULL) { - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT_RET(counters.close_calls == 0); - EXPECT_RET(counters.recv_calls == 1); - EXPECT_RET(counters.recved_bytes == data_len); - EXPECT_RET(counters.err_calls == 0); - } -#endif - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -static u8_t tx_data[TCP_WND*2]; - -static void -check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected) -{ - struct tcp_seg *s = segs; - int i; - for (i = 0; i < num_expected; i++, s = s->next) { - EXPECT_RET(s != NULL); - EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i])); - } - EXPECT(s == NULL); -} - -/** Send data with sequence numbers that wrap around the u32_t range. - * Then, provoke fast retransmission by duplicate ACKs and check that all - * segment lists are still properly sorted. */ -START_TEST(test_tcp_fast_rexmit_wraparound) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf* p; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; -#define SEQNO1 (0xFFFFFF00 - TCP_MSS) -#define ISS 6510 - u16_t i, sent_total = 0; - u32_t seqnos[] = { - SEQNO1, - SEQNO1 + (1 * TCP_MSS), - SEQNO1 + (2 * TCP_MSS), - SEQNO1 + (3 * TCP_MSS), - SEQNO1 + (4 * TCP_MSS), - SEQNO1 + (5 * TCP_MSS)}; - LWIP_UNUSED_ARG(_i); - - for (i = 0; i < sizeof(tx_data); i++) { - tx_data[i] = (u8_t)i; - } - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - - /* create and initialize the pcb */ - tcp_ticks = SEQNO1 - ISS; - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = 2*TCP_MSS; - /* start in congestion advoidance */ - pcb->ssthresh = pcb->cwnd; - - /* send 6 mss-sized segments */ - for (i = 0; i < 6; i++) { - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - sent_total += TCP_MSS; - } - check_seqnos(pcb->unsent, 6, seqnos); - EXPECT(pcb->unacked == NULL); - err = tcp_output(pcb); - EXPECT(txcounters.num_tx_calls == 2); - EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); - memset(&txcounters, 0, sizeof(txcounters)); - - check_seqnos(pcb->unacked, 2, seqnos); - check_seqnos(pcb->unsent, 4, &seqnos[2]); - - /* ACK the first segment */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK); - test_tcp_input(p, &netif); - /* ensure this didn't trigger a retransmission. Only one - segment should be transmitted because cwnd opened up by - TCP_MSS and a fraction since we are in congestion avoidance */ - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - check_seqnos(pcb->unacked, 2, &seqnos[1]); - check_seqnos(pcb->unsent, 3, &seqnos[3]); - - /* 3 dupacks */ - EXPECT(pcb->dupacks == 0); - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(pcb->dupacks == 1); - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(pcb->dupacks == 2); - /* 3rd dupack -> fast rexmit */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - EXPECT(pcb->dupacks == 3); - EXPECT(txcounters.num_tx_calls == 4); - memset(&txcounters, 0, sizeof(txcounters)); - EXPECT(pcb->unsent == NULL); - check_seqnos(pcb->unacked, 5, &seqnos[1]); - - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -/** Send data with sequence numbers that wrap around the u32_t range. - * Then, provoke RTO retransmission and check that all - * segment lists are still properly sorted. */ -START_TEST(test_tcp_rto_rexmit_wraparound) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; -#define SEQNO1 (0xFFFFFF00 - TCP_MSS) -#define ISS 6510 - u16_t i, sent_total = 0; - u32_t seqnos[] = { - SEQNO1, - SEQNO1 + (1 * TCP_MSS), - SEQNO1 + (2 * TCP_MSS), - SEQNO1 + (3 * TCP_MSS), - SEQNO1 + (4 * TCP_MSS), - SEQNO1 + (5 * TCP_MSS)}; - LWIP_UNUSED_ARG(_i); - - for (i = 0; i < sizeof(tx_data); i++) { - tx_data[i] = (u8_t)i; - } - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - - /* create and initialize the pcb */ - tcp_ticks = 0; - tcp_ticks = 0 - tcp_next_iss(NULL); - tcp_ticks = SEQNO1 - tcp_next_iss(NULL); - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = 2*TCP_MSS; - - /* send 6 mss-sized segments */ - for (i = 0; i < 6; i++) { - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - sent_total += TCP_MSS; - } - check_seqnos(pcb->unsent, 6, seqnos); - EXPECT(pcb->unacked == NULL); - err = tcp_output(pcb); - EXPECT(txcounters.num_tx_calls == 2); - EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U)); - memset(&txcounters, 0, sizeof(txcounters)); - - check_seqnos(pcb->unacked, 2, seqnos); - check_seqnos(pcb->unsent, 4, &seqnos[2]); - - /* call the tcp timer some times */ - for (i = 0; i < 10; i++) { - test_tcp_tmr(); - EXPECT(txcounters.num_tx_calls == 0); - } - /* 11th call to tcp_tmr: RTO rexmit fires */ - test_tcp_tmr(); - EXPECT(txcounters.num_tx_calls == 1); - check_seqnos(pcb->unacked, 1, seqnos); - check_seqnos(pcb->unsent, 5, &seqnos[1]); - - /* fake greater cwnd */ - pcb->cwnd = pcb->snd_wnd; - /* send more data */ - err = tcp_output(pcb); - EXPECT(err == ERR_OK); - /* check queues are sorted */ - EXPECT(pcb->unsent == NULL); - check_seqnos(pcb->unacked, 6, seqnos); - - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -/** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data. - * At the end, send more data. */ -static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent) -{ - struct netif netif; - struct test_tcp_txcounters txcounters; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - err_t err; - u16_t sent_total, i; - u8_t expected = 0xFE; - - for (i = 0; i < sizeof(tx_data); i++) { - u8_t d = (u8_t)i; - if (d == 0xFE) { - d = 0xF0; - } - tx_data[i] = d; - } - if (zero_window_probe_from_unsent) { - tx_data[TCP_WND] = expected; - } else { - tx_data[0] = expected; - } - - /* initialize local vars */ - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask); - memset(&counters, 0, sizeof(counters)); - memset(&txcounters, 0, sizeof(txcounters)); - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->mss = TCP_MSS; - /* disable initial congestion window (we don't send a SYN here...) */ - pcb->cwnd = pcb->snd_wnd; - - /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */ - sent_total = 0; - if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) { - u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS; - err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - sent_total += initial_data_len; - } - for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) { - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - } - EXPECT(sent_total == (TCP_WND - TCP_MSS)); - - /* now ACK the packet before the first */ - p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK); - test_tcp_input(p, &netif); - /* ensure this didn't trigger a retransmission */ - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - - EXPECT(pcb->persist_backoff == 0); - /* send the last packet, now a complete window has been sent */ - err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY); - sent_total += TCP_MSS; - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U); - memset(&txcounters, 0, sizeof(txcounters)); - EXPECT(pcb->persist_backoff == 0); - - if (zero_window_probe_from_unsent) { - /* ACK all data but close the TX window */ - p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0); - test_tcp_input(p, &netif); - /* ensure this didn't trigger any transmission */ - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - EXPECT(pcb->persist_backoff == 1); - } - - /* send one byte more (out of window) -> persist timer starts */ - err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY); - EXPECT_RET(err == ERR_OK); - err = tcp_output(pcb); - EXPECT_RET(err == ERR_OK); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - memset(&txcounters, 0, sizeof(txcounters)); - if (!zero_window_probe_from_unsent) { - /* no persist timer unless a zero window announcement has been received */ - EXPECT(pcb->persist_backoff == 0); - } else { - EXPECT(pcb->persist_backoff == 1); - - /* call tcp_timer some more times to let persist timer count up */ - for (i = 0; i < 4; i++) { - test_tcp_tmr(); - EXPECT(txcounters.num_tx_calls == 0); - EXPECT(txcounters.num_tx_bytes == 0); - } - - /* this should trigger the zero-window-probe */ - txcounters.copy_tx_packets = 1; - test_tcp_tmr(); - txcounters.copy_tx_packets = 0; - EXPECT(txcounters.num_tx_calls == 1); - EXPECT(txcounters.num_tx_bytes == 1 + 40U); - EXPECT(txcounters.tx_packets != NULL); - if (txcounters.tx_packets != NULL) { - u8_t sent; - u16_t ret; - ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U); - EXPECT(ret == 1); - EXPECT(sent == expected); - } - if (txcounters.tx_packets != NULL) { - pbuf_free(txcounters.tx_packets); - txcounters.tx_packets = NULL; - } - } - - /* make sure the pcb is freed */ - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} - -START_TEST(test_tcp_tx_full_window_lost_from_unsent) -{ - LWIP_UNUSED_ARG(_i); - test_tcp_tx_full_window_lost(1); -} -END_TEST - -START_TEST(test_tcp_tx_full_window_lost_from_unacked) -{ - LWIP_UNUSED_ARG(_i); - test_tcp_tx_full_window_lost(0); -} -END_TEST - -/** Create the suite including all tests for this module */ -Suite * -tcp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_tcp_new_abort), - TESTFUNC(test_tcp_recv_inseq), - TESTFUNC(test_tcp_malformed_header), - TESTFUNC(test_tcp_fast_retx_recover), - TESTFUNC(test_tcp_fast_rexmit_wraparound), - TESTFUNC(test_tcp_rto_rexmit_wraparound), - TESTFUNC(test_tcp_tx_full_window_lost_from_unacked), - TESTFUNC(test_tcp_tx_full_window_lost_from_unsent) - }; - return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp.h b/components/net/lwip-2.0.2/test/unit/tcp/test_tcp.h deleted file mode 100644 index f28ee56530..0000000000 --- a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_TCP_H -#define LWIP_HDR_TEST_TCP_H - -#include "../lwip_check.h" - -Suite *tcp_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.c b/components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.c deleted file mode 100644 index be61172251..0000000000 --- a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.c +++ /dev/null @@ -1,1049 +0,0 @@ -#include "test_tcp_oos.h" - -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" -#include "tcp_helper.h" - -#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS -#error "This tests needs TCP- and MEMP-statistics enabled" -#endif -#if !TCP_QUEUE_OOSEQ -#error "This tests needs TCP_QUEUE_OOSEQ enabled" -#endif - -/** CHECK_SEGMENTS_ON_OOSEQ: - * 1: check count, seqno and len of segments on pcb->ooseq (strict) - * 0: only check that bytes are received in correct order (less strict) */ -#define CHECK_SEGMENTS_ON_OOSEQ 1 - -#if CHECK_SEGMENTS_ON_OOSEQ -#define EXPECT_OOSEQ(x) EXPECT(x) -#else -#define EXPECT_OOSEQ(x) -#endif - -/* helper functions */ - -/** Get the numbers of segments on the ooseq list */ -static int tcp_oos_count(struct tcp_pcb* pcb) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - while(seg != NULL) { - num++; - seg = seg->next; - } - return num; -} - -#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) -/** Get the numbers of pbufs on the ooseq list */ -static int tcp_oos_pbuf_count(struct tcp_pcb* pcb) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - while(seg != NULL) { - num += pbuf_clen(seg->p); - seg = seg->next; - } - return num; -} -#endif - -/** Get the seqno of a segment (by index) on the ooseq list - * - * @param pcb the pcb to check for ooseq segments - * @param seg_index index of the segment on the ooseq list - * @return seqno of the segment - */ -static u32_t -tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - - /* then check the actual segment */ - while(seg != NULL) { - if(num == seg_index) { - return seg->tcphdr->seqno; - } - num++; - seg = seg->next; - } - fail(); - return 0; -} - -/** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list - * - * @param pcb the pcb to check for ooseq segments - * @param seg_index index of the segment on the ooseq list - * @return tcplen of the segment - */ -static int -tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index) -{ - int num = 0; - struct tcp_seg* seg = pcb->ooseq; - - /* then check the actual segment */ - while(seg != NULL) { - if(num == seg_index) { - return TCP_TCPLEN(seg); - } - num++; - seg = seg->next; - } - fail(); - return -1; -} - -/** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list - * - * @param pcb the pcb to check for ooseq segments - * @return tcplen of all segment - */ -static int -tcp_oos_tcplen(struct tcp_pcb* pcb) -{ - int len = 0; - struct tcp_seg* seg = pcb->ooseq; - - /* then check the actual segment */ - while(seg != NULL) { - len += TCP_TCPLEN(seg); - seg = seg->next; - } - return len; -} - -/* Setup/teardown functions */ - -static void -tcp_oos_setup(void) -{ - tcp_remove_all(); -} - -static void -tcp_oos_teardown(void) -{ - tcp_remove_all(); - netif_list = NULL; - netif_default = NULL; -} - - - -/* Test functions */ - -/** create multiple segments and pass them to tcp_input in a wrong - * order to see if ooseq-caching works correctly - * FIN is received in out-of-sequence segments only */ -START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq; - char data[] = { - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12, - 13, 14, 15, 16}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create segments */ - /* pinseq is sent as last segment! */ - pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); - /* p1: 8 bytes before FIN */ - /* seqno: 8..16 */ - p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN); - /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ - /* seqno: 4..11 */ - p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); - /* p3: same as p2 but 2 bytes longer */ - /* seqno: 4..13 */ - p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK); - /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */ - /* seqno: 2..15 */ - p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK); - /* FIN, seqno 16 */ - p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN); - EXPECT(pinseq != NULL); - EXPECT(p_8_9 != NULL); - EXPECT(p_4_8 != NULL); - EXPECT(p_4_10 != NULL); - EXPECT(p_2_14 != NULL); - EXPECT(p_fin != NULL); - if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) { - /* pass the segment to tcp_input */ - test_tcp_input(p_8_9, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_4_8, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_4_10, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* ooseq queue: unchanged */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_2_14, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(p_fin, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* ooseq queue: unchanged */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */ - - /* pass the segment to tcp_input */ - test_tcp_input(pinseq, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 1); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == data_len); - EXPECT(counters.err_calls == 0); - EXPECT(pcb->ooseq == NULL); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - - -/** create multiple segments and pass them to tcp_input in a wrong - * order to see if ooseq-caching works correctly - * FIN is received IN-SEQUENCE at the end */ -START_TEST(test_tcp_recv_ooseq_FIN_INSEQ) -{ - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN; - char data[] = { - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12, - 13, 14, 15, 16}; - ip_addr_t remote_ip, local_ip, netmask; - u16_t data_len; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - LWIP_UNUSED_ARG(_i); - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - data_len = sizeof(data); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = data_len; - counters.expected_data = data; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - - /* create segments */ - /* p1: 7 bytes - 2 before FIN */ - /* seqno: 1..2 */ - p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK); - /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */ - /* seqno: 4..11 */ - p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK); - /* p3: same as p2 but 2 bytes longer and one byte more at the front */ - /* seqno: 3..13 */ - p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK); - /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */ - /* seqno: 2..13 */ - p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK); - /* pinseq is the first segment that is held back to create ooseq! */ - /* seqno: 0..3 */ - pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK); - /* p5: last byte before FIN */ - /* seqno: 15 */ - p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); - /* p6: same as p5, should be ignored */ - p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK); - /* pinseqFIN: last 2 bytes plus FIN */ - /* only segment containing seqno 14 and FIN */ - pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN); - EXPECT(pinseq != NULL); - EXPECT(p_1_2 != NULL); - EXPECT(p_4_8 != NULL); - EXPECT(p_3_11 != NULL); - EXPECT(p_2_12 != NULL); - EXPECT(p_15_1 != NULL); - EXPECT(p_15_1a != NULL); - EXPECT(pinseqFIN != NULL); - if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL) - && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) { - /* pass the segment to tcp_input */ - test_tcp_input(p_1_2, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); - - /* pass the segment to tcp_input */ - test_tcp_input(p_4_8, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8); - - /* pass the segment to tcp_input */ - test_tcp_input(p_3_11, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2); - /* p_3_11 has removed p_4_8 from ooseq */ - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11); - - /* pass the segment to tcp_input */ - test_tcp_input(p_2_12, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12); - - /* pass the segment to tcp_input */ - test_tcp_input(pinseq, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == 14); - EXPECT(counters.err_calls == 0); - EXPECT(pcb->ooseq == NULL); - - /* pass the segment to tcp_input */ - test_tcp_input(p_15_1, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == 14); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); - - /* pass the segment to tcp_input */ - test_tcp_input(p_15_1a, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 1); - EXPECT(counters.recved_bytes == 14); - EXPECT(counters.err_calls == 0); - /* check ooseq queue: unchanged */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == 1); - EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15); - EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); - - /* pass the segment to tcp_input */ - test_tcp_input(pinseqFIN, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 1); - EXPECT(counters.recv_calls == 2); - EXPECT(counters.recved_bytes == data_len); - EXPECT(counters.err_calls == 0); - EXPECT(pcb->ooseq == NULL); - } - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} -END_TEST - -static char data_full_wnd[TCP_WND + TCP_MSS]; - -/** create multiple segments and pass them to tcp_input with the first segment missing - * to simulate overruning the rxwin with ooseq queueing enabled */ -START_TEST(test_tcp_recv_ooseq_overrun_rxwin) -{ -#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *pinseq, *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < (int)sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* create segments */ - /* pinseq is sent as last segment! */ - pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); - - for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { - int count, expected_datalen; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], - TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_count(pcb); - EXPECT_OOSEQ(count == k+1); - datalen = tcp_oos_tcplen(pcb); - if (i + TCP_MSS < TCP_WND) { - expected_datalen = (k+1)*TCP_MSS; - } else { - expected_datalen = TCP_WND - TCP_MSS; - } - if (datalen != expected_datalen) { - EXPECT_OOSEQ(datalen == expected_datalen); - } - } - - /* pass in one more segment, cleary overrunning the rxwin */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == k); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == datalen2); - - /* now pass inseq */ - test_tcp_input(pinseq, &netif); - EXPECT(pcb->ooseq == NULL); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -/** similar to above test, except seqno starts near the max rxwin */ -START_TEST(test_tcp_recv_ooseq_overrun_rxwin_edge) -{ -#if !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *pinseq, *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < (int)sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0xffffffff - (TCP_WND / 2); - - /* create segments */ - /* pinseq is sent as last segment! */ - pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); - - for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) { - int count, expected_datalen; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], - TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_count(pcb); - EXPECT_OOSEQ(count == k+1); - datalen = tcp_oos_tcplen(pcb); - if (i + TCP_MSS < TCP_WND) { - expected_datalen = (k+1)*TCP_MSS; - } else { - expected_datalen = TCP_WND - TCP_MSS; - } - if (datalen != expected_datalen) { - EXPECT_OOSEQ(datalen == expected_datalen); - } - } - - /* pass in one more segment, cleary overrunning the rxwin */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == k); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == datalen2); - - /* now pass inseq */ - test_tcp_input(pinseq, &netif); - EXPECT(pcb->ooseq == NULL); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* !TCP_OOSEQ_MAX_BYTES && !TCP_OOSEQ_MAX_PBUFS */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -START_TEST(test_tcp_recv_ooseq_max_bytes) -{ -#if TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ - - /* create segments and 'recv' them */ - for(k = 1, i = 1; k < TCP_OOSEQ_MAX_BYTES; k += TCP_MSS, i++) { - int count; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[k], - TCP_MSS, k, 0, TCP_ACK); - EXPECT_RET(p != NULL); - EXPECT_RET(p->next == NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_pbuf_count(pcb); - EXPECT_OOSEQ(count == i); - datalen = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == (i * TCP_MSS)); - } - - /* pass in one more segment, overrunning the limit */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[k+1], 1, k+1, 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue (ensure the new segment was not accepted) */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen2 == ((i-1) * TCP_MSS)); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* TCP_OOSEQ_MAX_BYTES && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -START_TEST(test_tcp_recv_ooseq_max_pbufs) -{ -#if TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_PBUFS < ((TCP_WND / TCP_MSS) + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) - int i; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_ovr; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - int datalen = 0; - int datalen2; - - for(i = 0; i < sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* don't 'recv' the first segment (1 byte) so that all other segments will be ooseq */ - - /* create segments and 'recv' them */ - for(i = 1; i <= TCP_OOSEQ_MAX_PBUFS; i++) { - int count; - struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[i], - 1, i, 0, TCP_ACK); - EXPECT_RET(p != NULL); - EXPECT_RET(p->next == NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue */ - count = tcp_oos_pbuf_count(pcb); - EXPECT_OOSEQ(count == i); - datalen = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen == i); - } - - /* pass in one more segment, overrunning the limit */ - p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[i+1], 1, i+1, 0, TCP_ACK); - EXPECT_RET(p_ovr != NULL); - /* pass the segment to tcp_input */ - test_tcp_input(p_ovr, &netif); - /* check if counters are as expected */ - EXPECT(counters.close_calls == 0); - EXPECT(counters.recv_calls == 0); - EXPECT(counters.recved_bytes == 0); - EXPECT(counters.err_calls == 0); - /* check ooseq queue (ensure the new segment was not accepted) */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == (i-1)); - datalen2 = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(datalen2 == (i-1)); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -#endif /* TCP_OOSEQ_MAX_PBUFS && (TCP_OOSEQ_MAX_BYTES < (TCP_WND + 1)) && (PBUF_POOL_BUFSIZE >= (TCP_MSS + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN)) */ - LWIP_UNUSED_ARG(_i); -} -END_TEST - -static void -check_rx_counters(struct tcp_pcb *pcb, struct test_tcp_counters *counters, u32_t exp_close_calls, u32_t exp_rx_calls, - u32_t exp_rx_bytes, u32_t exp_err_calls, int exp_oos_count, int exp_oos_len) -{ - int oos_len; - EXPECT(counters->close_calls == exp_close_calls); - EXPECT(counters->recv_calls == exp_rx_calls); - EXPECT(counters->recved_bytes == exp_rx_bytes); - EXPECT(counters->err_calls == exp_err_calls); - /* check that pbuf is queued in ooseq */ - EXPECT_OOSEQ(tcp_oos_count(pcb) == exp_oos_count); - oos_len = tcp_oos_tcplen(pcb); - EXPECT_OOSEQ(exp_oos_len == oos_len); -} - -/* this test uses 4 packets: - * - data (len=TCP_MSS) - * - FIN - * - data after FIN (len=1) (invalid) - * - 2nd FIN (invalid) - * - * the parameter 'delay_packet' is a bitmask that choses which on these packets is ooseq - */ -static void test_tcp_recv_ooseq_double_FINs(int delay_packet) -{ - int i, k; - struct test_tcp_counters counters; - struct tcp_pcb* pcb; - struct pbuf *p_normal_fin, *p_data_after_fin, *p, *p_2nd_fin_ooseq; - ip_addr_t remote_ip, local_ip, netmask; - u16_t remote_port = 0x100, local_port = 0x101; - struct netif netif; - u32_t exp_rx_calls = 0, exp_rx_bytes = 0, exp_close_calls = 0, exp_oos_pbufs = 0, exp_oos_tcplen = 0; - int first_dropped = 0xff; - - for(i = 0; i < (int)sizeof(data_full_wnd); i++) { - data_full_wnd[i] = (char)i; - } - - /* initialize local vars */ - memset(&netif, 0, sizeof(netif)); - IP_ADDR4(&local_ip, 192, 168, 1, 1); - IP_ADDR4(&remote_ip, 192, 168, 1, 2); - IP_ADDR4(&netmask, 255, 255, 255, 0); - test_tcp_init_netif(&netif, NULL, &local_ip, &netmask); - /* initialize counter struct */ - memset(&counters, 0, sizeof(counters)); - counters.expected_data_len = TCP_WND; - counters.expected_data = data_full_wnd; - - /* create and initialize the pcb */ - pcb = test_tcp_new_counters_pcb(&counters); - EXPECT_RET(pcb != NULL); - tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port); - pcb->rcv_nxt = 0x8000; - - /* create segments */ - p = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK); - p_normal_fin = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS, 0, TCP_ACK|TCP_FIN); - k = 1; - p_data_after_fin = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS+1], k, TCP_MSS+1, 0, TCP_ACK); - p_2nd_fin_ooseq = tcp_create_rx_segment(pcb, NULL, 0, TCP_MSS+1+k, 0, TCP_ACK|TCP_FIN); - - if(delay_packet & 1) { - /* drop normal data */ - first_dropped = 1; - } else { - /* send normal data */ - test_tcp_input(p, &netif); - exp_rx_calls++; - exp_rx_bytes += TCP_MSS; - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 2) { - /* drop FIN */ - if(first_dropped > 2) { - first_dropped = 2; - } - } else { - /* send FIN */ - test_tcp_input(p_normal_fin, &netif); - if (first_dropped < 2) { - /* already dropped packets, this one is ooseq */ - exp_oos_pbufs++; - exp_oos_tcplen++; - } else { - /* inseq */ - exp_close_calls++; - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 4) { - /* drop data-after-FIN */ - if(first_dropped > 3) { - first_dropped = 3; - } - } else { - /* send data-after-FIN */ - test_tcp_input(p_data_after_fin, &netif); - if (first_dropped < 3) { - /* already dropped packets, this one is ooseq */ - if (delay_packet & 2) { - /* correct FIN was ooseq */ - exp_oos_pbufs++; - exp_oos_tcplen += k; - } - } else { - /* inseq: no change */ - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 8) { - /* drop 2nd-FIN */ - if(first_dropped > 4) { - first_dropped = 4; - } - } else { - /* send 2nd-FIN */ - test_tcp_input(p_2nd_fin_ooseq, &netif); - if (first_dropped < 3) { - /* already dropped packets, this one is ooseq */ - if (delay_packet & 2) { - /* correct FIN was ooseq */ - exp_oos_pbufs++; - exp_oos_tcplen++; - } - } else { - /* inseq: no change */ - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 1) { - /* dropped normal data before */ - test_tcp_input(p, &netif); - exp_rx_calls++; - exp_rx_bytes += TCP_MSS; - if((delay_packet & 2) == 0) { - /* normal FIN was NOT delayed */ - exp_close_calls++; - exp_oos_pbufs = exp_oos_tcplen = 0; - } - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 2) { - /* dropped normal FIN before */ - test_tcp_input(p_normal_fin, &netif); - exp_close_calls++; - exp_oos_pbufs = exp_oos_tcplen = 0; - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 4) { - /* dropped data-after-FIN before */ - test_tcp_input(p_data_after_fin, &netif); - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - if(delay_packet & 8) { - /* dropped 2nd-FIN before */ - test_tcp_input(p_2nd_fin_ooseq, &netif); - } - /* check if counters are as expected */ - check_rx_counters(pcb, &counters, exp_close_calls, exp_rx_calls, exp_rx_bytes, 0, exp_oos_pbufs, exp_oos_tcplen); - - /* check that ooseq data has been dumped */ - EXPECT(pcb->ooseq == NULL); - - /* make sure the pcb is freed */ - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); - tcp_abort(pcb); - EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); -} - -/** create multiple segments and pass them to tcp_input with the first segment missing - * to simulate overruning the rxwin with ooseq queueing enabled */ -#define FIN_TEST(name, num) \ - START_TEST(name) \ - { \ - LWIP_UNUSED_ARG(_i); \ - test_tcp_recv_ooseq_double_FINs(num); \ - } \ - END_TEST -FIN_TEST(test_tcp_recv_ooseq_double_FIN_0, 0) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_1, 1) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_2, 2) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_3, 3) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_4, 4) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_5, 5) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_6, 6) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_7, 7) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_8, 8) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_9, 9) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_10, 10) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_11, 11) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_12, 12) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_13, 13) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_14, 14) -FIN_TEST(test_tcp_recv_ooseq_double_FIN_15, 15) - - -/** Create the suite including all tests for this module */ -Suite * -tcp_oos_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_tcp_recv_ooseq_FIN_OOSEQ), - TESTFUNC(test_tcp_recv_ooseq_FIN_INSEQ), - TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin), - TESTFUNC(test_tcp_recv_ooseq_overrun_rxwin_edge), - TESTFUNC(test_tcp_recv_ooseq_max_bytes), - TESTFUNC(test_tcp_recv_ooseq_max_pbufs), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_0), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_1), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_2), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_3), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_4), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_5), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_6), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_7), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_8), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_9), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_10), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_11), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_12), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_13), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_14), - TESTFUNC(test_tcp_recv_ooseq_double_FIN_15) - }; - return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(testfunc), tcp_oos_setup, tcp_oos_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.h b/components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.h deleted file mode 100644 index 5b82013b73..0000000000 --- a/components/net/lwip-2.0.2/test/unit/tcp/test_tcp_oos.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_TCP_OOS_H -#define LWIP_HDR_TEST_TCP_OOS_H - -#include "../lwip_check.h" - -Suite *tcp_oos_suite(void); - -#endif diff --git a/components/net/lwip-2.0.2/test/unit/udp/test_udp.c b/components/net/lwip-2.0.2/test/unit/udp/test_udp.c deleted file mode 100644 index 147822f492..0000000000 --- a/components/net/lwip-2.0.2/test/unit/udp/test_udp.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "test_udp.h" - -#include "lwip/udp.h" -#include "lwip/stats.h" - -#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS -#error "This tests needs UDP- and MEMP-statistics enabled" -#endif - -/* Helper functions */ -static void -udp_remove_all(void) -{ - struct udp_pcb *pcb = udp_pcbs; - struct udp_pcb *pcb2; - - while(pcb != NULL) { - pcb2 = pcb; - pcb = pcb->next; - udp_remove(pcb2); - } - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); -} - -/* Setups/teardown functions */ - -static void -udp_setup(void) -{ - udp_remove_all(); -} - -static void -udp_teardown(void) -{ - udp_remove_all(); -} - - -/* Test functions */ - -START_TEST(test_udp_new_remove) -{ - struct udp_pcb* pcb; - LWIP_UNUSED_ARG(_i); - - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); - - pcb = udp_new(); - fail_unless(pcb != NULL); - if (pcb != NULL) { - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 1); - udp_remove(pcb); - fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0); - } -} -END_TEST - - -/** Create the suite including all tests for this module */ -Suite * -udp_suite(void) -{ - testfunc tests[] = { - TESTFUNC(test_udp_new_remove), - }; - return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown); -} diff --git a/components/net/lwip-2.0.2/test/unit/udp/test_udp.h b/components/net/lwip-2.0.2/test/unit/udp/test_udp.h deleted file mode 100644 index 5426bf42e7..0000000000 --- a/components/net/lwip-2.0.2/test/unit/udp/test_udp.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef LWIP_HDR_TEST_UDP_H -#define LWIP_HDR_TEST_UDP_H - -#include "../lwip_check.h" - -Suite* udp_suite(void); - -#endif From c89735a357dda9f3249a90346e033b64e5a1a499 Mon Sep 17 00:00:00 2001 From: "Man, Jianting (Meco)" <920369182@qq.com> Date: Thu, 20 Jan 2022 07:55:31 -0500 Subject: [PATCH 37/65] [libdl] move libdl to posix folder (#5523) --- components/libc/Kconfig | 10 ---- .../libc_syms.c => gcc/newlib/dlsyms.c} | 46 +++++++++++-------- components/libc/posix/Kconfig | 10 ++++ components/libc/{ => posix}/libdl/SConscript | 4 +- components/libc/{ => posix}/libdl/arch/arm.c | 0 .../libc/{ => posix}/libdl/arch/riscv.c | 0 components/libc/{ => posix}/libdl/arch/x86.c | 0 components/libc/{ => posix}/libdl/dlclose.c | 0 components/libc/{ => posix}/libdl/dlelf.c | 0 components/libc/{ => posix}/libdl/dlelf.h | 0 components/libc/{ => posix}/libdl/dlerror.c | 0 components/libc/{ => posix}/libdl/dlfcn.h | 0 components/libc/{ => posix}/libdl/dlmodule.c | 14 +++--- components/libc/{ => posix}/libdl/dlmodule.h | 0 components/libc/{ => posix}/libdl/dlopen.c | 0 components/libc/{ => posix}/libdl/dlsym.c | 0 16 files changed, 46 insertions(+), 38 deletions(-) rename components/libc/compilers/{armlibc/libc_syms.c => gcc/newlib/dlsyms.c} (62%) rename components/libc/{ => posix}/libdl/SConscript (65%) rename components/libc/{ => posix}/libdl/arch/arm.c (100%) rename components/libc/{ => posix}/libdl/arch/riscv.c (100%) rename components/libc/{ => posix}/libdl/arch/x86.c (100%) rename components/libc/{ => posix}/libdl/dlclose.c (100%) rename components/libc/{ => posix}/libdl/dlelf.c (100%) rename components/libc/{ => posix}/libdl/dlelf.h (100%) rename components/libc/{ => posix}/libdl/dlerror.c (100%) rename components/libc/{ => posix}/libdl/dlfcn.h (100%) rename components/libc/{ => posix}/libdl/dlmodule.c (99%) rename components/libc/{ => posix}/libdl/dlmodule.h (100%) rename components/libc/{ => posix}/libdl/dlopen.c (100%) rename components/libc/{ => posix}/libdl/dlsym.c (100%) diff --git a/components/libc/Kconfig b/components/libc/Kconfig index 0556cf6183..71547e7970 100644 --- a/components/libc/Kconfig +++ b/components/libc/Kconfig @@ -1,15 +1,5 @@ menu "POSIX layer and C standard library" -config RT_USING_MODULE - bool "Enable dynamic module with dlopen/dlsym/dlclose feature" - default n - -if RT_USING_MODULE - config RT_USING_CUSTOM_DLMODULE - bool "Enable load dynamic module by custom" - default n -endif - config RT_LIBC_DEFAULT_TIMEZONE int "Set the default time zone (UTC+)" range -12 12 diff --git a/components/libc/compilers/armlibc/libc_syms.c b/components/libc/compilers/gcc/newlib/dlsyms.c similarity index 62% rename from components/libc/compilers/armlibc/libc_syms.c rename to components/libc/compilers/gcc/newlib/dlsyms.c index 2b370a25a6..e6ca23b393 100644 --- a/components/libc/compilers/armlibc/libc_syms.c +++ b/components/libc/compilers/gcc/newlib/dlsyms.c @@ -5,25 +5,26 @@ * * Change Logs: * Date Author Notes + * 2017/10/15 bernard the first version */ -#include -#include -#include -#include +#include #include -/* some export routines for module */ +#include +#include +#include -RTM_EXPORT(strstr); -RTM_EXPORT(strlen); -RTM_EXPORT(strchr); RTM_EXPORT(strcpy); RTM_EXPORT(strncpy); -RTM_EXPORT(strcmp); -RTM_EXPORT(strncmp); +RTM_EXPORT(strlen); RTM_EXPORT(strcat); +RTM_EXPORT(strstr); +RTM_EXPORT(strchr); +RTM_EXPORT(strcmp); RTM_EXPORT(strtol); +RTM_EXPORT(strtoul); +RTM_EXPORT(strncmp); RTM_EXPORT(memcpy); RTM_EXPORT(memcmp); @@ -31,13 +32,22 @@ RTM_EXPORT(memmove); RTM_EXPORT(memset); RTM_EXPORT(memchr); -RTM_EXPORT(toupper); -RTM_EXPORT(atoi); - -/* import the full stdio for printf */ -#if defined(RT_USING_MODULE) && defined(__MICROLIB) -#error "[RT_USING_LIBC] Please use standard libc but not microlib." -#endif - +RTM_EXPORT(putchar); RTM_EXPORT(puts); RTM_EXPORT(printf); +RTM_EXPORT(sprintf); +RTM_EXPORT(snprintf); + +RTM_EXPORT(fwrite); + +#include +RTM_EXPORT(longjmp); +RTM_EXPORT(setjmp); + +RTM_EXPORT(exit); +RTM_EXPORT(abort); + +RTM_EXPORT(rand); + +#include +RTM_EXPORT(__assert_func); diff --git a/components/libc/posix/Kconfig b/components/libc/posix/Kconfig index 8f527fa46d..5c766d9509 100644 --- a/components/libc/posix/Kconfig +++ b/components/libc/posix/Kconfig @@ -65,6 +65,16 @@ if RT_USING_PTHREADS default 8 endif +config RT_USING_MODULE + bool "Enable dynamic module with dlopen/dlsym/dlclose feature" + default n + +if RT_USING_MODULE + config RT_USING_CUSTOM_DLMODULE + bool "Enable load dynamic module by custom" + default n +endif + source "$RTT_DIR/components/libc/posix/ipc/Kconfig" endmenu diff --git a/components/libc/libdl/SConscript b/components/libc/posix/libdl/SConscript similarity index 65% rename from components/libc/libdl/SConscript rename to components/libc/posix/libdl/SConscript index 93636e4b7a..964e05ef76 100644 --- a/components/libc/libdl/SConscript +++ b/components/libc/posix/libdl/SConscript @@ -7,8 +7,6 @@ group = [] CPPPATH = [cwd] if rtconfig.PLATFORM == 'gcc': - group = DefineGroup('libc', src, - depend = ['RT_USING_MODULE'], - CPPPATH = CPPPATH) + group = DefineGroup('POSIX', src, depend = ['RT_USING_MODULE'], CPPPATH = CPPPATH) Return('group') diff --git a/components/libc/libdl/arch/arm.c b/components/libc/posix/libdl/arch/arm.c similarity index 100% rename from components/libc/libdl/arch/arm.c rename to components/libc/posix/libdl/arch/arm.c diff --git a/components/libc/libdl/arch/riscv.c b/components/libc/posix/libdl/arch/riscv.c similarity index 100% rename from components/libc/libdl/arch/riscv.c rename to components/libc/posix/libdl/arch/riscv.c diff --git a/components/libc/libdl/arch/x86.c b/components/libc/posix/libdl/arch/x86.c similarity index 100% rename from components/libc/libdl/arch/x86.c rename to components/libc/posix/libdl/arch/x86.c diff --git a/components/libc/libdl/dlclose.c b/components/libc/posix/libdl/dlclose.c similarity index 100% rename from components/libc/libdl/dlclose.c rename to components/libc/posix/libdl/dlclose.c diff --git a/components/libc/libdl/dlelf.c b/components/libc/posix/libdl/dlelf.c similarity index 100% rename from components/libc/libdl/dlelf.c rename to components/libc/posix/libdl/dlelf.c diff --git a/components/libc/libdl/dlelf.h b/components/libc/posix/libdl/dlelf.h similarity index 100% rename from components/libc/libdl/dlelf.h rename to components/libc/posix/libdl/dlelf.h diff --git a/components/libc/libdl/dlerror.c b/components/libc/posix/libdl/dlerror.c similarity index 100% rename from components/libc/libdl/dlerror.c rename to components/libc/posix/libdl/dlerror.c diff --git a/components/libc/libdl/dlfcn.h b/components/libc/posix/libdl/dlfcn.h similarity index 100% rename from components/libc/libdl/dlfcn.h rename to components/libc/posix/libdl/dlfcn.h diff --git a/components/libc/libdl/dlmodule.c b/components/libc/posix/libdl/dlmodule.c similarity index 99% rename from components/libc/libdl/dlmodule.c rename to components/libc/posix/libdl/dlmodule.c index 32d6b6b7e7..ffa23de82d 100644 --- a/components/libc/libdl/dlmodule.c +++ b/components/libc/posix/libdl/dlmodule.c @@ -14,7 +14,7 @@ #include "dlmodule.h" #include "dlelf.h" -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS #include #include #include @@ -423,14 +423,14 @@ struct rt_dlmodule *rt_module_self(void) struct rt_dlmodule* dlmodule_load(const char* filename) { -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS int fd = -1, length = 0; #endif rt_err_t ret = RT_EOK; rt_uint8_t *module_ptr = RT_NULL; struct rt_dlmodule *module = RT_NULL; -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS fd = open(filename, O_RDONLY, 0); if (fd >= 0) { @@ -522,7 +522,7 @@ struct rt_dlmodule* dlmodule_load(const char* filename) return module; __exit: -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS if (fd >= 0) close(fd); #endif if (module_ptr) rt_free(module_ptr); @@ -573,7 +573,7 @@ struct rt_dlmodule* dlmodule_exec(const char* pgname, const char* cmd, int cmd_s #if defined(RT_USING_CUSTOM_DLMODULE) struct rt_dlmodule* dlmodule_load_custom(const char* filename, struct rt_dlmodule_ops* ops) { -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS int fd = -1, length = 0; #endif rt_err_t ret = RT_EOK; @@ -586,7 +586,7 @@ struct rt_dlmodule* dlmodule_load_custom(const char* filename, struct rt_dlmodul RT_ASSERT(ops->unload); module_ptr = ops->load(filename); } -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS else { fd = open(filename, O_RDONLY, 0); @@ -688,7 +688,7 @@ struct rt_dlmodule* dlmodule_load_custom(const char* filename, struct rt_dlmodul return module; __exit: -#if defined(RT_USING_POSIX) +#ifdef RT_USING_POSIX_FS if (fd >= 0) close(fd); #endif if (module_ptr) diff --git a/components/libc/libdl/dlmodule.h b/components/libc/posix/libdl/dlmodule.h similarity index 100% rename from components/libc/libdl/dlmodule.h rename to components/libc/posix/libdl/dlmodule.h diff --git a/components/libc/libdl/dlopen.c b/components/libc/posix/libdl/dlopen.c similarity index 100% rename from components/libc/libdl/dlopen.c rename to components/libc/posix/libdl/dlopen.c diff --git a/components/libc/libdl/dlsym.c b/components/libc/posix/libdl/dlsym.c similarity index 100% rename from components/libc/libdl/dlsym.c rename to components/libc/posix/libdl/dlsym.c From 563e49890c597c53adba954063c37b03644c5c69 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 18 Jan 2022 00:35:13 -0500 Subject: [PATCH 38/65] =?UTF-8?q?[asm]=20=E8=A7=A3=E5=86=B3tab=E5=92=8C?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC=E6=B7=B7=E7=94=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libcpu/aarch64/common/cache.S | 4 +- libcpu/aarch64/common/context_gcc.S | 284 +++++------ libcpu/aarch64/common/cpu_gcc.S | 106 ++-- libcpu/aarch64/common/startup_gcc.S | 4 +- libcpu/aarch64/common/vector_gcc.S | 10 +- libcpu/arc/em/contex_gcc_mw.S | 436 ++++++++-------- libcpu/arm/AT91SAM7S/context_gcc.S | 76 +-- libcpu/arm/AT91SAM7S/context_rvds.S | 66 +-- libcpu/arm/AT91SAM7S/start_gcc.S | 334 ++++++------- libcpu/arm/AT91SAM7X/context_gcc.S | 76 +-- libcpu/arm/AT91SAM7X/context_rvds.S | 122 ++--- libcpu/arm/AT91SAM7X/start_gcc.S | 338 ++++++------- libcpu/arm/am335x/cp15_gcc.S | 74 +-- libcpu/arm/am335x/cp15_iar.s | 82 +-- libcpu/arm/am335x/start_gcc.S | 6 +- libcpu/arm/am335x/start_iar.s | 22 +- libcpu/arm/am335x/vector_gcc.S | 4 +- libcpu/arm/arm926/context_iar.S | 2 +- libcpu/arm/arm926/start_gcc.S | 46 +- libcpu/arm/armv6/arm_entry_gcc.S | 158 +++--- libcpu/arm/common/divsi3.S | 640 ++++++++++++------------ libcpu/arm/cortex-a/start_gcc.S | 2 +- libcpu/arm/cortex-m0/context_gcc.S | 20 +- libcpu/arm/cortex-m0/context_rvds.S | 6 +- libcpu/arm/cortex-m23/context_gcc.S | 20 +- libcpu/arm/cortex-m23/context_rvds.S | 6 +- libcpu/arm/cortex-m3/context_gcc.S | 6 +- libcpu/arm/cortex-m3/context_rvds.S | 2 +- libcpu/arm/cortex-m33/context_iar.S | 2 +- libcpu/arm/cortex-m33/syscall_gcc.S | 4 +- libcpu/arm/cortex-m33/syscall_iar.S | 4 +- libcpu/arm/cortex-m33/syscall_rvds.S | 8 +- libcpu/arm/cortex-m4/context_gcc.S | 6 +- libcpu/arm/cortex-m7/context_gcc.S | 4 +- libcpu/arm/cortex-r4/context_ccs.asm | 28 +- libcpu/arm/cortex-r4/context_gcc.S | 22 +- libcpu/arm/cortex-r4/start_ccs.asm | 26 +- libcpu/arm/cortex-r4/start_gcc.S | 18 +- libcpu/arm/dm36x/context_rvds.S | 122 ++--- libcpu/arm/lpc214x/context_gcc.S | 128 ++--- libcpu/arm/lpc214x/context_rvds.S | 170 +++---- libcpu/arm/lpc214x/startup_gcc.S | 324 ++++++------ libcpu/arm/lpc24xx/context_gcc.S | 76 +-- libcpu/arm/lpc24xx/context_rvds.S | 124 ++--- libcpu/arm/lpc24xx/start_gcc.S | 34 +- libcpu/arm/lpc24xx/start_rvds.S | 120 ++--- libcpu/arm/realview-a8-vmm/start_gcc.S | 20 +- libcpu/arm/realview-a8-vmm/vector_gcc.S | 4 +- libcpu/arm/s3c24x0/context_gcc.S | 76 +-- libcpu/arm/s3c24x0/context_rvds.S | 122 ++--- libcpu/arm/s3c24x0/start_gcc.S | 498 +++++++++--------- libcpu/arm/s3c24x0/start_rvds.S | 26 +- libcpu/arm/s3c44b0/context_gcc.S | 76 +-- libcpu/arm/s3c44b0/context_rvds.S | 122 ++--- libcpu/arm/s3c44b0/start_gcc.S | 306 +++++------ libcpu/arm/sep4020/context_rvds.S | 122 ++--- libcpu/arm/zynqmp-r5/context_gcc.S | 8 +- libcpu/arm/zynqmp-r5/start_gcc.S | 74 +-- libcpu/arm/zynqmp-r5/vector_gcc.S | 4 +- libcpu/avr32/uc3/context_gcc.S | 72 +-- libcpu/ia32/context_gcc.S | 86 ++-- libcpu/ia32/hdisr_gcc.S | 110 ++-- libcpu/ia32/start_gcc.S | 88 ++-- libcpu/ia32/trapisr_gcc.S | 90 ++-- libcpu/m16c/m16c62p/context_gcc.S | 18 +- libcpu/m16c/m16c62p/context_iar.S | 10 +- libcpu/m16c/m16c62p/context_iar.asm | 10 +- libcpu/mips/common/context_gcc.S | 4 +- libcpu/mips/common/entry_gcc.S | 32 +- libcpu/mips/common/exception_gcc.S | 34 +- libcpu/mips/gs232/cache_gcc.S | 172 +++---- libcpu/mips/gs232/cpuinit_gcc.S | 6 +- libcpu/mips/pic32/context_gcc.S | 22 +- libcpu/risc-v/e310/interrupt_gcc.S | 4 +- libcpu/risc-v/k210/startup_gcc.S | 4 +- libcpu/risc-v/rv32m1/interrupt_gcc.S | 4 +- libcpu/risc-v/virt64/startup_gcc.S | 6 +- libcpu/ti-dsp/c28x/context.s | 118 ++--- libcpu/unicore32/sep6200/context_gcc.S | 82 +-- libcpu/unicore32/sep6200/start_gcc.S | 318 ++++++------ 80 files changed, 3460 insertions(+), 3460 deletions(-) diff --git a/libcpu/aarch64/common/cache.S b/libcpu/aarch64/common/cache.S index 38c476ac47..81416544f1 100644 --- a/libcpu/aarch64/common/cache.S +++ b/libcpu/aarch64/common/cache.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -199,4 +199,4 @@ __asm_invalidate_icache_all: .globl __asm_flush_l3_cache __asm_flush_l3_cache: mov x0, #0 /* return status as success */ - ret \ No newline at end of file + ret diff --git a/libcpu/aarch64/common/context_gcc.S b/libcpu/aarch64/common/context_gcc.S index 9d7f52b585..d1c6cb0ad0 100644 --- a/libcpu/aarch64/common/context_gcc.S +++ b/libcpu/aarch64/common/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -23,9 +23,9 @@ */ .globl rt_hw_gtimer_enable rt_hw_gtimer_enable: - MOV X0,#1 - MSR CNTP_CTL_EL0,X0 - RET + MOV X0,#1 + MSR CNTP_CTL_EL0,X0 + RET /* *disable gtimer @@ -40,183 +40,183 @@ rt_hw_gtimer_disable: */ .globl rt_hw_set_gtimer_val rt_hw_set_gtimer_val: - MSR CNTP_TVAL_EL0,X0 - RET + MSR CNTP_TVAL_EL0,X0 + RET /* *get gtimer CNTP_TVAL_EL0 value */ .globl rt_hw_get_gtimer_val rt_hw_get_gtimer_val: - MRS X0,CNTP_TVAL_EL0 - RET + MRS X0,CNTP_TVAL_EL0 + RET .globl rt_hw_get_cntpct_val rt_hw_get_cntpct_val: - MRS X0, CNTPCT_EL0 - RET + MRS X0, CNTPCT_EL0 + RET /* *get gtimer frq value */ .globl rt_hw_get_gtimer_frq rt_hw_get_gtimer_frq: - MRS X0,CNTFRQ_EL0 - RET + MRS X0,CNTFRQ_EL0 + RET .macro SAVE_CONTEXT /* Save the entire context. */ SAVE_FPU SP - STP X0, X1, [SP, #-0x10]! - STP X2, X3, [SP, #-0x10]! - STP X4, X5, [SP, #-0x10]! - STP X6, X7, [SP, #-0x10]! - STP X8, X9, [SP, #-0x10]! - STP X10, X11, [SP, #-0x10]! - STP X12, X13, [SP, #-0x10]! - STP X14, X15, [SP, #-0x10]! - STP X16, X17, [SP, #-0x10]! - STP X18, X19, [SP, #-0x10]! - STP X20, X21, [SP, #-0x10]! - STP X22, X23, [SP, #-0x10]! - STP X24, X25, [SP, #-0x10]! - STP X26, X27, [SP, #-0x10]! - STP X28, X29, [SP, #-0x10]! + STP X0, X1, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! + STP X4, X5, [SP, #-0x10]! + STP X6, X7, [SP, #-0x10]! + STP X8, X9, [SP, #-0x10]! + STP X10, X11, [SP, #-0x10]! + STP X12, X13, [SP, #-0x10]! + STP X14, X15, [SP, #-0x10]! + STP X16, X17, [SP, #-0x10]! + STP X18, X19, [SP, #-0x10]! + STP X20, X21, [SP, #-0x10]! + STP X22, X23, [SP, #-0x10]! + STP X24, X25, [SP, #-0x10]! + STP X26, X27, [SP, #-0x10]! + STP X28, X29, [SP, #-0x10]! MRS X28, FPCR MRS X29, FPSR STP X28, X29, [SP, #-0x10]! - STP X30, XZR, [SP, #-0x10]! + STP X30, XZR, [SP, #-0x10]! - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - B . + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . 3: - MRS X3, SPSR_EL3 + MRS X3, SPSR_EL3 /* Save the ELR. */ - MRS X2, ELR_EL3 - B 0f + MRS X2, ELR_EL3 + B 0f 2: - MRS X3, SPSR_EL2 + MRS X3, SPSR_EL2 /* Save the ELR. */ - MRS X2, ELR_EL2 - B 0f + MRS X2, ELR_EL2 + B 0f 1: - MRS X3, SPSR_EL1 - MRS X2, ELR_EL1 - B 0f + MRS X3, SPSR_EL1 + MRS X2, ELR_EL1 + B 0f 0: - STP X2, X3, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! - MOV X0, SP /* Move SP into X0 for saving. */ + MOV X0, SP /* Move SP into X0 for saving. */ .endm .macro SAVE_CONTEXT_T /* Save the entire context. */ SAVE_FPU SP - STP X0, X1, [SP, #-0x10]! - STP X2, X3, [SP, #-0x10]! - STP X4, X5, [SP, #-0x10]! - STP X6, X7, [SP, #-0x10]! - STP X8, X9, [SP, #-0x10]! - STP X10, X11, [SP, #-0x10]! - STP X12, X13, [SP, #-0x10]! - STP X14, X15, [SP, #-0x10]! - STP X16, X17, [SP, #-0x10]! - STP X18, X19, [SP, #-0x10]! - STP X20, X21, [SP, #-0x10]! - STP X22, X23, [SP, #-0x10]! - STP X24, X25, [SP, #-0x10]! - STP X26, X27, [SP, #-0x10]! - STP X28, X29, [SP, #-0x10]! + STP X0, X1, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! + STP X4, X5, [SP, #-0x10]! + STP X6, X7, [SP, #-0x10]! + STP X8, X9, [SP, #-0x10]! + STP X10, X11, [SP, #-0x10]! + STP X12, X13, [SP, #-0x10]! + STP X14, X15, [SP, #-0x10]! + STP X16, X17, [SP, #-0x10]! + STP X18, X19, [SP, #-0x10]! + STP X20, X21, [SP, #-0x10]! + STP X22, X23, [SP, #-0x10]! + STP X24, X25, [SP, #-0x10]! + STP X26, X27, [SP, #-0x10]! + STP X28, X29, [SP, #-0x10]! MRS X28, FPCR MRS X29, FPSR STP X28, X29, [SP, #-0x10]! - STP X30, XZR, [SP, #-0x10]! + STP X30, XZR, [SP, #-0x10]! - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - B . + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . 3: - MOV X3, 0x0d - MOV X2, X30 - B 0f + MOV X3, 0x0d + MOV X2, X30 + B 0f 2: - MOV X3, 0x09 - MOV X2, X30 - B 0f + MOV X3, 0x09 + MOV X2, X30 + B 0f 1: - MOV X3, 0x05 - MOV X2, X30 - B 0f + MOV X3, 0x05 + MOV X2, X30 + B 0f 0: - STP X2, X3, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! - MOV X0, SP /* Move SP into X0 for saving. */ + MOV X0, SP /* Move SP into X0 for saving. */ .endm .macro RESTORE_CONTEXT /* Set the SP to point to the stack of the task being restored. */ - MOV SP, X0 + MOV SP, X0 - LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ + LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - B . + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . 3: - MSR SPSR_EL3, X3 - MSR ELR_EL3, X2 - B 0f + MSR SPSR_EL3, X3 + MSR ELR_EL3, X2 + B 0f 2: - MSR SPSR_EL2, X3 - MSR ELR_EL2, X2 - B 0f + MSR SPSR_EL2, X3 + MSR ELR_EL2, X2 + B 0f 1: - MSR SPSR_EL1, X3 - MSR ELR_EL1, X2 - B 0f + MSR SPSR_EL1, X3 + MSR ELR_EL1, X2 + B 0f 0: - LDP X30, XZR, [SP], #0x10 + LDP X30, XZR, [SP], #0x10 LDP X28, X29, [SP], #0x10 MSR FPCR, X28 MSR FPSR, X29 - LDP X28, X29, [SP], #0x10 - LDP X26, X27, [SP], #0x10 - LDP X24, X25, [SP], #0x10 - LDP X22, X23, [SP], #0x10 - LDP X20, X21, [SP], #0x10 - LDP X18, X19, [SP], #0x10 - LDP X16, X17, [SP], #0x10 - LDP X14, X15, [SP], #0x10 - LDP X12, X13, [SP], #0x10 - LDP X10, X11, [SP], #0x10 - LDP X8, X9, [SP], #0x10 - LDP X6, X7, [SP], #0x10 - LDP X4, X5, [SP], #0x10 - LDP X2, X3, [SP], #0x10 - LDP X0, X1, [SP], #0x10 + LDP X28, X29, [SP], #0x10 + LDP X26, X27, [SP], #0x10 + LDP X24, X25, [SP], #0x10 + LDP X22, X23, [SP], #0x10 + LDP X20, X21, [SP], #0x10 + LDP X18, X19, [SP], #0x10 + LDP X16, X17, [SP], #0x10 + LDP X14, X15, [SP], #0x10 + LDP X12, X13, [SP], #0x10 + LDP X10, X11, [SP], #0x10 + LDP X8, X9, [SP], #0x10 + LDP X6, X7, [SP], #0x10 + LDP X4, X5, [SP], #0x10 + LDP X2, X3, [SP], #0x10 + LDP X0, X1, [SP], #0x10 RESTORE_FPU SP ERET @@ -264,7 +264,7 @@ rt_hw_context_switch_to: BL rt_cpus_lock_status_restore LDR X0, [SP], #0x8 #endif /*RT_USING_SMP*/ - LDR X0, [X0] + LDR X0, [X0] RESTORE_CONTEXT .text @@ -289,14 +289,14 @@ rt_hw_context_switch: LDP X0, X1, [SP], #0x10 #endif /*RT_USING_SMP*/ - MOV X8,X0 - MOV X9,X1 + MOV X8,X0 + MOV X9,X1 SAVE_CONTEXT_T - - STR X0, [X8] // store sp in preempted tasks TCB - LDR X0, [X9] // get new task stack pointer - + + STR X0, [X8] // store sp in preempted tasks TCB + LDR X0, [X9] // get new task stack pointer + RESTORE_CONTEXT /* @@ -320,17 +320,17 @@ rt_hw_context_switch_interrupt: MOV X0, SP RESTORE_CONTEXT #else - LDR X2, =rt_thread_switch_interrupt_flag - LDR X3, [X2] - CMP X3, #1 - B.EQ _reswitch - LDR X4, =rt_interrupt_from_thread // set rt_interrupt_from_thread - MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1 - STR X0, [X4] - STR X3, [X2] + LDR X2, =rt_thread_switch_interrupt_flag + LDR X3, [X2] + CMP X3, #1 + B.EQ _reswitch + LDR X4, =rt_interrupt_from_thread // set rt_interrupt_from_thread + MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1 + STR X0, [X4] + STR X3, [X2] _reswitch: - LDR X2, =rt_interrupt_to_thread // set rt_interrupt_to_thread - STR X1, [X2] + LDR X2, =rt_interrupt_to_thread // set rt_interrupt_to_thread + STR X1, [X2] RET #endif .text @@ -341,9 +341,9 @@ _reswitch: .globl vector_fiq vector_fiq: SAVE_CONTEXT - STP X0, X1, [SP, #-0x10]! + STP X0, X1, [SP, #-0x10]! BL rt_hw_trap_fiq - LDP X0, X1, [SP], #0x10 + LDP X0, X1, [SP], #0x10 RESTORE_CONTEXT .globl rt_interrupt_enter @@ -359,13 +359,13 @@ vector_fiq: .globl vector_irq vector_irq: SAVE_CONTEXT - STP X0, X1, [SP, #-0x10]! + STP X0, X1, [SP, #-0x10]! BL rt_interrupt_enter BL rt_hw_trap_irq BL rt_interrupt_leave - - LDP X0, X1, [SP], #0x10 + + LDP X0, X1, [SP], #0x10 #ifdef RT_USING_SMP /* Never reture If can switch */ BL rt_scheduler_do_irq_switch @@ -374,7 +374,7 @@ vector_irq: // if rt_thread_switch_interrupt_flag set, jump to // rt_hw_context_switch_interrupt_do and don't return - LDR X1, =rt_thread_switch_interrupt_flag + LDR X1, =rt_thread_switch_interrupt_flag LDR X2, [X1] CMP X2, #1 B.NE vector_irq_exit @@ -389,8 +389,8 @@ vector_irq: LDR x3, =rt_interrupt_to_thread LDR X4, [X3] LDR x0, [X4] // get new task's stack pointer - -vector_irq_exit: + +vector_irq_exit: RESTORE_CONTEXT // ------------------------------------------------- diff --git a/libcpu/aarch64/common/cpu_gcc.S b/libcpu/aarch64/common/cpu_gcc.S index b8c8b8768c..17dea1a481 100644 --- a/libcpu/aarch64/common/cpu_gcc.S +++ b/libcpu/aarch64/common/cpu_gcc.S @@ -1,82 +1,82 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Date Author Notes * 2018-10-06 ZhaoXiaowei the first version */ - + .text .globl rt_hw_get_current_el rt_hw_get_current_el: - MRS X0, CurrentEL - CMP X0, 0xc - B.EQ 3f - CMP X0, 0x8 - B.EQ 2f - CMP X0, 0x4 - B.EQ 1f - - LDR X0, =0 - B 0f + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + + LDR X0, =0 + B 0f 3: - LDR X0, =3 - B 0f + LDR X0, =3 + B 0f 2: - LDR X0, =2 - B 0f + LDR X0, =2 + B 0f 1: - LDR X0, =1 - B 0f + LDR X0, =1 + B 0f 0: - RET + RET .globl rt_hw_set_current_vbar rt_hw_set_current_vbar: - MRS X1, CurrentEL - CMP X1, 0xc - B.EQ 3f - CMP X1, 0x8 - B.EQ 2f - CMP X1, 0x4 - B.EQ 1f - B 0f + MRS X1, CurrentEL + CMP X1, 0xc + B.EQ 3f + CMP X1, 0x8 + B.EQ 2f + CMP X1, 0x4 + B.EQ 1f + B 0f 3: - MSR VBAR_EL3,X0 - B 0f + MSR VBAR_EL3,X0 + B 0f 2: - MSR VBAR_EL2,X0 - B 0f + MSR VBAR_EL2,X0 + B 0f 1: - MSR VBAR_EL1,X0 - B 0f + MSR VBAR_EL1,X0 + B 0f 0: - RET + RET + - .globl rt_hw_set_elx_env rt_hw_set_elx_env: - MRS X1, CurrentEL - CMP X1, 0xc - B.EQ 3f - CMP X1, 0x8 - B.EQ 2f - CMP X1, 0x4 - B.EQ 1f - B 0f + MRS X1, CurrentEL + CMP X1, 0xc + B.EQ 3f + CMP X1, 0x8 + B.EQ 2f + CMP X1, 0x4 + B.EQ 1f + B 0f 3: - MRS X0, SCR_EL3 - ORR X0, X0, #0xF /* SCR_EL3.NS|IRQ|FIQ|EA */ - MSR SCR_EL3, X0 - B 0f + MRS X0, SCR_EL3 + ORR X0, X0, #0xF /* SCR_EL3.NS|IRQ|FIQ|EA */ + MSR SCR_EL3, X0 + B 0f 2: - MRS X0, HCR_EL2 - ORR X0, X0, #0x38 - MSR HCR_EL2, X0 - B 0f + MRS X0, HCR_EL2 + ORR X0, X0, #0x38 + MSR HCR_EL2, X0 + B 0f 1: - B 0f + B 0f 0: - RET + RET diff --git a/libcpu/aarch64/common/startup_gcc.S b/libcpu/aarch64/common/startup_gcc.S index ea4268148c..033b2f7881 100644 --- a/libcpu/aarch64/common/startup_gcc.S +++ b/libcpu/aarch64/common/startup_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,7 +7,7 @@ * Date Author Notes */ - .global Reset_Handler + .global Reset_Handler .section ".start", "ax" Reset_Handler: nop diff --git a/libcpu/aarch64/common/vector_gcc.S b/libcpu/aarch64/common/vector_gcc.S index 50ff41a8e3..6227686e2b 100644 --- a/libcpu/aarch64/common/vector_gcc.S +++ b/libcpu/aarch64/common/vector_gcc.S @@ -1,12 +1,12 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Date Author Notes * 2018-10-06 ZhaoXiaowei the first version */ - + .text .globl system_vectors @@ -20,7 +20,7 @@ system_vectors: .org VBAR // Exception from CurrentEL (EL1) with SP_EL0 (SPSEL=0) .org (VBAR + 0x00 + 0) - B vector_error // Synchronous + B vector_error // Synchronous .org (VBAR + 0x80 + 0) B vector_irq // IRQ/vIRQ .org (VBAR + 0x100 + 0) @@ -30,9 +30,9 @@ system_vectors: // Exception from CurrentEL (EL1) with SP_ELn .org (VBAR + 0x200 + 0) - B vector_error // Synchronous + B vector_error // Synchronous .org (VBAR + 0x280 + 0) - B vector_irq // IRQ/vIRQ + B vector_irq // IRQ/vIRQ .org (VBAR + 0x300 + 0) B vector_fiq // FIQ/vFIQ .org (VBAR + 0x380 + 0) diff --git a/libcpu/arc/em/contex_gcc_mw.S b/libcpu/arc/em/contex_gcc_mw.S index 81b291c1c8..0f6fe48fd6 100644 --- a/libcpu/arc/em/contex_gcc_mw.S +++ b/libcpu/arc/em/contex_gcc_mw.S @@ -15,68 +15,68 @@ .global exc_nest_count; .global set_hw_stack_check; - .text - .align 4 + .text + .align 4 dispatcher: - st sp, [r0] - ld sp, [r1] + st sp, [r0] + ld sp, [r1] #if ARC_FEATURE_STACK_CHECK #if ARC_FEATURE_SEC_PRESENT - lr r0, [AUX_SEC_STAT] - bclr r0, r0, AUX_SEC_STAT_BIT_SSC - sflag r0 + lr r0, [AUX_SEC_STAT] + bclr r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 #else - lr r0, [AUX_STATUS32] - bclr r0, r0, AUX_STATUS_BIT_SC - kflag r0 + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_SC + kflag r0 #endif - jl set_hw_stack_check + jl set_hw_stack_check #if ARC_FEATURE_SEC_PRESENT - lr r0, [AUX_SEC_STAT] - bset r0, r0, AUX_SEC_STAT_BIT_SSC - sflag r0 + lr r0, [AUX_SEC_STAT] + bset r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 #else - lr r0, [AUX_STATUS32] - bset r0, r0, AUX_STATUS_BIT_SC - kflag r0 + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_SC + kflag r0 #endif #endif - pop r0 - j [r0] + pop r0 + j [r0] /* return routine when task dispatch happened in task context */ dispatch_r: - RESTORE_NONSCRATCH_REGS - j [blink] + RESTORE_NONSCRATCH_REGS + j [blink] /* * rt_base_t rt_hw_interrupt_disable(); */ - .global rt_hw_interrupt_disable - .align 4 + .global rt_hw_interrupt_disable + .align 4 rt_hw_interrupt_disable: - clri r0 - j [blink] + clri r0 + j [blink] /* * void rt_hw_interrupt_enable(rt_base_t level); */ - .global rt_hw_interrupt_enable - .align 4 + .global rt_hw_interrupt_enable + .align 4 rt_hw_interrupt_enable: - seti r0 - j [blink] + seti r0 + j [blink] - .global rt_hw_context_switch_interrupt - .align 4 + .global rt_hw_context_switch_interrupt + .align 4 rt_hw_context_switch_interrupt: - st r0, [rt_interrupt_from_thread] - st r1, [rt_interrupt_to_thread] - mov r0, 1 - st r0, [context_switch_reqflg] - j [blink] + st r0, [rt_interrupt_from_thread] + st r1, [rt_interrupt_to_thread] + mov r0, 1 + st r0, [context_switch_reqflg] + j [blink] /* @@ -84,281 +84,281 @@ rt_hw_context_switch_interrupt: * r0 --> from * r1 --> to */ - .global rt_hw_context_switch - .align 4 + .global rt_hw_context_switch + .align 4 rt_hw_context_switch: - SAVE_NONSCRATCH_REGS - mov r2, dispatch_r - push r2 - b dispatcher + SAVE_NONSCRATCH_REGS + mov r2, dispatch_r + push r2 + b dispatcher /* * void rt_hw_context_switch_to(rt_uint32 to); * r0 --> to */ - .global rt_hw_context_switch_to - .align 4 + .global rt_hw_context_switch_to + .align 4 rt_hw_context_switch_to: - ld sp, [r0] + ld sp, [r0] #if ARC_FEATURE_STACK_CHECK - mov r1, r0 + mov r1, r0 #if ARC_FEATURE_SEC_PRESENT - lr r0, [AUX_SEC_STAT] - bclr r0, r0, AUX_SEC_STAT_BIT_SSC - sflag r0 + lr r0, [AUX_SEC_STAT] + bclr r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 #else - lr r0, [AUX_STATUS32] - bclr r0, r0, AUX_STATUS_BIT_SC - kflag r0 + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_SC + kflag r0 #endif - jl set_hw_stack_check + jl set_hw_stack_check #if ARC_FEATURE_SEC_PRESENT - lr r0, [AUX_SEC_STAT] - bset r0, r0, AUX_SEC_STAT_BIT_SSC - sflag r0 + lr r0, [AUX_SEC_STAT] + bset r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 #else - lr r0, [AUX_STATUS32] - bset r0, r0, AUX_STATUS_BIT_SC - kflag r0 + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_SC + kflag r0 #endif #endif - pop r0 - j [r0] + pop r0 + j [r0] - .global start_r - .align 4 + .global start_r + .align 4 start_r: - pop blink; - pop r1 - pop r2 - pop r0 + pop blink; + pop r1 + pop r2 + pop r0 - j_s.d [r1] - kflag r2 + j_s.d [r1] + kflag r2 /* * int __rt_ffs(int value); * r0 --> value */ - .global __rt_ffs - .align 4 + .global __rt_ffs + .align 4 __rt_ffs: - breq r0, 0, __rt_ffs_return - ffs r1, r0 - add r0, r1, 1 + breq r0, 0, __rt_ffs_return + ffs r1, r0 + add r0, r1, 1 __rt_ffs_return: - j [blink] + j [blink] /****** exceptions and interrupts handing ******/ /****** entry for exception handling ******/ - .global exc_entry_cpu - .align 4 + .global exc_entry_cpu + .align 4 exc_entry_cpu: - EXCEPTION_PROLOGUE + EXCEPTION_PROLOGUE - mov blink, sp - mov r3, sp /* as exception handler's para(p_excinfo) */ + mov blink, sp + mov r3, sp /* as exception handler's para(p_excinfo) */ - ld r0, [exc_nest_count] - add r1, r0, 1 - st r1, [exc_nest_count] - brne r0, 0, exc_handler_1 + ld r0, [exc_nest_count] + add r1, r0, 1 + st r1, [exc_nest_count] + brne r0, 0, exc_handler_1 /* change to exception stack if interrupt happened in task context */ - mov sp, _e_stack + mov sp, _e_stack exc_handler_1: - PUSH blink + PUSH blink - lr r0, [AUX_ECR] - lsr r0, r0, 16 - mov r1, exc_int_handler_table - ld.as r2, [r1, r0] + lr r0, [AUX_ECR] + lsr r0, r0, 16 + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] - mov r0, r3 - jl [r2] + mov r0, r3 + jl [r2] /* interrupts are not allowed */ ret_exc: - POP sp - mov r1, exc_nest_count - ld r0, [r1] - sub r0, r0, 1 - st r0, [r1] - brne r0, 0, ret_exc_1 /* nest exception case */ - lr r1, [AUX_IRQ_ACT] /* nest interrupt case */ - brne r1, 0, ret_exc_1 + POP sp + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + st r0, [r1] + brne r0, 0, ret_exc_1 /* nest exception case */ + lr r1, [AUX_IRQ_ACT] /* nest interrupt case */ + brne r1, 0, ret_exc_1 - ld r0, [context_switch_reqflg] - brne r0, 0, ret_exc_2 -ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ - EXCEPTION_EPILOGUE - rtie + ld r0, [context_switch_reqflg] + brne r0, 0, ret_exc_2 +ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ + EXCEPTION_EPILOGUE + rtie /* there is a dispatch request */ ret_exc_2: - /* clear dispatch request */ - mov r0, 0 - st r0, [context_switch_reqflg] + /* clear dispatch request */ + mov r0, 0 + st r0, [context_switch_reqflg] - SAVE_CALLEE_REGS /* save callee save registers */ + SAVE_CALLEE_REGS /* save callee save registers */ - /* clear exception bit to do exception exit by SW */ - lr r0, [AUX_STATUS32] - bclr r0, r0, AUX_STATUS_BIT_AE - kflag r0 + /* clear exception bit to do exception exit by SW */ + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_AE + kflag r0 - mov r1, ret_exc_r /* save return address */ - PUSH r1 + mov r1, ret_exc_r /* save return address */ + PUSH r1 - ld r0, [rt_interrupt_from_thread] - ld r1, [rt_interrupt_to_thread] - b dispatcher + ld r0, [rt_interrupt_from_thread] + ld r1, [rt_interrupt_to_thread] + b dispatcher ret_exc_r: - /* recover exception status */ - lr r0, [AUX_STATUS32] - bset r0, r0, AUX_STATUS_BIT_AE - kflag r0 + /* recover exception status */ + lr r0, [AUX_STATUS32] + bset r0, r0, AUX_STATUS_BIT_AE + kflag r0 - RESTORE_CALLEE_REGS - EXCEPTION_EPILOGUE - rtie + RESTORE_CALLEE_REGS + EXCEPTION_EPILOGUE + rtie /****** entry for normal interrupt exception handling ******/ - .global exc_entry_int /* entry for interrupt handling */ - .align 4 + .global exc_entry_int /* entry for interrupt handling */ + .align 4 exc_entry_int: #if ARC_FEATURE_FIRQ == 1 /* check whether it is P0 interrupt */ #if ARC_FEATURE_RGF_NUM_BANKS > 1 - lr r0, [AUX_IRQ_ACT] - btst r0, 0 - jnz exc_entry_firq + lr r0, [AUX_IRQ_ACT] + btst r0, 0 + jnz exc_entry_firq #else - PUSH r10 - lr r10, [AUX_IRQ_ACT] - btst r10, 0 - POP r10 - jnz exc_entry_firq + PUSH r10 + lr r10, [AUX_IRQ_ACT] + btst r10, 0 + POP r10 + jnz exc_entry_firq #endif #endif - INTERRUPT_PROLOGUE + INTERRUPT_PROLOGUE - mov blink, sp + mov blink, sp - clri /* disable interrupt */ - ld r3, [exc_nest_count] - add r2, r3, 1 - st r2, [exc_nest_count] - seti /* enable higher priority interrupt */ + clri /* disable interrupt */ + ld r3, [exc_nest_count] + add r2, r3, 1 + st r2, [exc_nest_count] + seti /* enable higher priority interrupt */ - brne r3, 0, irq_handler_1 + brne r3, 0, irq_handler_1 /* change to exception stack if interrupt happened in task context */ - mov sp, _e_stack + mov sp, _e_stack #if ARC_FEATURE_STACK_CHECK #if ARC_FEATURE_SEC_PRESENT - lr r0, [AUX_SEC_STAT] - bclr r0, r0, AUX_SEC_STAT_BIT_SSC - sflag r0 + lr r0, [AUX_SEC_STAT] + bclr r0, r0, AUX_SEC_STAT_BIT_SSC + sflag r0 #else - lr r0, [AUX_STATUS32] - bclr r0, r0, AUX_STATUS_BIT_SC - kflag r0 + lr r0, [AUX_STATUS32] + bclr r0, r0, AUX_STATUS_BIT_SC + kflag r0 #endif #endif irq_handler_1: - PUSH blink + PUSH blink - jl rt_interrupt_enter + jl rt_interrupt_enter - lr r0, [AUX_IRQ_CAUSE] - sr r0, [AUX_IRQ_SELECT] - mov r1, exc_int_handler_table - ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ + lr r0, [AUX_IRQ_CAUSE] + sr r0, [AUX_IRQ_SELECT] + mov r1, exc_int_handler_table + ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ /* handle software triggered interrupt */ - lr r3, [AUX_IRQ_HINT] - cmp r3, r0 - bne.d irq_hint_handled - xor r3, r3, r3 - sr r3, [AUX_IRQ_HINT] + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d irq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] irq_hint_handled: - lr r3, [AUX_IRQ_PRIORITY] - PUSH r3 /* save irq priority */ + lr r3, [AUX_IRQ_PRIORITY] + PUSH r3 /* save irq priority */ - jl [r2] /* jump to interrupt handler */ - jl rt_interrupt_leave + jl [r2] /* jump to interrupt handler */ + jl rt_interrupt_leave ret_int: - clri /* disable interrupt */ - POP r3 /* irq priority */ - POP sp - mov r1, exc_nest_count - ld r0, [r1] - sub r0, r0, 1 - st r0, [r1] + clri /* disable interrupt */ + POP r3 /* irq priority */ + POP sp + mov r1, exc_nest_count + ld r0, [r1] + sub r0, r0, 1 + st r0, [r1] /* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */ - lr r0, [AUX_IRQ_CAUSE] - sr r0, [AUX_IRQ_SELECT] - lr r3, [AUX_IRQ_PRIORITY] - lr r1, [AUX_IRQ_ACT] - bclr r2, r1, r3 - brne r2, 0, ret_int_1 + lr r0, [AUX_IRQ_CAUSE] + sr r0, [AUX_IRQ_SELECT] + lr r3, [AUX_IRQ_PRIORITY] + lr r1, [AUX_IRQ_ACT] + bclr r2, r1, r3 + brne r2, 0, ret_int_1 - ld r0, [context_switch_reqflg] - brne r0, 0, ret_int_2 -ret_int_1: /* return from non-task context */ - INTERRUPT_EPILOGUE - rtie + ld r0, [context_switch_reqflg] + brne r0, 0, ret_int_2 +ret_int_1: /* return from non-task context */ + INTERRUPT_EPILOGUE + rtie /* there is a dispatch request */ ret_int_2: - /* clear dispatch request */ - mov r0, 0 - st r0, [context_switch_reqflg] + /* clear dispatch request */ + mov r0, 0 + st r0, [context_switch_reqflg] - /* interrupt return by SW */ - lr r10, [AUX_IRQ_ACT] - PUSH r10 - bclr r10, r10, r3 /* clear related bits in IRQ_ACT */ - sr r10, [AUX_IRQ_ACT] + /* interrupt return by SW */ + lr r10, [AUX_IRQ_ACT] + PUSH r10 + bclr r10, r10, r3 /* clear related bits in IRQ_ACT */ + sr r10, [AUX_IRQ_ACT] - SAVE_CALLEE_REGS /* save callee save registers */ - mov r1, ret_int_r /* save return address */ - PUSH r1 + SAVE_CALLEE_REGS /* save callee save registers */ + mov r1, ret_int_r /* save return address */ + PUSH r1 - ld r0, [rt_interrupt_from_thread] - ld r1, [rt_interrupt_to_thread] - b dispatcher + ld r0, [rt_interrupt_from_thread] + ld r1, [rt_interrupt_to_thread] + b dispatcher ret_int_r: - RESTORE_CALLEE_REGS - /* recover AUX_IRQ_ACT to restore the interrup status */ - POPAX AUX_IRQ_ACT - INTERRUPT_EPILOGUE - rtie + RESTORE_CALLEE_REGS + /* recover AUX_IRQ_ACT to restore the interrup status */ + POPAX AUX_IRQ_ACT + INTERRUPT_EPILOGUE + rtie /****** entry for fast irq exception handling ******/ - .global exc_entry_firq - .weak exc_entry_firq - .align 4 + .global exc_entry_firq + .weak exc_entry_firq + .align 4 exc_entry_firq: - SAVE_FIQ_EXC_REGS + SAVE_FIQ_EXC_REGS - lr r0, [AUX_IRQ_CAUSE] - mov r1, exc_int_handler_table + lr r0, [AUX_IRQ_CAUSE] + mov r1, exc_int_handler_table /* r2 = _kernel_exc_tbl + irqno *4 */ - ld.as r2, [r1, r0] + ld.as r2, [r1, r0] /* for the case of software triggered interrupt */ - lr r3, [AUX_IRQ_HINT] - cmp r3, r0 - bne.d firq_hint_handled - xor r3, r3, r3 - sr r3, [AUX_IRQ_HINT] + lr r3, [AUX_IRQ_HINT] + cmp r3, r0 + bne.d firq_hint_handled + xor r3, r3, r3 + sr r3, [AUX_IRQ_HINT] firq_hint_handled: /* jump to interrupt handler */ - mov r0, sp - jl [r2] + mov r0, sp + jl [r2] firq_return: - RESTORE_FIQ_EXC_REGS - rtie + RESTORE_FIQ_EXC_REGS + rtie diff --git a/libcpu/arm/AT91SAM7S/context_gcc.S b/libcpu/arm/AT91SAM7S/context_gcc.S index aa9bb160cd..b2629a6498 100644 --- a/libcpu/arm/AT91SAM7S/context_gcc.S +++ b/libcpu/arm/AT91SAM7S/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,25 +8,25 @@ * 2006-03-13 Bernard first version */ -#define NOINT 0xc0 +#define NOINT 0xc0 /* * rt_base_t rt_hw_interrupt_disable()/* */ .globl rt_hw_interrupt_disable rt_hw_interrupt_disable: - mrs r0, cpsr - orr r1, r0, #NOINT - msr cpsr_c, r1 - mov pc, lr + mrs r0, cpsr + orr r1, r0, #NOINT + msr cpsr_c, r1 + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level)/* */ .globl rt_hw_interrupt_enable rt_hw_interrupt_enable: - msr cpsr, r0 - mov pc, lr + msr cpsr, r0 + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)/* @@ -35,23 +35,23 @@ rt_hw_interrupt_enable: */ .globl rt_hw_context_switch rt_hw_context_switch: - stmfd sp!, {lr} /* push pc (lr should be pushed in place of PC) */ - stmfd sp!, {r0-r12, lr} /* push lr & register file */ + stmfd sp!, {lr} /* push pc (lr should be pushed in place of PC) */ + stmfd sp!, {r0-r12, lr} /* push lr & register file */ - mrs r4, cpsr - stmfd sp!, {r4} /* push cpsr */ - mrs r4, spsr - stmfd sp!, {r4} /* push spsr */ + mrs r4, cpsr + stmfd sp!, {r4} /* push cpsr */ + mrs r4, spsr + stmfd sp!, {r4} /* push spsr */ - str sp, [r0] /* store sp in preempted tasks TCB */ - ldr sp, [r1] /* get new task stack pointer */ + str sp, [r0] /* store sp in preempted tasks TCB */ + ldr sp, [r1] /* get new task stack pointer */ - ldmfd sp!, {r4} /* pop new task spsr */ - msr spsr_cxsf, r4 - ldmfd sp!, {r4} /* pop new task cpsr */ - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} /* pop new task spsr */ + msr spsr_cxsf, r4 + ldmfd sp!, {r4} /* pop new task cpsr */ + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ + ldmfd sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ /* * void rt_hw_context_switch_to(rt_uint32 to)/* @@ -59,14 +59,14 @@ rt_hw_context_switch: */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldr sp, [r0] /* get new task stack pointer */ + ldr sp, [r0] /* get new task stack pointer */ - ldmfd sp!, {r4} /* pop new task spsr */ - msr spsr_cxsf, r4 - ldmfd sp!, {r4} /* pop new task cpsr */ - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} /* pop new task spsr */ + msr spsr_cxsf, r4 + ldmfd sp!, {r4} /* pop new task cpsr */ + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ + ldmfd sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/* @@ -76,15 +76,15 @@ rt_hw_context_switch_to: .globl rt_interrupt_to_thread .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldr r2, =rt_thread_switch_interrupt_flag - ldr r3, [r2] - cmp r3, #1 - beq _reswitch - mov r3, #1 /* set rt_thread_switch_interrupt_flag to 1 */ - str r3, [r2] - ldr r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */ - str r0, [r2] + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 /* set rt_thread_switch_interrupt_flag to 1 */ + str r3, [r2] + ldr r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread */ + str r0, [r2] _reswitch: - ldr r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */ - str r1, [r2] - mov pc, lr + ldr r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread */ + str r1, [r2] + mov pc, lr diff --git a/libcpu/arm/AT91SAM7S/context_rvds.S b/libcpu/arm/AT91SAM7S/context_rvds.S index 78e3df9736..3cc70c76f3 100644 --- a/libcpu/arm/AT91SAM7S/context_rvds.S +++ b/libcpu/arm/AT91SAM7S/context_rvds.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,7 +8,7 @@ * 2009-01-20 Bernard first version */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr AREA |.text|, CODE, READONLY, ALIGN=2 ARM @@ -18,21 +18,21 @@ NOINT EQU 0xc0 ; disable interrupt in psr ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC +rt_hw_interrupt_disable PROC EXPORT rt_hw_interrupt_disable MRS r0, cpsr ORR r1, r0, #NOINT MSR cpsr_c, r1 - BX lr + BX lr ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC +rt_hw_interrupt_enable PROC EXPORT rt_hw_interrupt_enable MSR cpsr_c, r0 - BX lr + BX lr ENDP ;/* @@ -40,41 +40,41 @@ rt_hw_interrupt_enable PROC ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC +rt_hw_context_switch PROC EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr + MRS r4, cpsr + STMFD sp!, {r4} ; push cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push spsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC +rt_hw_context_switch_to PROC EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc ENDP ;/* @@ -84,20 +84,20 @@ rt_hw_context_switch_to PROC IMPORT rt_interrupt_from_thread IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC +rt_hw_context_switch_interrupt PROC EXPORT rt_hw_context_switch_interrupt LDR r2, =rt_thread_switch_interrupt_flag LDR r3, [r2] CMP r3, #1 BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread STR r1, [r2] - BX lr + BX lr ENDP - END \ No newline at end of file + END diff --git a/libcpu/arm/AT91SAM7S/start_gcc.S b/libcpu/arm/AT91SAM7S/start_gcc.S index 2334f08e4f..d71234ca04 100644 --- a/libcpu/arm/AT91SAM7S/start_gcc.S +++ b/libcpu/arm/AT91SAM7S/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,151 +8,151 @@ * 2006-08-31 Bernard first version */ - /* Internal Memory Base Addresses */ - .equ FLASH_BASE, 0x00100000 - .equ RAM_BASE, 0x00200000 + /* Internal Memory Base Addresses */ + .equ FLASH_BASE, 0x00100000 + .equ RAM_BASE, 0x00200000 - /* Stack Configuration */ - .equ TOP_STACK, 0x00204000 - .equ UND_STACK_SIZE, 0x00000100 - .equ SVC_STACK_SIZE, 0x00000400 - .equ ABT_STACK_SIZE, 0x00000100 - .equ FIQ_STACK_SIZE, 0x00000100 - .equ IRQ_STACK_SIZE, 0x00000100 - .equ USR_STACK_SIZE, 0x00000004 + /* Stack Configuration */ + .equ TOP_STACK, 0x00204000 + .equ UND_STACK_SIZE, 0x00000100 + .equ SVC_STACK_SIZE, 0x00000400 + .equ ABT_STACK_SIZE, 0x00000100 + .equ FIQ_STACK_SIZE, 0x00000100 + .equ IRQ_STACK_SIZE, 0x00000100 + .equ USR_STACK_SIZE, 0x00000004 - /* ARM architecture definitions */ - .equ MODE_USR, 0x10 - .equ MODE_FIQ, 0x11 - .equ MODE_IRQ, 0x12 - .equ MODE_SVC, 0x13 - .equ MODE_ABT, 0x17 - .equ MODE_UND, 0x1B - .equ MODE_SYS, 0x1F + /* ARM architecture definitions */ + .equ MODE_USR, 0x10 + .equ MODE_FIQ, 0x11 + .equ MODE_IRQ, 0x12 + .equ MODE_SVC, 0x13 + .equ MODE_ABT, 0x17 + .equ MODE_UND, 0x1B + .equ MODE_SYS, 0x1F - .equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */ - .equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */ + .equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */ + .equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */ .section .init, "ax" .code 32 .align 0 .globl _start _start: - b reset - ldr pc, _vector_undef - ldr pc, _vector_swi - ldr pc, _vector_pabt - ldr pc, _vector_dabt - nop /* reserved vector */ - ldr pc, _vector_irq - ldr pc, _vector_fiq + b reset + ldr pc, _vector_undef + ldr pc, _vector_swi + ldr pc, _vector_pabt + ldr pc, _vector_dabt + nop /* reserved vector */ + ldr pc, _vector_irq + ldr pc, _vector_fiq -_vector_undef: .word vector_undef -_vector_swi: .word vector_swi -_vector_pabt: .word vector_pabt -_vector_dabt: .word vector_dabt -_vector_resv: .word vector_resv -_vector_irq: .word vector_irq -_vector_fiq: .word vector_fiq +_vector_undef: .word vector_undef +_vector_swi: .word vector_swi +_vector_pabt: .word vector_pabt +_vector_dabt: .word vector_dabt +_vector_resv: .word vector_resv +_vector_irq: .word vector_irq +_vector_fiq: .word vector_fiq /* * rtthread bss start and end * which are defined in linker script */ .globl _bss_start -_bss_start: .word __bss_start +_bss_start: .word __bss_start .globl _bss_end -_bss_end: .word __bss_end +_bss_end: .word __bss_end /* the system entry */ reset: - /* disable watchdog */ - ldr r0, =0xFFFFFD40 - ldr r1, =0x00008000 - str r1, [r0, #0x04] - - /* enable the main oscillator */ - ldr r0, =0xFFFFFC00 - ldr r1, =0x00000601 - str r1, [r0, #0x20] - - /* wait for main oscillator to stabilize */ + /* disable watchdog */ + ldr r0, =0xFFFFFD40 + ldr r1, =0x00008000 + str r1, [r0, #0x04] + + /* enable the main oscillator */ + ldr r0, =0xFFFFFC00 + ldr r1, =0x00000601 + str r1, [r0, #0x20] + + /* wait for main oscillator to stabilize */ moscs_loop: - ldr r2, [r0, #0x68] - ands r2, r2, #1 - beq moscs_loop - - /* set up the PLL */ - ldr r1, =0x00191C05 - str r1, [r0, #0x2C] - - /* wait for PLL to lock */ + ldr r2, [r0, #0x68] + ands r2, r2, #1 + beq moscs_loop + + /* set up the PLL */ + ldr r1, =0x00191C05 + str r1, [r0, #0x2C] + + /* wait for PLL to lock */ pll_loop: - ldr r2, [r0, #0x68] - ands r2, r2, #0x04 - beq pll_loop - - /* select clock */ - ldr r1, =0x00000007 - str r1, [r0, #0x30] - - /* setup stack for each mode */ - ldr r0, =TOP_STACK - - /* set stack */ - /* undefined instruction mode */ - msr cpsr_c, #MODE_UND|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #UND_STACK_SIZE - - /* abort mode */ - msr cpsr_c, #MODE_ABT|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #ABT_STACK_SIZE - - /* FIQ mode */ - msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #FIQ_STACK_SIZE - - /* IRQ mode */ - msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #IRQ_STACK_SIZE - - /* supervisor mode */ - msr cpsr_c, #MODE_SVC - mov sp, r0 - + ldr r2, [r0, #0x68] + ands r2, r2, #0x04 + beq pll_loop + + /* select clock */ + ldr r1, =0x00000007 + str r1, [r0, #0x30] + + /* setup stack for each mode */ + ldr r0, =TOP_STACK + + /* set stack */ + /* undefined instruction mode */ + msr cpsr_c, #MODE_UND|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + + /* abort mode */ + msr cpsr_c, #MODE_ABT|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + + /* FIQ mode */ + msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + + /* IRQ mode */ + msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + + /* supervisor mode */ + msr cpsr_c, #MODE_SVC + mov sp, r0 + #ifdef __FLASH_BUILD__ - /* Relocate .data section (Copy from ROM to RAM) */ - ldr r1, =_etext - ldr r2, =_data - ldr r3, =_edata + /* Relocate .data section (Copy from ROM to RAM) */ + ldr r1, =_etext + ldr r2, =_data + ldr r3, =_edata data_loop: - cmp r2, r3 - ldrlo r0, [r1], #4 - strlo r0, [r2], #4 - blo data_loop + cmp r2, r3 + ldrlo r0, [r1], #4 + strlo r0, [r2], #4 + blo data_loop #else - /* remap SRAM to 0x0000 */ - ldr r0, =0xFFFFFF00 - mov r1, #0x01 - str r1, [r0] + /* remap SRAM to 0x0000 */ + ldr r0, =0xFFFFFF00 + mov r1, #0x01 + str r1, [r0] #endif - - /* mask all IRQs */ - ldr r1, =0xFFFFF124 - ldr r0, =0XFFFFFFFF - str r0, [r1] - - /* start RT-Thread Kernel */ - ldr pc, _rtthread_startup - + + /* mask all IRQs */ + ldr r1, =0xFFFFF124 + ldr r0, =0XFFFFFFFF + str r0, [r1] + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup + _rtthread_startup: .word rtthread_startup /* exception handlers */ -vector_undef: b vector_undef +vector_undef: b vector_undef vector_swi : b vector_swi vector_pabt : b vector_pabt vector_dabt : b vector_dabt @@ -164,70 +164,70 @@ vector_resv : b vector_resv .globl rt_interrupt_from_thread .globl rt_interrupt_to_thread vector_irq: - stmfd sp!, {r0-r12,lr} - bl rt_interrupt_enter - bl rt_hw_trap_irq - bl rt_interrupt_leave + stmfd sp!, {r0-r12,lr} + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave - /* - * if rt_thread_switch_interrupt_flag set, jump to - * rt_hw_context_switch_interrupt_do and don't return - */ - ldr r0, =rt_thread_switch_interrupt_flag - ldr r1, [r0] - cmp r1, #1 - beq rt_hw_context_switch_interrupt_do + /* + * if rt_thread_switch_interrupt_flag set, jump to + * rt_hw_context_switch_interrupt_do and don't return + */ + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq rt_hw_context_switch_interrupt_do - ldmfd sp!, {r0-r12,lr} - subs pc, lr, #4 + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 vector_fiq: - stmfd sp!,{r0-r7,lr} - bl rt_hw_trap_fiq - ldmfd sp!,{r0-r7,lr} - subs pc,lr,#4 + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc,lr,#4 /* * void rt_hw_context_switch_interrupt_do(rt_base_t flag) */ rt_hw_context_switch_interrupt_do: - mov r1, #0 /* clear flag */ - str r1, [r0] + mov r1, #0 /* clear flag */ + str r1, [r0] - ldmfd sp!, {r0-r12,lr} /* reload saved registers */ - stmfd sp!, {r0-r3} /* save r0-r3 */ - mov r1, sp - add sp, sp, #16 /* restore sp */ - sub r2, lr, #4 /* save old task's pc to r2 */ + ldmfd sp!, {r0-r12,lr} /* reload saved registers */ + stmfd sp!, {r0-r3} /* save r0-r3 */ + mov r1, sp + add sp, sp, #16 /* restore sp */ + sub r2, lr, #4 /* save old task's pc to r2 */ - mrs r3, spsr /* disable interrupt */ - orr r0, r3, #I_BIT|F_BIT - msr spsr_c, r0 + mrs r3, spsr /* disable interrupt */ + orr r0, r3, #I_BIT|F_BIT + msr spsr_c, r0 - ldr r0, =.+8 /* switch to interrupted task's stack */ - movs pc, r0 + ldr r0, =.+8 /* switch to interrupted task's stack */ + movs pc, r0 - stmfd sp!, {r2} /* push old task's pc */ - stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */ - mov r4, r1 /* Special optimised code below */ - mov r5, r3 - ldmfd r4!, {r0-r3} - stmfd sp!, {r0-r3} /* push old task's r3-r0 */ - stmfd sp!, {r5} /* push old task's psr */ - mrs r4, spsr - stmfd sp!, {r4} /* push old task's spsr */ + stmfd sp!, {r2} /* push old task's pc */ + stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */ + mov r4, r1 /* Special optimised code below */ + mov r5, r3 + ldmfd r4!, {r0-r3} + stmfd sp!, {r0-r3} /* push old task's r3-r0 */ + stmfd sp!, {r5} /* push old task's psr */ + mrs r4, spsr + stmfd sp!, {r4} /* push old task's spsr */ - ldr r4, =rt_interrupt_from_thread - ldr r5, [r4] - str sp, [r5] /* store sp in preempted tasks's TCB */ + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] /* store sp in preempted tasks's TCB */ - ldr r6, =rt_interrupt_to_thread - ldr r6, [r6] - ldr sp, [r6] /* get new task's stack pointer */ + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] /* get new task's stack pointer */ - ldmfd sp!, {r4} /* pop new task's spsr */ - msr SPSR_cxsf, r4 - ldmfd sp!, {r4} /* pop new task's psr */ - msr CPSR_cxsf, r4 + ldmfd sp!, {r4} /* pop new task's spsr */ + msr SPSR_cxsf, r4 + ldmfd sp!, {r4} /* pop new task's psr */ + msr CPSR_cxsf, r4 - ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ + ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ diff --git a/libcpu/arm/AT91SAM7X/context_gcc.S b/libcpu/arm/AT91SAM7X/context_gcc.S index 20b6f5e8cc..d4d63631f2 100644 --- a/libcpu/arm/AT91SAM7X/context_gcc.S +++ b/libcpu/arm/AT91SAM7X/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -13,25 +13,25 @@ */ /*@{*/ -#define NOINT 0xc0 +#define NOINT 0xc0 /* * rt_base_t rt_hw_interrupt_disable(); */ .globl rt_hw_interrupt_disable rt_hw_interrupt_disable: - mrs r0, cpsr - orr r1, r0, #NOINT - msr cpsr_c, r1 - mov pc, lr + mrs r0, cpsr + orr r1, r0, #NOINT + msr cpsr_c, r1 + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level); */ .globl rt_hw_interrupt_enable rt_hw_interrupt_enable: - msr cpsr, r0 - mov pc, lr + msr cpsr, r0 + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); @@ -40,23 +40,23 @@ rt_hw_interrupt_enable: */ .globl rt_hw_context_switch rt_hw_context_switch: - stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) - stmfd sp!, {r0-r12, lr} @ push lr & register file + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file - mrs r4, cpsr - stmfd sp!, {r4} @ push cpsr - mrs r4, spsr - stmfd sp!, {r4} @ push spsr + mrs r4, cpsr + stmfd sp!, {r4} @ push cpsr + mrs r4, spsr + stmfd sp!, {r4} @ push spsr - str sp, [r0] @ store sp in preempted tasks TCB - ldr sp, [r1] @ get new task stack pointer + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_to(rt_uint32 to); @@ -64,14 +64,14 @@ rt_hw_context_switch: */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldr sp, [r0] @ get new task stack pointer + ldr sp, [r0] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); @@ -81,15 +81,15 @@ rt_hw_context_switch_to: .globl rt_interrupt_to_thread .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldr r2, =rt_thread_switch_interrupt_flag - ldr r3, [r2] - cmp r3, #1 - beq _reswitch - mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 - str r3, [r2] - ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread - str r0, [r2] + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r3, [r2] + ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + str r0, [r2] _reswitch: - ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread - str r1, [r2] - mov pc, lr + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + mov pc, lr diff --git a/libcpu/arm/AT91SAM7X/context_rvds.S b/libcpu/arm/AT91SAM7X/context_rvds.S index 0d8bf56237..3cc70c76f3 100644 --- a/libcpu/arm/AT91SAM7X/context_rvds.S +++ b/libcpu/arm/AT91SAM7X/context_rvds.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,96 +8,96 @@ * 2009-01-20 Bernard first version */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr + MRS r4, cpsr + STMFD sp!, {r4} ; push cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push spsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP - END \ No newline at end of file + END diff --git a/libcpu/arm/AT91SAM7X/start_gcc.S b/libcpu/arm/AT91SAM7X/start_gcc.S index d1b2334ac0..6e09356134 100644 --- a/libcpu/arm/AT91SAM7X/start_gcc.S +++ b/libcpu/arm/AT91SAM7X/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -8,145 +8,145 @@ * 2006-08-31 Bernard first version */ - /* Internal Memory Base Addresses */ - .equ FLASH_BASE, 0x00100000 - .equ RAM_BASE, 0x00200000 + /* Internal Memory Base Addresses */ + .equ FLASH_BASE, 0x00100000 + .equ RAM_BASE, 0x00200000 - /* Stack Configuration */ - .equ TOP_STACK, 0x00204000 - .equ UND_STACK_SIZE, 0x00000100 - .equ SVC_STACK_SIZE, 0x00000400 - .equ ABT_STACK_SIZE, 0x00000100 - .equ FIQ_STACK_SIZE, 0x00000100 - .equ IRQ_STACK_SIZE, 0x00000100 - .equ USR_STACK_SIZE, 0x00000004 + /* Stack Configuration */ + .equ TOP_STACK, 0x00204000 + .equ UND_STACK_SIZE, 0x00000100 + .equ SVC_STACK_SIZE, 0x00000400 + .equ ABT_STACK_SIZE, 0x00000100 + .equ FIQ_STACK_SIZE, 0x00000100 + .equ IRQ_STACK_SIZE, 0x00000100 + .equ USR_STACK_SIZE, 0x00000004 - /* ARM architecture definitions */ - .equ MODE_USR, 0x10 - .equ MODE_FIQ, 0x11 - .equ MODE_IRQ, 0x12 - .equ MODE_SVC, 0x13 - .equ MODE_ABT, 0x17 - .equ MODE_UND, 0x1B - .equ MODE_SYS, 0x1F + /* ARM architecture definitions */ + .equ MODE_USR, 0x10 + .equ MODE_FIQ, 0x11 + .equ MODE_IRQ, 0x12 + .equ MODE_SVC, 0x13 + .equ MODE_ABT, 0x17 + .equ MODE_UND, 0x1B + .equ MODE_SYS, 0x1F - .equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */ - .equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */ + .equ I_BIT, 0x80 /* when this bit is set, IRQ is disabled */ + .equ F_BIT, 0x40 /* when this bit is set, FIQ is disabled */ .section .init, "ax" .code 32 .align 0 .globl _start _start: - b reset - ldr pc, _vector_undef - ldr pc, _vector_swi - ldr pc, _vector_pabt - ldr pc, _vector_dabt - nop /* reserved vector */ - ldr pc, _vector_irq - ldr pc, _vector_fiq + b reset + ldr pc, _vector_undef + ldr pc, _vector_swi + ldr pc, _vector_pabt + ldr pc, _vector_dabt + nop /* reserved vector */ + ldr pc, _vector_irq + ldr pc, _vector_fiq -_vector_undef: .word vector_undef -_vector_swi: .word vector_swi -_vector_pabt: .word vector_pabt -_vector_dabt: .word vector_dabt -_vector_resv: .word vector_resv -_vector_irq: .word vector_irq -_vector_fiq: .word vector_fiq +_vector_undef: .word vector_undef +_vector_swi: .word vector_swi +_vector_pabt: .word vector_pabt +_vector_dabt: .word vector_dabt +_vector_resv: .word vector_resv +_vector_irq: .word vector_irq +_vector_fiq: .word vector_fiq /* * rtthread bss start and end * which are defined in linker script */ .globl _bss_start -_bss_start: .word __bss_start +_bss_start: .word __bss_start .globl _bss_end -_bss_end: .word __bss_end +_bss_end: .word __bss_end /* the system entry */ reset: - /* disable watchdog */ - ldr r0, =0xFFFFFD40 - ldr r1, =0x00008000 - str r1, [r0, #0x04] - - /* enable the main oscillator */ - ldr r0, =0xFFFFFC00 - ldr r1, =0x00000601 - str r1, [r0, #0x20] - - /* wait for main oscillator to stabilize */ + /* disable watchdog */ + ldr r0, =0xFFFFFD40 + ldr r1, =0x00008000 + str r1, [r0, #0x04] + + /* enable the main oscillator */ + ldr r0, =0xFFFFFC00 + ldr r1, =0x00000601 + str r1, [r0, #0x20] + + /* wait for main oscillator to stabilize */ moscs_loop: - ldr r2, [r0, #0x68] - ands r2, r2, #1 - beq moscs_loop - - /* set up the PLL */ - ldr r1, =0x00191C05 - str r1, [r0, #0x2C] - - /* wait for PLL to lock */ + ldr r2, [r0, #0x68] + ands r2, r2, #1 + beq moscs_loop + + /* set up the PLL */ + ldr r1, =0x00191C05 + str r1, [r0, #0x2C] + + /* wait for PLL to lock */ pll_loop: - ldr r2, [r0, #0x68] - ands r2, r2, #0x04 - beq pll_loop - - /* select clock */ - ldr r1, =0x00000007 - str r1, [r0, #0x30] - + ldr r2, [r0, #0x68] + ands r2, r2, #0x04 + beq pll_loop + + /* select clock */ + ldr r1, =0x00000007 + str r1, [r0, #0x30] + #ifdef __FLASH_BUILD__ - /* copy exception vectors into internal sram */ + /* copy exception vectors into internal sram */ /* - mov r8, #RAM_BASE - ldr r9, =_start - ldmia r9!, {r0-r7} - stmia r8!, {r0-r7} - ldmia r9!, {r0-r6} - stmia r8!, {r0-r6} + mov r8, #RAM_BASE + ldr r9, =_start + ldmia r9!, {r0-r7} + stmia r8!, {r0-r7} + ldmia r9!, {r0-r6} + stmia r8!, {r0-r6} */ #endif - - /* setup stack for each mode */ - ldr r0, =TOP_STACK - - /* set stack */ - /* undefined instruction mode */ - msr cpsr_c, #MODE_UND|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #UND_STACK_SIZE - - /* abort mode */ - msr cpsr_c, #MODE_ABT|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #ABT_STACK_SIZE - - /* FIQ mode */ - msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #FIQ_STACK_SIZE - - /* IRQ mode */ - msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT - mov sp, r0 - sub r0, r0, #IRQ_STACK_SIZE - - /* supervisor mode */ - msr cpsr_c, #MODE_SVC|I_BIT|F_BIT - mov sp, r0 - - /* remap SRAM to 0x0000 */ - /* - ldr r0, =0xFFFFFF00 - mov r1, #0x01 - str r1, [r0] - */ - - /* mask all IRQs */ - ldr r1, =0xFFFFF124 - ldr r0, =0XFFFFFFFF - str r0, [r1] + + /* setup stack for each mode */ + ldr r0, =TOP_STACK + + /* set stack */ + /* undefined instruction mode */ + msr cpsr_c, #MODE_UND|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #UND_STACK_SIZE + + /* abort mode */ + msr cpsr_c, #MODE_ABT|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #ABT_STACK_SIZE + + /* FIQ mode */ + msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #FIQ_STACK_SIZE + + /* IRQ mode */ + msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT + mov sp, r0 + sub r0, r0, #IRQ_STACK_SIZE + + /* supervisor mode */ + msr cpsr_c, #MODE_SVC|I_BIT|F_BIT + mov sp, r0 + + /* remap SRAM to 0x0000 */ + /* + ldr r0, =0xFFFFFF00 + mov r1, #0x01 + str r1, [r0] + */ + + /* mask all IRQs */ + ldr r1, =0xFFFFF124 + ldr r0, =0XFFFFFFFF + str r0, [r1] /* copy .data to SRAM */ ldr r1, =_sidata /* .data start in image */ @@ -187,14 +187,14 @@ ctor_loop: b ctor_loop ctor_end: - - /* start RT-Thread Kernel */ - ldr pc, _rtthread_startup - + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup + _rtthread_startup: .word rtthread_startup /* exception handlers */ -vector_undef: b vector_undef +vector_undef: b vector_undef vector_swi : b vector_swi vector_pabt : b vector_pabt vector_dabt : b vector_dabt @@ -206,70 +206,70 @@ vector_resv : b vector_resv .globl rt_interrupt_from_thread .globl rt_interrupt_to_thread vector_irq: - stmfd sp!, {r0-r12,lr} - bl rt_interrupt_enter - bl rt_hw_trap_irq - bl rt_interrupt_leave + stmfd sp!, {r0-r12,lr} + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave - /* - * if rt_thread_switch_interrupt_flag set, jump to - * rt_hw_context_switch_interrupt_do and don't return - */ - ldr r0, =rt_thread_switch_interrupt_flag - ldr r1, [r0] - cmp r1, #1 - beq rt_hw_context_switch_interrupt_do + /* + * if rt_thread_switch_interrupt_flag set, jump to + * rt_hw_context_switch_interrupt_do and don't return + */ + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq rt_hw_context_switch_interrupt_do - ldmfd sp!, {r0-r12,lr} - subs pc, lr, #4 + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 vector_fiq: - stmfd sp!,{r0-r7,lr} - bl rt_hw_trap_fiq - ldmfd sp!,{r0-r7,lr} - subs pc,lr,#4 + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc,lr,#4 /* * void rt_hw_context_switch_interrupt_do(rt_base_t flag) */ rt_hw_context_switch_interrupt_do: - mov r1, #0 @ clear flag - str r1, [r0] + mov r1, #0 @ clear flag + str r1, [r0] - ldmfd sp!, {r0-r12,lr}@ reload saved registers - stmfd sp!, {r0-r3} @ save r0-r3 - mov r1, sp - add sp, sp, #16 @ restore sp - sub r2, lr, #4 @ save old task's pc to r2 + ldmfd sp!, {r0-r12,lr}@ reload saved registers + stmfd sp!, {r0-r3} @ save r0-r3 + mov r1, sp + add sp, sp, #16 @ restore sp + sub r2, lr, #4 @ save old task's pc to r2 - mrs r3, spsr @ disable interrupt - orr r0, r3, #I_BIT|F_BIT - msr spsr_c, r0 + mrs r3, spsr @ disable interrupt + orr r0, r3, #I_BIT|F_BIT + msr spsr_c, r0 - ldr r0, =.+8 @ switch to interrupted task's stack - movs pc, r0 + ldr r0, =.+8 @ switch to interrupted task's stack + movs pc, r0 - stmfd sp!, {r2} @ push old task's pc - stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 - mov r4, r1 @ Special optimised code below - mov r5, r3 - ldmfd r4!, {r0-r3} - stmfd sp!, {r0-r3} @ push old task's r3-r0 - stmfd sp!, {r5} @ push old task's psr - mrs r4, spsr - stmfd sp!, {r4} @ push old task's spsr + stmfd sp!, {r2} @ push old task's pc + stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 + mov r4, r1 @ Special optimised code below + mov r5, r3 + ldmfd r4!, {r0-r3} + stmfd sp!, {r0-r3} @ push old task's r3-r0 + stmfd sp!, {r5} @ push old task's psr + mrs r4, spsr + stmfd sp!, {r4} @ push old task's spsr - ldr r4, =rt_interrupt_from_thread - ldr r5, [r4] - str sp, [r5] @ store sp in preempted tasks's TCB + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB - ldr r6, =rt_interrupt_to_thread - ldr r6, [r6] - ldr sp, [r6] @ get new task's stack pointer + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer - ldmfd sp!, {r4} @ pop new task's spsr - msr SPSR_cxsf, r4 - ldmfd sp!, {r4} @ pop new task's psr - msr CPSR_cxsf, r4 + ldmfd sp!, {r4} @ pop new task's spsr + msr SPSR_cxsf, r4 + ldmfd sp!, {r4} @ pop new task's psr + msr CPSR_cxsf, r4 - ldmfd sp!, {r0-r12,lr,pc} @ pop new task's r0-r12,lr & pc + ldmfd sp!, {r0-r12,lr,pc} @ pop new task's r0-r12,lr & pc diff --git a/libcpu/arm/am335x/cp15_gcc.S b/libcpu/arm/am335x/cp15_gcc.S index 9860a229da..6568f7d030 100644 --- a/libcpu/arm/am335x/cp15_gcc.S +++ b/libcpu/arm/am335x/cp15_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -26,7 +26,7 @@ rt_cpu_get_sctlr: .globl rt_cpu_dcache_enable rt_cpu_dcache_enable: - mrc p15, #0, r0, c1, c0, #0 + mrc p15, #0, r0, c1, c0, #0 orr r0, r0, #0x00000004 mcr p15, #0, r0, c1, c0, #0 bx lr @@ -35,7 +35,7 @@ rt_cpu_dcache_enable: rt_cpu_icache_enable: mrc p15, #0, r0, c1, c0, #0 orr r0, r0, #0x00001000 - mcr p15, #0, r0, c1, c0, #0 + mcr p15, #0, r0, c1, c0, #0 bx lr _FLD_MAX_WAY: @@ -45,48 +45,48 @@ _FLD_MAX_IDX: .globl rt_cpu_dcache_clean_flush rt_cpu_dcache_clean_flush: - push {r4-r11} - dmb + push {r4-r11} + dmb mrc p15, #1, r0, c0, c0, #1 @ read clid register ands r3, r0, #0x7000000 @ get level of coherency - mov r3, r3, lsr #23 - beq finished - mov r10, #0 + mov r3, r3, lsr #23 + beq finished + mov r10, #0 loop1: - add r2, r10, r10, lsr #1 + add r2, r10, r10, lsr #1 mov r1, r0, lsr r2 - and r1, r1, #7 - cmp r1, #2 - blt skip - mcr p15, #2, r10, c0, c0, #0 - isb - mrc p15, #1, r1, c0, c0, #0 - and r2, r1, #7 - add r2, r2, #4 - ldr r4, _FLD_MAX_WAY + and r1, r1, #7 + cmp r1, #2 + blt skip + mcr p15, #2, r10, c0, c0, #0 + isb + mrc p15, #1, r1, c0, c0, #0 + and r2, r1, #7 + add r2, r2, #4 + ldr r4, _FLD_MAX_WAY ands r4, r4, r1, lsr #3 clz r5, r4 ldr r7, _FLD_MAX_IDX - ands r7, r7, r1, lsr #13 + ands r7, r7, r1, lsr #13 loop2: - mov r9, r4 + mov r9, r4 loop3: - orr r11, r10, r9, lsl r5 - orr r11, r11, r7, lsl r2 - mcr p15, #0, r11, c7, c14, #2 - subs r9, r9, #1 - bge loop3 - subs r7, r7, #1 - bge loop2 -skip: - add r10, r10, #2 - cmp r3, r10 - bgt loop1 + orr r11, r10, r9, lsl r5 + orr r11, r11, r7, lsl r2 + mcr p15, #0, r11, c7, c14, #2 + subs r9, r9, #1 + bge loop3 + subs r7, r7, #1 + bge loop2 +skip: + add r10, r10, #2 + cmp r3, r10 + bgt loop1 finished: dsb - isb - pop {r4-r11} + isb + pop {r4-r11} bx lr .globl rt_cpu_dcache_disable @@ -108,11 +108,11 @@ rt_cpu_icache_disable: .globl rt_cpu_mmu_disable rt_cpu_mmu_disable: - mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb - mrc p15, #0, r0, c1, c0, #0 - bic r0, r0, #1 + mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #1 mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit - dsb + dsb bx lr .globl rt_cpu_mmu_enable diff --git a/libcpu/arm/am335x/cp15_iar.s b/libcpu/arm/am335x/cp15_iar.s index 058dc6074e..9e155fa0aa 100644 --- a/libcpu/arm/am335x/cp15_iar.s +++ b/libcpu/arm/am335x/cp15_iar.s @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,9 +7,9 @@ * Date Author Notes * 2015-04-06 zchong change to iar compiler from convert from cp15_gcc.S */ - + SECTION .text:CODE:NOROOT(2) - + ARM EXPORT rt_cpu_vector_set_base @@ -17,7 +17,7 @@ rt_cpu_vector_set_base: MCR p15, #0, r0, c12, c0, #0 DSB BX lr - + EXPORT rt_cpu_vector_get_base rt_cpu_vector_get_base: MRC p15, #0, r0, c12, c0, #0 @@ -30,7 +30,7 @@ rt_cpu_get_sctlr: EXPORT rt_cpu_dcache_enable rt_cpu_dcache_enable: - MRC p15, #0, r0, c1, c0, #0 + MRC p15, #0, r0, c1, c0, #0 ORR r0, r0, #0x00000004 MCR p15, #0, r0, c1, c0, #0 BX lr @@ -39,7 +39,7 @@ rt_cpu_dcache_enable: rt_cpu_icache_enable: MRC p15, #0, r0, c1, c0, #0 ORR r0, r0, #0x00001000 - MCR p15, #0, r0, c1, c0, #0 + MCR p15, #0, r0, c1, c0, #0 BX lr ;_FLD_MAX_WAY DEFINE 0x3ff @@ -48,50 +48,50 @@ rt_cpu_icache_enable: EXPORT rt_cpu_dcache_clean_flush rt_cpu_dcache_clean_flush: - PUSH {r4-r11} - DMB + PUSH {r4-r11} + DMB MRC p15, #1, r0, c0, c0, #1 ; read clid register ANDS r3, r0, #0x7000000 ; get level of coherency - MOV r3, r3, lsr #23 - BEQ finished - MOV r10, #0 + MOV r3, r3, lsr #23 + BEQ finished + MOV r10, #0 loop1: - ADD r2, r10, r10, lsr #1 + ADD r2, r10, r10, lsr #1 MOV r1, r0, lsr r2 - AND r1, r1, #7 - CMP r1, #2 - BLT skip - MCR p15, #2, r10, c0, c0, #0 - ISB - MRC p15, #1, r1, c0, c0, #0 - AND r2, r1, #7 - ADD r2, r2, #4 - ;LDR r4, _FLD_MAX_WAY + AND r1, r1, #7 + CMP r1, #2 + BLT skip + MCR p15, #2, r10, c0, c0, #0 + ISB + MRC p15, #1, r1, c0, c0, #0 + AND r2, r1, #7 + ADD r2, r2, #4 + ;LDR r4, _FLD_MAX_WAY LDR r4, =0x3FF ANDS r4, r4, r1, lsr #3 CLZ r5, r4 ;LDR r7, _FLD_MAX_IDX LDR r7, =0x7FF - ANDS r7, r7, r1, lsr #13 + ANDS r7, r7, r1, lsr #13 loop2: - MOV r9, r4 + MOV r9, r4 loop3: - ORR r11, r10, r9, lsl r5 - ORR r11, r11, r7, lsl r2 - MCR p15, #0, r11, c7, c14, #2 - SUBS r9, r9, #1 - BGE loop3 - SUBS r7, r7, #1 - BGE loop2 -skip: - ADD r10, r10, #2 - CMP r3, r10 - BGT loop1 + ORR r11, r10, r9, lsl r5 + ORR r11, r11, r7, lsl r2 + MCR p15, #0, r11, c7, c14, #2 + SUBS r9, r9, #1 + BGE loop3 + SUBS r7, r7, #1 + BGE loop2 +skip: + ADD r10, r10, #2 + CMP r3, r10 + BGT loop1 finished: DSB - ISB - POP {r4-r11} + ISB + POP {r4-r11} BX lr @@ -115,11 +115,11 @@ rt_cpu_icache_disable: EXPORT rt_cpu_mmu_disable rt_cpu_mmu_disable: - MCR p15, #0, r0, c8, c7, #0 ; invalidate tlb - MRC p15, #0, r0, c1, c0, #0 - BIC r0, r0, #1 + MCR p15, #0, r0, c8, c7, #0 ; invalidate tlb + MRC p15, #0, r0, c1, c0, #0 + BIC r0, r0, #1 MCR p15, #0, r0, c1, c0, #0 ; clear mmu bit - DSB + DSB BX lr EXPORT rt_cpu_mmu_enable @@ -135,5 +135,5 @@ rt_cpu_tlb_set: MCR p15, #0, r0, c2, c0, #0 DMB BX lr - + END diff --git a/libcpu/arm/am335x/start_gcc.S b/libcpu/arm/am335x/start_gcc.S index 7e996e2a80..07f505c7ff 100644 --- a/libcpu/arm/am335x/start_gcc.S +++ b/libcpu/arm/am335x/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -65,7 +65,7 @@ bss_loop: /* call C++ constructors of global objects */ ldr r0, =__ctors_start__ ldr r1, =__ctors_end__ - + ctor_loop: cmp r0, r1 beq ctor_end @@ -150,7 +150,7 @@ vector_undef: vector_swi: bl rt_hw_trap_swi - .align 5 + .align 5 .globl vector_pabt vector_pabt: bl rt_hw_trap_pabt diff --git a/libcpu/arm/am335x/start_iar.s b/libcpu/arm/am335x/start_iar.s index e06d7b8861..beb3113b70 100644 --- a/libcpu/arm/am335x/start_iar.s +++ b/libcpu/arm/am335x/start_iar.s @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2015-04-06 zchong the first version + * 2015-04-06 zchong the first version */ MODULE ?cstartup - + ; -------------------- ; Mode, correspords to bits 0-5 in CPSR @@ -25,7 +25,7 @@ ABT_MODE DEFINE 0x17 ; Abort mode UND_MODE DEFINE 0x1B ; Undefined Instruction mode SYS_MODE DEFINE 0x1F ; System mode - + ;; Forward declaration of sections. SECTION IRQ_STACK:DATA:NOROOT(3) SECTION FIQ_STACK:DATA:NOROOT(3) @@ -34,8 +34,8 @@ SYS_MODE DEFINE 0x1F ; System mode SECTION UND_STACK:DATA:NOROOT(3) SECTION CSTACK:DATA:NOROOT(3) SECTION .text:CODE - - + + SECTION .intvec:CODE:NOROOT(5) PUBLIC __vector @@ -95,7 +95,7 @@ FIQ_Addr: DCD FIQ_Handler EXTERN rt_current_thread EXTERN vmm_thread EXTERN vmm_virq_check - + EXTERN __cmain REQUIRE __vector EXTWEAK __iar_init_core @@ -135,7 +135,7 @@ __iar_program_start: MSR cpsr_c, r0 ; Change the mode LDR sp, =SFE(FIQ_STACK) ; End of FIQ_STACK BIC sp,sp,#0x7 ; Make sure SP is 8 aligned - + BIC r0,r0,#MODE_MSK ; Clear the mode bits ORR r0,r0,#ABT_MODE ; Set Abort mode bits MSR cpsr_c,r0 ; Change the mode @@ -165,7 +165,7 @@ __iar_program_start: ;; Continue to __cmain for C-level initialization. B __cmain - + Undefined_Handler: SUB sp, sp, #72 STMIA sp, {r0 - r12} ;/* Calling r0-r12 */ @@ -217,7 +217,7 @@ Abort_Handler: LDR lr, [sp, #60] ;/* Get PC */ ADD sp, sp, #72 MOVS pc, lr ;/* return & move spsr_svc into cpsr */ - + FIQ_Handler: STMFD sp!,{r0-r7,lr} BL rt_hw_trap_fiq @@ -274,5 +274,5 @@ rt_hw_context_switch_interrupt_do: MSR spsr_cxsf, r4 LDMFD sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr - + END diff --git a/libcpu/arm/am335x/vector_gcc.S b/libcpu/arm/am335x/vector_gcc.S index 60d3c6cf1d..9c30f62851 100644 --- a/libcpu/arm/am335x/vector_gcc.S +++ b/libcpu/arm/am335x/vector_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -48,4 +48,4 @@ _vector_irq: _vector_fiq: .word vector_fiq -.balignl 16,0xdeadbeef +.balignl 16,0xdeadbeef diff --git a/libcpu/arm/arm926/context_iar.S b/libcpu/arm/arm926/context_iar.S index 902552734e..f4588ec1ae 100644 --- a/libcpu/arm/arm926/context_iar.S +++ b/libcpu/arm/arm926/context_iar.S @@ -79,4 +79,4 @@ _reswitch: STR R1, [R2] MOV PC, LR END - + diff --git a/libcpu/arm/arm926/start_gcc.S b/libcpu/arm/arm926/start_gcc.S index 658dcf8656..56f996cbf0 100644 --- a/libcpu/arm/arm926/start_gcc.S +++ b/libcpu/arm/arm926/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -71,7 +71,7 @@ _vector_fiq: /* *************************************** - * Stack and Heap Definitions + * Stack and Heap Definitions *************************************** */ .section .data @@ -107,7 +107,7 @@ svc_stack_start: /* *************************************** - * Startup Code + * Startup Code *************************************** */ .section .text @@ -126,10 +126,10 @@ reset: ldr sp, =svc_stack_start ldr r0, =rt_low_level_init blx r0 - + /* init stack */ bl stack_setup - + /* clear bss */ mov r0, #0 ldr r1, =__bss_start @@ -139,7 +139,7 @@ bss_clear_loop: cmp r1, r2 strlo r0, [r1], #4 blo bss_clear_loop - + /* call c++ constructors of global objects */ /* ldr r0, =__ctors_start__ @@ -178,7 +178,7 @@ cpu_init_crit: mcr p15, 0, r0, c1, c0, 0 bx lr - + stack_setup: /* Setup Stack for each mode */ mrs r0, cpsr @@ -209,10 +209,10 @@ stack_setup: ldr sp, =svc_stack_start bx lr - + /* *************************************** - * exception handlers + * exception handlers *************************************** */ /* Interrupt */ @@ -238,42 +238,42 @@ vector_irq: subs pc, lr, #4 rt_hw_context_switch_interrupt_do: - mov r1, #0 + mov r1, #0 str r1, [r0] - mov r1, sp + mov r1, sp add sp, sp, #4*4 ldmfd sp!, {r4-r12,lr} - mrs r0, spsr - sub r2, lr, #4 + mrs r0, spsr + sub r2, lr, #4 msr cpsr_c, #I_BIT|F_BIT|MODE_SVC - stmfd sp!, {r2} + stmfd sp!, {r2} stmfd sp!, {r4-r12,lr} - ldmfd r1, {r1-r4} - stmfd sp!, {r1-r4} - stmfd sp!, {r0} + ldmfd r1, {r1-r4} + stmfd sp!, {r1-r4} + stmfd sp!, {r0} ldr r4, =rt_interrupt_from_thread ldr r5, [r4] - str sp, [r5] + str sp, [r5] ldr r6, =rt_interrupt_to_thread ldr r6, [r6] - ldr sp, [r6] + ldr sp, [r6] - ldmfd sp!, {r4} + ldmfd sp!, {r4} msr spsr_cxsf, r4 - ldmfd sp!, {r0-r12,lr,pc}^ + ldmfd sp!, {r0-r12,lr,pc}^ /* Exception */ .macro push_svc_reg sub sp, sp, #17 * 4 - stmia sp, {r0 - r12} + stmia sp, {r0 - r12} mov r0, sp - mrs r6, spsr + mrs r6, spsr str lr, [r0, #15*4] str r6, [r0, #16*4] str sp, [r0, #13*4] diff --git a/libcpu/arm/armv6/arm_entry_gcc.S b/libcpu/arm/armv6/arm_entry_gcc.S index 6d4ac111d0..c11c691d41 100644 --- a/libcpu/arm/armv6/arm_entry_gcc.S +++ b/libcpu/arm/armv6/arm_entry_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -14,113 +14,113 @@ //#define DEBUG -.macro PRINT, str +.macro PRINT, str #ifdef DEBUG - stmfd sp!, {r0-r3, ip, lr} - add r0, pc, #4 - bl rt_kprintf - b 1f - .asciz "UNDEF: \str\n" - .balign 4 -1: ldmfd sp!, {r0-r3, ip, lr} + stmfd sp!, {r0-r3, ip, lr} + add r0, pc, #4 + bl rt_kprintf + b 1f + .asciz "UNDEF: \str\n" + .balign 4 +1: ldmfd sp!, {r0-r3, ip, lr} #endif - .endm + .endm .macro PRINT1, str, arg #ifdef DEBUG - stmfd sp!, {r0-r3, ip, lr} - mov r1, \arg - add r0, pc, #4 - bl rt_kprintf - b 1f - .asciz "UNDEF: \str\n" - .balign 4 -1: ldmfd sp!, {r0-r3, ip, lr} + stmfd sp!, {r0-r3, ip, lr} + mov r1, \arg + add r0, pc, #4 + bl rt_kprintf + b 1f + .asciz "UNDEF: \str\n" + .balign 4 +1: ldmfd sp!, {r0-r3, ip, lr} #endif - .endm + .endm .macro PRINT3, str, arg1, arg2, arg3 #ifdef DEBUG - stmfd sp!, {r0-r3, ip, lr} - mov r3, \arg3 - mov r2, \arg2 - mov r1, \arg1 - add r0, pc, #4 - bl rt_kprintf - b 1f - .asciz "UNDEF: \str\n" - .balign 4 -1: ldmfd sp!, {r0-r3, ip, lr} + stmfd sp!, {r0-r3, ip, lr} + mov r3, \arg3 + mov r2, \arg2 + mov r1, \arg1 + add r0, pc, #4 + bl rt_kprintf + b 1f + .asciz "UNDEF: \str\n" + .balign 4 +1: ldmfd sp!, {r0-r3, ip, lr} #endif - .endm + .endm -.macro get_current_thread, rd - ldr \rd, .current_thread - ldr \rd, [\rd] - .endm +.macro get_current_thread, rd + ldr \rd, .current_thread + ldr \rd, [\rd] + .endm .current_thread: - .word rt_current_thread + .word rt_current_thread #ifdef RT_USING_NEON - .align 6 + .align 6 /* is the neon instuction on arm mode? */ .neon_opcode: - .word 0xfe000000 @ mask - .word 0xf2000000 @ opcode + .word 0xfe000000 @ mask + .word 0xf2000000 @ opcode - .word 0xff100000 @ mask - .word 0xf4000000 @ opcode + .word 0xff100000 @ mask + .word 0xf4000000 @ opcode - .word 0x00000000 @ end mask - .word 0x00000000 @ end opcode + .word 0x00000000 @ end mask + .word 0x00000000 @ end opcode #endif /* undefined instruction exception processing */ .globl undef_entry undef_entry: - PRINT1 "r0=0x%08x", r0 - PRINT1 "r2=0x%08x", r2 - PRINT1 "r9=0x%08x", r9 - PRINT1 "sp=0x%08x", sp + PRINT1 "r0=0x%08x", r0 + PRINT1 "r2=0x%08x", r2 + PRINT1 "r9=0x%08x", r9 + PRINT1 "sp=0x%08x", sp #ifdef RT_USING_NEON - ldr r6, .neon_opcode + ldr r6, .neon_opcode __check_neon_instruction: - ldr r7, [r6], #4 @ load mask value - cmp r7, #0 @ end mask? - beq __check_vfp_instruction - and r8, r0, r7 - ldr r7, [r6], #4 @ load opcode value - cmp r8, r7 @ is NEON instruction? - bne __check_neon_instruction - b vfp_entry + ldr r7, [r6], #4 @ load mask value + cmp r7, #0 @ end mask? + beq __check_vfp_instruction + and r8, r0, r7 + ldr r7, [r6], #4 @ load opcode value + cmp r8, r7 @ is NEON instruction? + bne __check_neon_instruction + b vfp_entry __check_vfp_instruction: #endif - tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC instruction has bit 27 - tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2 instruction - moveq pc, lr @ no vfp coprocessor instruction, return - get_current_thread r10 - and r8, r0, #0x00000f00 @ get coprocessor number - PRINT1 "CP=0x%08x", r8 - add pc, pc, r8, lsr #6 - nop - mov pc, lr @ CP0 - mov pc, lr @ CP1 - mov pc, lr @ CP2 - mov pc, lr @ CP3 - mov pc, lr @ CP4 - mov pc, lr @ CP5 - mov pc, lr @ CP6 - mov pc, lr @ CP7 - mov pc, lr @ CP8 - mov pc, lr @ CP9 - mov pc, lr @ CP10 VFP - mov pc, lr @ CP11 VFP - mov pc, lr @ CP12 - mov pc, lr @ CP13 - mov pc, lr @ CP14 DEBUG - mov pc, lr @ CP15 SYS CONTROL + tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC instruction has bit 27 + tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2 instruction + moveq pc, lr @ no vfp coprocessor instruction, return + get_current_thread r10 + and r8, r0, #0x00000f00 @ get coprocessor number + PRINT1 "CP=0x%08x", r8 + add pc, pc, r8, lsr #6 + nop + mov pc, lr @ CP0 + mov pc, lr @ CP1 + mov pc, lr @ CP2 + mov pc, lr @ CP3 + mov pc, lr @ CP4 + mov pc, lr @ CP5 + mov pc, lr @ CP6 + mov pc, lr @ CP7 + mov pc, lr @ CP8 + mov pc, lr @ CP9 + mov pc, lr @ CP10 VFP + mov pc, lr @ CP11 VFP + mov pc, lr @ CP12 + mov pc, lr @ CP13 + mov pc, lr @ CP14 DEBUG + mov pc, lr @ CP15 SYS CONTROL diff --git a/libcpu/arm/common/divsi3.S b/libcpu/arm/common/divsi3.S index 3941bfc476..2e4fbf1133 100644 --- a/libcpu/arm/common/divsi3.S +++ b/libcpu/arm/common/divsi3.S @@ -1,12 +1,12 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes */ -/* $NetBSD: divsi3.S,v 1.5 2005/02/26 22:58:56 perry Exp $ */ +/* $NetBSD: divsi3.S,v 1.5 2005/02/26 22:58:56 perry Exp $ */ /* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND @@ -26,376 +26,376 @@ * stack is aligned as there's a possibility of branching to L_overflow * which makes a C call */ - .text - .align 0 - .globl __umodsi3 - .type __umodsi3 , function + .text + .align 0 + .globl __umodsi3 + .type __umodsi3 , function __umodsi3: - stmfd sp!, {lr} - sub sp, sp, #4 /* align stack */ - bl .L_udivide - add sp, sp, #4 /* unalign stack */ - mov r0, r1 - ldmfd sp!, {pc} + stmfd sp!, {lr} + sub sp, sp, #4 /* align stack */ + bl .L_udivide + add sp, sp, #4 /* unalign stack */ + mov r0, r1 + ldmfd sp!, {pc} - .text - .align 0 - .globl __modsi3 - .type __modsi3 , function + .text + .align 0 + .globl __modsi3 + .type __modsi3 , function __modsi3: - stmfd sp!, {lr} - sub sp, sp, #4 /* align stack */ - bl .L_divide - add sp, sp, #4 /* unalign stack */ - mov r0, r1 - ldmfd sp!, {pc} + stmfd sp!, {lr} + sub sp, sp, #4 /* align stack */ + bl .L_divide + add sp, sp, #4 /* unalign stack */ + mov r0, r1 + ldmfd sp!, {pc} .L_overflow: - /* XXX should cause a fatal error */ - mvn r0, #0 - mov pc, lr + /* XXX should cause a fatal error */ + mvn r0, #0 + mov pc, lr - .text - .align 0 - .globl __udivsi3 - .type __udivsi3 , function + .text + .align 0 + .globl __udivsi3 + .type __udivsi3 , function __udivsi3: -.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ - eor r0, r1, r0 - eor r1, r0, r1 - eor r0, r1, r0 - /* r0 = r1 / r0; r1 = r1 % r0 */ - cmp r0, #1 - bcc .L_overflow - beq .L_divide_l0 - mov ip, #0 - movs r1, r1 - bpl .L_divide_l1 - orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ - movs r1, r1, lsr #1 - orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ - b .L_divide_l1 +.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc .L_overflow + beq .L_divide_l0 + mov ip, #0 + movs r1, r1 + bpl .L_divide_l1 + orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ + movs r1, r1, lsr #1 + orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ + b .L_divide_l1 -.L_divide_l0: /* r0 == 1 */ - mov r0, r1 - mov r1, #0 - mov pc, lr +.L_divide_l0: /* r0 == 1 */ + mov r0, r1 + mov r1, #0 + mov pc, lr - .text - .align 0 - .globl __divsi3 - .type __divsi3 , function + .text + .align 0 + .globl __divsi3 + .type __divsi3 , function __divsi3: -.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ - eor r0, r1, r0 - eor r1, r0, r1 - eor r0, r1, r0 - /* r0 = r1 / r0; r1 = r1 % r0 */ - cmp r0, #1 - bcc .L_overflow - beq .L_divide_l0 - ands ip, r0, #0x80000000 - rsbmi r0, r0, #0 - ands r2, r1, #0x80000000 - eor ip, ip, r2 - rsbmi r1, r1, #0 - orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ - /* ip bit 0x80000000 = -ve remainder */ +.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc .L_overflow + beq .L_divide_l0 + ands ip, r0, #0x80000000 + rsbmi r0, r0, #0 + ands r2, r1, #0x80000000 + eor ip, ip, r2 + rsbmi r1, r1, #0 + orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ + /* ip bit 0x80000000 = -ve remainder */ .L_divide_l1: - mov r2, #1 - mov r3, #0 + mov r2, #1 + mov r3, #0 - /* - * If the highest bit of the dividend is set, we have to be - * careful when shifting the divisor. Test this. - */ - movs r1,r1 - bpl .L_old_code + /* + * If the highest bit of the dividend is set, we have to be + * careful when shifting the divisor. Test this. + */ + movs r1,r1 + bpl .L_old_code - /* - * At this point, the highest bit of r1 is known to be set. - * We abuse this below in the tst instructions. - */ - tst r1, r0 /*, lsl #0 */ - bmi .L_divide_b1 - tst r1, r0, lsl #1 - bmi .L_divide_b2 - tst r1, r0, lsl #2 - bmi .L_divide_b3 - tst r1, r0, lsl #3 - bmi .L_divide_b4 - tst r1, r0, lsl #4 - bmi .L_divide_b5 - tst r1, r0, lsl #5 - bmi .L_divide_b6 - tst r1, r0, lsl #6 - bmi .L_divide_b7 - tst r1, r0, lsl #7 - bmi .L_divide_b8 - tst r1, r0, lsl #8 - bmi .L_divide_b9 - tst r1, r0, lsl #9 - bmi .L_divide_b10 - tst r1, r0, lsl #10 - bmi .L_divide_b11 - tst r1, r0, lsl #11 - bmi .L_divide_b12 - tst r1, r0, lsl #12 - bmi .L_divide_b13 - tst r1, r0, lsl #13 - bmi .L_divide_b14 - tst r1, r0, lsl #14 - bmi .L_divide_b15 - tst r1, r0, lsl #15 - bmi .L_divide_b16 - tst r1, r0, lsl #16 - bmi .L_divide_b17 - tst r1, r0, lsl #17 - bmi .L_divide_b18 - tst r1, r0, lsl #18 - bmi .L_divide_b19 - tst r1, r0, lsl #19 - bmi .L_divide_b20 - tst r1, r0, lsl #20 - bmi .L_divide_b21 - tst r1, r0, lsl #21 - bmi .L_divide_b22 - tst r1, r0, lsl #22 - bmi .L_divide_b23 - tst r1, r0, lsl #23 - bmi .L_divide_b24 - tst r1, r0, lsl #24 - bmi .L_divide_b25 - tst r1, r0, lsl #25 - bmi .L_divide_b26 - tst r1, r0, lsl #26 - bmi .L_divide_b27 - tst r1, r0, lsl #27 - bmi .L_divide_b28 - tst r1, r0, lsl #28 - bmi .L_divide_b29 - tst r1, r0, lsl #29 - bmi .L_divide_b30 - tst r1, r0, lsl #30 - bmi .L_divide_b31 + /* + * At this point, the highest bit of r1 is known to be set. + * We abuse this below in the tst instructions. + */ + tst r1, r0 /*, lsl #0 */ + bmi .L_divide_b1 + tst r1, r0, lsl #1 + bmi .L_divide_b2 + tst r1, r0, lsl #2 + bmi .L_divide_b3 + tst r1, r0, lsl #3 + bmi .L_divide_b4 + tst r1, r0, lsl #4 + bmi .L_divide_b5 + tst r1, r0, lsl #5 + bmi .L_divide_b6 + tst r1, r0, lsl #6 + bmi .L_divide_b7 + tst r1, r0, lsl #7 + bmi .L_divide_b8 + tst r1, r0, lsl #8 + bmi .L_divide_b9 + tst r1, r0, lsl #9 + bmi .L_divide_b10 + tst r1, r0, lsl #10 + bmi .L_divide_b11 + tst r1, r0, lsl #11 + bmi .L_divide_b12 + tst r1, r0, lsl #12 + bmi .L_divide_b13 + tst r1, r0, lsl #13 + bmi .L_divide_b14 + tst r1, r0, lsl #14 + bmi .L_divide_b15 + tst r1, r0, lsl #15 + bmi .L_divide_b16 + tst r1, r0, lsl #16 + bmi .L_divide_b17 + tst r1, r0, lsl #17 + bmi .L_divide_b18 + tst r1, r0, lsl #18 + bmi .L_divide_b19 + tst r1, r0, lsl #19 + bmi .L_divide_b20 + tst r1, r0, lsl #20 + bmi .L_divide_b21 + tst r1, r0, lsl #21 + bmi .L_divide_b22 + tst r1, r0, lsl #22 + bmi .L_divide_b23 + tst r1, r0, lsl #23 + bmi .L_divide_b24 + tst r1, r0, lsl #24 + bmi .L_divide_b25 + tst r1, r0, lsl #25 + bmi .L_divide_b26 + tst r1, r0, lsl #26 + bmi .L_divide_b27 + tst r1, r0, lsl #27 + bmi .L_divide_b28 + tst r1, r0, lsl #28 + bmi .L_divide_b29 + tst r1, r0, lsl #29 + bmi .L_divide_b30 + tst r1, r0, lsl #30 + bmi .L_divide_b31 /* * instead of: - * tst r1, r0, lsl #31 - * bmi .L_divide_b32 + * tst r1, r0, lsl #31 + * bmi .L_divide_b32 */ - b .L_divide_b32 + b .L_divide_b32 .L_old_code: - cmp r1, r0 - bcc .L_divide_b0 - cmp r1, r0, lsl #1 - bcc .L_divide_b1 - cmp r1, r0, lsl #2 - bcc .L_divide_b2 - cmp r1, r0, lsl #3 - bcc .L_divide_b3 - cmp r1, r0, lsl #4 - bcc .L_divide_b4 - cmp r1, r0, lsl #5 - bcc .L_divide_b5 - cmp r1, r0, lsl #6 - bcc .L_divide_b6 - cmp r1, r0, lsl #7 - bcc .L_divide_b7 - cmp r1, r0, lsl #8 - bcc .L_divide_b8 - cmp r1, r0, lsl #9 - bcc .L_divide_b9 - cmp r1, r0, lsl #10 - bcc .L_divide_b10 - cmp r1, r0, lsl #11 - bcc .L_divide_b11 - cmp r1, r0, lsl #12 - bcc .L_divide_b12 - cmp r1, r0, lsl #13 - bcc .L_divide_b13 - cmp r1, r0, lsl #14 - bcc .L_divide_b14 - cmp r1, r0, lsl #15 - bcc .L_divide_b15 - cmp r1, r0, lsl #16 - bcc .L_divide_b16 - cmp r1, r0, lsl #17 - bcc .L_divide_b17 - cmp r1, r0, lsl #18 - bcc .L_divide_b18 - cmp r1, r0, lsl #19 - bcc .L_divide_b19 - cmp r1, r0, lsl #20 - bcc .L_divide_b20 - cmp r1, r0, lsl #21 - bcc .L_divide_b21 - cmp r1, r0, lsl #22 - bcc .L_divide_b22 - cmp r1, r0, lsl #23 - bcc .L_divide_b23 - cmp r1, r0, lsl #24 - bcc .L_divide_b24 - cmp r1, r0, lsl #25 - bcc .L_divide_b25 - cmp r1, r0, lsl #26 - bcc .L_divide_b26 - cmp r1, r0, lsl #27 - bcc .L_divide_b27 - cmp r1, r0, lsl #28 - bcc .L_divide_b28 - cmp r1, r0, lsl #29 - bcc .L_divide_b29 - cmp r1, r0, lsl #30 - bcc .L_divide_b30 + cmp r1, r0 + bcc .L_divide_b0 + cmp r1, r0, lsl #1 + bcc .L_divide_b1 + cmp r1, r0, lsl #2 + bcc .L_divide_b2 + cmp r1, r0, lsl #3 + bcc .L_divide_b3 + cmp r1, r0, lsl #4 + bcc .L_divide_b4 + cmp r1, r0, lsl #5 + bcc .L_divide_b5 + cmp r1, r0, lsl #6 + bcc .L_divide_b6 + cmp r1, r0, lsl #7 + bcc .L_divide_b7 + cmp r1, r0, lsl #8 + bcc .L_divide_b8 + cmp r1, r0, lsl #9 + bcc .L_divide_b9 + cmp r1, r0, lsl #10 + bcc .L_divide_b10 + cmp r1, r0, lsl #11 + bcc .L_divide_b11 + cmp r1, r0, lsl #12 + bcc .L_divide_b12 + cmp r1, r0, lsl #13 + bcc .L_divide_b13 + cmp r1, r0, lsl #14 + bcc .L_divide_b14 + cmp r1, r0, lsl #15 + bcc .L_divide_b15 + cmp r1, r0, lsl #16 + bcc .L_divide_b16 + cmp r1, r0, lsl #17 + bcc .L_divide_b17 + cmp r1, r0, lsl #18 + bcc .L_divide_b18 + cmp r1, r0, lsl #19 + bcc .L_divide_b19 + cmp r1, r0, lsl #20 + bcc .L_divide_b20 + cmp r1, r0, lsl #21 + bcc .L_divide_b21 + cmp r1, r0, lsl #22 + bcc .L_divide_b22 + cmp r1, r0, lsl #23 + bcc .L_divide_b23 + cmp r1, r0, lsl #24 + bcc .L_divide_b24 + cmp r1, r0, lsl #25 + bcc .L_divide_b25 + cmp r1, r0, lsl #26 + bcc .L_divide_b26 + cmp r1, r0, lsl #27 + bcc .L_divide_b27 + cmp r1, r0, lsl #28 + bcc .L_divide_b28 + cmp r1, r0, lsl #29 + bcc .L_divide_b29 + cmp r1, r0, lsl #30 + bcc .L_divide_b30 .L_divide_b32: - cmp r1, r0, lsl #31 - subhs r1, r1,r0, lsl #31 - addhs r3, r3,r2, lsl #31 + cmp r1, r0, lsl #31 + subhs r1, r1,r0, lsl #31 + addhs r3, r3,r2, lsl #31 .L_divide_b31: - cmp r1, r0, lsl #30 - subhs r1, r1,r0, lsl #30 - addhs r3, r3,r2, lsl #30 + cmp r1, r0, lsl #30 + subhs r1, r1,r0, lsl #30 + addhs r3, r3,r2, lsl #30 .L_divide_b30: - cmp r1, r0, lsl #29 - subhs r1, r1,r0, lsl #29 - addhs r3, r3,r2, lsl #29 + cmp r1, r0, lsl #29 + subhs r1, r1,r0, lsl #29 + addhs r3, r3,r2, lsl #29 .L_divide_b29: - cmp r1, r0, lsl #28 - subhs r1, r1,r0, lsl #28 - addhs r3, r3,r2, lsl #28 + cmp r1, r0, lsl #28 + subhs r1, r1,r0, lsl #28 + addhs r3, r3,r2, lsl #28 .L_divide_b28: - cmp r1, r0, lsl #27 - subhs r1, r1,r0, lsl #27 - addhs r3, r3,r2, lsl #27 + cmp r1, r0, lsl #27 + subhs r1, r1,r0, lsl #27 + addhs r3, r3,r2, lsl #27 .L_divide_b27: - cmp r1, r0, lsl #26 - subhs r1, r1,r0, lsl #26 - addhs r3, r3,r2, lsl #26 + cmp r1, r0, lsl #26 + subhs r1, r1,r0, lsl #26 + addhs r3, r3,r2, lsl #26 .L_divide_b26: - cmp r1, r0, lsl #25 - subhs r1, r1,r0, lsl #25 - addhs r3, r3,r2, lsl #25 + cmp r1, r0, lsl #25 + subhs r1, r1,r0, lsl #25 + addhs r3, r3,r2, lsl #25 .L_divide_b25: - cmp r1, r0, lsl #24 - subhs r1, r1,r0, lsl #24 - addhs r3, r3,r2, lsl #24 + cmp r1, r0, lsl #24 + subhs r1, r1,r0, lsl #24 + addhs r3, r3,r2, lsl #24 .L_divide_b24: - cmp r1, r0, lsl #23 - subhs r1, r1,r0, lsl #23 - addhs r3, r3,r2, lsl #23 + cmp r1, r0, lsl #23 + subhs r1, r1,r0, lsl #23 + addhs r3, r3,r2, lsl #23 .L_divide_b23: - cmp r1, r0, lsl #22 - subhs r1, r1,r0, lsl #22 - addhs r3, r3,r2, lsl #22 + cmp r1, r0, lsl #22 + subhs r1, r1,r0, lsl #22 + addhs r3, r3,r2, lsl #22 .L_divide_b22: - cmp r1, r0, lsl #21 - subhs r1, r1,r0, lsl #21 - addhs r3, r3,r2, lsl #21 + cmp r1, r0, lsl #21 + subhs r1, r1,r0, lsl #21 + addhs r3, r3,r2, lsl #21 .L_divide_b21: - cmp r1, r0, lsl #20 - subhs r1, r1,r0, lsl #20 - addhs r3, r3,r2, lsl #20 + cmp r1, r0, lsl #20 + subhs r1, r1,r0, lsl #20 + addhs r3, r3,r2, lsl #20 .L_divide_b20: - cmp r1, r0, lsl #19 - subhs r1, r1,r0, lsl #19 - addhs r3, r3,r2, lsl #19 + cmp r1, r0, lsl #19 + subhs r1, r1,r0, lsl #19 + addhs r3, r3,r2, lsl #19 .L_divide_b19: - cmp r1, r0, lsl #18 - subhs r1, r1,r0, lsl #18 - addhs r3, r3,r2, lsl #18 + cmp r1, r0, lsl #18 + subhs r1, r1,r0, lsl #18 + addhs r3, r3,r2, lsl #18 .L_divide_b18: - cmp r1, r0, lsl #17 - subhs r1, r1,r0, lsl #17 - addhs r3, r3,r2, lsl #17 + cmp r1, r0, lsl #17 + subhs r1, r1,r0, lsl #17 + addhs r3, r3,r2, lsl #17 .L_divide_b17: - cmp r1, r0, lsl #16 - subhs r1, r1,r0, lsl #16 - addhs r3, r3,r2, lsl #16 + cmp r1, r0, lsl #16 + subhs r1, r1,r0, lsl #16 + addhs r3, r3,r2, lsl #16 .L_divide_b16: - cmp r1, r0, lsl #15 - subhs r1, r1,r0, lsl #15 - addhs r3, r3,r2, lsl #15 + cmp r1, r0, lsl #15 + subhs r1, r1,r0, lsl #15 + addhs r3, r3,r2, lsl #15 .L_divide_b15: - cmp r1, r0, lsl #14 - subhs r1, r1,r0, lsl #14 - addhs r3, r3,r2, lsl #14 + cmp r1, r0, lsl #14 + subhs r1, r1,r0, lsl #14 + addhs r3, r3,r2, lsl #14 .L_divide_b14: - cmp r1, r0, lsl #13 - subhs r1, r1,r0, lsl #13 - addhs r3, r3,r2, lsl #13 + cmp r1, r0, lsl #13 + subhs r1, r1,r0, lsl #13 + addhs r3, r3,r2, lsl #13 .L_divide_b13: - cmp r1, r0, lsl #12 - subhs r1, r1,r0, lsl #12 - addhs r3, r3,r2, lsl #12 + cmp r1, r0, lsl #12 + subhs r1, r1,r0, lsl #12 + addhs r3, r3,r2, lsl #12 .L_divide_b12: - cmp r1, r0, lsl #11 - subhs r1, r1,r0, lsl #11 - addhs r3, r3,r2, lsl #11 + cmp r1, r0, lsl #11 + subhs r1, r1,r0, lsl #11 + addhs r3, r3,r2, lsl #11 .L_divide_b11: - cmp r1, r0, lsl #10 - subhs r1, r1,r0, lsl #10 - addhs r3, r3,r2, lsl #10 + cmp r1, r0, lsl #10 + subhs r1, r1,r0, lsl #10 + addhs r3, r3,r2, lsl #10 .L_divide_b10: - cmp r1, r0, lsl #9 - subhs r1, r1,r0, lsl #9 - addhs r3, r3,r2, lsl #9 + cmp r1, r0, lsl #9 + subhs r1, r1,r0, lsl #9 + addhs r3, r3,r2, lsl #9 .L_divide_b9: - cmp r1, r0, lsl #8 - subhs r1, r1,r0, lsl #8 - addhs r3, r3,r2, lsl #8 + cmp r1, r0, lsl #8 + subhs r1, r1,r0, lsl #8 + addhs r3, r3,r2, lsl #8 .L_divide_b8: - cmp r1, r0, lsl #7 - subhs r1, r1,r0, lsl #7 - addhs r3, r3,r2, lsl #7 + cmp r1, r0, lsl #7 + subhs r1, r1,r0, lsl #7 + addhs r3, r3,r2, lsl #7 .L_divide_b7: - cmp r1, r0, lsl #6 - subhs r1, r1,r0, lsl #6 - addhs r3, r3,r2, lsl #6 + cmp r1, r0, lsl #6 + subhs r1, r1,r0, lsl #6 + addhs r3, r3,r2, lsl #6 .L_divide_b6: - cmp r1, r0, lsl #5 - subhs r1, r1,r0, lsl #5 - addhs r3, r3,r2, lsl #5 + cmp r1, r0, lsl #5 + subhs r1, r1,r0, lsl #5 + addhs r3, r3,r2, lsl #5 .L_divide_b5: - cmp r1, r0, lsl #4 - subhs r1, r1,r0, lsl #4 - addhs r3, r3,r2, lsl #4 + cmp r1, r0, lsl #4 + subhs r1, r1,r0, lsl #4 + addhs r3, r3,r2, lsl #4 .L_divide_b4: - cmp r1, r0, lsl #3 - subhs r1, r1,r0, lsl #3 - addhs r3, r3,r2, lsl #3 + cmp r1, r0, lsl #3 + subhs r1, r1,r0, lsl #3 + addhs r3, r3,r2, lsl #3 .L_divide_b3: - cmp r1, r0, lsl #2 - subhs r1, r1,r0, lsl #2 - addhs r3, r3,r2, lsl #2 + cmp r1, r0, lsl #2 + subhs r1, r1,r0, lsl #2 + addhs r3, r3,r2, lsl #2 .L_divide_b2: - cmp r1, r0, lsl #1 - subhs r1, r1,r0, lsl #1 - addhs r3, r3,r2, lsl #1 + cmp r1, r0, lsl #1 + subhs r1, r1,r0, lsl #1 + addhs r3, r3,r2, lsl #1 .L_divide_b1: - cmp r1, r0 - subhs r1, r1, r0 - addhs r3, r3, r2 + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 .L_divide_b0: - tst ip, #0x20000000 - bne .L_udivide_l1 - mov r0, r3 - cmp ip, #0 - rsbmi r1, r1, #0 - movs ip, ip, lsl #1 - bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ - rsbmi r0, r0, #0 - mov pc, lr + tst ip, #0x20000000 + bne .L_udivide_l1 + mov r0, r3 + cmp ip, #0 + rsbmi r1, r1, #0 + movs ip, ip, lsl #1 + bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ + rsbmi r0, r0, #0 + mov pc, lr .L_udivide_l1: - tst ip, #0x10000000 - mov r1, r1, lsl #1 - orrne r1, r1, #1 - mov r3, r3, lsl #1 - cmp r1, r0 - subhs r1, r1, r0 - addhs r3, r3, r2 - mov r0, r3 - mov pc, lr + tst ip, #0x10000000 + mov r1, r1, lsl #1 + orrne r1, r1, #1 + mov r3, r3, lsl #1 + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 + mov r0, r3 + mov pc, lr diff --git a/libcpu/arm/cortex-a/start_gcc.S b/libcpu/arm/cortex-a/start_gcc.S index 908468476e..5fcc0d03fe 100644 --- a/libcpu/arm/cortex-a/start_gcc.S +++ b/libcpu/arm/cortex-a/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/libcpu/arm/cortex-m0/context_gcc.S b/libcpu/arm/cortex-m0/context_gcc.S index a504ee076e..6e06661708 100644 --- a/libcpu/arm/cortex-m0/context_gcc.S +++ b/libcpu/arm/cortex-m0/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -12,18 +12,18 @@ * 2013-06-18 aozima add restore MSP feature. * 2013-11-04 bright fixed hardfault bug for gcc. */ - + .cpu cortex-m0 .fpu softvfp .syntax unified .thumb .text - .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ - .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ - .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ - .equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ - .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ + .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ + .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ + .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ + .equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ + .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ /* * rt_base_t rt_hw_interrupt_disable(); @@ -90,7 +90,7 @@ PendSV_Handler: LDR R0, =rt_thread_switch_interrupt_flag LDR R1, [R0] CMP R1, #0x00 - BEQ pendsv_exit /* pendsv aLReady handled */ + BEQ pendsv_exit /* pendsv aLReady handled */ /* clear rt_thread_switch_interrupt_flag to 0 */ MOVS R1, #0 @@ -101,7 +101,7 @@ PendSV_Handler: CMP R1, #0x00 BEQ switch_to_thread /* skip register save at the first time */ - MRS R1, PSP /* get from thread stack pointer */ + MRS R1, PSP /* get from thread stack pointer */ SUBS R1, R1, #0x20 /* space for {R4 - R7} and {R8 - R11} */ LDR R0, [R0] @@ -119,7 +119,7 @@ switch_to_thread: LDR R1, [R1] LDR R1, [R1] /* load thread stack pointer */ - LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ + LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ PUSH {R4 - R7} /* push {R4 - R7} to MSP for copy {R8 - R11} */ LDMIA R1!, {R4 - R7} /* pop thread {R8 - R11} high register from thread stack to {R4 - R7} */ diff --git a/libcpu/arm/cortex-m0/context_rvds.S b/libcpu/arm/cortex-m0/context_rvds.S index 072486587c..c6afec4f18 100644 --- a/libcpu/arm/cortex-m0/context_rvds.S +++ b/libcpu/arm/cortex-m0/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -46,8 +46,8 @@ rt_hw_interrupt_disable PROC ; */ rt_hw_interrupt_enable PROC EXPORT rt_hw_interrupt_enable - MSR PRIMASK, r0 - BX LR + MSR PRIMASK, r0 + BX LR ENDP ;/* diff --git a/libcpu/arm/cortex-m23/context_gcc.S b/libcpu/arm/cortex-m23/context_gcc.S index 48f90413d9..21f7fb3f94 100644 --- a/libcpu/arm/cortex-m23/context_gcc.S +++ b/libcpu/arm/cortex-m23/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -13,18 +13,18 @@ * 2013-11-04 bright fixed hardfault bug for gcc. * 2019-03-31 xuzhuoyi port to Cortex-M23. */ - + .cpu cortex-m23 .fpu softvfp .syntax unified .thumb .text - .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ - .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ - .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ - .equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ - .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ + .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ + .equ NVIC_INT_CTRL, 0xE000ED04 /* interrupt control state register */ + .equ NVIC_SHPR3, 0xE000ED20 /* system priority register (3) */ + .equ NVIC_PENDSV_PRI, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ + .equ NVIC_PENDSVSET, 0x10000000 /* value to trigger PendSV exception */ /* * rt_base_t rt_hw_interrupt_disable(); @@ -91,7 +91,7 @@ PendSV_Handler: LDR R0, =rt_thread_switch_interrupt_flag LDR R1, [R0] CMP R1, #0x00 - BEQ pendsv_exit /* pendsv aLReady handled */ + BEQ pendsv_exit /* pendsv aLReady handled */ /* clear rt_thread_switch_interrupt_flag to 0 */ MOVS R1, #0 @@ -102,7 +102,7 @@ PendSV_Handler: CMP R1, #0x00 BEQ switch_to_thread /* skip register save at the first time */ - MRS R1, PSP /* get from thread stack pointer */ + MRS R1, PSP /* get from thread stack pointer */ SUBS R1, R1, #0x20 /* space for {R4 - R7} and {R8 - R11} */ LDR R0, [R0] @@ -120,7 +120,7 @@ switch_to_thread: LDR R1, [R1] LDR R1, [R1] /* load thread stack pointer */ - LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ + LDMIA R1!, {R4 - R7} /* pop thread {R4 - R7} register from thread stack */ PUSH {R4 - R7} /* push {R4 - R7} to MSP for copy {R8 - R11} */ LDMIA R1!, {R4 - R7} /* pop thread {R8 - R11} high register from thread stack to {R4 - R7} */ diff --git a/libcpu/arm/cortex-m23/context_rvds.S b/libcpu/arm/cortex-m23/context_rvds.S index ca381d0f8f..4771012779 100644 --- a/libcpu/arm/cortex-m23/context_rvds.S +++ b/libcpu/arm/cortex-m23/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2019, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -47,8 +47,8 @@ rt_hw_interrupt_disable PROC ; */ rt_hw_interrupt_enable PROC EXPORT rt_hw_interrupt_enable - MSR PRIMASK, r0 - BX LR + MSR PRIMASK, r0 + BX LR ENDP ;/* diff --git a/libcpu/arm/cortex-m3/context_gcc.S b/libcpu/arm/cortex-m3/context_gcc.S index 2878d20082..82246c6379 100644 --- a/libcpu/arm/cortex-m3/context_gcc.S +++ b/libcpu/arm/cortex-m3/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -12,7 +12,7 @@ * 2013-06-18 aozima add restore MSP feature. * 2013-07-09 aozima enhancement hard fault exception handler. */ - + .cpu cortex-m3 .fpu softvfp .syntax unified @@ -22,7 +22,7 @@ .equ SCB_VTOR, 0xE000ED08 /* Vector Table Offset Register */ .equ ICSR, 0xE000ED04 /* interrupt control state register */ .equ PENDSVSET_BIT, 0x10000000 /* value to trigger PendSV exception */ - + .equ SHPR3, 0xE000ED20 /* system priority register (3) */ .equ PENDSV_PRI_LOWEST, 0xFFFF0000 /* PendSV and SysTick priority value (lowest) */ diff --git a/libcpu/arm/cortex-m3/context_rvds.S b/libcpu/arm/cortex-m3/context_rvds.S index a661430499..8a4f9880af 100644 --- a/libcpu/arm/cortex-m3/context_rvds.S +++ b/libcpu/arm/cortex-m3/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * diff --git a/libcpu/arm/cortex-m33/context_iar.S b/libcpu/arm/cortex-m33/context_iar.S index 67cf2727a2..cfc2459167 100644 --- a/libcpu/arm/cortex-m33/context_iar.S +++ b/libcpu/arm/cortex-m33/context_iar.S @@ -272,7 +272,7 @@ HardFault_Handler: get_sp_done STMFD r0!, {r4 - r11} ; push r4 - r11 register - + LDR r2, =rt_trustzone_current_context ; r2 = &rt_secure_current_context LDR r2, [r2] ; r2 = *r2 MOV r3, lr ; r3 = lr diff --git a/libcpu/arm/cortex-m33/syscall_gcc.S b/libcpu/arm/cortex-m33/syscall_gcc.S index d7d16fb8a0..c648378844 100644 --- a/libcpu/arm/cortex-m33/syscall_gcc.S +++ b/libcpu/arm/cortex-m33/syscall_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,7 +19,7 @@ .global tzcall .type tzcall, %function tzcall: - SVC 1 /* call SVC 1 */ + SVC 1 /* call SVC 1 */ BX LR tzcall_entry: diff --git a/libcpu/arm/cortex-m33/syscall_iar.S b/libcpu/arm/cortex-m33/syscall_iar.S index aa30ead9e3..53a6790ec1 100644 --- a/libcpu/arm/cortex-m33/syscall_iar.S +++ b/libcpu/arm/cortex-m33/syscall_iar.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -23,7 +23,7 @@ .global tzcall .type tzcall, %function tzcall: - SVC 1 ;/* call SVC 1 */ + SVC 1 ;/* call SVC 1 */ BX LR tzcall_entry: diff --git a/libcpu/arm/cortex-m33/syscall_rvds.S b/libcpu/arm/cortex-m33/syscall_rvds.S index 95ee247ee5..9189debd7e 100644 --- a/libcpu/arm/cortex-m33/syscall_rvds.S +++ b/libcpu/arm/cortex-m33/syscall_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -20,7 +20,7 @@ ; */ tzcall PROC EXPORT tzcall - SVC 1 ;call SVC 1 + SVC 1 ;call SVC 1 BX LR ENDP @@ -28,7 +28,7 @@ tzcall PROC tzcall_entry PROC PUSH {R1, R4, LR} MOV R4, R1 ; copy thread SP to R4 - LDMFD R4!, {r0 - r3} ; pop user stack, get input arg0, arg1, arg2 + LDMFD R4!, {r0 - r3} ; pop user stack, get input arg0, arg1, arg2 STMFD R4!, {r0 - r3} ; push stack, user stack recovery BL rt_secure_svc_handle ; call fun POP {R1, R4, LR} @@ -71,4 +71,4 @@ get_sp_done ALIGN - END \ No newline at end of file + END diff --git a/libcpu/arm/cortex-m4/context_gcc.S b/libcpu/arm/cortex-m4/context_gcc.S index 0c69b4d4dd..6f1ffa3b17 100644 --- a/libcpu/arm/cortex-m4/context_gcc.S +++ b/libcpu/arm/cortex-m4/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -104,13 +104,13 @@ PendSV_Handler: CBZ r1, switch_to_thread /* skip register save at the first time */ MRS r1, psp /* get from thread stack pointer */ - + #if defined (__VFP_FP__) && !defined(__SOFTFP__) TST lr, #0x10 /* if(!EXC_RETURN[4]) */ IT EQ VSTMDBEQ r1!, {d8 - d15} /* push FPU register s16~s31 */ #endif - + STMFD r1!, {r4 - r11} /* push r4 - r11 register */ #if defined (__VFP_FP__) && !defined(__SOFTFP__) diff --git a/libcpu/arm/cortex-m7/context_gcc.S b/libcpu/arm/cortex-m7/context_gcc.S index 0c69b4d4dd..b5a4920862 100644 --- a/libcpu/arm/cortex-m7/context_gcc.S +++ b/libcpu/arm/cortex-m7/context_gcc.S @@ -104,13 +104,13 @@ PendSV_Handler: CBZ r1, switch_to_thread /* skip register save at the first time */ MRS r1, psp /* get from thread stack pointer */ - + #if defined (__VFP_FP__) && !defined(__SOFTFP__) TST lr, #0x10 /* if(!EXC_RETURN[4]) */ IT EQ VSTMDBEQ r1!, {d8 - d15} /* push FPU register s16~s31 */ #endif - + STMFD r1!, {r4 - r11} /* push r4 - r11 register */ #if defined (__VFP_FP__) && !defined(__SOFTFP__) diff --git a/libcpu/arm/cortex-r4/context_ccs.asm b/libcpu/arm/cortex-r4/context_ccs.asm index 9463556743..6a734cb494 100644 --- a/libcpu/arm/cortex-r4/context_ccs.asm +++ b/libcpu/arm/cortex-r4/context_ccs.asm @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -59,17 +59,17 @@ rt_hw_context_switch STMDB sp!, {r4} ; push cpsr .if (__TI_VFP_SUPPORT__) - VMRS r4, fpexc + VMRS r4, fpexc TST r4, #0x40000000 BEQ __no_vfp_frame1 - VSTMDB sp!, {d0-d15} + VSTMDB sp!, {d0-d15} VMRS r5, fpscr ; TODO: add support for Common VFPv3. ; Save registers like FPINST, FPINST2 STMDB sp!, {r5} __no_vfp_frame1 STMDB sp!, {r4} - .endif + .endif STR sp, [r0] ; store sp in preempted tasks TCB LDR sp, [r1] ; get new task stack pointer @@ -81,7 +81,7 @@ __no_vfp_frame1 BEQ __no_vfp_frame2 LDMIA sp!, {r1} ; get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame2 .endif @@ -107,7 +107,7 @@ rt_hw_context_switch_to BEQ __no_vfp_frame_to LDMIA sp!, {r1} ; get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_to .endif @@ -143,17 +143,17 @@ IRQ_Handler STMDB sp!, {r0-r12,lr} .if (__TI_VFP_SUPPORT__) - VMRS r0, fpexc + VMRS r0, fpexc TST r0, #0x40000000 BEQ __no_vfp_frame_str_irq - VSTMDB sp!, {d0-d15} + VSTMDB sp!, {d0-d15} VMRS r1, fpscr ; TODO: add support for Common VFPv3. ; Save registers like FPINST, FPINST2 STMDB sp!, {r1} __no_vfp_frame_str_irq STMDB sp!, {r0} - .endif + .endif BL rt_interrupt_enter BL rt_hw_trap_irq @@ -173,7 +173,7 @@ __no_vfp_frame_str_irq BEQ __no_vfp_frame_ldr_irq LDMIA sp!, {r1} ; get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_ldr_irq .endif @@ -195,7 +195,7 @@ rt_hw_context_switch_interrupt_do BEQ __no_vfp_frame_do1 LDMIA sp!, {r1} ; get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_do1 .endif @@ -219,7 +219,7 @@ __no_vfp_frame_do1 STMDB sp!, {r3} ; push old task's cpsr .if (__TI_VFP_SUPPORT__) - VMRS r0, fpexc + VMRS r0, fpexc TST r0, #0x40000000 BEQ __no_vfp_frame_do2 VSTMDB sp!, {d0-d15} @@ -229,7 +229,7 @@ __no_vfp_frame_do1 STMDB sp!, {r1} __no_vfp_frame_do2 STMDB sp!, {r0} - .endif + .endif LDR r4, pfromthread LDR r5, [r4] @@ -246,7 +246,7 @@ __no_vfp_frame_do2 BEQ __no_vfp_frame_do3 LDMIA sp!, {r1} ; get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_do3 .endif diff --git a/libcpu/arm/cortex-r4/context_gcc.S b/libcpu/arm/cortex-r4/context_gcc.S index 50e1069c06..a148fe933e 100644 --- a/libcpu/arm/cortex-r4/context_gcc.S +++ b/libcpu/arm/cortex-r4/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -57,10 +57,10 @@ rt_hw_context_switch: STMDB sp!, {r4} @ push cpsr #if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) - VMRS r4, fpexc + VMRS r4, fpexc TST r4, #0x40000000 BEQ __no_vfp_frame1 - VSTMDB sp!, {d0-d15} + VSTMDB sp!, {d0-d15} VMRS r5, fpscr @ TODO: add support for Common VFPv3. @ Save registers like FPINST, FPINST2 @@ -79,7 +79,7 @@ __no_vfp_frame1: BEQ __no_vfp_frame2 LDMIA sp!, {r1} @ get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame2: #endif @@ -103,7 +103,7 @@ rt_hw_context_switch_to: BEQ __no_vfp_frame_to LDMIA sp!, {r1} @ get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_to: #endif @@ -137,10 +137,10 @@ IRQ_Handler: STMDB sp!, {r0-r12,lr} #if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) - VMRS r0, fpexc + VMRS r0, fpexc TST r0, #0x40000000 BEQ __no_vfp_frame_str_irq - VSTMDB sp!, {d0-d15} + VSTMDB sp!, {d0-d15} VMRS r1, fpscr @ TODO: add support for Common VFPv3. @ Save registers like FPINST, FPINST2 @@ -167,7 +167,7 @@ __no_vfp_frame_str_irq: BEQ __no_vfp_frame_ldr_irq LDMIA sp!, {r1} @ get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_ldr_irq: #endif @@ -189,7 +189,7 @@ rt_hw_context_switch_interrupt_do: BEQ __no_vfp_frame_do1 LDMIA sp!, {r1} @ get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_do1: #endif @@ -213,7 +213,7 @@ __no_vfp_frame_do1: STMDB sp!, {r3} @ push old task's cpsr #if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) - VMRS r0, fpexc + VMRS r0, fpexc TST r0, #0x40000000 BEQ __no_vfp_frame_do2 VSTMDB sp!, {d0-d15} @@ -240,7 +240,7 @@ __no_vfp_frame_do2: BEQ __no_vfp_frame_do3 LDMIA sp!, {r1} @ get fpscr VMSR fpscr, r1 - VLDMIA sp!, {d0-d15} + VLDMIA sp!, {d0-d15} __no_vfp_frame_do3: #endif diff --git a/libcpu/arm/cortex-r4/start_ccs.asm b/libcpu/arm/cortex-r4/start_ccs.asm index 4334fa9b0f..4436646543 100644 --- a/libcpu/arm/cortex-r4/start_ccs.asm +++ b/libcpu/arm/cortex-r4/start_ccs.asm @@ -502,42 +502,42 @@ _push_svc_reg .macro cps #0x13 str sp, [r0, #13*4] ;/* Save calling SP */ str lr, [r0, #14*4] ;/* Save calling PC */ - .endm + .endm - .ref rt_hw_trap_svc - .def vector_svc + .ref rt_hw_trap_svc + .def vector_svc .asmfunc vector_svc: _push_svc_reg bl rt_hw_trap_svc - sub pc, pc, #-4 + sub pc, pc, #-4 .endasmfunc - .ref rt_hw_trap_pabt - .def vector_pabort + .ref rt_hw_trap_pabt + .def vector_pabort .asmfunc vector_pabort: _push_svc_reg bl rt_hw_trap_pabt - sub pc, pc, #-4 + sub pc, pc, #-4 .endasmfunc - .ref rt_hw_trap_dabt - .def vector_dabort + .ref rt_hw_trap_dabt + .def vector_dabort .asmfunc vector_dabort: _push_svc_reg bl rt_hw_trap_dabt - sub pc, pc, #-4 + sub pc, pc, #-4 .endasmfunc - .ref rt_hw_trap_resv - .def vector_resv + .ref rt_hw_trap_resv + .def vector_resv .asmfunc vector_resv: _push_svc_reg bl rt_hw_trap_resv - sub pc, pc, #-4 + sub pc, pc, #-4 .endasmfunc ;------------------------------------------------------------------------------- diff --git a/libcpu/arm/cortex-r4/start_gcc.S b/libcpu/arm/cortex-r4/start_gcc.S index a347503ec0..de3059e821 100644 --- a/libcpu/arm/cortex-r4/start_gcc.S +++ b/libcpu/arm/cortex-r4/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -462,26 +462,26 @@ turnon_VFP: str lr, [r0, #14*4] @/* Save calling PC */ .endm - .globl vector_svc + .globl vector_svc vector_svc: push_svc_reg bl rt_hw_trap_svc - b . + b . - .globl vector_pabort + .globl vector_pabort vector_pabort: push_svc_reg bl rt_hw_trap_pabt - b . + b . - .globl vector_dabort + .globl vector_dabort vector_dabort: push_svc_reg bl rt_hw_trap_dabt - b . + b . - .globl vector_resv + .globl vector_resv vector_resv: push_svc_reg bl rt_hw_trap_resv - b . + b . diff --git a/libcpu/arm/dm36x/context_rvds.S b/libcpu/arm/dm36x/context_rvds.S index 8e0fc4465b..4054b97d71 100644 --- a/libcpu/arm/dm36x/context_rvds.S +++ b/libcpu/arm/dm36x/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -8,96 +8,96 @@ ; * 2011-08-14 weety copy from mini2440 ; */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr + MRS r4, cpsr + STMFD sp!, {r4} ; push cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push spsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR spsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP - END + END diff --git a/libcpu/arm/lpc214x/context_gcc.S b/libcpu/arm/lpc214x/context_gcc.S index 2b1856be3d..16d4720090 100644 --- a/libcpu/arm/lpc214x/context_gcc.S +++ b/libcpu/arm/lpc214x/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,22 +19,22 @@ 关闭中断,关闭前返回CPSR寄存器值 */ rt_hw_interrupt_disable: - //EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - //ENDP + //EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + //ENDP /* * void rt_hw_interrupt_enable(rt_base_t level); 恢复中断状态 */ rt_hw_interrupt_enable: - //EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - //ENDP + //EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + //ENDP /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); @@ -43,68 +43,68 @@ rt_hw_interrupt_enable: 进行线程的上下文切换 */ rt_hw_context_switch: - //EXPORT rt_hw_context_switch - STMFD sp!, {lr} /* push pc (lr should be pushed in place of PC) */ - /* 把LR寄存器压入栈(这个函数返回后的下一个执行处) */ - STMFD sp!, {r0-r12, lr} /* push lr & register file */ - /* 把R0 – R12以及LR压入栈 */ + //EXPORT rt_hw_context_switch + STMFD sp!, {lr} /* push pc (lr should be pushed in place of PC) */ + /* 把LR寄存器压入栈(这个函数返回后的下一个执行处) */ + STMFD sp!, {r0-r12, lr} /* push lr & register file */ + /* 把R0 – R12以及LR压入栈 */ - MRS r4, cpsr /* 读取CPSR寄存器到R4寄存器 */ - STMFD sp!, {r4} /* push cpsr */ - /* 把R4寄存器压栈(即上一指令取出的CPSR寄存器) */ - MRS r4, spsr /* 读取SPSR寄存器到R4寄存器 */ - STMFD sp!, {r4} /* push spsr */ - /* 把R4寄存器压栈(即SPSR寄存器) */ + MRS r4, cpsr /* 读取CPSR寄存器到R4寄存器 */ + STMFD sp!, {r4} /* push cpsr */ + /* 把R4寄存器压栈(即上一指令取出的CPSR寄存器) */ + MRS r4, spsr /* 读取SPSR寄存器到R4寄存器 */ + STMFD sp!, {r4} /* push spsr */ + /* 把R4寄存器压栈(即SPSR寄存器) */ - STR sp, [r0] /* store sp in preempted tasks TCB */ - /* 把栈指针更新到TCB的sp,是由R0传入此函数 */ - /* 到这里换出线程的上下文都保存在栈中 */ - LDR sp, [r1] /* get new task stack pointer */ - /* 载入切换到线程的TCB的sp */ - /* 从切换到线程的栈中恢复上下文,次序和保存的时候刚好相反 */ + STR sp, [r0] /* store sp in preempted tasks TCB */ + /* 把栈指针更新到TCB的sp,是由R0传入此函数 */ + /* 到这里换出线程的上下文都保存在栈中 */ + LDR sp, [r1] /* get new task stack pointer */ + /* 载入切换到线程的TCB的sp */ + /* 从切换到线程的栈中恢复上下文,次序和保存的时候刚好相反 */ - LDMFD sp!, {r4} /* pop new task spsr */ - /* 出栈到R4寄存器(保存了SPSR寄存器) */ - MSR spsr_cxsf, r4 /* 恢复SPSR寄存器 */ - LDMFD sp!, {r4} /* pop new task cpsr */ - /* 出栈到R4寄存器(保存了CPSR寄存器) */ - MSR cpsr_cxsf, r4 /* 恢复CPSR寄存器 */ + LDMFD sp!, {r4} /* pop new task spsr */ + /* 出栈到R4寄存器(保存了SPSR寄存器) */ + MSR spsr_cxsf, r4 /* 恢复SPSR寄存器 */ + LDMFD sp!, {r4} /* pop new task cpsr */ + /* 出栈到R4寄存器(保存了CPSR寄存器) */ + MSR cpsr_cxsf, r4 /* 恢复CPSR寄存器 */ - LDMFD sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ - /* 对R0 – R12及LR、PC进行恢复 */ - //ENDP + LDMFD sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ + /* 对R0 – R12及LR、PC进行恢复 */ + //ENDP rt_hw_context_switch_to: - //EXPORT rt_hw_context_switch_to - LDR sp, [r0] /* get new task stack pointer */ - /* 获得切换到线程的SP指针 */ + //EXPORT rt_hw_context_switch_to + LDR sp, [r0] /* get new task stack pointer */ + /* 获得切换到线程的SP指针 */ - LDMFD sp!, {r4} /* pop new task spsr */ - /* 出栈R4寄存器(保存了SPSR寄存器值) */ - MSR spsr_cxsf, r4 /* 恢复SPSR寄存器 */ - LDMFD sp!, {r4} /* pop new task cpsr */ - /* 出栈R4寄存器(保存了CPSR寄存器值) */ - MSR cpsr_cxsf, r4 /* 恢复CPSR寄存器 */ + LDMFD sp!, {r4} /* pop new task spsr */ + /* 出栈R4寄存器(保存了SPSR寄存器值) */ + MSR spsr_cxsf, r4 /* 恢复SPSR寄存器 */ + LDMFD sp!, {r4} /* pop new task cpsr */ + /* 出栈R4寄存器(保存了CPSR寄存器值) */ + MSR cpsr_cxsf, r4 /* 恢复CPSR寄存器 */ - LDMFD sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ - /* 恢复R0 – R12,LR及PC寄存器 */ - //ENDP + LDMFD sp!, {r0-r12, lr, pc} /* pop new task r0-r12, lr & pc */ + /* 恢复R0 – R12,LR及PC寄存器 */ + //ENDP rt_hw_context_switch_interrupt: - //EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] /* 载入中断中切换标致地址 */ - CMP r3, #1 /* 等于 1 ?*/ - BEQ _reswitch /* 如果等于1,跳转到_reswitch*/ - MOV r3, #1 /* set rt_thread_switch_interrupt_flag to 1*/ - /* 设置中断中切换标志位1 */ - STR r3, [r2] /* */ - LDR r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread*/ - STR r0, [r2] /* 保存切换出线程栈指针*/ + //EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] /* 载入中断中切换标致地址 */ + CMP r3, #1 /* 等于 1 ?*/ + BEQ _reswitch /* 如果等于1,跳转到_reswitch*/ + MOV r3, #1 /* set rt_thread_switch_interrupt_flag to 1*/ + /* 设置中断中切换标志位1 */ + STR r3, [r2] /* */ + LDR r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread*/ + STR r0, [r2] /* 保存切换出线程栈指针*/ _reswitch: - LDR r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread*/ - STR r1, [r2] /* 保存切换到线程栈指针*/ - BX lr - //ENDP + LDR r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread*/ + STR r1, [r2] /* 保存切换到线程栈指针*/ + BX lr + //ENDP - //END \ No newline at end of file + //END diff --git a/libcpu/arm/lpc214x/context_rvds.S b/libcpu/arm/lpc214x/context_rvds.S index 47ca31cd1f..c5cb59d7e5 100644 --- a/libcpu/arm/lpc214x/context_rvds.S +++ b/libcpu/arm/lpc214x/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -20,141 +20,141 @@ Mode_SYS EQU 0x1F I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr + MRS r4, cpsr TST lr, #0x01 BEQ _ARM_MODE ORR r4, r4, #0x20 ; it's thumb code _ARM_MODE - STMFD sp!, {r4} ; push cpsr + STMFD sp!, {r4} ; push cpsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer LDMFD sp!, {r4} ; pop new task cpsr to spsr - MSR spsr_cxsf, r4 + MSR spsr_cxsf, r4 BIC r4, r4, #0x20 ; must be ARM mode - MSR cpsr_cxsf, r4 + MSR cpsr_cxsf, r4 LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr - ENDP + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer LDMFD sp!, {r4} ; pop new task cpsr to spsr - MSR spsr_cxsf, r4 + MSR spsr_cxsf, r4 BIC r4, r4, #0x20 ; must be ARM mode - MSR cpsr_cxsf, r4 + MSR cpsr_cxsf, r4 LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr - ENDP + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP ; /* ; * void rt_hw_context_switch_interrupt_do(rt_base_t flag) ; */ -rt_hw_context_switch_interrupt_do PROC - EXPORT rt_hw_context_switch_interrupt_do - MOV r1, #0 ; clear flag - STR r1, [r0] +rt_hw_context_switch_interrupt_do PROC + EXPORT rt_hw_context_switch_interrupt_do + MOV r1, #0 ; clear flag + STR r1, [r0] - LDMFD sp!, {r0-r12,lr}; reload saved registers - STMFD sp!, {r0-r3} ; save r0-r3 - MOV r1, sp - ADD sp, sp, #16 ; restore sp - SUB r2, lr, #4 ; save old task's pc to r2 + LDMFD sp!, {r0-r12,lr}; reload saved registers + STMFD sp!, {r0-r3} ; save r0-r3 + MOV r1, sp + ADD sp, sp, #16 ; restore sp + SUB r2, lr, #4 ; save old task's pc to r2 - MRS r3, spsr ; get cpsr of interrupt thread + MRS r3, spsr ; get cpsr of interrupt thread - ; switch to SVC mode and no interrupt - MSR cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC + ; switch to SVC mode and no interrupt + MSR cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC - STMFD sp!, {r2} ; push old task's pc - STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4 - MOV r4, r1 ; Special optimised code below - MOV r5, r3 - LDMFD r4!, {r0-r3} - STMFD sp!, {r0-r3} ; push old task's r3-r0 - STMFD sp!, {r5} ; push old task's cpsr + STMFD sp!, {r2} ; push old task's pc + STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4 + MOV r4, r1 ; Special optimised code below + MOV r5, r3 + LDMFD r4!, {r0-r3} + STMFD sp!, {r0-r3} ; push old task's r3-r0 + STMFD sp!, {r5} ; push old task's cpsr - LDR r4, =rt_interrupt_from_thread - LDR r5, [r4] - STR sp, [r5] ; store sp in preempted tasks's TCB + LDR r4, =rt_interrupt_from_thread + LDR r5, [r4] + STR sp, [r5] ; store sp in preempted tasks's TCB - LDR r6, =rt_interrupt_to_thread - LDR r6, [r6] - LDR sp, [r6] ; get new task's stack pointer - - LDMFD sp!, {r4} ; pop new task's cpsr to spsr - MSR spsr_cxsf, r4 - BIC r4, r4, #0x20 ; must be ARM mode - MSR cpsr_cxsf, r4 + LDR r6, =rt_interrupt_to_thread + LDR r6, [r6] + LDR sp, [r6] ; get new task's stack pointer - LDMFD sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr - ENDP + LDMFD sp!, {r4} ; pop new task's cpsr to spsr + MSR spsr_cxsf, r4 + BIC r4, r4, #0x20 ; must be ARM mode + MSR cpsr_cxsf, r4 - END \ No newline at end of file + LDMFD sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr + ENDP + + END diff --git a/libcpu/arm/lpc214x/startup_gcc.S b/libcpu/arm/lpc214x/startup_gcc.S index 5b9b04f0d1..22f316b181 100644 --- a/libcpu/arm/lpc214x/startup_gcc.S +++ b/libcpu/arm/lpc214x/startup_gcc.S @@ -1,25 +1,25 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes */ - .extern main /* 引入外部C入口 */ + .extern main /* 引入外部C入口 */ - .extern rt_interrupt_enter - .extern rt_interrupt_leave - .extern rt_thread_switch_interrupt_flag - .extern rt_interrupt_from_thread - .extern rt_interrupt_to_thread - .extern rt_hw_trap_irq + .extern rt_interrupt_enter + .extern rt_interrupt_leave + .extern rt_thread_switch_interrupt_flag + .extern rt_interrupt_from_thread + .extern rt_interrupt_to_thread + .extern rt_hw_trap_irq - .global start - .global endless_loop + .global start + .global endless_loop .global rt_hw_context_switch_interrupt_do - /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */ + /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */ .set MODE_USR, 0x10 /* User Mode */ .set MODE_FIQ, 0x11 /* FIQ Mode */ .set MODE_IRQ, 0x12 /* IRQ Mode */ @@ -34,107 +34,107 @@ .equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */ /* VPBDIV definitions*/ - .equ VPBDIV, 0xE01FC100 - .set VPBDIV_VALUE, 0x00000000 + .equ VPBDIV, 0xE01FC100 + .set VPBDIV_VALUE, 0x00000000 /* Phase Locked Loop (PLL) definitions*/ - .equ PLL_BASE, 0xE01FC080 /* PLL Base Address */ - .equ PLLCON_OFS, 0x00 /* PLL Control Offset */ - .equ PLLCFG_OFS, 0x04 /* PLL Configuration Offset */ - .equ PLLSTAT_OFS, 0x08 /* PLL Status Offset */ + .equ PLL_BASE, 0xE01FC080 /* PLL Base Address */ + .equ PLLCON_OFS, 0x00 /* PLL Control Offset */ + .equ PLLCFG_OFS, 0x04 /* PLL Configuration Offset */ + .equ PLLSTAT_OFS, 0x08 /* PLL Status Offset */ .equ PLLFEED_OFS, 0x0C /* PLL Feed Offset */ - .equ PLLCON_PLLE, (1<<0) /* PLL Enable */ - .equ PLLCON_PLLC, (1<<1) /* PLL Connect */ - .equ PLLCFG_MSEL, (0x1F<<0) /* PLL Multiplier */ - .equ PLLCFG_PSEL, (0x03<<5) /* PLL Divider */ - .equ PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */ - .equ PLLCFG_Val, 0x00000024 /* MSEL: PLL Multiplier Selection, PSEL: PLL Divider Selection */ + .equ PLLCON_PLLE, (1<<0) /* PLL Enable */ + .equ PLLCON_PLLC, (1<<1) /* PLL Connect */ + .equ PLLCFG_MSEL, (0x1F<<0) /* PLL Multiplier */ + .equ PLLCFG_PSEL, (0x03<<5) /* PLL Divider */ + .equ PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */ + .equ PLLCFG_Val, 0x00000024 /* MSEL: PLL Multiplier Selection, PSEL: PLL Divider Selection */ - .equ MEMMAP, 0xE01FC040 /*Memory Mapping Control*/ + .equ MEMMAP, 0xE01FC040 /*Memory Mapping Control*/ /* Memory Accelerator Module (MAM) definitions*/ - .equ MAM_BASE, 0xE01FC000 - .equ MAMCR_OFS, 0x00 - .equ MAMTIM_OFS, 0x04 + .equ MAM_BASE, 0xE01FC000 + .equ MAMCR_OFS, 0x00 + .equ MAMTIM_OFS, 0x04 .equ MAMCR_Val, 0x00000002 .equ MAMTIM_Val, 0x00000004 - .equ VICIntEnClr, 0xFFFFF014 - .equ VICIntSelect, 0xFFFFF00C + .equ VICIntEnClr, 0xFFFFF014 + .equ VICIntSelect, 0xFFFFF00C /************* 目标配置结束 *************/ /* Setup the operating mode & stack.*/ /* --------------------------------- */ - .global _reset + .global _reset _reset: - .code 32 - .align 0 + .code 32 + .align 0 /************************* PLL_SETUP **********************************/ - ldr r0, =PLL_BASE - mov r1, #0xAA - mov r2, #0x55 + ldr r0, =PLL_BASE + mov r1, #0xAA + mov r2, #0x55 /* Configure and Enable PLL */ - mov r3, #PLLCFG_Val - str r3, [r0, #PLLCFG_OFS] - mov r3, #PLLCON_PLLE - str r3, [r0, #PLLCON_OFS] - str r1, [r0, #PLLFEED_OFS] - str r2, [r0, #PLLFEED_OFS] + mov r3, #PLLCFG_Val + str r3, [r0, #PLLCFG_OFS] + mov r3, #PLLCON_PLLE + str r3, [r0, #PLLCON_OFS] + str r1, [r0, #PLLFEED_OFS] + str r2, [r0, #PLLFEED_OFS] /* Wait until PLL Locked */ PLL_Locked_loop: - ldr r3, [r0, #PLLSTAT_OFS] - ands r3, r3, #PLLSTAT_PLOCK - beq PLL_Locked_loop + ldr r3, [r0, #PLLSTAT_OFS] + ands r3, r3, #PLLSTAT_PLOCK + beq PLL_Locked_loop /* Switch to PLL Clock */ - mov r3, #(PLLCON_PLLE|PLLCON_PLLC) - str r3, [r0, #PLLCON_OFS] - str r1, [r0, #PLLFEED_OFS] - str R2, [r0, #PLLFEED_OFS] + mov r3, #(PLLCON_PLLE|PLLCON_PLLC) + str r3, [r0, #PLLCON_OFS] + str r1, [r0, #PLLFEED_OFS] + str R2, [r0, #PLLFEED_OFS] /************************* PLL_SETUP **********************************/ /************************ Setup VPBDIV ********************************/ - ldr r0, =VPBDIV - ldr r1, =VPBDIV_VALUE - str r1, [r0] + ldr r0, =VPBDIV + ldr r1, =VPBDIV_VALUE + str r1, [r0] /************************ Setup VPBDIV ********************************/ /************** Setup MAM **************/ - ldr r0, =MAM_BASE - mov r1, #MAMTIM_Val - str r1, [r0, #MAMTIM_OFS] - mov r1, #MAMCR_Val - str r1, [r0, #MAMCR_OFS] + ldr r0, =MAM_BASE + mov r1, #MAMTIM_Val + str r1, [r0, #MAMTIM_OFS] + mov r1, #MAMCR_Val + str r1, [r0, #MAMCR_OFS] /************** Setup MAM **************/ /************************ setup stack *********************************/ ldr r0, .undefined_stack_top - sub r0, r0, #4 + sub r0, r0, #4 msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ mov sp, r0 ldr r0, .abort_stack_top - sub r0, r0, #4 + sub r0, r0, #4 msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ mov sp, r0 ldr r0, .fiq_stack_top - sub r0, r0, #4 + sub r0, r0, #4 msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ mov sp, r0 ldr r0, .irq_stack_top - sub r0, r0, #4 + sub r0, r0, #4 msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ mov sp, r0 ldr r0, .svc_stack_top - sub r0, r0, #4 + sub r0, r0, #4 msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ mov sp, r0 /************************ setup stack ********************************/ @@ -152,7 +152,7 @@ data_loop: cmp r3, r2 /* check if data to clear */ blo data_loop /* loop until done */ - + /* clear .bss */ mov r0,#0 /* get a zero */ ldr r1,=__bss_start /* bss start */ @@ -179,20 +179,20 @@ ctor_loop: b ctor_loop ctor_end: - /* enter C code */ - bl main + /* enter C code */ + bl main - .align 0 - .undefined_stack_top: - .word _undefined_stack_top - .abort_stack_top: - .word _abort_stack_top - .fiq_stack_top: - .word _fiq_stack_top - .irq_stack_top: - .word _irq_stack_top - .svc_stack_top: - .word _svc_stack_top + .align 0 + .undefined_stack_top: + .word _undefined_stack_top + .abort_stack_top: + .word _abort_stack_top + .fiq_stack_top: + .word _fiq_stack_top + .irq_stack_top: + .word _irq_stack_top + .svc_stack_top: + .word _svc_stack_top /*********************** END Clear BSS ******************************/ .section .init,"ax" @@ -201,116 +201,116 @@ ctor_end: .globl _start _start: - ldr pc, __start /* reset - _start */ - ldr pc, _undf /* undefined - _undf */ - ldr pc, _swi /* SWI - _swi */ - ldr pc, _pabt /* program abort - _pabt */ - ldr pc, _dabt /* data abort - _dabt */ - .word 0xB8A06F58 /* reserved */ - ldr pc, __IRQ_Handler /* IRQ - read the VIC */ - ldr pc, _fiq /* FIQ - _fiq */ + ldr pc, __start /* reset - _start */ + ldr pc, _undf /* undefined - _undf */ + ldr pc, _swi /* SWI - _swi */ + ldr pc, _pabt /* program abort - _pabt */ + ldr pc, _dabt /* data abort - _dabt */ + .word 0xB8A06F58 /* reserved */ + ldr pc, __IRQ_Handler /* IRQ - read the VIC */ + ldr pc, _fiq /* FIQ - _fiq */ __start:.word _reset -_undf: .word __undf /* undefined */ -_swi: .word __swi /* SWI */ -_pabt: .word __pabt /* program abort */ -_dabt: .word __dabt /* data abort */ +_undf: .word __undf /* undefined */ +_swi: .word __swi /* SWI */ +_pabt: .word __pabt /* program abort */ +_dabt: .word __dabt /* data abort */ temp1: .word 0 __IRQ_Handler: .word IRQ_Handler -_fiq: .word __fiq /* FIQ */ +_fiq: .word __fiq /* FIQ */ -__undf: b . /* undefined */ +__undf: b . /* undefined */ __swi : b . -__pabt: b . /* program abort */ -__dabt: b . /* data abort */ -__fiq : b . /* FIQ */ +__pabt: b . /* program abort */ +__dabt: b . /* data abort */ +__fiq : b . /* FIQ */ /* IRQ入口 */ IRQ_Handler : - stmfd sp!, {r0-r12,lr} /* 对R0 – R12,LR寄存器压栈 */ - bl rt_interrupt_enter /* 通知RT-Thread进入中断模式 */ - bl rt_hw_trap_irq /* 相应中断服务例程处理 */ - bl rt_interrupt_leave /* ; 通知RT-Thread要离开中断模式 */ + stmfd sp!, {r0-r12,lr} /* 对R0 – R12,LR寄存器压栈 */ + bl rt_interrupt_enter /* 通知RT-Thread进入中断模式 */ + bl rt_hw_trap_irq /* 相应中断服务例程处理 */ + bl rt_interrupt_leave /* ; 通知RT-Thread要离开中断模式 */ - /* 如果设置了rt_thread_switch_interrupt_flag,进行中断中的线程上下文处理 */ - ldr r0, =rt_thread_switch_interrupt_flag - ldr r1, [r0] - cmp r1, #1 - beq rt_hw_context_switch_interrupt_do /* 中断中切换发生 */ - /* 如果跳转了,将不会回来 */ - ldmfd sp!, {r0-r12,lr} /* 恢复栈 */ - subs pc, lr, #4 /* 从IRQ中返回 */ + /* 如果设置了rt_thread_switch_interrupt_flag,进行中断中的线程上下文处理 */ + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq rt_hw_context_switch_interrupt_do /* 中断中切换发生 */ + /* 如果跳转了,将不会回来 */ + ldmfd sp!, {r0-r12,lr} /* 恢复栈 */ + subs pc, lr, #4 /* 从IRQ中返回 */ /* * void rt_hw_context_switch_interrupt_do(rt_base_t flag) * 中断结束后的上下文切换 */ rt_hw_context_switch_interrupt_do: - mov r1, #0 /* clear flag */ - /* 清楚中断中切换标志 */ - str r1, [r0] /* */ + mov r1, #0 /* clear flag */ + /* 清楚中断中切换标志 */ + str r1, [r0] /* */ - ldmfd sp!, {r0-r12,lr}/* reload saved registers */ - /* 先恢复被中断线程的上下文 */ - stmfd sp!, {r0-r3} /* save r0-r3 */ - /* 对R0 – R3压栈,因为后面会用到 */ - mov r1, sp /* 把此处的栈值保存到R1 */ - add sp, sp, #16 /* restore sp */ - /* 恢复IRQ的栈,后面会跳出IRQ模式 */ - sub r2, lr, #4 /* save old task's pc to r2 */ - /* 保存切换出线程的PC到R2 */ + ldmfd sp!, {r0-r12,lr}/* reload saved registers */ + /* 先恢复被中断线程的上下文 */ + stmfd sp!, {r0-r3} /* save r0-r3 */ + /* 对R0 – R3压栈,因为后面会用到 */ + mov r1, sp /* 把此处的栈值保存到R1 */ + add sp, sp, #16 /* restore sp */ + /* 恢复IRQ的栈,后面会跳出IRQ模式 */ + sub r2, lr, #4 /* save old task's pc to r2 */ + /* 保存切换出线程的PC到R2 */ - mrs r3, spsr /* disable interrupt 保存中断前的CPSR到R3寄存器 */ - /* 获得SPSR寄存器值 */ - orr r0, r3, #I_BIT|F_BIT - msr spsr_c, r0 /* 关闭SPSR中的IRQ/FIQ中断 */ + mrs r3, spsr /* disable interrupt 保存中断前的CPSR到R3寄存器 */ + /* 获得SPSR寄存器值 */ + orr r0, r3, #I_BIT|F_BIT + msr spsr_c, r0 /* 关闭SPSR中的IRQ/FIQ中断 */ - ldr r0, =.+8 /* 把当前地址+8载入到R0寄存器中 switch to interrupted task's stack */ - movs pc, r0 /* 退出IRQ模式,由于SPSR被设置成关中断模式 */ - /* 所以从IRQ返回后,中断并没有打开 - ; R0寄存器中的位置实际就是下一条指令, - ; 即PC继续往下走 - ; 此时 - ; 模式已经换成中断前的SVC模式, - ; SP寄存器也是SVC模式下的栈寄存器 - ; R1保存IRQ模式下的栈指针 - ; R2保存切换出线程的PC - ; R3保存切换出线程的CPSR */ - stmfd sp!, {r2} /* push old task's pc */ - /* 保存切换出任务的PC */ - stmfd sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */ - /* 保存R4 – R12,LR寄存器 */ - mov r4, r1 /* Special optimised code below */ - /* R1保存有压栈R0 – R3处的栈位置 */ - mov r5, r3 /* R3切换出线程的CPSR */ - ldmfd r4!, {r0-r3} /* 恢复R0 – R3 */ - stmfd sp!, {r0-r3} /* push old task's r3-r0 */ - /* R0 – R3压栈到切换出线程 */ - stmfd sp!, {r5} /* push old task's psr */ - /* 切换出线程CPSR压栈 */ - mrs r4, spsr - stmfd sp!, {r4} /* push old task's spsr */ - /* 切换出线程SPSR压栈 */ + ldr r0, =.+8 /* 把当前地址+8载入到R0寄存器中 switch to interrupted task's stack */ + movs pc, r0 /* 退出IRQ模式,由于SPSR被设置成关中断模式 */ + /* 所以从IRQ返回后,中断并没有打开 + ; R0寄存器中的位置实际就是下一条指令, + ; 即PC继续往下走 + ; 此时 + ; 模式已经换成中断前的SVC模式, + ; SP寄存器也是SVC模式下的栈寄存器 + ; R1保存IRQ模式下的栈指针 + ; R2保存切换出线程的PC + ; R3保存切换出线程的CPSR */ + stmfd sp!, {r2} /* push old task's pc */ + /* 保存切换出任务的PC */ + stmfd sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */ + /* 保存R4 – R12,LR寄存器 */ + mov r4, r1 /* Special optimised code below */ + /* R1保存有压栈R0 – R3处的栈位置 */ + mov r5, r3 /* R3切换出线程的CPSR */ + ldmfd r4!, {r0-r3} /* 恢复R0 – R3 */ + stmfd sp!, {r0-r3} /* push old task's r3-r0 */ + /* R0 – R3压栈到切换出线程 */ + stmfd sp!, {r5} /* push old task's psr */ + /* 切换出线程CPSR压栈 */ + mrs r4, spsr + stmfd sp!, {r4} /* push old task's spsr */ + /* 切换出线程SPSR压栈 */ - ldr r4, =rt_interrupt_from_thread - ldr r5, [r4] - str sp, [r5] /* store sp in preempted tasks's TCB */ - /* 保存切换出线程的SP指针 */ + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] /* store sp in preempted tasks's TCB */ + /* 保存切换出线程的SP指针 */ - ldr r6, =rt_interrupt_to_thread - ldr r6, [r6] - ldr sp, [r6] /* get new task's stack pointer */ - /* 获得切换到线程的栈 */ + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] /* get new task's stack pointer */ + /* 获得切换到线程的栈 */ - ldmfd sp!, {r4} /* pop new task's spsr */ - /* 恢复SPSR */ - msr SPSR_cxsf, r4 - ldmfd sp!, {r4} /* pop new task's psr */ - /* 恢复CPSR */ - msr CPSR_cxsf, r4 + ldmfd sp!, {r4} /* pop new task's spsr */ + /* 恢复SPSR */ + msr SPSR_cxsf, r4 + ldmfd sp!, {r4} /* pop new task's psr */ + /* 恢复CPSR */ + msr CPSR_cxsf, r4 - ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ - /* 恢复R0 – R12,LR及PC寄存器 */ + ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ + /* 恢复R0 – R12,LR及PC寄存器 */ /* 代码加密功能 */ #if defined(CODE_PROTECTION) diff --git a/libcpu/arm/lpc24xx/context_gcc.S b/libcpu/arm/lpc24xx/context_gcc.S index b2c3abeee4..b824a91bbf 100644 --- a/libcpu/arm/lpc24xx/context_gcc.S +++ b/libcpu/arm/lpc24xx/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -13,25 +13,25 @@ */ /*@{*/ -#define NOINT 0xc0 +#define NOINT 0xc0 /* * rt_base_t rt_hw_interrupt_disable(); */ .globl rt_hw_interrupt_disable rt_hw_interrupt_disable: - mrs r0, cpsr - orr r1, r0, #NOINT - msr cpsr_c, r1 - mov pc, lr + mrs r0, cpsr + orr r1, r0, #NOINT + msr cpsr_c, r1 + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level); */ .globl rt_hw_interrupt_enable rt_hw_interrupt_enable: - msr cpsr, r0 - mov pc, lr + msr cpsr, r0 + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); @@ -40,23 +40,23 @@ rt_hw_interrupt_enable: */ .globl rt_hw_context_switch rt_hw_context_switch: - stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) - stmfd sp!, {r0-r12, lr} @ push lr & register file + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file - mrs r4, cpsr - stmfd sp!, {r4} @ push cpsr - mrs r4, spsr - stmfd sp!, {r4} @ push spsr + mrs r4, cpsr + stmfd sp!, {r4} @ push cpsr + mrs r4, spsr + stmfd sp!, {r4} @ push spsr - str sp, [r0] @ store sp in preempted tasks TCB - ldr sp, [r1] @ get new task stack pointer + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_to(rt_uint32 to); @@ -64,14 +64,14 @@ rt_hw_context_switch: */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldr sp, [r0] @ get new task stack pointer + ldr sp, [r0] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); @@ -81,15 +81,15 @@ rt_hw_context_switch_to: .globl rt_interrupt_to_thread .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldr r2, =rt_thread_switch_interrupt_flag - ldr r3, [r2] - cmp r3, #1 - beq _reswitch - mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 - str r3, [r2] - ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread - str r0, [r2] + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r3, [r2] + ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + str r0, [r2] _reswitch: - ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread - str r1, [r2] - mov pc, lr + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + mov pc, lr diff --git a/libcpu/arm/lpc24xx/context_rvds.S b/libcpu/arm/lpc24xx/context_rvds.S index 0d9915f4f1..9666127664 100644 --- a/libcpu/arm/lpc24xx/context_rvds.S +++ b/libcpu/arm/lpc24xx/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -9,99 +9,99 @@ ; * 2011-07-22 Bernard added thumb mode porting ; */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - TST lr, #0x01 - BEQ _ARM_MODE - ORR r4, r4, #0x20 ; it's thumb code + MRS r4, cpsr + TST lr, #0x01 + BEQ _ARM_MODE + ORR r4, r4, #0x20 ; it's thumb code _ARM_MODE - STMFD sp!, {r4} ; push cpsr + STMFD sp!, {r4} ; push cpsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task cpsr to spsr - MSR spsr_cxsf, r4 - BIC r4, r4, #0x20 ; must be ARM mode - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr to spsr + MSR spsr_cxsf, r4 + BIC r4, r4, #0x20 ; must be ARM mode + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr - ENDP + LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task cpsr to spsr - MSR spsr_cxsf, r4 - BIC r4, r4, #0x20 ; must be ARM mode - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr to spsr + MSR spsr_cxsf, r4 + BIC r4, r4, #0x20 ; must be ARM mode + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr - ENDP + LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc, copy spsr to cpsr + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP - END \ No newline at end of file + END diff --git a/libcpu/arm/lpc24xx/start_gcc.S b/libcpu/arm/lpc24xx/start_gcc.S index be1741da57..8e63ffa76c 100644 --- a/libcpu/arm/lpc24xx/start_gcc.S +++ b/libcpu/arm/lpc24xx/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -18,8 +18,8 @@ #define PLLFEED (0xE01FC000 + 0x08C) #define PLLSTAT (0xE01FC000 + 0x088) #define CCLKCFG (0xE01FC000 + 0x104) -#define MEMMAP (0xE01FC000 + 0x040) -#define SCS (0xE01FC000 + 0x1A0) +#define MEMMAP (0xE01FC000 + 0x040) +#define SCS (0xE01FC000 + 0x1A0) #define CLKSRCSEL (0xE01FC000 + 0x10C) #define MAMCR (0xE01FC000 + 0x000) #define MAMTIM (0xE01FC000 + 0x004) @@ -77,7 +77,7 @@ _vector_fiq: .word vector_fiq .globl _rtthread_start _rtthread_start: .word _start - + .globl _rtthread_end _rtthread_end: .word _end @@ -86,9 +86,9 @@ _rtthread_end: * rtthread bss start and end which are defined in linker script */ .globl _bss_start -_bss_start: +_bss_start: .word __bss_start - + .globl _bss_end _bss_end: .word __bss_end @@ -100,25 +100,25 @@ _bss_end: reset: /* enter svc mode */ msr cpsr_c, #SVCMODE|NOINT - + /*watch dog disable */ ldr r0,=WDMOD - ldr r1,=0x0 + ldr r1,=0x0 str r1,[r0] - + /* all interrupt disable */ ldr r0,=VICIntEnClr ldr r1,=0xffffffff str r1,[r0] - + ldr r1, =VICVectAddr ldr r0, =0x00 str r0, [r1] - + ldr r1, =VICIntSelect ldr r0, =0x00 - str r0, [r1] - + str r0, [r1] + /* setup stack */ bl stack_setup @@ -140,7 +140,7 @@ data_loop: mov r0,#0 /* get a zero */ ldr r1,=__bss_start /* bss start */ ldr r2,=__bss_end /* bss end */ - + bss_loop: cmp r1,r2 /* check if data to clear */ strlo r0,[r1],#4 /* clear 4 bytes */ @@ -158,13 +158,13 @@ ctor_loop: mov lr, pc bx r2 ldmfd sp!, {r0-r1} - b ctor_loop + b ctor_loop ctor_end: /* start RT-Thread Kernel */ ldr pc, _rtthread_startup -_rtthread_startup: +_rtthread_startup: .word rtthread_startup .equ USERMODE, 0x10 @@ -188,7 +188,7 @@ vector_resv: bl rt_hw_trap_resv .globl rt_thread_switch_interrupt_flag .globl rt_interrupt_from_thread .globl rt_interrupt_to_thread -vector_irq: +vector_irq: stmfd sp!, {r0-r12,lr} bl rt_interrupt_enter bl rt_hw_trap_irq diff --git a/libcpu/arm/lpc24xx/start_rvds.S b/libcpu/arm/lpc24xx/start_rvds.S index 36f59cf9f6..6357cfce80 100644 --- a/libcpu/arm/lpc24xx/start_rvds.S +++ b/libcpu/arm/lpc24xx/start_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -20,22 +20,22 @@ ;/*****************************************************************************/ ;/* -; * The LPC2400.S code is executed after CPU Reset. This file may be -; * translated with the following SET symbols. In uVision these SET +; * The LPC2400.S code is executed after CPU Reset. This file may be +; * translated with the following SET symbols. In uVision these SET ; * symbols are entered under Options - ASM - Define. ; * -; * NO_CLOCK_SETUP: when set the startup code will not initialize Clock -; * (used mostly when clock is already initialized from script .ini +; * NO_CLOCK_SETUP: when set the startup code will not initialize Clock +; * (used mostly when clock is already initialized from script .ini ; * file). ; * -; * NO_EMC_SETUP: when set the startup code will not initialize +; * NO_EMC_SETUP: when set the startup code will not initialize ; * External Bus Controller. ; * -; * RAM_INTVEC: when set the startup code copies exception vectors +; * RAM_INTVEC: when set the startup code copies exception vectors ; * from on-chip Flash to on-chip RAM. ; * -; * REMAP: when set the startup code initializes the register MEMMAP -; * which overwrites the settings of the CPU configuration pins. The +; * REMAP: when set the startup code initializes the register MEMMAP +; * which overwrites the settings of the CPU configuration pins. The ; * startup and interrupt vectors are remapped from: ; * 0x00000000 default setting (not remapped) ; * 0x40000000 when RAM_MODE is used @@ -45,7 +45,7 @@ ; * from external memory starting at address 0x80000000. ; * ; * RAM_MODE: when set the device is configured for code execution -; * from on-chip RAM starting at address 0x40000000. +; * from on-chip RAM starting at address 0x40000000. ; */ @@ -64,7 +64,7 @@ F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled ;----------------------- Memory Definitions ------------------------------------ ; Internal Memory Base Addresses -FLASH_BASE EQU 0x00000000 +FLASH_BASE EQU 0x00000000 RAM_BASE EQU 0x40000000 EXTMEM_BASE EQU 0x80000000 @@ -73,10 +73,10 @@ STA_MEM0_BASE EQU 0x80000000 STA_MEM1_BASE EQU 0x81000000 STA_MEM2_BASE EQU 0x82000000 STA_MEM3_BASE EQU 0x83000000 -DYN_MEM0_BASE EQU 0xA0000000 -DYN_MEM1_BASE EQU 0xB0000000 -DYN_MEM2_BASE EQU 0xC0000000 -DYN_MEM3_BASE EQU 0xD0000000 +DYN_MEM0_BASE EQU 0xA0000000 +DYN_MEM1_BASE EQU 0xB0000000 +DYN_MEM2_BASE EQU 0xC0000000 +DYN_MEM3_BASE EQU 0xD0000000 ;----------------------- Stack and Heap Definitions ---------------------------- @@ -516,7 +516,7 @@ EMC_DYN_RD_CFG_Val EQU 0x00000001 ;// Dynamic Memory Self-refresh Exit Time Register (EMCDynamictSREX) ;// tSREX: Self-refresh exit time <1-16> <#-1> ;// The delay is in CCLK cycles -;// This value is normally found in SDRAM data sheets as tSREX, +;// This value is normally found in SDRAM data sheets as tSREX, ;// for devices without this parameter you use the same value as tXSR ;// ;// Dynamic Memory Last Data Out to Active Time Register (EMCDynamictAPR) @@ -799,7 +799,7 @@ EMC_STA_WWEN0_Val EQU 0x00000002 ;// The delay is in CCLK cycles ;// EMC_STA_WOEN0_Val EQU 0x00000002 - + ;// Static Memory Read Delay Register (EMCStaticWaitRd0) ;// Selects the delay from CS0 to a read access ;// WAITRD: Non-page mode read wait states or asynchronous page mode read first access wait states <1-32> <#-1> @@ -866,7 +866,7 @@ EMC_STA_WWEN1_Val EQU 0x00000000 ;// The delay is in CCLK cycles ;// EMC_STA_WOEN1_Val EQU 0x00000000 - + ;// Static Memory Read Delay Register (EMCStaticWaitRd1) ;// Selects the delay from CS1 to a read access ;// WAITRD: Non-page mode read wait states or asynchronous page mode read first access wait states <1-32> <#-1> @@ -933,7 +933,7 @@ EMC_STA_WWEN2_Val EQU 0x00000000 ;// The delay is in CCLK cycles ;// EMC_STA_WOEN2_Val EQU 0x00000000 - + ;// Static Memory Read Delay Register (EMCStaticWaitRd2) ;// Selects the delay from CS2 to a read access ;// WAITRD: Non-page mode read wait states or asynchronous page mode read first access wait states <1-32> <#-1> @@ -1000,7 +1000,7 @@ EMC_STA_WWEN3_Val EQU 0x00000000 ;// The delay is in CCLK cycles ;// EMC_STA_WOEN3_Val EQU 0x00000000 - + ;// Static Memory Read Delay Register (EMCStaticWaitRd3) ;// Selects the delay from CS3 to a read access ;// WAITRD: Non-page mode read wait states or asynchronous page mode read first access wait states <1-32> <#-1> @@ -1057,12 +1057,12 @@ EMC_STA_EXT_W_Val EQU 0x00000000 ; Absolute addressing mode must be used. ; Dummy Handlers are implemented as infinite loops which can be modified. -Vectors LDR PC, Reset_Addr +Vectors LDR PC, Reset_Addr LDR PC, Undef_Addr LDR PC, SWI_Addr LDR PC, PAbt_Addr LDR PC, DAbt_Addr - NOP ; Reserved Vector + NOP ; Reserved Vector LDR PC, IRQ_Addr LDR PC, FIQ_Addr @@ -1071,7 +1071,7 @@ Undef_Addr DCD Undef_Handler SWI_Addr DCD SWI_Handler PAbt_Addr DCD PAbt_Handler DAbt_Addr DCD DAbt_Handler - DCD 0 ; Reserved Address + DCD 0 ; Reserved Address IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler @@ -1085,32 +1085,32 @@ FIQ_Addr DCD FIQ_Handler ; Prepare Fatal Context MACRO - prepare_fatal - STMFD sp!, {r0-r3} - MOV r1, sp - ADD sp, sp, #16 - SUB r2, lr, #4 - MRS r3, spsr + prepare_fatal + STMFD sp!, {r0-r3} + MOV r1, sp + ADD sp, sp, #16 + SUB r2, lr, #4 + MRS r3, spsr - ; switch to SVC mode and no interrupt - MSR cpsr_c, #I_Bit :OR: F_Bit :OR: Mode_SVC + ; switch to SVC mode and no interrupt + MSR cpsr_c, #I_Bit :OR: F_Bit :OR: Mode_SVC - STMFD sp!, {r0} ; old r0 - ; get sp - ADD r0, sp, #4 - STMFD sp!, {r3} ; cpsr - STMFD sp!, {r2} ; pc - STMFD sp!, {lr} ; lr - STMFD sp!, {r0} ; sp - STMFD sp!, {r4-r12} + STMFD sp!, {r0} ; old r0 + ; get sp + ADD r0, sp, #4 + STMFD sp!, {r3} ; cpsr + STMFD sp!, {r2} ; pc + STMFD sp!, {lr} ; lr + STMFD sp!, {r0} ; sp + STMFD sp!, {r4-r12} - MOV r4, r1 + MOV r4, r1 - LDMFD r4!, {r0-r3} - STMFD sp!, {r0-r3} + LDMFD r4!, {r0-r3} + STMFD sp!, {r0-r3} - MOV r0, sp - MEND + MOV r0, sp + MEND Undef_Handler prepare_fatal @@ -1123,7 +1123,7 @@ SWI_Handler B . PAbt_Handler - prepare_fatal + prepare_fatal BL rt_hw_trap_pabt B . @@ -1140,7 +1140,7 @@ FIQ_Handler ; Reset Handler EXPORT Reset_Handler -Reset_Handler +Reset_Handler ; Clock Setup ------------------------------------------------------------------ @@ -1152,18 +1152,18 @@ Reset_Handler ; Configure and Enable PLL LDR R3, =SCS_Val ; Enable main oscillator - STR R3, [R0, #SCS_OFS] + STR R3, [R0, #SCS_OFS] - IF (SCS_Val:AND:OSCEN) != 0 + IF (SCS_Val:AND:OSCEN) != 0 OSC_Loop LDR R3, [R0, #SCS_OFS] ; Wait for main osc stabilize ANDS R3, R3, #OSCSTAT BEQ OSC_Loop ENDIF LDR R3, =CLKSRCSEL_Val ; Select PLL source clock - STR R3, [R0, #CLKSRCSEL_OFS] + STR R3, [R0, #CLKSRCSEL_OFS] LDR R3, =PLLCFG_Val - STR R3, [R0, #PLLCFG_OFS] + STR R3, [R0, #PLLCFG_OFS] STR R1, [R0, #PLLFEED_OFS] STR R2, [R0, #PLLFEED_OFS] MOV R3, #PLLCON_PLLE @@ -1217,9 +1217,9 @@ M_N_Lock LDR R3, [R0, #PLLSTAT_OFS] IF MAM_SETUP != 0 LDR R0, =MAM_BASE MOV R1, #MAMTIM_Val - STR R1, [R0, #MAMTIM_OFS] + STR R1, [R0, #MAMTIM_OFS] MOV R1, #MAMCR_Val - STR R1, [R0, #MAMCR_OFS] + STR R1, [R0, #MAMCR_OFS] ENDIF ; MAM_SETUP @@ -1325,7 +1325,7 @@ Wait_1 SUBS R6, R6, #1 ; Delay ~200 ms proc clk 57.6 LDR R4, =(PALL_CMD:OR:0x03) ; Write Precharge All Command STR R4, [R0, #EMC_DYN_CTRL_OFS] - + MOV R4, #2 STR R4, [R0, #EMC_DYN_RFSH_OFS] @@ -1338,7 +1338,7 @@ Wait_2 SUBS R6, R6, #1 ; Delay LDR R4, =(MODE_CMD:OR:0x03) ; Write MODE Command STR R4, [R0, #EMC_DYN_CTRL_OFS] - + ; Dummy read IF (EMC_DYNCS0_SETUP != 0) LDR R4, =DYN_MEM0_BASE @@ -1476,7 +1476,7 @@ Wait_5 SUBS R6, R6, #1 ; Delay ~10 ms @ proc clk 57.6 ADD R5, R5, R0 STR R4, [R5, #0] - ENDIF ; EMC_STATIC_SETUP + ENDIF ; EMC_STATIC_SETUP ENDIF ; EMC_SETUP @@ -1486,9 +1486,9 @@ Wait_5 SUBS R6, R6, #1 ; Delay ~10 ms @ proc clk 57.6 IF :DEF:RAM_INTVEC ADR R8, Vectors ; Source LDR R9, =RAM_BASE ; Destination - LDMIA R8!, {R0-R7} ; Load Vectors - STMIA R9!, {R0-R7} ; Store Vectors - LDMIA R8!, {R0-R7} ; Load Handler Addresses + LDMIA R8!, {R0-R7} ; Load Vectors + STMIA R9!, {R0-R7} ; Store Vectors + LDMIA R8!, {R0-R7} ; Load Handler Addresses STMIA R9!, {R0-R7} ; Store Handler Addresses ENDIF @@ -1610,8 +1610,8 @@ rt_hw_context_switch_interrupt_do PROC LDR sp, [r6] ; get new task's stack pointer LDMFD sp!, {r4} ; pop new task's cpsr to spsr - MSR spsr_cxsf, r4 - BIC r4, r4, #0x20 ; must be ARM mode + MSR spsr_cxsf, r4 + BIC r4, r4, #0x20 ; must be ARM mode MSR cpsr_cxsf, r4 LDMFD sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr diff --git a/libcpu/arm/realview-a8-vmm/start_gcc.S b/libcpu/arm/realview-a8-vmm/start_gcc.S index 879cf992a8..2643960320 100644 --- a/libcpu/arm/realview-a8-vmm/start_gcc.S +++ b/libcpu/arm/realview-a8-vmm/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -245,16 +245,16 @@ switch_to_guest: ldr r0, [r1] mcr p15, 0, r0, c3, c0 #endif - /* check whether there is a pending interrupt for Guest OS */ - bl vmm_virq_check + /* check whether there is a pending interrupt for Guest OS */ + bl vmm_virq_check #ifdef RT_VMM_USING_DOMAIN @ All done, restore the guest domain. mcr p15, 0, r5, c3, c0 #endif - cmp r0, #0x0 - beq route_irq_to_guest + cmp r0, #0x0 + beq route_irq_to_guest ldmfd sp!, {r0-r12,lr} subs pc, lr, #4 @@ -318,35 +318,35 @@ rt_hw_context_switch_interrupt_do: .endm .align 5 - .globl vector_swi + .globl vector_swi vector_swi: push_svc_reg bl rt_hw_trap_swi b . .align 5 - .globl vector_undef + .globl vector_undef vector_undef: push_svc_reg bl rt_hw_trap_undef b . .align 5 - .globl vector_pabt + .globl vector_pabt vector_pabt: push_svc_reg bl rt_hw_trap_pabt b . .align 5 - .globl vector_dabt + .globl vector_dabt vector_dabt: push_svc_reg bl rt_hw_trap_dabt b . .align 5 - .globl vector_resv + .globl vector_resv vector_resv: push_svc_reg bl rt_hw_trap_resv diff --git a/libcpu/arm/realview-a8-vmm/vector_gcc.S b/libcpu/arm/realview-a8-vmm/vector_gcc.S index 46d27a3fc5..46fdf291d8 100644 --- a/libcpu/arm/realview-a8-vmm/vector_gcc.S +++ b/libcpu/arm/realview-a8-vmm/vector_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -49,4 +49,4 @@ _vector_irq: _vector_fiq: .word vector_fiq -.balignl 16,0xdeadbeef +.balignl 16,0xdeadbeef diff --git a/libcpu/arm/s3c24x0/context_gcc.S b/libcpu/arm/s3c24x0/context_gcc.S index 23362a9013..c737abe6d7 100644 --- a/libcpu/arm/s3c24x0/context_gcc.S +++ b/libcpu/arm/s3c24x0/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -13,25 +13,25 @@ */ /*@{*/ -#define NOINT 0xc0 +#define NOINT 0xc0 /* * rt_base_t rt_hw_interrupt_disable(); */ .globl rt_hw_interrupt_disable rt_hw_interrupt_disable: - mrs r0, cpsr - orr r1, r0, #NOINT - msr cpsr_c, r1 - mov pc, lr + mrs r0, cpsr + orr r1, r0, #NOINT + msr cpsr_c, r1 + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level); */ .globl rt_hw_interrupt_enable rt_hw_interrupt_enable: - msr cpsr, r0 - mov pc, lr + msr cpsr, r0 + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); @@ -40,23 +40,23 @@ rt_hw_interrupt_enable: */ .globl rt_hw_context_switch rt_hw_context_switch: - stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) - stmfd sp!, {r0-r12, lr} @ push lr & register file + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file - mrs r4, cpsr - stmfd sp!, {r4} @ push cpsr - mrs r4, spsr - stmfd sp!, {r4} @ push spsr + mrs r4, cpsr + stmfd sp!, {r4} @ push cpsr + mrs r4, spsr + stmfd sp!, {r4} @ push spsr - str sp, [r0] @ store sp in preempted tasks TCB - ldr sp, [r1] @ get new task stack pointer + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr spsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_to(rt_uint32 to); @@ -64,14 +64,14 @@ rt_hw_context_switch: */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldr sp, [r0] @ get new task stack pointer + ldr sp, [r0] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); @@ -81,15 +81,15 @@ rt_hw_context_switch_to: .globl rt_interrupt_to_thread .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldr r2, =rt_thread_switch_interrupt_flag - ldr r3, [r2] - cmp r3, #1 - beq _reswitch - mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 - str r3, [r2] - ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread - str r0, [r2] + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r3, [r2] + ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + str r0, [r2] _reswitch: - ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread - str r1, [r2] - mov pc, lr + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + mov pc, lr diff --git a/libcpu/arm/s3c24x0/context_rvds.S b/libcpu/arm/s3c24x0/context_rvds.S index 9078f6173a..f34f912c7d 100644 --- a/libcpu/arm/s3c24x0/context_rvds.S +++ b/libcpu/arm/s3c24x0/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -8,96 +8,96 @@ ; * 2009-01-20 Bernard first version ; */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr + MRS r4, cpsr + STMFD sp!, {r4} ; push cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push spsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR spsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc}^ ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP - END \ No newline at end of file + END diff --git a/libcpu/arm/s3c24x0/start_gcc.S b/libcpu/arm/s3c24x0/start_gcc.S index cc2b2f6310..c6c7fa4604 100644 --- a/libcpu/arm/s3c24x0/start_gcc.S +++ b/libcpu/arm/s3c24x0/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,66 +10,66 @@ * 2008-01-29 Yi.Qiu for QEMU emulator */ -#define CONFIG_STACKSIZE 512 -#define S_FRAME_SIZE 72 +#define CONFIG_STACKSIZE 512 +#define S_FRAME_SIZE 72 -#define S_OLD_R0 68 -#define S_PSR 64 -#define S_PC 60 -#define S_LR 56 -#define S_SP 52 +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 -#define S_IP 48 -#define S_FP 44 -#define S_R10 40 -#define S_R9 36 -#define S_R8 32 -#define S_R7 28 -#define S_R6 24 -#define S_R5 20 -#define S_R4 16 -#define S_R3 12 -#define S_R2 8 -#define S_R1 4 -#define S_R0 0 +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 -.equ USERMODE, 0x10 -.equ FIQMODE, 0x11 -.equ IRQMODE, 0x12 -.equ SVCMODE, 0x13 -.equ ABORTMODE, 0x17 -.equ UNDEFMODE, 0x1b -.equ MODEMASK, 0x1f -.equ NOINT, 0xc0 +.equ USERMODE, 0x10 +.equ FIQMODE, 0x11 +.equ IRQMODE, 0x12 +.equ SVCMODE, 0x13 +.equ ABORTMODE, 0x17 +.equ UNDEFMODE, 0x1b +.equ MODEMASK, 0x1f +.equ NOINT, 0xc0 -.equ RAM_BASE, 0x00000000 /*Start address of RAM */ -.equ ROM_BASE, 0x30000000 /*Start address of Flash */ +.equ RAM_BASE, 0x00000000 /*Start address of RAM */ +.equ ROM_BASE, 0x30000000 /*Start address of Flash */ -.equ MPLLCON, 0x4c000004 /*Mpll control register */ -.equ M_MDIV, 0x20 -.equ M_PDIV, 0x4 -.equ M_SDIV, 0x2 +.equ MPLLCON, 0x4c000004 /*Mpll control register */ +.equ M_MDIV, 0x20 +.equ M_PDIV, 0x4 +.equ M_SDIV, 0x2 -.equ INTMSK, 0x4a000008 -.equ INTSUBMSK, 0x4a00001c -.equ WTCON, 0x53000000 -.equ LOCKTIME, 0x4c000000 -.equ CLKDIVN, 0x4c000014 /*Clock divider control */ -.equ GPHCON, 0x56000070 /*Port H control */ -.equ GPHUP, 0x56000078 /*Pull-up control H */ -.equ BWSCON, 0x48000000 /*Bus width & wait status */ -.equ BANKCON0, 0x48000004 /*Boot ROM control */ -.equ BANKCON1, 0x48000008 /*BANK1 control */ -.equ BANKCON2, 0x4800000c /*BANK2 cControl */ -.equ BANKCON3, 0x48000010 /*BANK3 control */ -.equ BANKCON4, 0x48000014 /*BANK4 control */ -.equ BANKCON5, 0x48000018 /*BANK5 control */ -.equ BANKCON6, 0x4800001c /*BANK6 control */ -.equ BANKCON7, 0x48000020 /*BANK7 control */ -.equ REFRESH, 0x48000024 /*DRAM/SDRAM efresh */ -.equ BANKSIZE, 0x48000028 /*Flexible Bank Size */ -.equ MRSRB6, 0x4800002c /*Mode egister set for SDRAM*/ -.equ MRSRB7, 0x48000030 /*Mode egister set for SDRAM*/ +.equ INTMSK, 0x4a000008 +.equ INTSUBMSK, 0x4a00001c +.equ WTCON, 0x53000000 +.equ LOCKTIME, 0x4c000000 +.equ CLKDIVN, 0x4c000014 /*Clock divider control */ +.equ GPHCON, 0x56000070 /*Port H control */ +.equ GPHUP, 0x56000078 /*Pull-up control H */ +.equ BWSCON, 0x48000000 /*Bus width & wait status */ +.equ BANKCON0, 0x48000004 /*Boot ROM control */ +.equ BANKCON1, 0x48000008 /*BANK1 control */ +.equ BANKCON2, 0x4800000c /*BANK2 cControl */ +.equ BANKCON3, 0x48000010 /*BANK3 control */ +.equ BANKCON4, 0x48000014 /*BANK4 control */ +.equ BANKCON5, 0x48000018 /*BANK5 control */ +.equ BANKCON6, 0x4800001c /*BANK6 control */ +.equ BANKCON7, 0x48000020 /*BANK7 control */ +.equ REFRESH, 0x48000024 /*DRAM/SDRAM efresh */ +.equ BANKSIZE, 0x48000028 /*Flexible Bank Size */ +.equ MRSRB6, 0x4800002c /*Mode egister set for SDRAM*/ +.equ MRSRB7, 0x48000030 /*Mode egister set for SDRAM*/ /* ************************************************************************* @@ -84,24 +84,24 @@ .globl _start _start: - b reset - ldr pc, _vector_undef - ldr pc, _vector_swi - ldr pc, _vector_pabt - ldr pc, _vector_dabt - ldr pc, _vector_resv - ldr pc, _vector_irq - ldr pc, _vector_fiq + b reset + ldr pc, _vector_undef + ldr pc, _vector_swi + ldr pc, _vector_pabt + ldr pc, _vector_dabt + ldr pc, _vector_resv + ldr pc, _vector_irq + ldr pc, _vector_fiq -_vector_undef: .word vector_undef -_vector_swi: .word vector_swi -_vector_pabt: .word vector_pabt -_vector_dabt: .word vector_dabt -_vector_resv: .word vector_resv -_vector_irq: .word vector_irq -_vector_fiq: .word vector_fiq +_vector_undef: .word vector_undef +_vector_swi: .word vector_swi +_vector_pabt: .word vector_pabt +_vector_dabt: .word vector_dabt +_vector_resv: .word vector_resv +_vector_irq: .word vector_irq +_vector_fiq: .word vector_fiq -.balignl 16,0xdeadbeef +.balignl 16,0xdeadbeef /* ************************************************************************* @@ -115,7 +115,7 @@ _vector_fiq: .word vector_fiq */ _TEXT_BASE: - .word TEXT_BASE + .word TEXT_BASE /* * rtthread kernel start and end @@ -123,117 +123,117 @@ _TEXT_BASE: */ .globl _rtthread_start _rtthread_start: - .word _start - + .word _start + .globl _rtthread_end _rtthread_end: - .word _end + .word _end /* * rtthread bss start and end which are defined in linker script */ .globl _bss_start -_bss_start: - .word __bss_start - +_bss_start: + .word __bss_start + .globl _bss_end _bss_end: - .word __bss_end + .word __bss_end -/* IRQ stack memory (calculated at run-time) */ +/* IRQ stack memory (calculated at run-time) */ .globl IRQ_STACK_START IRQ_STACK_START: - .word _irq_stack_start + 1024 - + .word _irq_stack_start + 1024 + .globl FIQ_STACK_START FIQ_STACK_START: - .word _fiq_stack_start + 1024 - + .word _fiq_stack_start + 1024 + .globl UNDEFINED_STACK_START UNDEFINED_STACK_START: - .word _undefined_stack_start + CONFIG_STACKSIZE - + .word _undefined_stack_start + CONFIG_STACKSIZE + .globl ABORT_STACK_START ABORT_STACK_START: - .word _abort_stack_start + CONFIG_STACKSIZE - + .word _abort_stack_start + CONFIG_STACKSIZE + .globl _STACK_START _STACK_START: - .word _svc_stack_start + 4096 + .word _svc_stack_start + 4096 /* ----------------------------------entry------------------------------*/ reset: - - /* set the cpu to SVC32 mode */ - mrs r0,cpsr - bic r0,r0,#MODEMASK - orr r0,r0,#SVCMODE - msr cpsr,r0 - - /* watch dog disable */ - ldr r0,=WTCON - ldr r1,=0x0 - str r1,[r0] - /* mask all IRQs by clearing all bits in the INTMRs */ - ldr r1, =INTMSK - ldr r0, =0xffffffff - str r0, [r1] - ldr r1, =INTSUBMSK - ldr r0, =0x7fff /*all sub interrupt disable */ - str r0, [r1] + /* set the cpu to SVC32 mode */ + mrs r0,cpsr + bic r0,r0,#MODEMASK + orr r0,r0,#SVCMODE + msr cpsr,r0 - /* set interrupt vector */ - ldr r0, _load_address - mov r1, #0x0 /* target address */ - add r2, r0, #0x20 /* size, 32bytes */ + /* watch dog disable */ + ldr r0,=WTCON + ldr r1,=0x0 + str r1,[r0] + + /* mask all IRQs by clearing all bits in the INTMRs */ + ldr r1, =INTMSK + ldr r0, =0xffffffff + str r0, [r1] + ldr r1, =INTSUBMSK + ldr r0, =0x7fff /*all sub interrupt disable */ + str r0, [r1] + + /* set interrupt vector */ + ldr r0, _load_address + mov r1, #0x0 /* target address */ + add r2, r0, #0x20 /* size, 32bytes */ copy_loop: - ldmia r0!, {r3-r10} /* copy from source address [r0] */ - stmia r1!, {r3-r10} /* copy to target address [r1] */ - cmp r0, r2 /* until source end address [r2] */ - ble copy_loop + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + ble copy_loop - /* setup stack */ - bl stack_setup + /* setup stack */ + bl stack_setup + + /* clear .bss */ + mov r0,#0 /* get a zero */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ - /* clear .bss */ - mov r0,#0 /* get a zero */ - ldr r1,=__bss_start /* bss start */ - ldr r2,=__bss_end /* bss end */ - bss_loop: - cmp r1,r2 /* check if data to clear */ - strlo r0,[r1],#4 /* clear 4 bytes */ - blo bss_loop /* loop until done */ + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + + /* call C++ constructors of global objects */ + ldr r0, =__ctors_start__ + ldr r1, =__ctors_end__ - /* call C++ constructors of global objects */ - ldr r0, =__ctors_start__ - ldr r1, =__ctors_end__ - ctor_loop: - cmp r0, r1 - beq ctor_end - ldr r2, [r0], #4 - stmfd sp!, {r0-r1} - mov lr, pc - bx r2 - ldmfd sp!, {r0-r1} - b ctor_loop - + cmp r0, r1 + beq ctor_end + ldr r2, [r0], #4 + stmfd sp!, {r0-r1} + mov lr, pc + bx r2 + ldmfd sp!, {r0-r1} + b ctor_loop + ctor_end: - /* start RT-Thread Kernel */ - ldr pc, _rtthread_startup + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup -_rtthread_startup: - .word rtthread_startup +_rtthread_startup: + .word rtthread_startup #if defined (__FLASH_BUILD__) -_load_address: - .word ROM_BASE + _TEXT_BASE +_load_address: + .word ROM_BASE + _TEXT_BASE #else -_load_address: - .word RAM_BASE + _TEXT_BASE +_load_address: + .word RAM_BASE + _TEXT_BASE #endif /* @@ -244,143 +244,143 @@ _load_address: ************************************************************************* */ -/* exception handlers */ - .align 5 +/* exception handlers */ + .align 5 vector_undef: - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} /* Calling r0-r12 */ - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ /* Calling SP, LR */ - str lr, [r8, #0] /* Save calling PC */ - mrs r6, spsr - str r6, [r8, #4] /* Save CPSR */ - str r0, [r8, #8] /* Save OLD_R0 */ - mov r0, sp + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} /* Calling r0-r12 */ + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ /* Calling SP, LR */ + str lr, [r8, #0] /* Save calling PC */ + mrs r6, spsr + str r6, [r8, #4] /* Save CPSR */ + str r0, [r8, #8] /* Save OLD_R0 */ + mov r0, sp - bl rt_hw_trap_udef + bl rt_hw_trap_udef - .align 5 + .align 5 vector_swi: - bl rt_hw_trap_swi + bl rt_hw_trap_swi - .align 5 + .align 5 vector_pabt: - bl rt_hw_trap_pabt + bl rt_hw_trap_pabt - .align 5 + .align 5 vector_dabt: - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} /* Calling r0-r12 */ - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ /* Calling SP, LR */ - str lr, [r8, #0] /* Save calling PC */ - mrs r6, spsr - str r6, [r8, #4] /* Save CPSR */ - str r0, [r8, #8] /* Save OLD_R0 */ - mov r0, sp + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} /* Calling r0-r12 */ + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ /* Calling SP, LR */ + str lr, [r8, #0] /* Save calling PC */ + mrs r6, spsr + str r6, [r8, #4] /* Save CPSR */ + str r0, [r8, #8] /* Save OLD_R0 */ + mov r0, sp - bl rt_hw_trap_dabt + bl rt_hw_trap_dabt - .align 5 + .align 5 vector_resv: - bl rt_hw_trap_resv + bl rt_hw_trap_resv -.globl rt_interrupt_enter -.globl rt_interrupt_leave -.globl rt_thread_switch_interrupt_flag -.globl rt_interrupt_from_thread -.globl rt_interrupt_to_thread +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread vector_irq: - stmfd sp!, {r0-r12,lr} - bl rt_interrupt_enter - bl rt_hw_trap_irq - bl rt_interrupt_leave + stmfd sp!, {r0-r12,lr} + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave - /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ - ldr r0, =rt_thread_switch_interrupt_flag - ldr r1, [r0] - cmp r1, #1 - beq _interrupt_thread_switch + /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq _interrupt_thread_switch - ldmfd sp!, {r0-r12,lr} - subs pc, lr, #4 + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 - .align 5 + .align 5 vector_fiq: - stmfd sp!,{r0-r7,lr} - bl rt_hw_trap_fiq - ldmfd sp!,{r0-r7,lr} - subs pc,lr,#4 + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc,lr,#4 _interrupt_thread_switch: - mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ - str r1, [r0] + mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ + str r1, [r0] - ldmfd sp!, {r0-r12,lr} /* reload saved registers */ - stmfd sp!, {r0-r3} /* save r0-r3 */ - mov r1, sp - add sp, sp, #16 /* restore sp */ - sub r2, lr, #4 /* save old task's pc to r2 */ - - mrs r3, spsr /* disable interrupt */ - orr r0, r3, #NOINT - msr spsr_c, r0 + ldmfd sp!, {r0-r12,lr} /* reload saved registers */ + stmfd sp!, {r0-r3} /* save r0-r3 */ + mov r1, sp + add sp, sp, #16 /* restore sp */ + sub r2, lr, #4 /* save old task's pc to r2 */ - ldr r0, =.+8 /* switch to interrupted task's stack*/ - movs pc, r0 + mrs r3, spsr /* disable interrupt */ + orr r0, r3, #NOINT + msr spsr_c, r0 - stmfd sp!, {r2} /* push old task's pc */ - stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */ - mov r4, r1 /* Special optimised code below */ - mov r5, r3 - ldmfd r4!, {r0-r3} - stmfd sp!, {r0-r3} /* push old task's r3-r0 */ - stmfd sp!, {r5} /* push old task's psr */ - mrs r4, spsr - stmfd sp!, {r4} /* push old task's spsr */ + ldr r0, =.+8 /* switch to interrupted task's stack*/ + movs pc, r0 - ldr r4, =rt_interrupt_from_thread - ldr r5, [r4] - str sp, [r5] /* store sp in preempted tasks's TCB*/ + stmfd sp!, {r2} /* push old task's pc */ + stmfd sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */ + mov r4, r1 /* Special optimised code below */ + mov r5, r3 + ldmfd r4!, {r0-r3} + stmfd sp!, {r0-r3} /* push old task's r3-r0 */ + stmfd sp!, {r5} /* push old task's psr */ + mrs r4, spsr + stmfd sp!, {r4} /* push old task's spsr */ - ldr r6, =rt_interrupt_to_thread - ldr r6, [r6] - ldr sp, [r6] /* get new task's stack pointer */ + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] /* store sp in preempted tasks's TCB*/ - ldmfd sp!, {r4} /* pop new task's spsr */ - msr SPSR_cxsf, r4 - ldmfd sp!, {r4} /* pop new task's psr */ - msr CPSR_cxsf, r4 + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] /* get new task's stack pointer */ - ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ + ldmfd sp!, {r4} /* pop new task's spsr */ + msr SPSR_cxsf, r4 + ldmfd sp!, {r4} /* pop new task's psr */ + msr CPSR_cxsf, r4 + + ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */ stack_setup: - mrs r0, cpsr - bic r0, r0, #MODEMASK - orr r1, r0, #UNDEFMODE|NOINT - msr cpsr_cxsf, r1 /* undef mode */ - ldr sp, UNDEFINED_STACK_START + mrs r0, cpsr + bic r0, r0, #MODEMASK + orr r1, r0, #UNDEFMODE|NOINT + msr cpsr_cxsf, r1 /* undef mode */ + ldr sp, UNDEFINED_STACK_START - orr r1,r0,#ABORTMODE|NOINT - msr cpsr_cxsf,r1 /* abort mode */ - ldr sp, ABORT_STACK_START + orr r1,r0,#ABORTMODE|NOINT + msr cpsr_cxsf,r1 /* abort mode */ + ldr sp, ABORT_STACK_START - orr r1,r0,#IRQMODE|NOINT - msr cpsr_cxsf,r1 /* IRQ mode */ - ldr sp, IRQ_STACK_START + orr r1,r0,#IRQMODE|NOINT + msr cpsr_cxsf,r1 /* IRQ mode */ + ldr sp, IRQ_STACK_START - orr r1,r0,#FIQMODE|NOINT - msr cpsr_cxsf,r1 /* FIQ mode */ - ldr sp, FIQ_STACK_START + orr r1,r0,#FIQMODE|NOINT + msr cpsr_cxsf,r1 /* FIQ mode */ + ldr sp, FIQ_STACK_START - bic r0,r0,#MODEMASK - orr r1,r0,#SVCMODE|NOINT - msr cpsr_cxsf,r1 /* SVC mode */ + bic r0,r0,#MODEMASK + orr r1,r0,#SVCMODE|NOINT + msr cpsr_cxsf,r1 /* SVC mode */ - ldr sp, _STACK_START + ldr sp, _STACK_START - /* USER mode is not initialized. */ - mov pc,lr /* The LR register may be not valid for the mode changes.*/ + /* USER mode is not initialized. */ + mov pc,lr /* The LR register may be not valid for the mode changes.*/ /*/*}*/ diff --git a/libcpu/arm/s3c24x0/start_rvds.S b/libcpu/arm/s3c24x0/start_rvds.S index dd5e9cc309..bd4478fdf0 100644 --- a/libcpu/arm/s3c24x0/start_rvds.S +++ b/libcpu/arm/s3c24x0/start_rvds.S @@ -843,14 +843,14 @@ GPJUP_Val EQU 0x00000000 ; Absolute addressing mode must be used. ; Dummy Handlers are implemented as infinite loops which can be modified. - EXPORT Entry_Point + EXPORT Entry_Point Entry_Point Vectors LDR PC, Reset_Addr LDR PC, Undef_Addr LDR PC, SWI_Addr LDR PC, PAbt_Addr LDR PC, DAbt_Addr - NOP + NOP LDR PC, IRQ_Addr LDR PC, FIQ_Addr @@ -880,17 +880,17 @@ FIQ_Handler B FIQ_Handler DAbt_Handler IMPORT rt_hw_trap_dabt - sub sp, sp, #72 - stmia sp, {r0 - r12} ;/* Calling r0-r12 */ - add r8, sp, #60 - stmdb r8, {sp, lr} ;/* Calling SP, LR */ - str lr, [r8, #0] ;/* Save calling PC */ - mrs r6, spsr - str r6, [r8, #4] ;/* Save CPSR */ - str r0, [r8, #8] ;/* Save OLD_R0 */ - mov r0, sp + sub sp, sp, #72 + stmia sp, {r0 - r12} ;/* Calling r0-r12 */ + add r8, sp, #60 + stmdb r8, {sp, lr} ;/* Calling SP, LR */ + str lr, [r8, #0] ;/* Save calling PC */ + mrs r6, spsr + str r6, [r8, #4] ;/* Save CPSR */ + str r0, [r8, #8] ;/* Save OLD_R0 */ + mov r0, sp - bl rt_hw_trap_dabt + bl rt_hw_trap_dabt ;########################################## @@ -1137,7 +1137,7 @@ rt_hw_context_switch_interrupt_do PROC MRS r3, spsr ; get cpsr of interrupt thread ; switch to SVC mode and no interrupt - MSR cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC + MSR cpsr_c, #I_Bit:OR:F_Bit:OR:Mode_SVC STMFD sp!, {r2} ; push old task's pc STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4 diff --git a/libcpu/arm/s3c44b0/context_gcc.S b/libcpu/arm/s3c44b0/context_gcc.S index 0898cdbf87..3fb5e772eb 100644 --- a/libcpu/arm/s3c44b0/context_gcc.S +++ b/libcpu/arm/s3c44b0/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -13,25 +13,25 @@ */ /*@{*/ -#define NOINT 0xc0 +#define NOINT 0xc0 /* * rt_base_t rt_hw_interrupt_disable(); */ .globl rt_hw_interrupt_disable rt_hw_interrupt_disable: - mrs r0, cpsr - orr r1, r0, #NOINT - msr cpsr_c, r1 - mov pc, lr + mrs r0, cpsr + orr r1, r0, #NOINT + msr cpsr_c, r1 + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level); */ .globl rt_hw_interrupt_enable rt_hw_interrupt_enable: - msr cpsr, r0 - mov pc, lr + msr cpsr, r0 + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); @@ -40,23 +40,23 @@ rt_hw_interrupt_enable: */ .globl rt_hw_context_switch rt_hw_context_switch: - stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) - stmfd sp!, {r0-r12, lr} @ push lr & register file + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file - mrs r4, cpsr - stmfd sp!, {r4} @ push cpsr - mrs r4, spsr - stmfd sp!, {r4} @ push spsr + mrs r4, cpsr + stmfd sp!, {r4} @ push cpsr + mrs r4, spsr + stmfd sp!, {r4} @ push spsr - str sp, [r0] @ store sp in preempted tasks TCB - ldr sp, [r1] @ get new task stack pointer + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_to(rt_uint32 to); @@ -64,14 +64,14 @@ rt_hw_context_switch: */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldr sp, [r0] @ get new task stack pointer + ldr sp, [r0] @ get new task stack pointer - ldmfd sp!, {r4} @ pop new task spsr - msr spsr_cxsf, r4 - ldmfd sp!, {r4} @ pop new task cpsr - msr cpsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task spsr + msr spsr_cxsf, r4 + ldmfd sp!, {r4} @ pop new task cpsr + msr cpsr_cxsf, r4 - ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc + ldmfd sp!, {r0-r12, lr, pc} @ pop new task r0-r12, lr & pc /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); @@ -81,15 +81,15 @@ rt_hw_context_switch_to: .globl rt_interrupt_to_thread .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldr r2, =rt_thread_switch_interrupt_flag - ldr r3, [r2] - cmp r3, #1 - beq _reswitch - mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 - str r3, [r2] - ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread - str r0, [r2] + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r3, [r2] + ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + str r0, [r2] _reswitch: - ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread - str r1, [r2] - mov pc, lr + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + mov pc, lr diff --git a/libcpu/arm/s3c44b0/context_rvds.S b/libcpu/arm/s3c44b0/context_rvds.S index 27ebf8f5e3..5f61b86e1f 100644 --- a/libcpu/arm/s3c44b0/context_rvds.S +++ b/libcpu/arm/s3c44b0/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -8,96 +8,96 @@ ; * 2009-01-20 Bernard first version ; */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr + MRS r4, cpsr + STMFD sp!, {r4} ; push cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push spsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP - END \ No newline at end of file + END diff --git a/libcpu/arm/s3c44b0/start_gcc.S b/libcpu/arm/s3c44b0/start_gcc.S index 4c448a344f..ff7665c13a 100644 --- a/libcpu/arm/s3c44b0/start_gcc.S +++ b/libcpu/arm/s3c44b0/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -18,22 +18,22 @@ .code 32 .globl _start _start: - b reset - ldr pc, _vector_undef - ldr pc, _vector_swi - ldr pc, _vector_pabt - ldr pc, _vector_dabt - ldr pc, _vector_resv - ldr pc, _vector_irq - ldr pc, _vector_fiq + b reset + ldr pc, _vector_undef + ldr pc, _vector_swi + ldr pc, _vector_pabt + ldr pc, _vector_dabt + ldr pc, _vector_resv + ldr pc, _vector_irq + ldr pc, _vector_fiq -_vector_undef: .word vector_undef -_vector_swi: .word vector_swi -_vector_pabt: .word vector_pabt -_vector_dabt: .word vector_dabt -_vector_resv: .word vector_resv -_vector_irq: .word vector_irq -_vector_fiq: .word vector_fiq +_vector_undef: .word vector_undef +_vector_swi: .word vector_swi +_vector_pabt: .word vector_pabt +_vector_dabt: .word vector_dabt +_vector_resv: .word vector_resv +_vector_irq: .word vector_irq +_vector_fiq: .word vector_fiq .text .code 32 @@ -45,209 +45,209 @@ _vector_fiq: .word vector_fiq .globl _rtthread_start _rtthread_start:.word _start .globl _rtthread_end -_rtthread_end: .word _end +_rtthread_end: .word _end /* * rtthread bss start and end * which are defined in linker script */ .globl _bss_start -_bss_start: .word __bss_start +_bss_start: .word __bss_start .globl _bss_end -_bss_end: .word __bss_end +_bss_end: .word __bss_end #if defined(__FLASH_BUILD__) /* - * TEXT_BASE, + * TEXT_BASE, * which is defined in macro of make */ -_TEXT_BASE: .word TEXT_BASE +_TEXT_BASE: .word TEXT_BASE #endif - .equ WTCON, 0x1d30000 - .equ INTCON, 0x1e00000 - .equ INTMSK, 0x1e0000c + .equ WTCON, 0x1d30000 + .equ INTCON, 0x1e00000 + .equ INTMSK, 0x1e0000c /* the system entry */ reset: - /* enter svc mode */ - msr cpsr_c, #SVCMODE|NOINT + /* enter svc mode */ + msr cpsr_c, #SVCMODE|NOINT - /*watch dog disable */ - ldr r0,=WTCON - ldr r1,=0x0 + /*watch dog disable */ + ldr r0,=WTCON + ldr r1,=0x0 str r1,[r0] - - /* all interrupt disable */ - ldr r0,=INTMSK - ldr r1,=0x07ffffff - str r1,[r0] - - ldr r1, =INTCON - ldr r0, =0x05 - str r0, [r1] + + /* all interrupt disable */ + ldr r0,=INTMSK + ldr r1,=0x07ffffff + str r1,[r0] + + ldr r1, =INTCON + ldr r0, =0x05 + str r0, [r1] #if defined(__FLASH_BUILD__) - /* init lowlevel */ - bl lowlevel_init + /* init lowlevel */ + bl lowlevel_init #endif - /* setup stack */ - bl stack_setup - + /* setup stack */ + bl stack_setup + #if defined(__FLASH_BUILD__) - mov r0, #0x0 /* r0 <- flash base address */ - ldr r1, _TEXT_BASE /* r1 <- the taget address */ - - ldr r2, _rtthread_start - ldr r3, _bss_start - sub r2, r3, r2 /* r2 <- size of rtthread kernel */ - add r2, r0, r2 /* r2 <- source end address */ - + mov r0, #0x0 /* r0 <- flash base address */ + ldr r1, _TEXT_BASE /* r1 <- the taget address */ + + ldr r2, _rtthread_start + ldr r3, _bss_start + sub r2, r3, r2 /* r2 <- size of rtthread kernel */ + add r2, r0, r2 /* r2 <- source end address */ + copy_loop: - ldmia r0!, {r3-r10} /* copy from source address [r0] */ - stmia r1!, {r3-r10} /* copy to target address [r1] */ - cmp r0, r2 /* until source end address [r2] */ - ble copy_loop + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + ble copy_loop #endif - - /* start RT-Thread Kernel */ - ldr pc, _rtthread_startup + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup _rtthread_startup: .word rtthread_startup - .equ USERMODE, 0x10 - .equ FIQMODE, 0x11 - .equ IRQMODE, 0x12 - .equ SVCMODE, 0x13 - .equ ABORTMODE, 0x17 - .equ UNDEFMODE, 0x1b - .equ MODEMASK, 0x1f - .equ NOINT, 0xc0 + .equ USERMODE, 0x10 + .equ FIQMODE, 0x11 + .equ IRQMODE, 0x12 + .equ SVCMODE, 0x13 + .equ ABORTMODE, 0x17 + .equ UNDEFMODE, 0x1b + .equ MODEMASK, 0x1f + .equ NOINT, 0xc0 /* exception handlers */ -vector_undef: bl rt_hw_trap_udef -vector_swi: bl rt_hw_trap_swi -vector_pabt: bl rt_hw_trap_pabt -vector_dabt: bl rt_hw_trap_dabt -vector_resv: bl rt_hw_trap_resv +vector_undef: bl rt_hw_trap_udef +vector_swi: bl rt_hw_trap_swi +vector_pabt: bl rt_hw_trap_pabt +vector_dabt: bl rt_hw_trap_dabt +vector_resv: bl rt_hw_trap_resv .globl rt_interrupt_enter .globl rt_interrupt_leave .globl rt_thread_switch_interrupt_flag .globl rt_interrupt_from_thread .globl rt_interrupt_to_thread -vector_irq: - stmfd sp!, {r0-r12,lr} - bl led_off - bl rt_interrupt_enter - bl rt_hw_trap_irq - bl rt_interrupt_leave +vector_irq: + stmfd sp!, {r0-r12,lr} + bl led_off + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave - /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ - ldr r0, =rt_thread_switch_interrupt_flag - ldr r1, [r0] - cmp r1, #1 - beq _interrupt_thread_switch + /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ + ldr r0, =rt_thread_switch_interrupt_flag + ldr r1, [r0] + cmp r1, #1 + beq _interrupt_thread_switch - ldmfd sp!, {r0-r12,lr} - subs pc, lr, #4 + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 - .align 5 + .align 5 vector_fiq: - stmfd sp!,{r0-r7,lr} - bl rt_hw_trap_fiq - ldmfd sp!,{r0-r7,lr} - subs pc,lr,#4 + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc,lr,#4 _interrupt_thread_switch: - mov r1, #0 @ clear rt_thread_switch_interrupt_flag - str r1, [r0] + mov r1, #0 @ clear rt_thread_switch_interrupt_flag + str r1, [r0] - ldmfd sp!, {r0-r12,lr} @ reload saved registers - stmfd sp!, {r0-r3} @ save r0-r3 - mov r1, sp - add sp, sp, #16 @ restore sp - sub r2, lr, #4 @ save old task's pc to r2 + ldmfd sp!, {r0-r12,lr} @ reload saved registers + stmfd sp!, {r0-r3} @ save r0-r3 + mov r1, sp + add sp, sp, #16 @ restore sp + sub r2, lr, #4 @ save old task's pc to r2 - mrs r3, spsr @ disable interrupt - orr r0, r3, #NOINT - msr spsr_c, r0 + mrs r3, spsr @ disable interrupt + orr r0, r3, #NOINT + msr spsr_c, r0 - ldr r0, =.+8 @ switch to interrupted task's stack - movs pc, r0 + ldr r0, =.+8 @ switch to interrupted task's stack + movs pc, r0 - stmfd sp!, {r2} @ push old task's pc - stmfd sp!, {r4-r12,lr} @ push old task's lr,r12-r4 - mov r4, r1 @ Special optimised code below - mov r5, r3 - ldmfd r4!, {r0-r3} - stmfd sp!, {r0-r3} @ push old task's r3-r0 - stmfd sp!, {r5} @ push old task's psr - mrs r4, spsr - stmfd sp!, {r4} @ push old task's spsr + stmfd sp!, {r2} @ push old task's pc + stmfd sp!, {r4-r12,lr} @ push old task's lr,r12-r4 + mov r4, r1 @ Special optimised code below + mov r5, r3 + ldmfd r4!, {r0-r3} + stmfd sp!, {r0-r3} @ push old task's r3-r0 + stmfd sp!, {r5} @ push old task's psr + mrs r4, spsr + stmfd sp!, {r4} @ push old task's spsr - ldr r4, =rt_interrupt_from_thread - ldr r5, [r4] - str sp, [r5] @ store sp in preempted tasks's TCB + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB - ldr r6, =rt_interrupt_to_thread - ldr r6, [r6] - ldr sp, [r6] @ get new task's stack pointer + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer - ldmfd sp!, {r4} @ pop new task's spsr - msr SPSR_cxsf, r4 - ldmfd sp!, {r4} @ pop new task's psr - msr CPSR_cxsf, r4 + ldmfd sp!, {r4} @ pop new task's spsr + msr SPSR_cxsf, r4 + ldmfd sp!, {r4} @ pop new task's psr + msr CPSR_cxsf, r4 - ldmfd sp!, {r0-r12,lr,pc} @ pop new task's r0-r12,lr & pc + ldmfd sp!, {r0-r12,lr,pc} @ pop new task's r0-r12,lr & pc /* each mode stack memory */ -UNDSTACK_START: .word _undefined_stack_start + 128 -ABTSTACK_START: .word _abort_stack_start + 128 -FIQSTACK_START: .word _fiq_stack_start + 1024 -IRQSTACK_START: .word _irq_stack_start + 1024 +UNDSTACK_START: .word _undefined_stack_start + 128 +ABTSTACK_START: .word _abort_stack_start + 128 +FIQSTACK_START: .word _fiq_stack_start + 1024 +IRQSTACK_START: .word _irq_stack_start + 1024 SVCSTACK_START: .word _svc_stack_start + 4096 stack_setup: - /* undefined instruction mode */ - msr cpsr_c, #UNDEFMODE|NOINT - ldr sp, UNDSTACK_START + /* undefined instruction mode */ + msr cpsr_c, #UNDEFMODE|NOINT + ldr sp, UNDSTACK_START - /* abort mode */ - msr cpsr_c, #ABORTMODE|NOINT - ldr sp, ABTSTACK_START + /* abort mode */ + msr cpsr_c, #ABORTMODE|NOINT + ldr sp, ABTSTACK_START - /* FIQ mode */ - msr cpsr_c, #FIQMODE|NOINT - ldr sp, FIQSTACK_START + /* FIQ mode */ + msr cpsr_c, #FIQMODE|NOINT + ldr sp, FIQSTACK_START - /* IRQ mode */ - msr cpsr_c, #IRQMODE|NOINT - ldr sp, IRQSTACK_START + /* IRQ mode */ + msr cpsr_c, #IRQMODE|NOINT + ldr sp, IRQSTACK_START - /* supervisor mode */ - msr cpsr_c, #SVCMODE|NOINT - ldr sp, SVCSTACK_START + /* supervisor mode */ + msr cpsr_c, #SVCMODE|NOINT + ldr sp, SVCSTACK_START - mov pc,lr @ The LR register may be not valid for the mode changes. + mov pc,lr @ The LR register may be not valid for the mode changes. .globl led_on led_on: - ldr r1, =0x1d20014 @ r1<-PDATC - ldr r0, [r1] @ r0<-[r1] - orr r0, r0, #0x0e @ r0=r0 or 0x0e - str r0, [r1] @ r0->[r1] - mov pc, lr + ldr r1, =0x1d20014 @ r1<-PDATC + ldr r0, [r1] @ r0<-[r1] + orr r0, r0, #0x0e @ r0=r0 or 0x0e + str r0, [r1] @ r0->[r1] + mov pc, lr .globl led_off led_off: - ldr r1, =0x1d20010 @ r1<-PCONC - ldr r0, =0x5f555555 @ r0<-0x5f555555 - str r0, [r1] @ r0->[r1] + ldr r1, =0x1d20010 @ r1<-PCONC + ldr r0, =0x5f555555 @ r0<-0x5f555555 + str r0, [r1] @ r0->[r1] - ldr r1, =0x1d20014 @ r1<-PDATC - ldr r0, =0x0 @ r0<-00 - str r0, [r1] @ r0->[r1] + ldr r1, =0x1d20014 @ r1<-PDATC + ldr r0, =0x0 @ r0<-00 + str r0, [r1] @ r0->[r1] - mov pc, lr + mov pc, lr diff --git a/libcpu/arm/sep4020/context_rvds.S b/libcpu/arm/sep4020/context_rvds.S index 27ebf8f5e3..5f61b86e1f 100644 --- a/libcpu/arm/sep4020/context_rvds.S +++ b/libcpu/arm/sep4020/context_rvds.S @@ -1,5 +1,5 @@ ;/* -; * Copyright (c) 2006-2018, RT-Thread Development Team +; * Copyright (c) 2006-2022, RT-Thread Development Team ; * ; * SPDX-License-Identifier: Apache-2.0 ; * @@ -8,96 +8,96 @@ ; * 2009-01-20 Bernard first version ; */ -NOINT EQU 0xc0 ; disable interrupt in psr +NOINT EQU 0xc0 ; disable interrupt in psr - AREA |.text|, CODE, READONLY, ALIGN=2 - ARM - REQUIRE8 - PRESERVE8 + AREA |.text|, CODE, READONLY, ALIGN=2 + ARM + REQUIRE8 + PRESERVE8 ;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ -rt_hw_interrupt_disable PROC - EXPORT rt_hw_interrupt_disable - MRS r0, cpsr - ORR r1, r0, #NOINT - MSR cpsr_c, r1 - BX lr - ENDP +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + MRS r0, cpsr + ORR r1, r0, #NOINT + MSR cpsr_c, r1 + BX lr + ENDP ;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ -rt_hw_interrupt_enable PROC - EXPORT rt_hw_interrupt_enable - MSR cpsr_c, r0 - BX lr - ENDP +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + MSR cpsr_c, r0 + BX lr + ENDP ;/* ; * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; * r0 --> from ; * r1 --> to ; */ -rt_hw_context_switch PROC - EXPORT rt_hw_context_switch - STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) - STMFD sp!, {r0-r12, lr} ; push lr & register file +rt_hw_context_switch PROC + EXPORT rt_hw_context_switch + STMFD sp!, {lr} ; push pc (lr should be pushed in place of PC) + STMFD sp!, {r0-r12, lr} ; push lr & register file - MRS r4, cpsr - STMFD sp!, {r4} ; push cpsr - MRS r4, spsr - STMFD sp!, {r4} ; push spsr + MRS r4, cpsr + STMFD sp!, {r4} ; push cpsr + MRS r4, spsr + STMFD sp!, {r4} ; push spsr - STR sp, [r0] ; store sp in preempted tasks TCB - LDR sp, [r1] ; get new task stack pointer + STR sp, [r0] ; store sp in preempted tasks TCB + LDR sp, [r1] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to ; */ -rt_hw_context_switch_to PROC - EXPORT rt_hw_context_switch_to - LDR sp, [r0] ; get new task stack pointer +rt_hw_context_switch_to PROC + EXPORT rt_hw_context_switch_to + LDR sp, [r0] ; get new task stack pointer - LDMFD sp!, {r4} ; pop new task spsr - MSR spsr_cxsf, r4 - LDMFD sp!, {r4} ; pop new task cpsr - MSR cpsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task spsr + MSR spsr_cxsf, r4 + LDMFD sp!, {r4} ; pop new task cpsr + MSR cpsr_cxsf, r4 - LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc - ENDP + LDMFD sp!, {r0-r12, lr, pc} ; pop new task r0-r12, lr & pc + ENDP ;/* ; * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); ; */ - IMPORT rt_thread_switch_interrupt_flag - IMPORT rt_interrupt_from_thread - IMPORT rt_interrupt_to_thread + IMPORT rt_thread_switch_interrupt_flag + IMPORT rt_interrupt_from_thread + IMPORT rt_interrupt_to_thread -rt_hw_context_switch_interrupt PROC - EXPORT rt_hw_context_switch_interrupt - LDR r2, =rt_thread_switch_interrupt_flag - LDR r3, [r2] - CMP r3, #1 - BEQ _reswitch - MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 - STR r3, [r2] - LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread - STR r0, [r2] +rt_hw_context_switch_interrupt PROC + EXPORT rt_hw_context_switch_interrupt + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 ; set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread ; set rt_interrupt_from_thread + STR r0, [r2] _reswitch - LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread - STR r1, [r2] - BX lr - ENDP + LDR r2, =rt_interrupt_to_thread ; set rt_interrupt_to_thread + STR r1, [r2] + BX lr + ENDP - END \ No newline at end of file + END diff --git a/libcpu/arm/zynqmp-r5/context_gcc.S b/libcpu/arm/zynqmp-r5/context_gcc.S index 0d660017da..a5eee0b717 100644 --- a/libcpu/arm/zynqmp-r5/context_gcc.S +++ b/libcpu/arm/zynqmp-r5/context_gcc.S @@ -1,11 +1,11 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2020-03-19 WangHuachen first version + * 2020-03-19 WangHuachen first version */ .section .text, "ax" @@ -35,7 +35,7 @@ rt_hw_context_switch_to: ldr sp, [r0] @ get new task stack pointer #if defined (__VFP_FP__) && !defined(__SOFTFP__) - ldmfd sp!, {r1} /* Restore floating point registers */ + ldmfd sp!, {r1} /* Restore floating point registers */ vmsr FPEXC, r1 ldmfd sp!, {r1} vmsr FPSCR, r1 @@ -79,7 +79,7 @@ _ARM_MODE: ldr sp, [r1] @ get new task stack pointer #if defined (__VFP_FP__) && !defined(__SOFTFP__) - ldmfd sp!, {r1} /* Restore floating point registers */ + ldmfd sp!, {r1} /* Restore floating point registers */ vmsr FPEXC, r1 ldmfd sp!, {r1} vmsr FPSCR, r1 diff --git a/libcpu/arm/zynqmp-r5/start_gcc.S b/libcpu/arm/zynqmp-r5/start_gcc.S index 7e99c9e82b..6d892c6fa6 100644 --- a/libcpu/arm/zynqmp-r5/start_gcc.S +++ b/libcpu/arm/zynqmp-r5/start_gcc.S @@ -1,12 +1,12 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2020-03-19 WangHuachen first version - * 2021-05-11 WangHuachen Added call to Xil_InitializeExistingMPURegConfig to + * 2020-03-19 WangHuachen first version + * 2021-05-11 WangHuachen Added call to Xil_InitializeExistingMPURegConfig to * initialize the MPU configuration table with the MPU * configurations already set in Init_Mpu function. */ @@ -59,19 +59,19 @@ stack_top: _reset: /* Initialize processor registers to 0 */ - mov r0,#0 - mov r1,#0 - mov r2,#0 - mov r3,#0 - mov r4,#0 - mov r5,#0 - mov r6,#0 - mov r7,#0 - mov r8,#0 - mov r9,#0 - mov r10,#0 - mov r11,#0 - mov r12,#0 + mov r0,#0 + mov r1,#0 + mov r2,#0 + mov r3,#0 + mov r4,#0 + mov r5,#0 + mov r6,#0 + mov r7,#0 + mov r8,#0 + mov r9,#0 + mov r10,#0 + mov r11,#0 + mov r12,#0 /* set the cpu to SVC32 mode and disable interrupt */ cpsid if, #Mode_SVC @@ -83,18 +83,18 @@ _reset: * Enable access to VFP by enabling access to Coprocessors 10 and 11. * Enables Full Access i.e. in both privileged and non privileged modes */ - mrc p15, 0, r0, c1, c0, 2 /* Read Coprocessor Access Control Register (CPACR) */ - orr r0, r0, #(0xF << 20) /* Enable access to CP 10 & 11 */ - mcr p15, 0, r0, c1, c0, 2 /* Write Coprocessor Access Control Register (CPACR) */ + mrc p15, 0, r0, c1, c0, 2 /* Read Coprocessor Access Control Register (CPACR) */ + orr r0, r0, #(0xF << 20) /* Enable access to CP 10 & 11 */ + mcr p15, 0, r0, c1, c0, 2 /* Write Coprocessor Access Control Register (CPACR) */ isb /* enable fpu access */ vmrs r3, FPEXC - orr r1, r3, #(1<<30) + orr r1, r3, #(1<<30) vmsr FPEXC, r1 /* clear the floating point register*/ - mov r1,#0 + mov r1,#0 vmov d0,r1,r1 vmov d1,r1,r1 vmov d2,r1,r1 @@ -114,16 +114,16 @@ _reset: #ifdef __SOFTFP__ /* Disable the FPU if SOFTFP is defined*/ - vmsr FPEXC,r3 + vmsr FPEXC,r3 #endif /* Disable MPU and caches */ - mrc p15, 0, r0, c1, c0, 0 /* Read CP15 Control Register*/ - bic r0, r0, #0x05 /* Disable MPU (M bit) and data cache (C bit) */ - bic r0, r0, #0x1000 /* Disable instruction cache (I bit) */ - dsb /* Ensure all previous loads/stores have completed */ - mcr p15, 0, r0, c1, c0, 0 /* Write CP15 Control Register */ - isb /* Ensure subsequent insts execute wrt new MPU settings */ + mrc p15, 0, r0, c1, c0, 0 /* Read CP15 Control Register*/ + bic r0, r0, #0x05 /* Disable MPU (M bit) and data cache (C bit) */ + bic r0, r0, #0x1000 /* Disable instruction cache (I bit) */ + dsb /* Ensure all previous loads/stores have completed */ + mcr p15, 0, r0, c1, c0, 0 /* Write CP15 Control Register */ + isb /* Ensure subsequent insts execute wrt new MPU settings */ /* Disable Branch prediction, TCM ECC checks */ mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR */ @@ -173,14 +173,14 @@ _reset: nop init: - bl Init_MPU /* Initialize MPU */ + bl Init_MPU /* Initialize MPU */ /* Enable Branch prediction */ mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/ bic r0, r0, #(0x1 << 17) /* Clear RSDIS bit 17 to enable return stack*/ bic r0, r0, #(0x1 << 16) /* Clear BP bit 15 and BP bit 16:*/ bic r0, r0, #(0x1 << 15) /* Normal operation, BP is taken from the global history table.*/ - orr r0, r0, #(0x1 << 14) /* Disable DBWR for errata 780125 */ + orr r0, r0, #(0x1 << 14) /* Disable DBWR for errata 780125 */ mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/ /* Enable icahce and dcache */ @@ -189,7 +189,7 @@ init: orr r1,r1,r0 dsb mcr p15,0,r1,c1,c0,0 /* Enable cache */ - isb /* isb flush prefetch buffer */ + isb /* isb flush prefetch buffer */ /* Set vector table in TCM/LOVEC */ mrc p15, 0, r0, c1, c0, 0 @@ -237,7 +237,7 @@ ctor_loop: b ctor_loop ctor_end: - bl Xil_InitializeExistingMPURegConfig /* Initialize MPU config */ + bl Xil_InitializeExistingMPURegConfig /* Initialize MPU config */ /* start RT-Thread Kernel */ ldr pc, _entry @@ -393,35 +393,35 @@ rt_hw_context_switch_interrupt_do: .endm .align 5 - .globl vector_swi + .globl vector_swi vector_swi: push_svc_reg bl rt_hw_trap_swi b . .align 5 - .globl vector_undef + .globl vector_undef vector_undef: push_svc_reg bl rt_hw_trap_undef b . .align 5 - .globl vector_pabt + .globl vector_pabt vector_pabt: push_svc_reg bl rt_hw_trap_pabt b . .align 5 - .globl vector_dabt + .globl vector_dabt vector_dabt: push_svc_reg bl rt_hw_trap_dabt b . .align 5 - .globl vector_resv + .globl vector_resv vector_resv: push_svc_reg bl rt_hw_trap_resv diff --git a/libcpu/arm/zynqmp-r5/vector_gcc.S b/libcpu/arm/zynqmp-r5/vector_gcc.S index 60d3c6cf1d..9c30f62851 100644 --- a/libcpu/arm/zynqmp-r5/vector_gcc.S +++ b/libcpu/arm/zynqmp-r5/vector_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -48,4 +48,4 @@ _vector_irq: _vector_fiq: .word vector_fiq -.balignl 16,0xdeadbeef +.balignl 16,0xdeadbeef diff --git a/libcpu/avr32/uc3/context_gcc.S b/libcpu/avr32/uc3/context_gcc.S index cbc08e24b2..2a59b4d2da 100644 --- a/libcpu/avr32/uc3/context_gcc.S +++ b/libcpu/avr32/uc3/context_gcc.S @@ -12,8 +12,8 @@ * 2010-03-27 Kyle First version */ -#define AVR32_SR 0 -#define AVR32_SR_GM_OFFSET 16 +#define AVR32_SR 0 +#define AVR32_SR_GM_OFFSET 16 .text @@ -23,8 +23,8 @@ .globl rt_hw_interrupt_disable .type rt_hw_interrupt_disable, %function rt_hw_interrupt_disable: - ssrf AVR32_SR_GM_OFFSET - mov pc, lr + ssrf AVR32_SR_GM_OFFSET + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level) @@ -32,8 +32,8 @@ rt_hw_interrupt_disable: .globl rt_hw_interrupt_enable .type rt_hw_interrupt_enable, %function rt_hw_interrupt_enable: - csrf AVR32_SR_GM_OFFSET - mov pc, lr + csrf AVR32_SR_GM_OFFSET + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)/* @@ -43,22 +43,22 @@ rt_hw_interrupt_enable: .globl rt_hw_context_switch .type rt_hw_context_switch, %function rt_hw_context_switch: - ssrf AVR32_SR_GM_OFFSET /* Disable global interrupt */ - stm --sp, r8-r12, lr /* Push R8-R12, LR */ - st.w --sp, lr /* Push LR (instead of PC) */ - mfsr r8, AVR32_SR /* Read Status Register */ - cbr r8, AVR32_SR_GM_OFFSET /* Clear GM bit */ - st.w --sp, r8 /* Push SR */ - stm --sp, r0-r7 /* Push R0-R7 */ - /* Stack layout: R8-R12, LR, PC, SR, R0-R7 */ + ssrf AVR32_SR_GM_OFFSET /* Disable global interrupt */ + stm --sp, r8-r12, lr /* Push R8-R12, LR */ + st.w --sp, lr /* Push LR (instead of PC) */ + mfsr r8, AVR32_SR /* Read Status Register */ + cbr r8, AVR32_SR_GM_OFFSET /* Clear GM bit */ + st.w --sp, r8 /* Push SR */ + stm --sp, r0-r7 /* Push R0-R7 */ + /* Stack layout: R8-R12, LR, PC, SR, R0-R7 */ - st.w r12[0], sp /* Store SP in preempted tasks TCB */ - ld.w sp, r11[0] /* Get new task stack pointer */ + st.w r12[0], sp /* Store SP in preempted tasks TCB */ + ld.w sp, r11[0] /* Get new task stack pointer */ - ldm sp++, r0-r7 /* pop R0-R7 */ - ld.w r8, sp++ /* pop SR */ - mtsr AVR32_SR, r8 /* Restore SR */ - ldm sp++, r8-r12, lr, pc/* Pop R8-R12, LR, PC and resume to thread */ + ldm sp++, r0-r7 /* pop R0-R7 */ + ld.w r8, sp++ /* pop SR */ + mtsr AVR32_SR, r8 /* Restore SR */ + ldm sp++, r8-r12, lr, pc/* Pop R8-R12, LR, PC and resume to thread */ /* * void rt_hw_context_switch_to(rt_uint32 to)/* @@ -67,12 +67,12 @@ rt_hw_context_switch: .globl rt_hw_context_switch_to .type rt_hw_context_switch_to, %function rt_hw_context_switch_to: - ld.w sp, r12[0] /* Get new task stack pointer */ + ld.w sp, r12[0] /* Get new task stack pointer */ - ldm sp++, r0-r7 /* pop R0-R7 */ - ld.w r8, sp++ /* pop SR */ - mtsr AVR32_SR, r8 /* Restore SR */ - ldm sp++, r8-r12, lr, pc/* Pop R8-R12, LR, PC and resume execution */ + ldm sp++, r0-r7 /* pop R0-R7 */ + ld.w r8, sp++ /* pop SR */ + mtsr AVR32_SR, r8 /* Restore SR */ + ldm sp++, r8-r12, lr, pc/* Pop R8-R12, LR, PC and resume execution */ /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)/* @@ -83,15 +83,15 @@ rt_hw_context_switch_to: .globl rt_hw_context_switch_interrupt .type rt_hw_context_switch_interrupt, %function rt_hw_context_switch_interrupt: - lda.w r8, rt_thread_switch_interrupt_flag - ld.w r9, r8[0] - cp.w r9, 1 - breq _reswitch - mov r9, 1 - st.w r8[0], r9 - lda.w r8, rt_interrupt_from_thread - st.w r8[0], r12 + lda.w r8, rt_thread_switch_interrupt_flag + ld.w r9, r8[0] + cp.w r9, 1 + breq _reswitch + mov r9, 1 + st.w r8[0], r9 + lda.w r8, rt_interrupt_from_thread + st.w r8[0], r12 _reswitch: - lda.w r8, rt_interrupt_to_thread - st.w r8[0], r11 - mov pc, lr + lda.w r8, rt_interrupt_to_thread + st.w r8[0], r11 + mov pc, lr diff --git a/libcpu/ia32/context_gcc.S b/libcpu/ia32/context_gcc.S index 32233303c7..65b6a0cdba 100644 --- a/libcpu/ia32/context_gcc.S +++ b/libcpu/ia32/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,63 +19,63 @@ */ .globl rt_hw_context_switch rt_hw_context_switch: - pushfl /*pushed eflags*/ + pushfl /*pushed eflags*/ /* - * add by ssslady@gmail.com 2009-10-14 + * add by ssslady@gmail.com 2009-10-14 * When we return again the esp should no be change. - * The old code change the esp to esp-4 :-(. - * A protection fault maybe occure for img created by some compiler,eg.gcc in the fedor-11 + * The old code change the esp to esp-4 :-(. + * A protection fault maybe occure for img created by some compiler,eg.gcc in the fedor-11 * ------------------------------------------------------------------------- - * entry old code new code - * EIP ->return esp EIP FLAGS ->return esp - * ... FLAGS ->retern esp CS - * CS EIP - * EIP + * entry old code new code + * EIP ->return esp EIP FLAGS ->return esp + * ... FLAGS ->retern esp CS + * CS EIP + * EIP */ - popl %eax /*get flags*/ - popl %ebx /*get eip*/ - pushl %eax /*push flags*/ - push %cs /*push cs*/ - pushl %ebx /*push eip*/ - + popl %eax /*get flags*/ + popl %ebx /*get eip*/ + pushl %eax /*push flags*/ + push %cs /*push cs*/ + pushl %ebx /*push eip*/ + /*------------------------------------------------------------------- */ - /*push %cs*/ /*push cs register*/ - /*pushl 0x8(%esp)*/ /*pushed eip register*/ + /*push %cs*/ /*push cs register*/ + /*pushl 0x8(%esp)*/ /*pushed eip register*/ - pushl $0 /*fill irqno*/ - push %ds /*push ds register*/ - push %es /*push es register*/ - pushal /*push eax,ecx,edx,ebx,esp,ebp,esp,edi registers*/ - - /*movl 0x40(%esp), %eax*/ /*to thread TCB*/ - /*movl 0x3c(%esp), %ebx*/ /*from thread TCB*/ - movl 0x3c(%esp), %eax /*to thread TCB*/ - movl 0x38(%esp), %ebx /*from thread TCB*/ + pushl $0 /*fill irqno*/ + push %ds /*push ds register*/ + push %es /*push es register*/ + pushal /*push eax,ecx,edx,ebx,esp,ebp,esp,edi registers*/ - movl %esp, (%ebx) /*store esp in preempted tasks TCB*/ - movl (%eax), %esp /*get new task stack pointer*/ + /*movl 0x40(%esp), %eax*/ /*to thread TCB*/ + /*movl 0x3c(%esp), %ebx*/ /*from thread TCB*/ + movl 0x3c(%esp), %eax /*to thread TCB*/ + movl 0x38(%esp), %ebx /*from thread TCB*/ - popal /*restore new task TCB*/ - pop %es - pop %ds - add $4,%esp /*skip irqno*/ - iret + movl %esp, (%ebx) /*store esp in preempted tasks TCB*/ + movl (%eax), %esp /*get new task stack pointer*/ + + popal /*restore new task TCB*/ + pop %es + pop %ds + add $4,%esp /*skip irqno*/ + iret /* * void rt_hw_context_switch_to(rt_uint32 to); */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - push %ebp - movl %esp, %ebp + push %ebp + movl %esp, %ebp - movl 0x8(%ebp), %eax /* to thread TCB */ - movl (%eax), %esp /* get new task stack pointer */ + movl 0x8(%ebp), %eax /* to thread TCB */ + movl (%eax), %esp /* get new task stack pointer */ - popal /* restore new task TCB*/ - pop %es - pop %ds - add $4, %esp /* skip irqno */ - iret + popal /* restore new task TCB*/ + pop %es + pop %ds + add $4, %esp /* skip irqno */ + iret diff --git a/libcpu/ia32/hdisr_gcc.S b/libcpu/ia32/hdisr_gcc.S index 24c4c17990..dbdc416bf1 100644 --- a/libcpu/ia32/hdisr_gcc.S +++ b/libcpu/ia32/hdisr_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -14,23 +14,23 @@ /*@{*/ #define ENTRY(proc)\ - .align 2;\ - .globl proc;\ - .type proc,@function;\ - proc: + .align 2;\ + .globl proc;\ + .type proc,@function;\ + proc: #define HDINTERRUPTFNC(name,num) \ - ENTRY(name)\ - pushl $(num);\ - jmp _hdinterrupts;\ - .data;\ - .long name;\ - .text + ENTRY(name)\ + pushl $(num);\ + jmp _hdinterrupts;\ + .data;\ + .long name;\ + .text .globl hdinterrupt_func - .data - .align 4 - .type hdinterrupt_func,@object - hdinterrupt_func : + .data + .align 4 + .type hdinterrupt_func,@object + hdinterrupt_func : .text /* the external device interrupts */ @@ -62,57 +62,57 @@ HDINTERRUPTFNC(irq15, 15) .globl rt_interrupt_to_thread _hdinterrupts: - push %ds - push %es - pushal - movw $0x10, %ax - movw %ax, %ds - movw %ax, %es - pushl %esp + push %ds + push %es + pushal + movw $0x10, %ax + movw %ax, %ds + movw %ax, %es + pushl %esp - call rt_interrupt_enter + call rt_interrupt_enter - movl %esp, %eax /* copy esp to eax */ - addl $0x2c, %eax /* move to vector address */ - movl (%eax), %eax /* vector(eax) = *eax */ + movl %esp, %eax /* copy esp to eax */ + addl $0x2c, %eax /* move to vector address */ + movl (%eax), %eax /* vector(eax) = *eax */ - pushl %eax /* push argument : int vector */ - call rt_hw_isr - add $4, %esp /* restore argument */ + pushl %eax /* push argument : int vector */ + call rt_hw_isr + add $4, %esp /* restore argument */ - call rt_interrupt_leave + call rt_interrupt_leave - /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ - movl $rt_thread_switch_interrupt_flag, %eax - movl (%eax), %ebx - cmp $0x1, %ebx - jz _interrupt_thread_switch + /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ + movl $rt_thread_switch_interrupt_flag, %eax + movl (%eax), %ebx + cmp $0x1, %ebx + jz _interrupt_thread_switch - popl %esp - popal - pop %es - pop %ds - add $4,%esp - iret + popl %esp + popal + pop %es + pop %ds + add $4,%esp + iret _interrupt_thread_switch: - popl %esp + popl %esp - movl $0x0, %ebx - movl %ebx, (%eax) + movl $0x0, %ebx + movl %ebx, (%eax) - movl $rt_interrupt_from_thread, %eax - movl (%eax), %ebx - movl %esp, (%ebx) + movl $rt_interrupt_from_thread, %eax + movl (%eax), %ebx + movl %esp, (%ebx) - movl $rt_interrupt_to_thread, %ecx - movl (%ecx), %edx - movl (%edx), %esp + movl $rt_interrupt_to_thread, %ecx + movl (%ecx), %edx + movl (%edx), %esp - popal - pop %es - pop %ds - add $4,%esp - iret + popal + pop %es + pop %ds + add $4,%esp + iret /*@}*/ diff --git a/libcpu/ia32/start_gcc.S b/libcpu/ia32/start_gcc.S index ee7d2787fd..30500a2877 100644 --- a/libcpu/ia32/start_gcc.S +++ b/libcpu/ia32/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,10 +10,10 @@ */ /* the magic number for the multiboot header. */ -#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 /* the flags for the multiboot header. */ -#define MULTIBOOT_HEADER_FLAGS 0x00000003 +#define MULTIBOOT_HEADER_FLAGS 0x00000003 #define CONFIG_STACKSIZE 8192 @@ -27,67 +27,67 @@ /* the system entry */ .globl _start _start: - jmp multiboot_entry + jmp multiboot_entry - /* Align 32 bits boundary. */ - .align 4 + /* Align 32 bits boundary. */ + .align 4 - /* multiboot header. */ + /* multiboot header. */ multiboot_header: - /* magic */ - .long MULTIBOOT_HEADER_MAGIC - /* flags */ - .long MULTIBOOT_HEADER_FLAGS - /* checksum */ - .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + /* magic */ + .long MULTIBOOT_HEADER_MAGIC + /* flags */ + .long MULTIBOOT_HEADER_FLAGS + /* checksum */ + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) multiboot_entry: - movl $(_end + 0x1000),%esp + movl $(_end + 0x1000),%esp - /* reset eflags. */ - pushl $0 - popf + /* reset eflags. */ + pushl $0 + popf - /* rebuild globe describe table */ - lgdt __gdtdesc + /* rebuild globe describe table */ + lgdt __gdtdesc - movl $0x10,%eax - movw %ax,%ds - movw %ax,%es - movw %ax,%ss - ljmp $0x08, $relocated + movl $0x10,%eax + movw %ax,%ds + movw %ax,%es + movw %ax,%ss + ljmp $0x08, $relocated relocated: - /* push the pointer to the multiboot information structure. */ - pushl %ebx + /* push the pointer to the multiboot information structure. */ + pushl %ebx - /* push the magic value. */ - pushl %eax + /* push the magic value. */ + pushl %eax - call rtthread_startup + call rtthread_startup - /* never get here */ + /* never get here */ spin: - hlt - jmp spin + hlt + jmp spin .data -.p2align 2 +.p2align 2 __gdt: - .word 0,0,0,0 + .word 0,0,0,0 - .word 0x07FF /* 8Mb - limit=2047 */ - .word 0x0000 - .word 0x9A00 /* code read/exec */ - .word 0x00C0 + .word 0x07FF /* 8Mb - limit=2047 */ + .word 0x0000 + .word 0x9A00 /* code read/exec */ + .word 0x00C0 - .word 0x07FF /* 8Mb - limit=2047 */ - .word 0x0000 - .word 0x9200 /* data read/write */ - .word 0x00C0 + .word 0x07FF /* 8Mb - limit=2047 */ + .word 0x0000 + .word 0x9200 /* data read/write */ + .word 0x00C0 __gdtdesc: - .word 0x17 - .long __gdt + .word 0x17 + .long __gdt /*@}*/ diff --git a/libcpu/ia32/trapisr_gcc.S b/libcpu/ia32/trapisr_gcc.S index 82887ecda3..3ac2c9d959 100644 --- a/libcpu/ia32/trapisr_gcc.S +++ b/libcpu/ia32/trapisr_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -14,33 +14,33 @@ /*@{*/ #define ENTRY(proc)\ - .align 2;\ - .globl proc;\ - .type proc,@function;\ - proc: + .align 2;\ + .globl proc;\ + .type proc,@function;\ + proc: #define TRAPFNC(name,num)\ - ENTRY(name)\ - pushl $(num);\ - jmp _traps;\ - .data;\ - .long name;\ - .text + ENTRY(name)\ + pushl $(num);\ + jmp _traps;\ + .data;\ + .long name;\ + .text #define TRAPFNC_NOEC(name,num)\ - ENTRY(name)\ - pushl $0;\ - pushl $(num);\ - jmp _traps;\ - .data;\ - .long name;\ - .text + ENTRY(name)\ + pushl $0;\ + pushl $(num);\ + jmp _traps;\ + .data;\ + .long name;\ + .text .globl trap_func - .data - .align 4 - .type trap_func,@object - trap_func : + .data + .align 4 + .type trap_func,@object + trap_func : .text /* CPU traps */ @@ -65,32 +65,32 @@ TRAPFNC (Xalign, 15) TRAPFNC (Xdefault, 500) .p2align 4,0x90 -.globl _traps -.type _traps,@function +.globl _traps +.type _traps,@function .globl rt_interrupt_enter .globl rt_interrupt_leave _traps: - push %ds - push %es - pushal - movw $0x10,%ax - movw %ax,%ds - movw %ax,%es - pushl %esp - call rt_interrupt_enter - movl %esp, %eax - addl $0x2c,%eax /*get trapno*/ - movl (%eax),%eax - pushl %eax /*push trapno*/ - call rt_hw_trap_irq - addl $4,%esp - call rt_interrupt_leave - popl %esp - popal - pop %es - pop %ds - add $8,%esp - iret + push %ds + push %es + pushal + movw $0x10,%ax + movw %ax,%ds + movw %ax,%es + pushl %esp + call rt_interrupt_enter + movl %esp, %eax + addl $0x2c,%eax /*get trapno*/ + movl (%eax),%eax + pushl %eax /*push trapno*/ + call rt_hw_trap_irq + addl $4,%esp + call rt_interrupt_leave + popl %esp + popal + pop %es + pop %ds + add $8,%esp + iret /*@}*/ diff --git a/libcpu/m16c/m16c62p/context_gcc.S b/libcpu/m16c/m16c62p/context_gcc.S index 45a2080800..0f131a922d 100644 --- a/libcpu/m16c/m16c62p/context_gcc.S +++ b/libcpu/m16c/m16c62p/context_gcc.S @@ -11,32 +11,32 @@ * Date Author Notes * 2010-04-09 fify the first version * 2010-04-19 fify rewrite rt_hw_interrupt_disable/enable fuction - * 2010-04-20 fify move peripheral ISR to bsp/interrupts.s34 + * 2010-04-20 fify move peripheral ISR to bsp/interrupts.s34 */ .section .text - + .globl _rt_interrupt_from_thread .globl _rt_interrupt_to_thread - .global _os_context_switch - .type _os_context_switch, @function + .global _os_context_switch + .type _os_context_switch, @function _os_context_switch: PUSHM R0,R1,R2,R3,A0,A1,SB,FB - + MOV.W _rt_interrupt_from_thread, A0 STC ISP, [A0] MOV.W _rt_interrupt_to_thread, A0 LDC [A0], ISP POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack - REIT ; Return from interrup - + REIT ; Return from interrup + /* * void rt_hw_context_switch_to(rt_uint32 to); * this fucntion is used to perform the first thread switch */ - .global _rt_hw_context_switch_to - .type _rt_hw_context_switch_to, @function + .global _rt_hw_context_switch_to + .type _rt_hw_context_switch_to, @function _rt_hw_context_switch_to: ENTER #0x0 MOV.W 0x5[FB], A0 diff --git a/libcpu/m16c/m16c62p/context_iar.S b/libcpu/m16c/m16c62p/context_iar.S index 9415b2bdea..ada3bd4c28 100644 --- a/libcpu/m16c/m16c62p/context_iar.S +++ b/libcpu/m16c/m16c62p/context_iar.S @@ -11,7 +11,7 @@ * Date Author Notes * 2010-04-09 fify the first version * 2010-04-19 fify rewrite rt_hw_interrupt_disable/enable fuction - * 2010-04-20 fify move peripheral ISR to bsp/interrupts.s34 + * 2010-04-20 fify move peripheral ISR to bsp/interrupts.s34 * * For : Renesas M16C * Toolchain : IAR's EW for M16C v3.401 @@ -39,19 +39,19 @@ rt_hw_interrupt_disable: rt_hw_interrupt_enable: LDC R0, FLG ;fify 20100419 RTS - + .EVEN os_context_switch: PUSHM R0,R1,R2,R3,A0,A1,SB,FB - + MOV.W rt_interrupt_from_thread, A0 STC ISP, [A0] MOV.W rt_interrupt_to_thread, A0 LDC [A0], ISP POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack - REIT ; Return from interrup - + REIT ; Return from interrup + /* * void rt_hw_context_switch_to(rt_uint32 to); * r0 --> to diff --git a/libcpu/m16c/m16c62p/context_iar.asm b/libcpu/m16c/m16c62p/context_iar.asm index 9415b2bdea..ada3bd4c28 100644 --- a/libcpu/m16c/m16c62p/context_iar.asm +++ b/libcpu/m16c/m16c62p/context_iar.asm @@ -11,7 +11,7 @@ * Date Author Notes * 2010-04-09 fify the first version * 2010-04-19 fify rewrite rt_hw_interrupt_disable/enable fuction - * 2010-04-20 fify move peripheral ISR to bsp/interrupts.s34 + * 2010-04-20 fify move peripheral ISR to bsp/interrupts.s34 * * For : Renesas M16C * Toolchain : IAR's EW for M16C v3.401 @@ -39,19 +39,19 @@ rt_hw_interrupt_disable: rt_hw_interrupt_enable: LDC R0, FLG ;fify 20100419 RTS - + .EVEN os_context_switch: PUSHM R0,R1,R2,R3,A0,A1,SB,FB - + MOV.W rt_interrupt_from_thread, A0 STC ISP, [A0] MOV.W rt_interrupt_to_thread, A0 LDC [A0], ISP POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack - REIT ; Return from interrup - + REIT ; Return from interrup + /* * void rt_hw_context_switch_to(rt_uint32 to); * r0 --> to diff --git a/libcpu/mips/common/context_gcc.S b/libcpu/mips/common/context_gcc.S index 3fdbe374c9..af0339276e 100644 --- a/libcpu/mips/common/context_gcc.S +++ b/libcpu/mips/common/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -84,7 +84,7 @@ mips_irq_handle: jal rt_interrupt_enter nop /* Get Old SP from k0 as paremeter in a0 */ - move a0, k0 + move a0, k0 jal rt_general_exc_dispatch nop jal rt_interrupt_leave diff --git a/libcpu/mips/common/entry_gcc.S b/libcpu/mips/common/entry_gcc.S index d1a0704809..287e895868 100644 --- a/libcpu/mips/common/entry_gcc.S +++ b/libcpu/mips/common/entry_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -28,37 +28,37 @@ _rtthread_entry: .globl _start _start: #endif - PTR_LA ra, _rtthread_entry + PTR_LA ra, _rtthread_entry /* disable interrupt */ - MTC0 zero, CP0_CAUSE - MTC0 zero, CP0_STATUS # Set CPU to disable interrupt. + MTC0 zero, CP0_CAUSE + MTC0 zero, CP0_STATUS # Set CPU to disable interrupt. ehb #ifdef ARCH_MIPS64 - dli t0, ST0_KX - MTC0 t0, CP0_STATUS + dli t0, ST0_KX + MTC0 t0, CP0_STATUS #endif /* setup stack pointer */ - PTR_LA sp, _system_stack - PTR_LA gp, _gp + PTR_LA sp, _system_stack + PTR_LA gp, _gp - bal rt_cpu_early_init + bal rt_cpu_early_init nop /* clear bss */ - PTR_LA t0, __bss_start - PTR_LA t1, __bss_end + PTR_LA t0, __bss_start + PTR_LA t1, __bss_end _clr_bss_loop: - sw zero, 0(t0) - bne t1, t0, _clr_bss_loop - addu t0, 4 + sw zero, 0(t0) + bne t1, t0, _clr_bss_loop + addu t0, 4 /* jump to RT-Thread RTOS */ - jal rtthread_startup + jal rtthread_startup nop /* restart, never die */ - j _start + j _start nop diff --git a/libcpu/mips/common/exception_gcc.S b/libcpu/mips/common/exception_gcc.S index c685928a84..8766529b5b 100644 --- a/libcpu/mips/common/exception_gcc.S +++ b/libcpu/mips/common/exception_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -21,50 +21,50 @@ /* 0x0 - TLB refill handler */ .global tlb_refill_exception - .type tlb_refill_exception,@function + .type tlb_refill_exception,@function ebase_start: tlb_refill_exception: - b _general_exception_handler + b _general_exception_handler nop /* 0x080 - XTLB refill handler */ .org ebase_start + 0x080 - b _general_exception_handler + b _general_exception_handler nop /* 0x100 - Cache error handler */ .org ebase_start + 0x100 - j cache_error_handler + j cache_error_handler nop /* 0x180 - Exception/Interrupt handler */ .global general_exception - .type general_exception,@function + .type general_exception,@function .org ebase_start + 0x180 general_exception: - b _general_exception_handler + b _general_exception_handler nop /* 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) */ .global irq_exception - .type irq_exception,@function + .type irq_exception,@function .org ebase_start + 0x200 irq_exception: - b _general_exception_handler + b _general_exception_handler nop /* general exception handler */ _general_exception_handler: - .set noreorder - PTR_LA k0, mips_irq_handle - jr k0 + .set noreorder + PTR_LA k0, mips_irq_handle + jr k0 nop - .set reorder + .set reorder /* interrupt handler */ _irq_handler: - .set noreorder - PTR_LA k0, mips_irq_handle - jr k0 + .set noreorder + PTR_LA k0, mips_irq_handle + jr k0 nop - .set reorder + .set reorder diff --git a/libcpu/mips/gs232/cache_gcc.S b/libcpu/mips/gs232/cache_gcc.S index 10a41652a3..c0aa67392c 100644 --- a/libcpu/mips/gs232/cache_gcc.S +++ b/libcpu/mips/gs232/cache_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,7 +19,7 @@ #include #include "cache.h" - .ent cache_init + .ent cache_init .global cache_init .set noreorder cache_init: @@ -68,67 +68,67 @@ cache_i4way: sllv t6, t4, t6 sllv t5, t4, t5 #if 0 - la t0, memvar - sw t7, 0x0(t0) #ways - sw t5, 0x4(t0) #icache size - sw t6, 0x8(t0) #dcache size + la t0, memvar + sw t7, 0x0(t0) #ways + sw t5, 0x4(t0) #icache size + sw t6, 0x8(t0) #dcache size #endif ####part 3#### - .set mips3 - lui a0, 0x8000 - addu a1, $0, t5 - addu a2, $0, t6 + .set mips3 + lui a0, 0x8000 + addu a1, $0, t5 + addu a2, $0, t6 cache_init_d2way: #a0=0x80000000, a1=icache_size, a2=dcache_size #a3, v0 and v1 used as local registers - mtc0 $0, CP0_TAGHI - addu v0, $0, a0 - addu v1, a0, a2 -1: slt a3, v0, v1 - beq a3, $0, 1f + mtc0 $0, CP0_TAGHI + addu v0, $0, a0 + addu v1, a0, a2 +1: slt a3, v0, v1 + beq a3, $0, 1f nop - mtc0 $0, CP0_TAGLO - beq t7, 1, 4f - cache Index_Store_Tag_D, 0x0(v0) # 1 way - beq t7, 2 ,4f - cache Index_Store_Tag_D, 0x1(v0) # 2 way - cache Index_Store_Tag_D, 0x2(v0) # 4 way - cache Index_Store_Tag_D, 0x3(v0) -4: beq $0, $0, 1b - addiu v0, v0, 0x20 + mtc0 $0, CP0_TAGLO + beq t7, 1, 4f + cache Index_Store_Tag_D, 0x0(v0) # 1 way + beq t7, 2 ,4f + cache Index_Store_Tag_D, 0x1(v0) # 2 way + cache Index_Store_Tag_D, 0x2(v0) # 4 way + cache Index_Store_Tag_D, 0x3(v0) +4: beq $0, $0, 1b + addiu v0, v0, 0x20 1: cache_flush_i2way: - addu v0, $0, a0 - addu v1, a0, a1 -1: slt a3, v0, v1 - beq a3, $0, 1f + addu v0, $0, a0 + addu v1, a0, a1 +1: slt a3, v0, v1 + beq a3, $0, 1f nop - beq t3, 1, 4f - cache Index_Invalidate_I, 0x0(v0) # 1 way - beq t3, 2, 4f - cache Index_Invalidate_I, 0x1(v0) # 2 way - cache Index_Invalidate_I, 0x2(v0) - cache Index_Invalidate_I, 0x3(v0) # 4 way -4: beq $0, $0, 1b - addiu v0, v0, 0x20 + beq t3, 1, 4f + cache Index_Invalidate_I, 0x0(v0) # 1 way + beq t3, 2, 4f + cache Index_Invalidate_I, 0x1(v0) # 2 way + cache Index_Invalidate_I, 0x2(v0) + cache Index_Invalidate_I, 0x3(v0) # 4 way +4: beq $0, $0, 1b + addiu v0, v0, 0x20 1: cache_flush_d2way: - addu v0, $0, a0 - addu v1, a0, a2 -1: slt a3, v0, v1 - beq a3, $0, 1f + addu v0, $0, a0 + addu v1, a0, a2 +1: slt a3, v0, v1 + beq a3, $0, 1f nop - beq t7, 1, 4f - cache Index_Writeback_Inv_D, 0x0(v0) #1 way - beq t7, 2, 4f - cache Index_Writeback_Inv_D, 0x1(v0) # 2 way - cache Index_Writeback_Inv_D, 0x2(v0) - cache Index_Writeback_Inv_D, 0x3(v0) # 4 way -4: beq $0, $0, 1b - addiu v0, v0, 0x20 + beq t7, 1, 4f + cache Index_Writeback_Inv_D, 0x0(v0) #1 way + beq t7, 2, 4f + cache Index_Writeback_Inv_D, 0x1(v0) # 2 way + cache Index_Writeback_Inv_D, 0x2(v0) + cache Index_Writeback_Inv_D, 0x3(v0) # 4 way +4: beq $0, $0, 1b + addiu v0, v0, 0x20 1: cache_init_finish: - jr t1 + jr t1 nop .set reorder .end cache_init @@ -139,80 +139,80 @@ cache_init_finish: LEAF(enable_cpu_cache) .set noreorder - mfc0 t0, CP0_CONFIG + mfc0 t0, CP0_CONFIG nop - and t0, ~0x03 - or t0, 0x03 - mtc0 t0, CP0_CONFIG + and t0, ~0x03 + or t0, 0x03 + mtc0 t0, CP0_CONFIG nop .set reorder - j ra + j ra END (enable_cpu_cache) - + ########################### # disable CPU cache # ########################### LEAF(disable_cpu_cache) .set noreorder - mfc0 t0, CP0_CONFIG + mfc0 t0, CP0_CONFIG nop - and t0, ~0x03 - or t0, 0x2 - mtc0 t0, CP0_CONFIG + and t0, ~0x03 + or t0, 0x2 + mtc0 t0, CP0_CONFIG nop .set reorder - j ra + j ra END (disable_cpu_cache) /**********************************/ -/* Invalidate Instruction Cache */ +/* Invalidate Instruction Cache */ /**********************************/ LEAF(Clear_TagLo) - .set noreorder - mtc0 zero, CP0_TAGLO + .set noreorder + mtc0 zero, CP0_TAGLO nop - .set reorder - j ra + .set reorder + j ra END(Clear_TagLo) .set mips3 /**********************************/ -/* Invalidate Instruction Cache */ +/* Invalidate Instruction Cache */ /**********************************/ LEAF(Invalidate_Icache_Ls1c) - .set noreorder - cache Index_Invalidate_I,0(a0) - cache Index_Invalidate_I,1(a0) - cache Index_Invalidate_I,2(a0) - cache Index_Invalidate_I,3(a0) - .set reorder - j ra + .set noreorder + cache Index_Invalidate_I,0(a0) + cache Index_Invalidate_I,1(a0) + cache Index_Invalidate_I,2(a0) + cache Index_Invalidate_I,3(a0) + .set reorder + j ra END(Invalidate_Icache_Ls1c) /**********************************/ -/* Invalidate Data Cache */ +/* Invalidate Data Cache */ /**********************************/ LEAF(Invalidate_Dcache_ClearTag_Ls1c) - .set noreorder - cache Index_Store_Tag_D, 0(a0) # BDSLOT: clear tag - cache Index_Store_Tag_D, 1(a0) # BDSLOT: clear tag - .set reorder - j ra + .set noreorder + cache Index_Store_Tag_D, 0(a0) # BDSLOT: clear tag + cache Index_Store_Tag_D, 1(a0) # BDSLOT: clear tag + .set reorder + j ra END(Invalidate_Dcache_ClearTag_Ls1c) LEAF(Invalidate_Dcache_Fill_Ls1c) - .set noreorder - cache Index_Writeback_Inv_D, 0(a0) # BDSLOT: clear tag - cache Index_Writeback_Inv_D, 1(a0) # BDSLOT: clear tag - .set reorder - j ra + .set noreorder + cache Index_Writeback_Inv_D, 0(a0) # BDSLOT: clear tag + cache Index_Writeback_Inv_D, 1(a0) # BDSLOT: clear tag + .set reorder + j ra END(Invalidate_Dcache_Fill_Ls1c) LEAF(Writeback_Invalidate_Dcache) .set noreorder - cache Hit_Writeback_Inv_D, (a0) + cache Hit_Writeback_Inv_D, (a0) .set reorder - j ra + j ra END(Writeback_Invalidate_Dcache) .set mips0 diff --git a/libcpu/mips/gs232/cpuinit_gcc.S b/libcpu/mips/gs232/cpuinit_gcc.S index 3379d7dae4..ba665fe0b5 100644 --- a/libcpu/mips/gs232/cpuinit_gcc.S +++ b/libcpu/mips/gs232/cpuinit_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -19,5 +19,5 @@ .globl rt_cpu_early_init rt_cpu_early_init: - jr ra - nop \ No newline at end of file + jr ra + nop diff --git a/libcpu/mips/pic32/context_gcc.S b/libcpu/mips/pic32/context_gcc.S index bd46dffdc7..5c6f20af6e 100644 --- a/libcpu/mips/pic32/context_gcc.S +++ b/libcpu/mips/pic32/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -18,7 +18,7 @@ #include "../common/stackframe.h" .section ".text", "ax" - .set noat + .set noat .set noreorder /* @@ -92,7 +92,7 @@ _reswitch: mfc0 t0, CP0_CAUSE /* t0 = Cause */ ori t0, t0, (1<<8) /* t0 |= (1<<8) */ mtc0 t0, CP0_CAUSE /* cause = t0 */ - addiu t1, zero, -257 /* t1 = ~(1<<8) */ + addiu t1, zero, -257 /* t1 = ~(1<<8) */ and t0, t0, t1 /* t0 &= t1 */ mtc0 t0, CP0_CAUSE /* cause = t0 */ jr ra @@ -103,17 +103,17 @@ _reswitch: */ .section ".text", "ax" .set noreorder - .set noat - .ent CoreSW0Handler + .set noat + .ent CoreSW0Handler - .globl CoreSW0Handler + .globl CoreSW0Handler CoreSW0Handler: SAVE_ALL - /* mCS0ClearIntFlag(); */ - la t0, IFS0CLR /* t0 = IFS0CLR */ - addiu t1,zero,0x02 /* t1 = (1<<2) */ - sw t1, 0(t0) /* IFS0CLR = t1 */ + /* mCS0ClearIntFlag(); */ + la t0, IFS0CLR /* t0 = IFS0CLR */ + addiu t1,zero,0x02 /* t1 = (1<<2) */ + sw t1, 0(t0) /* IFS0CLR = t1 */ la k0, rt_thread_switch_interrupt_flag sw zero, 0(k0) /* clear flag */ @@ -133,4 +133,4 @@ CoreSW0Handler: RESTORE_ALL_AND_RET - .end CoreSW0Handler + .end CoreSW0Handler diff --git a/libcpu/risc-v/e310/interrupt_gcc.S b/libcpu/risc-v/e310/interrupt_gcc.S index 1eac7af90a..ad4a495ac7 100644 --- a/libcpu/risc-v/e310/interrupt_gcc.S +++ b/libcpu/risc-v/e310/interrupt_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -94,7 +94,7 @@ spurious_interrupt: li t0, 0x00001800 csrs mstatus, t0 LOAD t0, 2 * REGBYTES(sp) - csrs mstatus, t0 + csrs mstatus, t0 LOAD x4, 4 * REGBYTES(sp) LOAD x5, 5 * REGBYTES(sp) diff --git a/libcpu/risc-v/k210/startup_gcc.S b/libcpu/risc-v/k210/startup_gcc.S index f40ab1b6f8..69f65f7f92 100644 --- a/libcpu/risc-v/k210/startup_gcc.S +++ b/libcpu/risc-v/k210/startup_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -12,7 +12,7 @@ #define MSTATUS_FS 0x00006000U /* initial state of FPU */ #include - .global _start + .global _start .section ".start", "ax" _start: j 1f diff --git a/libcpu/risc-v/rv32m1/interrupt_gcc.S b/libcpu/risc-v/rv32m1/interrupt_gcc.S index eacf667c67..c472f85999 100644 --- a/libcpu/risc-v/rv32m1/interrupt_gcc.S +++ b/libcpu/risc-v/rv32m1/interrupt_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -95,7 +95,7 @@ spurious_interrupt: li t0, 0x00001800 csrs mstatus, t0 LOAD t0, 2 * REGBYTES(sp) - csrs mstatus, t0 + csrs mstatus, t0 LOAD x4, 4 * REGBYTES(sp) LOAD x5, 5 * REGBYTES(sp) diff --git a/libcpu/risc-v/virt64/startup_gcc.S b/libcpu/risc-v/virt64/startup_gcc.S index 98fdc1d15b..9c12b6dd44 100644 --- a/libcpu/risc-v/virt64/startup_gcc.S +++ b/libcpu/risc-v/virt64/startup_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -11,13 +11,13 @@ */ #define XSTATUS_FS (3 << 13) /* initial state of FPU, clear to disable */ -#define XSTATUS_PUM (1 << 18) +#define XSTATUS_PUM (1 << 18) #include boot_hartid: .int .global boot_hartid - .global _start + .global _start .section ".start", "ax" _start: #ifdef RISCV_S_MODE diff --git a/libcpu/ti-dsp/c28x/context.s b/libcpu/ti-dsp/c28x/context.s index 323d97b180..fcae0aa520 100644 --- a/libcpu/ti-dsp/c28x/context.s +++ b/libcpu/ti-dsp/c28x/context.s @@ -1,5 +1,5 @@ ; -; Copyright (c) 2006-2018, RT-Thread Development Team +; Copyright (c) 2006-2022, RT-Thread Development Team ; ; SPDX-License-Identifier: Apache-2.0 ; @@ -25,7 +25,7 @@ .def _rt_hw_interrupt_thread_switch .def _rt_hw_interrupt_disable .def _rt_hw_interrupt_enable - + ;workaround for importing fpu settings from the compiler .cdecls C,NOLIST %{ @@ -37,7 +37,7 @@ %} -RT_CTX_SAVE .macro +RT_CTX_SAVE .macro PUSH AR1H:AR0H @@ -49,38 +49,38 @@ RT_CTX_SAVE .macro PUSH XAR7 PUSH XT PUSH RPC - + .if __FPU32__ - PUSH RB - MOV32 *SP++, STF - MOV32 *SP++, R0H - MOV32 *SP++, R1H - MOV32 *SP++, R2H - MOV32 *SP++, R3H - MOV32 *SP++, R4H - MOV32 *SP++, R5H - MOV32 *SP++, R6H - MOV32 *SP++, R7H + PUSH RB + MOV32 *SP++, STF + MOV32 *SP++, R0H + MOV32 *SP++, R1H + MOV32 *SP++, R2H + MOV32 *SP++, R3H + MOV32 *SP++, R4H + MOV32 *SP++, R5H + MOV32 *SP++, R6H + MOV32 *SP++, R7H .endif - + .endm RT_CTX_RESTORE .macro .if __FPU32__ - MOV32 R7H, *--SP, UNCF - MOV32 R6H, *--SP, UNCF - MOV32 R5H, *--SP, UNCF - MOV32 R4H, *--SP, UNCF - MOV32 R3H, *--SP, UNCF - MOV32 R2H, *--SP, UNCF - MOV32 R1H, *--SP, UNCF - MOV32 R0H, *--SP, UNCF - MOV32 STF, *--SP - POP RB + MOV32 R7H, *--SP, UNCF + MOV32 R6H, *--SP, UNCF + MOV32 R5H, *--SP, UNCF + MOV32 R4H, *--SP, UNCF + MOV32 R3H, *--SP, UNCF + MOV32 R2H, *--SP, UNCF + MOV32 R1H, *--SP, UNCF + MOV32 R0H, *--SP, UNCF + MOV32 STF, *--SP + POP RB .endif - + POP RPC POP XT POP XAR7 @@ -91,7 +91,7 @@ RT_CTX_RESTORE .macro POP XAR2 - MOVZ AR0 , @SP + MOVZ AR0 , @SP SUBB XAR0, #6 MOVL ACC , *XAR0 AND ACC, #0xFFFF << 16 @@ -127,13 +127,13 @@ _rt_hw_interrupt_enable: POP ST1 LRETR .endasmfunc - + ; ; void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); ; r0 --> from ; r4 --> to - + .asmfunc _rt_hw_context_switch_interrupt: MOVL XAR0, #0 @@ -169,7 +169,7 @@ _rt_hw_context_switch: MOVL XAR0, #0 MOV AR0, AL MOVL XAR4, *-SP[4] - ; set rt_thread_switch_interrupt_flag to 1 + ; set rt_thread_switch_interrupt_flag to 1 MOVL XAR5, #_rt_thread_switch_interrupt_flag MOVL XAR6, *XAR5 MOVL ACC, XAR6 @@ -188,20 +188,20 @@ _reswitch2: TRAP #16 LRETR .endasmfunc - + .asmfunc _RTOSINT_Handler: -; disable interrupt to protect context switch +; disable interrupt to protect context switch DINT - ; get rt_thread_switch_interrupt_flag + ; get rt_thread_switch_interrupt_flag MOV AR0, #_rt_thread_switch_interrupt_flag MOV AL, *AR0 MOV AR1, AL CMP AR1, #0 - B rtosint_exit, EQ ; pendsv already handled + B rtosint_exit, EQ ; pendsv already handled - ; clear rt_thread_switch_interrupt_flag to 0 + ; clear rt_thread_switch_interrupt_flag to 0 MOV AR1, #0x00 MOV *AR0, AR1 @@ -209,22 +209,22 @@ _RTOSINT_Handler: MOV AL, *AR0 MOV AR1, AL CMP AR1, #0 - B switch_to_thread, EQ ; skip register save at the first time - + B switch_to_thread, EQ ; skip register save at the first time + ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) -; TST lr, #0x10 ; if(!EXC_RETURN[4]) -; VSTMDBEQ r1!, {d8 - d15} ; push FPU register s16~s31 +; TST lr, #0x10 ; if(!EXC_RETURN[4]) +; VSTMDBEQ r1!, {d8 - d15} ; push FPU register s16~s31 ;#endif - - RT_CTX_SAVE ; push r4 - r11 register + + RT_CTX_SAVE ; push r4 - r11 register ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) -; MOV r4, #0x00 ; flag = 0 +; MOV r4, #0x00 ; flag = 0 -; TST lr, #0x10 ; if(!EXC_RETURN[4]) -; MOVEQ r4, #0x01 ; flag = 1 +; TST lr, #0x10 ; if(!EXC_RETURN[4]) +; MOVEQ r4, #0x01 ; flag = 1 -; STMFD r1!, {r4} ; push flag +; STMFD r1!, {r4} ; push flag ;#endif MOV AL, *AR0 @@ -237,10 +237,10 @@ switch_to_thread: MOV AL, *AR1 MOV AR1, AL MOV AL, *AR1 - MOV AR1, AL ; load thread stack pointer + MOV AR1, AL ; load thread stack pointer ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) -; LDMFD r1!, {r3} ; pop flag +; LDMFD r1!, {r3} ; pop flag ;#endif MOV @SP, AR1 @@ -248,7 +248,7 @@ switch_to_thread: RT_CTX_RESTORE ; pop r4 - r11 register rtosint_exit: - ; restore interrupt + ; restore interrupt EINT IRET @@ -290,25 +290,25 @@ _rt_hw_calc_csb: ; ; * void rt_hw_context_switch_to(rt_uint32 to); ; * r0 --> to - + .asmfunc _rt_hw_context_switch_to: MOV AR1, #_rt_interrupt_to_thread MOV *AR1, AL ;#if defined (__VFP_FP__) && !defined(__SOFTFP__) - ; CLEAR CONTROL.FPCA -; MRS r2, CONTROL ; read -; BIC r2, #0x04 ; modify -; MSR CONTROL, r2 ; write-back + ; CLEAR CONTROL.FPCA +; MRS r2, CONTROL ; read +; BIC r2, #0x04 ; modify +; MSR CONTROL, r2 ; write-back ;#endif - ; set from thread to 0 + ; set from thread to 0 MOV AR1, #_rt_interrupt_from_thread MOV AR0, #0x0 MOV *AR1, AR0 - ; set interrupt flag to 1 + ; set interrupt flag to 1 MOV AR1, #_rt_thread_switch_interrupt_flag MOV AR0, #1 MOV *AR1, AR0 @@ -316,14 +316,14 @@ _rt_hw_context_switch_to: TRAP #16 - ; never reach here! + ; never reach here! .endasmfunc - -; compatible with old version + +; compatible with old version .asmfunc _rt_hw_interrupt_thread_switch: LRETR NOP .endasmfunc - + .end diff --git a/libcpu/unicore32/sep6200/context_gcc.S b/libcpu/unicore32/sep6200/context_gcc.S index 9f8e2b8f13..ff9e14536c 100644 --- a/libcpu/unicore32/sep6200/context_gcc.S +++ b/libcpu/unicore32/sep6200/context_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -14,7 +14,7 @@ /*@{*/ -#define NOINT 0xc0 +#define NOINT 0xc0 /* * rt_base_t rt_hw_interrupt_disable(); @@ -23,11 +23,11 @@ .type rt_hw_interrupt_disable, %function rt_hw_interrupt_disable: stw.w r1, [sp-], #4 - mov r0, asr - or r1, r0, #NOINT - mov.a asr, r1 + mov r0, asr + or r1, r0, #NOINT + mov.a asr, r1 ldw.w r1, [sp]+, #4 - mov pc, lr + mov pc, lr /* * void rt_hw_interrupt_enable(rt_base_t level); @@ -35,8 +35,8 @@ rt_hw_interrupt_disable: .globl rt_hw_interrupt_enable .type rt_hw_interrupt_disable, %function rt_hw_interrupt_enable: - mov.a asr, r0 - mov pc, lr + mov.a asr, r0 + mov pc, lr /* * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); @@ -46,24 +46,24 @@ rt_hw_interrupt_enable: .globl rt_hw_context_switch .type rt_hw_interrupt_disable, %function rt_hw_context_switch: - stm.w (lr), [sp-] - stm.w (r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, lr), [sp-] - stm.w (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15), [sp-] - mov r4, asr - stm.w (r4), [sp-] - mov r4, bsr - stm.w (r4), [sp-] + stm.w (lr), [sp-] + stm.w (r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, lr), [sp-] + stm.w (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15), [sp-] + mov r4, asr + stm.w (r4), [sp-] + mov r4, bsr + stm.w (r4), [sp-] - stw sp, [r0+] - ldw sp, [r1+] + stw sp, [r0+] + ldw sp, [r1+] - ldm.w (r4), [sp]+ - mov.a bsr,r4 - ldm.w (r4), [sp]+ - mov.a asr, r4 + ldm.w (r4), [sp]+ + mov.a bsr,r4 + ldm.w (r4), [sp]+ + mov.a asr, r4 - ldm.w (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15), [sp]+ - ldm.w (r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, lr, pc), [sp]+ + ldm.w (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15), [sp]+ + ldm.w (r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, lr, pc), [sp]+ /* * void rt_hw_context_switch_to(rt_uint32 to); @@ -71,13 +71,13 @@ rt_hw_context_switch: */ .globl rt_hw_context_switch_to rt_hw_context_switch_to: - ldw sp, [r0+] - ldm.w (r4), [sp]+ - mov.a bsr, r4 - ldm.w (r4), [sp]+ - mov.a asr, r4 - ldm.w (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15), [sp]+ - ldm.w (r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, lr, pc), [sp]+ + ldw sp, [r0+] + ldm.w (r4), [sp]+ + mov.a bsr, r4 + ldm.w (r4), [sp]+ + mov.a asr, r4 + ldm.w (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15), [sp]+ + ldm.w (r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, lr, pc), [sp]+ /* * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); @@ -87,15 +87,15 @@ rt_hw_context_switch_to: .globl rt_interrupt_to_thread .globl rt_hw_context_switch_interrupt rt_hw_context_switch_interrupt: - ldw r2, =rt_thread_switch_interrupt_flag - ldw r3, [r2+] - cmpsub.a r3, #1 - beq _reswitch - mov r3, #1 - stw r3, [r2+] - ldw r2, =rt_interrupt_from_thread - stw r0, [r2+] + ldw r2, =rt_thread_switch_interrupt_flag + ldw r3, [r2+] + cmpsub.a r3, #1 + beq _reswitch + mov r3, #1 + stw r3, [r2+] + ldw r2, =rt_interrupt_from_thread + stw r0, [r2+] _reswitch: - ldw r2, =rt_interrupt_to_thread - stw r1, [r2+] - mov pc, lr + ldw r2, =rt_interrupt_to_thread + stw r1, [r2+] + mov pc, lr diff --git a/libcpu/unicore32/sep6200/start_gcc.S b/libcpu/unicore32/sep6200/start_gcc.S index 11676e875c..cfbbf2fafb 100644 --- a/libcpu/unicore32/sep6200/start_gcc.S +++ b/libcpu/unicore32/sep6200/start_gcc.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -9,53 +9,53 @@ */ -#define CONFIG_STACKSIZE 1024 -#define S_FRAME_SIZE 132 +#define CONFIG_STACKSIZE 1024 +#define S_FRAME_SIZE 132 -#define S_OLD_R0 132 -#define S_PSR 128 -#define S_PC 124 -#define S_LR 120 -#define S_SP 116 +#define S_OLD_R0 132 +#define S_PSR 128 +#define S_PC 124 +#define S_LR 120 +#define S_SP 116 -#define S_IP 112 -#define S_FP 108 -#define S_R26 104 -#define S_R25 100 -#define S_R24 96 -#define S_R23 92 -#define S_R22 88 -#define S_R21 84 -#define S_R20 80 -#define S_R19 76 -#define S_R18 72 -#define S_R17 68 -#define S_R16 64 -#define S_R15 60 -#define S_R14 56 -#define S_R13 52 -#define S_R12 48 -#define S_R11 44 -#define S_R10 40 -#define S_R9 36 -#define S_R8 32 -#define S_R7 28 -#define S_R6 24 -#define S_R5 20 -#define S_R4 16 -#define S_R3 12 -#define S_R2 8 -#define S_R1 4 -#define S_R0 0 +#define S_IP 112 +#define S_FP 108 +#define S_R26 104 +#define S_R25 100 +#define S_R24 96 +#define S_R23 92 +#define S_R22 88 +#define S_R21 84 +#define S_R20 80 +#define S_R19 76 +#define S_R18 72 +#define S_R17 68 +#define S_R16 64 +#define S_R15 60 +#define S_R14 56 +#define S_R13 52 +#define S_R12 48 +#define S_R11 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 -.equ USERMODE, 0x10 -.equ REALMODE, 0x11 -.equ IRQMODE, 0x12 -.equ PRIVMODE, 0x13 -.equ TRAPMODE, 0x17 -.equ EXTNMODE, 0x1b -.equ MODEMASK, 0x1f -.equ NOINT, 0xc0 +.equ USERMODE, 0x10 +.equ REALMODE, 0x11 +.equ IRQMODE, 0x12 +.equ PRIVMODE, 0x13 +.equ TRAPMODE, 0x17 +.equ EXTNMODE, 0x1b +.equ MODEMASK, 0x1f +.equ NOINT, 0xc0 /* ************************************************************************* @@ -127,96 +127,96 @@ FIQ_STACK_START: .globl UNDEFINED_STACK_START UNDEFINED_STACK_START: - .word _undefined_stack_start + CONFIG_STACKSIZE + .word _undefined_stack_start + CONFIG_STACKSIZE .globl ABORT_STACK_START ABORT_STACK_START: - .word _abort_stack_start + CONFIG_STACKSIZE + .word _abort_stack_start + CONFIG_STACKSIZE .globl _STACK_START _STACK_START: - .word _priv_stack_start + 4096 + .word _priv_stack_start + 4096 -.equ SEP6200_VIC_BASE, 0xb0000000 -.equ SEP6200_SYSCTL_BASE, 0xb0008000 +.equ SEP6200_VIC_BASE, 0xb0000000 +.equ SEP6200_SYSCTL_BASE, 0xb0008000 /* ----------------------------------entry------------------------------*/ reset: - /* set the cpu to PRIV mode and disable cpu interrupt */ - mov r0, asr - andn r0, r0, #0xff - or r0, r0, #PRIVMODE|NOINT - mov.a asr, r0 + /* set the cpu to PRIV mode and disable cpu interrupt */ + mov r0, asr + andn r0, r0, #0xff + or r0, r0, #PRIVMODE|NOINT + mov.a asr, r0 - /* mask all IRQs by clearing all bits in the INTMRs */ - ldw r1, =SEP6200_VIC_BASE - ldw r0, =0xffffffff - stw r0, [r1+], #0x20 /*interrupt enable clear*/ - stw r0, [r1+], #0x24 + /* mask all IRQs by clearing all bits in the INTMRs */ + ldw r1, =SEP6200_VIC_BASE + ldw r0, =0xffffffff + stw r0, [r1+], #0x20 /*interrupt enable clear*/ + stw r0, [r1+], #0x24 - /*remap ddr to 0x00000000 address*/ - ldw r1, =SEP6200_SYSCTL_BASE - ldw r0, [r1+] - ldw r2, =0x80000000 - or r0, r0, r2 - stw r2, [r1+] + /*remap ddr to 0x00000000 address*/ + ldw r1, =SEP6200_SYSCTL_BASE + ldw r0, [r1+] + ldw r2, =0x80000000 + or r0, r0, r2 + stw r2, [r1+] - /* set interrupt vector */ - /*do nothing here for vector*/ + /* set interrupt vector */ + /*do nothing here for vector*/ - /* setup stack */ - b.l stack_setup + /* setup stack */ + b.l stack_setup /* copy the vector code to address 0 */ - ldw r12, =0x100 - ldw r0, = 0x40000000 - ldw r1, = 0x00000000 + ldw r12, =0x100 + ldw r0, = 0x40000000 + ldw r1, = 0x00000000 copy_vetor: - ldw r2, [r0] - stw r2, [r1] - add r0, r0, #4 - add r1, r1, #4 - sub r12, r12, #4 - cmpsub.a r12, #0 - bne copy_vetor + ldw r2, [r0] + stw r2, [r1] + add r0, r0, #4 + add r1, r1, #4 + sub r12, r12, #4 + cmpsub.a r12, #0 + bne copy_vetor - /* clear .bss */ - ldw r0, _bss_start /* bss start */ - ldw r1, _bss_end /* bss end */ - mov r2,#0 /* get a zero */ + /* clear .bss */ + ldw r0, _bss_start /* bss start */ + ldw r1, _bss_end /* bss end */ + mov r2,#0 /* get a zero */ bss_loop: - stw r2, [r0] @ clear loop... - add r0, r0, #4 - cmpsub.a r0, r1 - bel bss_loop + stw r2, [r0] @ clear loop... + add r0, r0, #4 + cmpsub.a r0, r1 + bel bss_loop - /* call C++ constructors of global objects */ - ldw r0, =__ctors_start__ - ldw r1, =__ctors_end__ + /* call C++ constructors of global objects */ + ldw r0, =__ctors_start__ + ldw r1, =__ctors_end__ ctor_loop: - cmpsub.a r0, r1 - beq ctor_end - ldw.w r2, [r0]+, #4 - stm.w (r0, r1), [sp-] - add lr, pc, #4 - mov pc, r2 - ldm.w (r0, r1), [sp]+ - b ctor_loop + cmpsub.a r0, r1 + beq ctor_end + ldw.w r2, [r0]+, #4 + stm.w (r0, r1), [sp-] + add lr, pc, #4 + mov pc, r2 + ldm.w (r0, r1), [sp]+ + b ctor_loop ctor_end: /*enable interrupt*/ - mov r0, asr - andn r1, r0, #NOINT - mov.a asr, r1 + mov r0, asr + andn r1, r0, #NOINT + mov.a asr, r1 - /* start RT-Thread Kernel */ - ldw pc, _rtthread_startup + /* start RT-Thread Kernel */ + ldw pc, _rtthread_startup _rtthread_startup: - .word rtthread_startup + .word rtthread_startup /* ************************************************************************* @@ -228,7 +228,7 @@ _rtthread_startup: /* exception handlers */ /*Just simple implementation here */ - .align 5 + .align 5 extend_handle: b rt_hw_trap_extn swi_handle: @@ -240,84 +240,84 @@ dabort_handle: reserve_handle: b rt_hw_trap_resv -.globl rt_interrupt_enter -.globl rt_interrupt_leave -.globl rt_thread_switch_interrupt_flag -.globl rt_interrupt_from_thread -.globl rt_interrupt_to_thread +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread IRQ_handle: stm.w (lr), [sp-] stm.w (r16 - r28), [sp-] stm.w (r0 - r15), [sp-] - b.l rt_interrupt_enter - b.l rt_hw_trap_irq - b.l rt_interrupt_leave + b.l rt_interrupt_enter + b.l rt_hw_trap_irq + b.l rt_interrupt_leave - /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ - ldw r0, =rt_thread_switch_interrupt_flag - ldw r1, [r0+] - cmpsub.a r1, #1 - beq _interrupt_thread_switch + /* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */ + ldw r0, =rt_thread_switch_interrupt_flag + ldw r1, [r0+] + cmpsub.a r1, #1 + beq _interrupt_thread_switch ldm.w (r0 - r15), [sp]+ ldm.w (r16 - r28), [sp]+ ldm.w (lr), [sp]+ mov.a pc, lr - .align 5 + .align 5 FIQ_handle: b rt_hw_trap_fiq _interrupt_thread_switch: - mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ - stw r1, [r0+] + mov r1, #0 /* clear rt_thread_switch_interrupt_flag*/ + stw r1, [r0+] - /*reload register*/ + /*reload register*/ ldm.w (r0 - r15), [sp]+ ldm.w (r16 - r28), [sp]+ ldm.w (lr), [sp]+ - stm.w (r0 - r3), [sp-] /*save r0-r3*/ + stm.w (r0 - r3), [sp-] /*save r0-r3*/ - mov r1, sp - add sp, sp, #16 /* restore sp */ - mov r2, lr /* save old task's pc to r2 */ + mov r1, sp + add sp, sp, #16 /* restore sp */ + mov r2, lr /* save old task's pc to r2 */ mov r3, bsr mov r0, #0xd3 /*I:F:0:PRIV*/ mov.a asr, r0 - stm.w (r2), [sp-] /* push old task's pc */ + stm.w (r2), [sp-] /* push old task's pc */ - /* push old task's registers */ + /* push old task's registers */ stm.w (lr), [sp-] stm.w (r16 - r28), [sp-] stm.w (r4 - r15), [sp-] - mov r4, r1 /* Special optimised code below */ - mov r5, r3 + mov r4, r1 /* Special optimised code below */ + mov r5, r3 ldm.w (r0 - r3), [r4]+ stm.w (r0 - r3), [sp-] /*push old task's r3-r0*/ - stm.w (r5), [sp-] /* push old task's asr */ - mov r4, bsr - stm.w (r4), [sp-] /* push old task's bsr*/ + stm.w (r5), [sp-] /* push old task's asr */ + mov r4, bsr + stm.w (r4), [sp-] /* push old task's bsr*/ - ldw r4, =rt_interrupt_from_thread - ldw r5, [r4+] - stw sp, [r5+] /* store sp in preempted tasks's TCB*/ + ldw r4, =rt_interrupt_from_thread + ldw r5, [r4+] + stw sp, [r5+] /* store sp in preempted tasks's TCB*/ - ldw r6, =rt_interrupt_to_thread - ldw r6, [r6+] - ldw sp, [r6+] /* get new task's stack pointer */ + ldw r6, =rt_interrupt_to_thread + ldw r6, [r6+] + ldw sp, [r6+] /* get new task's stack pointer */ - ldm.w (r4), [sp]+ /* pop new task's spsr */ - mov.a bsr, r4 - ldm.w (r4), [sp]+ /* pop new task's psr */ - mov.a asr, r4 + ldm.w (r4), [sp]+ /* pop new task's spsr */ + mov.a bsr, r4 + ldm.w (r4), [sp]+ /* pop new task's psr */ + mov.a asr, r4 - /* pop new task's r0-r28,lr & pc */ + /* pop new task's r0-r28,lr & pc */ ldm.w (r0 - r15), [sp]+ ldm.w (r16 - r28), [sp]+ @@ -325,25 +325,25 @@ _interrupt_thread_switch: ldm.w (pc), [sp]+ stack_setup: - /*irq*/ + /*irq*/ mov ip, lr - mov r0, asr - andn r0, r0, #0x1f - or r0, r0, #IRQMODE|NOINT - mov.a asr, r0 /*IRQMODE*/ + mov r0, asr + andn r0, r0, #0x1f + or r0, r0, #IRQMODE|NOINT + mov.a asr, r0 /*IRQMODE*/ ldw r0, =IRQ_STACK_START ldw sp, [r0+] - /*ldw sp, IRQ_STACK_START*/ + /*ldw sp, IRQ_STACK_START*/ - /*priv*/ - mov r0, asr - andn r0, r0, #0x1f - or r0, r0, #PRIVMODE|NOINT - mov.a asr, r0 /*PRIVMODE*/ + /*priv*/ + mov r0, asr + andn r0, r0, #0x1f + or r0, r0, #PRIVMODE|NOINT + mov.a asr, r0 /*PRIVMODE*/ ldw r0, =_STACK_START ldw sp, [r0+] - /*ldw sp, _STACK_START*/ + /*ldw sp, _STACK_START*/ mov lr, ip - /*fiq and other mode is not implemented in code here*/ - mov pc, lr /*lr may not be valid for the mode changes*/ + /*fiq and other mode is not implemented in code here*/ + mov pc, lr /*lr may not be valid for the mode changes*/ /*/*}*/ From 65ecca80ee7b3e63998d2207f28fdc8847169eb3 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 14 Jan 2022 12:24:12 -0500 Subject: [PATCH 39/65] [kernel] improve comments --- src/device.c | 21 +++++++++++++++------ src/ipc.c | 13 +++++++------ src/thread.c | 16 ++++++++-------- src/timer.c | 12 ++++++------ 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/device.c b/src/device.c index ebb8f26854..9bfaf776d6 100644 --- a/src/device.c +++ b/src/device.c @@ -82,6 +82,7 @@ RTM_EXPORT(rt_device_register); */ rt_err_t rt_device_unregister(rt_device_t dev) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); RT_ASSERT(rt_object_is_systemobject(&dev->parent)); @@ -143,6 +144,7 @@ RTM_EXPORT(rt_device_create); */ void rt_device_destroy(rt_device_t dev) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); RT_ASSERT(rt_object_is_systemobject(&dev->parent) == RT_FALSE); @@ -202,6 +204,7 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag) { rt_err_t result = RT_EOK; + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); @@ -267,6 +270,7 @@ rt_err_t rt_device_close(rt_device_t dev) { rt_err_t result = RT_EOK; + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); @@ -312,6 +316,7 @@ rt_size_t rt_device_read(rt_device_t dev, void *buffer, rt_size_t size) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); @@ -354,6 +359,7 @@ rt_size_t rt_device_write(rt_device_t dev, const void *buffer, rt_size_t size) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); @@ -389,6 +395,7 @@ RTM_EXPORT(rt_device_write); */ rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); @@ -412,10 +419,11 @@ RTM_EXPORT(rt_device_control); * * @return RT_EOK */ -rt_err_t -rt_device_set_rx_indicate(rt_device_t dev, - rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size)) +rt_err_t rt_device_set_rx_indicate(rt_device_t dev, + rt_err_t (*rx_ind)(rt_device_t dev, + rt_size_t size)) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); @@ -435,10 +443,11 @@ RTM_EXPORT(rt_device_set_rx_indicate); * * @return RT_EOK */ -rt_err_t -rt_device_set_tx_complete(rt_device_t dev, - rt_err_t (*tx_done)(rt_device_t dev, void *buffer)) +rt_err_t rt_device_set_tx_complete(rt_device_t dev, + rt_err_t (*tx_done)(rt_device_t dev, + void *buffer)) { + /* parameter check */ RT_ASSERT(dev != RT_NULL); RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device); diff --git a/src/ipc.c b/src/ipc.c index 09cc74e103..aea149a67a 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -725,8 +725,7 @@ RTM_EXPORT(rt_sem_control); * * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait * when the mutex is not available. - * NOTE: The mutex flag can ONLY be RT_IPC_FLAG_PRIO. Using RT_IPC_FLAG_FIFO will seriously affect - * the real-time performance of the system. + * NOTE: This parameter has been obsoleted. It can be RT_IPC_FLAG_PRIO, RT_IPC_FLAG_FIFO or RT_NULL. * * @return Return the operation status. When the return value is RT_EOK, the initialization is successful. * If the return value is any other values, it represents the initialization failed. @@ -735,7 +734,8 @@ RTM_EXPORT(rt_sem_control); */ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag) { - (void)flag; + /* flag parameter has been obsoleted */ + RT_UNUSED(flag); /* parameter check */ RT_ASSERT(mutex != RT_NULL); @@ -807,8 +807,7 @@ RTM_EXPORT(rt_mutex_detach); * * @param flag is the mutex flag, which determines the queuing way of how multiple threads wait * when the mutex is not available. - * NOTE: The mutex flag can ONLY be RT_IPC_FLAG_PRIO. Using RT_IPC_FLAG_FIFO will seriously affect - * the real-time performance of the system. + * NOTE: This parameter has been obsoleted. It can be RT_IPC_FLAG_PRIO, RT_IPC_FLAG_FIFO or RT_NULL. * * @return Return a pointer to the mutex object. When the return value is RT_NULL, it means the creation failed. * @@ -817,7 +816,9 @@ RTM_EXPORT(rt_mutex_detach); rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag) { struct rt_mutex *mutex; - (void)flag; + + /* flag parameter has been obsoleted */ + RT_UNUSED(flag); RT_DEBUG_NOT_IN_INTERRUPT; diff --git a/src/thread.c b/src/thread.c index 6c221c1f29..bf1f2482a9 100644 --- a/src/thread.c +++ b/src/thread.c @@ -130,7 +130,7 @@ static void _thread_timeout(void *parameter) thread = (struct rt_thread *)parameter; - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); @@ -289,7 +289,7 @@ rt_err_t rt_thread_init(struct rt_thread *thread, rt_uint8_t priority, rt_uint32_t tick) { - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(stack_start != RT_NULL); @@ -340,7 +340,7 @@ RTM_EXPORT(rt_thread_self); */ rt_err_t rt_thread_startup(rt_thread_t thread) { - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); @@ -383,7 +383,7 @@ rt_err_t rt_thread_detach(rt_thread_t thread) { rt_base_t lock; - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread)); @@ -486,7 +486,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread) { rt_base_t lock; - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE); @@ -703,7 +703,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) { register rt_base_t temp; - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); @@ -821,7 +821,7 @@ rt_err_t rt_thread_suspend(rt_thread_t thread) register rt_base_t stat; register rt_base_t temp; - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_ASSERT(thread == rt_thread_self()); @@ -867,7 +867,7 @@ rt_err_t rt_thread_resume(rt_thread_t thread) { register rt_base_t temp; - /* thread check */ + /* parameter check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); diff --git a/src/timer.c b/src/timer.c index 6ef9a4ed3f..577dd5ae47 100644 --- a/src/timer.c +++ b/src/timer.c @@ -257,7 +257,7 @@ void rt_timer_init(rt_timer_t timer, rt_tick_t time, rt_uint8_t flag) { - /* timer check */ + /* parameter check */ RT_ASSERT(timer != RT_NULL); /* timer object initialization */ @@ -278,7 +278,7 @@ rt_err_t rt_timer_detach(rt_timer_t timer) { register rt_base_t level; - /* timer check */ + /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent)); @@ -347,7 +347,7 @@ rt_err_t rt_timer_delete(rt_timer_t timer) { register rt_base_t level; - /* timer check */ + /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); RT_ASSERT(rt_object_is_systemobject(&timer->parent) == RT_FALSE); @@ -386,7 +386,7 @@ rt_err_t rt_timer_start(rt_timer_t timer) unsigned int tst_nr; static unsigned int random_nr; - /* timer check */ + /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); @@ -511,7 +511,7 @@ rt_err_t rt_timer_stop(rt_timer_t timer) { register rt_base_t level; - /* timer check */ + /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); @@ -547,7 +547,7 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) { register rt_base_t level; - /* timer check */ + /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); From 1874bd25aae647d116dac36a17d3bc79850e200b Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 16 Jan 2022 14:33:41 -0500 Subject: [PATCH 40/65] [timer] improve parameter checking --- components/drivers/src/workqueue.c | 3 ++- src/timer.c | 28 +++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 6dbb0da627..9ee333cedd 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -98,7 +98,7 @@ static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, /* remove list */ rt_list_remove(&(work->list)); work->flags &= ~RT_WORK_STATE_PENDING; - /* */ + if (ticks == 0) { if (queue->work_current != work) @@ -288,6 +288,7 @@ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) * @param queue A pointer to the workqueue object. * @param work A pointer to the work item object. * @param time The delay time (unit: OS ticks) for the work item to be submitted to the work queue. + * The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. * @return -RT_EBUSY This work item is executing. diff --git a/src/timer.c b/src/timer.c index 577dd5ae47..63cbcf9e07 100644 --- a/src/timer.c +++ b/src/timer.c @@ -246,9 +246,12 @@ void rt_timer_dump(rt_list_t timer_heads[]) * * @param parameter is the param of the callback * - * @param time is the ticks of timer + * @param time is timeout ticks of timer + * + * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1). * * @param flag is the flag of timer + * */ void rt_timer_init(rt_timer_t timer, const char *name, @@ -259,6 +262,8 @@ void rt_timer_init(rt_timer_t timer, { /* parameter check */ RT_ASSERT(timer != RT_NULL); + RT_ASSERT(timeout != RT_NULL); + RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); /* timer object initialization */ rt_object_init(&(timer->parent), RT_Object_Class_Timer, name); @@ -303,15 +308,17 @@ RTM_EXPORT(rt_timer_detach); /** * @brief This function will create a timer * - * @param name the name of timer + * @param name is the name of timer * - * @param timeout the timeout function + * @param timeout is the timeout function * - * @param parameter the parameter of timeout function + * @param parameter is the parameter of timeout function * - * @param time the tick of timer + * @param time is timeout ticks of the timer * - * @param flag the flag of timer + * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1). + * + * @param flag is the flag of timer * * @return the created timer object */ @@ -323,6 +330,10 @@ rt_timer_t rt_timer_create(const char *name, { struct rt_timer *timer; + /* parameter check */ + RT_ASSERT(timeout != RT_NULL); + RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); + /* allocate a object */ timer = (struct rt_timer *)rt_object_allocate(RT_Object_Class_Timer, name); if (timer == RT_NULL) @@ -401,11 +412,6 @@ rt_err_t rt_timer_start(rt_timer_t timer) RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent))); - /* - * get timeout tick, - * the max timeout tick shall not great than RT_TICK_MAX/2 - */ - RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); timer->timeout_tick = rt_tick_get() + timer->init_tick; #ifdef RT_USING_TIMER_SOFT From 3a789b33176ffd8196eb212635f4581e9d649f79 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 16 Jan 2022 15:05:50 -0500 Subject: [PATCH 41/65] [workqueue] improve comment --- components/drivers/src/workqueue.c | 74 ++++++++++++++++++------------ 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 9ee333cedd..97e0a573bd 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -213,11 +213,13 @@ static void _delayed_work_timeout_handler(void *parameter) /** * @brief Create a work queue with a thread inside. * - * @param name The name of the work queue thread. - * @param stack_size The stack size of the work queue thread. - * @param priority The priority of the work queue thread. + * @param name is a name of the work queue thread. * - * @return Return A pointer to the workqueue object. It will return RT_NULL if failed. + * @param stack_size is stack size of the work queue thread. + * + * @param priority is a priority of the work queue thread. + * + * @return Return a pointer to the workqueue object. It will return RT_NULL if failed. */ struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority) { @@ -249,9 +251,9 @@ struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_siz /** * @brief Destroy a work queue. * - * @param queue A pointer to the workqueue object. + * @param queue is a pointer to the workqueue object. * - * @return RT_EOK Success. + * @return RT_EOK Success. */ rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue) { @@ -268,11 +270,12 @@ rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue) /** * @brief Submit a work item to the work queue without delay. * - * @param queue A pointer to the workqueue object. - * @param work A pointer to the work item object. + * @param queue is a pointer to the workqueue object. + * + * @param work is a pointer to the work item object. * * @return RT_EOK Success. - * @return -RT_EBUSY This work item is executing. + * -RT_EBUSY This work item is executing. */ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) { @@ -285,14 +288,17 @@ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) /** * @brief Submit a work item to the work queue with a delay. * - * @param queue A pointer to the workqueue object. - * @param work A pointer to the work item object. - * @param time The delay time (unit: OS ticks) for the work item to be submitted to the work queue. - * The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) + * @param queue is a pointer to the workqueue object. + * + * @param work is a pointer to the work item object. + * + * @param time is the delay time (unit: OS ticks) for the work item to be submitted to the work queue. + * + * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. - * @return -RT_EBUSY This work item is executing. - * @return -RT_ERROR The time parameter is invalid. + * -RT_EBUSY This work item is executing. + * -RT_ERROR The time parameter is invalid. */ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time) { @@ -305,14 +311,16 @@ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *wo /** * @brief Submit a work item to the work queue without delay. This work item will be executed after the current work item. * - * @param queue A pointer to the workqueue object. - * @param work A pointer to the work item object. + * @param queue is a pointer to the workqueue object. + * + * @param work is a pointer to the work item object. * * @return RT_EOK Success. */ rt_err_t rt_workqueue_urgent_work(struct rt_workqueue *queue, struct rt_work *work) { rt_base_t level; + RT_ASSERT(queue != RT_NULL); RT_ASSERT(work != RT_NULL); @@ -340,24 +348,27 @@ rt_err_t rt_workqueue_urgent_work(struct rt_workqueue *queue, struct rt_work *wo /** * @brief Cancel a work item in the work queue. * - * @param queue A pointer to the workqueue object. - * @param work A pointer to the work item object. + * @param queue is a pointer to the workqueue object. + * + * @param work is a pointer to the work item object. * * @return RT_EOK Success. - * @return -RT_EBUSY This work item is executing. + * -RT_EBUSY This work item is executing. */ rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work) { RT_ASSERT(work != RT_NULL); RT_ASSERT(queue != RT_NULL); + return _workqueue_cancel_work(queue, work); } /** * @brief Cancel a work item in the work queue. If the work item is executing, this function will block until it is done. * - * @param queue A pointer to the workqueue object. - * @param work A pointer to the work item object. + * @param queue is a pointer to the workqueue object. + * + * @param work is a pointer to the work item object. * * @return RT_EOK Success. */ @@ -382,7 +393,7 @@ rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_wor /** * @brief This function will cancel all work items in work queue. * - * @param queue A pointer to the workqueue object. + * @param queue is a pointer to the workqueue object. * * @return RT_EOK Success. */ @@ -416,12 +427,15 @@ static struct rt_workqueue *sys_workq; /** * @brief Submit a work item to the system work queue with a delay. * - * @param work A pointer to the work item object. - * @param time The delay time (unit: OS ticks) for the work item to be submitted to the work queue. + * @param work is a pointer to the work item object. + * + * @param time is the delay time (unit: OS ticks) for the work item to be submitted to the work queue. + * + * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. - * @return -RT_EBUSY This work item is executing. - * @return -RT_ERROR The time parameter is invalid. + * -RT_EBUSY This work item is executing. + * -RT_ERROR The time parameter is invalid. */ rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time) { @@ -431,10 +445,10 @@ rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time) /** * @brief Cancel a work item in the system work queue. * - * @param work A pointer to the work item object. + * @param work is a pointer to the work item object. * * @return RT_EOK Success. - * @return -RT_EBUSY This work item is executing. + * -RT_EBUSY This work item is executing. */ rt_err_t rt_work_cancel(struct rt_work *work) { From 36cbc1fd2f811f00280fe32cec8ff228d6142788 Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 16 Jan 2022 15:15:08 -0500 Subject: [PATCH 42/65] =?UTF-8?q?[workqueue]=20time=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=94=B9=E4=B8=BAticks=EF=BC=8C=E9=98=B2=E6=AD=A2=E8=AF=AF?= =?UTF-8?q?=E8=A7=A3=E5=8D=95=E4=BD=8D=E4=B8=BAms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/include/ipc/workqueue.h | 25 +++--------- components/drivers/src/workqueue.c | 44 +++++++++++++++++----- src/timer.c | 4 +- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index edefb0933e..4403969e67 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -54,37 +54,22 @@ struct rt_work /** * WorkQueue for DeviceDriver */ +void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_work *work, void *work_data), void *work_data); struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_size, rt_uint8_t priority); rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue); rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work); -rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time); +rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t ticks); rt_err_t rt_workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work); rt_err_t rt_workqueue_cancel_work_sync(struct rt_workqueue *queue, struct rt_work *work); rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue); rt_err_t rt_workqueue_urgent_work(struct rt_workqueue *queue, struct rt_work *work); #ifdef RT_USING_SYSTEM_WORKQUEUE -rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time); +rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t ticks); rt_err_t rt_work_cancel(struct rt_work *work); #endif /* RT_USING_SYSTEM_WORKQUEUE */ -/** - * @brief Initialize a work item, binding with a callback function. - * - * @param work A pointer to the work item object. - * @param work_func A callback function that will be called when this work item is executed. - * @param work_data A user data passed to the callback function as the second parameter. - */ -rt_inline void rt_work_init(struct rt_work *work, void (*work_func)(struct rt_work *work, void *work_data), - void *work_data) -{ - rt_list_init(&(work->list)); - work->work_func = work_func; - work->work_data = work_data; - work->workqueue = RT_NULL; - work->flags = 0; - work->type = 0; -} + #endif /* RT_USING_HEAP */ diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 97e0a573bd..fe42ede0f6 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -210,6 +210,30 @@ static void _delayed_work_timeout_handler(void *parameter) } } +/** + * @brief Initialize a work item, binding with a callback function. + * + * @param work is a pointer to the work item object. + * + * @param work_func is a callback function that will be called when this work item is executed. + * + * @param work_data is a user data passed to the callback function as the second parameter. + */ +void rt_work_init(struct rt_work *work, + void (*work_func)(struct rt_work *work, void *work_data), + void *work_data) +{ + RT_ASSERT(work != RT_NULL); + RT_ASSERT(work_func != RT_NULL); + + rt_list_init(&(work->list)); + work->work_func = work_func; + work->work_data = work_data; + work->workqueue = RT_NULL; + work->flags = 0; + work->type = 0; +} + /** * @brief Create a work queue with a thread inside. * @@ -292,20 +316,21 @@ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) * * @param work is a pointer to the work item object. * - * @param time is the delay time (unit: OS ticks) for the work item to be submitted to the work queue. + * @param ticks is the delay ticks for the work item to be submitted to the work queue. * * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. * -RT_EBUSY This work item is executing. - * -RT_ERROR The time parameter is invalid. + * -RT_ERROR The ticks parameter is invalid. */ -rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t time) +rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t ticks) { RT_ASSERT(queue != RT_NULL); RT_ASSERT(work != RT_NULL); + RT_ASSERT(ticks < RT_TICK_MAX / 2); - return _workqueue_submit_work(queue, work, time); + return _workqueue_submit_work(queue, work, ticks); } /** @@ -422,24 +447,25 @@ rt_err_t rt_workqueue_cancel_all_work(struct rt_workqueue *queue) } #ifdef RT_USING_SYSTEM_WORKQUEUE -static struct rt_workqueue *sys_workq; + +static struct rt_workqueue *sys_workq; /* system work queue */ /** * @brief Submit a work item to the system work queue with a delay. * * @param work is a pointer to the work item object. * - * @param time is the delay time (unit: OS ticks) for the work item to be submitted to the work queue. + * @param ticks is the delay OS ticks for the work item to be submitted to the work queue. * * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. * -RT_EBUSY This work item is executing. - * -RT_ERROR The time parameter is invalid. + * -RT_ERROR The ticks parameter is invalid. */ -rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t time) +rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t ticks) { - return rt_workqueue_submit_work(sys_workq, work, time); + return rt_workqueue_submit_work(sys_workq, work, ticks); } /** diff --git a/src/timer.c b/src/timer.c index 63cbcf9e07..5d54f85dbd 100644 --- a/src/timer.c +++ b/src/timer.c @@ -263,7 +263,7 @@ void rt_timer_init(rt_timer_t timer, /* parameter check */ RT_ASSERT(timer != RT_NULL); RT_ASSERT(timeout != RT_NULL); - RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); + RT_ASSERT(time < RT_TICK_MAX / 2); /* timer object initialization */ rt_object_init(&(timer->parent), RT_Object_Class_Timer, name); @@ -332,7 +332,7 @@ rt_timer_t rt_timer_create(const char *name, /* parameter check */ RT_ASSERT(timeout != RT_NULL); - RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2); + RT_ASSERT(time < RT_TICK_MAX / 2); /* allocate a object */ timer = (struct rt_timer *)rt_object_allocate(RT_Object_Class_Timer, name); From 8bf5a285281d5699630fa1d2c9f12db1d0d2263c Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Sun, 16 Jan 2022 16:00:55 -0500 Subject: [PATCH 43/65] =?UTF-8?q?[workqueue]=20=E5=A2=9E=E5=8A=A0rt=5Fwork?= =?UTF-8?q?=5Furgent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/include/ipc/workqueue.h | 1 + components/drivers/src/workqueue.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index 4403969e67..b2224bdcf4 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -66,6 +66,7 @@ rt_err_t rt_workqueue_urgent_work(struct rt_workqueue *queue, struct rt_work *wo #ifdef RT_USING_SYSTEM_WORKQUEUE rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t ticks); +rt_err_t rt_work_urgent(struct rt_work *work); rt_err_t rt_work_cancel(struct rt_work *work); #endif /* RT_USING_SYSTEM_WORKQUEUE */ diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index fe42ede0f6..58cb0ddf56 100644 --- a/components/drivers/src/workqueue.c +++ b/components/drivers/src/workqueue.c @@ -7,7 +7,8 @@ * Date Author Notes * 2017-02-27 Bernard fix the re-work issue. * 2021-08-01 Meco Man remove rt_delayed_work_init() - * 2021-08-14 Jackistang add comments for function interface. + * 2021-08-14 Jackistang add comments for function interface + * 2022-01-16 Meco Man add rt_work_urgent() */ #include @@ -468,6 +469,18 @@ rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t ticks) return rt_workqueue_submit_work(sys_workq, work, ticks); } +/** + * @brief Submit a work item to the system work queue without delay. This work item will be executed after the current work item. + * + * @param work is a pointer to the work item object. + * + * @return RT_EOK Success. + */ +rt_err_t rt_work_urgent(struct rt_work *work) +{ + return rt_workqueue_urgent_work(sys_workq, work); +} + /** * @brief Cancel a work item in the system work queue. * @@ -486,7 +499,7 @@ static int rt_work_sys_workqueue_init(void) if (sys_workq != RT_NULL) return RT_EOK; - sys_workq = rt_workqueue_create("sys_work", RT_SYSTEM_WORKQUEUE_STACKSIZE, + sys_workq = rt_workqueue_create("sys workq", RT_SYSTEM_WORKQUEUE_STACKSIZE, RT_SYSTEM_WORKQUEUE_PRIORITY); RT_ASSERT(sys_workq != RT_NULL); From 03f46c6694056a6284b06422bc7b1329b0e3e003 Mon Sep 17 00:00:00 2001 From: diskwu <27161916@qq.com> Date: Fri, 21 Jan 2022 11:06:37 +0800 Subject: [PATCH 44/65] =?UTF-8?q?=E9=81=BF=E5=85=8D=E8=AD=A6=E5=91=8A?= =?UTF-8?q?=EF=BC=8C=E5=8F=98=E9=87=8F=E5=8F=AF=E8=83=BD=E6=9C=AA=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=B0=B1=E4=BD=BF=E7=94=A8=20(#5544)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 避免警告,变量可能未初始化就使用 * 避免警告,变量可能未初始化就使用 * 避免警告,变化可能未初始化就使用。 * Update bsp/stm32/libraries/HAL_Drivers/drv_usart.c Co-authored-by: guo * Update bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c Co-authored-by: guo Co-authored-by: guo --- bsp/stm32/libraries/HAL_Drivers/drv_usart.c | 3 ++- bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart.c index 7807e0c010..6211676056 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart.c @@ -918,6 +918,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) struct stm32_uart *uart; RT_ASSERT(serial != RT_NULL); + RT_ASSERT(flag == RT_DEVICE_FLAG_DMA_TX || flag == RT_DEVICE_FLAG_DMA_RX); uart = rt_container_of(serial, struct stm32_uart, serial); if (RT_DEVICE_FLAG_DMA_RX == flag) @@ -925,7 +926,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) DMA_Handle = &uart->dma_rx.handle; dma_config = uart->config->dma_rx; } - else if (RT_DEVICE_FLAG_DMA_TX == flag) + else /* RT_DEVICE_FLAG_DMA_TX == flag */ { DMA_Handle = &uart->dma_tx.handle; dma_config = uart->config->dma_tx; diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c index 038129beef..95635fe37b 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c @@ -959,6 +959,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) struct stm32_uart *uart; RT_ASSERT(serial != RT_NULL); + RT_ASSERT(flag == RT_DEVICE_FLAG_DMA_TX || flag == RT_DEVICE_FLAG_DMA_RX); uart = rt_container_of(serial, struct stm32_uart, serial); if (RT_DEVICE_FLAG_DMA_RX == flag) @@ -966,7 +967,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) DMA_Handle = &uart->dma_rx.handle; dma_config = uart->config->dma_rx; } - else if (RT_DEVICE_FLAG_DMA_TX == flag) + else /* RT_DEVICE_FLAG_DMA_TX == flag */ { DMA_Handle = &uart->dma_tx.handle; dma_config = uart->config->dma_tx; From 1aa96f34cd327dbb913bb90147bb96a1f19f0d92 Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Fri, 21 Jan 2022 11:45:33 +0800 Subject: [PATCH 45/65] [lwip]Improve lwip support for 64-bit architecture --- components/net/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/net/Kconfig b/components/net/Kconfig index f4531375c0..2ad34567e9 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -138,6 +138,7 @@ config RT_USING_LWIP config RT_LWIP_MEM_ALIGNMENT int "Memory alignment" + default 8 if ARCH_CPU_64BIT default 4 config RT_LWIP_IGMP @@ -258,6 +259,7 @@ config RT_USING_LWIP config RT_LWIP_TCPTHREAD_STACKSIZE int "the stack size of lwIP thread" + default 2048 if ARCH_CPU_64BIT default 1024 config LWIP_NO_RX_THREAD @@ -274,6 +276,7 @@ config RT_USING_LWIP config RT_LWIP_ETHTHREAD_STACKSIZE int "the stack size of ethernet thread" + default 2048 if ARCH_CPU_64BIT default 1024 config RT_LWIP_ETHTHREAD_MBOX_SIZE From e10173daff840ea8e58d20c59d0e8fb9517a3bae Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Fri, 21 Jan 2022 17:06:00 -0500 Subject: [PATCH 46/65] [device] rename src folder as ipc --- components/drivers/{src => ipc}/SConscript | 0 components/drivers/{src => ipc}/completion.c | 0 components/drivers/{src => ipc}/dataqueue.c | 0 components/drivers/{src => ipc}/pipe.c | 0 components/drivers/{src => ipc}/ringblk_buf.c | 0 components/drivers/{src => ipc}/ringbuffer.c | 0 components/drivers/{src => ipc}/waitqueue.c | 0 components/drivers/{src => ipc}/workqueue.c | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename components/drivers/{src => ipc}/SConscript (100%) rename components/drivers/{src => ipc}/completion.c (100%) rename components/drivers/{src => ipc}/dataqueue.c (100%) rename components/drivers/{src => ipc}/pipe.c (100%) rename components/drivers/{src => ipc}/ringblk_buf.c (100%) rename components/drivers/{src => ipc}/ringbuffer.c (100%) rename components/drivers/{src => ipc}/waitqueue.c (100%) rename components/drivers/{src => ipc}/workqueue.c (100%) diff --git a/components/drivers/src/SConscript b/components/drivers/ipc/SConscript similarity index 100% rename from components/drivers/src/SConscript rename to components/drivers/ipc/SConscript diff --git a/components/drivers/src/completion.c b/components/drivers/ipc/completion.c similarity index 100% rename from components/drivers/src/completion.c rename to components/drivers/ipc/completion.c diff --git a/components/drivers/src/dataqueue.c b/components/drivers/ipc/dataqueue.c similarity index 100% rename from components/drivers/src/dataqueue.c rename to components/drivers/ipc/dataqueue.c diff --git a/components/drivers/src/pipe.c b/components/drivers/ipc/pipe.c similarity index 100% rename from components/drivers/src/pipe.c rename to components/drivers/ipc/pipe.c diff --git a/components/drivers/src/ringblk_buf.c b/components/drivers/ipc/ringblk_buf.c similarity index 100% rename from components/drivers/src/ringblk_buf.c rename to components/drivers/ipc/ringblk_buf.c diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/ipc/ringbuffer.c similarity index 100% rename from components/drivers/src/ringbuffer.c rename to components/drivers/ipc/ringbuffer.c diff --git a/components/drivers/src/waitqueue.c b/components/drivers/ipc/waitqueue.c similarity index 100% rename from components/drivers/src/waitqueue.c rename to components/drivers/ipc/waitqueue.c diff --git a/components/drivers/src/workqueue.c b/components/drivers/ipc/workqueue.c similarity index 100% rename from components/drivers/src/workqueue.c rename to components/drivers/ipc/workqueue.c From 31c3214fafd059dfe7cd33aee1aa6c573437bed5 Mon Sep 17 00:00:00 2001 From: "Man, Jianting (Meco)" <920369182@qq.com> Date: Sun, 23 Jan 2022 20:16:57 -0500 Subject: [PATCH 47/65] =?UTF-8?q?[posix][io]=E6=95=B4=E7=90=86posix/io?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=20(#5539)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [posix][io]整理posix/io文件夹 - 将select.c移入到poll文件夹 - 将libc.c移入到tty文件夹,isatty函数归并到libc.c中, termios并入tty文件夹中 - 整理Sconscript Signed-off-by: Meco Man <920369182@qq.com> * [libc][newlib]调整文件夹结构 --- components/libc/compilers/newlib/libc_syms.c | 53 ------------------- components/libc/posix/io/README.md | 10 ++++ components/libc/posix/io/SConscript | 15 ------ components/libc/posix/io/poll/SConscript | 5 +- components/libc/posix/io/{ => poll}/select.c | 0 components/libc/posix/io/stdio/SConscript | 22 ++++++++ components/libc/posix/io/{ => stdio}/libc.c | 26 +++++++-- components/libc/posix/io/{ => stdio}/libc.h | 0 components/libc/posix/io/termios/termios.c | 2 - components/libc/posix/libdl/SConscript | 2 +- .../gcc/newlib => posix/libdl}/dlsyms.c | 0 components/libc/posix/readme.md | 5 +- components/libc/posix/src/SConscript | 16 ------ components/libc/posix/src/unistd.c | 41 -------------- 14 files changed, 64 insertions(+), 133 deletions(-) delete mode 100644 components/libc/compilers/newlib/libc_syms.c create mode 100644 components/libc/posix/io/README.md rename components/libc/posix/io/{ => poll}/select.c (100%) create mode 100644 components/libc/posix/io/stdio/SConscript rename components/libc/posix/io/{ => stdio}/libc.c (87%) rename components/libc/posix/io/{ => stdio}/libc.h (100%) rename components/libc/{compilers/gcc/newlib => posix/libdl}/dlsyms.c (100%) delete mode 100644 components/libc/posix/src/SConscript delete mode 100644 components/libc/posix/src/unistd.c diff --git a/components/libc/compilers/newlib/libc_syms.c b/components/libc/compilers/newlib/libc_syms.c deleted file mode 100644 index e6ca23b393..0000000000 --- a/components/libc/compilers/newlib/libc_syms.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2017/10/15 bernard the first version - */ - -#include -#include - -#include -#include -#include - -RTM_EXPORT(strcpy); -RTM_EXPORT(strncpy); -RTM_EXPORT(strlen); -RTM_EXPORT(strcat); -RTM_EXPORT(strstr); -RTM_EXPORT(strchr); -RTM_EXPORT(strcmp); -RTM_EXPORT(strtol); -RTM_EXPORT(strtoul); -RTM_EXPORT(strncmp); - -RTM_EXPORT(memcpy); -RTM_EXPORT(memcmp); -RTM_EXPORT(memmove); -RTM_EXPORT(memset); -RTM_EXPORT(memchr); - -RTM_EXPORT(putchar); -RTM_EXPORT(puts); -RTM_EXPORT(printf); -RTM_EXPORT(sprintf); -RTM_EXPORT(snprintf); - -RTM_EXPORT(fwrite); - -#include -RTM_EXPORT(longjmp); -RTM_EXPORT(setjmp); - -RTM_EXPORT(exit); -RTM_EXPORT(abort); - -RTM_EXPORT(rand); - -#include -RTM_EXPORT(__assert_func); diff --git a/components/libc/posix/io/README.md b/components/libc/posix/io/README.md new file mode 100644 index 0000000000..54f5c0a02d --- /dev/null +++ b/components/libc/posix/io/README.md @@ -0,0 +1,10 @@ +This folder contains: + +| sub-folders | description | +| ----------- | ------------------------- | +| aio | Asynchronous I/O | +| mman | Memory-Mapped I/O | +| poll | Nonblocking I/O | +| stdio | Standard Input/Output I/O | +| termios | Terminal I/O | + diff --git a/components/libc/posix/io/SConscript b/components/libc/posix/io/SConscript index bb45211ec0..e016836a9d 100644 --- a/components/libc/posix/io/SConscript +++ b/components/libc/posix/io/SConscript @@ -3,24 +3,9 @@ import os from building import * -src = [] cwd = GetCurrentDir() -CPPPATH = [cwd] group = [] -flag = False - -if GetDepend('RT_USING_POSIX_STDIO'): - src += ['libc.c'] - flag = True - -if GetDepend('RT_USING_POSIX_SELECT'): - src += ['select.c'] - flag = True - -if flag == True: - group = DefineGroup('POSIX', src, depend = [''], CPPPATH = CPPPATH) - list = os.listdir(cwd) for d in list: path = os.path.join(cwd, d) diff --git a/components/libc/posix/io/poll/SConscript b/components/libc/posix/io/poll/SConscript index 39b321b6c5..7e7c0f55f7 100644 --- a/components/libc/posix/io/poll/SConscript +++ b/components/libc/posix/io/poll/SConscript @@ -7,7 +7,10 @@ src = [] CPPPATH = [cwd] if GetDepend('RT_USING_POSIX_POLL'): - src += ['poll.c'] + src += ['poll.c'] + +if GetDepend('RT_USING_POSIX_SELECT'): + src += ['select.c'] group = DefineGroup('POSIX', src, depend = [''], CPPPATH = CPPPATH) diff --git a/components/libc/posix/io/select.c b/components/libc/posix/io/poll/select.c similarity index 100% rename from components/libc/posix/io/select.c rename to components/libc/posix/io/poll/select.c diff --git a/components/libc/posix/io/stdio/SConscript b/components/libc/posix/io/stdio/SConscript new file mode 100644 index 0000000000..d33809ce42 --- /dev/null +++ b/components/libc/posix/io/stdio/SConscript @@ -0,0 +1,22 @@ +# RT-Thread building script for component + +import os +from building import * + +src = [] +cwd = GetCurrentDir() +CPPPATH = [cwd] +group = [] + +if GetDepend('RT_USING_POSIX_STDIO'): + src += ['libc.c'] + +group = DefineGroup('POSIX', src, depend = [''], CPPPATH = CPPPATH) + +list = os.listdir(cwd) +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + group = group + SConscript(os.path.join(d, 'SConscript')) + +Return('group') diff --git a/components/libc/posix/io/libc.c b/components/libc/posix/io/stdio/libc.c similarity index 87% rename from components/libc/posix/io/libc.c rename to components/libc/posix/io/stdio/libc.c index e57749f1da..ebdc3a537b 100644 --- a/components/libc/posix/io/libc.c +++ b/components/libc/posix/io/stdio/libc.c @@ -15,9 +15,8 @@ #include #include #include +#include #include "libc.h" -#include -#include int libc_system_init(void) { @@ -108,7 +107,7 @@ int libc_stdio_get_console(void) return -1; } -#else +#elif defined(RT_USING_POSIX_STDIO) #define STDIO_DEVICE_NAME_MAX 32 static int std_fd = -1; int libc_stdio_set_console(const char* device_name, int mode) @@ -136,3 +135,24 @@ int libc_stdio_get_console(void) { return std_fd; } #endif /* defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIB) */ + +int isatty(int fd) +{ +#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) + if(fd == STDOUT_FILENO || fd == STDERR_FILENO) + { + return 1; + } +#endif + +#ifdef RT_USING_POSIX_STDIO + if(fd == STDIN_FILENO) + { + return 1; + } +#endif + + rt_set_errno(ENOTTY); + return 0; +} +RTM_EXPORT(isatty); diff --git a/components/libc/posix/io/libc.h b/components/libc/posix/io/stdio/libc.h similarity index 100% rename from components/libc/posix/io/libc.h rename to components/libc/posix/io/stdio/libc.h diff --git a/components/libc/posix/io/termios/termios.c b/components/libc/posix/io/termios/termios.c index 14d85e9f0c..8333b594bf 100644 --- a/components/libc/posix/io/termios/termios.c +++ b/components/libc/posix/io/termios/termios.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include "termios.h" diff --git a/components/libc/posix/libdl/SConscript b/components/libc/posix/libdl/SConscript index 964e05ef76..7c5f9b8085 100644 --- a/components/libc/posix/libdl/SConscript +++ b/components/libc/posix/libdl/SConscript @@ -1,7 +1,7 @@ from building import * Import('rtconfig') -src = Glob('*.c') + Glob('*.cpp') + Glob('arch/*.c') +src = Glob('*.c') + Glob('arch/*.c') cwd = GetCurrentDir() group = [] CPPPATH = [cwd] diff --git a/components/libc/compilers/gcc/newlib/dlsyms.c b/components/libc/posix/libdl/dlsyms.c similarity index 100% rename from components/libc/compilers/gcc/newlib/dlsyms.c rename to components/libc/posix/libdl/dlsyms.c diff --git a/components/libc/posix/readme.md b/components/libc/posix/readme.md index df01047d6b..9683a02a6a 100644 --- a/components/libc/posix/readme.md +++ b/components/libc/posix/readme.md @@ -4,5 +4,8 @@ This folder provides functions that are not part of the standard C library but a ## NOTE -1. For consistency of compilation results across the different of platforms(gcc, keil, iar) , you better use ``#include `` to instead of ``#include ``. +1. For consistency of compilation results across the different of platforms(gcc, keil, iar) , use: + - `#include ` to instead of `#include ` + - `#include ` to instead of `#include ` + - `#include ` to instead of `#include ` diff --git a/components/libc/posix/src/SConscript b/components/libc/posix/src/SConscript deleted file mode 100644 index 93bb93b0ad..0000000000 --- a/components/libc/posix/src/SConscript +++ /dev/null @@ -1,16 +0,0 @@ -# RT-Thread building script for component - -from building import * - -src = [] -cwd = GetCurrentDir() -CPPPATH = [cwd] -group = [] - -flag = False -src += ['unistd.c'] #TODO - -if flag == True: - group = DefineGroup('POSIX', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/libc/posix/src/unistd.c b/components/libc/posix/src/unistd.c deleted file mode 100644 index cb18dd3499..0000000000 --- a/components/libc/posix/src/unistd.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-09-01 Meco Man first Version - * 2021-02-12 Meco Man move all functions located in to this file - */ - -#include -#include - -#ifdef RT_USING_POSIX_TERMIOS -#include "termios.h" -int isatty(int fd) -{ - struct termios ts; - return(tcgetattr(fd, &ts) != -1); /*true if no error (is a tty)*/ -} -#else -int isatty(int fd) -{ - if (fd >=0 && fd < 3) - { - return 1; - } - else - { - return 0; - } -} -#endif -RTM_EXPORT(isatty); - -char *ttyname(int fd) -{ - return "/dev/tty"; /* TODO: need to add more specific */ -} -RTM_EXPORT(ttyname); From 0f6e2bbf27050abb5113d6d760e5895c7f65c471 Mon Sep 17 00:00:00 2001 From: "Man, Jianting (Meco)" <920369182@qq.com> Date: Mon, 24 Jan 2022 01:20:09 -0500 Subject: [PATCH 48/65] =?UTF-8?q?[kservice]=20rt=5Fshow=5Fversion=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=B9=B4=E4=BB=BD=20(#5552)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kservice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kservice.c b/src/kservice.c index b992c7e6e1..d39d3c614e 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -613,7 +613,7 @@ void rt_show_version(void) rt_kprintf("- RT - Thread Operating System\n"); rt_kprintf(" / | \\ %d.%d.%d build %s %s\n", RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__, __TIME__); - rt_kprintf(" 2006 - 2021 Copyright by rt-thread team\n"); + rt_kprintf(" 2006 - 2022 Copyright by RT-Thread team\n"); } RTM_EXPORT(rt_show_version); From cd72ef6ecb1e5624ee7eaafb93f3b8cce0e17248 Mon Sep 17 00:00:00 2001 From: LeeChunHei Date: Mon, 24 Jan 2022 14:22:48 +0800 Subject: [PATCH 49/65] add pulse encoder porting to imxrt1052 (#4372) --- bsp/imxrt/libraries/MIMXRT1050/SConscript | 7 + bsp/imxrt/libraries/drivers/SConscript | 3 + .../libraries/drivers/drv_pulse_encoder.c | 160 ++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 bsp/imxrt/libraries/drivers/drv_pulse_encoder.c diff --git a/bsp/imxrt/libraries/MIMXRT1050/SConscript b/bsp/imxrt/libraries/MIMXRT1050/SConscript index 75fde95bc1..c774395330 100644 --- a/bsp/imxrt/libraries/MIMXRT1050/SConscript +++ b/bsp/imxrt/libraries/MIMXRT1050/SConscript @@ -75,6 +75,13 @@ if GetDepend(['BSP_USING_DMA']): src += ['MIMXRT1052/drivers/fsl_lpuart_edma.c'] if GetDepend(['BSP_USING_SPI']): src += ['MIMXRT1052/drivers/fsl_lpspi_edma.c'] + +if GetDepend(['BSP_USING_PULSE_ENCODER']): + src += ['MIMXRT1052/drivers/fsl_enc.c'] + +#Adding this as XBAR is used in pin mux +src += ['MIMXRT1052/drivers/fsl_xbara.c'] +src += ['MIMXRT1052/drivers/fsl_xbarb.c'] if rtconfig.CROSS_TOOL == 'gcc': group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, ASFLAGS = '$ASFLAGS -D __STARTUP_CLEAR_BSS') diff --git a/bsp/imxrt/libraries/drivers/SConscript b/bsp/imxrt/libraries/drivers/SConscript index 3328d2af08..eaefd7c5e1 100644 --- a/bsp/imxrt/libraries/drivers/SConscript +++ b/bsp/imxrt/libraries/drivers/SConscript @@ -63,6 +63,9 @@ if GetDepend('BSP_USING_USB_DEVICE'): src += Glob('usb/phy/*.c') CPPDEFINES += ['ENDIANNESS'] +if GetDepend('BSP_USING_PULSE_ENCODER'): + src += ['drv_pulse_encoder.c'] + path = [cwd,cwd + '/config'] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES=CPPDEFINES) diff --git a/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c b/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c new file mode 100644 index 0000000000..c0e5ce27f8 --- /dev/null +++ b/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-23 balanceTWK first version + * 2021-01-19 Leslie Lee port to imxrt series + */ + +#include +#include +#ifdef BSP_USING_PULSE_ENCODER + +#include "fsl_common.h" +#include "fsl_enc.h" + +#define LOG_TAG "drv.pulse_encoder" +#include + +#if !defined(BSP_USING_PULSE_ENCODER1) && !defined(BSP_USING_PULSE_ENCODER2) && !defined(BSP_USING_PULSE_ENCODER3) \ + && !defined(BSP_USING_PULSE_ENCODER4) + #error "Please define at least one BSP_USING_PULSE_ENCODERx" + /* this driver can be disabled at menuconfig → RT-Thread Components → Device Drivers */ +#elif (defined(BSP_USING_PULSE_ENCODER2) || defined(BSP_USING_PULSE_ENCODER3) || defined(BSP_USING_PULSE_ENCODER4)) || defined(SOC_IMXRT1015_SERIES) + #error "IMXRT1015 had only one quadrature decoder module" +#elif (defined(BSP_USING_PULSE_ENCODER3) || defined(BSP_USING_PULSE_ENCODER4)) || defined(SOC_IMXRT1020_SERIES) + #error "IMXRT1020 had only two quadrature decoder module" +#endif + +enum +{ +#ifdef BSP_USING_PULSE_ENCODER1 + PULSE_ENCODER1_INDEX, +#endif +#ifdef BSP_USING_PULSE_ENCODER2 + PULSE_ENCODER2_INDEX, +#endif +#ifdef BSP_USING_PULSE_ENCODER3 + PULSE_ENCODER3_INDEX, +#endif +#ifdef BSP_USING_PULSE_ENCODER4 + PULSE_ENCODER4_INDEX, +#endif +}; + +struct imxrt_pulse_encoder_device +{ + struct rt_pulse_encoder_device pulse_encoder; + ENC_Type *base; + char *name; +}; +typedef struct imxrt_pulse_encoder_device imxrt_pulse_enccoder_device_t; + +static imxrt_pulse_enccoder_device_t imxrt_pulse_encoder_obj[] = +{ +#ifdef BSP_USING_PULSE_ENCODER1 + { + .base = ENC1, + .name = "pulse1" + }, +#endif +#ifdef BSP_USING_PULSE_ENCODER2 + { + .base = ENC2, + .name = "pulse2" + }, +#endif +#ifdef BSP_USING_PULSE_ENCODER3 + { + .base = ENC3, + .name = "pulse3" + }, +#endif +#ifdef BSP_USING_PULSE_ENCODER4 + { + .base = ENC4, + .name = "pulse4" + }, +#endif +}; + + + +rt_err_t pulse_encoder_init(struct rt_pulse_encoder_device *pulse_encoder) +{ + ENC_Type *base = ((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base; + enc_config_t enc_config; + ENC_GetDefaultConfig(&enc_config); + ENC_Init(base, &enc_config); + ENC_DoSoftwareLoadInitialPositionValue(base); /* Update the position counter with initial value. */ + return RT_EOK; +} + +rt_err_t pulse_encoder_clear_count(struct rt_pulse_encoder_device *pulse_encoder) +{ + ENC_SetInitialPositionValue(((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base, 0); + return RT_EOK; +} + +rt_int32_t pulse_encoder_get_count(struct rt_pulse_encoder_device *pulse_encoder) +{ + return (rt_int32_t)ENC_GetPositionValue(((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base); +} + +rt_err_t pulse_encoder_control(struct rt_pulse_encoder_device *pulse_encoder, rt_uint32_t cmd, void *args) +{ + rt_err_t result; + + result = RT_EOK; + + switch (cmd) + { + case PULSE_ENCODER_CMD_ENABLE: + result = pulse_encoder->ops->init(pulse_encoder); + break; + case PULSE_ENCODER_CMD_DISABLE: + ENC_Deinit(((imxrt_pulse_enccoder_device_t *)(pulse_encoder->parent.user_data))->base); + break; + default: + result = -RT_ENOSYS; + break; + } + + return result; +} + +static const struct rt_pulse_encoder_ops _ops = +{ + .init = pulse_encoder_init, + .get_count = pulse_encoder_get_count, + .clear_count = pulse_encoder_clear_count, + .control = pulse_encoder_control, +}; + +int rt_hw_pulse_encoder_init(void) +{ + int i; + int result; + + result = RT_EOK; + for (i = 0; i < sizeof(imxrt_pulse_encoder_obj) / sizeof(imxrt_pulse_encoder_obj[0]); i++) + { + imxrt_pulse_encoder_obj[i].pulse_encoder.type = AB_PHASE_PULSE_ENCODER; + imxrt_pulse_encoder_obj[i].pulse_encoder.ops = &_ops; + imxrt_pulse_encoder_obj[i].pulse_encoder.parent.user_data = &(imxrt_pulse_encoder_obj[i]); + + if (rt_device_pulse_encoder_register(&imxrt_pulse_encoder_obj[i].pulse_encoder, imxrt_pulse_encoder_obj[i].name, &imxrt_pulse_encoder_obj[i]) != RT_EOK) + { + LOG_E("%s register failed", imxrt_pulse_encoder_obj[i].name); + result = -RT_ERROR; + } + } + + return result; +} +INIT_BOARD_EXPORT(rt_hw_pulse_encoder_init); + +#endif \ No newline at end of file From 11d83225d6c773e6c05aa26d1a5f152beb75e5e4 Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Mon, 24 Jan 2022 14:35:50 +0800 Subject: [PATCH 50/65] [remove] useless variable. --- components/libc/compilers/common/time.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/libc/compilers/common/time.c b/components/libc/compilers/common/time.c index a963b25f1a..71755b8bbb 100644 --- a/components/libc/compilers/common/time.c +++ b/components/libc/compilers/common/time.c @@ -852,7 +852,6 @@ int timer_gettime(timer_t timerid, struct itimerspec *its) struct timer_obj *timer = (struct timer_obj *)timerid; rt_tick_t remaining; rt_uint32_t seconds, nanoseconds; - rt_int64_t nsecs, secs; if (timer == NULL) { @@ -918,7 +917,6 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue) { struct timer_obj *timer = (struct timer_obj *)timerid; - rt_uint32_t duration, current; if (timer == NULL || value->it_interval.tv_nsec < 0 || From 3e59cfd70e5bfd9c95ac98a096432b1e9e2d185e Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Mon, 24 Jan 2022 02:04:10 -0500 Subject: [PATCH 51/65] update posix-info.txt --- components/libc/posix-info.txt | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/components/libc/posix-info.txt b/components/libc/posix-info.txt index e5cccbc89b..5b779b1564 100644 --- a/components/libc/posix-info.txt +++ b/components/libc/posix-info.txt @@ -16,8 +16,7 @@ + tolower() + toupper() - -> for gcc, keil, iar platform at the same time; - Suggest to choose + -> Suggesting to use instead of to be compatible with three compilation platforms of IAR Keil GCC at the same time. + errno @@ -138,8 +137,7 @@ + longjmp() + setjmp() - -> for gcc, keil, iar platform at the same time; - Suggest to choose + -> Suggesting to use instead of to be compatible with three compilation platforms of IAR Keil GCC at the same time. + kill() + pthread_kill() + pthread_sigmask() @@ -174,7 +172,7 @@ + fflush() + fgetc() + fgets() -- fileno() ++ fileno() ; GCC and IAR support, but Keil doesn't support - flockfile() + fopen() + fprintf() @@ -285,8 +283,7 @@ + uname() - -> for gcc, keil, iar platform at the same time; - Suggest to choose + -> Suggesting to use instead of to be compatible with three compilation platforms of IAR Keil GCC at the same time. + asctime() + asctime_r() + clock_getres() @@ -309,8 +306,8 @@ + timer_getoverrun() + timer_gettime() + timer_settime() -% tzname ; you should better use 'tz_xxx' in the rt-thread. -% tzset() ; you should better use 'tz_xxx' in the rt-thread. +- tzname ; you should better use 'tz_xxx' in the rt-thread. +- tzset() ; you should better use 'tz_xxx' in the rt-thread. + alarm() From 4db9cfbebe6d66f31d3a851fde82fd20318bfd05 Mon Sep 17 00:00:00 2001 From: thewon86 Date: Mon, 24 Jan 2022 16:52:26 +0800 Subject: [PATCH 52/65] return thread error when resumed by signal --- components/drivers/ipc/waitqueue.c | 7 ++++++- src/ipc.c | 9 +-------- src/thread.c | 11 +++++++++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/components/drivers/ipc/waitqueue.c b/components/drivers/ipc/waitqueue.c index 4c6bb7e97f..6a26604617 100644 --- a/components/drivers/ipc/waitqueue.c +++ b/components/drivers/ipc/waitqueue.c @@ -7,6 +7,7 @@ * Date Author Notes * 2018/06/26 Bernard Fix the wait queue issue when wakeup a soon * to blocked thread. + * 2022-01-24 THEWON let rt_wqueue_wait return thread->error when using signal */ #include @@ -141,6 +142,10 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec) rt_list_init(&__wait.list); level = rt_hw_interrupt_disable(); + + /* reset thread error */ + tid->error = RT_EOK; + if (queue->flag == RT_WQ_FLAG_WAKEUP) { /* already wakeup */ @@ -171,5 +176,5 @@ __exit_wakeup: rt_wqueue_remove(&__wait); - return 0; + return tid->error; } diff --git a/src/ipc.c b/src/ipc.c index aea149a67a..5d4a2d018f 100755 --- a/src/ipc.c +++ b/src/ipc.c @@ -40,6 +40,7 @@ * 2021-01-03 Meco Man implement rt_mb_urgent() * 2021-05-30 Meco Man implement rt_mutex_trytake() * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to ipc.c + * 2022-01-24 THEWON let rt_mutex_take return thread->error when using signal */ #include @@ -947,9 +948,6 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time) } else { -#ifdef RT_USING_SIGNALS -__again: -#endif /* RT_USING_SIGNALS */ /* The value of mutex is 1 in initial status. Therefore, if the * value is great than 0, it indicates the mutex is avaible. */ @@ -1026,11 +1024,6 @@ __again: if (thread->error != RT_EOK) { -#ifdef RT_USING_SIGNALS - /* interrupt by signal, try it again */ - if (thread->error == -RT_EINTR) goto __again; -#endif /* RT_USING_SIGNALS */ - /* return error */ return thread->error; } diff --git a/src/thread.c b/src/thread.c index bf1f2482a9..30208f1dd1 100644 --- a/src/thread.c +++ b/src/thread.c @@ -30,6 +30,7 @@ * 2021-11-15 THEWON Remove duplicate work between idle and _thread_exit * 2021-12-27 Meco Man remove .init_priority * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to thread.c + * 2022-01-24 THEWON let rt_thread_sleep return thread->error when using signal */ #include @@ -566,6 +567,9 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) /* disable interrupt */ temp = rt_hw_interrupt_disable(); + /* reset thread error */ + thread->error = RT_EOK; + /* suspend thread */ rt_thread_suspend(thread); @@ -582,7 +586,7 @@ rt_err_t rt_thread_sleep(rt_tick_t tick) if (thread->error == -RT_ETIMEOUT) thread->error = RT_EOK; - return RT_EOK; + return thread->error; } /** @@ -625,6 +629,9 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) /* disable interrupt */ level = rt_hw_interrupt_disable(); + /* reset thread error */ + thread->error = RT_EOK; + cur_tick = rt_tick_get(); if (cur_tick - *tick < inc_tick) { @@ -657,7 +664,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick) rt_hw_interrupt_enable(level); } - return RT_EOK; + return thread->error; } RTM_EXPORT(rt_thread_delay_until); From 382e19ccbfc73033e76606650d41a36b5cf51b36 Mon Sep 17 00:00:00 2001 From: ChungHsuanChen Date: Mon, 24 Jan 2022 16:36:27 +0800 Subject: [PATCH 53/65] improve and add comments in examples/network/ including tcpserver.c tcpclient.c udpserver.c and udpclient.c Formatting Co-authored-by: Man, Jianting (Meco) <920369182@qq.com> --- examples/network/tcpclient.c | 39 +++++++++++++++++++++-------- examples/network/tcpserver.c | 48 ++++++++++++++++++++++++------------ examples/network/udpclient.c | 32 ++++++++++++++++-------- examples/network/udpserver.c | 30 ++++++++++++++-------- 4 files changed, 103 insertions(+), 46 deletions(-) diff --git a/examples/network/tcpclient.c b/examples/network/tcpclient.c index 8f88985b10..97ea690b6e 100644 --- a/examples/network/tcpclient.c +++ b/examples/network/tcpclient.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes + * 2022-01-24 ChungHsuan improve code comments */ #include @@ -16,7 +17,7 @@ #include #include #endif -#include /* 使用BSD socket,需要包含socket.h头文件 */ +#include /* socket.h header file is needed when using BSD socket */ /* 使用BSD socket,需要包含socket.h头文件 */ #include "netdb.h" #define DEBUG_TCP_CLIENT @@ -35,8 +36,11 @@ static int started = 0; static int is_running = 0; static char url[256]; static int port = 8080; -static const char send_data[] = "This is TCP Client from RT-Thread."; /* 发送用到的数据 */ +static const char send_data[] = "This is TCP Client from RT-Thread."; /* The message be sent */ /* 发送用到的数据 */ +/** +* @brief This function is for creating a tcp client on RT-Thread +*/ static void tcpclient(void *arg) { int ret; @@ -48,7 +52,7 @@ static void tcpclient(void *arg) struct timeval timeout; fd_set readset; - + /* Get host address by parameter url(Domain name resolution if input domain) */ /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(url); if (host == RT_NULL) @@ -56,7 +60,7 @@ static void tcpclient(void *arg) LOG_E("Get host by name failed!"); return; } - + /* Allocate space for recv_data */ /* 分配用于存放接收数据的缓冲 */ recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) @@ -64,24 +68,26 @@ static void tcpclient(void *arg) LOG_E("No memory"); return; } - + /* Create a socket and set it to SOCK_STREAM(TCP) */ /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + /* Failed on creatinf socket */ /* 创建socket失败 */ LOG_E("Create socket error"); goto __exit; } - + /* Initialize server side address */ /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); - + /* Connect to server */ /* 连接到服务端 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { + /*Failed on connecting to server*/ /* 连接失败 */ LOG_E("Connect fail!"); goto __exit; @@ -101,49 +107,56 @@ static void tcpclient(void *arg) /* Wait for read */ if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0) continue; - + /* Receive the maximum size 1024 bytes from socket */ /* 从sock连接中接收最大BUFSZ - 1字节数据 */ bytes_received = recv(sock, recv_data, BUFSZ - 1, 0); if (bytes_received < 0) { + /* Receive failed and close the connection */ /* 接收失败,关闭这个连接 */ LOG_E("Received error, close the socket."); goto __exit; } else if (bytes_received == 0) { + /* Print warning message when recv function return 0 */ /* 打印recv函数返回值为0的警告信息 */ LOG_W("Received warning, recv function return 0."); continue; } else { + /* Receive data sucessfully and append '\0' at the end of message */ /* 有接收到数据,把末端清零 */ recv_data[bytes_received] = '\0'; if (rt_strcmp(recv_data, "q") == 0 || rt_strcmp(recv_data, "Q") == 0) { + /* If the first letter is 'q' or 'Q', close the connection */ /* 如果是首字母是q或Q,关闭这个连接 */ LOG_I("Got a 'q' or 'Q', close the socket."); goto __exit; } else { + /* Show the message in terminal */ /* 在控制终端显示收到的数据 */ LOG_D("Received data = %s", recv_data); } } - + /* Send message to connected socket */ /* 发送数据到sock连接 */ ret = send(sock, send_data, rt_strlen(send_data), 0); if (ret < 0) { + /* Send failed, close the connection */ /* 发送失败,关闭这个连接 */ LOG_I("send error, close the socket."); goto __exit; } else if (ret == 0) { + /* Print warning message when send function return 0 */ /* 打印send函数返回值为0的警告信息 */ LOG_W("Send warning, send function return 0."); } @@ -165,6 +178,9 @@ __exit: return; } +/** +* @brief The usage description of tcp client on rt-Thread +*/ static void usage(void) { rt_kprintf("Usage: tcpclient -h -p \n"); @@ -178,6 +194,9 @@ static void usage(void) rt_kprintf(" --help Print help information\n"); } +/** +* @brief This function is for testing tcp client on rt-Thread +*/ static void tcpclient_test(int argc, char** argv) { rt_thread_t tid; diff --git a/examples/network/tcpserver.c b/examples/network/tcpserver.c index e7438eb6f3..ff89595c15 100644 --- a/examples/network/tcpserver.c +++ b/examples/network/tcpserver.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes + * 2022-01-24 ChungHsuan improve code comments */ #include @@ -16,7 +17,7 @@ #include #include #endif -#include /* 使用BSD socket,需要包含socket.h头文件 */ +#include /* socket.h header file is needed when using BSD socket */ /* 使用BSD socket,需要包含socket.h头文件 */ #include "netdb.h" #define DEBUG_TCP_SERVER @@ -34,12 +35,15 @@ static int started = 0; static int is_running = 0; static int port = 5000; -static const char send_data[] = "This is TCP Server from RT-Thread."; /* 发送用到的数据 */ +static const char send_data[] = "This is TCP Server from RT-Thread."; /* The message be sent */ /* 发送用到的数据 */ +/** +* @brief This function is for creating a tcp server on RT-Thread +*/ static void tcpserv(void *arg) { int ret; - char *recv_data; /* 用于接收的指针,后面会做一次动态分配以请求可用内存 */ + char *recv_data; /* recv_data is a pointer used to receive data */ /* 用于接收的指针,后面会做一次动态分配以请求可用内存 */ int sock, connected, bytes_received; struct sockaddr_in server_addr, client_addr; @@ -47,33 +51,33 @@ static void tcpserv(void *arg) fd_set readset, readset_c; socklen_t sin_size = sizeof(struct sockaddr_in); - recv_data = rt_malloc(BUFSZ + 1); /* 分配接收用的数据缓冲 */ + recv_data = rt_malloc(BUFSZ + 1);/* Allocate space for recv_data */ /* 分配接收用的数据缓冲 */ if (recv_data == RT_NULL) { LOG_E("No memory"); return; } - + /* Before making use of socket, socket should be created first and set the socket created to SOCK_STREAM(TCP) */ /* 一个socket在使用前,需要预先创建出来,指定SOCK_STREAM为TCP的socket */ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { LOG_E("Create socket error"); goto __exit; } - + /* Initialize server side address */ /* 初始化服务端地址 */ server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(port); /* 服务端工作的端口 */ + server_addr.sin_port = htons(port); /*Server side port number*//* 服务端工作的端口 */ server_addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); - + /* Bind socket to server side address */ /* 绑定socket到服务端地址 */ if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { LOG_E("Unable to bind"); goto __exit; } - + /* Listen on socket */ /* 在socket上进行监听 */ if (listen(sock, 10) == -1) { @@ -99,20 +103,21 @@ static void tcpserv(void *arg) /* Wait for read or write */ if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0) continue; - + /* Accept a request from client and the function is blocking */ /* 接受一个客户端连接socket的请求,这个函数调用是阻塞式的 */ connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size); + /* Return the socket connected sucessfully */ /* 返回的是连接成功的socket */ if (connected < 0) { LOG_E("accept connection failed! errno = %d", errno); continue; } - + /* Accept the message which points by client address */ /* 接受返回的client_addr指向了客户端的地址信息 */ LOG_I("I got a connection from (%s , %d)\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); - + /* Handle method of client connection */ /* 客户端连接的处理 */ while (is_running) { @@ -122,7 +127,7 @@ static void tcpserv(void *arg) /* Wait for read or write */ if (select(connected + 1, &readset_c, RT_NULL, RT_NULL, &timeout) == 0) continue; - + /* Receive message from connected socket. Buffer size is 1024 bytes,but it's not guranteed to receive size exactly 1024 */ /* 从connected socket中接收数据,接收buffer是1024大小,但并不一定能够收到1024大小的数据 */ bytes_received = recv(connected, recv_data, BUFSZ, 0); if (bytes_received < 0) @@ -134,16 +139,18 @@ static void tcpserv(void *arg) } else if (bytes_received == 0) { + /* Print warning message when recv function return 0 */ /* 打印recv函数返回值为0的警告信息 */ LOG_W("Received warning, recv function return 0."); continue; } else - { + { /* Receive data sucessfully and append '\0' at the end of message */ /* 有接收到数据,把末端清零 */ recv_data[bytes_received] = '\0'; if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0) { + /* If the first letter is 'q' or 'Q', close the connection */ /* 如果是首字母是q或Q,关闭这个连接 */ LOG_I("Got a 'q' or 'Q', close the connect."); closesocket(connected); @@ -152,6 +159,7 @@ static void tcpserv(void *arg) } else if (strcmp(recv_data, "exit") == 0) { + /* If the message received is 'exit', close the whole server side. */ /* 如果接收的是exit,则关闭整个服务端 */ closesocket(connected); connected = -1; @@ -159,11 +167,12 @@ static void tcpserv(void *arg) } else { + /* Show the message in terminal */ /* 在控制终端显示收到的数据 */ LOG_D("Received data = %s", recv_data); } } - + /* Send message to connected socket */ /* 发送数据到connected socket */ ret = send(connected, send_data, rt_strlen(send_data), 0); if (ret < 0) @@ -175,6 +184,7 @@ static void tcpserv(void *arg) } else if (ret == 0) { + /* Print warning message when send function return 0 */ /* 打印send函数返回值为0的警告信息 */ LOG_W("Send warning, send function return 0."); } @@ -202,6 +212,9 @@ __exit: return; } +/** +* @brief The usage description of tcp server on rt-Thread +*/ static void usage(void) { rt_kprintf("Usage: tcpserver -p \n"); @@ -214,6 +227,9 @@ static void usage(void) rt_kprintf(" --help Print help information\n"); } +/** +* @brief This function is for testing tcp server on rt-Thread +*/ static void tcpserver_test(int argc, char** argv) { rt_thread_t tid; diff --git a/examples/network/udpclient.c b/examples/network/udpclient.c index 1a3f0268af..3ad27c76ff 100644 --- a/examples/network/udpclient.c +++ b/examples/network/udpclient.c @@ -1,15 +1,16 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes + * 2022-01-24 ChungHsuan improve code comments */ #include -#include /* 使用BSD socket,需要包含sockets.h头文件 */ +#include /* socket.h header file is needed when using BSD socket */ /* 使用BSD socket,需要包含sockets.h头文件 */ #include "netdb.h" #define DEBUG_UDP_CLIENT @@ -27,14 +28,17 @@ static int is_running = 0; static char url[256]; static int port = 8080; static int count = 10; -const char send_data[] = "This is UDP Client from RT-Thread.\n"; /* 发送用到的数据 */ +const char send_data[] = "This is UDP Client from RT-Thread.\n";/* The message be sent */ /* 发送用到的数据 */ +/** +* @brief This function is for creating a udp client on RT-Thread +*/ static void udpclient(void *arg) { int sock; struct hostent *host; struct sockaddr_in server_addr; - + /* Get host address by parameter URL (domain name resolution if input domain) */ /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = (struct hostent *) gethostbyname(url); if (host == RT_NULL) @@ -42,14 +46,15 @@ static void udpclient(void *arg) LOG_E("Get host by name failed!"); return; } - + /* Create a socket and set it to SOCK_DGRAM(UDP) */ /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + /* Failed on creatinf socket */ LOG_E("Create socket error"); return; } - + /* Initialize server side address */ /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); @@ -58,17 +63,18 @@ static void udpclient(void *arg) started = 1; is_running = 1; - + /* The total sending number(count) */ /* 总计发送count次数据 */ while (count && is_running) { + /* Send message to server side */ /* 发送数据到服务远端 */ sendto(sock, send_data, rt_strlen(send_data), 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); - + /* Thread sllep for 1 second */ /* 线程休眠一段时间 */ rt_thread_mdelay(1000); - + /* count decrease 1 */ /* 计数值减一 */ count --; } @@ -77,7 +83,7 @@ static void udpclient(void *arg) { LOG_I("UDP client send data finished!"); } - + /* Close the socket */ /* 关闭这个socket */ if (sock >= 0) { @@ -88,6 +94,9 @@ static void udpclient(void *arg) is_running = 0; } +/** +* @brief The usage description of udp client on rt-Thread +*/ static void usage(void) { rt_kprintf("Usage: udpclient -h -p [--cnt] [count]\n"); @@ -102,6 +111,9 @@ static void usage(void) rt_kprintf(" --help Print help information\n"); } +/** +* @brief This function is for testing udp client on rt-Thread +*/ static void udpclient_test(int argc, char** argv) { rt_thread_t tid; diff --git a/examples/network/udpserver.c b/examples/network/udpserver.c index a33a27da10..33442a72ed 100644 --- a/examples/network/udpserver.c +++ b/examples/network/udpserver.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes + * 2022-01-24 ChungHsuan improve code comments */ #include @@ -16,7 +17,7 @@ #include #include #endif -#include /* 使用BSD socket,需要包含socket.h头文件 */ +#include /* socket.h header file is needed when using BSD socket */ /* 使用BSD socket,需要包含socket.h头文件 */ #include "netdb.h" #define DEBUG_UDP_SERVER @@ -35,6 +36,9 @@ static int started = 0; static int is_running = 0; static int port = 5000; +/** +* @brief This function is for creating a udp server on RT-Thread +*/ static void udpserv(void *paramemter) { int sock; @@ -45,7 +49,7 @@ static void udpserv(void *paramemter) struct timeval timeout; fd_set readset; - + /* Allocate space for recv_data */ /* 分配接收用的数据缓冲 */ recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) @@ -53,20 +57,20 @@ static void udpserv(void *paramemter) LOG_E("No memory"); return; } - + /* Create a socket and set it to SOCK_DGRAM(UDP) */ /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { LOG_E("Create socket error"); goto __exit; } - + /* Initialize server side address */ /* 初始化服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); - + /* Bind socket to server side address */ /* 绑定socket到服务端地址 */ if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) @@ -92,7 +96,7 @@ static void udpserv(void *paramemter) /* Wait for read or write */ if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0) continue; - + /* The maximum size received from sock is BUFSZ-1 bytes*/ /* 从sock中收取最大BUFSZ - 1字节数据 */ bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0, (struct sockaddr *)&client_addr, &addr_len); @@ -108,11 +112,11 @@ static void udpserv(void *paramemter) } else { - recv_data[bytes_read] = '\0'; /* 把末端清零 */ - + recv_data[bytes_read] = '\0'; /* Append '\0' at the end of message *//* 把末端清零 */ + /* Output received message */ /* 输出接收的数据 */ LOG_D("Received data = %s", recv_data); - + /* If the message received is 'exit', quit. */ /* 如果接收数据是exit,退出 */ if (strcmp(recv_data, "exit") == 0) { @@ -136,6 +140,9 @@ __exit: is_running = 0; } +/** +* @brief The usage description of udp server on rt-Thread +*/ static void usage(void) { rt_kprintf("Usage: udpserver -p \n"); @@ -148,6 +155,9 @@ static void usage(void) rt_kprintf(" --help Print help information\n"); } +/** +* @brief This function is for testing udp server on rt-Thread +*/ static void udpserver_test(int argc, char** argv) { rt_thread_t tid; From 5a0575e7be1281ebc891a7ff5c4c64a3c405b672 Mon Sep 17 00:00:00 2001 From: brightsally <121477585@qq.com> Date: Tue, 25 Jan 2022 06:35:27 +0000 Subject: [PATCH 54/65] =?UTF-8?q?!428=20[at91sam9260=20platform/interrupt.?= =?UTF-8?q?c=20fix=20"rt=5Finterrupt=5Fdispatch"=20Undefined=20error]=20*?= =?UTF-8?q?=201.=E4=BF=AE=E6=94=B9template.uvproj=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=89=80=E4=BC=B4=E9=9A=8F=E7=9A=84=E6=94=B9=E5=8A=A8=20*=201.?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E9=80=89=E9=A1=B9=E6=8C=87=E5=AE=9AC99?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=EF=BC=8C=E8=A7=A3=E5=86=B3=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E9=94=99=E8=AF=AFdeclaration=20may=20not=20appear=20after=20ex?= =?UTF-8?q?ecutable=20statem=E2=80=A6=20*=201.=E4=BF=AE=E5=A4=8D=E6=89=BE?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E5=87=BD=E6=95=B0rt=5Finterrupt=5Fdispatch?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/at91sam9260/platform/interrupt.c | 22 ++++++++++++++++++++++ bsp/at91sam9260/template.uvopt | 13 +++++++++++-- bsp/at91sam9260/template.uvproj | 22 +++++++++++++++++----- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/bsp/at91sam9260/platform/interrupt.c b/bsp/at91sam9260/platform/interrupt.c index dc98fe7c4d..60c4d0790b 100644 --- a/bsp/at91sam9260/platform/interrupt.c +++ b/bsp/at91sam9260/platform/interrupt.c @@ -396,6 +396,28 @@ void rt_hw_interrupt_ack(rt_uint32_t fiq_irq, rt_uint32_t id) at91_sys_write(AT91_AIC_EOICR, 0x0); } +void rt_interrupt_dispatch(rt_uint32_t fiq_irq) +{ + rt_isr_handler_t isr_func; + rt_uint32_t irq; + void *param; + + /* get irq number */ + irq = rt_hw_interrupt_get_active(fiq_irq); + + /* get interrupt service routine */ + isr_func = irq_desc[irq].handler; + param = irq_desc[irq].param; + + /* turn to interrupt service routine */ + isr_func(irq, param); + + rt_hw_interrupt_ack(fiq_irq, irq); +#ifdef RT_USING_INTERRUPT_INFO + irq_desc[irq].counter ++; +#endif +} + #ifdef RT_USING_FINSH #ifdef RT_USING_INTERRUPT_INFO void list_irq(void) diff --git a/bsp/at91sam9260/template.uvopt b/bsp/at91sam9260/template.uvopt index 2dca5102b8..7454a3661d 100644 --- a/bsp/at91sam9260/template.uvopt +++ b/bsp/at91sam9260/template.uvopt @@ -13,6 +13,7 @@ *.txt; *.h; *.inc *.plm *.cpp + 0 @@ -31,6 +32,7 @@ 1 1 0 + 0 1 @@ -108,10 +110,10 @@ 1 1 1 - 1 0 0 - 5 + 1 + 18 @@ -168,6 +170,13 @@ + 0 + 0 + 0 + + + + diff --git a/bsp/at91sam9260/template.uvproj b/bsp/at91sam9260/template.uvproj index c644bc5440..6e4ee85615 100644 --- a/bsp/at91sam9260/template.uvproj +++ b/bsp/at91sam9260/template.uvproj @@ -72,14 +72,18 @@ 0 0 + 0 + 0 - 0 + 1 0 - + fromelf.exe --bin -o $L@L.bin #L 0 0 + 0 + 0 0 @@ -141,10 +145,9 @@ 1 1 1 - 1 0 - 5 + 18 @@ -224,6 +227,7 @@ 0 0 0 + 0 3 3 0 @@ -356,8 +360,15 @@ 2 0 0 - 0 + 1 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 RT_USING_INTERRUPT_INFO @@ -375,6 +386,7 @@ 0 0 0 + 0 From 5a0fea69877922bf6e06b7da0abfbf128b8b842c Mon Sep 17 00:00:00 2001 From: "Man, Jianting (Meco)" <920369182@qq.com> Date: Tue, 25 Jan 2022 02:00:47 -0500 Subject: [PATCH 55/65] =?UTF-8?q?[Kconfig][libcpu]=20=E5=A2=9E=E5=8A=A0ARC?= =?UTF-8?q?H=5FCPU=5FBIG=5FENDIAN=20(#5547)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [cpu] 增加ARCH_CPU_BIG_ENDIAN - 之前RT_USING_BIG_ENDIAN的命名并不合理,予以替换为ARCH_CPU_BIG_ENDIAN - 删除一处多余的ARCH_CPU_64BIT - 整理了libcpu/Kconfig的格式 * [libcpu][Kconfig] Cortex-M4&7 select ARCH_ARM_CORTEX_FPU * revert last commit --- components/net/lwip-1.4.1/src/arch/include/arch/cc.h | 4 ++-- components/net/lwip-2.0.3/src/arch/include/arch/cc.h | 4 ++-- components/net/lwip-2.1.2/src/arch/include/arch/cc.h | 4 ++-- libcpu/Kconfig | 8 ++++---- src/Kconfig | 4 ---- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h index 50248b9863..4679777257 100644 --- a/components/net/lwip-1.4.1/src/arch/include/arch/cc.h +++ b/components/net/lwip-1.4.1/src/arch/include/arch/cc.h @@ -41,11 +41,11 @@ #include #ifndef BYTE_ORDER -#ifdef RT_USING_BIG_ENDIAN +#ifdef ARCH_CPU_BIG_ENDIAN #define BYTE_ORDER BIG_ENDIAN #else #define BYTE_ORDER LITTLE_ENDIAN -#endif /* RT_USING_BIG_ENDIAN */ +#endif /* ARCH_CPU_BIG_ENDIAN */ #endif /* BYTE_ORDER */ typedef uint8_t u8_t; diff --git a/components/net/lwip-2.0.3/src/arch/include/arch/cc.h b/components/net/lwip-2.0.3/src/arch/include/arch/cc.h index be5d406f50..ad029e8999 100644 --- a/components/net/lwip-2.0.3/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.0.3/src/arch/include/arch/cc.h @@ -40,11 +40,11 @@ #include #ifndef BYTE_ORDER -#ifdef RT_USING_BIG_ENDIAN +#ifdef ARCH_CPU_BIG_ENDIAN #define BYTE_ORDER BIG_ENDIAN #else #define BYTE_ORDER LITTLE_ENDIAN -#endif /* RT_USING_BIG_ENDIAN */ +#endif /* ARCH_CPU_BIG_ENDIAN */ #endif /* BYTE_ORDER */ #define U16_F "hu" diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h index ea201be28a..e54b0a7ae7 100644 --- a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -40,11 +40,11 @@ #include #ifndef BYTE_ORDER -#ifdef RT_USING_BIG_ENDIAN +#ifdef ARCH_CPU_BIG_ENDIAN #define BYTE_ORDER BIG_ENDIAN #else #define BYTE_ORDER LITTLE_ENDIAN -#endif /* RT_USING_BIG_ENDIAN */ +#endif /* ARCH_CPU_BIG_ENDIAN */ #endif /* BYTE_ORDER */ #define U16_F "hu" diff --git a/libcpu/Kconfig b/libcpu/Kconfig index d0fa40d1bd..9e6acdf70e 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -1,6 +1,9 @@ config ARCH_CPU_64BIT bool +config ARCH_CPU_BIG_ENDIAN + bool + config ARCH_ARM bool @@ -101,10 +104,7 @@ config ARCH_MIPS config ARCH_MIPS64 bool - select ARCH_CPU_64BIT - -config ARCH_CPU_64BIT - bool + select ARCH_CPU_64BIT config ARCH_MIPS_XBURST bool diff --git a/src/Kconfig b/src/Kconfig index 69edd20641..6dc73bc400 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -8,10 +8,6 @@ config RT_NAME_MAX Each kernel object, such as thread, timer, semaphore etc, has a name, the RT_NAME_MAX is the maximal size of this object name. -config RT_USING_BIG_ENDIAN - bool - default n - config RT_USING_ARCH_DATA_TYPE bool "Use the data types defined in ARCH_CPU" default n From e272d042190817dc8e77a9ffe4b83ce39d03f5d8 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Tue, 25 Jan 2022 19:03:07 +0800 Subject: [PATCH 56/65] [nuvoton] Sync to 4.1.0. 1. Remove dfs_posix.h including for syncing 4.1.0. 2. Fix issue in crypto driver. 3. Add LVGLv81 supporting in NuMaker-M2354 BSP. 4. Update USB board menu in M480 BSP. --- .../libraries/m2354/rtt_port/drv_crc.c | 12 +- .../libraries/m2354/rtt_port/drv_crypto.c | 187 ++++++++++-------- .../libraries/m2354/rtt_port/drv_sdh.c | 12 +- .../libraries/m2354/rtt_port/drv_trng.c | 6 +- bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c | 8 +- .../libraries/m480/rtt_port/drv_crypto.c | 182 +++++++---------- bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c | 12 +- .../libraries/m480/rtt_port/drv_trng.c | 6 +- .../libraries/n9h30/rtt_port/drv_adc_touch.c | 6 +- .../libraries/n9h30/rtt_port/drv_sdh.c | 12 +- .../nu_packages/ILI9341/lcd_ili9341.c | 17 +- .../libraries/nuc980/rtt_port/drv_adc_touch.c | 6 +- .../libraries/nuc980/rtt_port/drv_crypto.c | 14 +- .../libraries/nuc980/rtt_port/drv_sdh.c | 12 +- .../applications/lvgl/lv_port_disp.c | 17 +- bsp/nuvoton/nk-980iot/applications/mnt.c | 12 +- bsp/nuvoton/nk-n9h30/.config | 4 +- bsp/nuvoton/nk-n9h30/applications/mnt.c | 12 +- bsp/nuvoton/nk-rtu980/applications/mnt.c | 12 +- bsp/nuvoton/numaker-iot-m487/.config | 42 ++-- .../numaker-iot-m487/applications/mnt.c | 12 +- bsp/nuvoton/numaker-iot-m487/board/Kconfig | 69 ++++--- bsp/nuvoton/numaker-m032ki/applications/mnt.c | 12 +- .../numaker-m2354/applications/SConscript | 12 +- .../applications/lvgl/SConscript | 10 + .../numaker-m2354/applications/lvgl/lv_conf.h | 28 +++ .../numaker-m2354/applications/lvgl/lv_demo.c | 49 +++++ .../applications/lvgl/lv_port_disp.c | 99 ++++++++++ .../applications/lvgl/lv_port_disp.h | 23 +++ .../applications/lvgl/lv_port_indev.c | 57 ++++++ .../applications/lvgl/lv_port_indev.h | 28 +++ bsp/nuvoton/numaker-m2354/board/Kconfig | 31 +++ .../board/NuPinConfig/nutool_pincfg.c | 7 + bsp/nuvoton/numaker-m2354/board/board_dev.c | 26 +++ bsp/nuvoton/numaker-pfm-m487/.config | 11 +- .../numaker-pfm-m487/applications/mnt.c | 12 +- bsp/nuvoton/numaker-pfm-m487/board/Kconfig | 67 ++++--- 37 files changed, 747 insertions(+), 397 deletions(-) create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/SConscript create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/lv_conf.h create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/lv_demo.c create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.c create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.h create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.c create mode 100644 bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.h diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c index 5e82c82367..48b91099f1 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crc.c @@ -44,8 +44,10 @@ static rt_uint32_t nu_crc_run( { uint32_t u32CalChecksum = 0; uint32_t i = 0; + rt_err_t result; - rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER); + result = rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); /* Configure CRC controller */ CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_CPU_WDATA_8); @@ -85,7 +87,9 @@ static rt_uint32_t nu_crc_run( /* Get checksum value */ u32CalChecksum = CRC_GetChecksum(); - rt_mutex_release(&s_CRC_mutex); + + result = rt_mutex_release(&s_CRC_mutex); + RT_ASSERT(result == RT_EOK); return u32CalChecksum; } @@ -93,9 +97,7 @@ static rt_uint32_t nu_crc_run( rt_err_t nu_crc_init(void) { SYS_ResetModule(CRC_RST); - - rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); - return RT_EOK; + return rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); } rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length) diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c index 91f1d26819..543ac7f521 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_crypto.c @@ -37,7 +37,6 @@ typedef struct uint32_t u32BlockSize; } S_SHA_CONTEXT; - /* Private functions ------------------------------------------------------------*/ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx); static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx); @@ -67,57 +66,32 @@ static struct rt_mutex s_SHA_mutex; #if !defined(BSP_USING_TRNG) static struct rt_mutex s_PRNG_mutex; - static volatile int s_PRNG_done; #endif -static volatile int s_AES_done; -static volatile int s_SHA_done; - static rt_err_t nu_crypto_init(void) { - /* Enable Crypto engine interrupt */ - NVIC_EnableIRQ(CRPT_IRQn); + rt_err_t result = RT_EOK; + /* init cipher mutex */ +#if defined(RT_HWCRYPTO_USING_AES) + result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); + RT_ASSERT(result == RT_EOK); AES_ENABLE_INT(CRPT); +#endif + +#if defined(RT_HWCRYPTO_USING_SHA1) || defined(RT_HWCRYPTO_USING_SHA2) + result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); + RT_ASSERT(result == RT_EOK); SHA_ENABLE_INT(CRPT); +#endif - //init cipher mutex - rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); - rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); -#if !defined(BSP_USING_TRNG) +#if defined(RT_HWCRYPTO_USING_RNG) && !defined(BSP_USING_TRNG) + result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); + RT_ASSERT(result == RT_EOK); PRNG_ENABLE_INT(CRPT); - rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); #endif - return RT_EOK; -} - -//Crypto engine IRQ handler -void CRPT_IRQHandler() -{ - if (AES_GET_INT_FLAG(CRPT)) - { - if (CRPT->INTSTS & (CRPT_INTSTS_AESEIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk | (0x1ul << 21)))) - rt_kprintf("AES ERROR\n"); - s_AES_done = 1; - AES_CLR_INT_FLAG(CRPT); - } - - if (SHA_GET_INT_FLAG(CRPT)) - { - if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk | (0x1ul << 9)))) - rt_kprintf("SHA ERROR\n"); - s_SHA_done = 1; - SHA_CLR_INT_FLAG(CRPT); - } - -#if !defined(BSP_USING_TRNG) - if (PRNG_GET_INT_FLAG(CRPT)) - { - s_PRNG_done = 1; - PRNG_CLR_INT_FLAG(CRPT); - } -#endif + return result; } static rt_err_t nu_aes_crypt_run( @@ -133,6 +107,7 @@ static rt_err_t nu_aes_crypt_run( { uint32_t au32SwapKey[8]; uint32_t au32SwapIV[4]; + rt_err_t result; au32SwapKey[0] = nu_get32_be(&pu8Key[0]); au32SwapKey[1] = nu_get32_be(&pu8Key[4]); @@ -156,22 +131,34 @@ static rt_err_t nu_aes_crypt_run( au32SwapIV[2] = nu_get32_be(&pu8IV[8]); au32SwapIV[3] = nu_get32_be(&pu8IV[12]); - rt_mutex_take(&s_AES_mutex, RT_WAITING_FOREVER); + result = rt_mutex_take(&s_AES_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); //Using Channel 0 AES_Open(CRPT, 0, bEncrypt, u32OpMode, u32KeySize, AES_IN_OUT_SWAP); - AES_SetKey(CRPT, 0, (uint32_t *)au32SwapKey, u32KeySize); + AES_SetKey(CRPT, 0, (uint32_t *)&au32SwapKey[0], u32KeySize); AES_SetInitVect(CRPT, 0, (uint32_t *)au32SwapIV); //Setup AES DMA AES_SetDMATransfer(CRPT, 0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen); AES_CLR_INT_FLAG(CRPT); - //Start AES encryption/decryption - s_AES_done = 0; - AES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT); - while (!s_AES_done) {}; - rt_mutex_release(&s_AES_mutex); + /* Start AES encryption/decryption */ + AES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT); + + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTEN_AESIEN_Msk)) {}; + + if ((u32DataLen % 16) && (CRPT->AES_STS & (CRPT_AES_STS_OUTBUFEMPTY_Msk | CRPT_AES_STS_INBUFEMPTY_Msk))) + rt_kprintf("AES WARNING - AES Data length(%d) is not enough. -> %d \n", u32DataLen, RT_ALIGN(u32DataLen, 16)); + else if (CRPT->INTSTS & (CRPT_INTSTS_AESEIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk))) + rt_kprintf("AES ERROR - CRPT->INTSTS-%08x, CRPT->AES_STS-%08x\n", CRPT->INTSTS, CRPT->AES_STS); + + /* Clear AES interrupt status */ + AES_CLR_INT_FLAG(CRPT); + + result = rt_mutex_release(&s_AES_mutex); + RT_ASSERT(result == RT_EOK); return RT_EOK; } @@ -180,28 +167,38 @@ static rt_err_t nu_aes_crypt_run( //Using PRNG instead of TRNG static void nu_prng_open(uint32_t u32Seed) { - rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + rt_err_t result; - //Open PRNG 128 bits. But always return 32 bits + result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); + + //Open PRNG 128 bits. PRNG_Open(CRPT, PRNG_KEY_SIZE_128, PRNG_SEED_RELOAD, u32Seed); - rt_mutex_release(&s_PRNG_mutex); + result = rt_mutex_release(&s_PRNG_mutex); + RT_ASSERT(result == RT_EOK); } static rt_uint32_t nu_prng_run(void) { - uint32_t au32RNGValue[2]; + uint32_t au32RNGValue[4]; + rt_err_t result; - rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); - s_PRNG_done = 0; PRNG_Start(CRPT); - while (!s_PRNG_done) {}; + while ((CRPT->PRNG_CTL & CRPT_PRNG_CTL_BUSY_Msk)) {}; - PRNG_Read(CRPT, au32RNGValue); + /* Clear PRNG interrupt status */ + PRNG_CLR_INT_FLAG(CRPT); - rt_mutex_release(&s_PRNG_mutex); - return au32RNGValue[0]; + PRNG_Read(CRPT, &au32RNGValue[0]); + + result = rt_mutex_release(&s_PRNG_mutex); + RT_ASSERT(result == RT_EOK); + + return au32RNGValue[0] ^ au32RNGValue[1] ^ au32RNGValue[2] ^ au32RNGValue[3]; } #endif @@ -214,6 +211,8 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw unsigned char in_align_flag = 0; unsigned char out_align_flag = 0; unsigned char iv_temp[16]; + RT_ASSERT(symmetric_ctx != RT_NULL); + RT_ASSERT(symmetric_info != RT_NULL); if ((symmetric_info->length % 4) != 0) { @@ -336,18 +335,23 @@ static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32 //Setup SHA DMA SHA_SetDMATransfer(CRPT, u32SrcAddr, u32Len); - SHA_CLR_INT_FLAG(CRPT); - - //Start SHA - s_SHA_done = 0; if (u32Mode == CRYPTO_DMA_FIRST) CRPT->HMAC_CTL |= CRPT_HMAC_CTL_DMAFIRST_Msk; else CRPT->HMAC_CTL &= ~CRPT_HMAC_CTL_DMAFIRST_Msk; + //Start SHA + SHA_CLR_INT_FLAG(CRPT); SHA_Start(CRPT, u32Mode); - while (!s_SHA_done) {}; + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTSTS_HMACIF_Msk)) {}; + + if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk))) + rt_kprintf("SHA ERROR - CRPT->INTSTS-%08x, CRPT->HMAC_STS-%08x\n", CRPT->INTSTS, CRPT->HMAC_STS); + + /* Clear SHA interrupt status */ + SHA_CLR_INT_FLAG(CRPT); } static rt_err_t nu_sha_hash_run( @@ -357,12 +361,18 @@ static rt_err_t nu_sha_hash_run( uint32_t u32DataLen ) { - rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER); + rt_err_t result; + + RT_ASSERT(psSHACtx != RT_NULL); + RT_ASSERT(pu8InData != RT_NULL); + + result = rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); uint8_t *pu8SrcAddr = (uint8_t *)pu8InData; uint32_t u32CopyLen = 0; - while ((psSHACtx->u32SHATempBufLen + u32DataLen) >= psSHACtx->u32BlockSize) + while ((psSHACtx->u32SHATempBufLen + u32DataLen) > psSHACtx->u32BlockSize) { if (psSHACtx->pu8SHATempBuf) { @@ -397,7 +407,8 @@ static rt_err_t nu_sha_hash_run( if (psSHACtx->pu8SHATempBuf == RT_NULL) { LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); - rt_mutex_release(&s_SHA_mutex); + result = rt_mutex_release(&s_SHA_mutex); + RT_ASSERT(result == RT_EOK); return -RT_ENOMEM; } @@ -425,7 +436,8 @@ static rt_err_t nu_sha_hash_run( if (psSHACtx->pu8SHATempBuf == RT_NULL) { LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); - rt_mutex_release(&s_SHA_mutex); + result = rt_mutex_release(&s_SHA_mutex); + RT_ASSERT(result == RT_EOK); return -RT_ENOMEM; } @@ -436,7 +448,8 @@ static rt_err_t nu_sha_hash_run( psSHACtx->u32SHATempBufLen += u32DataLen; } - rt_mutex_release(&s_SHA_mutex); + result = rt_mutex_release(&s_SHA_mutex); + RT_ASSERT(result == RT_EOK); return RT_EOK; } @@ -446,6 +459,8 @@ static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t * uint32_t u32SHAOpMode; unsigned char *nu_in; unsigned char in_align_flag = 0; + RT_ASSERT(hash_ctx != RT_NULL); + RT_ASSERT(in != RT_NULL); //Select SHA operation mode switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) @@ -500,7 +515,11 @@ static rt_err_t nu_sha_finish(struct hwcrypto_hash *hash_ctx, rt_uint8_t *out, r unsigned char *nu_out; unsigned char out_align_flag = 0; uint32_t u32SHAOpMode; - S_SHA_CONTEXT *psSHACtx = hash_ctx->parent.contex; + S_SHA_CONTEXT *psSHACtx = RT_NULL; + RT_ASSERT(hash_ctx != RT_NULL); + RT_ASSERT(out != RT_NULL); + + psSHACtx = hash_ctx->parent.contex; //Check SHA Hash value buffer length switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) @@ -639,6 +658,7 @@ static const struct hwcrypto_rng_ops nu_rng_ops = static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) { rt_err_t res = RT_EOK; + RT_ASSERT(ctx != RT_NULL); switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK) { @@ -672,18 +692,6 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) } case HWCRYPTO_TYPE_SHA1: - { - ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT)); - - if (ctx->contex == RT_NULL) - return -RT_ERROR; - - rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT)); - //Setup SHA1 operation - ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops; - break; - } - case HWCRYPTO_TYPE_SHA2: { ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT)); @@ -692,7 +700,7 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) return -RT_ERROR; rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT)); - //Setup SHA2 operation + //Setup operation ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops; break; } @@ -718,11 +726,15 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) break; } + nu_hwcrypto_reset(ctx); + return res; } static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx) { + RT_ASSERT(ctx != RT_NULL); + if (ctx->contex) rt_free(ctx->contex); } @@ -730,6 +742,8 @@ static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx) static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) { rt_err_t res = RT_EOK; + RT_ASSERT(des != RT_NULL); + RT_ASSERT(src != RT_NULL); if (des->contex && src->contex) { @@ -791,6 +805,7 @@ static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx) int nu_hwcrypto_device_init(void) { + rt_err_t result; static struct rt_hwcrypto_device nu_hwcrypto_dev; nu_hwcrypto_dev.ops = &nu_hwcrypto_ops; @@ -809,11 +824,9 @@ int nu_hwcrypto_device_init(void) nu_trng_init(); #endif - // register hwcrypto operation - if (rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME) != RT_EOK) - { - return -1; - } + /* register hwcrypto operation */ + result = rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME); + RT_ASSERT(result == RT_EOK); return 0; } diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c index 38086cb2d5..1ab43b4989 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c @@ -20,12 +20,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c index 485ff8fea2..e6c0d514c4 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_trng.c @@ -71,10 +71,8 @@ rt_uint32_t nu_trng_rand(struct hwcrypto_rng *ctx) { if (!s_i32TRNGEnable) { - uint32_t u32RNGValue; - //use software rand - u32RNGValue = rand(); - return u32RNGValue; + /* Use software rand */ + return (rt_uint32_t)rand(); } return nu_trng_run(); diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c index 3eb2a19356..64a3595d91 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crc.c @@ -96,14 +96,8 @@ static rt_uint32_t nu_crc_run( rt_err_t nu_crc_init(void) { - rt_err_t result; - SYS_ResetModule(CRC_RST); - - result = rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); - RT_ASSERT(result == RT_EOK); - - return RT_EOK; + return rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO); } rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length) diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c index eda0392c53..6cb252068f 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_crypto.c @@ -30,7 +30,6 @@ #endif /* Private typedef --------------------------------------------------------------*/ - typedef struct { uint8_t *pu8SHATempBuf; @@ -72,76 +71,38 @@ static struct rt_mutex s_SHA_mutex; #if !defined(BSP_USING_TRNG) static struct rt_mutex s_PRNG_mutex; - static volatile int s_PRNG_done; #endif -static volatile int s_AES_done; -static volatile int s_TDES_done; -static volatile int s_SHA_done; - static rt_err_t nu_crypto_init(void) { - rt_err_t result; + rt_err_t result = RT_EOK; - /* Enable Crypto engine interrupt */ - NVIC_EnableIRQ(CRPT_IRQn); - - AES_ENABLE_INT(CRPT); - TDES_ENABLE_INT(CRPT); - SHA_ENABLE_INT(CRPT); - - //init cipher mutex + /* init cipher mutex */ +#if defined(RT_HWCRYPTO_USING_AES) result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); + AES_ENABLE_INT(CRPT); +#endif +#if defined(RT_HWCRYPTO_USING_3DES) result = rt_mutex_init(&s_TDES_mutex, NU_HWCRYPTO_TDES_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); + TDES_ENABLE_INT(CRPT); +#endif +#if defined(RT_HWCRYPTO_USING_SHA1) || defined(RT_HWCRYPTO_USING_SHA2) result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); + SHA_ENABLE_INT(CRPT); +#endif -#if !defined(BSP_USING_TRNG) - PRNG_ENABLE_INT(CRPT); +#if defined(RT_HWCRYPTO_USING_RNG) && !defined(BSP_USING_TRNG) result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO); RT_ASSERT(result == RT_EOK); + PRNG_ENABLE_INT(CRPT); #endif - return RT_EOK; -} - -//Crypto engine IRQ handler - -void CRYPTO_IRQHandler() -{ - if (AES_GET_INT_FLAG(CRPT)) - { - if (CRPT->INTSTS & (CRPT_INTSTS_AESEIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk | (0x1ul << 21)))) - rt_kprintf("AES ERROR\n"); - s_AES_done = 1; - AES_CLR_INT_FLAG(CRPT); - } - - if (TDES_GET_INT_FLAG(CRPT)) - { - s_TDES_done = 1; - TDES_CLR_INT_FLAG(CRPT); - } - - if (SHA_GET_INT_FLAG(CRPT)) - { - if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk | (0x1ul << 9)))) - rt_kprintf("SHA ERROR\n"); - s_SHA_done = 1; - SHA_CLR_INT_FLAG(CRPT); - } - -#if !defined(BSP_USING_TRNG) - if (PRNG_GET_INT_FLAG(CRPT)) - { - s_PRNG_done = 1; - PRNG_CLR_INT_FLAG(CRPT); - } -#endif + return result; } static rt_err_t nu_aes_crypt_run( @@ -155,10 +116,9 @@ static rt_err_t nu_aes_crypt_run( uint32_t u32DataLen ) { - rt_err_t result; - uint32_t au32SwapKey[8]; uint32_t au32SwapIV[4]; + rt_err_t result; au32SwapKey[0] = nu_get32_be(&pu8Key[0]); au32SwapKey[1] = nu_get32_be(&pu8Key[4]); @@ -187,16 +147,26 @@ static rt_err_t nu_aes_crypt_run( //Using Channel 0 AES_Open(CRPT, 0, bEncrypt, u32OpMode, u32KeySize, AES_IN_OUT_SWAP); - AES_SetKey(CRPT, 0, (uint32_t *)au32SwapKey, u32KeySize); + AES_SetKey(CRPT, 0, (uint32_t *)&au32SwapKey[0], u32KeySize); AES_SetInitVect(CRPT, 0, (uint32_t *)au32SwapIV); //Setup AES DMA AES_SetDMATransfer(CRPT, 0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen); AES_CLR_INT_FLAG(CRPT); - //Start AES encryption/decryption - s_AES_done = 0; + + /* Start AES encryption/decryption */ AES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT); - while (!s_AES_done) {}; + + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTEN_AESIEN_Msk)) {}; + + if ((u32DataLen % 16) && (CRPT->AES_STS & (CRPT_AES_STS_OUTBUFEMPTY_Msk | CRPT_AES_STS_INBUFEMPTY_Msk))) + rt_kprintf("AES WARNING - AES Data length(%d) is not enough. -> %d \n", u32DataLen, RT_ALIGN(u32DataLen, 16)); + else if (CRPT->INTSTS & (CRPT_INTSTS_AESEIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk))) + rt_kprintf("AES ERROR - CRPT->INTSTS-%08x, CRPT->AES_STS-%08x\n", CRPT->INTSTS, CRPT->AES_STS); + + /* Clear AES interrupt status */ + AES_CLR_INT_FLAG(CRPT); result = rt_mutex_release(&s_AES_mutex); RT_ASSERT(result == RT_EOK); @@ -213,32 +183,33 @@ static void nu_prng_open(uint32_t u32Seed) result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); RT_ASSERT(result == RT_EOK); - //Open PRNG 64 bits. But always return 32 bits + //Open PRNG 64 bits. PRNG_Open(CRPT, PRNG_KEY_SIZE_64, PRNG_SEED_RELOAD, u32Seed); result = rt_mutex_release(&s_PRNG_mutex); RT_ASSERT(result == RT_EOK); - } static rt_uint32_t nu_prng_run(void) { - rt_err_t result; uint32_t au32RNGValue[2]; + rt_err_t result; result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); RT_ASSERT(result == RT_EOK); - s_PRNG_done = 0; PRNG_Start(CRPT); - while (!s_PRNG_done) {}; + while ((CRPT->PRNG_CTL & CRPT_PRNG_CTL_BUSY_Msk)) {}; - PRNG_Read(CRPT, au32RNGValue); + /* Clear PRNG interrupt status */ + PRNG_CLR_INT_FLAG(CRPT); + + PRNG_Read(CRPT, &au32RNGValue[0]); result = rt_mutex_release(&s_PRNG_mutex); RT_ASSERT(result == RT_EOK); - return au32RNGValue[0]; + return au32RNGValue[0] ^ au32RNGValue[1]; } #endif @@ -251,6 +222,8 @@ static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hw unsigned char in_align_flag = 0; unsigned char out_align_flag = 0; unsigned char iv_temp[16]; + RT_ASSERT(symmetric_ctx != RT_NULL); + RT_ASSERT(symmetric_info != RT_NULL); if ((symmetric_info->length % 4) != 0) { @@ -408,10 +381,11 @@ static rt_err_t nu_des_crypt_run( //Setup TDES DMA TDES_SetDMATransfer(CRPT, 0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen); TDES_CLR_INT_FLAG(CRPT); + //Start TDES encryption/decryption - s_TDES_done = 0; TDES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT); - while (!s_TDES_done) {}; + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTEN_TDESIEN_Msk)) {}; result = rt_mutex_release(&s_TDES_mutex); RT_ASSERT(result == RT_EOK); @@ -521,10 +495,6 @@ static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32 //Setup SHA DMA SHA_SetDMATransfer(CRPT, u32SrcAddr, u32Len); - SHA_CLR_INT_FLAG(CRPT); - - //Start SHA - s_SHA_done = 0; if (u32Mode == CRYPTO_DMA_FIRST) { @@ -547,10 +517,18 @@ static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32 CRPT->HMAC_CTL &= ~CRPT_HMAC_CTL_DMAFIRST_Msk; } } - + //Start SHA + SHA_CLR_INT_FLAG(CRPT); SHA_Start(CRPT, u32Mode); - while (!s_SHA_done) {}; + /* Wait done */ + while (!(CRPT->INTSTS & CRPT_INTSTS_HMACIF_Msk)) {}; + + if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk))) + rt_kprintf("SHA ERROR - CRPT->INTSTS-%08x, CRPT->HMAC_STS-%08x\n", CRPT->INTSTS, CRPT->HMAC_STS); + + /* Clear SHA interrupt status */ + SHA_CLR_INT_FLAG(CRPT); } static rt_err_t nu_sha_hash_run( @@ -562,6 +540,9 @@ static rt_err_t nu_sha_hash_run( { rt_err_t result; + RT_ASSERT(psSHACtx != RT_NULL); + RT_ASSERT(pu8InData != RT_NULL); + result = rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER); RT_ASSERT(result == RT_EOK); @@ -603,10 +584,8 @@ static rt_err_t nu_sha_hash_run( if (psSHACtx->pu8SHATempBuf == RT_NULL) { LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); - result = rt_mutex_release(&s_SHA_mutex); RT_ASSERT(result == RT_EOK); - return -RT_ENOMEM; } @@ -634,10 +613,8 @@ static rt_err_t nu_sha_hash_run( if (psSHACtx->pu8SHATempBuf == RT_NULL) { LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize); - result = rt_mutex_release(&s_SHA_mutex); RT_ASSERT(result == RT_EOK); - return -RT_ENOMEM; } @@ -659,6 +636,8 @@ static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t * uint32_t u32SHAOpMode; unsigned char *nu_in; unsigned char in_align_flag = 0; + RT_ASSERT(hash_ctx != RT_NULL); + RT_ASSERT(in != RT_NULL); //Select SHA operation mode switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) @@ -713,7 +692,11 @@ static rt_err_t nu_sha_finish(struct hwcrypto_hash *hash_ctx, rt_uint8_t *out, r unsigned char *nu_out; unsigned char out_align_flag = 0; uint32_t u32SHAOpMode; - S_SHA_CONTEXT *psSHACtx = hash_ctx->parent.contex; + S_SHA_CONTEXT *psSHACtx = RT_NULL; + RT_ASSERT(hash_ctx != RT_NULL); + RT_ASSERT(out != RT_NULL); + + psSHACtx = hash_ctx->parent.contex; //Check SHA Hash value buffer length switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK)) @@ -857,6 +840,7 @@ static const struct hwcrypto_rng_ops nu_rng_ops = static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) { rt_err_t res = RT_EOK; + RT_ASSERT(ctx != RT_NULL); switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK) { @@ -890,35 +874,16 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) } case HWCRYPTO_TYPE_DES: - { - ctx->contex = RT_NULL; - //Setup DES operation - ((struct hwcrypto_symmetric *)ctx)->ops = &nu_des_ops; - break; - } - case HWCRYPTO_TYPE_3DES: { ctx->contex = RT_NULL; - //Setup 3DES operation + //Setup operation ((struct hwcrypto_symmetric *)ctx)->ops = &nu_des_ops; break; } case HWCRYPTO_TYPE_SHA1: - { - ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT)); - - if (ctx->contex == RT_NULL) - return -RT_ERROR; - - rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT)); - //Setup SHA1 operation - ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops; - break; - } - case HWCRYPTO_TYPE_SHA2: { ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT)); @@ -927,7 +892,7 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) return -RT_ERROR; rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT)); - //Setup SHA2 operation + //Setup operation ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops; break; } @@ -953,11 +918,15 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) break; } + nu_hwcrypto_reset(ctx); + return res; } static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx) { + RT_ASSERT(ctx != RT_NULL); + if (ctx->contex) rt_free(ctx->contex); } @@ -965,6 +934,8 @@ static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx) static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src) { rt_err_t res = RT_EOK; + RT_ASSERT(des != RT_NULL); + RT_ASSERT(src != RT_NULL); if (des->contex && src->contex) { @@ -1015,8 +986,8 @@ static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx) } break; } -#endif +#endif default: break; } @@ -1026,6 +997,7 @@ static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx) int nu_hwcrypto_device_init(void) { + rt_err_t result; static struct rt_hwcrypto_device nu_hwcrypto_dev; nu_hwcrypto_dev.ops = &nu_hwcrypto_ops; @@ -1044,11 +1016,9 @@ int nu_hwcrypto_device_init(void) nu_trng_init(); #endif - // register hwcrypto operation - if (rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME) != RT_EOK) - { - return -1; - } + /* register hwcrypto operation */ + result = rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME); + RT_ASSERT(result == RT_EOK); return 0; } diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c index 7c5aa68697..7fdd2c8876 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c @@ -20,12 +20,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c index dfffc0ebb3..a7bfdb4cb9 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_trng.c @@ -77,10 +77,8 @@ rt_uint32_t nu_trng_rand(struct hwcrypto_rng *ctx) { if (!s_i32TRNGEnable) { - uint32_t u32RNGValue; - //use software rand - u32RNGValue = rand(); - return u32RNGValue; + /* Use software rand */ + return (rt_uint32_t)rand(); } return nu_trng_run(); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c index 9d4848251c..5eeea0eb05 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c @@ -15,7 +15,11 @@ #include "NuMicro.h" #include -#include +#include +#include +#include +#include +#include #include "drv_adc.h" #include "touch.h" diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c index 955fe6a645..26c3a3a90e 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c @@ -20,12 +20,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c index 5f87e038c1..90829c3c8f 100644 --- a/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c +++ b/bsp/nuvoton/libraries/nu_packages/ILI9341/lcd_ili9341.c @@ -17,10 +17,6 @@ #include #include -#if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) - #define DEF_VRAM_BUFFER_NUMBER 2 -#endif - static struct rt_device_graphic_info g_Ili9341Info = { .bits_per_pixel = 16, @@ -275,16 +271,9 @@ static rt_err_t ili9341_lcd_control(rt_device_t dev, int cmd, void *args) case RTGRAPHIC_CTRL_RECT_UPDATE: { #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) - struct rt_device_rect_info *psRectInfo = args; + struct rt_device_rect_info *psRectInfo = (struct rt_device_rect_info *)args; rt_uint16_t *pixels = (rt_uint16_t *)g_Ili9341Info.framebuffer; - RT_ASSERT(args != RT_NULL); - - if (psRectInfo->y >= g_Ili9341Info.height) - { - int buf_id = psRectInfo->y / g_Ili9341Info.height; - pixels += g_Ili9341Info.width * g_Ili9341Info.height * buf_id; - psRectInfo->y %= g_Ili9341Info.height; - } + RT_ASSERT(args); ili9341_fillrect(pixels, psRectInfo); #else @@ -325,7 +314,7 @@ int rt_hw_lcd_ili9341_init(void) lcd_device.user_data = &ili9341_ops; #if defined(NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER) - g_Ili9341Info.framebuffer = rt_malloc_align((DEF_VRAM_BUFFER_NUMBER * g_Ili9341Info.pitch * g_Ili9341Info.height) + 32, 32); + g_Ili9341Info.framebuffer = rt_malloc_align((g_Ili9341Info.pitch * g_Ili9341Info.height) + 32, 32); RT_ASSERT(g_Ili9341Info.framebuffer != RT_NULL); #endif diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c index e995f249af..aa6cf1be8d 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_adc_touch.c @@ -15,7 +15,11 @@ #include "NuMicro.h" #include -#include +#include +#include +#include +#include +#include #include "drv_adc.h" #include "touch.h" diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c index 4a31151c29..f26440524d 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_crypto.c @@ -57,11 +57,6 @@ static struct rt_mutex s_AES_mutex; static struct rt_mutex s_SHA_mutex; static struct rt_mutex s_PRNG_mutex; -static void nu_crypto_isr(int vector, void *param) -{ - /* Nothing */ -} - static rt_err_t nu_aes_crypt_run( rt_bool_t bEncrypt, uint32_t u32OpMode, @@ -153,7 +148,7 @@ static void nu_prng_open(uint32_t u32Seed) result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER); RT_ASSERT(result == RT_EOK); - //Open PRNG 64 bits. But always return 32 bits + //Open PRNG 64 bits PRNG_Open(CRPT, PRNG_KEY_SIZE_64, PRNG_SEED_RELOAD, u32Seed); result = rt_mutex_release(&s_PRNG_mutex); @@ -179,7 +174,7 @@ static rt_uint32_t nu_prng_run(void) result = rt_mutex_release(&s_PRNG_mutex); RT_ASSERT(result == RT_EOK); - return au32RNGValue[0]; + return au32RNGValue[0] ^ au32RNGValue[1]; } static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info) @@ -665,6 +660,8 @@ static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx) break; } + nu_hwcrypto_reset(ctx); + return res; } @@ -770,9 +767,6 @@ int nu_hwcrypto_device_init(void) result = rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME); RT_ASSERT(result == RT_EOK); - /* Enable Crypto engine interrupt */ - rt_hw_interrupt_install(IRQ_CRYPTO, nu_crypto_isr, RT_NULL, "crypto"); - return 0; } INIT_DEVICE_EXPORT(nu_hwcrypto_device_init); diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c index 4b81a01f52..6832db912b 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c @@ -21,12 +21,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif /* Private define ---------------------------------------------------------------*/ diff --git a/bsp/nuvoton/nk-980iot/applications/lvgl/lv_port_disp.c b/bsp/nuvoton/nk-980iot/applications/lvgl/lv_port_disp.c index cc72d47337..cee304eb09 100644 --- a/bsp/nuvoton/nk-980iot/applications/lvgl/lv_port_disp.c +++ b/bsp/nuvoton/nk-980iot/applications/lvgl/lv_port_disp.c @@ -33,11 +33,6 @@ static void lcd_fb_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_colo rect.width = area->x2 - area->x1 + 1; rect.height = area->y2 - area->y1 + 1; - if ((uint32_t)info.framebuffer != (uint32_t)color_p) - { - rect.y += info.height; - } - rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); lv_disp_flush_ready(disp_drv); } @@ -50,8 +45,7 @@ void lcd_perf_monitor(struct _lv_disp_drv_t *disp_drv, uint32_t time, uint32_t p void lv_port_disp_init(void) { rt_err_t result; - void *buf_1 = RT_NULL; - void *buf_2 = RT_NULL; + void *buf1 = RT_NULL; lcd_device = rt_device_find("lcd"); if (lcd_device == 0) @@ -62,7 +56,7 @@ void lv_port_disp_init(void) /* get framebuffer address */ result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); - if (result != RT_EOK) + if (result != RT_EOK && info.framebuffer == RT_NULL) { LOG_E("error!"); /* get device information failed */ @@ -72,12 +66,11 @@ void lv_port_disp_init(void) RT_ASSERT(info.bits_per_pixel == 8 || info.bits_per_pixel == 16 || info.bits_per_pixel == 24 || info.bits_per_pixel == 32); - buf_1 = (void *)info.framebuffer; - buf_2 = (void *)((uint32_t)buf_1 + info.height * info.width * info.bits_per_pixel / 8); - rt_kprintf("LVGL: Use two buffers - buf_1@%08x, buf_2@%08x\n", buf_1, buf_2); + buf1 = (void *)info.framebuffer; + rt_kprintf("LVGL: Use one buffers - buf1@%08x\n", buf1); /*Initialize `disp_buf` with the buffer(s).*/ - lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, info.width * info.height); + lv_disp_draw_buf_init(&disp_buf, buf1, RT_NULL, info.width * info.height); result = rt_device_open(lcd_device, 0); if (result != RT_EOK) diff --git a/bsp/nuvoton/nk-980iot/applications/mnt.c b/bsp/nuvoton/nk-980iot/applications/mnt.c index 803e4b751b..fc440ab8e4 100644 --- a/bsp/nuvoton/nk-980iot/applications/mnt.c +++ b/bsp/nuvoton/nk-980iot/applications/mnt.c @@ -22,12 +22,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/nk-n9h30/.config b/bsp/nuvoton/nk-n9h30/.config index 5fc517cbdb..d561d34221 100644 --- a/bsp/nuvoton/nk-n9h30/.config +++ b/bsp/nuvoton/nk-n9h30/.config @@ -310,8 +310,8 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +# CONFIG_RT_USING_LWIP202 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 diff --git a/bsp/nuvoton/nk-n9h30/applications/mnt.c b/bsp/nuvoton/nk-n9h30/applications/mnt.c index f4e7cf5bf3..05b29c2a24 100644 --- a/bsp/nuvoton/nk-n9h30/applications/mnt.c +++ b/bsp/nuvoton/nk-n9h30/applications/mnt.c @@ -22,12 +22,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/nk-rtu980/applications/mnt.c b/bsp/nuvoton/nk-rtu980/applications/mnt.c index f99fcb0134..266ea0ede0 100644 --- a/bsp/nuvoton/nk-rtu980/applications/mnt.c +++ b/bsp/nuvoton/nk-rtu980/applications/mnt.c @@ -22,12 +22,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-iot-m487/.config b/bsp/nuvoton/numaker-iot-m487/.config index 58d95746ed..b9b1366c42 100644 --- a/bsp/nuvoton/numaker-iot-m487/.config +++ b/bsp/nuvoton/numaker-iot-m487/.config @@ -277,7 +277,6 @@ CONFIG_RT_USB_DEVICE_HID_MOUSE=y # # POSIX layer and C standard library # -# CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # @@ -293,7 +292,9 @@ CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_MMAN is not set # CONFIG_RT_USING_POSIX_DELAY is not set # CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_TIMER is not set # CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_USING_MODULE is not set # # Interprocess Communication (IPC) @@ -427,7 +428,9 @@ CONFIG_PKG_AT_DEVICE_PATH="/packages/iot/at_device" # CONFIG_AT_DEVICE_USING_ESP32 is not set CONFIG_AT_DEVICE_USING_ESP8266=y CONFIG_AT_DEVICE_ESP8266_INIT_ASYN=y +CONFIG_AT_DEVICE_ESP8266_SOCKET=y # CONFIG_AT_DEVICE_ESP8266_SAMPLE is not set +# CONFIG_AT_DEVICE_ESP8266_SAMPLE_BSP_TAKEOVER is not set # CONFIG_AT_DEVICE_USING_RW007 is not set # CONFIG_AT_DEVICE_USING_SIM800C is not set # CONFIG_AT_DEVICE_USING_SIM76XX is not set @@ -561,6 +564,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_MCURSES is not set # CONFIG_PKG_USING_TERMBOX is not set # CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_QRCODE is not set # # tools packages @@ -571,7 +575,6 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_SYSTEMVIEW is not set # CONFIG_PKG_USING_SEGGER_RTT is not set # CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set # CONFIG_PKG_USING_ULOG_FILE is not set # CONFIG_PKG_USING_LOGMGR is not set @@ -622,6 +625,7 @@ CONFIG_PKG_AT_DEVICE_VER_NUM=0x99999 # CONFIG_PKG_USING_POSIX_GETLINE is not set # CONFIG_PKG_USING_POSIX_WCWIDTH is not set # CONFIG_PKG_USING_POSIX_ITOA is not set +# CONFIG_PKG_USING_POSIX_STRINGS is not set # # acceleration: Assembly language or algorithmic acceleration packages @@ -747,6 +751,7 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_RS232 is not set # CONFIG_PKG_USING_NES is not set # CONFIG_PKG_USING_VIRTUAL_SENSOR is not set # CONFIG_PKG_USING_VDEVICE is not set @@ -834,19 +839,8 @@ CONFIG_PKG_FAL_VER_NUM=0x99999 # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set - -# -# Nuvoton Packages Config -# -CONFIG_NU_PKG_USING_UTILS=y -CONFIG_NU_PKG_USING_DEMO=y -CONFIG_NU_PKG_USING_BMX055=y -# CONFIG_NU_PKG_USING_MAX31875 is not set -CONFIG_NU_PKG_USING_NAU88L25=y -# CONFIG_NU_PKG_USING_NAU8822 is not set -# CONFIG_NU_PKG_USING_DA9062 is not set -# CONFIG_NU_PKG_USING_ILI9341 is not set -# CONFIG_NU_PKG_USING_SPINAND is not set +# CONFIG_PKG_USING_CONTROLLER is not set +# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set # # Hardware Drivers Config @@ -946,11 +940,11 @@ CONFIG_NU_CRC_USE_PDMA=y CONFIG_BSP_USING_WDT=y # CONFIG_BSP_USING_EBI is not set CONFIG_BSP_USING_USBD=y -# CONFIG_BSP_USING_HSUSBD is not set +CONFIG_BSP_USING_HSUSBD=y # CONFIG_BSP_USING_USBH is not set CONFIG_BSP_USING_HSUSBH=y CONFIG_NU_USBHOST_HUB_POLLING_INTERVAL=100 -# CONFIG_BSP_USING_HSOTG is not set +CONFIG_BSP_USING_HSOTG=y # # On-board Peripheral Drivers @@ -962,6 +956,7 @@ CONFIG_BOARD_USING_BMX055=y CONFIG_BOARD_USING_NAU88L25=y CONFIG_BOARD_USING_STORAGE_SDCARD=y CONFIG_BOARD_USING_STORAGE_SPIFLASH=y +CONFIG_BOARD_USING_USB_D_H=y # CONFIG_BOARD_USING_HSUSBD is not set # CONFIG_BOARD_USING_HSUSBD_USBH is not set # CONFIG_BOARD_USING_HSUSBH is not set @@ -973,5 +968,18 @@ CONFIG_BOARD_USING_HSUSBH_USBD=y # # CONFIG_BOARD_USING_MAX31875 is not set # CONFIG_BOARD_USING_LCD_ILI9341 is not set + +# +# Nuvoton Packages Config +# +CONFIG_NU_PKG_USING_UTILS=y +CONFIG_NU_PKG_USING_DEMO=y +CONFIG_NU_PKG_USING_BMX055=y +# CONFIG_NU_PKG_USING_MAX31875 is not set +CONFIG_NU_PKG_USING_NAU88L25=y +# CONFIG_NU_PKG_USING_NAU8822 is not set +# CONFIG_NU_PKG_USING_DA9062 is not set +# CONFIG_NU_PKG_USING_ILI9341 is not set +# CONFIG_NU_PKG_USING_SPINAND is not set CONFIG_BOARD_USE_UTEST=y CONFIG_UTEST_CMD_PREFIX="bsp.nuvoton.numaker-iot-m487.test.utest." diff --git a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c index c0cec18978..3bafda9b75 100644 --- a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c @@ -13,12 +13,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-iot-m487/board/Kconfig b/bsp/nuvoton/numaker-iot-m487/board/Kconfig index 0e81a45529..4656abea30 100644 --- a/bsp/nuvoton/numaker-iot-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-iot-m487/board/Kconfig @@ -54,42 +54,49 @@ menu "Hardware Drivers Config" select BSP_USING_QSPI0 default y - choice - prompt "Select FS/HS USB Ports" - - config BOARD_USING_HSUSBD - select BSP_USING_HSUSBD - bool "Enable HSUSBD(over USB2.0)" - help - Choose this option if you need HSUSBD function mode. + config BOARD_USING_USB_D_H + select BSP_USING_HSOTG + bool "Enable USB Device or Host function" + help + Choose this option if you need USB function. - config BOARD_USING_HSUSBD_USBH - select BSP_USING_USBH - select BSP_USING_HSUSBD - bool "Enable HSUSBD(over USB2.0) and USBH(over USB1.1)" - help - Choose this option if you need HSUSBD and USBH function mode at the same time. + if BOARD_USING_USB_D_H + choice + prompt "Select FS/HS USB Ports" - config BOARD_USING_HSUSBH - select BSP_USING_HSUSBH - bool "Enable HSUSBH(over USB2.0)" - help - Choose this option if you need HSUSBH function mode. + config BOARD_USING_HSUSBD + select BSP_USING_HSUSBD + bool "Enable HSUSBD(over USB2.0)" + help + Choose this option if you need HSUSBD function mode. - config BOARD_USING_HSUSBH_USBD - select BSP_USING_HSUSBH - select BSP_USING_USBD - bool "Enable HSUSBH(over USB2.0) and USBD(over USB1.1)" - help - Choose this option if you need HSUSBH and USBD function mode at the same time. + config BOARD_USING_HSUSBD_USBH + select BSP_USING_USBH + select BSP_USING_HSUSBD + bool "Enable HSUSBD(over USB2.0) and USBH(over USB1.1)" + help + Choose this option if you need HSUSBD and USBH function mode at the same time. - config BOARD_USING_HSOTG - select BSP_USING_HSOTG - bool "Enable HSOTG(over USB2.0)" - help - Choose this option if you need HSOTG function mode. + config BOARD_USING_HSUSBH + select BSP_USING_HSUSBH + bool "Enable HSUSBH(over USB2.0)" + help + Choose this option if you need HSUSBH function mode. - endchoice + config BOARD_USING_HSUSBH_USBD + select BSP_USING_HSUSBH + select BSP_USING_USBD + bool "Enable HSUSBH(over USB2.0) and USBD(over USB1.1)" + help + Choose this option if you need HSUSBH and USBD function mode at the same time. + + config BOARD_USING_HSOTG + select BSP_USING_HSOTG + bool "Enable HSOTG(over USB2.0)" + help + Choose this option if you need HSOTG function mode. + endchoice + endif endmenu diff --git a/bsp/nuvoton/numaker-m032ki/applications/mnt.c b/bsp/nuvoton/numaker-m032ki/applications/mnt.c index 00f0f91499..62c470570c 100644 --- a/bsp/nuvoton/numaker-m032ki/applications/mnt.c +++ b/bsp/nuvoton/numaker-m032ki/applications/mnt.c @@ -13,12 +13,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-m2354/applications/SConscript b/bsp/nuvoton/numaker-m2354/applications/SConscript index 9ffdbcd0f9..3769d125df 100644 --- a/bsp/nuvoton/numaker-m2354/applications/SConscript +++ b/bsp/nuvoton/numaker-m2354/applications/SConscript @@ -3,9 +3,19 @@ from building import * cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + src = Glob('*.c') + Glob('*.cpp') CPPPATH = [cwd, str(Dir('#'))] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) -Return('group') +objs = objs + group + +Return('objs') + diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/SConscript b/bsp/nuvoton/numaker-m2354/applications/lvgl/SConscript new file mode 100644 index 0000000000..18f793dbe0 --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('LVGL-port', src, depend = ['PKG_USING_LVGL'], CPPPATH = CPPPATH) + +Return('group') + diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_conf.h b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_conf.h new file mode 100644 index 0000000000..9c2479dc5c --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_conf.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-18 Meco Man First version + */ + +#ifndef LV_CONF_H +#define LV_CONF_H + +#define LV_USE_PERF_MONITOR 1 +#define LV_COLOR_DEPTH 16 + +#define LV_HOR_RES_MAX (320) +#define LV_VER_RES_MAX (240) + +#define LV_FONT_MONTSERRAT_12 1 +#define LV_FONT_MONTSERRAT_16 1 +#define LV_USE_DEMO_RTT_MUSIC 1 +#define LV_DEMO_RTT_MUSIC_AUTO_PLAY 1 + +#define LV_DISP_DEF_REFR_PERIOD 16 + +//#define CONFIG_LV_LOG_LEVEL LV_LOG_LEVEL_TRACE +#endif diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_demo.c b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_demo.c new file mode 100644 index 0000000000..7ac1eab9e5 --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_demo.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-17 Meco Man First version + */ +#include +#include +#define DBG_TAG "LVGL" +#define DBG_LVL DBG_INFO +#include + +#ifndef LV_THREAD_STACK_SIZE + #define LV_THREAD_STACK_SIZE 4096 +#endif + +#ifndef LV_THREAD_PRIO + #define LV_THREAD_PRIO (RT_THREAD_PRIORITY_MAX*2/3) +#endif + +static void lvgl_thread(void *parameter) +{ + extern void lv_demo_music(void); + lv_demo_music(); + + while (1) + { + lv_task_handler(); + rt_thread_mdelay(1); + } +} + +static int lvgl_demo_init(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("LVGL", lvgl_thread, RT_NULL, LV_THREAD_STACK_SIZE, LV_THREAD_PRIO, 10); + if (tid == RT_NULL) + { + LOG_E("Fail to create 'LVGL' thread"); + } + rt_thread_startup(tid); + + return 0; +} +INIT_APP_EXPORT(lvgl_demo_init); diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.c b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.c new file mode 100644 index 0000000000..cee304eb09 --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-12-17 Wayne The first version + */ +#include + +#define LOG_TAG "lvgl.disp" +#define DBG_ENABLE +#define DBG_SECTION_NAME LOG_TAG +#define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +/*A static or global variable to store the buffers*/ +static lv_disp_draw_buf_t disp_buf; +static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ + +static rt_device_t lcd_device = 0; +static struct rt_device_graphic_info info; + +static void lcd_fb_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) +{ + /* Rendering */ + struct rt_device_rect_info rect; + + rect.x = area->x1; + rect.y = area->y1; + rect.width = area->x2 - area->x1 + 1; + rect.height = area->y2 - area->y1 + 1; + + rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect); + lv_disp_flush_ready(disp_drv); +} + +void lcd_perf_monitor(struct _lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px) +{ + rt_kprintf("Elapsed: %dms, Pixel: %d, Bytes:%d\n", time, px, px * sizeof(lv_color_t)); +} + +void lv_port_disp_init(void) +{ + rt_err_t result; + void *buf1 = RT_NULL; + + lcd_device = rt_device_find("lcd"); + if (lcd_device == 0) + { + LOG_E("error!"); + return; + } + + /* get framebuffer address */ + result = rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info); + if (result != RT_EOK && info.framebuffer == RT_NULL) + { + LOG_E("error!"); + /* get device information failed */ + return; + } + + RT_ASSERT(info.bits_per_pixel == 8 || info.bits_per_pixel == 16 || + info.bits_per_pixel == 24 || info.bits_per_pixel == 32); + + buf1 = (void *)info.framebuffer; + rt_kprintf("LVGL: Use one buffers - buf1@%08x\n", buf1); + + /*Initialize `disp_buf` with the buffer(s).*/ + lv_disp_draw_buf_init(&disp_buf, buf1, RT_NULL, info.width * info.height); + + result = rt_device_open(lcd_device, 0); + if (result != RT_EOK) + { + LOG_E("error!"); + return; + } + + lv_disp_drv_init(&disp_drv); /*Basic initialization*/ + + /*Set the resolution of the display*/ + disp_drv.hor_res = info.width; + disp_drv.ver_res = info.height; + + /*Set a display buffer*/ + disp_drv.draw_buf = &disp_buf; + + /*Write the internal buffer (draw_buf) to the display*/ + disp_drv.flush_cb = lcd_fb_flush; + + /* Called after every refresh cycle to tell the rendering and flushing time + the number of flushed pixels */ + //disp_drv.monitor_cb = lcd_perf_monitor; + + /*Finally register the driver*/ + lv_disp_drv_register(&disp_drv); +} diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.h b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.h new file mode 100644 index 0000000000..ef39eb03cd --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_disp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-18 Meco Man The first version + */ +#ifndef LV_PORT_DISP_H +#define LV_PORT_DISP_H + +#ifdef __cplusplus +extern "C" { +#endif + +void lv_port_disp_init(void); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.c b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.c new file mode 100644 index 0000000000..4451ad4f84 --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-18 Meco Man The first version + * 2021-12-17 Wayne Add input event + */ +#include +#include +#include +#include "touch.h" + +static lv_indev_state_t last_state = LV_INDEV_STATE_REL; +static rt_int16_t last_x = 0; +static rt_int16_t last_y = 0; + +static void input_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) +{ + data->point.x = last_x; + data->point.y = last_y; + data->state = last_state; +} + +void nu_touch_inputevent_cb(rt_int16_t x, rt_int16_t y, rt_uint8_t state) +{ + switch (state) + { + case RT_TOUCH_EVENT_UP: + last_state = LV_INDEV_STATE_RELEASED; + break; + case RT_TOUCH_EVENT_DOWN: + last_x = x; + last_y = y; + last_state = LV_INDEV_STATE_PRESSED; + break; + case RT_TOUCH_EVENT_MOVE: + last_x = x; + last_y = y; + break; + } +} + +void lv_port_indev_init(void) +{ + static lv_indev_drv_t indev_drv; + + /* Basic initialization */ + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.read_cb = input_read; + + /* Register the driver in LVGL and save the created input device object */ + lv_indev_drv_register(&indev_drv); +} diff --git a/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.h b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.h new file mode 100644 index 0000000000..dec92bccbc --- /dev/null +++ b/bsp/nuvoton/numaker-m2354/applications/lvgl/lv_port_indev.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-10-18 Meco Man The first version + */ +#ifndef LV_PORT_INDEV_H +#define LV_PORT_INDEV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern lv_indev_t *button_indev; + +void lv_port_indev_init(void); +void lv_port_indev_input(rt_int16_t x, rt_int16_t y, lv_indev_state_t state); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/bsp/nuvoton/numaker-m2354/board/Kconfig b/bsp/nuvoton/numaker-m2354/board/Kconfig index 3c71934493..8af0a080ea 100644 --- a/bsp/nuvoton/numaker-m2354/board/Kconfig +++ b/bsp/nuvoton/numaker-m2354/board/Kconfig @@ -61,6 +61,37 @@ menu "Hardware Drivers Config" endmenu menu "Board extended module drivers" + config BOARD_USING_LCD_ILI9341 + bool "LCD ILI9341 (over spi1)" + select RT_USING_TOUCH + select NU_PKG_USING_ILI9341 + select NU_PKG_USING_ILI9341_SPI + select NU_PKG_ILI9341_WITH_OFFSCREEN_FRAMEBUFFER + select NU_PKG_ILI9341_HORIZONTAL + select BSP_USING_SPI1 + select PKG_USING_LVGL + select PKG_USING_LV_MUSIC_DEMO + default n + + if BOARD_USING_LCD_ILI9341 + + config BOARD_USING_ILI9341_PIN_BACKLIGHT + int "Specify the pin index of backlight pin index" + range 0 127 + default 43 + + config BOARD_USING_ILI9341_PIN_RESET + int "Specify the pin index of reset pin index" + range 0 127 + default 9 + + config BOARD_USING_ILI9341_PIN_DC + int "Specify the pin index of data&command switching" + range 0 127 + default 8 + + endif + config BOARD_USING_SEGMENT_LCD bool "Segment LCD supporting.(over lcd)" select BSP_USING_SLCD diff --git a/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c b/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c index f64be93443..f4e2a1ffd0 100644 --- a/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c +++ b/bsp/nuvoton/numaker-m2354/board/NuPinConfig/nutool_pincfg.c @@ -108,7 +108,12 @@ void nutool_pincfg_deinit_epwm0(void) void nutool_pincfg_init_epwm1(void) { SYS->GPC_MFPH &= ~(SYS_GPC_MFPH_PC12MFP_Msk | SYS_GPC_MFPH_PC11MFP_Msk | SYS_GPC_MFPH_PC10MFP_Msk | SYS_GPC_MFPH_PC9MFP_Msk); +#if !defined(BOARD_USING_LCD_ILI9341) SYS->GPC_MFPH |= (SYS_GPC_MFPH_PC12MFP_EPWM1_CH0 | SYS_GPC_MFPH_PC11MFP_EPWM1_CH1 | SYS_GPC_MFPH_PC10MFP_EPWM1_CH2 | SYS_GPC_MFPH_PC9MFP_EPWM1_CH3); +#else + SYS->GPC_MFPH |= (SYS_GPC_MFPH_PC12MFP_EPWM1_CH0 | SYS_GPC_MFPH_PC10MFP_EPWM1_CH2 | SYS_GPC_MFPH_PC9MFP_EPWM1_CH3); +#endif + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC1MFP_Msk | SYS_GPC_MFPL_PC0MFP_Msk); SYS->GPC_MFPL |= (SYS_GPC_MFPL_PC1MFP_EPWM1_CH4 | SYS_GPC_MFPL_PC0MFP_EPWM1_CH5); @@ -396,7 +401,9 @@ void nutool_pincfg_init(void) nutool_pincfg_init_spi0(); nutool_pincfg_init_spi1(); nutool_pincfg_init_uart0(); +#if !defined(BOARD_USING_LCD_ILI9341) nutool_pincfg_init_uart1(); +#endif nutool_pincfg_init_uart4(); nutool_pincfg_init_usb(); diff --git a/bsp/nuvoton/numaker-m2354/board/board_dev.c b/bsp/nuvoton/numaker-m2354/board/board_dev.c index 3cf1d862b7..0b2453be39 100644 --- a/bsp/nuvoton/numaker-m2354/board/board_dev.c +++ b/bsp/nuvoton/numaker-m2354/board/board_dev.c @@ -13,6 +13,32 @@ #include #include + + +#if defined(BOARD_USING_LCD_ILI9341) && defined(NU_PKG_USING_ILI9341_SPI) +#include +#if defined(PKG_USING_GUIENGINE) + #include +#endif +int rt_hw_ili9341_port(void) +{ + if (rt_hw_lcd_ili9341_spi_init("spi1") != RT_EOK) + return -1; + + rt_hw_lcd_ili9341_init(); + +#if defined(PKG_USING_GUIENGINE) + rt_device_t lcd_ili9341; + lcd_ili9341 = rt_device_find("lcd"); + if (lcd_ili9341) + { + rtgui_graphic_set_device(lcd_ili9341); + } +#endif + return 0; +} +INIT_COMPONENT_EXPORT(rt_hw_ili9341_port); +#endif /* BOARD_USING_LCD_ILI9341 */ #if defined(BOARD_USING_ESP8266) #include diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index 84c9359e02..b0fbce1297 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -279,7 +279,6 @@ CONFIG_RT_USB_DEVICE_HID_MOUSE=y # # POSIX layer and C standard library # -# CONFIG_RT_USING_MODULE is not set CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # @@ -295,7 +294,9 @@ CONFIG_RT_USING_POSIX_DEVIO=y # CONFIG_RT_USING_POSIX_MMAN is not set # CONFIG_RT_USING_POSIX_DELAY is not set # CONFIG_RT_USING_POSIX_CLOCK is not set +# CONFIG_RT_USING_POSIX_TIMER is not set # CONFIG_RT_USING_PTHREADS is not set +# CONFIG_RT_USING_MODULE is not set # # Interprocess Communication (IPC) @@ -343,8 +344,7 @@ CONFIG_NETDEV_IPV6=0 # CONFIG_RT_USING_LWIP=y # CONFIG_RT_USING_LWIP141 is not set -CONFIG_RT_USING_LWIP202=y -# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP203=y # CONFIG_RT_USING_LWIP212 is not set # CONFIG_RT_USING_LWIP_IPV6 is not set CONFIG_RT_LWIP_MEM_ALIGNMENT=4 @@ -942,11 +942,11 @@ CONFIG_NU_CRC_USE_PDMA=y CONFIG_BSP_USING_WDT=y # CONFIG_BSP_USING_EBI is not set CONFIG_BSP_USING_USBD=y -# CONFIG_BSP_USING_HSUSBD is not set +CONFIG_BSP_USING_HSUSBD=y # CONFIG_BSP_USING_USBH is not set CONFIG_BSP_USING_HSUSBH=y CONFIG_NU_USBHOST_HUB_POLLING_INTERVAL=100 -# CONFIG_BSP_USING_HSOTG is not set +CONFIG_BSP_USING_HSOTG=y # # On-board Peripheral Drivers @@ -956,6 +956,7 @@ CONFIG_BOARD_USING_IP101GR=y CONFIG_BOARD_USING_NAU88L25=y CONFIG_BOARD_USING_STORAGE_SDCARD=y CONFIG_BOARD_USING_STORAGE_SPIFLASH=y +CONFIG_BOARD_USING_USB_D_H=y # CONFIG_BOARD_USING_HSUSBD is not set # CONFIG_BOARD_USING_HSUSBD_USBH is not set # CONFIG_BOARD_USING_HSUSBH is not set diff --git a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c index 844ab9960d..398f292c43 100644 --- a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c @@ -13,12 +13,12 @@ #include #if defined(RT_USING_DFS) -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include #endif #if defined(PKG_USING_FAL) diff --git a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig index a4f4e0c69a..2c95e671b1 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig @@ -37,42 +37,49 @@ menu "Hardware Drivers Config" select BSP_USING_QSPI0 default y - choice - prompt "Select FS/HS USB Ports" + config BOARD_USING_USB_D_H + select BSP_USING_HSOTG + bool "Enable USB Device or Host function" + help + Choose this option if you need USB function. - config BOARD_USING_HSUSBD - select BSP_USING_HSUSBD - bool "Enable HSUSBD(over USB2.0)" - help - Choose this option if you need HSUSBD function mode. + if BOARD_USING_USB_D_H + choice + prompt "Select FS/HS USB Ports" - config BOARD_USING_HSUSBD_USBH - select BSP_USING_USBH - select BSP_USING_HSUSBD - bool "Enable HSUSBD(over USB2.0) and USBH(over USB1.1)" - help - Choose this option if you need HSUSBD and USBH function mode at the same time. + config BOARD_USING_HSUSBD + select BSP_USING_HSUSBD + bool "Enable HSUSBD(over USB2.0)" + help + Choose this option if you need HSUSBD function mode. - config BOARD_USING_HSUSBH - select BSP_USING_HSUSBH - bool "Enable HSUSBH(over USB2.0)" - help - Choose this option if you need HSUSBH function mode. + config BOARD_USING_HSUSBD_USBH + select BSP_USING_USBH + select BSP_USING_HSUSBD + bool "Enable HSUSBD(over USB2.0) and USBH(over USB1.1)" + help + Choose this option if you need HSUSBD and USBH function mode at the same time. - config BOARD_USING_HSUSBH_USBD - select BSP_USING_HSUSBH - select BSP_USING_USBD - bool "Enable HSUSBH(over USB2.0) and USBD(over USB1.1)" - help - Choose this option if you need HSUSBH and USBD function mode at the same time. + config BOARD_USING_HSUSBH + select BSP_USING_HSUSBH + bool "Enable HSUSBH(over USB2.0)" + help + Choose this option if you need HSUSBH function mode. - config BOARD_USING_HSOTG - select BSP_USING_HSOTG - bool "Enable HSOTG(over USB2.0)" - help - Choose this option if you need HSOTG function mode. + config BOARD_USING_HSUSBH_USBD + select BSP_USING_HSUSBH + select BSP_USING_USBD + bool "Enable HSUSBH(over USB2.0) and USBD(over USB1.1)" + help + Choose this option if you need HSUSBH and USBD function mode at the same time. - endchoice + config BOARD_USING_HSOTG + select BSP_USING_HSOTG + bool "Enable HSOTG(over USB2.0)" + help + Choose this option if you need HSOTG function mode. + endchoice + endif endmenu From 1577e91c50fb6cea131767163665a0640644fe96 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Tue, 25 Jan 2022 19:15:55 +0800 Subject: [PATCH 57/65] Update default configurations. --- bsp/nuvoton/numaker-iot-m487/.config | 4 ++-- bsp/nuvoton/numaker-iot-m487/board/Kconfig | 1 - bsp/nuvoton/numaker-pfm-m487/.config | 4 ++-- bsp/nuvoton/numaker-pfm-m487/board/Kconfig | 1 - 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/bsp/nuvoton/numaker-iot-m487/.config b/bsp/nuvoton/numaker-iot-m487/.config index b9b1366c42..35a86cd719 100644 --- a/bsp/nuvoton/numaker-iot-m487/.config +++ b/bsp/nuvoton/numaker-iot-m487/.config @@ -940,11 +940,11 @@ CONFIG_NU_CRC_USE_PDMA=y CONFIG_BSP_USING_WDT=y # CONFIG_BSP_USING_EBI is not set CONFIG_BSP_USING_USBD=y -CONFIG_BSP_USING_HSUSBD=y +# CONFIG_BSP_USING_HSUSBD is not set # CONFIG_BSP_USING_USBH is not set CONFIG_BSP_USING_HSUSBH=y CONFIG_NU_USBHOST_HUB_POLLING_INTERVAL=100 -CONFIG_BSP_USING_HSOTG=y +# CONFIG_BSP_USING_HSOTG is not set # # On-board Peripheral Drivers diff --git a/bsp/nuvoton/numaker-iot-m487/board/Kconfig b/bsp/nuvoton/numaker-iot-m487/board/Kconfig index 4656abea30..3e3d614599 100644 --- a/bsp/nuvoton/numaker-iot-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-iot-m487/board/Kconfig @@ -55,7 +55,6 @@ menu "Hardware Drivers Config" default y config BOARD_USING_USB_D_H - select BSP_USING_HSOTG bool "Enable USB Device or Host function" help Choose this option if you need USB function. diff --git a/bsp/nuvoton/numaker-pfm-m487/.config b/bsp/nuvoton/numaker-pfm-m487/.config index b0fbce1297..8bc0959025 100644 --- a/bsp/nuvoton/numaker-pfm-m487/.config +++ b/bsp/nuvoton/numaker-pfm-m487/.config @@ -942,11 +942,11 @@ CONFIG_NU_CRC_USE_PDMA=y CONFIG_BSP_USING_WDT=y # CONFIG_BSP_USING_EBI is not set CONFIG_BSP_USING_USBD=y -CONFIG_BSP_USING_HSUSBD=y +# CONFIG_BSP_USING_HSUSBD is not set # CONFIG_BSP_USING_USBH is not set CONFIG_BSP_USING_HSUSBH=y CONFIG_NU_USBHOST_HUB_POLLING_INTERVAL=100 -CONFIG_BSP_USING_HSOTG=y +# CONFIG_BSP_USING_HSOTG is not set # # On-board Peripheral Drivers diff --git a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig index 2c95e671b1..dd7ef72a68 100644 --- a/bsp/nuvoton/numaker-pfm-m487/board/Kconfig +++ b/bsp/nuvoton/numaker-pfm-m487/board/Kconfig @@ -38,7 +38,6 @@ menu "Hardware Drivers Config" default y config BOARD_USING_USB_D_H - select BSP_USING_HSOTG bool "Enable USB Device or Host function" help Choose this option if you need USB function. From 3be35fecae513b07c35bd6f3992bf7824434bdd6 Mon Sep 17 00:00:00 2001 From: "WBI\\nxf44444" Date: Wed, 26 Jan 2022 00:54:03 +0800 Subject: [PATCH 58/65] Update i2c driver, add read ACK and BUS status check --- bsp/imxrt/libraries/drivers/drv_i2c.c | 145 +++++++++++++++++++++----- 1 file changed, 120 insertions(+), 25 deletions(-) diff --git a/bsp/imxrt/libraries/drivers/drv_i2c.c b/bsp/imxrt/libraries/drivers/drv_i2c.c index 117b29f3d3..f38db34b6c 100644 --- a/bsp/imxrt/libraries/drivers/drv_i2c.c +++ b/bsp/imxrt/libraries/drivers/drv_i2c.c @@ -18,7 +18,7 @@ #define LOG_TAG "drv.i2c" #include -#if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) && !defined(BSP_USING_I2C4) +#if !defined(BSP_USING_I2C1) && !defined(BSP_USING_I2C2) && !defined(BSP_USING_I2C3) && !defined(BSP_USING_I2C4) && !defined(BSP_USING_I2C5)&& !defined(BSP_USING_I2C6) #error "Please define at least one BSP_USING_I2Cx" #endif @@ -35,6 +35,9 @@ struct imxrt_i2c_bus volatile rt_uint32_t msg_ptr; volatile rt_uint32_t dptr; char *device_name; +#ifdef SOC_IMXRT1170_SERIES + clock_root_t clock_root; +#endif }; #if defined (BSP_USING_I2C1) @@ -55,13 +58,28 @@ struct imxrt_i2c_bus #define I2C4BUS_NAME "i2c4" #endif /*BSP_USING_I2C4*/ +#if defined (BSP_USING_I2C5) +#define I2C5BUS_NAME "i2c5" +#endif /*BSP_USING_I2C5*/ + +#if defined (BSP_USING_I2C6) +#define I2C6BUS_NAME "i2c6" +#endif /*BSP_USING_I2C6*/ + #endif /* MIMXRT1015_SERIES */ -#define LPI2C_CLOCK_SOURCE_DIVIDER 4 +/* Select USB1 PLL (360 MHz) as master lpi2c clock source */ +#define LPI2C_CLOCK_SOURCE_SELECT (1U) +#ifdef SOC_IMXRT1170_SERIES +/* Clock divider for master lpi2c clock source */ +#define LPI2C_CLOCK_SOURCE_DIVIDER (12U) +#else +#define LPI2C_CLOCK_SOURCE_DIVIDER (0U) /* Get frequency of lpi2c clock */ -#define LPI2C_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER)) +#define LPI2C_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U)) +#endif #ifdef BSP_USING_I2C1 static struct imxrt_i2c_bus lpi2c1 = { @@ -96,9 +114,25 @@ static struct imxrt_i2c_bus lpi2c4 = }; #endif /* RT_USING_HW_I2C4 */ +#ifdef BSP_USING_I2C5 +static struct imxrt_i2c_bus lpi2c5 = +{ + .I2C = LPI2C5, + .device_name = I2C5BUS_NAME, +}; +#endif /* RT_USING_HW_I2C5 */ + +#ifdef BSP_USING_I2C6 +static struct imxrt_i2c_bus lpi2c6 = +{ + .I2C = LPI2C6, + .device_name = I2C6BUS_NAME, +}; +#endif /* RT_USING_HW_I2C6 */ + #endif /* MIMXRT1015_SERIES */ -#if (defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3) || defined(BSP_USING_I2C4)) +#if (defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) || defined(BSP_USING_I2C3) || defined(BSP_USING_I2C4) ||defined(BSP_USING_I2C5) || defined(BSP_USING_I2C6)) static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], @@ -123,7 +157,19 @@ static rt_err_t imxrt_lpi2c_configure(struct imxrt_i2c_bus *bus, lpi2c_master_co RT_ASSERT(cfg != RT_NULL); bus->parent.ops = &imxrt_i2c_ops; +#ifdef SOC_IMXRT1170_SERIES + clock_root_config_t rootCfg = {0}; + rootCfg.mux = LPI2C_CLOCK_SOURCE_SELECT; + rootCfg.div = LPI2C_CLOCK_SOURCE_DIVIDER + 1; + CLOCK_SetRootClock(bus->clock_root, &rootCfg); + volatile uint32_t freq = CLOCK_GetRootClockFreq(bus->clock_root); + LPI2C_MasterInit(bus->I2C, cfg, freq); +#else + CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT); + CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER); LPI2C_MasterInit(bus->I2C, cfg, LPI2C_CLOCK_FREQUENCY); +#endif + return RT_EOK; } @@ -221,21 +267,36 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, { if (imxrt_i2c->msg[i].flags & RT_I2C_RD) { - if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success) - { - i = 0; - break; - } + if ((imxrt_i2c->msg[i].flags & RT_I2C_NO_START) != RT_I2C_NO_START) + { + if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success) + { + i = 0; + break; + } - while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) - { - } - - if (LPI2C_MasterRepeatedStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) - { - i = 0; - break; - } + while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + { + } + + if (LPI2C_MasterRepeatedStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) + { + i = 0; + break; + } + } + else + { + if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) + { + i = 0; + break; + } + + while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + { + } + } if (LPI2C_MasterReceive(imxrt_i2c->I2C, imxrt_i2c->msg[i].buf, imxrt_i2c->msg[i].len) != kStatus_Success) { @@ -250,9 +311,17 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, i = 0; break; } - - while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + + if(LPI2C_MasterWaitForTxFifoAllEmpty(imxrt_i2c->I2C) != kStatus_Success) { + i = 0; + break; + } + + if (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + { + i = 0; + break; } if (LPI2C_MasterSend(imxrt_i2c->I2C, imxrt_i2c->msg[i].buf, imxrt_i2c->msg[i].len) != kStatus_Success) @@ -267,11 +336,12 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, break; } } - } - - if (LPI2C_MasterStop(imxrt_i2c->I2C) != kStatus_Success) - { - i = 0; + + if (LPI2C_MasterStop(imxrt_i2c->I2C) != kStatus_Success) + { + i = 0; + } + } imxrt_i2c->msg = RT_NULL; @@ -347,6 +417,31 @@ int rt_hw_i2c_init(void) rt_i2c_bus_device_register(&lpi2c4.parent, lpi2c4.device_name); #endif /* BSP_USING_I2C4 */ +#if defined(BSP_USING_I2C5) + LPI2C_MasterGetDefaultConfig(&masterConfig); +#if defined(HW_I2C5_BADURATE_400kHZ) + masterConfig.baudRate_Hz = 400000U; +#elif defined(HW_I2C5_BADURATE_100kHZ) + masterConfig.baudRate_Hz = 100000U; +#endif /* HW_I2C5_BADURATE_400kHZ */ + lpi2c5.clock_root = kCLOCK_Root_Lpi2c5; + imxrt_lpi2c_configure(&lpi2c5, &masterConfig); + rt_i2c_bus_device_register(&lpi2c5.parent, lpi2c5.device_name); +#endif /* BSP_USING_I2C5 */ + +#if defined(BSP_USING_I2C6) + LPI2C_MasterGetDefaultConfig(&masterConfig); +#if defined(HW_I2C6_BADURATE_400kHZ) + masterConfig.baudRate_Hz = 400000U; +#elif defined(HW_I2C6_BADURATE_100kHZ) + masterConfig.baudRate_Hz = 100000U; +#endif /* HW_I2C6_BADURATE_400kHZ */ + lpi2c6.clock_root = kCLOCK_Root_Lpi2c6; + imxrt_lpi2c_configure(&lpi2c6, &masterConfig); + rt_i2c_bus_device_register(&lpi2c6.parent, lpi2c6.device_name); +#endif /* BSP_USING_I2C6 */ + + #endif /* MIMXRT1015_SERIES */ return 0; From e4892b95fdcf6454d4ca5b131e5a6fa2ac98d063 Mon Sep 17 00:00:00 2001 From: iysheng Date: Tue, 25 Jan 2022 16:37:19 +0800 Subject: [PATCH 59/65] [bsp][gd32103c-eval] Port rtc, adc, wdt, hwtimer drivers to new gd32 frame --- bsp/gd32/gd32103c-eval/board/Kconfig | 58 +- .../GD32F10x_Firmware_Library/SConscript | 1 + bsp/gd32/libraries/gd32_drivers/SConscript | 16 +- .../libraries/gd32_drivers}/drv_adc.c | 58 +- bsp/gd32/libraries/gd32_drivers/drv_gpio.h | 8 +- .../libraries/gd32_drivers}/drv_hwtimer.c | 114 +- .../libraries/gd32_drivers}/drv_rtc.c | 19 +- .../libraries/gd32_drivers/drv_wdt.c} | 39 +- bsp/gd32103c-eval/.config | 672 -- bsp/gd32103c-eval/Kconfig | 109 - .../CMSIS/GD/GD32F1xx/Include/gd32f10x.h | 8033 ----------------- .../CMSIS/GD/GD32F1xx/Include/gd32f10x_conf.h | 39 - .../GD/GD32F1xx/Include/system_gd32f10x.h | 64 - .../CMSIS/GD/GD32F1xx/Source/GCC/isr_tab.s | 213 - .../GD/GD32F1xx/Source/GCC/startup_gd32.s | 48 - .../GD/GD32F1xx/Source/system_gd32f1xx.c | 1131 --- bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.c | 784 -- bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.h | 1614 ---- .../Libraries/CMSIS/core_cmFunc.h | 616 -- .../Libraries/CMSIS/core_cmInstr.h | 618 -- .../Include/gd32f10x_adc.h | 278 - .../Include/gd32f10x_bkp.h | 139 - .../Include/gd32f10x_can.h | 512 -- .../Include/gd32f10x_crc.h | 52 - .../Include/gd32f10x_dac.h | 208 - .../Include/gd32f10x_dma.h | 321 - .../Include/gd32f10x_eth.h | 1407 --- .../Include/gd32f10x_exmc.h | 454 - .../Include/gd32f10x_exti.h | 130 - .../Include/gd32f10x_fmc.h | 263 - .../Include/gd32f10x_gpio.h | 281 - .../Include/gd32f10x_i2c.h | 289 - .../Include/gd32f10x_iwdg.h | 103 - .../Include/gd32f10x_mcudbg.h | 90 - .../Include/gd32f10x_misc.h | 119 - .../Include/gd32f10x_pwr.h | 131 - .../Include/gd32f10x_rcc.h | 690 -- .../Include/gd32f10x_rcu.h | 1019 --- .../Include/gd32f10x_rtc.h | 92 - .../Include/gd32f10x_sdio.h | 369 - .../Include/gd32f10x_spi.h | 353 - .../Include/gd32f10x_timer.h | 758 -- .../Include/gd32f10x_usart.h | 297 - .../Include/gd32f10x_wwdg.h | 77 - .../Source/gd32f10x_adc.c | 977 -- .../Source/gd32f10x_bkp.c | 250 - .../Source/gd32f10x_can.c | 1120 --- .../Source/gd32f10x_crc.c | 101 - .../Source/gd32f10x_dac.c | 326 - .../Source/gd32f10x_dma.c | 553 -- .../Source/gd32f10x_eth.c | 2587 ------ .../Source/gd32f10x_exmc.c | 758 -- .../Source/gd32f10x_exti.c | 196 - .../Source/gd32f10x_fmc.c | 1166 --- .../Source/gd32f10x_gpio.c | 511 -- .../Source/gd32f10x_i2c.c | 899 -- .../Source/gd32f10x_iwdg.c | 130 - .../Source/gd32f10x_mcudbg.c | 105 - .../Source/gd32f10x_misc.c | 136 - .../Source/gd32f10x_pwr.c | 333 - .../Source/gd32f10x_rcc.c | 1323 --- .../Source/gd32f10x_rcu.c | 1277 --- .../Source/gd32f10x_rtc.c | 263 - .../Source/gd32f10x_sdio.c | 636 -- .../Source/gd32f10x_spi.c | 554 -- .../Source/gd32f10x_timer.c | 2360 ----- .../Source/gd32f10x_usart.c | 784 -- .../Source/gd32f10x_wwdg.c | 155 - bsp/gd32103c-eval/Libraries/SConscript | 26 - bsp/gd32103c-eval/README.md | 74 - bsp/gd32103c-eval/SConscript | 14 - bsp/gd32103c-eval/SConstruct | 40 - bsp/gd32103c-eval/applications/SConscript | 11 - bsp/gd32103c-eval/applications/main.c | 33 - bsp/gd32103c-eval/drivers/SConscript | 35 - bsp/gd32103c-eval/drivers/board.c | 74 - bsp/gd32103c-eval/drivers/board.h | 26 - bsp/gd32103c-eval/drivers/drv_adc.h | 23 - bsp/gd32103c-eval/drivers/drv_comm.h | 27 - bsp/gd32103c-eval/drivers/drv_gpio.c | 512 -- bsp/gd32103c-eval/drivers/drv_gpio.h | 45 - bsp/gd32103c-eval/drivers/drv_hwtimer.h | 38 - bsp/gd32103c-eval/drivers/drv_usart.c | 358 - bsp/gd32103c-eval/drivers/drv_usart.h | 33 - bsp/gd32103c-eval/gd32_rom.ld | 146 - bsp/gd32103c-eval/rtconfig.h | 208 - bsp/gd32103c-eval/rtconfig.py | 126 - 87 files changed, 192 insertions(+), 41843 deletions(-) rename bsp/{gd32103c-eval/drivers => gd32/libraries/gd32_drivers}/drv_adc.c (63%) rename bsp/{gd32103c-eval/drivers => gd32/libraries/gd32_drivers}/drv_hwtimer.c (75%) rename bsp/{gd32103c-eval/drivers => gd32/libraries/gd32_drivers}/drv_rtc.c (89%) rename bsp/{gd32103c-eval/drivers/drv_iwdt.c => gd32/libraries/gd32_drivers/drv_wdt.c} (69%) delete mode 100644 bsp/gd32103c-eval/.config delete mode 100644 bsp/gd32103c-eval/Kconfig delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Include/gd32f10x.h delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Include/gd32f10x_conf.h delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Include/system_gd32f10x.h delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Source/GCC/isr_tab.s delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Source/GCC/startup_gd32.s delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Source/system_gd32f1xx.c delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.c delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.h delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/core_cmFunc.h delete mode 100644 bsp/gd32103c-eval/Libraries/CMSIS/core_cmInstr.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_adc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_bkp.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_can.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_crc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dac.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dma.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_eth.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exmc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exti.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_fmc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_gpio.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_i2c.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_iwdg.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_mcudbg.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_misc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_pwr.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcu.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rtc.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_sdio.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_spi.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_timer.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_usart.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_wwdg.h delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_adc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_bkp.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_can.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_crc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dac.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dma.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_eth.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exmc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exti.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_fmc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_gpio.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_i2c.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_iwdg.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_mcudbg.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_misc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_pwr.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcu.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rtc.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_sdio.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_spi.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_timer.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_usart.c delete mode 100644 bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_wwdg.c delete mode 100644 bsp/gd32103c-eval/Libraries/SConscript delete mode 100644 bsp/gd32103c-eval/README.md delete mode 100644 bsp/gd32103c-eval/SConscript delete mode 100644 bsp/gd32103c-eval/SConstruct delete mode 100644 bsp/gd32103c-eval/applications/SConscript delete mode 100644 bsp/gd32103c-eval/applications/main.c delete mode 100644 bsp/gd32103c-eval/drivers/SConscript delete mode 100644 bsp/gd32103c-eval/drivers/board.c delete mode 100644 bsp/gd32103c-eval/drivers/board.h delete mode 100644 bsp/gd32103c-eval/drivers/drv_adc.h delete mode 100644 bsp/gd32103c-eval/drivers/drv_comm.h delete mode 100644 bsp/gd32103c-eval/drivers/drv_gpio.c delete mode 100644 bsp/gd32103c-eval/drivers/drv_gpio.h delete mode 100644 bsp/gd32103c-eval/drivers/drv_hwtimer.h delete mode 100644 bsp/gd32103c-eval/drivers/drv_usart.c delete mode 100644 bsp/gd32103c-eval/drivers/drv_usart.h delete mode 100644 bsp/gd32103c-eval/gd32_rom.ld delete mode 100644 bsp/gd32103c-eval/rtconfig.h delete mode 100644 bsp/gd32103c-eval/rtconfig.py diff --git a/bsp/gd32/gd32103c-eval/board/Kconfig b/bsp/gd32/gd32103c-eval/board/Kconfig index 01d1240fce..354d212994 100644 --- a/bsp/gd32/gd32103c-eval/board/Kconfig +++ b/bsp/gd32/gd32103c-eval/board/Kconfig @@ -74,12 +74,66 @@ menu "On-chip Peripheral Drivers" range 1 216 default 25 endif + + config BSP_USING_WDT + bool "Enable Watchdog Timer" + select RT_USING_WDT + default n + + config BSP_USING_RTC + bool "Enable Internal RTC" + select RT_USING_RTC + default n + + menuconfig BSP_USING_HWTIMER + bool "Enable hwtimer" + default n + select RT_USING_HWTIMER + if BSP_USING_HWTIMER + config BSP_USING_HWTIMER0 + bool "using hwtimer0" + default n + config BSP_USING_HWTIMER1 + bool "using hwtimer1" + default n + config BSP_USING_HWTIMER2 + bool "using hwtimer2" + default n + config BSP_USING_HWTIMER3 + bool "using hwtimer3" + default n + config BSP_USING_HWTIMER4 + bool "using hwtimer4" + default n + config BSP_USING_HWTIMER5 + bool "using hwtimer5" + default n + config BSP_USING_HWTIMER6 + bool "using hwtimer6" + default n + config BSP_USING_HWTIMER7 + bool "using hwtimer7" + default n + endif + + menuconfig BSP_USING_ADC + bool "Enable ADC" + default n + select RT_USING_ADC + if BSP_USING_ADC + config BSP_USING_ADC0 + bool "using adc0" + default n + config BSP_USING_ADC1 + bool "using adc1" + default n + endif source "../libraries/gd32_drivers/Kconfig" - + endmenu menu "Board extended module Drivers" endmenu - + endmenu diff --git a/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript b/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript index f5004445c0..889e33dd2a 100644 --- a/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript +++ b/bsp/gd32/libraries/GD32F10x_Firmware_Library/SConscript @@ -40,6 +40,7 @@ if GetDepend(['RT_USING_HWTIMER']): if GetDepend(['RT_USING_RTC']): src += ['GD32F10x_standard_peripheral/Source/gd32f10x_rtc.c'] + src += ['GD32F10x_standard_peripheral/Source/gd32f10x_pmu.c'] if GetDepend(['RT_USING_WDT']): src += ['GD32F10x_standard_peripheral/Source/gd32f10x_wwdgt.c'] diff --git a/bsp/gd32/libraries/gd32_drivers/SConscript b/bsp/gd32/libraries/gd32_drivers/SConscript index b33b2c5768..16a76e2b0b 100644 --- a/bsp/gd32/libraries/gd32_drivers/SConscript +++ b/bsp/gd32/libraries/gd32_drivers/SConscript @@ -27,9 +27,21 @@ if GetDepend('RT_USING_SPI'): # add spi flash drivers. if GetDepend('RT_USING_SFUD'): - src += ['drv_spi_flash.c', 'drv_spi.c'] + src += ['drv_spi_flash.c', 'drv_spi.c'] -path = [cwd] +if GetDepend('RT_USING_WDT'): + src += ['drv_wdt.c'] + +if GetDepend('RT_USING_RTC'): + src += ['drv_rtc.c'] + +if GetDepend('RT_USING_HWTIMER'): + src += ['drv_hwtimer.c'] + +if GetDepend('RT_USING_ADC'): + src += ['drv_adc.c'] + +path = [cwd] group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) diff --git a/bsp/gd32103c-eval/drivers/drv_adc.c b/bsp/gd32/libraries/gd32_drivers/drv_adc.c similarity index 63% rename from bsp/gd32103c-eval/drivers/drv_adc.c rename to bsp/gd32/libraries/gd32_drivers/drv_adc.c index 65e781e40c..bd3b2d6b63 100644 --- a/bsp/gd32103c-eval/drivers/drv_adc.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_adc.c @@ -1,15 +1,14 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2021-01-03 iysheng first version + * 2021-02-25 iysheng first version */ #include -#include #include #define DBG_TAG "drv.adc" @@ -39,7 +38,7 @@ static gd32_adc_device g_gd32_devs[] = { GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5), }, - ADC0, + (void *)ADC0, }, #endif @@ -53,7 +52,7 @@ static gd32_adc_device g_gd32_devs[] = { GET_PIN(B, 0), GET_PIN(B, 1), GET_PIN(C, 0), GET_PIN(C, 1), GET_PIN(C, 2), GET_PIN(C, 3), GET_PIN(C, 4), GET_PIN(C, 5), }, - ADC1, + (void *)ADC1, }, #endif }; @@ -61,53 +60,41 @@ static gd32_adc_device g_gd32_devs[] = { /* * static void init_pin4adc * - * 初始化指定的管腳爲 analog 模式 * @ rt_uint32_t pin: pin information * return: N/A */ static void init_pin4adc(rt_base_t pin) { - GPIO_InitPara GPIO_InitStruct = {0}; - - GPIO_InitStruct.GPIO_Pin = PIN_GDPIN(pin); - GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_50MHZ; - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_AIN; - GPIO_Init(PIN_GDPORT(pin), &GPIO_InitStruct); + gpio_init(PIN_GDPORT(pin), GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, PIN_GDPIN(pin)); } static rt_err_t gd32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) { - ADC_TypeDef *ADCx; - ADC_InitPara ADC_InitParaStruct = {0}; + uint32_t adc_periph; gd32_adc_device * gd32_adc = (gd32_adc_device *)device; if (channel >= MAX_EXTERN_ADC_CHANNEL) { LOG_E("invalid channel"); - return -E2BIG; + return -RT_EINVAL; } - ADCx = (ADC_TypeDef *)(device->parent.user_data); + adc_periph = (uint32_t )(device->parent.user_data); if (enabled == ENABLE) { init_pin4adc(gd32_adc->adc_pins[channel]); - ADC_InitParaStruct.ADC_Trig_External = ADC_EXTERNAL_TRIGGER_MODE_NONE; - /* Fix the channel number to fit the firmware library */ - ADC_InitParaStruct.ADC_Channel_Number = 1 + channel; - ADC_InitParaStruct.ADC_Data_Align = ADC_DATAALIGN_RIGHT; - ADC_InitParaStruct.ADC_Mode_Scan = DISABLE; - ADC_InitParaStruct.ADC_Mode = ADC_MODE_INDEPENDENT; - ADC_InitParaStruct.ADC_Mode_Continuous = ENABLE; - ADC_Init(ADCx, &ADC_InitParaStruct); - - ADC_RegularChannel_Config(ADCx, channel, 1, ADC_SAMPLETIME_13POINT5); - ADC_Enable(ADCx, ENABLE); - ADC_SoftwareStartConv_Enable(ADCx, ENABLE); + adc_deinit(adc_periph); + adc_channel_length_config(adc_periph, ADC_REGULAR_CHANNEL, 1); + adc_data_alignment_config(adc_periph, ADC_DATAALIGN_RIGHT); + adc_external_trigger_source_config(adc_periph, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_INSERTED_NONE); + adc_external_trigger_config(adc_periph, ADC_REGULAR_CHANNEL, ENABLE); + adc_regular_channel_config(adc_periph, 0, channel, ADC_SAMPLETIME_13POINT5); + adc_enable(adc_periph); } else { - ADC_Enable(ADCx, DISABLE); + adc_disable(adc_periph); } return 0; @@ -115,16 +102,17 @@ static rt_err_t gd32_adc_enabled(struct rt_adc_device *device, rt_uint32_t chann static rt_err_t gd32_adc_convert(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) { - ADC_TypeDef *ADCx; + uint32_t adc_periph; if (!value) { LOG_E("invalid param"); - return -EINVAL; + return -RT_EINVAL; } - ADCx = (ADC_TypeDef *)(device->parent.user_data); - *value = ADC_GetConversionValue(ADCx); + adc_periph = (uint32_t )(device->parent.user_data); + adc_software_trigger_enable(adc_periph, ADC_REGULAR_CHANNEL); + *value = adc_regular_data_read(adc_periph); return 0; } @@ -148,11 +136,11 @@ static int rt_hw_adc_init(void) rcu_periph_clock_enable(RCU_ADC1); #endif - for (; i < ARRAY_SIZE(g_gd32_devs); i++) + for (; i < sizeof(g_gd32_devs) / sizeof(g_gd32_devs[0]); i++) { ret = rt_hw_adc_register(&g_gd32_devs[i].adc_dev, \ (const char *)g_gd32_devs[i].name, \ - &g_gd32_adc_ops, g_gd32_devs[i].private_data); + &g_gd32_adc_ops, (void *)g_gd32_devs[i].private_data); if (ret != RT_EOK) { /* TODO err handler */ diff --git a/bsp/gd32/libraries/gd32_drivers/drv_gpio.h b/bsp/gd32/libraries/gd32_drivers/drv_gpio.h index 9300191198..5258a4f5ac 100644 --- a/bsp/gd32/libraries/gd32_drivers/drv_gpio.h +++ b/bsp/gd32/libraries/gd32_drivers/drv_gpio.h @@ -38,7 +38,7 @@ extern "C" { EXTI_SOURCE_PIN##pin} #else #define GD32_PIN(index, port, pin) {index, RCU_GPIO##port, \ - GPIO##port, GPIO_PIN_##pin, \ + GPIO##port, GPIO_PIN_##pin, \ GPIO_PORT_SOURCE_GPIO##port, \ GPIO_PIN_SOURCE_##pin} @@ -48,6 +48,12 @@ extern "C" { #define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__GD32_PORT(PORTx) - (rt_base_t)GPIO_BASE)/(0x0400UL) )) + PIN) +#define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu)) +#define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) + +#define PIN_GDPORT(pin) (GPIO_BASE + (0x400u * PIN_PORT(pin))) +#define PIN_GDPIN(pin) ((uint16_t)(1u << PIN_NO(pin))) + struct pin_index { rt_int16_t index; diff --git a/bsp/gd32103c-eval/drivers/drv_hwtimer.c b/bsp/gd32/libraries/gd32_drivers/drv_hwtimer.c similarity index 75% rename from bsp/gd32103c-eval/drivers/drv_hwtimer.c rename to bsp/gd32/libraries/gd32_drivers/drv_hwtimer.c index 8b5f5010e6..1c22b10467 100644 --- a/bsp/gd32103c-eval/drivers/drv_hwtimer.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_hwtimer.c @@ -1,19 +1,32 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2021-01-28 iysheng first version + * 2021-02-25 iysheng first version */ #include -#include -#include +#include +#include #ifdef BSP_USING_HWTIMER +typedef struct { + uint32_t reg_base; + IRQn_Type irqn; + rcu_periph_enum rcu; +} gd32_hwtimer_data; + +typedef struct { + char dev_name[RT_NAME_MAX]; + const gd32_hwtimer_data hw_data; + rt_hwtimer_t hwtimer_dev; + const struct rt_hwtimer_info hwtimer_info; +} gd32_hwtimer_device; + enum timer_index_E { #ifdef BSP_USING_HWTIMER0 TIM0_INDEX, @@ -67,49 +80,48 @@ enum timer_index_E { * @param freq of the timer clock * @retval None */ -static void __set_timerx_freq(TIMER_TypeDef *timerx, uint32_t freq) +static void __set_timerx_freq(uint32_t timerx, uint32_t freq) { - RCC_ClocksPara RCC_Clocks = {0}; + uint32_t ap1freq, ap2freq; uint16_t prescaler; uint32_t temp; - RCC_GetClocksFreq(&RCC_Clocks); if (timerx == TIMER0 || timerx == TIMER7 || timerx == TIMER8 \ || timerx == TIMER9 || timerx == TIMER10) { - temp = RCC->GCFGR & RCC_GCFGR_APB2PS; + ap2freq = rcu_clock_freq_get(CK_APB2); + temp = RCU_CFG0 & RCU_CFG0_APB2PSC; temp >>= 11; /* whether should frequency doubling */ temp = (temp < 4) ? 0 : 1; - prescaler = (RCC_Clocks.APB2_Frequency << temp) / freq - 1; + prescaler = (ap2freq << temp) / freq - 1; } else { - temp = RCC->GCFGR & RCC_GCFGR_APB1PS; + ap1freq = rcu_clock_freq_get(CK_APB1); + temp = RCU_CFG0 & RCU_CFG0_APB1PSC; temp >>= 8; /* whether should frequency doubling */ temp = (temp < 4) ? 0 : 1; - prescaler = (RCC_Clocks.APB1_Frequency << temp) / freq - 1; + prescaler = (ap1freq << temp) / freq - 1; } - TIMER_PrescalerConfig(timerx, prescaler, TIMER_PSC_RELOAD_NOW); + timer_prescaler_config(timerx, prescaler, TIMER_PSC_RELOAD_NOW); } static void gd32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state) { - TIMER_TypeDef * timer_base = timer->parent.user_data; - TIMER_BaseInitPara TIMER_Init; - - RT_ASSERT(timer_base); + uint32_t timer_base = (uint32_t)timer->parent.user_data; + timer_parameter_struct initpara; if (state) { - TIMER_InternalClockConfig(timer_base); - TIMER_BaseStructInit(&TIMER_Init); - TIMER_Init.TIMER_Period = timer->info->maxcnt; - TIMER_BaseInit(timer_base, &TIMER_Init); + timer_internal_clock_config(timer_base); + timer_struct_para_init(&initpara); + initpara.period = timer->info->maxcnt; + timer_init(timer_base, &initpara); __set_timerx_freq(timer_base, timer->info->maxfreq); } } @@ -117,37 +129,37 @@ static void gd32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state static rt_err_t gd32_hwtimer_start(struct rt_hwtimer_device *timer, \ rt_uint32_t cnt, rt_hwtimer_mode_t mode) { - TIMER_TypeDef * timer_base = timer->parent.user_data; + uint32_t timer_base = (uint32_t)timer->parent.user_data; if (mode == HWTIMER_MODE_ONESHOT) { - TIMER_SinglePulseMode(timer_base, TIMER_SP_MODE_SINGLE); + timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_SINGLE); } else if (mode == HWTIMER_MODE_PERIOD) { - TIMER_SinglePulseMode(timer_base, TIMER_SP_MODE_REPETITIVE); + timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_REPETITIVE); } - TIMER_SetCounter(timer_base, 0); - TIMER_SetAutoreload(timer_base, cnt - 1); - TIMER_Enable(timer_base, ENABLE); + timer_counter_value_config(timer_base, 0); + timer_autoreload_value_config(timer_base, cnt - 1); + timer_enable(timer_base); return 0; } static void gd32_hwtimer_stop(struct rt_hwtimer_device *timer) { - TIMER_TypeDef * timer_base = timer->parent.user_data; + uint32_t timer_base = (uint32_t)timer->parent.user_data; - TIMER_Enable(timer_base, DISABLE); + timer_disable(timer_base); } static rt_uint32_t gd32_hwtimer_count_get(struct rt_hwtimer_device *timer) { - TIMER_TypeDef * timer_base = timer->parent.user_data; + uint32_t timer_base = (uint32_t)timer->parent.user_data; rt_uint32_t count; - count = TIMER_GetCounter(timer_base); + count = timer_counter_read(timer_base); return count; } @@ -163,11 +175,11 @@ static rt_err_t gd32_hwtimer_control(struct rt_hwtimer_device *timer, rt_uint32_ { case HWTIMER_CTRL_FREQ_SET: freq = *(rt_uint32_t *)args; - __set_timerx_freq(timer->parent.user_data, freq); + __set_timerx_freq((uint32_t)timer->parent.user_data, freq); break; default: rt_kprintf("invalid cmd:%x\n", cmd); - ret = -EINVAL; + ret = -RT_EINVAL; break; } @@ -428,8 +440,8 @@ void TIMER0_UP_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -439,8 +451,8 @@ void TIMER1_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -450,8 +462,8 @@ void TIMER2_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -461,8 +473,8 @@ void TIMER3_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -472,8 +484,8 @@ void TIMER4_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -483,8 +495,8 @@ void TIMER5_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -494,8 +506,8 @@ void TIMER6_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -505,8 +517,8 @@ void TIMER7_UP_IRQHandler(void) { rt_interrupt_enter(); rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev); - TIMER_ClearIntBitState(g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev.parent.user_data, \ - TIMER_INT_UPDATE); + timer_flag_clear((uint32_t)g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev.parent.user_data, \ + TIMER_INT_UP); rt_interrupt_leave(); } #endif @@ -515,7 +527,7 @@ static int rt_hwtimer_init(void) { int ret = 0, i = 0; - for (; i < ARRAY_SIZE(g_gd32_hwtimer); i++) + for (; i < sizeof(g_gd32_hwtimer) / sizeof(g_gd32_hwtimer[0]); i++) { g_gd32_hwtimer[i].hwtimer_dev.ops = &g_gd32_hwtimer_ops; g_gd32_hwtimer[i].hwtimer_dev.info = &g_gd32_hwtimer[i].hwtimer_info; @@ -523,9 +535,9 @@ static int rt_hwtimer_init(void) rcu_periph_clock_enable(g_gd32_hwtimer[i].hw_data.rcu); NVIC_SetPriority(g_gd32_hwtimer[i].hw_data.irqn, 0); NVIC_EnableIRQ(g_gd32_hwtimer[i].hw_data.irqn); - TIMER_INTConfig(g_gd32_hwtimer[i].hw_data.reg_base, TIMER_INT_UPDATE, ENABLE); + timer_interrupt_enable(g_gd32_hwtimer[i].hw_data.reg_base, TIMER_INT_UP); ret = rt_device_hwtimer_register(&g_gd32_hwtimer[i].hwtimer_dev, \ - g_gd32_hwtimer[i].dev_name, g_gd32_hwtimer[i].hw_data.reg_base); + g_gd32_hwtimer[i].dev_name, (void *)g_gd32_hwtimer[i].hw_data.reg_base); if (RT_EOK != ret) { rt_kprintf("failed register %s, err=%d\n", g_gd32_hwtimer[i].dev_name, \ diff --git a/bsp/gd32103c-eval/drivers/drv_rtc.c b/bsp/gd32/libraries/gd32_drivers/drv_rtc.c similarity index 89% rename from bsp/gd32103c-eval/drivers/drv_rtc.c rename to bsp/gd32/libraries/gd32_drivers/drv_rtc.c index 95c6e56e9d..4ed2a31f38 100644 --- a/bsp/gd32103c-eval/drivers/drv_rtc.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_rtc.c @@ -1,16 +1,15 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2021-02-20 iysheng first version + * 2022-01-25 iysheng first version */ #include #include -#include #define DBG_TAG "drv.rtc" #define DBG_LVL DBG_INFO @@ -29,7 +28,7 @@ static time_t get_rtc_timestamp(void) { time_t rtc_counter; - rtc_counter = (time_t)RTC_GetCounter(); + rtc_counter = (time_t)rtc_counter_get(); return rtc_counter; } @@ -41,15 +40,15 @@ static rt_err_t set_rtc_timestamp(time_t time_stamp) rtc_counter = (uint32_t)time_stamp; /* wait until LWOFF bit in RTC_CTL to 1 */ - RTC_WaitLWOFF(); + rtc_lwoff_wait(); /* enter configure mode */ - RTC_EnterConfigMode(); + rtc_configuration_mode_enter(); /* write data to rtc register */ - RTC_SetCounter(rtc_counter); + rtc_counter_set(rtc_counter); /* exit configure mode */ - RTC_ExitConfigMode(); + rtc_configuration_mode_exit(); /* wait until LWOFF bit in RTC_CTL to 1 */ - RTC_WaitLWOFF(); + rtc_lwoff_wait(); return RT_EOK; } @@ -94,7 +93,7 @@ static int rt_hw_rtc_init(void) time_t rtc_counter; rcu_periph_clock_enable(RCU_PMU); - PWR_BackupAccess_Enable(ENABLE); + pmu_backup_write_enable(); rcu_periph_clock_enable(RCU_BKPI); rtc_counter = get_rtc_timestamp(); diff --git a/bsp/gd32103c-eval/drivers/drv_iwdt.c b/bsp/gd32/libraries/gd32_drivers/drv_wdt.c similarity index 69% rename from bsp/gd32103c-eval/drivers/drv_iwdt.c rename to bsp/gd32/libraries/gd32_drivers/drv_wdt.c index f218f46104..8ef5096caf 100644 --- a/bsp/gd32103c-eval/drivers/drv_iwdt.c +++ b/bsp/gd32/libraries/gd32_drivers/drv_wdt.c @@ -1,11 +1,11 @@ /* - * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2021-03-03 iysheng first version + * 2022-01-25 iysheng first version */ #include @@ -25,13 +25,13 @@ typedef struct { static gd32_wdt_device_t g_wdt_dev; -static rt_err_t gd32_iwdt_init(rt_watchdog_t *wdt) +static rt_err_t gd32_wdt_init(rt_watchdog_t *wdt) { rcu_osci_on(RCU_IRC40K); if (ERROR == rcu_osci_stab_wait(RCU_IRC40K)) { LOG_E("failed init IRC40K clock for free watchdog."); - return -EINVAL; + return -RT_EINVAL; } g_wdt_dev.min_threshold_s = 1; @@ -39,22 +39,21 @@ static rt_err_t gd32_iwdt_init(rt_watchdog_t *wdt) LOG_I("threshold section [%u, %d]", \ g_wdt_dev.min_threshold_s, g_wdt_dev.max_threshold_s); - IWDG_Write_Enable(IWDG_WRITEACCESS_ENABLE); - IWDG_SetPrescaler(IWDG_PRESCALER_256); - IWDG_SetReloadValue(0xfff); - IWDG_Write_Enable(IWDG_WRITEACCESS_DISABLE); + fwdgt_write_enable(); + fwdgt_config(0xfff, FWDGT_PSC_DIV256); + fwdgt_enable(); return 0; } -static rt_err_t gd32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg) +static rt_err_t gd32_wdt_control(rt_watchdog_t *wdt, int cmd, void *arg) { rt_uint32_t param; switch (cmd) { case RT_DEVICE_CTRL_WDT_KEEPALIVE: - IWDG_ReloadCounter(); + fwdgt_counter_reload(); break; case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: param = *(rt_uint32_t *) arg; @@ -62,21 +61,21 @@ static rt_err_t gd32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg) (param < g_wdt_dev.min_threshold_s)) { LOG_E("invalid param@%u.", param); - return -E2BIG; + return -RT_EINVAL; } else { g_wdt_dev.current_threshold_s = param; } - IWDG_Write_Enable(IWDG_WRITEACCESS_ENABLE); - IWDG_SetReloadValue(param * 40000 >> 8); - IWDG_Write_Enable(IWDG_WRITEACCESS_DISABLE); + fwdgt_write_enable(); + fwdgt_config(param * 40000 >> 8, FWDGT_PSC_DIV256); + fwdgt_write_disable(); break; case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: *(rt_uint32_t *)arg = g_wdt_dev.current_threshold_s; break; case RT_DEVICE_CTRL_WDT_START: - IWDG_Enable(); + fwdgt_enable(); break; default: LOG_W("This command is not supported."); @@ -87,17 +86,17 @@ static rt_err_t gd32_iwdt_control(rt_watchdog_t *wdt, int cmd, void *arg) } static struct rt_watchdog_ops g_wdt_ops = { - gd32_iwdt_init, - gd32_iwdt_control, + gd32_wdt_init, + gd32_wdt_control, }; -static int rt_hw_iwdt_init(void) +static int rt_hw_wdt_init(void) { rt_err_t ret; g_wdt_dev.wdt.ops = &g_wdt_ops; /* register watchdog device */ - if (rt_hw_watchdog_register(&g_wdt_dev.wdt, "iwdt", \ + if (rt_hw_watchdog_register(&g_wdt_dev.wdt, "wdt", \ RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK) { LOG_E("wdt device register failed."); @@ -107,5 +106,5 @@ static int rt_hw_iwdt_init(void) return ret; } -INIT_BOARD_EXPORT(rt_hw_iwdt_init); +INIT_PREV_EXPORT(rt_hw_wdt_init); #endif diff --git a/bsp/gd32103c-eval/.config b/bsp/gd32103c-eval/.config deleted file mode 100644 index de1ea1ac0c..0000000000 --- a/bsp/gd32103c-eval/.config +++ /dev/null @@ -1,672 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# RT-Thread Configuration -# - -# -# RT-Thread Kernel -# -CONFIG_RT_NAME_MAX=8 -# CONFIG_RT_USING_BIG_ENDIAN is not set -# CONFIG_RT_USING_ARCH_DATA_TYPE is not set -# CONFIG_RT_USING_SMP is not set -CONFIG_RT_ALIGN_SIZE=4 -# CONFIG_RT_THREAD_PRIORITY_8 is not set -CONFIG_RT_THREAD_PRIORITY_32=y -# CONFIG_RT_THREAD_PRIORITY_256 is not set -CONFIG_RT_THREAD_PRIORITY_MAX=32 -CONFIG_RT_TICK_PER_SECOND=100 -CONFIG_RT_USING_OVERFLOW_CHECK=y -CONFIG_RT_USING_HOOK=y -CONFIG_RT_HOOK_USING_FUNC_PTR=y -CONFIG_RT_USING_IDLE_HOOK=y -CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 -CONFIG_IDLE_THREAD_STACK_SIZE=256 -CONFIG_RT_USING_TIMER_SOFT=y -CONFIG_RT_TIMER_THREAD_PRIO=4 -CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 - -# -# kservice optimization -# -# CONFIG_RT_KSERVICE_USING_STDLIB is not set -# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set -# CONFIG_RT_USING_TINY_FFS is not set -# CONFIG_RT_PRINTF_LONGLONG is not set -CONFIG_RT_DEBUG=y -# CONFIG_RT_DEBUG_COLOR is not set -# CONFIG_RT_DEBUG_INIT_CONFIG is not set -# CONFIG_RT_DEBUG_THREAD_CONFIG is not set -# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set -# CONFIG_RT_DEBUG_IPC_CONFIG is not set -# CONFIG_RT_DEBUG_TIMER_CONFIG is not set -# CONFIG_RT_DEBUG_IRQ_CONFIG is not set -# CONFIG_RT_DEBUG_MEM_CONFIG is not set -# CONFIG_RT_DEBUG_SLAB_CONFIG is not set -# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set -# CONFIG_RT_DEBUG_MODULE_CONFIG is not set - -# -# Inter-Thread communication -# -CONFIG_RT_USING_SEMAPHORE=y -CONFIG_RT_USING_MUTEX=y -CONFIG_RT_USING_EVENT=y -CONFIG_RT_USING_MAILBOX=y -CONFIG_RT_USING_MESSAGEQUEUE=y -# CONFIG_RT_USING_SIGNALS is not set - -# -# Memory Management -# -CONFIG_RT_USING_MEMPOOL=y -CONFIG_RT_USING_SMALL_MEM=y -# CONFIG_RT_USING_SLAB is not set -# CONFIG_RT_USING_MEMHEAP is not set -CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y -# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set -# CONFIG_RT_USING_SLAB_AS_HEAP is not set -# CONFIG_RT_USING_USERHEAP is not set -# CONFIG_RT_USING_NOHEAP is not set -# CONFIG_RT_USING_MEMTRACE is not set -# CONFIG_RT_USING_HEAP_ISR is not set -CONFIG_RT_USING_HEAP=y - -# -# Kernel Device Object -# -CONFIG_RT_USING_DEVICE=y -# CONFIG_RT_USING_DEVICE_OPS is not set -# CONFIG_RT_USING_INTERRUPT_INFO is not set -CONFIG_RT_USING_CONSOLE=y -CONFIG_RT_CONSOLEBUF_SIZE=128 -CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x40100 -# CONFIG_RT_USING_CPU_FFS is not set -# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set - -# -# RT-Thread Components -# -CONFIG_RT_USING_COMPONENTS_INIT=y -CONFIG_RT_USING_USER_MAIN=y -CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 -CONFIG_RT_MAIN_THREAD_PRIORITY=10 -# CONFIG_RT_USING_LEGACY is not set - -# -# C++ features -# -# CONFIG_RT_USING_CPLUSPLUS is not set - -# -# Command shell -# -CONFIG_RT_USING_FINSH=y -CONFIG_RT_USING_MSH=y -CONFIG_FINSH_USING_MSH=y -CONFIG_FINSH_THREAD_NAME="tshell" -CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 -CONFIG_FINSH_USING_HISTORY=y -CONFIG_FINSH_HISTORY_LINES=5 -CONFIG_FINSH_USING_SYMTAB=y -CONFIG_FINSH_CMD_SIZE=80 -CONFIG_MSH_USING_BUILT_IN_COMMANDS=y -CONFIG_FINSH_USING_DESCRIPTION=y -# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set -# CONFIG_FINSH_USING_AUTH is not set -CONFIG_FINSH_ARG_MAX=10 - -# -# Device virtual file system -# -CONFIG_RT_USING_DFS=y -CONFIG_DFS_USING_POSIX=y -CONFIG_DFS_USING_WORKDIR=y -CONFIG_DFS_FILESYSTEMS_MAX=2 -CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 -CONFIG_DFS_FD_MAX=16 -# CONFIG_RT_USING_DFS_MNTTABLE is not set -# CONFIG_RT_USING_DFS_ELMFAT is not set -CONFIG_RT_USING_DFS_DEVFS=y -# CONFIG_RT_USING_DFS_ROMFS is not set -# CONFIG_RT_USING_DFS_RAMFS is not set - -# -# Device Drivers -# -CONFIG_RT_USING_DEVICE_IPC=y -# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set -CONFIG_RT_USING_SERIAL=y -CONFIG_RT_USING_SERIAL_V1=y -# CONFIG_RT_USING_SERIAL_V2 is not set -CONFIG_RT_SERIAL_USING_DMA=y -CONFIG_RT_SERIAL_RB_BUFSZ=64 -# CONFIG_RT_USING_CAN is not set -# CONFIG_RT_USING_HWTIMER is not set -# CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set -# CONFIG_RT_USING_PHY is not set -CONFIG_RT_USING_PIN=y -# CONFIG_RT_USING_ADC is not set -# CONFIG_RT_USING_DAC is not set -# CONFIG_RT_USING_PWM is not set -# CONFIG_RT_USING_MTD_NOR is not set -# CONFIG_RT_USING_MTD_NAND is not set -# CONFIG_RT_USING_PM is not set -# CONFIG_RT_USING_RTC is not set -# CONFIG_RT_USING_SDIO is not set -# CONFIG_RT_USING_SPI is not set -# CONFIG_RT_USING_WDT is not set -# CONFIG_RT_USING_AUDIO is not set -# CONFIG_RT_USING_SENSOR is not set -# CONFIG_RT_USING_TOUCH is not set -# CONFIG_RT_USING_HWCRYPTO is not set -# CONFIG_RT_USING_PULSE_ENCODER is not set -# CONFIG_RT_USING_INPUT_CAPTURE is not set -# CONFIG_RT_USING_WIFI is not set - -# -# Using USB -# -# CONFIG_RT_USING_USB is not set -# CONFIG_RT_USING_USB_HOST is not set -# CONFIG_RT_USING_USB_DEVICE is not set - -# -# POSIX layer and C standard library -# -# CONFIG_RT_USING_MODULE is not set -CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 - -# -# POSIX (Portable Operating System Interface) layer -# -# CONFIG_RT_USING_POSIX_FS is not set -# CONFIG_RT_USING_POSIX_DELAY is not set -# CONFIG_RT_USING_POSIX_CLOCK is not set -# CONFIG_RT_USING_PTHREADS is not set - -# -# Interprocess Communication (IPC) -# -# CONFIG_RT_USING_POSIX_PIPE is not set -# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set -# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set - -# -# Socket is in the 'Network' category -# - -# -# Network -# - -# -# Socket abstraction layer -# -# CONFIG_RT_USING_SAL is not set - -# -# Network interface device -# -# CONFIG_RT_USING_NETDEV is not set - -# -# light weight TCP/IP stack -# -# CONFIG_RT_USING_LWIP is not set - -# -# AT commands -# -# CONFIG_RT_USING_AT is not set - -# -# VBUS(Virtual Software BUS) -# -# CONFIG_RT_USING_VBUS is not set - -# -# Utilities -# -# CONFIG_RT_USING_RYM is not set -# CONFIG_RT_USING_ULOG is not set -# CONFIG_RT_USING_UTEST is not set -# CONFIG_RT_USING_VAR_EXPORT is not set -# CONFIG_RT_USING_RT_LINK is not set - -# -# RT-Thread Utestcases -# -# CONFIG_RT_USING_UTESTCASES is not set - -# -# RT-Thread online packages -# - -# -# IoT - internet of things -# -# CONFIG_PKG_USING_LORAWAN_DRIVER is not set -# CONFIG_PKG_USING_PAHOMQTT is not set -# CONFIG_PKG_USING_UMQTT is not set -# CONFIG_PKG_USING_WEBCLIENT is not set -# CONFIG_PKG_USING_WEBNET is not set -# CONFIG_PKG_USING_MONGOOSE is not set -# CONFIG_PKG_USING_MYMQTT is not set -# CONFIG_PKG_USING_KAWAII_MQTT is not set -# CONFIG_PKG_USING_BC28_MQTT is not set -# CONFIG_PKG_USING_WEBTERMINAL is not set -# CONFIG_PKG_USING_CJSON is not set -# CONFIG_PKG_USING_JSMN is not set -# CONFIG_PKG_USING_LIBMODBUS is not set -# CONFIG_PKG_USING_FREEMODBUS is not set -# CONFIG_PKG_USING_LJSON is not set -# CONFIG_PKG_USING_EZXML is not set -# CONFIG_PKG_USING_NANOPB is not set - -# -# Wi-Fi -# - -# -# Marvell WiFi -# -# CONFIG_PKG_USING_WLANMARVELL is not set - -# -# Wiced WiFi -# -# CONFIG_PKG_USING_WLAN_WICED is not set -# CONFIG_PKG_USING_RW007 is not set -# CONFIG_PKG_USING_COAP is not set -# CONFIG_PKG_USING_NOPOLL is not set -# CONFIG_PKG_USING_NETUTILS is not set -# CONFIG_PKG_USING_CMUX is not set -# CONFIG_PKG_USING_PPP_DEVICE is not set -# CONFIG_PKG_USING_AT_DEVICE is not set -# CONFIG_PKG_USING_ATSRV_SOCKET is not set -# CONFIG_PKG_USING_WIZNET is not set -# CONFIG_PKG_USING_ZB_COORDINATOR is not set - -# -# IoT Cloud -# -# CONFIG_PKG_USING_ONENET is not set -# CONFIG_PKG_USING_GAGENT_CLOUD is not set -# CONFIG_PKG_USING_ALI_IOTKIT is not set -# CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set -# CONFIG_PKG_USING_JIOT-C-SDK is not set -# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set -# CONFIG_PKG_USING_JOYLINK is not set -# CONFIG_PKG_USING_EZ_IOT_OS is not set -# CONFIG_PKG_USING_NIMBLE is not set -# CONFIG_PKG_USING_OTA_DOWNLOADER is not set -# CONFIG_PKG_USING_IPMSG is not set -# CONFIG_PKG_USING_LSSDP is not set -# CONFIG_PKG_USING_AIRKISS_OPEN is not set -# CONFIG_PKG_USING_LIBRWS is not set -# CONFIG_PKG_USING_TCPSERVER is not set -# CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_DLT645 is not set -# CONFIG_PKG_USING_QXWZ is not set -# CONFIG_PKG_USING_SMTP_CLIENT is not set -# CONFIG_PKG_USING_ABUP_FOTA is not set -# CONFIG_PKG_USING_LIBCURL2RTT is not set -# CONFIG_PKG_USING_CAPNP is not set -# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set -# CONFIG_PKG_USING_AGILE_TELNET is not set -# CONFIG_PKG_USING_NMEALIB is not set -# CONFIG_PKG_USING_AGILE_JSMN is not set -# CONFIG_PKG_USING_PDULIB is not set -# CONFIG_PKG_USING_BTSTACK is not set -# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set -# CONFIG_PKG_USING_WAYZ_IOTKIT is not set -# CONFIG_PKG_USING_MAVLINK is not set -# CONFIG_PKG_USING_RAPIDJSON is not set -# CONFIG_PKG_USING_BSAL is not set -# CONFIG_PKG_USING_AGILE_MODBUS is not set -# CONFIG_PKG_USING_AGILE_FTP is not set -# CONFIG_PKG_USING_EMBEDDEDPROTO is not set -# CONFIG_PKG_USING_RT_LINK_HW is not set -# CONFIG_PKG_USING_LORA_PKT_FWD is not set -# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set -# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set -# CONFIG_PKG_USING_HM is not set -# CONFIG_PKG_USING_SMALL_MODBUS is not set -# CONFIG_PKG_USING_NET_SERVER is not set - -# -# security packages -# -# CONFIG_PKG_USING_MBEDTLS is not set -# CONFIG_PKG_USING_LIBSODIUM is not set -# CONFIG_PKG_USING_TINYCRYPT is not set -# CONFIG_PKG_USING_TFM is not set -# CONFIG_PKG_USING_YD_CRYPTO is not set - -# -# language packages -# -# CONFIG_PKG_USING_LUATOS_SOC is not set -# CONFIG_PKG_USING_LUA is not set -# CONFIG_PKG_USING_JERRYSCRIPT is not set -# CONFIG_PKG_USING_MICROPYTHON is not set -# CONFIG_PKG_USING_PIKASCRIPT is not set - -# -# multimedia packages -# - -# -# LVGL: powerful and easy-to-use embedded GUI library -# -# CONFIG_PKG_USING_LVGL is not set -# CONFIG_PKG_USING_LITTLEVGL2RTT is not set -# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set - -# -# u8g2: a monochrome graphic library -# -# CONFIG_PKG_USING_U8G2_OFFICIAL is not set -# CONFIG_PKG_USING_U8G2 is not set -# CONFIG_PKG_USING_OPENMV is not set -# CONFIG_PKG_USING_MUPDF is not set -# CONFIG_PKG_USING_STEMWIN is not set -# CONFIG_PKG_USING_WAVPLAYER is not set -# CONFIG_PKG_USING_TJPGD is not set -# CONFIG_PKG_USING_PDFGEN is not set -# CONFIG_PKG_USING_HELIX is not set -# CONFIG_PKG_USING_AZUREGUIX is not set -# CONFIG_PKG_USING_TOUCHGFX2RTT is not set -# CONFIG_PKG_USING_NUEMWIN is not set -# CONFIG_PKG_USING_MP3PLAYER is not set -# CONFIG_PKG_USING_TINYJPEG is not set -# CONFIG_PKG_USING_UGUI is not set - -# -# PainterEngine: A cross-platform graphics application framework written in C language -# -# CONFIG_PKG_USING_PAINTERENGINE is not set -# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set -# CONFIG_PKG_USING_MCURSES is not set -# CONFIG_PKG_USING_TERMBOX is not set -# CONFIG_PKG_USING_VT100 is not set - -# -# tools packages -# -# CONFIG_PKG_USING_CMBACKTRACE is not set -# CONFIG_PKG_USING_EASYFLASH is not set -# CONFIG_PKG_USING_EASYLOGGER is not set -# CONFIG_PKG_USING_SYSTEMVIEW is not set -# CONFIG_PKG_USING_SEGGER_RTT is not set -# CONFIG_PKG_USING_RDB is not set -# CONFIG_PKG_USING_QRCODE is not set -# CONFIG_PKG_USING_ULOG_EASYFLASH is not set -# CONFIG_PKG_USING_ULOG_FILE is not set -# CONFIG_PKG_USING_LOGMGR is not set -# CONFIG_PKG_USING_ADBD is not set -# CONFIG_PKG_USING_COREMARK is not set -# CONFIG_PKG_USING_DHRYSTONE is not set -# CONFIG_PKG_USING_MEMORYPERF is not set -# CONFIG_PKG_USING_NR_MICRO_SHELL is not set -# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set -# CONFIG_PKG_USING_LUNAR_CALENDAR is not set -# CONFIG_PKG_USING_BS8116A is not set -# CONFIG_PKG_USING_GPS_RMC is not set -# CONFIG_PKG_USING_URLENCODE is not set -# CONFIG_PKG_USING_UMCN is not set -# CONFIG_PKG_USING_LWRB2RTT is not set -# CONFIG_PKG_USING_CPU_USAGE is not set -# CONFIG_PKG_USING_GBK2UTF8 is not set -# CONFIG_PKG_USING_VCONSOLE is not set -# CONFIG_PKG_USING_KDB is not set -# CONFIG_PKG_USING_WAMR is not set -# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set -# CONFIG_PKG_USING_LWLOG is not set -# CONFIG_PKG_USING_ANV_TRACE is not set -# CONFIG_PKG_USING_ANV_MEMLEAK is not set -# CONFIG_PKG_USING_ANV_TESTSUIT is not set -# CONFIG_PKG_USING_ANV_BENCH is not set -# CONFIG_PKG_USING_DEVMEM is not set -# CONFIG_PKG_USING_REGEX is not set -# CONFIG_PKG_USING_MEM_SANDBOX is not set -# CONFIG_PKG_USING_SOLAR_TERMS is not set -# CONFIG_PKG_USING_GAN_ZHI is not set -# CONFIG_PKG_USING_FDT is not set - -# -# system packages -# - -# -# enhanced kernel services -# -# CONFIG_PKG_USING_RT_MEMCPY_CM is not set -# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set - -# -# POSIX extension functions -# -# CONFIG_PKG_USING_POSIX_GETLINE is not set -# CONFIG_PKG_USING_POSIX_WCWIDTH is not set -# CONFIG_PKG_USING_POSIX_ITOA is not set - -# -# acceleration: Assembly language or algorithmic acceleration packages -# -# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set -# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set -# CONFIG_PKG_USING_QFPLIB_M3 is not set - -# -# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard -# -# CONFIG_PKG_USING_CMSIS_5 is not set -# CONFIG_PKG_USING_CMSIS_RTOS2 is not set - -# -# Micrium: Micrium software products porting for RT-Thread -# -# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set -# CONFIG_PKG_USING_UCOSII_WRAPPER is not set -# CONFIG_PKG_USING_UC_CRC is not set -# CONFIG_PKG_USING_UC_CLK is not set -# CONFIG_PKG_USING_UC_COMMON is not set -# CONFIG_PKG_USING_UC_MODBUS is not set -# CONFIG_RT_USING_ARDUINO is not set -# CONFIG_PKG_USING_GUIENGINE is not set -# CONFIG_PKG_USING_CAIRO is not set -# CONFIG_PKG_USING_PIXMAN is not set -# CONFIG_PKG_USING_PARTITION is not set -# CONFIG_PKG_USING_FAL is not set -# CONFIG_PKG_USING_FLASHDB is not set -# CONFIG_PKG_USING_SQLITE is not set -# CONFIG_PKG_USING_RTI is not set -# CONFIG_PKG_USING_DFS_YAFFS is not set -# CONFIG_PKG_USING_LITTLEFS is not set -# CONFIG_PKG_USING_DFS_JFFS2 is not set -# CONFIG_PKG_USING_DFS_UFFS is not set -# CONFIG_PKG_USING_LWEXT4 is not set -# CONFIG_PKG_USING_THREAD_POOL is not set -# CONFIG_PKG_USING_ROBOTS is not set -# CONFIG_PKG_USING_EV is not set -# CONFIG_PKG_USING_SYSWATCH is not set -# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set -# CONFIG_PKG_USING_PLCCORE is not set -# CONFIG_PKG_USING_RAMDISK is not set -# CONFIG_PKG_USING_MININI is not set -# CONFIG_PKG_USING_QBOOT is not set -# CONFIG_PKG_USING_PPOOL is not set -# CONFIG_PKG_USING_OPENAMP is not set -# CONFIG_PKG_USING_LPM is not set -# CONFIG_PKG_USING_TLSF is not set -# CONFIG_PKG_USING_EVENT_RECORDER is not set -# CONFIG_PKG_USING_ARM_2D is not set -# CONFIG_PKG_USING_MCUBOOT is not set -# CONFIG_PKG_USING_TINYUSB is not set -# CONFIG_PKG_USING_USB_STACK is not set - -# -# peripheral libraries and drivers -# -# CONFIG_PKG_USING_SENSORS_DRIVERS is not set -# CONFIG_PKG_USING_REALTEK_AMEBA is not set -# CONFIG_PKG_USING_SHT2X is not set -# CONFIG_PKG_USING_SHT3X is not set -# CONFIG_PKG_USING_AS7341 is not set -# CONFIG_PKG_USING_STM32_SDIO is not set -# CONFIG_PKG_USING_ICM20608 is not set -# CONFIG_PKG_USING_BUTTON is not set -# CONFIG_PKG_USING_PCF8574 is not set -# CONFIG_PKG_USING_SX12XX is not set -# CONFIG_PKG_USING_SIGNAL_LED is not set -# CONFIG_PKG_USING_LEDBLINK is not set -# CONFIG_PKG_USING_LITTLED is not set -# CONFIG_PKG_USING_LKDGUI is not set -# CONFIG_PKG_USING_NRF5X_SDK is not set -# CONFIG_PKG_USING_NRFX is not set -# CONFIG_PKG_USING_WM_LIBRARIES is not set -# CONFIG_PKG_USING_KENDRYTE_SDK is not set -# CONFIG_PKG_USING_INFRARED is not set -# CONFIG_PKG_USING_AGILE_BUTTON is not set -# CONFIG_PKG_USING_AGILE_LED is not set -# CONFIG_PKG_USING_AT24CXX is not set -# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set -# CONFIG_PKG_USING_AD7746 is not set -# CONFIG_PKG_USING_PCA9685 is not set -# CONFIG_PKG_USING_I2C_TOOLS is not set -# CONFIG_PKG_USING_NRF24L01 is not set -# CONFIG_PKG_USING_TOUCH_DRIVERS is not set -# CONFIG_PKG_USING_MAX17048 is not set -# CONFIG_PKG_USING_RPLIDAR is not set -# CONFIG_PKG_USING_AS608 is not set -# CONFIG_PKG_USING_RC522 is not set -# CONFIG_PKG_USING_WS2812B is not set -# CONFIG_PKG_USING_EMBARC_BSP is not set -# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set -# CONFIG_PKG_USING_MULTI_RTIMER is not set -# CONFIG_PKG_USING_MAX7219 is not set -# CONFIG_PKG_USING_BEEP is not set -# CONFIG_PKG_USING_EASYBLINK is not set -# CONFIG_PKG_USING_PMS_SERIES is not set -# CONFIG_PKG_USING_CAN_YMODEM is not set -# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set -# CONFIG_PKG_USING_QLED is not set -# CONFIG_PKG_USING_PAJ7620 is not set -# CONFIG_PKG_USING_AGILE_CONSOLE is not set -# CONFIG_PKG_USING_LD3320 is not set -# CONFIG_PKG_USING_WK2124 is not set -# CONFIG_PKG_USING_LY68L6400 is not set -# CONFIG_PKG_USING_DM9051 is not set -# CONFIG_PKG_USING_SSD1306 is not set -# CONFIG_PKG_USING_QKEY is not set -# CONFIG_PKG_USING_RS485 is not set -# CONFIG_PKG_USING_NES is not set -# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set -# CONFIG_PKG_USING_VDEVICE is not set -# CONFIG_PKG_USING_SGM706 is not set -# CONFIG_PKG_USING_STM32WB55_SDK is not set -# CONFIG_PKG_USING_RDA58XX is not set -# CONFIG_PKG_USING_LIBNFC is not set -# CONFIG_PKG_USING_MFOC is not set -# CONFIG_PKG_USING_TMC51XX is not set -# CONFIG_PKG_USING_TCA9534 is not set -# CONFIG_PKG_USING_KOBUKI is not set -# CONFIG_PKG_USING_ROSSERIAL is not set -# CONFIG_PKG_USING_MICRO_ROS is not set -# CONFIG_PKG_USING_MCP23008 is not set -# CONFIG_PKG_USING_BLUETRUM_SDK is not set -# CONFIG_PKG_USING_MISAKA_AT24CXX is not set -# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set -# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set -# CONFIG_PKG_USING_BL_MCU_SDK is not set -# CONFIG_PKG_USING_SOFT_SERIAL is not set -# CONFIG_PKG_USING_MB85RS16 is not set -# CONFIG_PKG_USING_CW2015 is not set - -# -# AI packages -# -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set -# CONFIG_PKG_USING_ELAPACK is not set -# CONFIG_PKG_USING_ULAPACK is not set -# CONFIG_PKG_USING_QUEST is not set -# CONFIG_PKG_USING_NAXOS is not set - -# -# miscellaneous packages -# - -# -# samples: kernel and components samples -# -# CONFIG_PKG_USING_KERNEL_SAMPLES is not set -# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set -# CONFIG_PKG_USING_NETWORK_SAMPLES is not set -# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set - -# -# entertainment: terminal games and other interesting software packages -# -# CONFIG_PKG_USING_CMATRIX is not set -# CONFIG_PKG_USING_SL is not set -# CONFIG_PKG_USING_CAL is not set -# CONFIG_PKG_USING_ACLOCK is not set -# CONFIG_PKG_USING_THREES is not set -# CONFIG_PKG_USING_2048 is not set -# CONFIG_PKG_USING_SNAKE is not set -# CONFIG_PKG_USING_TETRIS is not set -# CONFIG_PKG_USING_DONUT is not set -# CONFIG_PKG_USING_COWSAY is not set -# CONFIG_PKG_USING_LIBCSV is not set -# CONFIG_PKG_USING_OPTPARSE is not set -# CONFIG_PKG_USING_FASTLZ is not set -# CONFIG_PKG_USING_MINILZO is not set -# CONFIG_PKG_USING_QUICKLZ is not set -# CONFIG_PKG_USING_LZMA is not set -# CONFIG_PKG_USING_MULTIBUTTON is not set -# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set -# CONFIG_PKG_USING_CANFESTIVAL is not set -# CONFIG_PKG_USING_ZLIB is not set -# CONFIG_PKG_USING_MINIZIP is not set -# CONFIG_PKG_USING_DSTR is not set -# CONFIG_PKG_USING_TINYFRAME is not set -# CONFIG_PKG_USING_KENDRYTE_DEMO is not set -# CONFIG_PKG_USING_DIGITALCTRL is not set -# CONFIG_PKG_USING_UPACKER is not set -# CONFIG_PKG_USING_UPARAM is not set -# CONFIG_PKG_USING_HELLO is not set -# CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_KI is not set -# CONFIG_PKG_USING_ARMv7M_DWT is not set -# CONFIG_PKG_USING_UKAL is not set -# CONFIG_PKG_USING_CRCLIB is not set -# CONFIG_PKG_USING_LWGPS is not set -# CONFIG_PKG_USING_STATE_MACHINE is not set -# CONFIG_PKG_USING_DESIGN_PATTERN is not set -CONFIG_SOC_SERIES_GD32F1=y -CONFIG_SOC_GD32103C=y - -# -# On-chip Peripheral Drivers -# -CONFIG_BSP_USING_UART=y -CONFIG_BSP_USING_UART0=y -# CONFIG_BSP_USING_UART1 is not set -# CONFIG_BSP_USING_UART2 is not set -# CONFIG_BSP_USING_UART3 is not set -# CONFIG_BSP_USING_UART4 is not set -# CONFIG_BSP_USING_ADC is not set -# CONFIG_BSP_USING_HWTIMER is not set -# CONFIG_BSP_USING_WDT is not set -# CONFIG_BSP_USING_RTC is not set diff --git a/bsp/gd32103c-eval/Kconfig b/bsp/gd32103c-eval/Kconfig deleted file mode 100644 index 97fb8f2b2c..0000000000 --- a/bsp/gd32103c-eval/Kconfig +++ /dev/null @@ -1,109 +0,0 @@ -mainmenu "RT-Thread Configuration" - -config BSP_DIR - string - option env="BSP_ROOT" - default "." - -config RTT_DIR - string - option env="RTT_ROOT" - default "../.." - -# you can change the RTT_ROOT default: "rt-thread" -# example : default "F:/git_repositories/rt-thread" - -config PKGS_DIR - string - option env="PKGS_ROOT" - default "packages" - -source "$RTT_DIR/Kconfig" -source "$PKGS_DIR/Kconfig" - -config SOC_SERIES_GD32F1 - bool - default y - -config SOC_GD32103C - bool - select RT_USING_COMPONENTS_INIT - select RT_USING_USER_MAIN - select SOC_SERIES_GD32F1 - default y - -menu "On-chip Peripheral Drivers" - menuconfig BSP_USING_UART - bool "Enable UART" - default y - select RT_USING_SERIAL - if BSP_USING_UART - config BSP_USING_UART0 - bool "using uart0" - default n - config BSP_USING_UART1 - bool "using uart1" - default n - config BSP_USING_UART2 - bool "using uart2" - default y - config BSP_USING_UART3 - bool "using uart3" - default n - config BSP_USING_UART4 - bool "using uart4" - default n - endif - menuconfig BSP_USING_ADC - bool "Enable ADC" - default n - select RT_USING_ADC - if BSP_USING_ADC - config BSP_USING_ADC0 - bool "using adc0" - default n - config BSP_USING_ADC1 - bool "using adc1" - default n - endif - menuconfig BSP_USING_HWTIMER - bool "Enable hwtimer" - default n - select RT_USING_HWTIMER - if BSP_USING_HWTIMER - config BSP_USING_HWTIMER0 - bool "using hwtimer0" - default n - config BSP_USING_HWTIMER1 - bool "using hwtimer1" - default n - config BSP_USING_HWTIMER2 - bool "using hwtimer2" - default n - config BSP_USING_HWTIMER3 - bool "using hwtimer3" - default n - config BSP_USING_HWTIMER4 - bool "using hwtimer4" - default n - config BSP_USING_HWTIMER5 - bool "using hwtimer5" - default n - config BSP_USING_HWTIMER6 - bool "using hwtimer6" - default n - config BSP_USING_HWTIMER7 - bool "using hwtimer7" - default n - endif - config BSP_USING_WDT - bool "Enable Watchdog Timer" - select RT_USING_WDT - default n - - config BSP_USING_RTC - bool "using internal rtc" - default n - select RT_USING_RTC - -endmenu diff --git a/bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Include/gd32f10x.h b/bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Include/gd32f10x.h deleted file mode 100644 index 1dde2fb596..0000000000 --- a/bsp/gd32103c-eval/Libraries/CMSIS/GD/GD32F1xx/Include/gd32f10x.h +++ /dev/null @@ -1,8033 +0,0 @@ -/** - ****************************************************************************** - * @brief CMSIS Cortex-M3 Device Peripheral Access Layer Header File.. - ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup GD32f10X - * @{ - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_H -#define __GD32F10X_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** @addtogroup Library_configuration_section - * @{ - */ - -/* Uncomment the line below according to the target gd32f10x device used in your - application - */ - -#if !defined (GD32F10X_MD)&&!defined (GD32F10X_HD)&&!defined (GD32F10X_XD)&&!defined (GD32F10X_CL) -/* #define GD32F10X_MD */ /*!< GD32F10X_MD: GD32 Medium density devices */ -#define GD32F10X_HD /*!< GD32F10X_HD: GD32 High density Value Line devices */ -/* #define GD32F10X_XD */ /*!< GD32F10X_XD: GD32 Extra density devices */ -/* #define GD32F10X_CL */ /*!< GD32F10X_CL: GD32 Connectivity line devices */ -#endif - - -#if !defined (GD32F10X_MD)&&!defined (GD32F10X_HD)&&!defined (GD32F10X_XD)&&!defined (GD32F10X_CL) -#error "Please select first the target gd32f10x device used in your application (in gd32f10x.h file)" -#endif /* GD32F10X */ - -#if !defined USE_STDPERIPH_DRIVER -/** - * @brief Comment the line below if you will not use the peripherals drivers. - In this case, these drivers will not be included and the application code will - be based on direct access to peripherals registers - */ -/*#define USE_STDPERIPH_DRIVER*/ -#endif /* USE_STDPERIPH_DRIVER */ - -/** - * @brief In the following line adjust the value of External High Speed oscillator (HSE) - used in your application - - Tip: To avoid modifying this file each time you need to use different HSE, you - can define the HSE value in your toolchain compiler preprocessor. - */ -#if !defined HSE_VALUE -#ifdef GD32F10X_CL -#define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ -#else -#define HSE_VALUE ((uint32_t)8000000) /* !< From 4M to 16M *!< Value of the External oscillator in Hz*/ -#endif /* HSE_VALUE */ -#endif - -#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF) /*!< Time out for HSI start up */ - -/* define value of high speed crystal oscillator (HXTAL) in Hz */ -#if !defined HXTAL_VALUE -#define HXTAL_VALUE ((uint32_t)8000000) /* !< from 4M to 16M *!< value of the external oscillator in Hz*/ -#endif /* high speed crystal oscillator value */ - -/* define startup timeout value of high speed crystal oscillator (HXTAL) */ -#if !defined (HXTAL_STARTUP_TIMEOUT) -#define HXTAL_STARTUP_TIMEOUT ((uint16_t)0x0800) -#endif /* high speed crystal oscillator startup timeout */ - -/* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ -#if !defined (IRC8M_STARTUP_TIMEOUT) -#define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) -#endif /* internal 8MHz RC oscillator startup timeout */ - -#if !defined (HSI_VALUE) -#define HSI_VALUE ((uint32_t)8000000) /*!< Value of the Internal High Speed oscillator in Hz. - The real value may vary depending on the variations - in voltage and temperature. */ -#endif /* HSI_VALUE */ - -/* define value of internal 48MHz RC oscillator (IRC48M) in Hz */ -#if !defined (IRC48M_VALUE) -#define IRC48M_VALUE ((uint32_t)48000000) -#endif /* internal 48MHz RC oscillator value */ - -/* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ -#if !defined (IRC8M_VALUE) -#define IRC8M_VALUE ((uint32_t)8000000) -#endif /* internal 8MHz RC oscillator value */ - -#if !defined (LSI_VALUE) -#define LSI_VALUE ((uint32_t)40000) /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature. */ -#endif /* LSI_VALUE */ - -#if !defined (LSE_VALUE) -#define LSE_VALUE ((uint32_t)32768) /*!< Value of the External Low Speed oscillator in Hz */ -#endif /* LSE_VALUE */ - -/** - * @brief GD32F10X Firmware Library version number V1.0 - */ -#define __GD32F10X_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ -#define __GD32F10X_STDPERIPH_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */ -#define __GD32F10X_STDPERIPH_VERSION_SUB2 (0x01) /*!< [15:8] sub2 version */ -#define __GD32F10X_STDPERIPH_VERSION_RC (0x00) /*!< [7:0] release candidate */ -#define __GD32F10X_STDPERIPH_VERSION ((__GD32F10X_STDPERIPH_VERSION_MAIN << 24)\ - |(__GD32F10X_STDPERIPH_VERSION_SUB1 << 16)\ - |(__GD32F10X_STDPERIPH_VERSION_SUB2 << 8)\ - |(__GD32F10X_STDPERIPH_VERSION_RC)) - -/** - * @} - */ - -/** @addtogroup Configuration_section_for_CMSIS - * @{ - */ - -/** - * @brief Configuration of the Cortex-M3 Processor and Core Peripherals - */ -#define __MPU_PRESENT 0 /*!< GD32 devices does not provide an MPU */ -#define __NVIC_PRIO_BITS 4 /*!< GD32F10X uses 4 Bits for the Priority Levels */ -#define __VENDOR_SYSTICKCONFIG 0 /*!< Set to 1 if different SysTick Config is used */ - -/*!< Interrupt Number Definition */ -typedef enum IRQn { - /****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ - NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ - MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ - BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ - SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ - SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ - - /****** GD32 specific Interrupt Numbers *********************************************************/ - WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ - LVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ - TAMPER_IRQn = 2, /*!< Tamper Interrupt */ - RTC_IRQn = 3, /*!< RTC global Interrupt */ - FLASH_IRQn = 4, /*!< FLASH global Interrupt */ - RCC_IRQn = 5, /*!< RCC global Interrupt */ - EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ - EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ - EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ - EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ - EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ - DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ - DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ - DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ - DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ - DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ - DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ - DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ - -#ifdef GD32F10X_MD - ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 global Interrupt */ - USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ - USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TIMER0_BRK_IRQn = 24, /*!< TIMER0 Break Interrupt */ - TIMER0_UP_IRQn = 25, /*!< TIMER0 Update Interrupt */ - TIMER0_TRG_COM_IRQn = 26, /*!< TIMER0 Trigger and Commutation Interrupt */ - TIMER0_CC_IRQn = 27, /*!< TIMER0 Capture Compare Interrupt */ - TIMER1_IRQn = 28, /*!< TIMER1 global Interrupt */ - TIMER2_IRQn = 29, /*!< TIMER2 global Interrupt */ - TIMER3_IRQn = 30, /*!< TIMER3 global Interrupt */ - I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ - I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ - I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ - I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ - SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ - SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ - USART1_IRQn = 37, /*!< USART1 global Interrupt */ - USART2_IRQn = 38, /*!< USART2 global Interrupt */ - USART3_IRQn = 39, /*!< USART3 global Interrupt */ - EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ - USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ - EXMC_IRQn = 48 /*!< EXMC global Interrupt */ -#endif /* GD32F10X_MD */ - -#ifdef GD32F10X_HD - ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 global Interrupt */ - USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ - USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TIMER0_BRK_IRQn = 24, /*!< TIMER0 Break Interrupt */ - TIMER0_UP_IRQn = 25, /*!< TIMER0 Update Interrupt */ - TIMER0_TRG_COM_IRQn = 26, /*!< TIMER0 Trigger and Commutation Interrupt */ - TIMER0_CC_IRQn = 27, /*!< TIMER0 Capture Compare Interrupt */ - TIMER1_IRQn = 28, /*!< TIMER1 global Interrupt */ - TIMER2_IRQn = 29, /*!< TIMER2 global Interrupt */ - TIMER3_IRQn = 30, /*!< TIMER3 global Interrupt */ - I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ - I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ - I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ - I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ - SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ - SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ - USART0_IRQn = 37, /*!< USART1 global Interrupt */ - USART1_IRQn = 38, /*!< USART2 global Interrupt */ - USART2_IRQn = 39, /*!< USART3 global Interrupt */ - EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ - USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ - TIMER7_BRK_IRQn = 43, /*!< TIMER7 Break Interrupt */ - TIMER7_UP_IRQn = 44, /*!< TIMER7 Update Interrupt */ - TIMER7_TRG_COM_IRQn = 45, /*!< TIMER7 Trigger and Commutation Interrupt */ - TIMER7_CC_IRQn = 46, /*!< TIMER7 Capture Compare Interrupt */ - ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ - EXMC_IRQn = 48, /*!< EXMC global Interrupt */ - SDIO_IRQn = 49, /*!< SDIO global Interrupt */ - TIMER4_IRQn = 50, /*!< TIMER4 global Interrupt */ - SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ - UART3_IRQn = 52, /*!< UART4 global Interrupt */ - UART4_IRQn = 53, /*!< UART5 global Interrupt */ - TIMER5_IRQn = 54, /*!< TIMER5 global Interrupt */ - TIMER6_IRQn = 55, /*!< TIMER6 global Interrupt */ - DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ - DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ - DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ - DMA2_Channel4_5_IRQn = 59 /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ -#endif /* GD32F10X_HD */ - -#ifdef GD32F10X_XD - ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 global Interrupt */ - USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */ - USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 Break Interrupt and TIMER8 global Interrupt */ - TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 Update Interrupt and TIMER9 global Interrupt */ - TIMER0_TRG_COM_TIMER10_IRQn = 26, /*!< TIMER0 Trigger and Commutation Interrupt and TIMER10 global interrupt */ - TIMER0_CC_IRQn = 27, /*!< TIMER0 Capture Compare Interrupt */ - TIMER1_IRQn = 28, /*!< TIMER1 global Interrupt */ - TIMER2_IRQn = 29, /*!< TIMER2 global Interrupt */ - TIMER3_IRQn = 30, /*!< TIMER3 global Interrupt */ - I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ - I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ - I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ - I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ - SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ - SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ - USART1_IRQn = 37, /*!< USART1 global Interrupt */ - USART2_IRQn = 38, /*!< USART2 global Interrupt */ - USART3_IRQn = 39, /*!< USART3 global Interrupt */ - EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ - USBWakeUp_IRQn = 42, /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */ - TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 Break Interrupt and TIMER11 global Interrupt */ - TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 Update Interrupt and TIMER12 global Interrupt */ - TIMER7_TRG_COM_TIMER13_IRQn = 45, /*!< TIMER7 Trigger and Commutation Interrupt and TIMER13 global interrupt */ - TIMER7_CC_IRQn = 46, /*!< TIMER7 Capture Compare Interrupt */ - ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ - EXMC_IRQn = 48, /*!< EXMC global Interrupt */ - SDIO_IRQn = 49, /*!< SDIO global Interrupt */ - TIMER4_IRQn = 50, /*!< TIMER4 global Interrupt */ - SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ - UART4_IRQn = 52, /*!< UART4 global Interrupt */ - UART5_IRQn = 53, /*!< UART5 global Interrupt */ - TIMER5_IRQn = 54, /*!< TIMER5 global Interrupt */ - TIMER6_IRQn = 55, /*!< TIMER6 global Interrupt */ - DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ - DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ - DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ - DMA2_Channel4_5_IRQn = 59 /*!< DMA2 Channel 4 and Channel 5 global Interrupt */ -#endif /* GD32F10X_XD */ - -#ifdef GD32F10X_CL - ADC0_1_IRQn = 18, /*!< ADC0 and ADC1 global Interrupt */ - CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupts */ - CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupts */ - CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ - CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ - EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ - TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 Break Interrupt and TIMER8 global Interrupt */ - TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 Update Interrupt and TIMER9 global Interrupt */ - TIMER0_TRG_COM_TIMER10_IRQn = 26, /*!< TIMER0 Trigger and Commutation Interrupt and TIMER10 global interrupt */ - TIMER0_CC_IRQn = 27, /*!< TIMER0 Capture Compare Interrupt */ - TIMER1_IRQn = 28, /*!< TIMER1 global Interrupt */ - TIMER2_IRQn = 29, /*!< TIMER2 global Interrupt */ - TIMER3_IRQn = 30, /*!< TIMER3 global Interrupt */ - I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ - I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ - I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ - I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ - SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ - SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ - USART1_IRQn = 37, /*!< USART1 global Interrupt */ - USART2_IRQn = 38, /*!< USART2 global Interrupt */ - USART3_IRQn = 39, /*!< USART3 global Interrupt */ - EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ - RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */ - OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS WakeUp from suspend through EXTI Line Interrupt */ - TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 Break Interrupt and TIMER11 global Interrupt */ - TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 Update Interrupt and TIMER12 global Interrupt */ - TIMER7_TRG_COM_TIMER13_IRQn = 45, /*!< TIMER7 Trigger and Commutation Interrupt and TIMER13 global interrupt */ - TIMER7_CC_IRQn = 46, /*!< TIMER7 Capture Compare Interrupt */ - ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ - EXMC_IRQn = 48, /*!< EXMC global Interrupt */ - TIMER4_IRQn = 50, /*!< TIMER4 global Interrupt */ - SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ - UART4_IRQn = 52, /*!< UART4 global Interrupt */ - UART5_IRQn = 53, /*!< UART5 global Interrupt */ - TIMER5_IRQn = 54, /*!< TIMER5 global Interrupt */ - TIMER6_IRQn = 55, /*!< TIMER6 global Interrupt */ - DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ - DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ - DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ - DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */ - DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */ - ETH_IRQn = 61, /*!< Ethernet global Interrupt */ - ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ - CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */ - CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */ - CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */ - CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */ - OTG_FS_IRQn = 67 /*!< USB OTG FS global Interrupt */ -#endif /* GD32F10X_CL */ -} IRQn_Type; - - -/** - * @} - */ - -/* Includes ------------------------------------------------------------------*/ -#include "core_cm3.h" -#include "system_gd32f10x.h" -#include - -/** @addtogroup Exported_types - * @{ - */ -typedef enum {ERROR = 0, SUCCESS = !ERROR, RESET = 0, SET = !RESET, DISABLE = 0, ENABLE = !DISABLE} TypeState, EventStatus, ControlStatus, FlagStatus, ErrStatus; - -#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) -#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) -#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr)) -#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) -#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) -#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) - -typedef int32_t s32; -typedef int16_t s16; -typedef int8_t s8; - -typedef const int32_t sc32; /*!< Read Only */ -typedef const int16_t sc16; /*!< Read Only */ -typedef const int8_t sc8; /*!< Read Only */ - -typedef __IO int32_t vs32; -typedef __IO int16_t vs16; -typedef __IO int8_t vs8; - -typedef __I int32_t vsc32; /*!< Read Only */ -typedef __I int16_t vsc16; /*!< Read Only */ -typedef __I int8_t vsc8; /*!< Read Only */ - -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -typedef const uint32_t uc32; /*!< Read Only */ -typedef const uint16_t uc16; /*!< Read Only */ -typedef const uint8_t uc8; /*!< Read Only */ - -typedef __IO uint32_t vu32; -typedef __IO uint16_t vu16; -typedef __IO uint8_t vu8; - -typedef __I uint32_t vuc32; /*!< Read Only */ -typedef __I uint16_t vuc16; /*!< Read Only */ -typedef __I uint8_t vuc8; /*!< Read Only */ - -/** @addtogroup Peripheral_registers_structures - * @{ - */ - -/** - * @brief Analog to Digital Converter - */ -typedef struct { - __IO uint32_t STR; - __IO uint32_t CTLR1; - __IO uint32_t CTLR2; - __IO uint32_t SPT1; - __IO uint32_t SPT2; - __IO uint32_t ICOS1; - __IO uint32_t ICOS2; - __IO uint32_t ICOS3; - __IO uint32_t ICOS4; - __IO uint32_t AWHT; - __IO uint32_t AWLT; - __IO uint32_t RSQ1; - __IO uint32_t RSQ2; - __IO uint32_t RSQ3; - __IO uint32_t ISQ; - __IO uint32_t IDTR1; - __IO uint32_t IDTR2; - __IO uint32_t IDTR3; - __IO uint32_t IDTR4; - __IO uint32_t RDTR; -} ADC_TypeDef; - -/** - * @brief Backup Registers - */ -typedef struct { - uint32_t RESERVED0; - __IO uint16_t DR1; - uint16_t RESERVED1; - __IO uint16_t DR2; - uint16_t RESERVED2; - __IO uint16_t DR3; - uint16_t RESERVED3; - __IO uint16_t DR4; - uint16_t RESERVED4; - __IO uint16_t DR5; - uint16_t RESERVED5; - __IO uint16_t DR6; - uint16_t RESERVED6; - __IO uint16_t DR7; - uint16_t RESERVED7; - __IO uint16_t DR8; - uint16_t RESERVED8; - __IO uint16_t DR9; - uint16_t RESERVED9; - __IO uint16_t DR10; - uint16_t RESERVED10; - __IO uint16_t RCCR; - uint16_t RESERVED11; - __IO uint16_t TPCR; - uint16_t RESERVED12; - __IO uint16_t TIER; - uint16_t RESERVED13[5]; - __IO uint16_t DR11; - uint16_t RESERVED14; - __IO uint16_t DR12; - uint16_t RESERVED15; - __IO uint16_t DR13; - uint16_t RESERVED16; - __IO uint16_t DR14; - uint16_t RESERVED17; - __IO uint16_t DR15; - uint16_t RESERVED18; - __IO uint16_t DR16; - uint16_t RESERVED19; - __IO uint16_t DR17; - uint16_t RESERVED20; - __IO uint16_t DR18; - uint16_t RESERVED21; - __IO uint16_t DR19; - uint16_t RESERVED22; - __IO uint16_t DR20; - uint16_t RESERVED23; - __IO uint16_t DR21; - uint16_t RESERVED24; - __IO uint16_t DR22; - uint16_t RESERVED25; - __IO uint16_t DR23; - uint16_t RESERVED26; - __IO uint16_t DR24; - uint16_t RESERVED27; - __IO uint16_t DR25; - uint16_t RESERVED28; - __IO uint16_t DR26; - uint16_t RESERVED29; - __IO uint16_t DR27; - uint16_t RESERVED30; - __IO uint16_t DR28; - uint16_t RESERVED31; - __IO uint16_t DR29; - uint16_t RESERVED32; - __IO uint16_t DR30; - uint16_t RESERVED33; - __IO uint16_t DR31; - uint16_t RESERVED34; - __IO uint16_t DR32; - uint16_t RESERVED35; - __IO uint16_t DR33; - uint16_t RESERVED36; - __IO uint16_t DR34; - uint16_t RESERVED37; - __IO uint16_t DR35; - uint16_t RESERVED38; - __IO uint16_t DR36; - uint16_t RESERVED39; - __IO uint16_t DR37; - uint16_t RESERVED40; - __IO uint16_t DR38; - uint16_t RESERVED41; - __IO uint16_t DR39; - uint16_t RESERVED42; - __IO uint16_t DR40; - uint16_t RESERVED43; - __IO uint16_t DR41; - uint16_t RESERVED44; - __IO uint16_t DR42; - uint16_t RESERVED45; -} BKP_TypeDef; - - -/** - * @brief Controller Area Network TxMailBox - */ - -typedef struct { - __IO uint32_t TMIR; /*!< CAN transmit mailbox identifier register, Address offset: 0x180, 0x190, 0x1A0 */ - __IO uint32_t TMPR; /*!< CAN transmit mailbox property register, Address offset: 0x184, 0x194, 0x1A4 */ - __IO uint32_t TMD0R; /*!< CAN transmit mailbox data0 register, Address offset: 0x188, 0x198, 0x1A8 */ - __IO uint32_t TMD1R; /*!< CAN transmit mailbox data1 register, Address offset: 0x18C, 0x19C, 0x1AC */ -} CAN_TxMailBox_TypeDef; - -/** - * @brief Controller Area Network FIFOMailBox - */ - -typedef struct { - __IO uint32_t RFMIR; /*!< CAN receive FIFO mailbox identifier register, Address offset: 0x1B0, 0x1C0 */ - __IO uint32_t RFMPR; /*!< CAN receive FIFO mailbox property register, Address offset: 0x1B4, 0x1C4 */ - __IO uint32_t RFMD0R; /*!< CAN receive FIFO mailbox data0 register, Address offset: 0x1B8, 0x1C8 */ - __IO uint32_t RFMD1R; /*!< CAN receive FIFO mailbox data1 register, Address offset: 0x1BC, 0x1CC */ -} CAN_FIFOMailBox_TypeDef; - -/** - * @brief Controller Area Network FilterRegister - */ - -typedef struct { - __IO uint32_t FD0R; /*!< CAN filter x data 0 register */ - __IO uint32_t FD1R; /*!< CAN filter x data 1 register */ -} CAN_FilterRegister_TypeDef; - -/** - * @brief Controller Area Network - */ - -typedef struct { - __IO uint32_t CTLR; /*!< CAN control register, Address offset: 0x00 */ - __IO uint32_t STR; /*!< CAN status register, Address offset: 0x04 */ - __IO uint32_t TSTR; /*!< CAN transmit status register, Address offset: 0x08 */ - __IO uint32_t RFR0; /*!< CAN receive FIFO0 register, Address offset: 0x0C */ - __IO uint32_t RFR1; /*!< CAN receive FIFO0 register, Address offset: 0x10 */ - __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ - __IO uint32_t ER; /*!< CAN error register, Address offset: 0x18 */ - __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ - uint32_t RESERVED0[88]; - CAN_TxMailBox_TypeDef TxMailBox[3]; - CAN_FIFOMailBox_TypeDef FIFOMailBox[2]; - uint32_t RESERVED1[12]; - __IO uint32_t FCTLR; /*!< CAN filter control register, Address offset: 0x200 */ - __IO uint32_t FMR; /*!< CAN filter mode register, Address offset: 0x204 */ - uint32_t RESERVED2; - __IO uint32_t FSR; /*!< CAN filter scale register, Address offset: 0x20C */ - uint32_t RESERVED3; - __IO uint32_t FAFR; /*!< CAN filter associated FIFO register, Address offset: 0x214 */ - uint32_t RESERVED4; - __IO uint32_t FWR; /*!< CAN filter working register, Address offset: 0x21C */ - uint32_t RESERVED5[8]; -#ifndef GD32F10X_CL - CAN_FilterRegister_TypeDef FilterRegister[14]; -#else - CAN_FilterRegister_TypeDef FilterRegister[28]; -#endif /* GD32F10X_CL */ -} CAN_TypeDef; - - -/** - * @brief CRC calculation unit - */ -typedef struct { - __IO uint32_t DTR; /*!< CRC Data register, Address offset: 0x00 */ - __IO uint8_t FDTR; /*!< CRC Independent data register, Address offset: 0x04 */ - uint8_t RESERVED0; /*!< Reserved, 0x05 */ - uint16_t RESERVED1; /*!< Reserved, 0x06 */ - __IO uint32_t CTLR; /*!< CRC Control register, Address offset: 0x08 */ -} CRC_TypeDef; -/** - * @brief Digital to Analog Converter - */ -typedef struct { - __IO uint32_t CTLR; - __IO uint32_t SWTR; - __IO uint32_t C1R12DHR; - __IO uint32_t C1L12DHR; - __IO uint32_t C1R8DHR; - - __IO uint32_t C2R12DHR; - __IO uint32_t C2L12DHR; - __IO uint32_t C2R8DHR; - - __IO uint32_t DCR12DHR; - __IO uint32_t DCL12DHR; - __IO uint32_t DCR8RD; - - __IO uint32_t C1ODR; - __IO uint32_t C2ODR; -} DAC_TypeDef; -/** - * @brief Debug MCU - */ -typedef struct { - __IO uint32_t IDR; /*!< MCU device ID code, Address offset: 0x00 */ - __IO uint32_t CTLR; /*!< Debug MCU CTLR freeze register, Address offset: 0x04 */ -} MCUDBG_TypeDef; - -/** - * @brief DMA Controller - */ - -typedef struct { - __IO uint32_t CTLR; /*!< DMA channel x configuration register */ - __IO uint32_t RCNT; /*!< DMA channel x number of data register */ - __IO uint32_t PBAR; /*!< DMA channel x peripheral address register */ - __IO uint32_t MBAR; /*!< DMA channel x memory address register */ -} DMA_Channel_TypeDef; - -typedef struct { - __IO uint32_t IFR; /*!< DMA interrupt status register, Address offset: 0x00 */ - __IO uint32_t ICR; /*!< DMA interrupt flag clear register,Address offset: 0x04 */ -} DMA_TypeDef; - -typedef struct { - __IO uint32_t CFR; /*!< Ethernet MAC configuration register, Address offset: 0x00 */ - __IO uint32_t FRMFR; /*!< Ethernet MAC frame filter register, Address offset: 0x04 */ - __IO uint32_t HLHR; /*!< Ethernet MAC hash list high register, Address offset: 0x08 */ - __IO uint32_t HLLR; /*!< Ethernet MAC hash list low register, Address offset: 0x0C */ - __IO uint32_t PHYAR; /*!< Ethernet MAC PHY address register, Address offset: 0x10 */ - __IO uint32_t PHYDR; /*!< Ethernet MAC PHY data register, Address offset: 0x14 */ - __IO uint32_t FCTLR; /*!< Ethernet MAC flow control register, Address offset: 0x18 */ - __IO uint32_t VLTR; /*!< Ethernet MAC VLAN tag register, Address offset: 0x1C */ - uint32_t RESERVED0[2]; /*!< Reserved, 0x24 */ - __IO uint32_t RWFFR; /*!< Ethernet MAC remote wakeup frame filter register, Address offset: 0x28 */ - __IO uint32_t WUMR; /*!< Ethernet MAC wake up management register, Address offset: 0x2C */ - uint32_t RESERVED1[2]; /*!< Reserved, 0x34 */ - __IO uint32_t ISR; /*!< Ethernet MAC interrupt status register, Address offset: 0x38 */ - __IO uint32_t IMR; /*!< Ethernet MAC interrupt mask register, Address offset: 0x3C */ - __IO uint32_t ADDR0HR; /*!< Ethernet MAC address 0 high register, Address offset: 0x40 */ - __IO uint32_t ADDR0LR; /*!< Ethernet MAC address 0 low register, Address offset: 0x44 */ - __IO uint32_t ADDR1HR; /*!< Ethernet MAC address 1 high register, Address offset: 0x48 */ - __IO uint32_t ADDR1LR; /*!< Ethernet MAC address 1 low register, Address offset: 0x4C */ - __IO uint32_t ADDR2HR; /*!< Ethernet MAC address 2 high register, Address offset: 0x50 */ - __IO uint32_t ADDR2LR; /*!< Ethernet MAC address 2 low register, Address offset: 0x54 */ - __IO uint32_t ADDR3HR; /*!< Ethernet MAC address 3 high register, Address offset: 0x58 */ - __IO uint32_t ADDR3LR; /*!< Ethernet MAC address 3 low register, Address offset: 0x5C */ - uint32_t RESERVED2[1032]; /*!< Reserved, 0x107C */ - __IO uint32_t FCTHR; /*!< Ethernet MAC flow control threshold register, Address offset: 0x1080 */ -} ETH_MAC_TypeDef; - -typedef struct { - __IO uint32_t CTLR; /*!< Ethernet MSC control register, Address offset: 0x100 */ - __IO uint32_t RISR; /*!< Ethernet MSC receive interrupt status register, Address offset: 0x104 */ - __IO uint32_t TISR; /*!< Ethernet MSC transmit interrupt status register, Address offset: 0x108 */ - __IO uint32_t RIMR; /*!< Ethernet MSC receive interrupt mask register, Address offset: 0x10C */ - __IO uint32_t TIMR; /*!< Ethernet MSC transmit interrupt mask register, Address offset: 0x110 */ - uint32_t RESERVED3[14]; /*!< Reserved, 0x148 */ - __IO uint32_t SCCNT; /*!< Ethernet MSC transmitted good frames after a single collision counterregister, Address offset: 0x14C */ - __IO uint32_t MSCCNT; /*!< Ethernet MSC transmitted good frames after more than a single collision counterregister, Address offset: 0x150 */ - uint32_t RESERVED4[5]; /*!< Reserved, 0x164 */ - __IO uint32_t TGFCNT; /*!< Ethernet MSC transmitted good frames counter register, Address offset: 0x168 */ - uint32_t RESERVED5[10]; /*!< Reserved, 0x190 */ - __IO uint32_t RFCECNT; /*!< Ethernet MSC received frames with CRC error counter register, Address offset: 0x194 */ - __IO uint32_t RFAECNT; /*!< Ethernet MSC received frames with alignment error counter register, Address offset: 0x198 */ - uint32_t RESERVED6[10]; /*!< Reserved, 0x1C0 */ - __IO uint32_t RGUFCNT; /*!< Ethernet MSC received good unicast frames counter register, Address offset: 0x1C4 */ -} ETH_MSC_TypeDef; - -typedef struct { - __IO uint32_t TSCTLR; /*!< Ethernet PTP time stamp control register, Address offset: 0x700 */ - __IO uint32_t SSINCR; /*!< Ethernet PTP subsecond increment register, Address offset: 0x704 */ - __IO uint32_t TMSHR; /*!< Ethernet PTP time stamp high register, Address offset: 0x708 */ - __IO uint32_t TMSLR; /*!< Ethernet PTP time stamp low register, Address offset: 0x70C */ - __IO uint32_t TMSHUR; /*!< Ethernet PTP time stamp high update register, Address offset: 0x710 */ - __IO uint32_t TMSLUR; /*!< Ethernet PTP time stamp low update register, Address offset: 0x714 */ - __IO uint32_t TSACNT; /*!< Ethernet PTP time stamp addend register, Address offset: 0x718 */ - __IO uint32_t ETHR; /*!< Ethernet PTP expected time high register, Address offset: 0x71C */ - __IO uint32_t ETLR; /*!< Ethernet PTP expected time low register, Address offset: 0x720 */ -} ETH_PTP_TypeDef; - -typedef struct { - __IO uint32_t BCR; /*!< Ethernet DMA bus control register, Address offset: 0x1000 */ - __IO uint32_t TPER; /*!< Ethernet DMA transmit poll enable register, Address offset: 0x1004 */ - __IO uint32_t RPER; /*!< Ethernet DMA receive poll enable register, Address offset: 0x1008 */ - __IO uint32_t RDTAR; /*!< Ethernet DMA receive descriptor tab address register, Address offset: 0x100C */ - __IO uint32_t TDTAR; /*!< Ethernet DMA transmit descriptor tab address register, Address offset: 0x1010 */ - __IO uint32_t STR; /*!< Ethernet DMA status register, Address offset: 0x1014 */ - __IO uint32_t CTLR; /*!< Ethernet DMA control register, Address offset: 0x1018 */ - __IO uint32_t IER; /*!< Ethernet DMA interrupt enable register, Address offset: 0x1018 */ - __IO uint32_t MFBOCNT; /*!< Ethernet DMA missed frame and buffer overflow counter register, Address offset: 0x101C */ - uint32_t RESERVED7[9]; /*!< Reserved, 0x1044 */ - __IO uint32_t CTDAR; /*!< Ethernet DMA current transmit descriptor address register, Address offset: 0x1048 */ - __IO uint32_t CRDAR; /*!< Ethernet DMA current receive descriptor address register, Address offset: 0x104C */ - __IO uint32_t CTBAR; /*!< Ethernet DMA current transmit buffer address register, Address offset: 0x1050 */ - __IO uint32_t CRBAR; /*!< Ethernet DMA current receive buffer address register, Address offset: 0x1054 */ -} ETH_DMA_Typedef; -/** - * @brief External Interrupt/Event Controller - */ -typedef struct { - __IO uint32_t IER; /*!GCCR |= SYS_GCCR_HSIEN_SET; - - /* Reset SCS[1:0], AHBPS[3:0], APB1PS[2:0],APB2PS[2:0], ADCPS[2:0],CKOTUSEL[2:0] bits */ -#ifdef GD32F10X_CL - RCC->GCFGR &= SYS_GCFGR_RESET_CL; -#else - RCC->GCFGR &= SYS_GCFGR_RESET; -#endif /* GD32F10X_CL */ - - /* Reset HSEEN, CKMEN and PLLEN bits */ - RCC->GCCR &= SYS_GCCR_HSEEN_CKMEN_PLLEN_RESET; - - /* Reset HSEBPS bit */ - RCC->GCCR &= SYS_GCCR_HSEBPS_RESET; - - /* Reset PLLSEL, PLLPREDV and PLLMF[4:0] USBPS/OTGPS bits */ -#ifdef GD32F10X_CL - RCC->GCFGR &= SYS_GCFGR_PLLSEL_PLLPREDV_PLLMF_USBPS_RESET_CL; -#else - RCC->GCFGR &= SYS_GCFGR_PLLSEL_PLLPREDV_PLLMF_USBPS_RESET; -#endif /* GD32F10X_CL */ - -#ifdef GD32F10X_CL - /* Reset PLL2EN and PLL3EN bits */ - RCC->GCCR &= SYS_GCCR_PLL2EN_PLL3EN_RESET; - - /* Reset GCFGR2 register */ - RCC->GCFGR2 = SYS_GCFGR2_RESET ; - - /* Disable all interrupts and clear flag bits */ - RCC->GCIR = SYS_GCIR_INT_FLAG_RESET_CL; -#else - /* Disable all interrupts and clear flag bits */ - RCC->GCIR = SYS_GCIR_INT_FLAG_RESET; -#endif /* GD32F10X_CL */ - - /* Configure the System clock frequency, AHB, APB2 and APB1 prescalers */ - /* Configure the Flash Latency cycles and enable prefetch buffer */ - SetSysClock(); -} - -/** - * @brief Update SystemCoreClock according to RCC Register Values - * @note Update the SystemCoreClock variable values, when the core clock (HCLK) changes. - * Otherwise, any configuration based on this variable will be wrong. - * @param None - * @retval None - */ -void SystemCoreClockUpdate(void) -{ - uint32_t temp = 0, pllmf = 0, pllmf4 = 0, pllselect = 0, presc = 0; - -#ifdef GD32F10X_CL - uint32_t prediv1select = 0, prediv1factor = 0, prediv2factor = 0, pll2mf = 0; -#endif /* GD32F10X_CL */ - - /* Get CK_SYS source -------------------------------------------------------*/ - temp = RCC->GCFGR & RCC_GCFGR_SCSS; - - switch (temp) { - case 0x00: /* HSI used as CK_SYS */ - SystemCoreClock = HSI_VALUE; - break; - case 0x04: /* HSE used as CK_SYS */ - SystemCoreClock = HSE_VALUE; - break; - case 0x08: /* PLL used as CK_SYS */ -#ifdef GD32F10X_CL - /* Get PLL clock source and multiplication factor ----------------------*/ - /* Get PLLMF[3:0] */ - pllmf = RCC->GCFGR & SYS_RCC_GCFGR_PLLMF_3_0; - /* Get PLLMF[4] */ - pllmf4 = RCC->GCFGR & RCC_GCFGR_PLLMF_4; - - pllmf4 = ((pllmf4 >> 29) * 15); - - pllmf = (pllmf >> 18) + pllmf4; - if (pllmf != 0x0D) { - pllmf += 2; - } else { - /* PLL multiplication factor = PLL input clock * 6.5 */ - pllmf = 13 / 2; - } - - pllselect = RCC->GCFGR & RCC_GCFGR_PLLSEL; - if (pllselect == 0x00) { - /* HSI clock divided by 2 selected as PLL clock source */ - SystemCoreClock = (HSI_VALUE >> SYS_HSI_CLOCK_DIVIDED_2) * pllmf; - } else { - /* PREDIV1 selected as PLL clock entry */ - - /* Get PREDIV1 clock source and division factor */ - prediv1select = RCC->GCFGR2 & RCC_GCFGR2_PREDV1SEL; - prediv1factor = (RCC->GCFGR2 & RCC_GCFGR2_PREDV1) + 1; - - if (prediv1select == 0) { - /* HSE clock selected as PREDIV1 clock entry */ - SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmf; - } else { - /* PLL2 clock selected as PREDIV1 clock entry */ - /* Get PREDIV2 division factor and PLL2 multiplication factor */ - prediv2factor = ((RCC->GCFGR2 & RCC_GCFGR2_PREDV2) >> 4) + 1; - pll2mf = ((RCC->GCFGR2 & RCC_GCFGR2_PLL2MF) >> 8); - if (pll2mf != 15) { - pll2mf += 2; - } else { - pll2mf += 5; - } - SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mf) / prediv1factor) * pllmf; - } - } -#else - /* Get PLL clock source and multiplication factor ----------------------*/ - /* Get PLLMF[3:0] */ - pllmf = RCC->GCFGR & SYS_RCC_GCFGR_PLLMF_3_0; - /* Get PLLMF[4] */ - pllmf4 = RCC->GCFGR & RCC_GCFGR_PLLMF_4; - - pllmf4 = ((pllmf4 >> 27) * 15); - pllmf = (pllmf >> 18) + pllmf4 + 2; - - - pllselect = RCC->GCFGR & RCC_GCFGR_PLLSEL; - if (pllselect == 0x00) { - /* HSI clock divided by 2 selected as PLL clock source */ - SystemCoreClock = (HSI_VALUE >> SYS_HSI_CLOCK_DIVIDED_2) * pllmf; - } else { - if ((RCC->GCFGR & RCC_GCFGR_PLLPREDV) != (uint32_t)RESET) { - /* HSE clock divided by 2 */ - SystemCoreClock = (HSE_VALUE >> 1) * pllmf; - } else { - SystemCoreClock = HSE_VALUE * pllmf; - } - } -#endif - break; - default: /* HSI used as system clock */ - SystemCoreClock = HSI_VALUE; - break; - } - - /* Get AHB prescaler */ - temp = RCC->GCFGR & RCC_GCFGR_AHBPS; - temp = temp >> 4; - presc = AHBPrescTableList[temp]; - /* Get AHB clock frequency */ - SystemCoreClock = SystemCoreClock >> presc; -} - -/** - * @brief Configure the System clock frequency, AHB, APB2 and APB1 prescalers. - * @param None - * @retval None - */ - - -static void SetSysClock(void) -{ -#ifdef SYSCLK_FREQ_HSE - SetSysClockToHSE(); -#elif defined SYSCLK_FREQ_24MHz - SetSysClockTo24(); -#elif defined SYSCLK_FREQ_36MHz - SetSysClockTo36(); -#elif defined SYSCLK_FREQ_48MHz - SetSysClockTo48(); -#elif defined SYSCLK_FREQ_56MHz - SetSysClockTo56(); -#elif defined SYSCLK_FREQ_72MHz - SetSysClockTo72(); -#elif defined SYSCLK_FREQ_96MHz - SetSysClockTo96(); -#elif defined SYSCLK_FREQ_108MHz - SetSysClockTo108(); -#elif defined SYSCLK_FREQ_48MHz_HSI - SetSysClockTo48HSI(); -#elif defined SYSCLK_FREQ_72MHz_HSI - SetSysClockTo72HSI(); -#elif defined SYSCLK_FREQ_108MHz_HSI - SetSysClockTo108HSI(); -#endif - -} - -#ifdef SYSCLK_FREQ_HSE -/** - * @brief Select HSE as System clock source and configure AHB, APB2 - * and APB1 prescalers. - * @param None - * @retval None - */ -static void SetSysClockToHSE(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - - /* Select HSE as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_HSE; - - /* Wait till HSE is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x04) { - } - } else { - } -} -#elif defined SYSCLK_FREQ_24MHz -/** - * @brief Set System clock frequency to 24MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo24(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */ - - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_PREDIV1 | RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF6); - - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF8 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV10); - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } -#else - /* PLL configuration: PLLCLK = (HSE /2)* 6 = 24 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE_DIV2 | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF6); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} - -#elif defined SYSCLK_FREQ_36MHz -/** - * @brief Set System clock frequency to 36MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo36(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - /* PLL configuration: PLLCLK = PREDIV1 * 9 = 36 MHz */ - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF9); - - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF8 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV10); - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } - -#else - /* PLL configuration: PLLCLK = (HSE /2)* 9 = 36 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE_DIV2 | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF9); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} -#elif defined SYSCLK_FREQ_48MHz -/** - * @brief Set System clock frequency to 48MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo48(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = PREDIV1 * 6 = 48 MHz */ - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF6); - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF8 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV5); - - - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } - -#else - /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF6); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} - -#elif defined SYSCLK_FREQ_56MHz -/** - * @brief Set System clock frequency to 56MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo56(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = PREDIV1 * 7 = 56 MHz */ - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF7); - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF8 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV5); - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } - -#else - /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF7); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} - -#elif defined SYSCLK_FREQ_72MHz -/** - * @brief Set System clock frequency to 72MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo72(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF9); - - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF8 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV5); - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } - -#else - /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF9); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} -#elif defined SYSCLK_FREQ_96MHz -/** - * @brief Set System clock frequency to 96MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo96(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = PREDIV1 * 12 = 96 MHz */ - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF12); - - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF8 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV5); - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } - -#else - /* PLL configuration: PLLCLK = HSE * 12 = 96 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF12); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} - -#elif defined SYSCLK_FREQ_108MHz -/** - * @brief Set System clock frequency to 108MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo108(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - /* Enable HSE */ - RCC->GCCR |= ((uint32_t)RCC_GCCR_HSEEN); - - /* Wait till HSE is ready and if Time out is reached exit */ - do { - HSEStatus = RCC->GCCR & RCC_GCCR_HSESTB; - StartUpCounter++; - } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); - - if ((RCC->GCCR & RCC_GCCR_HSESTB) != RESET) { - HSEStatus = (uint32_t)0x01; - } else { - HSEStatus = (uint32_t)0x00; - } - - if (HSEStatus == (uint32_t)0x01) { - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - -#ifdef GD32F10X_CL - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = PREDIV1 * 9 = 108 MHz */ - RCC->GCFGR &= (uint32_t)~(RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_PREDIV1 | RCC_GCFGR_PLLSEL_PREDIV1 | RCC_GCFGR_PLLMF9); - - /* PLL2 configuration: PLL2CLK = (HSE / 5) * 12 = 60 MHz */ - /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 12 MHz */ - - RCC->GCFGR2 &= (uint32_t)~(RCC_GCFGR2_PREDV2 | RCC_GCFGR2_PLL2MF | - RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - RCC->GCFGR2 |= (uint32_t)(RCC_GCFGR2_PREDV2_DIV5 | RCC_GCFGR2_PLL2MF12 | - RCC_GCFGR2_PREDV1SEL_PLL2 | RCC_GCFGR2_PREDV1_DIV5); - - /* Enable PLL2 */ - RCC->GCCR |= RCC_GCCR_PLL2EN; - /* Wait till PLL2 is ready */ - while ((RCC->GCCR & RCC_GCCR_PLL2STB) == 0) { - } - -#else - /* PLL configuration: PLLCLK = (HSE/2) * 27 = 108 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLPREDV_HSE_DIV2 | RCC_GCFGR_PLLSEL_HSE | RCC_GCFGR_PLLMF27); - -#endif /* GD32F10X_CL */ - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } - } else { - } -} -#elif defined SYSCLK_FREQ_48MHz_HSI -/** - * @brief Set System clock frequency to 48MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo48HSI(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = (HSI/2) * 12 = 48 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_HSI_DIV2 | RCC_GCFGR_PLLMF12); - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } -} -#elif defined SYSCLK_FREQ_72MHz_HSI -/** - * @brief Set System clock frequency to 72MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo72HSI(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = (HSI/2) * 18 = 72 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_HSI_DIV2 | RCC_GCFGR_PLLMF18); - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } -} - -#elif defined SYSCLK_FREQ_108MHz_HSI -/** - * @brief Set System clock frequency to 108MHz and configure AHB, APB1, and APB2 prescalers. - * @note This function should be used only after reset. - * @param None - * @retval None - */ -static void SetSysClockTo108HSI(void) -{ - __IO uint32_t StartUpCounter = 0, HSEStatus = 0; - - /* CK_SYS, AHB, APB2 and APB1 configuration ---------------------------*/ - - /* AHB = CK_SYS not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_AHBPS_DIV1; - - /* APB2 = AHB not divided */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB2PS_DIV1; - - /* APB1 = AHB is divided 2 */ - RCC->GCFGR |= (uint32_t)RCC_GCFGR_APB1PS_DIV2; - - /* Configure PLLs ------------------------------------------------------*/ - - /* PLL configuration: PLLCLK = (HSI/2) * 27 = 108 MHz */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_PLLSEL | RCC_GCFGR_PLLPREDV | RCC_GCFGR_PLLMF)); - RCC->GCFGR |= (uint32_t)(RCC_GCFGR_PLLSEL_HSI_DIV2 | RCC_GCFGR_PLLMF27); - - /* Enable PLL */ - RCC->GCCR |= RCC_GCCR_PLLEN; - - /* Wait till PLL is ready */ - while ((RCC->GCCR & RCC_GCCR_PLLSTB) == 0) { - } - - /* Select PLL as system clock source */ - RCC->GCFGR &= (uint32_t)((uint32_t)~(RCC_GCFGR_SCS)); - RCC->GCFGR |= (uint32_t)RCC_GCFGR_SCS_PLL; - - /* Wait till PLL is used as system clock source */ - while ((RCC->GCFGR & (uint32_t)RCC_GCFGR_SCSS) != (uint32_t)0x08) { - } -} -#endif - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - - diff --git a/bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.c b/bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.c deleted file mode 100644 index f2d043b8d6..0000000000 --- a/bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.c +++ /dev/null @@ -1,784 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.c - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File - * @version V1.30 - * @date 30. October 2009 - * - * @note - * Copyright (C) 2009 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#include - -/* define compiler specific symbols */ -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - -#endif - - -/* ################### Compiler specific Intrinsics ########################### */ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -__ASM uint32_t __get_PSP(void) -{ - mrs r0, psp - bx lr -} - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -__ASM void __set_PSP(uint32_t topOfProcStack) -{ - msr psp, r0 - bx lr -} - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -__ASM uint32_t __get_MSP(void) -{ - mrs r0, msp - bx lr -} - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -__ASM void __set_MSP(uint32_t mainStackPointer) -{ - msr msp, r0 - bx lr -} - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -__ASM uint32_t __REV16(uint16_t value) -{ - rev16 r0, r0 - bx lr -} - -/** - * @brief Reverse byte order in signed short value with sign extension to integer - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in signed short value with sign extension to integer - */ -__ASM int32_t __REVSH(int16_t value) -{ - revsh r0, r0 - bx lr -} - - -#if (__ARMCC_VERSION < 400000) - -/** - * @brief Remove the exclusive lock created by ldrex - * - * Removes the exclusive lock which is created by ldrex. - */ -__ASM void __CLREX(void) -{ - clrex -} - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -__ASM uint32_t __get_BASEPRI(void) -{ - mrs r0, basepri - bx lr -} - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -__ASM void __set_BASEPRI(uint32_t basePri) -{ - msr basepri, r0 - bx lr -} - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -__ASM uint32_t __get_PRIMASK(void) -{ - mrs r0, primask - bx lr -} - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -__ASM void __set_PRIMASK(uint32_t priMask) -{ - msr primask, r0 - bx lr -} - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -__ASM uint32_t __get_FAULTMASK(void) -{ - mrs r0, faultmask - bx lr -} - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -__ASM void __set_FAULTMASK(uint32_t faultMask) -{ - msr faultmask, r0 - bx lr -} - -/** - * @brief Return the Control Register value - * - * @return Control value - * - * Return the content of the control register - */ -__ASM uint32_t __get_CONTROL(void) -{ - mrs r0, control - bx lr -} - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -__ASM void __set_CONTROL(uint32_t control) -{ - msr control, r0 - bx lr -} - -#endif /* __ARMCC_VERSION */ - - - -#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ -#pragma diag_suppress=Pe940 - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -uint32_t __get_PSP(void) -{ - __ASM("mrs r0, psp"); - __ASM("bx lr"); -} - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -void __set_PSP(uint32_t topOfProcStack) -{ - __ASM("msr psp, r0"); - __ASM("bx lr"); -} - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -uint32_t __get_MSP(void) -{ - __ASM("mrs r0, msp"); - __ASM("bx lr"); -} - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -void __set_MSP(uint32_t topOfMainStack) -{ - __ASM("msr msp, r0"); - __ASM("bx lr"); -} - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -uint32_t __REV16(uint16_t value) -{ - __ASM("rev16 r0, r0"); - __ASM("bx lr"); -} - -/** - * @brief Reverse bit order of value - * - * @param value value to reverse - * @return reversed value - * - * Reverse bit order of value - */ -uint32_t __RBIT(uint32_t value) -{ - __ASM("rbit r0, r0"); - __ASM("bx lr"); -} - -/** - * @brief LDR Exclusive (8 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 8 bit values) - */ -uint8_t __LDREXB(uint8_t *addr) -{ - __ASM("ldrexb r0, [r0]"); - __ASM("bx lr"); -} - -/** - * @brief LDR Exclusive (16 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 16 bit values - */ -uint16_t __LDREXH(uint16_t *addr) -{ - __ASM("ldrexh r0, [r0]"); - __ASM("bx lr"); -} - -/** - * @brief LDR Exclusive (32 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 32 bit values - */ -uint32_t __LDREXW(uint32_t *addr) -{ - __ASM("ldrex r0, [r0]"); - __ASM("bx lr"); -} - -/** - * @brief STR Exclusive (8 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 8 bit values - */ -uint32_t __STREXB(uint8_t value, uint8_t *addr) -{ - __ASM("strexb r0, r0, [r1]"); - __ASM("bx lr"); -} - -/** - * @brief STR Exclusive (16 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 16 bit values - */ -uint32_t __STREXH(uint16_t value, uint16_t *addr) -{ - __ASM("strexh r0, r0, [r1]"); - __ASM("bx lr"); -} - -/** - * @brief STR Exclusive (32 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 32 bit values - */ -uint32_t __STREXW(uint32_t value, uint32_t *addr) -{ - __ASM("strex r0, r0, [r1]"); - __ASM("bx lr"); -} - -#pragma diag_default=Pe940 - - -#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -uint32_t __get_PSP(void) __attribute__((naked)); -uint32_t __get_PSP(void) -{ - uint32_t result = 0; - - __ASM volatile("MRS %0, psp\n\t" - "MOV r0, %0 \n\t" - "BX lr \n\t" : "=r"(result)); - return (result); -} - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -void __set_PSP(uint32_t topOfProcStack) __attribute__((naked)); -void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile("MSR psp, %0\n\t" - "BX lr \n\t" : : "r"(topOfProcStack)); -} - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -uint32_t __get_MSP(void) __attribute__((naked)); -uint32_t __get_MSP(void) -{ - uint32_t result = 0; - - __ASM volatile("MRS %0, msp\n\t" - "MOV r0, %0 \n\t" - "BX lr \n\t" : "=r"(result)); - return (result); -} - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -void __set_MSP(uint32_t topOfMainStack) __attribute__((naked)); -void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile("MSR msp, %0\n\t" - "BX lr \n\t" : : "r"(topOfMainStack)); -} - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -uint32_t __get_BASEPRI(void) -{ - uint32_t result = 0; - - __ASM volatile("MRS %0, basepri_max" : "=r"(result)); - return (result); -} - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -void __set_BASEPRI(uint32_t value) -{ - __ASM volatile("MSR basepri, %0" : : "r"(value)); -} - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -uint32_t __get_PRIMASK(void) -{ - uint32_t result = 0; - - __ASM volatile("MRS %0, primask" : "=r"(result)); - return (result); -} - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile("MSR primask, %0" : : "r"(priMask)); -} - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -uint32_t __get_FAULTMASK(void) -{ - uint32_t result = 0; - - __ASM volatile("MRS %0, faultmask" : "=r"(result)); - return (result); -} - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile("MSR faultmask, %0" : : "r"(faultMask)); -} - -/** - * @brief Return the Control Register value -* -* @return Control value - * - * Return the content of the control register - */ -uint32_t __get_CONTROL(void) -{ - uint32_t result = 0; - - __ASM volatile("MRS %0, control" : "=r"(result)); - return (result); -} - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -void __set_CONTROL(uint32_t control) -{ - __ASM volatile("MSR control, %0" : : "r"(control)); -} - - -/** - * @brief Reverse byte order in integer value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in integer value - */ -uint32_t __REV(uint32_t value) -{ - uint32_t result = 0; - - __ASM volatile("rev %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -uint32_t __REV16(uint16_t value) -{ - uint32_t result = 0; - - __ASM volatile("rev16 %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - -/** - * @brief Reverse byte order in signed short value with sign extension to integer - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in signed short value with sign extension to integer - */ -int32_t __REVSH(int16_t value) -{ - uint32_t result = 0; - - __ASM volatile("revsh %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - -/** - * @brief Reverse bit order of value - * - * @param value value to reverse - * @return reversed value - * - * Reverse bit order of value - */ -uint32_t __RBIT(uint32_t value) -{ - uint32_t result = 0; - - __ASM volatile("rbit %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - -/** - * @brief LDR Exclusive (8 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 8 bit value - */ -uint8_t __LDREXB(uint8_t *addr) -{ - uint8_t result = 0; - - __ASM volatile("ldrexb %0, [%1]" : "=r"(result) : "r"(addr)); - return (result); -} - -/** - * @brief LDR Exclusive (16 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 16 bit values - */ -uint16_t __LDREXH(uint16_t *addr) -{ - uint16_t result = 0; - - __ASM volatile("ldrexh %0, [%1]" : "=r"(result) : "r"(addr)); - return (result); -} - -/** - * @brief LDR Exclusive (32 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 32 bit values - */ -uint32_t __LDREXW(uint32_t *addr) -{ - uint32_t result = 0; - - __ASM volatile("ldrex %0, [%1]" : "=r"(result) : "r"(addr)); - return (result); -} - -/** - * @brief STR Exclusive (8 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 8 bit values - */ -uint32_t __STREXB(uint8_t value, uint8_t *addr) -{ - uint32_t result = 0; - - __ASM volatile("strexb %0, %2, [%1]" : "=r"(result) : "r"(addr), "r"(value)); - return (result); -} - -/** - * @brief STR Exclusive (16 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 16 bit values - */ -uint32_t __STREXH(uint16_t value, uint16_t *addr) -{ - uint32_t result = 0; - - __ASM volatile("strexh %0, %2, [%1]" : "=r"(result) : "r"(addr), "r"(value)); - return (result); -} - -/** - * @brief STR Exclusive (32 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 32 bit values - */ -uint32_t __STREXW(uint32_t value, uint32_t *addr) -{ - uint32_t result = 0; - - __ASM volatile("strex %0, %2, [%1]" : "=r"(result) : "r"(addr), "r"(value)); - return (result); -} - - -#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all instrinsics, - * Including the CMSIS ones. - */ - -#endif diff --git a/bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.h b/bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.h deleted file mode 100644 index d8ec332d93..0000000000 --- a/bsp/gd32103c-eval/Libraries/CMSIS/core_cm3.h +++ /dev/null @@ -1,1614 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.h - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V3.20 - * @date 25. February 2013 - * - * @note - * - ******************************************************************************/ -/* Copyright (c) 2009 - 2013 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __CORE_CM3_H_GENERIC -#define __CORE_CM3_H_GENERIC - -/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions - CMSIS violates the following MISRA-C:2004 rules: - - \li Required Rule 8.5, object/function definition in header file.
- Function definitions in header files are used to allow 'inlining'. - - \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
- Unions are used for effective representation of core registers. - - \li Advisory Rule 19.7, Function-like macro defined.
- Function-like macros are used to allow more efficient code. - */ - - -/******************************************************************************* - * CMSIS definitions - ******************************************************************************/ -/** \ingroup Cortex_M3 - @{ - */ - -/* CMSIS CM3 definitions */ -#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ -#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ - __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x03) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) -#define __ASM __asm /*!< asm keyword for ARM Compiler */ -#define __INLINE __inline /*!< inline keyword for ARM Compiler */ -#define __STATIC_INLINE static __inline - -#elif defined ( __ICCARM__ ) -#define __ASM __asm /*!< asm keyword for IAR Compiler */ -#define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ -#define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) -#define __ASM __asm /*!< asm keyword for TI CCS Compiler */ -#define __STATIC_INLINE static inline - -#elif defined ( __GNUC__ ) -#define __ASM __asm /*!< asm keyword for GNU Compiler */ -#define __INLINE inline /*!< inline keyword for GNU Compiler */ -#define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) -#define __ASM __asm /*!< asm keyword for TASKING Compiler */ -#define __INLINE inline /*!< inline keyword for TASKING Compiler */ -#define __STATIC_INLINE static inline - -#endif - -/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all -*/ -#define __FPU_USED 0 - -#if defined ( __CC_ARM ) -#if defined __TARGET_FPU_VFP -#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" -#endif - -#elif defined ( __ICCARM__ ) -#if defined __ARMVFP__ -#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" -#endif - -#elif defined ( __TMS470__ ) -#if defined __TI__VFP_SUPPORT____ -#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" -#endif - -#elif defined ( __GNUC__ ) -#if defined (__VFP_FP__) && !defined(__SOFTFP__) -#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" -#endif - -#elif defined ( __TASKING__ ) -#if defined __FPU_VFP__ -#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" -#endif -#endif - -#include /* standard types definitions */ -#include /* Core Instruction Access */ -#include /* Core Function Access */ - -#endif /* __CORE_CM3_H_GENERIC */ - -#ifndef __CMSIS_GENERIC - -#ifndef __CORE_CM3_H_DEPENDANT -#define __CORE_CM3_H_DEPENDANT - -/* check device defines and use defaults */ -#if defined __CHECK_DEVICE_DEFINES -#ifndef __CM3_REV -#define __CM3_REV 0x0200 -#warning "__CM3_REV not defined in device header file; using default!" -#endif - -#ifndef __MPU_PRESENT -#define __MPU_PRESENT 0 -#warning "__MPU_PRESENT not defined in device header file; using default!" -#endif - -#ifndef __NVIC_PRIO_BITS -#define __NVIC_PRIO_BITS 4 -#warning "__NVIC_PRIO_BITS not defined in device header file; using default!" -#endif - -#ifndef __Vendor_SysTickConfig -#define __Vendor_SysTickConfig 0 -#warning "__Vendor_SysTickConfig not defined in device header file; using default!" -#endif -#endif - -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ -#ifdef __cplusplus -#define __I volatile /*!< Defines 'read only' permissions */ -#else -#define __I volatile const /*!< Defines 'read only' permissions */ -#endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/*@} end of group Cortex_M3 */ - - - -/******************************************************************************* - * Register Abstraction - Core Register contain: - - Core Register - - Core NVIC Register - - Core SCB Register - - Core SysTick Register - - Core Debug Register - - Core MPU Register - ******************************************************************************/ -/** \defgroup CMSIS_core_register Defines and Type Definitions - \brief Type definitions and defines for Cortex-M processor based devices. -*/ - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_CORE Status and Control Registers - \brief Core Register type definitions. - @{ - */ - -/** \brief Union type to access the Application Program Status Register (APSR). - */ -typedef union { - struct { -#if (__CORTEX_M != 0x04) - uint32_t _reserved0: 27; /*!< bit: 0..26 Reserved */ -#else - uint32_t _reserved0: 16; /*!< bit: 0..15 Reserved */ - uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1: 7; /*!< bit: 20..26 Reserved */ -#endif - uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ - uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ - uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} APSR_Type; - - -/** \brief Union type to access the Interrupt Program Status Register (IPSR). - */ -typedef union { - struct { - uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0: 23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} IPSR_Type; - - -/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). - */ -typedef union { - struct { - uint32_t ISR: 9; /*!< bit: 0.. 8 Exception number */ -#if (__CORTEX_M != 0x04) - uint32_t _reserved0: 15; /*!< bit: 9..23 Reserved */ -#else - uint32_t _reserved0: 7; /*!< bit: 9..15 Reserved */ - uint32_t GE: 4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1: 4; /*!< bit: 20..23 Reserved */ -#endif - uint32_t T: 1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT: 2; /*!< bit: 25..26 saved IT state (read 0) */ - uint32_t Q: 1; /*!< bit: 27 Saturation condition flag */ - uint32_t V: 1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C: 1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z: 1; /*!< bit: 30 Zero condition code flag */ - uint32_t N: 1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} xPSR_Type; - - -/** \brief Union type to access the Control Registers (CONTROL). - */ -typedef union { - struct { - uint32_t nPRIV: 1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL: 1; /*!< bit: 1 Stack to be used */ - uint32_t FPCA: 1; /*!< bit: 2 FP extension active flag */ - uint32_t _reserved0: 29; /*!< bit: 3..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} CONTROL_Type; - -/*@} end of group CMSIS_CORE */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) - \brief Type definitions for the NVIC Registers - @{ - */ - -/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). - */ -typedef struct { - __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24]; - __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24]; - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24]; - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24]; - __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56]; - __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644]; - __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ -} NVIC_Type; - -/* Software Triggered Interrupt Register Definitions */ -#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ -#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ - -/*@} end of group CMSIS_NVIC */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SCB System Control Block (SCB) - \brief Type definitions for the System Control Block Registers - @{ - */ - -/** \brief Structure type to access the System Control Block (SCB). - */ -typedef struct { - __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5]; - __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ -#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ - -#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Vector Table Offset Register Definitions */ -#if (__CM3_REV < 0x0201) /* core r2p1 */ -#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ -#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ - -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#else -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#endif - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Registers Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* SCB Hard Fault Status Registers Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ - -/*@} end of group CMSIS_SCB */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) - \brief Type definitions for the System Control and ID Register not in the SCB - @{ - */ - -/** \brief Structure type to access the System Control and ID Register not in the SCB. - */ -typedef struct { - uint32_t RESERVED0[1]; - __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ -#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) - __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ -#else - uint32_t RESERVED1[1]; -#endif -} SCnSCB_Type; - -/* Interrupt Controller Type Register Definitions */ -#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ -#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ - -#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ -#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ - -#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ -#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ - -#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ -#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ - -/*@} end of group CMSIS_SCnotSCB */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SysTick System Tick Timer (SysTick) - \brief Type definitions for the System Timer Registers. - @{ - */ - -/** \brief Structure type to access the System Timer (SysTick). - */ -typedef struct { - __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ - -/*@} end of group CMSIS_SysTick */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) - \brief Type definitions for the Instrumentation Trace Macrocell (ITM) - @{ - */ - -/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). - */ -typedef struct { - __O union { - __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864]; - __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15]; - __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15]; - __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29]; - __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43]; - __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6]; - __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ -#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ - -#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ - -/*@}*/ /* end of group CMSIS_ITM */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) - \brief Type definitions for the Data Watchpoint and Trace (DWT) - @{ - */ - -/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). - */ -typedef struct { - __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1]; - __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1]; - __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1]; - __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ -} DWT_Type; - -/* DWT Control Register Definitions */ -#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ -#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ - -#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ -#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ - -#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ -#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ - -#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ -#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ - -#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ -#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ - -#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ -#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ - -#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ -#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ - -#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ -#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ - -#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ -#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ - -#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ -#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ - -#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ -#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ - -#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ -#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ - -#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ -#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ - -#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ -#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ - -#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ -#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ - -#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ -#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ - -#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ -#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ - -#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ -#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ - -/* DWT CPI Count Register Definitions */ -#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ -#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ - -/* DWT Exception Overhead Count Register Definitions */ -#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ -#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ - -/* DWT Sleep Count Register Definitions */ -#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ -#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ - -/* DWT LSU Count Register Definitions */ -#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ -#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ - -/* DWT Folded-instruction Count Register Definitions */ -#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ -#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ - -/* DWT Comparator Mask Register Definitions */ -#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ -#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ - -/* DWT Comparator Function Register Definitions */ -#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ -#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ - -#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ -#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ - -#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ -#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ - -#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ -#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ - -#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ -#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ - -#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ -#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ - -#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ -#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ - -#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ -#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ - -#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ -#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ - -/*@}*/ /* end of group CMSIS_DWT */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_TPI Trace Port Interface (TPI) - \brief Type definitions for the Trace Port Interface (TPI) - @{ - */ - -/** \brief Structure type to access the Trace Port Interface Register (TPI). - */ -typedef struct { - __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2]; - __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55]; - __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131]; - __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759]; - __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1]; - __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39]; - __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8]; - __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ -} TPI_Type; - -/* TPI Asynchronous Clock Prescaler Register Definitions */ -#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ -#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ - -/* TPI Selected Pin Protocol Register Definitions */ -#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ -#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ - -/* TPI Formatter and Flush Status Register Definitions */ -#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ -#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ - -#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ -#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ - -#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ -#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ - -#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ -#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ - -/* TPI Formatter and Flush Control Register Definitions */ -#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ -#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ - -#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ -#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ - -/* TPI TRIGGER Register Definitions */ -#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ -#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ - -/* TPI Integration ETM Data Register Definitions (FIFO0) */ -#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ - -#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ -#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ - -#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ - -#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ -#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ - -#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ -#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ - -#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ -#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ - -#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ -#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ - -/* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ - -/* TPI Integration ITM Data Register Definitions (FIFO1) */ -#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ - -#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ -#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ - -#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ - -#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ -#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ - -#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ -#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ - -#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ -#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ - -#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ -#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ - -/* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ - -/* TPI Integration Mode Control Register Definitions */ -#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ - -/* TPI DEVID Register Definitions */ -#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ -#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ - -#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ -#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ - -#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ -#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ - -#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ -#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ - -#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ -#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ - -#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ -#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ - -/* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ -#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ - -#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -/*@}*/ /* end of group CMSIS_TPI */ - - -#if (__MPU_PRESENT == 1) -/** \ingroup CMSIS_core_register - \defgroup CMSIS_MPU Memory Protection Unit (MPU) - \brief Type definitions for the Memory Protection Unit (MPU) - @{ - */ - -/** \brief Structure type to access the Memory Protection Unit (MPU). - */ -typedef struct { - __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -/* MPU Type Register */ -#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register */ -#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register */ -#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register */ -#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register */ -#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ -#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ - -#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ -#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ - -#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ -#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ - -#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ -#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ - -#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ -#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ - -#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ -#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ - -#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ -#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ - -#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@} end of group CMSIS_MPU */ -#endif - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) - \brief Type definitions for the Core Debug Registers - @{ - */ - -/** \brief Structure type to access the Core Debug Register (CoreDebug). - */ -typedef struct { - __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register */ -#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register */ -#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ - -/*@} end of group CMSIS_CoreDebug */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_core_base Core Definitions - \brief Definitions for base addresses, unions, and structures. - @{ - */ - -/* Memory mapping of Cortex-M3 Hardware */ -#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ -#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ -#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ -#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - -#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ -#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ -#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ -#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if (__MPU_PRESENT == 1) -#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ -#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ -#endif - -/*@} */ - - - -/******************************************************************************* - * Hardware Abstraction Layer - Core Function Interface contains: - - Core NVIC Functions - - Core SysTick Functions - - Core Debug Functions - - Core Register Access Functions - ******************************************************************************/ -/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference -*/ - - - -/* ########################## NVIC functions #################################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_NVICFunctions NVIC Functions - \brief Functions that manage interrupts and exceptions via the NVIC. - @{ - */ - -/** \brief Set Priority Grouping - - The function sets the priority grouping field using the required unlock sequence. - The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. - Only values from 0..7 are used. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - - \param [in] PriorityGroup Priority grouping field. - */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; -} - - -/** \brief Get Priority Grouping - - The function reads the priority grouping field from the NVIC Interrupt Controller. - - \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). - */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) -{ - return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ -} - - -/** \brief Enable External Interrupt - - The function enables a device-specific interrupt in the NVIC interrupt controller. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ -} - - -/** \brief Disable External Interrupt - - The function disables a device-specific interrupt in the NVIC interrupt controller. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ -} - - -/** \brief Get Pending Interrupt - - The function reads the pending register in the NVIC and returns the pending bit - for the specified interrupt. - - \param [in] IRQn Interrupt number. - - \return 0 Interrupt status is not pending. - \return 1 Interrupt status is pending. - */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return ((uint32_t)((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0)); /* Return 1 if pending else 0 */ -} - - -/** \brief Set Pending Interrupt - - The function sets the pending bit of an external interrupt. - - \param [in] IRQn Interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ -} - - -/** \brief Clear Pending Interrupt - - The function clears the pending bit of an external interrupt. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ -} - - -/** \brief Get Active Interrupt - - The function reads the active register in NVIC and returns the active bit. - - \param [in] IRQn Interrupt number. - - \return 0 Interrupt status is not active. - \return 1 Interrupt status is active. - */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return ((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0)); /* Return 1 if active else 0 */ -} - - -/** \brief Set Interrupt Priority - - The function sets the priority of an interrupt. - - \note The priority cannot be set for every core interrupt. - - \param [in] IRQn Interrupt number. - \param [in] priority Priority to set. - */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if (IRQn < 0) { - SCB->SHP[((uint32_t)(IRQn) & 0xF) - 4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); - } /* set Priority for Cortex-M System Interrupts */ - else { - NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); - } /* set Priority for device specific Interrupts */ -} - - -/** \brief Get Interrupt Priority - - The function reads the priority of an interrupt. The interrupt - number can be positive to specify an external (device specific) - interrupt, or negative to specify an internal (core) interrupt. - - - \param [in] IRQn Interrupt number. - \return Interrupt Priority. Value is aligned automatically to the implemented - priority bits of the microcontroller. - */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) -{ - - if (IRQn < 0) { - return ((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF) - 4] >> (8 - __NVIC_PRIO_BITS))); - } /* get priority for Cortex-M system interrupts */ - else { - return ((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); - } /* get priority for device specific interrupts */ -} - - -/** \brief Encode Priority - - The function encodes the priority for an interrupt with the given priority group, - preemptive priority value, and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. - - \param [in] PriorityGroup Used priority group. - \param [in] PreemptPriority Preemptive priority value (starting from 0). - \param [in] SubPriority Subpriority value (starting from 0). - \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). - */ -__STATIC_INLINE uint32_t NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - return ( - ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | - ((SubPriority & ((1 << (SubPriorityBits)) - 1))) - ); -} - - -/** \brief Decode Priority - - The function decodes an interrupt priority value with a given priority group to - preemptive priority value and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. - - \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). - \param [in] PriorityGroup Used priority group. - \param [out] pPreemptPriority Preemptive priority value (starting from 0). - \param [out] pSubPriority Subpriority value (starting from 0). - */ -__STATIC_INLINE void NVIC_DecodePriority(uint32_t Priority, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); - *pSubPriority = (Priority) & ((1 << (SubPriorityBits)) - 1); -} - - -/** \brief System Reset - - The function initiates a system reset request to reset the MCU. - */ -__STATIC_INLINE void NVIC_SystemReset(void) -{ - __DSB(); /* Ensure all outstanding memory accesses included - buffered write are completed before reset */ - SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ - while (1); /* wait until reset */ -} - -/*@} end of CMSIS_Core_NVICFunctions */ - - - -/* ################################## SysTick function ############################################ */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_SysTickFunctions SysTick Functions - \brief Functions that configure the System. - @{ - */ - -#if (__Vendor_SysTickConfig == 0) - -/** \brief System Tick Configuration - - The function initializes the System Timer and its interrupt, and starts the System Tick Timer. - Counter is in free running mode to generate periodic interrupts. - - \param [in] ticks Number of ticks between two interrupts. - - \return 0 Function succeeded. - \return 1 Function failed. - - \note When the variable __Vendor_SysTickConfig is set to 1, then the - function SysTick_Config is not included. In this case, the file device.h - must contain a vendor-specific implementation of this function. - - */ -__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ - - SysTick->LOAD = ticks - 1; /* set reload register */ - NVIC_SetPriority(SysTick_IRQn, (1 << __NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0); /* Function successful */ -} - -#endif - -/*@} end of CMSIS_Core_SysTickFunctions */ - - - -/* ##################################### Debug In/Output function ########################################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_core_DebugFunctions ITM Functions - \brief Functions that access the ITM debug interface. - @{ - */ - -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ - - -/** \brief ITM Send Character - - The function transmits a character via the ITM channel 0, and - \li Just returns when no debugger is connected that has booked the output. - \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. - - \param [in] ch Character to transmit. - - \returns Character to transmit. - */ -__STATIC_INLINE uint32_t ITM_SendChar(uint32_t ch) -{ - if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ - (ITM->TER & (1UL << 0))) { /* ITM Port #0 enabled */ - while (ITM->PORT[0].u32 == 0); - ITM->PORT[0].u8 = (uint8_t) ch; - } - return (ch); -} - - -/** \brief ITM Receive Character - - The function inputs a character via the external variable \ref ITM_RxBuffer. - - \return Received character. - \return -1 No character pending. - */ -__STATIC_INLINE int32_t ITM_ReceiveChar(void) -{ - int32_t ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** \brief ITM Check Character - - The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. - - \return 0 No character available. - \return 1 Character available. - */ -__STATIC_INLINE int32_t ITM_CheckChar(void) -{ - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { - return (0); /* no character available */ - } else { - return (1); /* character available */ - } -} - -/*@} end of CMSIS_core_DebugFunctions */ - -#endif /* __CORE_CM3_H_DEPENDANT */ - -#endif /* __CMSIS_GENERIC */ - -#ifdef __cplusplus -} -#endif diff --git a/bsp/gd32103c-eval/Libraries/CMSIS/core_cmFunc.h b/bsp/gd32103c-eval/Libraries/CMSIS/core_cmFunc.h deleted file mode 100644 index 4a6b5d6683..0000000000 --- a/bsp/gd32103c-eval/Libraries/CMSIS/core_cmFunc.h +++ /dev/null @@ -1,616 +0,0 @@ -/**************************************************************************//** - * @file core_cmFunc.h - * @brief CMSIS Cortex-M Core Function Access Header File - * @version V3.01 - * @date 06. March 2012 - * - * @note - * Copyright (C) 2009-2012 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#ifndef __CORE_CMFUNC_H -#define __CORE_CMFUNC_H - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -#if (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" -#endif - -/* intrinsic void __enable_irq(); */ -/* intrinsic void __disable_irq(); */ - -/** \brief Get Control Register - - This function returns the content of the Control Register. - - \return Control Register value - */ -__STATIC_INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return (__regControl); -} - - -/** \brief Set Control Register - - This function writes the given value to the Control Register. - - \param [in] control Control Register value to set - */ -__STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; -} - - -/** \brief Get IPSR Register - - This function returns the content of the IPSR Register. - - \return IPSR Register value - */ -__STATIC_INLINE uint32_t __get_IPSR(void) -{ - register uint32_t __regIPSR __ASM("ipsr"); - return (__regIPSR); -} - - -/** \brief Get APSR Register - - This function returns the content of the APSR Register. - - \return APSR Register value - */ -__STATIC_INLINE uint32_t __get_APSR(void) -{ - register uint32_t __regAPSR __ASM("apsr"); - return (__regAPSR); -} - - -/** \brief Get xPSR Register - - This function returns the content of the xPSR Register. - - \return xPSR Register value - */ -__STATIC_INLINE uint32_t __get_xPSR(void) -{ - register uint32_t __regXPSR __ASM("xpsr"); - return (__regXPSR); -} - - -/** \brief Get Process Stack Pointer - - This function returns the current value of the Process Stack Pointer (PSP). - - \return PSP Register value - */ -__STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - return (__regProcessStackPointer); -} - - -/** \brief Set Process Stack Pointer - - This function assigns the given value to the Process Stack Pointer (PSP). - - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - __regProcessStackPointer = topOfProcStack; -} - - -/** \brief Get Main Stack Pointer - - This function returns the current value of the Main Stack Pointer (MSP). - - \return MSP Register value - */ -__STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - return (__regMainStackPointer); -} - - -/** \brief Set Main Stack Pointer - - This function assigns the given value to the Main Stack Pointer (MSP). - - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - __regMainStackPointer = topOfMainStack; -} - - -/** \brief Get Priority Mask - - This function returns the current state of the priority mask bit from the Priority Mask Register. - - \return Priority Mask value - */ -__STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return (__regPriMask); -} - - -/** \brief Set Priority Mask - - This function assigns the given value to the Priority Mask Register. - - \param [in] priMask Priority Mask - */ -__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - - -#if (__CORTEX_M >= 0x03) - -/** \brief Enable FIQ - - This function enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq - - -/** \brief Disable FIQ - - This function disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq - - -/** \brief Get Base Priority - - This function returns the current value of the Base Priority register. - - \return Base Priority register value - */ -__STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return (__regBasePri); -} - - -/** \brief Set Base Priority - - This function assigns the given value to the Base Priority register. - - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xff); -} - - -/** \brief Get Fault Mask - - This function returns the current value of the Fault Mask register. - - \return Fault Mask register value - */ -__STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return (__regFaultMask); -} - - -/** \brief Set Fault Mask - - This function assigns the given value to the Fault Mask register. - - \param [in] faultMask Fault Mask value to set - */ -__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1); -} - -#endif /* (__CORTEX_M >= 0x03) */ - - -#if (__CORTEX_M == 0x04) - -/** \brief Get FPSCR - - This function returns the current value of the Floating Point Status/Control register. - - \return Floating Point Status/Control register value - */ -__STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - register uint32_t __regfpscr __ASM("fpscr"); - return (__regfpscr); -#else - return (0); -#endif -} - - -/** \brief Set FPSCR - - This function assigns the given value to the Floating Point Status/Control register. - - \param [in] fpscr Floating Point Status/Control value to set - */ -__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - register uint32_t __regfpscr __ASM("fpscr"); - __regfpscr = (fpscr); -#endif -} - -#endif /* (__CORTEX_M == 0x04) */ - - -#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ - -#include - - -#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ -/* TI CCS specific functions */ - -#include - - -#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -/** \brief Enable IRQ Interrupts - - This function enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) -{ - __ASM volatile("cpsie i"); -} - - -/** \brief Disable IRQ Interrupts - - This function disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) -{ - __ASM volatile("cpsid i"); -} - - -/** \brief Get Control Register - - This function returns the content of the Control Register. - - \return Control Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, control" : "=r"(result)); - return (result); -} - - -/** \brief Set Control Register - - This function writes the given value to the Control Register. - - \param [in] control Control Register value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile("MSR control, %0" : : "r"(control)); -} - - -/** \brief Get IPSR Register - - This function returns the content of the IPSR Register. - - \return IPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, ipsr" : "=r"(result)); - return (result); -} - - -/** \brief Get APSR Register - - This function returns the content of the APSR Register. - - \return APSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, apsr" : "=r"(result)); - return (result); -} - - -/** \brief Get xPSR Register - - This function returns the content of the xPSR Register. - - \return xPSR Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, xpsr" : "=r"(result)); - return (result); -} - - -/** \brief Get Process Stack Pointer - - This function returns the current value of the Process Stack Pointer (PSP). - - \return PSP Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t result; - - __ASM volatile("MRS %0, psp\n" : "=r"(result)); - return (result); -} - - -/** \brief Set Process Stack Pointer - - This function assigns the given value to the Process Stack Pointer (PSP). - - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile("MSR psp, %0\n" : : "r"(topOfProcStack)); -} - - -/** \brief Get Main Stack Pointer - - This function returns the current value of the Main Stack Pointer (MSP). - - \return MSP Register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t result; - - __ASM volatile("MRS %0, msp\n" : "=r"(result)); - return (result); -} - - -/** \brief Set Main Stack Pointer - - This function assigns the given value to the Main Stack Pointer (MSP). - - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile("MSR msp, %0\n" : : "r"(topOfMainStack)); -} - - -/** \brief Get Priority Mask - - This function returns the current state of the priority mask bit from the Priority Mask Register. - - \return Priority Mask value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, primask" : "=r"(result)); - return (result); -} - - -/** \brief Set Priority Mask - - This function assigns the given value to the Priority Mask Register. - - \param [in] priMask Priority Mask - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile("MSR primask, %0" : : "r"(priMask)); -} - - -#if (__CORTEX_M >= 0x03) - -/** \brief Enable FIQ - - This function enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) -{ - __ASM volatile("cpsie f"); -} - - -/** \brief Disable FIQ - - This function disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) -{ - __ASM volatile("cpsid f"); -} - - -/** \brief Get Base Priority - - This function returns the current value of the Base Priority register. - - \return Base Priority register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, basepri_max" : "=r"(result)); - return (result); -} - - -/** \brief Set Base Priority - - This function assigns the given value to the Base Priority register. - - \param [in] basePri Base Priority value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) -{ - __ASM volatile("MSR basepri, %0" : : "r"(value)); -} - - -/** \brief Get Fault Mask - - This function returns the current value of the Fault Mask register. - - \return Fault Mask register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - uint32_t result; - - __ASM volatile("MRS %0, faultmask" : "=r"(result)); - return (result); -} - - -/** \brief Set Fault Mask - - This function assigns the given value to the Fault Mask register. - - \param [in] faultMask Fault Mask value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile("MSR faultmask, %0" : : "r"(faultMask)); -} - -#endif /* (__CORTEX_M >= 0x03) */ - - -#if (__CORTEX_M == 0x04) - -/** \brief Get FPSCR - - This function returns the current value of the Floating Point Status/Control register. - - \return Floating Point Status/Control register value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - uint32_t result; - - __ASM volatile("VMRS %0, fpscr" : "=r"(result)); - return (result); -#else - return (0); -#endif -} - - -/** \brief Set FPSCR - - This function assigns the given value to the Floating Point Status/Control register. - - \param [in] fpscr Floating Point Status/Control value to set - */ -__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - __ASM volatile("VMSR fpscr, %0" : : "r"(fpscr)); -#endif -} - -#endif /* (__CORTEX_M == 0x04) */ - - -#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all instrinsics, - * Including the CMSIS ones. - */ - -#endif - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -#endif /* __CORE_CMFUNC_H */ diff --git a/bsp/gd32103c-eval/Libraries/CMSIS/core_cmInstr.h b/bsp/gd32103c-eval/Libraries/CMSIS/core_cmInstr.h deleted file mode 100644 index 1c0b6f6b97..0000000000 --- a/bsp/gd32103c-eval/Libraries/CMSIS/core_cmInstr.h +++ /dev/null @@ -1,618 +0,0 @@ -/**************************************************************************//** - * @file core_cmInstr.h - * @brief CMSIS Cortex-M Core Instruction Access Header File - * @version V3.01 - * @date 06. March 2012 - * - * @note - * Copyright (C) 2009-2012 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#ifndef __CORE_CMINSTR_H -#define __CORE_CMINSTR_H - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -#if (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" -#endif - - -/** \brief No Operation - - No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __nop - - -/** \brief Wait For Interrupt - - Wait For Interrupt is a hint instruction that suspends execution - until one of a number of events occurs. - */ -#define __WFI __wfi - - -/** \brief Wait For Event - - Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __wfe - - -/** \brief Send Event - - Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __sev - - -/** \brief Instruction Synchronization Barrier - - Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or - memory, after the instruction has been completed. - */ -#define __ISB() __isb(0xF) - - -/** \brief Data Synchronization Barrier - - This function acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() __dsb(0xF) - - -/** \brief Data Memory Barrier - - This function ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() __dmb(0xF) - - -/** \brief Reverse byte order (32 bit) - - This function reverses the byte order in integer value. - - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV __rev - - -/** \brief Reverse byte order (16 bit) - - This function reverses the byte order in two unsigned short values. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) -{ - rev16 r0, r0 - bx lr -} - - -/** \brief Reverse byte order in signed short value - - This function reverses the byte order in a signed short value with sign extension to integer. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) -{ - revsh r0, r0 - bx lr -} - - -/** \brief Rotate Right in unsigned value (32 bit) - - This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -#define __ROR __ror - - -#if (__CORTEX_M >= 0x03) - - /** \brief Reverse bit order of value - - This function reverses the bit order of the given value. - - \param [in] value Value to reverse - \return Reversed value - */ - #define __RBIT __rbit - - - /** \brief LDR Exclusive (8 bit) - - This function performs a exclusive LDR command for 8 bit value. - - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ - #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) - - - /** \brief LDR Exclusive (16 bit) - - This function performs a exclusive LDR command for 16 bit values. - - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ - #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) - - - /** \brief LDR Exclusive (32 bit) - - This function performs a exclusive LDR command for 32 bit values. - - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ - #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) - - - /** \brief STR Exclusive (8 bit) - - This function performs a exclusive STR command for 8 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ - #define __STREXB(value, ptr) __strex(value, ptr) - - - /** \brief STR Exclusive (16 bit) - - This function performs a exclusive STR command for 16 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ - #define __STREXH(value, ptr) __strex(value, ptr) - - - /** \brief STR Exclusive (32 bit) - - This function performs a exclusive STR command for 32 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ - #define __STREXW(value, ptr) __strex(value, ptr) - - - /** \brief Remove the exclusive lock - - This function removes the exclusive lock which is created by LDREX. - - */ - #define __CLREX __clrex - - - /** \brief Signed Saturate - - This function saturates a signed value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ - #define __SSAT __ssat - - - /** \brief Unsigned Saturate - - This function saturates an unsigned value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ - #define __USAT __usat - - - /** \brief Count leading zeros - - This function counts the number of leading zeros of a data value. - - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ - #define __CLZ __clz - -#endif /* (__CORTEX_M >= 0x03) */ - - - -#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ - -#include - - -#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ -/* TI CCS specific functions */ - -#include - - -#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -/** \brief No Operation - - No Operation does nothing. This instruction can be used for code alignment purposes. - */ -__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) -{ - __ASM volatile("nop"); -} - - -/** \brief Wait For Interrupt - - Wait For Interrupt is a hint instruction that suspends execution - until one of a number of events occurs. - */ -__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) -{ - __ASM volatile("wfi"); -} - - -/** \brief Wait For Event - - Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) -{ - __ASM volatile("wfe"); -} - - -/** \brief Send Event - - Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) -{ - __ASM volatile("sev"); -} - - -/** \brief Instruction Synchronization Barrier - - Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or - memory, after the instruction has been completed. - */ -__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) -{ - __ASM volatile("isb"); -} - - -/** \brief Data Synchronization Barrier - - This function acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) -{ - __ASM volatile("dsb"); -} - - -/** \brief Data Memory Barrier - - This function ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) -{ - __ASM volatile("dmb"); -} - - -/** \brief Reverse byte order (32 bit) - - This function reverses the byte order in integer value. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) -{ - uint32_t result; - - __ASM volatile("rev %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - - -/** \brief Reverse byte order (16 bit) - - This function reverses the byte order in two unsigned short values. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) -{ - uint32_t result; - - __ASM volatile("rev16 %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - - -/** \brief Reverse byte order in signed short value - - This function reverses the byte order in a signed short value with sign extension to integer. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) -{ - uint32_t result; - - __ASM volatile("revsh %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - - -/** \brief Rotate Right in unsigned value (32 bit) - - This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) -{ - - __ASM volatile("ror %0, %0, %1" : "+r"(op1) : "r"(op2)); - return (op1); -} - - -#if (__CORTEX_M >= 0x03) - -/** \brief Reverse bit order of value - - This function reverses the bit order of the given value. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - - __ASM volatile("rbit %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - - -/** \brief LDR Exclusive (8 bit) - - This function performs a exclusive LDR command for 8 bit value. - - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) -{ - uint8_t result; - - __ASM volatile("ldrexb %0, [%1]" : "=r"(result) : "r"(addr)); - return (result); -} - - -/** \brief LDR Exclusive (16 bit) - - This function performs a exclusive LDR command for 16 bit values. - - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) -{ - uint16_t result; - - __ASM volatile("ldrexh %0, [%1]" : "=r"(result) : "r"(addr)); - return (result); -} - - -/** \brief LDR Exclusive (32 bit) - - This function performs a exclusive LDR command for 32 bit values. - - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile("ldrex %0, [%1]" : "=r"(result) : "r"(addr)); - return (result); -} - - -/** \brief STR Exclusive (8 bit) - - This function performs a exclusive STR command for 8 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) -{ - uint32_t result; - - __ASM volatile("strexb %0, %2, [%1]" : "=&r"(result) : "r"(addr), "r"(value)); - return (result); -} - - -/** \brief STR Exclusive (16 bit) - - This function performs a exclusive STR command for 16 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) -{ - uint32_t result; - - __ASM volatile("strexh %0, %2, [%1]" : "=&r"(result) : "r"(addr), "r"(value)); - return (result); -} - - -/** \brief STR Exclusive (32 bit) - - This function performs a exclusive STR command for 32 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile("strex %0, %2, [%1]" : "=&r"(result) : "r"(addr), "r"(value)); - return (result); -} - - -/** \brief Remove the exclusive lock - - This function removes the exclusive lock which is created by LDREX. - - */ -__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) -{ - __ASM volatile("clrex"); -} - - -/** \brief Signed Saturate - - This function saturates a signed value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** \brief Unsigned Saturate - - This function saturates an unsigned value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** \brief Count leading zeros - - This function counts the number of leading zeros of a data value. - - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -__attribute__((always_inline)) __STATIC_INLINE uint8_t __CLZ(uint32_t value) -{ - uint8_t result; - - __ASM volatile("clz %0, %1" : "=r"(result) : "r"(value)); - return (result); -} - -#endif /* (__CORTEX_M >= 0x03) */ - - - - -#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -#endif - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - -#endif /* __CORE_CMINSTR_H */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_adc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_adc.h deleted file mode 100644 index b51e596522..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_adc.h +++ /dev/null @@ -1,278 +0,0 @@ -/** - ****************************************************************************** - * @brief ADC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_ADC_H -#define __GD32F10X_ADC_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { FALSE = 0, TRUE } BOOL; -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup ADC - * @{ - */ - -/** @defgroup ADC_Exported_Types - * @{ - */ - -/** - * @brief ADC Init structure definition - */ - -typedef struct { - uint32_t ADC_Trig_External; /*!< AD conversion of regular channels trigger. */ - uint8_t ADC_Channel_Number; /*!< The number of converted ADC channels . - This parameter must range from 1 to 16. */ - uint32_t ADC_Data_Align; /*!< ADC data alignment,left or right. */ - - TypeState ADC_Mode_Scan; /*!< AD conversion mode,multichannels mode or Single channel mode. - This parameter can be ENABLE or DISABLE */ - uint32_t ADC_Mode; /*!< AD operation mode,independent mode or dual mode. - This parameter can be a value of @ref ADC_mode */ - TypeState ADC_Mode_Continuous; /*!< AD perform mode,continuous mode or single mode. - This parameter can be ENABLE or DISABLE. */ -} ADC_InitPara; - -/** - * @} - */ -/** @defgroup ADC_Exported_Constants - * @{ - */ - -/** @defgroup ADC_external_trigger - * @{ - */ -#define ADC_EXTERNAL_TRIGGER_MODE_T1_CC1 ((uint32_t)0x00000000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T1_CC2 ((uint32_t)0x00020000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T2_CC2 ((uint32_t)0x00060000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T3_TRGO ((uint32_t)0x00080000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T4_CC4 ((uint32_t)0x000A0000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIGGER_MODE_EXT_IT11_T8_TRGO ((uint32_t)0x000C0000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T1_CC3 ((uint32_t)0x00040000) /*!< Used in ADC1,ADC2 and ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_NONE ((uint32_t)0x000E0000) /*!< Used in ADC1,ADC2 and ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T3_CC1 ((uint32_t)0x00000000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T2_CC3 ((uint32_t)0x00020000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T8_CC1 ((uint32_t)0x00060000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T8_TRGO ((uint32_t)0x00080000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T5_CC1 ((uint32_t)0x000A0000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIGGER_MODE_T5_CC3 ((uint32_t)0x000C0000) /*!< Only used in ADC3 */ - -/** - * @} - */ - -/** @defgroup ADC_channels - * @{ - */ -#define ADC_CHANNEL_0 ((uint8_t)0x00) -#define ADC_CHANNEL_1 ((uint8_t)0x01) -#define ADC_CHANNEL_2 ((uint8_t)0x02) -#define ADC_CHANNEL_3 ((uint8_t)0x03) -#define ADC_CHANNEL_4 ((uint8_t)0x04) -#define ADC_CHANNEL_5 ((uint8_t)0x05) -#define ADC_CHANNEL_6 ((uint8_t)0x06) -#define ADC_CHANNEL_7 ((uint8_t)0x07) -#define ADC_CHANNEL_8 ((uint8_t)0x08) -#define ADC_CHANNEL_9 ((uint8_t)0x09) -#define ADC_CHANNEL_10 ((uint8_t)0x0A) -#define ADC_CHANNEL_11 ((uint8_t)0x0B) -#define ADC_CHANNEL_12 ((uint8_t)0x0C) -#define ADC_CHANNEL_13 ((uint8_t)0x0D) -#define ADC_CHANNEL_14 ((uint8_t)0x0E) -#define ADC_CHANNEL_15 ((uint8_t)0x0F) -#define ADC_CHANNEL_16 ((uint8_t)0x10) -#define ADC_CHANNEL_17 ((uint8_t)0x11) -#define ADC_CHANNEL_TEMPSENSOR ((uint8_t)ADC_CHANNEL_16) -#define ADC_CHANNEL_VREFINT ((uint8_t)ADC_CHANNEL_17) - -/** - * @} - */ - -/** @defgroup ADC_data_align - * @{ - */ -#define ADC_DATAALIGN_RIGHT ((uint32_t)0x00000000) -#define ADC_DATAALIGN_LEFT ((uint32_t)0x00000800) - -/** - * @} - */ - -/** @defgroup ADC_mode - * @{ - */ -#define ADC_MODE_INDEPENDENT ((uint32_t)0x00000000) -#define ADC_MODE_REGINSERTSIMULT ((uint32_t)0x00010000) -#define ADC_MODE_REGSIMULT_ALTERTRIG ((uint32_t)0x00020000) -#define ADC_MODE_INSERTSIMULT_FASTINTERL ((uint32_t)0x00030000) -#define ADC_MODE_INSERTSIMULT_SLOWINTERL ((uint32_t)0x00040000) -#define ADC_MODE_INSERTSIMULT ((uint32_t)0x00050000) -#define ADC_MODE_REGSIMULT ((uint32_t)0x00060000) -#define ADC_MODE_FASTINTERL ((uint32_t)0x00070000) -#define ADC_MODE_SLOWINTERL ((uint32_t)0x00080000) -#define ADC_MODE_ALTERTRIG ((uint32_t)0x00090000) - -/** - * @} - */ - -/** @defgroup ADC_sampling_time - * @{ - */ -#define ADC_SAMPLETIME_1POINT5 ((uint8_t)0x00) -#define ADC_SAMPLETIME_7POINT5 ((uint8_t)0x01) -#define ADC_SAMPLETIME_13POINT5 ((uint8_t)0x02) -#define ADC_SAMPLETIME_28POINT5 ((uint8_t)0x03) -#define ADC_SAMPLETIME_41POINT5 ((uint8_t)0x04) -#define ADC_SAMPLETIME_55POINT5 ((uint8_t)0x05) -#define ADC_SAMPLETIME_71POINT5 ((uint8_t)0x06) -#define ADC_SAMPLETIME_239POINT5 ((uint8_t)0x07) - -/** - * @} - */ - -/** @defgroup ADC_external_trigger_sources_for_inserted_channels_conversion - * @{ - */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T2_TRGO ((uint32_t)0x00002000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T2_CC1 ((uint32_t)0x00003000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T3_CC4 ((uint32_t)0x00004000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T4_TRGO ((uint32_t)0x00005000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_EXT_IT15_T8_CC4 ((uint32_t)0x00006000) /*!< Only used in ADC1 and ADC2 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T1_TRIG ((uint32_t)0x00000000) /*!< Used in ADC1,ADC2 and ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T1_CC4 ((uint32_t)0x00001000) /*!< Used in ADC1,ADC2 and ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_NONE ((uint32_t)0x00007000) /*!< Used in ADC1,ADC2 and ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T4_CC3 ((uint32_t)0x00002000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T8_CC2 ((uint32_t)0x00003000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T8_CC4 ((uint32_t)0x00004000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T5_TRGO ((uint32_t)0x00005000) /*!< Only used in ADC3 */ -#define ADC_EXTERNAL_TRIG_INSERTCONV_T5_CC4 ((uint32_t)0x00006000) /*!< Only used in ADC3 */ - -/** - * @} - */ - -/** @defgroup ADC_inserted_channel_selection - * @{ - */ -#define ADC_INSERTEDCHANNEL_1 ((uint8_t)0x14) -#define ADC_INSERTEDCHANNEL_2 ((uint8_t)0x18) -#define ADC_INSERTEDCHANNEL_3 ((uint8_t)0x1C) -#define ADC_INSERTEDCHANNEL_4 ((uint8_t)0x20) - -/** - * @} - */ - -/** @defgroup ADC_analog_watchdog_selection - * @{ - */ -#define ADC_ANALOGWATCHDOG_SINGLEREGENABLE ((uint32_t)0x00800200) -#define ADC_ANALOGWATCHDOG_SINGLEINSERTENABLE ((uint32_t)0x00400200) -#define ADC_ANALOGWATCHDOG_SINGLEREGORINSERTENABLE ((uint32_t)0x00C00200) -#define ADC_ANALOGWATCHDOG_ALLREGENABLE ((uint32_t)0x00800000) -#define ADC_ANALOGWATCHDOG_ALLINSERTENABLE ((uint32_t)0x00400000) -#define ADC_ANALOGWATCHDOG_ALLREGALLINSERTENABLE ((uint32_t)0x00C00000) -#define ADC_ANALOGWATCHDOG_NONE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ADC_interrupts_definition - * @{ - */ -#define ADC_INT_EOC ((uint16_t)0x0220) -#define ADC_INT_AWE ((uint16_t)0x0140) -#define ADC_INT_EOIC ((uint16_t)0x0480) - -/** - * @} - */ - -/** @defgroup ADC_flags_definition - * @{ - */ -#define ADC_FLAG_AWE ((uint8_t)0x01) -#define ADC_FLAG_EOC ((uint8_t)0x02) -#define ADC_FLAG_EOIC ((uint8_t)0x04) -#define ADC_FLAG_STIC ((uint8_t)0x08) -#define ADC_FLAG_STRC ((uint8_t)0x10) - -/** - * @} - */ - -/** - * @} - */ - - -/** @defgroup ADC_Exported_Functions - * @{ - */ -void ADC_DeInit(ADC_TypeDef *ADCx, ADC_InitPara *ADC_InitParaStruct); -void ADC_Init(ADC_TypeDef *ADCx, ADC_InitPara *ADC_InitParaStruct); -void ADC_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -void ADC_DMA_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -void ADC_INTConfig(ADC_TypeDef *ADCx, uint16_t ADC_INT, TypeState NewValue); -void ADC_Calibration(ADC_TypeDef *ADCx); -void ADC_SoftwareStartConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -TypeState ADC_GetSoftwareStartConvBitState(ADC_TypeDef *ADCx); -void ADC_DiscModeChannelCount_Config(ADC_TypeDef *ADCx, uint8_t Number); -void ADC_DiscMode_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -void ADC_RegularChannel_Config(ADC_TypeDef *ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); -void ADC_ExternalTrigConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -uint16_t ADC_GetConversionValue(ADC_TypeDef *ADCx); -uint32_t ADC_GetDualModeConversionValue(void); -void ADC_AutoInsertedConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -void ADC_InsertedDiscMode_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -void ADC_ExternalTrigInsertedConv_Config(ADC_TypeDef *ADCx, uint32_t ADC_ExternalTrigInsertConv); -void ADC_ExternalTrigInsertedConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -void ADC_SoftwareStartInsertedConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue); -TypeState ADC_GetSoftwareStartInsertedConvCmdBitState(ADC_TypeDef *ADCx); -void ADC_InsertedChannel_Config(ADC_TypeDef *ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); -void ADC_InsertedSequencerLength_Config(ADC_TypeDef *ADCx, uint8_t Length); -void ADC_SetInsertedOffset(ADC_TypeDef *ADCx, uint8_t ADC_InsertedChannel, uint16_t Offset); -uint16_t ADC_GetInsertedConversionValue(ADC_TypeDef *ADCx, uint8_t ADC_InsertedChannel); -void ADC_AnalogWatchdog_Enable(ADC_TypeDef *ADCx, uint32_t ADC_AnalogWatchdog); -void ADC_AnalogWatchdogThresholds_Config(ADC_TypeDef *ADCx, uint16_t HighThreshold, uint16_t LowThreshold); -void ADC_AnalogWatchdogSingleChannel_Config(ADC_TypeDef *ADCx, uint8_t ADC_Channel); -void ADC_TempSensorVrefint_Enable(TypeState NewValue); -TypeState ADC_GetBitState(ADC_TypeDef *ADCx, uint8_t ADC_FLAG); -void ADC_ClearBitState(ADC_TypeDef *ADCx, uint8_t ADC_FLAG); -TypeState ADC_GetIntState(ADC_TypeDef *ADCx, uint16_t ADC_INT); -void ADC_ClearIntBitState(ADC_TypeDef *ADCx, uint16_t ADC_INT); - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_ADC_H */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_bkp.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_bkp.h deleted file mode 100644 index 72784b9557..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_bkp.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - ****************************************************************************** - * @brief BKP header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_BKP_H -#define __GD32F10X_BKP_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup BKP - * @{ - */ - -/** @defgroup BKP_Exported_Constants - * @{ - */ - -/** @defgroup TAMPER_pin_active_level - * @{ - */ -#define BKP_TPAL_HIGH ((uint16_t)0x0000) -#define BKP_TPAL_LOW ((uint16_t)0x0002) - -/** - * @} - */ - -/** @defgroup RTC_output_on_the_TAMPER_pin - * @{ - */ -#define BKP_RTCOUTPUT_NULL ((uint16_t)0x0000) -#define BKP_RTCOUTPUT_CLKCAL ((uint16_t)0x0080) -#define BKP_RTCOUTPUT_ALARM ((uint16_t)0x0100) -#define BKP_RTCOUTPUT_SECOND ((uint16_t)0x0300) - -/** - * @} - */ - -/** @defgroup Backup_Data_Register - * @{ - */ -#define BKP_DR1 ((uint16_t)0x0004) -#define BKP_DR2 ((uint16_t)0x0008) -#define BKP_DR3 ((uint16_t)0x000C) -#define BKP_DR4 ((uint16_t)0x0010) -#define BKP_DR5 ((uint16_t)0x0014) -#define BKP_DR6 ((uint16_t)0x0018) -#define BKP_DR7 ((uint16_t)0x001C) -#define BKP_DR8 ((uint16_t)0x0020) -#define BKP_DR9 ((uint16_t)0x0024) -#define BKP_DR10 ((uint16_t)0x0028) -#define BKP_DR11 ((uint16_t)0x0040) -#define BKP_DR12 ((uint16_t)0x0044) -#define BKP_DR13 ((uint16_t)0x0048) -#define BKP_DR14 ((uint16_t)0x004C) -#define BKP_DR15 ((uint16_t)0x0050) -#define BKP_DR16 ((uint16_t)0x0054) -#define BKP_DR17 ((uint16_t)0x0058) -#define BKP_DR18 ((uint16_t)0x005C) -#define BKP_DR19 ((uint16_t)0x0060) -#define BKP_DR20 ((uint16_t)0x0064) -#define BKP_DR21 ((uint16_t)0x0068) -#define BKP_DR22 ((uint16_t)0x006C) -#define BKP_DR23 ((uint16_t)0x0070) -#define BKP_DR24 ((uint16_t)0x0074) -#define BKP_DR25 ((uint16_t)0x0078) -#define BKP_DR26 ((uint16_t)0x007C) -#define BKP_DR27 ((uint16_t)0x0080) -#define BKP_DR28 ((uint16_t)0x0084) -#define BKP_DR29 ((uint16_t)0x0088) -#define BKP_DR30 ((uint16_t)0x008C) -#define BKP_DR31 ((uint16_t)0x0090) -#define BKP_DR32 ((uint16_t)0x0094) -#define BKP_DR33 ((uint16_t)0x0098) -#define BKP_DR34 ((uint16_t)0x009C) -#define BKP_DR35 ((uint16_t)0x00A0) -#define BKP_DR36 ((uint16_t)0x00A4) -#define BKP_DR37 ((uint16_t)0x00A8) -#define BKP_DR38 ((uint16_t)0x00AC) -#define BKP_DR39 ((uint16_t)0x00B0) -#define BKP_DR40 ((uint16_t)0x00B4) -#define BKP_DR41 ((uint16_t)0x00B8) -#define BKP_DR42 ((uint16_t)0x00BC) - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup BKP_Exported_Functions - * @{ - */ -void BKP_DeInit(void); -void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data); -uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR); -void BKP_RTCOutputConfig(uint16_t BKP_RTCOUTPUT); -void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue); -void BKP_TamperPinConfig(uint16_t BKP_TPAL, TypeState NewValue); -void BKP_TamperINT_Enable(TypeState NewValue); -TypeState BKP_GetBitState(void); -void BKP_ClearBitState(void); -TypeState BKP_GetIntBitState(void); -void BKP_ClearIntBitState(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_BKP_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_can.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_can.h deleted file mode 100644 index a13a612566..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_can.h +++ /dev/null @@ -1,512 +0,0 @@ -/** - ****************************************************************************** - * @brief CAN header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_CAN_H -#define __GD32F10X_CAN_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup CAN - * @{ - */ - -/** @defgroup CAN_Exported_Types - * @{ - */ - -/** - * @brief CAN Initial Parameters - */ - -typedef struct { - uint16_t CAN_Prescaler; /*!< Baud rate prescaler.It can be 1 to 1024. */ - - uint8_t CAN_Mode; /*!< Set the CAN operating mode. */ - - uint8_t CAN_SJW; /*!< Set Resynchronization jump width */ - - uint8_t CAN_BS1; /*!< Set time segment 1. */ - - uint8_t CAN_BS2; /*!< Set time segment 2. */ - - TypeState CAN_TTC; /*!< Set time triggered communication mode. */ - - TypeState CAN_ABOR; /*!< Set automatic bus-off recovery. */ - - TypeState CAN_AWK; /*!< Set the automatic wake-up mode. */ - - TypeState CAN_ARD; /*!< Set the automatic retransmission mode. */ - - TypeState CAN_RFOD; /*!< Receive FIFO overwrite mode. */ - - TypeState CAN_TFO; /*!< Set the Transmit FIFO order. */ -} CAN_InitPara; - -/** - * @brief CAN filter Initial Parameters - */ - -typedef struct { - uint16_t CAN_FilterListHigh; /*!< the filter List number. - If the filter scale is 32-bit,the filter list number is MSBs. - If the filter scale is 16-bit,the filter list number is first one. - This value can take from 0x0000 to 0xFFFF */ - - uint16_t CAN_FilterListLow; /*!< the filter List number. - If the filter scale is 32-bit,the filter list number is LSBs. - If the filter scale is 16-bit,the filter list number is second one. - This value can take from 0x0000 to 0xFFFF */ - - uint16_t CAN_FilterMaskListHigh; /*!< the filter mask number or list number,according to the filter mode. - If the filter scale is 32-bit,the filter mask number or list number is MSBs. - If the filter scale is 16-bit,the filter mask number or list number is first one. - This value can take from 0x0000 to 0xFFFF */ - - uint16_t CAN_FilterMaskListLow; /*!< the filter mask number or list number,according to the filter mode. - If the filter scale is 32-bit,the filter mask number or list number is LSBs. - If the filter scale is 16-bit,the filter mask number or list number is second one. - This value can take from 0x0000 to 0xFFFF */ - - uint16_t CAN_FilterFIFOAssociation; /*!< Set the FIFO (0 or 1) which will be associated with the filter. */ - - uint8_t CAN_FilterNumber; /*!< Set the which filter to be initialized. It ranges from 0 to 13 or 0 to 27(in GD32F10X_CL). */ - - uint8_t CAN_FilterMode; /*!< Set the filter mode to be identifier mask or identifier list. */ - - uint8_t CAN_FilterScale; /*!< Set the filter scale. */ - - TypeState CAN_FilterWork; /*!< Set the filter to work or not. */ -} CAN_FilterInitPara; - -/** - * @brief CAN Tx message structure definition - */ - -typedef struct { - uint32_t StdId; /*!< Set the standard format frame identifier. - This value can take from 0 to 0x7FF. */ - - uint32_t ExtId; /*!< Set the extended format frame identifier. - This value can take from 0 to 0x1FFFFFFF. */ - - uint8_t FF; /*!< Set the format of Frame , Standard or extended Frame - for the message that will be transmitted. */ - - uint8_t FT; /*!< Set the type of frame, Data or remote - for the message that will be transmitted. */ - - uint8_t DLC; /*!< Set the length of the frame that will be transmitted. - This value can take from 0 to 8 */ - - uint8_t Data[8]; /*!< store the data that will be transmitted. - This value can take from 0 to 0xFF. */ -} CanTxMessage; - -/** - * @brief CAN Rx message structure definition - */ - -typedef struct { - uint32_t StdId; /*!< Set the standard format frame identifier. - This value can take from 0 to 0x7FF. */ - - uint32_t ExtId; /*!< Set the extended format frame identifier. - This value can take from 0 to 0x1FFFFFFF. */ - - uint8_t FF; /*!< Set the format of Frame , Standard or extended Frame - for the message that will be received. */ - - uint8_t FT; /*!< Set the type of frame, Data or remote - for the message that will be received. */ - - uint8_t DLC; /*!< Set the length of the frame that will be received. - This value can take from 0 to 8 */ - - uint8_t Data[8]; /*!< store the data that will be received. - This value can take from 0 to 0xFF. */ - - uint8_t FI; /*!< The index of the filter by which the frame is passed.. - This value can take from 0 to 0xFF */ -} CanRxMessage; - -/** - * @} - */ - -/** @defgroup CAN_Exported_Constants - * @{ - */ - -/** @defgroup CAN_sleep_constants - * @{ - */ -#define CAN_INITSTATE_FAILED ((uint8_t)0x00) /*!< CAN initialization failed */ -#define CAN_INITSTATE_SUCCESS ((uint8_t)0x01) /*!< CAN initialization OK */ - -/** - * @} - */ - -/** @defgroup CAN_Communication_Mode - * @{ - */ -#define CAN_MODE_NORMAL ((uint8_t)0x00) /*!< Normal communication mode */ -#define CAN_MODE_LOOPBACK ((uint8_t)0x01) /*!< Loopback communication mode */ -#define CAN_MODE_SILENT ((uint8_t)0x02) /*!< Silent communication mode */ -#define CAN_MODE_SILENT_LOOPBACK ((uint8_t)0x03) /*!< Loopback and silent communication mode */ - -/** - * @} - */ - - -/** - * @defgroup CAN_Working_Mode - * @{ - */ -#define CAN_WORKINGMODE_INITIAL ((uint8_t)0x00) /*!< Initial working mode */ -#define CAN_WORKINGMODE_NORMAL ((uint8_t)0x01) /*!< Normal working mode */ -#define CAN_WORKINGMODE_SLEEP ((uint8_t)0x02) /*!< Sleep working mode */ - -/** - * @} - */ - - -/** - * @defgroup CAN_Mode_State - * @{ - */ -#define CAN_MODESTATE_FAILED ((uint8_t)0x00) /*!< CAN entering the specified mode failed */ -#define CAN_MODESTATE_SUCCESS ((uint8_t)!CAN_MODESTATE_FAILED) /*!< CAN entering the specified mode Succeed */ - -/** - * @} - */ - -/** @defgroup CAN_Synchronisation_Jump_Width - * @{ - */ -#define CAN_SJW_1TQ ((uint8_t)0x00) /*!< 1 time quanta */ -#define CAN_SJW_2TQ ((uint8_t)0x01) /*!< 2 time quanta */ -#define CAN_SJW_3TQ ((uint8_t)0x02) /*!< 3 time quanta */ -#define CAN_SJW_4TQ ((uint8_t)0x03) /*!< 4 time quanta */ - -/** - * @} - */ - -/** @defgroup CAN_Time_Quanta_In_Bit_Segment_1 - * @{ - */ -#define CAN_BS1_1TQ ((uint8_t)0x00) /*!< 1 time quanta */ -#define CAN_BS1_2TQ ((uint8_t)0x01) /*!< 2 time quanta */ -#define CAN_BS1_3TQ ((uint8_t)0x02) /*!< 3 time quanta */ -#define CAN_BS1_4TQ ((uint8_t)0x03) /*!< 4 time quanta */ -#define CAN_BS1_5TQ ((uint8_t)0x04) /*!< 5 time quanta */ -#define CAN_BS1_6TQ ((uint8_t)0x05) /*!< 6 time quanta */ -#define CAN_BS1_7TQ ((uint8_t)0x06) /*!< 7 time quanta */ -#define CAN_BS1_8TQ ((uint8_t)0x07) /*!< 8 time quanta */ -#define CAN_BS1_9TQ ((uint8_t)0x08) /*!< 9 time quanta */ -#define CAN_BS1_10TQ ((uint8_t)0x09) /*!< 10 time quanta */ -#define CAN_BS1_11TQ ((uint8_t)0x0A) /*!< 11 time quanta */ -#define CAN_BS1_12TQ ((uint8_t)0x0B) /*!< 12 time quanta */ -#define CAN_BS1_13TQ ((uint8_t)0x0C) /*!< 13 time quanta */ -#define CAN_BS1_14TQ ((uint8_t)0x0D) /*!< 14 time quanta */ -#define CAN_BS1_15TQ ((uint8_t)0x0E) /*!< 15 time quanta */ -#define CAN_BS1_16TQ ((uint8_t)0x0F) /*!< 16 time quanta */ - -/** - * @} - */ - -/** @defgroup CAN_Time_Quanta_In_Bit_Segment_2 - * @{ - */ -#define CAN_BS2_1TQ ((uint8_t)0x00) /*!< 1 time quanta */ -#define CAN_BS2_2TQ ((uint8_t)0x01) /*!< 2 time quanta */ -#define CAN_BS2_3TQ ((uint8_t)0x02) /*!< 3 time quanta */ -#define CAN_BS2_4TQ ((uint8_t)0x03) /*!< 4 time quanta */ -#define CAN_BS2_5TQ ((uint8_t)0x04) /*!< 5 time quanta */ -#define CAN_BS2_6TQ ((uint8_t)0x05) /*!< 6 time quanta */ -#define CAN_BS2_7TQ ((uint8_t)0x06) /*!< 7 time quanta */ -#define CAN_BS2_8TQ ((uint8_t)0x07) /*!< 8 time quanta */ - -/** - * @} - */ - - -/** @defgroup CAN_Filter_Mode - * @{ - */ -#define CAN_FILTERMODE_MASK ((uint8_t)0x00) /*!< mask mode */ -#define CAN_FILTERMODE_LIST ((uint8_t)0x01) /*!< List mode */ - -/** - * @} - */ - -/** @defgroup CAN_Filter_Scale - * @{ - */ -#define CAN_FILTERSCALE_16BIT ((uint8_t)0x00) /*!< Two 16-bit filters */ -#define CAN_FILTERSCALE_32BIT ((uint8_t)0x01) /*!< One 32-bit filter */ - -/** - * @} - */ - -/** @defgroup CAN_Filter_FIFO - * @{ - */ -#define CAN_FILTER_FIFO0 ((uint8_t)0x00) /*!< Filter associated with FIFO0 */ -#define CAN_FILTER_FIFO1 ((uint8_t)0x01) /*!< Filter associated with FIFO1 */ - -/** - * @} - */ - -/** @defgroup CAN_Format_Frame - * @{ - */ -#define CAN_FF_STANDARD ((uint32_t)0x00000000) /*!< Standard format frame */ -#define CAN_FF_EXTENDED ((uint32_t)0x00000004) /*!< Extended format frame */ - -/** - * @} - */ - -/** @defgroup CAN_Frame_Type - * @{ - */ -#define CAN_FT_DATA ((uint32_t)0x00000000) /*!< Data frame */ -#define CAN_FT_REMOTE ((uint32_t)0x00000002) /*!< Remote frame */ - -/** - * @} - */ - -/** @defgroup CAN_Transmit_State - * @{ - */ -#define CAN_TXSTATE_FAILED ((uint8_t)0x00)/*!< CAN transmitted failure */ -#define CAN_TXSTATE_OK ((uint8_t)0x01) /*!< CAN transmitted success */ -#define CAN_TXSTATE_PENDING ((uint8_t)0x02) /*!< CAN transmitted pending */ -#define CAN_TXSTATE_NOMAILBOX ((uint8_t)0x04) /*!< No empty mailbox to be used for CAN */ - -/** - * @} - */ - -/** @defgroup CAN_Receive_FIFO_Number_Constants - * @{ - */ -#define CAN_FIFO0 ((uint8_t)0x00) /*!< Use CAN FIFO 0 to receive */ -#define CAN_FIFO1 ((uint8_t)0x01) /*!< Use CAN FIFO 1 to receive */ - -/** - * @} - */ - -/** @defgroup CAN_Sleep_Constants - * @{ - */ -#define CAN_SLEEP_FAILED ((uint8_t)0x00) /*!< CAN entered the sleep mode failed */ -#define CAN_SLEEP_OK ((uint8_t)0x01) /*!< CAN entered the sleep mode succeeded */ - -/** - * @} - */ - -/** @defgroup CAN_Wake_Wp_Constants - * @{ - */ -#define CAN_WAKEUP_FAILED ((uint8_t)0x00) /*!< CAN leaved the sleep mode failed */ -#define CAN_WAKEUP_OK ((uint8_t)0x01) /*!< CAN leaved the sleep mode succeeded */ - -/** - * @} - */ - -/** - * @defgroup CAN_Error_Type_Constants - * @{ - */ -#define CAN_ERRORTYPE_NOERR ((uint8_t)0x00) /*!< No Error */ -#define CAN_ERRORTYPE_STUFFERR ((uint8_t)0x10) /*!< Stuff Error */ -#define CAN_ERRORTYPE_FORMERR ((uint8_t)0x20) /*!< Form Error */ -#define CAN_ERRORTYPE_ACKERR ((uint8_t)0x30) /*!< Acknowledgment Error */ -#define CAN_ERRORTYPE_BITRECESSIVEERR ((uint8_t)0x40) /*!< Bit Recessive Error */ -#define CAN_ERRORTYPE_BITDOMINANTERR ((uint8_t)0x50) /*!< Bit Dominant Error */ -#define CAN_ERRORTYPE_CRCERR ((uint8_t)0x60) /*!< CRC Error */ -#define CAN_ERRORTYPE_SOFTWARESETERR ((uint8_t)0x70) /*!< Set by software */ - -/** - * @} - */ - -/** @defgroup CAN_flags - * @{ - */ -/* The flag value of 0x3XXXXXXX is used with CAN_GetBitState()and CAN_ClearBitState() functions. */ -/* The flag value of 0x1XXXXXXX is only used with CAN_GetBitState() function. */ - -/* Transmit Flags */ -#define CAN_FLAG_MTF0 ((uint32_t)0x38000001) /*!< Mailbox 0 transmit finished Flag */ -#define CAN_FLAG_MTF1 ((uint32_t)0x38000100) /*!< Mailbox 1 transmit finished Flag */ -#define CAN_FLAG_MTF2 ((uint32_t)0x38010000) /*!< Mailbox 2 transmit finished Flag */ - -/* Receive Flags */ -#define CAN_FLAG_RFL0 ((uint32_t)0x12000003) /*!< the length of the receive FIFO0 Flag */ -#define CAN_FLAG_RFF0 ((uint32_t)0x32000008) /*!< Receive FIFO 0 full Flag */ -#define CAN_FLAG_RFO0 ((uint32_t)0x32000010) /*!< Receive FIFO 0 overfull Flag */ -#define CAN_FLAG_RFL1 ((uint32_t)0x14000003) /*!< the length of the receive FIFO1 Flag */ -#define CAN_FLAG_RFF1 ((uint32_t)0x34000008) /*!< Receive FIFO 1 full Flag */ -#define CAN_FLAG_RFO1 ((uint32_t)0x34000010) /*!< Receive FIFO 1 overfull Flag */ - -/* Working Mode Flags, in CAN status register */ -#define CAN_FLAG_WU ((uint32_t)0x31000008) /*!< Wake up Flag */ -#define CAN_FLAG_SLP ((uint32_t)0x31000012) /*!< Sleep working state Flag */ - -/* Error Flags, in CAN error register */ -#define CAN_FLAG_WE ((uint32_t)0x10F00001) /*!< Warning error Flag */ -#define CAN_FLAG_PE ((uint32_t)0x10F00002) /*!< Passive error Flag */ -#define CAN_FLAG_BOE ((uint32_t)0x10F00004) /*!< Bus-off error Flag */ -#define CAN_FLAG_ET ((uint32_t)0x30F00070) /*!< Error type Flag */ - -/** - * @} - */ - - -/** @defgroup CAN_interrupts - * @{ - */ -#define CAN_INT_TME ((uint32_t)0x00000001) /*!< Transmit mailbox empty Interrupt*/ - -/* Receive Interrupts */ -#define CAN_INT_RFNE0 ((uint32_t)0x00000002) /*!< FIFO 0 not empty interrupt */ -#define CAN_INT_RFF0 ((uint32_t)0x00000004) /*!< FIFO 0 full Interrupt*/ -#define CAN_INT_RFO0 ((uint32_t)0x00000008) /*!< FIFO 0 overrun Interrupt*/ -#define CAN_INT_RFNE1 ((uint32_t)0x00000010) /*!< FIFO 1 not empty interrupt*/ -#define CAN_INT_RFF1 ((uint32_t)0x00000020) /*!< FIFO 1 full Interrupt*/ -#define CAN_INT_RFO1 ((uint32_t)0x00000040) /*!< FIFO 1 overfull Interrupt*/ - -/* Working Mode Interrupts */ -#define CAN_INT_WU ((uint32_t)0x00010000) /*!< Wake-up Interrupt*/ -#define CAN_INT_SLP ((uint32_t)0x00020000) /*!< Sleep Interrupt*/ - -/* Error Interrupts */ -#define CAN_INT_WE ((uint32_t)0x00000100) /*!< Warning error Interrupt*/ -#define CAN_INT_PE ((uint32_t)0x00000200) /*!< Passive error Interrupt*/ -#define CAN_INT_BOE ((uint32_t)0x00000400) /*!< Bus-off error Interrupt*/ -#define CAN_INT_ET ((uint32_t)0x00000800) /*!< error type Interrupt*/ -#define CAN_INT_ERR ((uint32_t)0x00008000) /*!< Error Interrupt*/ - -#define CAN_INT_MTF0 CAN_INT_TME -#define CAN_INT_MTF1 CAN_INT_TME -#define CAN_INT_MTF2 CAN_INT_TME - -/** - * @} - */ - -/** @defgroup CAN_Legacy - * @{ - */ -#define CANINITFAILED CAN_INITSTATE_FAILED -#define CANINITOK CAN_INITSTATE_SUCCESS -#define CAN_FILTERFIFO0 CAN_FILTER_FIFO0 -#define CAN_FILTERFIFO1 CAN_FILTER_FIFO1 -#define CAN_FF_STD CAN_FF_STANDARD -#define CAN_FF_EXT CAN_FF_EXTENDED -//#define CAN_FT_DATA CAN_FT_DATA -//#define CAN_FT_REMOTE CAN_FT_REMOTE -#define CANTXFAILE CAN_TXSTATE_FAILED -#define CANTXOK CAN_TXSTATE_OK -#define CANTXPENDING CAN_TXSTATE_PENDING -#define CAN_NO_MB CAN_TXSTATE_NOMAILBOX -#define CANSLEEPFAILED CAN_SLEEP_FAILED -#define CANSLEEPOK CAN_SLEEP_OK -#define CANWAKEUPFAILED CAN_WAKEUP_FAILED -#define CANWAKEUPOK CAN_WAKEUP_OK - -/** - * @} - */ - -/** - * @} - */ - - -/** @defgroup CAN_Exported_Functions - * @{ - */ -void CAN_DeInit(CAN_TypeDef *CANx); -uint8_t CAN_Init(CAN_TypeDef *CANx, CAN_InitPara *CAN_InitParaStruct); -void CAN_FilterInit(CAN_FilterInitPara *CAN_FilterInitParaStruct); -void CAN_StructInit(CAN_InitPara *CAN_InitParaStruct); -void CAN_HeaderBank(uint8_t CAN_HeaderBankNumber); -void CAN_DebugFreeze(CAN_TypeDef *CANx, TypeState NewValue); -void CAN_TimeTrigComMode_Enable(CAN_TypeDef *CANx, TypeState NewValue); - -/* Transmit functions */ -uint8_t CAN_Transmit(CAN_TypeDef *CANx, CanTxMessage *TxMessage); -uint8_t CAN_TransmitState(CAN_TypeDef *CANx, uint8_t TransmitMailbox); -void CAN_StopTransmit(CAN_TypeDef *CANx, uint8_t Mailbox); - -/* Receive functions */ -void CAN_Receive(CAN_TypeDef *CANx, uint8_t FIFONumber, CanRxMessage *RxMessage); -void CAN_FIFODequeue(CAN_TypeDef *CANx, uint8_t FIFONumber); -uint8_t CAN_MessageLength(CAN_TypeDef *CANx, uint8_t FIFONumber); - - -/* Working modes functions */ -uint8_t CAN_WorkingMode(CAN_TypeDef *CANx, uint8_t CAN_WorkingMode); -uint8_t CAN_EnterSleep(CAN_TypeDef *CANx); -uint8_t CAN_WakeUp(CAN_TypeDef *CANx); - -/* Error management functions */ -uint8_t CAN_GetErrorType(CAN_TypeDef *CANx); -uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef *CANx); -uint8_t CAN_GetTransmitErrorCounter(CAN_TypeDef *CANx); - -/* Interrupts and flags management functions */ -void CAN_INTConfig(CAN_TypeDef *CANx, uint32_t CAN_INT, TypeState NewValue); -TypeState CAN_GetBitState(CAN_TypeDef *CANx, uint32_t CAN_FLAG); -void CAN_ClearBitState(CAN_TypeDef *CANx, uint32_t CAN_FLAG); -TypeState CAN_GetIntBitState(CAN_TypeDef *CANx, uint32_t CAN_INT); -void CAN_ClearIntBitState(CAN_TypeDef *CANx, uint32_t CAN_INT); -static TypeState CheckINTState(uint32_t CAN_Reg, uint32_t Int_Bit); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10x_CAN_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_crc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_crc.h deleted file mode 100644 index b4cd5d7e3b..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_crc.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - ****************************************************************************** - * @brief CRC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_CRC_H -#define __GD32F10X_CRC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup CRC - * @{ - */ - -/** @defgroup CRC_Exported_Functions - * @{ - */ - -void CRC_ResetDTR(void); -uint32_t CRC_CalcSingleData(uint32_t CRC_data); -uint32_t CRC_CalcDataFlow(uint32_t pbuffer[], uint32_t buffer_length); -uint32_t CRC_ReadDTR(void); -void CRC_WriteFDTR(uint8_t CRC_fdtr); -uint8_t CRC_ReadFDTR(void); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_CRC_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dac.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dac.h deleted file mode 100644 index 95eccc7b00..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dac.h +++ /dev/null @@ -1,208 +0,0 @@ -/** - ****************************************************************************** - * @brief DAC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_DAC_H -#define __GD32F10X_DAC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup DAC - * @{ - */ - -/** @defgroup DAC_Exported_Types - * @{ - */ - -/** - * @brief DAC Init structure definition - */ -typedef struct { - uint32_t DAC_Trigger; /*!< External trigger of the selected DAC channel. - This parameter can be a value of @ref DAC_Trigger */ - uint32_t DAC_WaveType; /*!< Wave type of the DAC channel, noise waves or triangle waves. - This parameter can be a value of @ref DAC_wave_type */ - uint32_t DAC_LFSRNoise_AmplitudeTriangle; /*!< The LFSR mask for noise wave generation or - the maximum amplitude triangle generation for the DAC channel. - This parameter can be a value of @ref DAC_lfsrnoise_amplitudetriangle */ - uint32_t DAC_OutputBuffer; /*!< whether the DAC channel output buffer is enabled or disabled. - This parameter can be a value of @ref DAC_OutputBuffer */ -} DAC_InitPara; - -/** - * @} - */ - -/** @defgroup DAC_Exported_Constants - * @{ - */ - -/** @defgroup DAC_Trigger - * @{ - */ -#define DAC_TRIGGER_NONE ((uint32_t)0x00000000) /*!< no trigger */ -#define DAC_TRIGGER_T2_TRIG ((uint32_t)0x00000024) /*!< TIMER2 TRIG */ -#define DAC_TRIGGER_T3_TRIG ((uint32_t)0x0000000C) /*!< TIMER3 TRIG */ -#define DAC_TRIGGER_T4_TRIG ((uint32_t)0x0000002C) /*!< TIMER4 TRIG */ -#define DAC_TRIGGER_T5_TRIG ((uint32_t)0x0000001C) /*!< TIMER5 TRIG */ -#define DAC_TRIGGER_T6_TRIG ((uint32_t)0x00000004) /*!< TIMER6 TRIG */ -#define DAC_TRIGGER_T7_TRIG ((uint32_t)0x00000014) /*!< TIMER7 TRIG */ -#define DAC_TRIGGER_T8_TRIG ((uint32_t)0x0000000C) /*!< TIMER8 TRIG */ -#define DAC_TRIGGER_T15_TRIG ((uint32_t)0x0000001C) /*!< TIMER15 TRIG */ -#define DAC_TRIGGER_EXTI_LINE9 ((uint32_t)0x00000034) /*!< EXTI Line9 event */ -#define DAC_TRIGGER_SOFTWARE ((uint32_t)0x0000003C) /*!< software trigger */ - -/** - * @} - */ - -/** @defgroup DAC_wave_type - * @{ - */ -#define DAC_WAVEGENE_NONE ((uint32_t)0x00000000) -#define DAC_WAVEGENE_NOISE ((uint32_t)0x00000040) -#define DAC_WAVEGENE_TRIANGLE ((uint32_t)0x00000080) - -/** - * @} - */ - -/** @defgroup DAC_lfsrnoise_amplitudetriangle - * @{ - */ -#define DAC_LFSR_BIT0 ((uint32_t)0x00000000) /*!< LFSR bit0 for noise wave generation */ -#define DAC_LFSR_BITS1_0 ((uint32_t)0x00000100) /*!< LFSR bit[1:0] for noise wave generation */ -#define DAC_LFSR_BITS2_0 ((uint32_t)0x00000200) /*!< LFSR bit[2:0] for noise wave generation */ -#define DAC_LFSR_BITS3_0 ((uint32_t)0x00000300) /*!< LFSR bit[3:0] for noise wave generation */ -#define DAC_LFSR_BITS4_0 ((uint32_t)0x00000400) /*!< LFSR bit[4:0] for noise wave generation */ -#define DAC_LFSR_BITS5_0 ((uint32_t)0x00000500) /*!< LFSR bit[5:0] for noise wave generation */ -#define DAC_LFSR_BITS6_0 ((uint32_t)0x00000600) /*!< LFSR bit[6:0] for noise wave generation */ -#define DAC_LFSR_BITS7_0 ((uint32_t)0x00000700) /*!< LFSR bit[7:0] for noise wave generation */ -#define DAC_LFSR_BITS8_0 ((uint32_t)0x00000800) /*!< LFSR bit[8:0] for noise wave generation */ -#define DAC_LFSR_BITS9_0 ((uint32_t)0x00000900) /*!< LFSR bit[9:0] for noise wave generation */ -#define DAC_LFSR_BITS10_0 ((uint32_t)0x00000A00) /*!< LFSR bit[10:0] for noise wave generation */ -#define DAC_LFSR_BITS11_0 ((uint32_t)0x00000B00) /*!< LFSR bit[11:0] for noise wave generation */ -#define DAC_AMPLITUDETRIANGLE_1 ((uint32_t)0x00000000) /*!< max triangle amplitude: 1 */ -#define DAC_AMPLITUDETRIANGLE_3 ((uint32_t)0x00000100) /*!< max triangle amplitude: 3 */ -#define DAC_AMPLITUDETRIANGLE_7 ((uint32_t)0x00000200) /*!< max triangle amplitude: 7 */ -#define DAC_AMPLITUDETRIANGLE_15 ((uint32_t)0x00000300) /*!< max triangle amplitude: 15 */ -#define DAC_AMPLITUDETRIANGLE_31 ((uint32_t)0x00000400) /*!< max triangle amplitude: 31 */ -#define DAC_AMPLITUDETRIANGLE_63 ((uint32_t)0x00000500) /*!< max triangle amplitude: 63 */ -#define DAC_AMPLITUDETRIANGLE_127 ((uint32_t)0x00000600) /*!< max triangle amplitude: 127 */ -#define DAC_AMPLITUDETRIANGLE_255 ((uint32_t)0x00000700) /*!< max triangle amplitude: 255 */ -#define DAC_AMPLITUDETRIANGLE_511 ((uint32_t)0x00000800) /*!< max triangle amplitude: 511 */ -#define DAC_AMPLITUDETRIANGLE_1023 ((uint32_t)0x00000900) /*!< max triangle amplitude: 1023 */ -#define DAC_AMPLITUDETRIANGLE_2047 ((uint32_t)0x00000A00) /*!< max triangle amplitude: 2047 */ -#define DAC_AMPLITUDETRIANGLE_4095 ((uint32_t)0x00000B00) /*!< max triangle amplitude: 4095 */ - -/** - * @} - */ -/** @defgroup DAC_OutputBuffer - * @{ - */ -#define DAC_OUTPUTBUFFER_ENABLE ((uint32_t)0x00000000) -#define DAC_OUTPUTBUFFER_DISABLE ((uint32_t)0x00000002) - -/** - * @} - */ - -/** @defgroup DAC_Channel_selection - * @{ - */ -#define DAC_CHANNEL_1 ((uint32_t)0x00000000) -#define DAC_CHANNEL_2 ((uint32_t)0x00000010) - -/** - * @} - */ - -/** @defgroup DAC_data_alignment - * @{ - */ -#define DAC_ALIGN_12B_R ((uint32_t)0x00000000) -#define DAC_ALIGN_12B_L ((uint32_t)0x00000004) -#define DAC_ALIGN_8B_R ((uint32_t)0x00000008) - -/** - * @} - */ - -/** @defgroup DAC_wave_generation - * @{ - */ -#define DAC_WAVE_NOISE ((uint32_t)0x00000040) -#define DAC_WAVE_TRIANGLE ((uint32_t)0x00000080) - -/** - * @} - */ - -/** @defgroup DAC_interrupts_definition - * @{ - */ -#define DAC_INT_DMAUDR ((uint32_t)0x00002000) - -/** - * @} - */ - -/** @defgroup DAC_flags_definition - * @{ - */ -#define DAC_FLAG_DMAUDR ((uint32_t)0x00002000) - -/** - * @} - */ - -/** - * @} - */ - - -/** @defgroup DAC_Exported_Functions - * @{ - */ -void DAC_DeInit(DAC_InitPara *DAC_InitParaStruct); -void DAC_Init(uint32_t DAC_Channel, DAC_InitPara *DAC_InitParaStruct); -void DAC_Enable(uint32_t DAC_Channel, TypeState NewValue); -void DAC_IntConfig(uint32_t DAC_Channel, TypeState NewValue); -void DAC_SoftwareTrigger_Enable(uint32_t DAC_Channel, TypeState NewValue); -void DAC_DualSoftwareTrigger_Enable(TypeState NewValue); -void DAC_WaveGeneration_Enable(uint32_t DAC_Channel, uint32_t DAC_Wave, TypeState NewValue); -void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data); -void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data); -void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1); -uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel); -void DAC_DMA_Enable(uint32_t DAC_Channel, TypeState NewValue); -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_DAC_H */ - -/** - * @} - */ - -/** - * @} - */ -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dma.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dma.h deleted file mode 100644 index 82eeba851c..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_dma.h +++ /dev/null @@ -1,321 +0,0 @@ -/** - ****************************************************************************** - * @brief DMA header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_DMA_H -#define __GD32F10X_DMA_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup DMA - * @{ - */ - -/** @defgroup DMA_Exported_Types - * @{ - */ - -/** - * @brief DMA Initial Parameters - */ - -typedef struct { - uint32_t DMA_PeripheralBaseAddr; /*!< The base address of the peripheral. */ - - uint32_t DMA_MemoryBaseAddr; /*!< The base address of the memory. */ - - uint32_t DMA_DIR; /*!< The direction of data transmission. - detailed in @ref DMA_data_transfer_direction */ - - uint32_t DMA_BufferSize; /*!< The buffer size of data transmission. */ - - uint32_t DMA_PeripheralInc; /*!< The incremented_mode of the Peripheral address register. - detailed in @ref DMA_peripheral_Address_incremented_mode */ - - uint32_t DMA_MemoryInc; /*!< The incremented_mode of the memory address register. - detailed in @ref DMA_memory_Address_incremented_mode */ - - uint32_t DMA_PeripheralDataSize; /*!< The data transmission width of Peripheral. - detailed in @ref DMA_peripheral_data_size */ - - uint32_t DMA_MemoryDataSize; /*!< The data transmission width of Memory. - detailed in @ref DMA_memory_data_size */ - - uint32_t DMA_Mode; /*!< The mode of circular transmission. - detailed in @ref DMA_circular_normal_mode */ - - uint32_t DMA_Priority; /*!< The software priority for the DMAy Channelx. - detailed in @ref DMA_priority_level */ - uint32_t DMA_MTOM; /*!< The mode of memory-to-memory transfer. - detailed in @ref DMA_memory_to_memory */ -} DMA_InitPara; - -/** - * @} - */ - -/** @defgroup DMA_Exported_Constants - * @{ - */ - -/** @defgroup DMA_data_transfer_direction - * @{ - */ - -#define DMA_DIR_PERIPHERALDST DMA_CTLR_DIR -#define DMA_DIR_PERIPHERALSRC ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup DMA_peripheral_Address_Increasing_mode - * @{ - */ - -#define DMA_PERIPHERALINC_ENABLE DMA_CTLR_PNAGA -#define DMA_PERIPHERALINC_DISABLE ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup DMA_memory_Address_Increasing_mode - * @{ - */ - -#define DMA_MEMORYINC_ENABLE DMA_CTLR_MNAGA -#define DMA_MEMORYINC_DISABLE ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup DMA_peripheral_data_size - * @{ - */ - -#define DMA_PERIPHERALDATASIZE_BYTE ((uint32_t)0x00000000) -#define DMA_PERIPHERALDATASIZE_HALFWORD DMA_CTLR_PSIZE_0 -#define DMA_PERIPHERALDATASIZE_WORD DMA_CTLR_PSIZE_1 -/** - * @} - */ - -/** @defgroup DMA_memory_data_size - * @{ - */ - -#define DMA_MEMORYDATASIZE_BYTE ((uint32_t)0x00000000) -#define DMA_MEMORYDATASIZE_HALFWORD DMA_CTLR_MSIZE_0 -#define DMA_MEMORYDATASIZE_WORD DMA_CTLR_MSIZE_1 -/** - * @} - */ - -/** @defgroup DMA_circular_normal_mode - * @{ - */ - -#define DMA_MODE_CIRCULAR DMA_CTLR_CIRC -#define DMA_MODE_NORMAL ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup DMA_priority_level - * @{ - */ - -#define DMA_PRIORITY_VERYHIGH DMA_CTLR_PRIO -#define DMA_PRIORITY_HIGH DMA_CTLR_PRIO_1 -#define DMA_PRIORITY_MEDIUM DMA_CTLR_PRIO_0 -#define DMA_PRIORITY_LOW ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup DMA_memory_to_memory - * @{ - */ - -#define DMA_MEMTOMEM_ENABLE DMA_CTLR_MEMTOMEM -#define DMA_MEMTOMEM_DISABLE ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup DMA_interrupts_definition - * @{ - */ - -#define DMA_INT_TC DMA_CTLR_TCIE -#define DMA_INT_HT DMA_CTLR_HTIE -#define DMA_INT_ERR DMA_CTLR_ERRIE - -#define DMA1_INT_GL1 DMA_IFR_GIF1 -#define DMA1_INT_TC1 DMA_IFR_TCIF1 -#define DMA1_INT_HT1 DMA_IFR_HTIF1 -#define DMA1_INT_ERR1 DMA_IFR_ERRIF1 -#define DMA1_INT_GL2 DMA_IFR_GIF2 -#define DMA1_INT_TC2 DMA_IFR_TCIF2 -#define DMA1_INT_HT2 DMA_IFR_HTIF2 -#define DMA1_INT_ERR2 DMA_IFR_ERRIF2 -#define DMA1_INT_GL3 DMA_IFR_GIF3 -#define DMA1_INT_TC3 DMA_IFR_TCIF3 -#define DMA1_INT_HT3 DMA_IFR_HTIF3 -#define DMA1_INT_ERR3 DMA_IFR_ERRIF3 -#define DMA1_INT_GL4 DMA_IFR_GIF4 -#define DMA1_INT_TC4 DMA_IFR_TCIF4 -#define DMA1_INT_HT4 DMA_IFR_HTIF4 -#define DMA1_INT_ERR4 DMA_IFR_ERRIF4 -#define DMA1_INT_GL5 DMA_IFR_GIF5 -#define DMA1_INT_TC5 DMA_IFR_TCIF5 -#define DMA1_INT_HT5 DMA_IFR_HTIF5 -#define DMA1_INT_ERR5 DMA_IFR_ERRIF5 -#define DMA1_INT_GL6 DMA_IFR_GIF6 -#define DMA1_INT_TC6 DMA_IFR_TCIF6 -#define DMA1_INT_HT6 DMA_IFR_HTIF6 -#define DMA1_INT_ERR6 DMA_IFR_ERRIF6 -#define DMA1_INT_GL7 DMA_IFR_GIF7 -#define DMA1_INT_TC7 DMA_IFR_TCIF7 -#define DMA1_INT_HT7 DMA_IFR_HTIF7 -#define DMA1_INT_ERR7 DMA_IFR_ERRIF7 - -#define DMA2_INT_GL1 ((uint32_t)0x10000001) -#define DMA2_INT_TC1 ((uint32_t)0x10000002) -#define DMA2_INT_HT1 ((uint32_t)0x10000004) -#define DMA2_INT_TE1 ((uint32_t)0x10000008) -#define DMA2_INT_GL2 ((uint32_t)0x10000010) -#define DMA2_INT_TC2 ((uint32_t)0x10000020) -#define DMA2_INT_HT2 ((uint32_t)0x10000040) -#define DMA2_INT_TE2 ((uint32_t)0x10000080) -#define DMA2_INT_GL3 ((uint32_t)0x10000100) -#define DMA2_INT_TC3 ((uint32_t)0x10000200) -#define DMA2_INT_HT3 ((uint32_t)0x10000400) -#define DMA2_INT_TE3 ((uint32_t)0x10000800) -#define DMA2_INT_GL4 ((uint32_t)0x10001000) -#define DMA2_INT_TC4 ((uint32_t)0x10002000) -#define DMA2_INT_HT4 ((uint32_t)0x10004000) -#define DMA2_INT_TE4 ((uint32_t)0x10008000) -#define DMA2_INT_GL5 ((uint32_t)0x10010000) -#define DMA2_INT_TC5 ((uint32_t)0x10020000) -#define DMA2_INT_HT5 ((uint32_t)0x10040000) -#define DMA2_INT_TE5 ((uint32_t)0x10080000) - - -/** - * @} - */ - -/** @defgroup DMA_flags_definition - * @{ - */ -#define DMA1_FLAG_GL1 DMA_IFR_GIF1 -#define DMA1_FLAG_TC1 DMA_IFR_TCIF1 -#define DMA1_FLAG_HT1 DMA_IFR_HTIF1 -#define DMA1_FLAG_ERR1 DMA_IFR_ERRIF1 -#define DMA1_FLAG_GL2 DMA_IFR_GIF2 -#define DMA1_FLAG_TC2 DMA_IFR_TCIF2 -#define DMA1_FLAG_HT2 DMA_IFR_HTIF2 -#define DMA1_FLAG_ERR2 DMA_IFR_ERRIF2 -#define DMA1_FLAG_GL3 DMA_IFR_GIF3 -#define DMA1_FLAG_TC3 DMA_IFR_TCIF3 -#define DMA1_FLAG_HT3 DMA_IFR_HTIF3 -#define DMA1_FLAG_ERR3 DMA_IFR_ERRIF3 -#define DMA1_FLAG_GL4 DMA_IFR_GIF4 -#define DMA1_FLAG_TC4 DMA_IFR_TCIF4 -#define DMA1_FLAG_HT4 DMA_IFR_HTIF4 -#define DMA1_FLAG_ERR4 DMA_IFR_ERRIF4 -#define DMA1_FLAG_GL5 DMA_IFR_GIF5 -#define DMA1_FLAG_TC5 DMA_IFR_TCIF5 -#define DMA1_FLAG_HT5 DMA_IFR_HTIF5 -#define DMA1_FLAG_ERR5 DMA_IFR_ERRIF5 -#define DMA1_FLAG_GL6 DMA_IFR_GIF6 -#define DMA1_FLAG_TC6 DMA_IFR_TCIF6 -#define DMA1_FLAG_HT6 DMA_IFR_HTIF6 -#define DMA1_FLAG_ERR6 DMA_IFR_ERRIF6 -#define DMA1_FLAG_GL7 DMA_IFR_GIF7 -#define DMA1_FLAG_TC7 DMA_IFR_TCIF7 -#define DMA1_FLAG_HT7 DMA_IFR_HTIF7 -#define DMA1_FLAG_ERR7 DMA_IFR_ERRIF7 - -#define DMA2_FLAG_GL1 ((uint32_t)0x10000001) -#define DMA2_FLAG_TC1 ((uint32_t)0x10000002) -#define DMA2_FLAG_HT1 ((uint32_t)0x10000004) -#define DMA2_FLAG_TE1 ((uint32_t)0x10000008) -#define DMA2_FLAG_GL2 ((uint32_t)0x10000010) -#define DMA2_FLAG_TC2 ((uint32_t)0x10000020) -#define DMA2_FLAG_HT2 ((uint32_t)0x10000040) -#define DMA2_FLAG_TE2 ((uint32_t)0x10000080) -#define DMA2_FLAG_GL3 ((uint32_t)0x10000100) -#define DMA2_FLAG_TC3 ((uint32_t)0x10000200) -#define DMA2_FLAG_HT3 ((uint32_t)0x10000400) -#define DMA2_FLAG_TE3 ((uint32_t)0x10000800) -#define DMA2_FLAG_GL4 ((uint32_t)0x10001000) -#define DMA2_FLAG_TC4 ((uint32_t)0x10002000) -#define DMA2_FLAG_HT4 ((uint32_t)0x10004000) -#define DMA2_FLAG_TE4 ((uint32_t)0x10008000) -#define DMA2_FLAG_GL5 ((uint32_t)0x10010000) -#define DMA2_FLAG_TC5 ((uint32_t)0x10020000) -#define DMA2_FLAG_HT5 ((uint32_t)0x10040000) -#define DMA2_FLAG_TE5 ((uint32_t)0x10080000) - -/** - * @} - */ - -/** - * @} - */ - - - -/** @defgroup DMA_Exported_Functions - * @{ - */ - -/* Function used to reset the DMA configuration */ -void DMA_DeInit(DMA_Channel_TypeDef *DMAy_Channelx); - -/* The functions of Initialization and Configuration */ -void DMA_Init(DMA_Channel_TypeDef *DMAy_Channelx, DMA_InitPara *DMA_InitParaStruct); -void DMA_ParaInit(DMA_InitPara *DMA_InitParaStruct); -void DMA_Enable(DMA_Channel_TypeDef *DMAy_Channelx, TypeState NewValue); - -/* The functions of Data Counter */ -void DMA_SetCurrDataCounter(DMA_Channel_TypeDef *DMAy_Channelx, uint16_t DataNumber); -uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef *DMAy_Channelx); - -/* The functions of Interrupts and flags management */ -void DMA_INTConfig(DMA_Channel_TypeDef *DMAy_Channelx, uint32_t DMA_INT, TypeState NewValue); -TypeState DMA_GetBitState(uint32_t DMA_FLAG); -void DMA_ClearBitState(uint32_t DMA_FLAG); -TypeState DMA_GetIntBitState(uint32_t DMA_INT); -void DMA_ClearIntBitState(uint32_t DMA_INT); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10x_DMA_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_eth.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_eth.h deleted file mode 100644 index 6500a8a9ea..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_eth.h +++ /dev/null @@ -1,1407 +0,0 @@ -/** - ****************************************************************************** - * @brief ETH header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_ETH_H -#define __GD32F10X_ETH_H -#define IF_USE_EXTERNPHY_LIB 0 - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" -#if (1 == IF_USE_EXTERNPHY_LIB) -#include "phy.h" -#endif - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup ETH - * @{ - */ - -/** @defgroup ETH_Exported_Types - * @{ - */ - -/** - * @brief ETH MAC Initial Parameters - */ -typedef struct { - /** - * @brief / * MAC - */ - uint32_t ETH_MAC_AutoNegotiation; /*!< Enable or disable external PHY's AutoNegotiation function - detailed in @ref ETH_AutoNegotiation */ - - uint32_t ETH_MAC_Watchdog; /*!< Enable or disable the Watchdog timer - detailed in @ref ETH_watchdog */ - - uint32_t ETH_MAC_Jabber; /*!< Enable or disable Jabber timer - detailed in @ref ETH_Jabber */ - - uint32_t ETH_MAC_InterFrameGap; /*!< Set the gap of two frames when transmission - detailed in @ref ETH_Inter_Frame_Gap */ - - uint32_t ETH_MAC_CarrierSense; /*!< Enable or disable the Carrier Sense - detailed in @ref ETH_Carrier_Sense */ - - uint32_t ETH_MAC_Speed; /*!< Set the Ethernet speed, detailed in @ref ETH_Speed */ - - - uint32_t ETH_MAC_ReceiveOwn; /*!< Enable or disable the ReceiveOwn mode - detailed in @ref ETH_Receive_Own */ - - uint32_t ETH_MAC_LoopbackMode; /*!< Enable or disable the MAC Loopback mode - detailed in @ref ETH_Loop_Back_Mode */ - - uint32_t ETH_MAC_Mode; /*!< Set the MAC duplex mode, detailed in @ref ETH_Duplex_Mode */ - - uint32_t ETH_MAC_ChecksumOffload; /*!< Enable or disable the IPv4(TCP/UDP/ICMP headers) checksum checking when reception - detailed in @ref ETH_Checksum_Offload */ - - uint32_t ETH_MAC_RetryTransmission; /*!< Enable or disable the MAC attempt retries transmission in Half-Duplex mode when a colision occurs - detailed in @ref ETH_Retry_Transmission */ - - uint32_t ETH_MAC_AutomaticPadCRCDrop; /*!< Enable or disable the Automatic Pad/CRC Drop - detailed in @ref ETH_Automatic_Pad_CRC_Drop */ - - uint32_t ETH_MAC_BackOffLimit; /*!< Set the BackOff limit value, detailed in @ref ETH_Back_Off_Limit */ - - uint32_t ETH_MAC_DeferralCheck; /*!< Enable or disable the deferral check function only in Half-Duplex mode - detailed in @ref ETH_Deferral_Check */ - - uint32_t ETH_MAC_FilterDisable; /*!< Enable or disable the MAC filter, detailed in @ref ETH_Filter_Disable */ - - uint32_t ETH_MAC_SourceAddrFilter; /*!< Set the SA Filter mode, detailed in @ref ETH_Source_Addr_Filter */ - - uint32_t ETH_MAC_PassControlFrames; /*!< Set the mode of the control frames (including unicast and multicast PAUSE frames) - detailed in @ref ETH_Pass_Control_Frames */ - - uint32_t ETH_MAC_BroadcastFramesReception; /*!< Enable or disable the reception of Broadcast Frames - detailed in @ref ETH_Broadcast_Frames_Reception */ - - uint32_t ETH_MAC_DestinationAddrFilter; /*!< Set the DA filter mode, detailed in @ref ETH_Destination_Addr_Filter */ - - uint32_t ETH_MAC_PromiscuousMode; /*!< Enable or disable the Promiscuous Mode - detailed in @ref ETH_Promiscuous_Mode */ - - uint32_t ETH_MAC_MulticastFramesFilter; /*!< Set the Multicast Frames filter mode - detailed in @ref ETH_Multicast_Frames_Filter */ - - uint32_t ETH_MAC_UnicastFramesFilter; /*!< Set the Unicast Frames filter mode - detailed in @ref ETH_Unicast_Frames_Filter */ - - uint32_t ETH_MAC_HashListHigh; /*!< Hash list higher 32 bits */ - - uint32_t ETH_MAC_HashListLow; /*!< Hash list lower 32 bits */ - - uint32_t ETH_MAC_PauseTime; /*!< Set the Pause Time field value in the transmit control frame */ - - uint32_t ETH_MAC_ZeroQuantaPause; /*!< Enable or disable the automatic generation of Zero-Quanta Pause Control frames - detailed in @ref ETH_Zero_Quanta_Pause */ - - uint32_t ETH_MAC_PauseLowThreshold; /*!< Set the threshold of the PAUSE to be checked for - automatic retransmission of PAUSE Frame - detailed in @ref ETH_Pause_Low_Threshold */ - - uint32_t ETH_MAC_FlowControlDeactiveThreshold;/*!< Set the threshold of the deactive flow control - detailed in @ref ETH_RFD_Threshold */ - - uint32_t ETH_MAC_FlowControlActiveThreshold; /*!< Set the threshold of the active flow control - detailed in @ref ETH_RFA_Threshold */ - - uint32_t ETH_MAC_UnicastPauseFrameDetect; /*!< Enable or disable the unicast Pause frames detection - detailed in @ref ETH_Unicast_Pause_Frame_Detect */ - - uint32_t ETH_MAC_ReceiveFlowControl; /*!< Enable or disable the MAC to received Pause frame - detailed in @ref ETH_Receive_Flow_Control */ - - uint32_t ETH_MAC_TransmitFlowControl; /*!< Enable or disable the MAC to transmit Pause frames in Full-Duplex mode - or back-pressure operation in Half-Duplex mode - detailed in @ref ETH_Transmit_Flow_Control */ - - uint32_t ETH_MAC_VLANTagComparison; /*!< Set VLAN tag comparison and filtering mode - detailed in @ref ETH_VLAN_Tag_Comparison */ - - uint32_t ETH_MAC_VLANTagIdentifier; /*!< Set VLAN tag identifier for receive frames */ - - /** - * @brief / * DMA - */ - - uint32_t ETH_DMA_DropTCPIPChecksumErrorFrame; /*!< Enable or disable the TCP/IP Checksum Error Frames drop - detailed in @ref ETH_Drop_TCP_IP_Checksum_Error_Frame */ - - uint32_t ETH_DMA_ReceiveStoreForward; /*!< Set the Rx FIFO operation mode - detailed in @ref ETH_Receive_Store_Forward */ - - uint32_t ETH_DMA_FlushReceivedFrame; /*!< Enable or disable the flushing Receive FIFO - detailed in @ref ETH_Flush_Received_Frame */ - - uint32_t ETH_DMA_TransmitStoreForward; /*!< Enable or disable Tx FIFO operation mode - detailed in @ref ETH_Transmit_Store_Forward */ - - uint32_t ETH_DMA_TransmitThresholdControl; /*!< Enable or disable the Transmit Threshold Control and set the level - detailed in @ref ETH_Transmit_Threshold_Control */ - - uint32_t ETH_DMA_ForwardErrorFrames; /*!< Enable or disable receive the erroneous frames to the DMA - detailed in @ref ETH_Forward_Error_Frames */ - - uint32_t ETH_DMA_ForwardUndersizedGoodFrames; /*!< Enable or disable receive the Undersized frames with no Error - and length less than 64 bytes including pad-bytes and CRC to the DMA - detailed in @ref ETH_Forward_Undersized_Good_Frames */ - - uint32_t ETH_DMA_ReceiveThresholdControl; /*!< Enable or disable the Receive Threshold Control and set the level - detailed in @ref ETH_Receive_Threshold_Control */ - - uint32_t ETH_DMA_SecondFrameOperate; /*!< Enable or disable the Operate on second frame mode - detailed in @ref ETH_Second_Frame_Operate */ - - uint32_t ETH_DMA_AddressAligned; /*!< Enable or disable the Address Aligned - detailed in @ref ETH_Address_Aligned */ - - uint32_t ETH_DMA_FixedBurst; /*!< Enable or disable the AHB Master interface fixed burst transfers - detailed in @ref ETH_Fixed_Burst */ - - uint32_t ETH_DMA_RxDMABurstLength; /*!< Set the maximum number of beats to be transferred in one Rx DMA transaction - detailed in @ref ETH_Rx_DMA_Burst_Length */ - - uint32_t ETH_DMA_TxDMABurstLength; /*!< Set the maximum number of beats to be transferred in one Tx DMA transaction - detailed in @ref ETH_Tx_DMA_Burst_Length */ - - uint32_t ETH_DMA_DescriptorSkipLength; /*!< Set the number of word to skip between two descriptors only in Ring mode */ - - uint32_t ETH_DMA_Arbitration; /*!< Set the DMA Tx/Rx priority ratio - detailed in @ref ETH_DMA_Arbitration */ -} ETH_InitPara; - -/** - * @brief ETH DMA Desciptors structure def - */ -typedef struct { - uint32_t Status; /*!< Status */ - uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ - uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ - uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ -} ETH_DMADESCTypeDef; - -/** - * @} - */ - -/** @defgroup ETH_Exported_Constants - * @{ - */ - -/** @defgroup ETH_delay_Def - * @{ - */ -/* #define USE_Delay */ - -#ifdef USE_Delay -#define _eth_delay_ Delay /*!< User can provide more timing precise _eth_delay_ function */ -#else -#define _eth_delay_ ETH_Delay /*!< Default _eth_delay_ function with less precise timing */ -#endif - -/** - * @} - */ - -/** @defgroup ETH_Buffer_Def - * @{ - */ -#define ETH_MAX_FRAME_SIZE 1520 /*!< FRAME_HEADER + FRAME_EXTRA + MAX_FRAME_PAYLOAD + FRAME_CRC */ -#define ETH_HEADER 14 /*!< 6 byte DA, 6 byte SA, 2 byte length/type */ -#define ETH_CRC 4 /*!< 4 byte CRC */ -#define ETH_EXTRA 2 /*!< Extra bytes in some cases */ -#define VLAN_TAG 4 /*!< optional 802.1q VLAN Tag */ -#define MIN_ETH_DATALENGTH 46 /*!< Minimum Eth payload byte */ -#define MAX_ETH_DATALENGTH 1500 /*!< Maximum Eth payload byte */ -#define JUMBO_FRAME_DATALENGTH 9000 /*!< Jumbo frame payload byte */ - -/** - DMA Tx Desciptor - ----------------------------------------------------------------------------------------------- - TDES0 | BUSY(31) | CTRL[30:26] | Reserved[25:24] | CTRL[23:20] | Reserved[19:17] | Status[16:0] | - ----------------------------------------------------------------------------------------------- - TDES1 | Reserved[31:29] | Buffer2 ByteCount[28:16] | Reserved[15:13] | Buffer1 ByteCount[12:0] | - ----------------------------------------------------------------------------------------------- - TDES2 | Buffer1 Address [31:0] | - ----------------------------------------------------------------------------------------------- - TDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | - ----------------------------------------------------------------------------------------------- -*/ - -/** - * @brief DMA Tx descriptor TDES0 register Bit def - */ -#define ETH_DMATXDESC_BUSY ((uint32_t)0x80000000) /*!< DMA or CPU control descriptor*/ -#define ETH_DMATXDESC_INTC ((uint32_t)0x40000000) /*!< Interrupt on Completion */ -#define ETH_DMATXDESC_LSG ((uint32_t)0x20000000) /*!< contains the last segment of the frame */ -#define ETH_DMATXDESC_FSG ((uint32_t)0x10000000) /*!< contains the first segment of the frame */ -#define ETH_DMATXDESC_DCRC ((uint32_t)0x08000000) /*!< Disable CRC */ -#define ETH_DMATXDESC_DPAD ((uint32_t)0x04000000) /*!< Disable Pad */ -#define ETH_DMATXDESC_TTSEN ((uint32_t)0x02000000) /*!< Transmit Time Stamp Enable */ -#define ETH_DMATXDESC_CM ((uint32_t)0x00C00000) /*!< Checksum Mode: 4 cases */ -#define ETH_DMATXDESC_CM_DISABLE ((uint32_t)0x00000000) /*!< Checksum Insertion disabled */ -#define ETH_DMATXDESC_CM_IPV4HEADER ((uint32_t)0x00400000) /*!< Only IP header checksum calculation and insertion are enabled */ -#define ETH_DMATXDESC_CM_TCPUDPICMP_SEGMENT ((uint32_t)0x00800000) /*!< TCP/UDP/ICMP Checksum Insertion calculated but pseudo-header */ -#define ETH_DMATXDESC_CM_TCPUDPICMP_FULL ((uint32_t)0x00C00000) /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */ -#define ETH_DMATXDESC_TERM ((uint32_t)0x00200000) /*!< Transmit End of Ring Mode*/ -#define ETH_DMATXDESC_TCHM ((uint32_t)0x00100000) /*!< Transmit des Chained Mode*/ -#define ETH_DMATXDESC_TTMSS ((uint32_t)0x00020000) /*!< Tx Time Stamp Status */ -#define ETH_DMATXDESC_IPHE ((uint32_t)0x00010000) /*!< IP Header Error: IP4 or IP6*/ -#define ETH_DMATXDESC_ES ((uint32_t)0x00008000) /*!< Error summary */ -#define ETH_DMATXDESC_JT ((uint32_t)0x00004000) /*!< Jabber Timeout */ -#define ETH_DMATXDESC_FRMF ((uint32_t)0x00002000) /*!< clean FIFO */ -#define ETH_DMATXDESC_IPPE ((uint32_t)0x00001000) /*!< IP Payload Error */ -#define ETH_DMATXDESC_LCA ((uint32_t)0x00000800) /*!< Loss of Carrier */ -#define ETH_DMATXDESC_NCA ((uint32_t)0x00000400) /*!< No Carrier */ -#define ETH_DMATXDESC_LCO ((uint32_t)0x00000200) /*!< Late Collision */ -#define ETH_DMATXDESC_ECO ((uint32_t)0x00000100) /*!< abort transmission due to collision */ -#define ETH_DMATXDESC_VFRM ((uint32_t)0x00000080) /*!< VLAN Frame */ -#define ETH_DMATXDESC_COCNT ((uint32_t)0x00000078) /*!< Collision Count */ -#define ETH_DMATXDESC_EXD ((uint32_t)0x00000004) /*!< Excessive Deferral */ -#define ETH_DMATXDESC_UFE ((uint32_t)0x00000002) /*!< late data arrival from the memory */ -#define ETH_DMATXDESC_DB ((uint32_t)0x00000001) /*!< Deferred Bit */ - -/** - * @brief DMA Tx descriptor TDES1 register Bit def - */ -#define ETH_DMATXDESC_TB2S ((uint32_t)0x1FFF0000) /*!< Transmit Buffer2 Size */ -#define ETH_DMATXDESC_TB1S ((uint32_t)0x00001FFF) /*!< Transmit Buffer1 Size */ - -/** - * @brief DMA Tx descriptor TDES2 register Bit def - */ -#define ETH_DMATXDESC_TB1AP ((uint32_t)0xFFFFFFFF) /*!< Buffer1 Address Pointer */ - -/** - * @brief DMA Tx descriptor TDES3 register Bit def - */ -#define ETH_DMATXDESC_TB2AP ((uint32_t)0xFFFFFFFF) /*!< Buffer2 Address Pointer */ - -/** - * @} - */ - - -/** @defgroup DMA_Rx_descriptor - * @{ - */ - -/** - DMA Rx Desciptor - -------------------------------------------------------------------------------------------------------------------- - RDES0 | BUSY(31) | Status [30:0] | - --------------------------------------------------------------------------------------------------------------------- - RDES1 | CTRL(31) | Reserved[30:29] | Buffer2 ByteCount[28:16] | CTRL[15:14] | Reserved(13) | Buffer1 ByteCount[12:0] | - --------------------------------------------------------------------------------------------------------------------- - RDES2 | Buffer1 Address [31:0] | - --------------------------------------------------------------------------------------------------------------------- - RDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | - --------------------------------------------------------------------------------------------------------------------- -*/ - -/** - * @brief DMA Rx descriptor RDES0 register Bit def - */ -#define ETH_DMARXDESC_BUSY ((uint32_t)0x80000000) /*!< DMA or CPU control descriptor */ -#define ETH_DMARXDESC_DAFF ((uint32_t)0x40000000) /*!< DA filter fail */ -#define ETH_DMARXDESC_FRML ((uint32_t)0x3FFF0000) /*!< Frame length */ -#define ETH_DMARXDESC_ERRS ((uint32_t)0x00008000) /*!< Error summary */ -#define ETH_DMARXDESC_DERR ((uint32_t)0x00004000) /*!< no more descriptors for receive frame */ -#define ETH_DMARXDESC_SAFF ((uint32_t)0x00002000) /*!< SA filter fail */ -#define ETH_DMARXDESC_LERR ((uint32_t)0x00001000) /*!< Frame size not matching with length field */ -#define ETH_DMARXDESC_OERR ((uint32_t)0x00000800) /*!< FIFO Overflow Error */ -#define ETH_DMARXDESC_VTAG ((uint32_t)0x00000400) /*!< VLAN Tag: a VLAN frame tag */ -#define ETH_DMARXDESC_FDES ((uint32_t)0x00000200) /*!< First descriptor of the frame */ -#define ETH_DMARXDESC_LDES ((uint32_t)0x00000100) /*!< Last descriptor of the frame */ -#define ETH_DMARXDESC_IPHCERR ((uint32_t)0x00000080) /*!< IPC Checksum Error: Rx Ipv4 or Ipv6 header checksum error */ -#define ETH_DMARXDESC_LCO ((uint32_t)0x00000040) /*!< Late collision occurred during reception */ -#define ETH_DMARXDESC_FRMT ((uint32_t)0x00000020) /*!< Frame type */ -#define ETH_DMARXDESC_RWDT ((uint32_t)0x00000010) /*!< Receive WD Timeout */ -#define ETH_DMARXDESC_RERR ((uint32_t)0x00000008) /*!< the RX_ERR signal is asserted while RX_DV is asserted during frame reception */ -#define ETH_DMARXDESC_DBERR ((uint32_t)0x00000004) /*!< received frame has a non int multiple of bytes */ -#define ETH_DMARXDESC_CERR ((uint32_t)0x00000002) /*!< CRC error */ -#define ETH_DMARXDESC_PCERR ((uint32_t)0x00000001) /*!< Receive MAC address matched/ Receive Payload Checksum Error */ - -/** - * @brief DMA Rx descriptor RDES1 register Bit def - */ -#define ETH_DMARXDESC_DINTC ((uint32_t)0x80000000) /*!< Disable Interrupt on Completion */ -#define ETH_DMARXDESC_RB2S ((uint32_t)0x1FFF0000) /*!< Receive Buffer2 Size */ -#define ETH_DMARXDESC_RERM ((uint32_t)0x00008000) /*!< Receive End of Ring mode*/ -#define ETH_DMARXDESC_RCHM ((uint32_t)0x00004000) /*!< Receive des Chained mode */ -#define ETH_DMARXDESC_RB1S ((uint32_t)0x00001FFF) /*!< Receive Buffer1 Size */ - -/** - * @brief DMA Rx descriptor RDES2 register Bit def - */ -#define ETH_DMARXDESC_RB1AP ((uint32_t)0xFFFFFFFF) /*!< Buffer1 Address Pointer */ - -/** - * @brief DMA Rx descriptor RDES3 register Bit def - */ -#define ETH_DMARXDESC_RB2AP ((uint32_t)0xFFFFFFFF) /*!< Buffer2 Address Pointer */ - -#ifndef _PHY_H_ -#define DP83848 0 -#define LAN8700 1 -#define PHY_TYPE DP83848 - -/** - * @} - */ - -/** @defgroup PHY_Read_write_Timeouts - * @{ - */ -#define PHY_READ_TO ((uint32_t)0x0004FFFF) -#define PHY_WRITE_TO ((uint32_t)0x0004FFFF) - -/** - * @} - */ - -/** @defgroup PHY_Reset_Delay - * @{ - */ -#define PHY_RESETDELAY ((uint32_t)0x000FFFFF) - -/** - * @} - */ - -/** @defgroup PHY_Config_Delay - * @{ - */ -#define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFF) - -/** - * @} - */ - -/** @defgroup PHY_Register_address - * @{ - */ -#define PHY_BCR 0 /*!< Tranceiver Basic Control Register */ -#define PHY_BSR 1 /*!< Tranceiver Basic Status Register */ - -/** - * @} - */ - -/** @defgroup PHY_basic_Control_register - * @{ - */ -#define PHY_RESET ((u16)0x8000) /*!< PHY Reset */ -#define PHY_LOOPBACK ((u16)0x4000) /*!< Enable loop-back mode */ -#define PHY_FULLDUPLEX_100M ((u16)0x2100) /*!< Configure speed to 100 Mb/s and the full-duplex mode */ -#define PHY_HALFDUPLEX_100M ((u16)0x2000) /*!< Configure speed to 100 Mb/s and the half-duplex mode */ -#define PHY_FULLDUPLEX_10M ((u16)0x0100) /*!< Configure speed to 10 Mb/s and the full-duplex mode */ -#define PHY_HALFDUPLEX_10M ((u16)0x0000) /*!< Configure speed to 10 Mb/s and the half-duplex mode */ -#define PHY_AUTONEGOTIATION ((u16)0x1000) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((u16)0x0200) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((u16)0x0800) /*!< Enable the power down mode */ -#define PHY_ISOLATE ((u16)0x0400) /*!< Isolate PHY from MII */ - -/** - * @} - */ - -/** @defgroup PHY_basic_status_register - * @{ - */ -#define PHY_AUTONEGO_COMPLETE ((u16)0x0020) /*!< Auto-Negotioation process completed */ -#define PHY_LINKED_STATUS ((u16)0x0004) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((u16)0x0002) /*!< Jabber condition detected */ - -/** - * @} - */ - -/** @defgroup PHY_status_register - * @{ - */ -/* The PHY status register value change with PHY in different Manufacturer - so the user can use external PHY lib to update this value if PHY types user selected not included in firmware */ -#if(PHY_TYPE == LAN8700) -/** - * @brief For LAN8700 - */ -#define PHY_SR 31 /*!< Tranceiver Status Register */ -/* The Speed and Duplex mask values change with PHY in different Manufacturer - so the user can use external PHY lib to update this value if PHY types user selected not included in firmware */ -#define PHY_Speed_Status ((u16)0x0004) /*!< Configured information of Speed: 10Mbps */ -#define PHY_DUPLEX_STATUS ((u16)0x0010) /*!< Configured information of Duplex: Full-duplex */ - -#elif(PHY_TYPE == DP83848) -/** - * @brief For DP83848 - */ -#define PHY_SR 16 /*!< Tranceiver Status Register */ -/* The Speed and Duplex mask values change with PHY in different Manufacturer - so the user can use external PHY lib to update this value if PHY types user selected not included in firmware */ -#define PHY_SPEED_STATUS ((u16)0x0002) /*!< Configured information of Speed: 10Mbps */ -#define PHY_DUPLEX_STATUS ((u16)0x0004) /*!< Configured information of Duplex: Full-duplex */ - -#define PHY_Reset PHY_RESETDELAY -#define PHY_ResetDelay PHY_RESETDELAY -#define PHY_Speed_Status PHY_SPEED_STATUS - -#endif - -#endif - - -/** - * @} - */ - -/** @defgroup ETH_AutoNegotiation - * @{ - */ -#define ETH_AUTONEGOTIATION_ENABLE ((uint32_t)0x00000001) -#define ETH_AUTONEGOTIATION_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_watchdog - * @{ - */ -#define ETH_WATCHDOG_ENABLE ((uint32_t)0x00000000) -#define ETH_WATCHDOG_DISABLE ((uint32_t)0x00800000) - -/** - * @} - */ - -/** @defgroup ETH_Jabber - * @{ - */ -#define ETH_JABBER_ENABLE ((uint32_t)0x00000000) -#define ETH_JABBER_DISABLE ((uint32_t)0x00400000) - -/** - * @} - */ - -/** @defgroup ETH_Inter_Frame_Gap - * @{ - */ -#define ETH_INTERFRAMEGAP_96BIT ((uint32_t)0x00000000) -#define ETH_INTERFRAMEGAP_88BIT ((uint32_t)0x00020000) -#define ETH_INTERFRAMEGAP_80BIT ((uint32_t)0x00040000) -#define ETH_INTERFRAMEGAP_72BIT ((uint32_t)0x00060000) -#define ETH_INTERFRAMEGAP_64BIT ((uint32_t)0x00080000) -#define ETH_INTERFRAMEGAP_56BIT ((uint32_t)0x000A0000) -#define ETH_INTERFRAMEGAP_48BIT ((uint32_t)0x000C0000) -#define ETH_INTERFRAMEGAP_40BIT ((uint32_t)0x000E0000) - - -/** - * @} - */ - -/** @defgroup ETH_Carrier_Sense - * @{ - */ -#define ETH_CARRIERSENSE_ENABLE ((uint32_t)0x00000000) -#define ETH_CARRIERSENSE_DISABLE ((uint32_t)0x00010000) - -/** - * @} - */ - -/** @defgroup ETH_Speed - * @{ - */ -#define ETH_SPEEDMODE_10M ((uint32_t)0x00000000) -#define ETH_SPEEDMODE_100M ((uint32_t)0x00004000) - -/** - * @} - */ - -/** @defgroup ETH_Receive_Own - * @{ - */ -#define ETH_RECEIVEOWN_ENABLE ((uint32_t)0x00000000) -#define ETH_RECEIVEOWN_DISABLE ((uint32_t)0x00002000) - - -/** - * @} - */ - -/** @defgroup ETH_Loop_Back_Mode - * @{ - */ -#define ETH_LOOPBACKMODE_ENABLE ((uint32_t)0x00001000) -#define ETH_LOOPBACKMODE_DISABLE ((uint32_t)0x00000000) - - -/** - * @} - */ - -/** @defgroup ETH_Duplex_Mode - * @{ - */ -#define ETH_MODE_FULLDUPLEX ((uint32_t)0x00000800) -#define ETH_MODE_HALFDUPLEX ((uint32_t)0x00000000) - - -/** - * @} - */ - -/** @defgroup ETH_Checksum_Offload - * @{ - */ -#define ETH_CHECKSUMOFFLOAD_ENABLE ((uint32_t)0x00000400) -#define ETH_CHECKSUMOFFLOAD_DISABLE ((uint32_t)0x00000000) - - -/** - * @} - */ - -/** @defgroup ETH_Retry_Transmission - * @{ - */ -#define ETH_RETRYTRANSMISSION_ENABLE ((uint32_t)0x00000000) -#define ETH_RETRYTRANSMISSION_DISABLE ((uint32_t)0x00000200) - - -/** - * @} - */ - -/** @defgroup ETH_Automatic_Pad_CRC_Drop - * @{ - */ -#define ETH_AUTOMATICPADCRCDROP_ENABLE ((uint32_t)0x00000080) -#define ETH_AUTOMATICPADCRCDROP_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Back_Off_Limit - * @{ - */ -#define ETH_BACKOFFLIMIT_10 ((uint32_t)0x00000000) -#define ETH_BACKOFFLIMIT_8 ((uint32_t)0x00000020) -#define ETH_BACKOFFLIMIT_4 ((uint32_t)0x00000040) -#define ETH_BACKOFFLIMIT_1 ((uint32_t)0x00000060) - -/** - * @} - */ - -/** @defgroup ETH_Deferral_Check - * @{ - */ -#define ETH_DEFERRALCHECK_ENABLE ((uint32_t)0x00000010) -#define ETH_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Filter_Disable - * @{ - */ -#define ETH_FILTERDISABLE_ENABLE ((uint32_t)0x80000000) -#define ETH_FILTERDISABLE_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Source_Addr_Filter - * @{ - */ -#define ETH_SOURCEADDRFILTER_NORMAL_ENABLE ((uint32_t)0x00000200) -#define ETH_SOURCEADDRFILTER_INVERSE_ENABLE ((uint32_t)0x00000300) -#define ETH_SOURCEADDRFILTER_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Pass_Control_Frames - * @{ - */ -#define ETH_PASSCONTROLFRAMES_BLOCKALL ((uint32_t)0x00000040) -#define ETH_PASSCONTROLFRAMES_FORWARDALL ((uint32_t)0x00000080) -#define ETH_PASSCONTROLFRAMES_FORWARDPASSEDADDRFILTER ((uint32_t)0x000000C0) - -/** - * @} - */ - -/** @defgroup ETH_Broadcast_Frames_Reception - * @{ - */ -#define ETH_BROADCASTFRAMESRECEPTION_ENABLE ((uint32_t)0x00000000) -#define ETH_BROADCASTFRAMESRECEPTION_DISABLE ((uint32_t)0x00000020) - -/** - * @} - */ - -/** @defgroup ETH_Destination_Addr_Filter - * @{ - */ -#define ETH_DESTINATIONADDRFILTER_NORMAL ((uint32_t)0x00000000) -#define ETH_DESTINATIONADDRFILTER_INVERSE ((uint32_t)0x00000008) - -/** - * @} - */ - -/** @defgroup ETH_Promiscuous_Mode - * @{ - */ -#define ETH_PROMISCUOUSMODE_ENABLE ((uint32_t)0x00000001) -#define ETH_PROMISCUOUSMODE_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Multicast_Frames_Filter - * @{ - */ -#define ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE ((uint32_t)0x00000404) -#define ETH_MULTICASTFRAMESFILTER_HASHTABLE ((uint32_t)0x00000004) -#define ETH_MULTICASTFRAMESFILTER_PERFECT ((uint32_t)0x00000000) -#define ETH_MULTICASTFRAMESFILTER_NONE ((uint32_t)0x00000010) - - -/** - * @} - */ - -/** @defgroup ETH_Unicast_Frames_Filter - * @{ - */ -#define ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE ((uint32_t)0x00000402) -#define ETH_UNICASTFRAMESFILTER_HASHTABLE ((uint32_t)0x00000002) -#define ETH_UNICASTFRAMESFILTER_PERFECT ((uint32_t)0x00000000) - -/** - * @} - */ - - -/** @defgroup ETH_Zero_Quanta_Pause - * @{ - */ -#define ETH_ZEROQUANTAPAUSE_ENABLE ((uint32_t)0x00000000) -#define ETH_ZEROQUANTAPAUSE_DISABLE ((uint32_t)0x00000080) -/** - * @} - */ - -/** @defgroup ETH_Pause_Low_Threshold - * @{ - */ -#define ETH_PAUSELOWTHRESHOLD_MINUS4 ((uint32_t)0x00000000) -#define ETH_PAUSELOWTHRESHOLD_MINUS28 ((uint32_t)0x00000010) -#define ETH_PAUSELOWTHRESHOLD_MINUS144 ((uint32_t)0x00000020) -#define ETH_PAUSELOWTHRESHOLD_MINUS256 ((uint32_t)0x00000030) - -/** - * @} - */ - -/** @defgroup ETH_RFD_Threshold - * @{ - */ -#define ETH_RFD_256BYTES ((uint32_t)0x00000000) -#define ETH_RFD_512BYTES ((uint32_t)0x00000010) -#define ETH_RFD_768BYTES ((uint32_t)0x00000020) -#define ETH_RFD_1024BYTES ((uint32_t)0x00000030) -#define ETH_RFD_1280BYTES ((uint32_t)0x00000040) -#define ETH_RFD_1536BYTES ((uint32_t)0x00000050) -#define ETH_RFD_1792BYTES ((uint32_t)0x00000060) - -/** - * @} - */ - -/** @defgroup ETH_RFA_Threshold - * @{ - */ -#define ETH_RFA_256BYTES ((uint32_t)0x00000000) -#define ETH_RFA_512BYTES ((uint32_t)0x00000001) -#define ETH_RFA_768BYTES ((uint32_t)0x00000002) -#define ETH_RFA_1024BYTES ((uint32_t)0x00000003) -#define ETH_RFA_1280BYTES ((uint32_t)0x00000004) -#define ETH_RFA_1536BYTES ((uint32_t)0x00000005) -#define ETH_RFA_1792BYTES ((uint32_t)0x00000006) - -/** - * @} - */ - -/** @defgroup ETH_Unicast_Pause_Frame_Detect - * @{ - */ -#define ETH_UNICASTPAUSEFRAMEDETECT_ENABLE ((uint32_t)0x00000008) -#define ETH_UNICASTPAUSEFRAMEDETECT_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Receive_Flow_Control - * @{ - */ -#define ETH_RECEIVEFLOWCONTROL_ENABLE ((uint32_t)0x00000004) -#define ETH_RECEIVEFLOWCONTROL_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Transmit_Flow_Control - * @{ - */ -#define ETH_TRANSMITFLOWCONTROL_ENABLE ((uint32_t)0x00000002) -#define ETH_TRANSMITFLOWCONTROL_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_VLAN_Tag_Comparison - * @{ - */ -#define ETH_VLANTAGCOMPARISON_12BIT ((uint32_t)0x00010000) -#define ETH_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_MAC_Flags - * @{ - */ -#define ETH_MAC_FLAG_TST ((uint32_t)0x00000200) /*!< Time stamp trigger flag (on MAC) */ -#define ETH_MAC_FLAG_MSCT ((uint32_t)0x00000040) /*!< MSC transmit flag */ -#define ETH_MAC_FLAG_MSCR ((uint32_t)0x00000020) /*!< MSC receive flag */ -#define ETH_MAC_FLAG_MSC ((uint32_t)0x00000010) -#define ETH_MAC_FLAG_WUM ((uint32_t)0x00000008) -/** - * @} - */ - -/** @defgroup ETH_MAC_Interrupts - * @{ - */ -#define ETH_MAC_INT_TST ((uint32_t)0x00000200) /*!< Time stamp trigger interrupt (on MAC) */ -#define ETH_MAC_INT_MSCT ((uint32_t)0x00000040) /*!< MSC transmit interrupt */ -#define ETH_MAC_INT_MSCR ((uint32_t)0x00000020) /*!< MSC receive interrupt */ -#define ETH_MAC_INT_MSC ((uint32_t)0x00000010) -#define ETH_MAC_INT_WUM ((uint32_t)0x00000008) -/** - * @} - */ - -/** @defgroup ETH_MAC_addresses - * @{ - */ -#define ETH_MAC_ADDRESS0 ((uint32_t)0x00000000) -#define ETH_MAC_ADDRESS1 ((uint32_t)0x00000008) -#define ETH_MAC_ADDRESS2 ((uint32_t)0x00000010) -#define ETH_MAC_ADDRESS3 ((uint32_t)0x00000018) -/** - * @} - */ - -/** @defgroup ETH_MAC_addresses_filter_SA_DA_filed_of_received_frames - * @{ - */ -#define ETH_MAC_ADDRESSFILTER_SA ((uint32_t)0x00000000) -#define ETH_MAC_ADDRESSFILTER_DA ((uint32_t)0x00000008) -/** - * @} - */ - -/** @defgroup ETH_MAC_addresses_filter_Mask_bytes - * @{ - */ -#define ETH_MAC_ADDRESSMASK_BYTE6 ((uint32_t)0x20000000) /*!< Mask MAC Address high reg bits [15:8] */ -#define ETH_MAC_ADDRESSMASK_BYTE5 ((uint32_t)0x10000000) /*!< Mask MAC Address high reg bits [7:0] */ -#define ETH_MAC_ADDRESSMASK_BYTE4 ((uint32_t)0x08000000) /*!< Mask MAC Address low reg bits [31:24] */ -#define ETH_MAC_ADDRESSMASK_BYTE3 ((uint32_t)0x04000000) /*!< Mask MAC Address low reg bits [23:16] */ -#define ETH_MAC_ADDRESSMASK_BYTE2 ((uint32_t)0x02000000) /*!< Mask MAC Address low reg bits [15:8] */ -#define ETH_MAC_ADDRESSMASK_BYTE1 ((uint32_t)0x01000000) /*!< Mask MAC Address low reg bits [7:0] */ - -/** - * @} - */ - - -/** @defgroup ETH_DMA_Tx_descriptor_segment - * @{ - */ -#define ETH_DMATXDESC_LASTSEGMENT ((uint32_t)0x40000000) -#define ETH_DMATXDESC_FIRSTSEGMENT ((uint32_t)0x20000000) - -/** - * @} - */ - -/** @defgroup ETH_DMA_Tx_descriptor_Checksum_Insertion_Control - * @{ - */ -#define ETH_DMATXDESC_CHECKSUMDISABLE ((uint32_t)0x00000000) -#define ETH_DMATXDESC_CHECKSUMIPV4HEADER ((uint32_t)0x00400000) -#define ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT ((uint32_t)0x00800000) -#define ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL ((uint32_t)0x00C00000) - - -/** - * @} - */ - -/** @defgroup ETH_DMA_Rx_descriptor_buffers_ - * @{ - */ -#define ETH_DMARXDESC_BUFFER1 ((uint32_t)0x00000000) -#define ETH_DMARXDESC_BUFFER2 ((uint32_t)0x00000001) - -/** - * @} - */ - -/** @defgroup ETH_Drop_TCP_IP_Checksum_Error_Frame - * @{ - */ -#define ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE ((uint32_t)0x00000000) -#define ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE ((uint32_t)0x04000000) -/** - * @} - */ - -/** @defgroup ETH_Receive_Store_Forward - * @{ - */ -#define ETH_RECEIVESTOREFORWARD_ENABLE ((uint32_t)0x02000000) -#define ETH_RECEIVESTOREFORWARD_DISABLE ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup ETH_Flush_Received_Frame - * @{ - */ -#define ETH_FLUSHRECEIVEDFRAME_ENABLE ((uint32_t)0x00000000) -#define ETH_FLUSHRECEIVEDFRAME_DISABLE ((uint32_t)0x01000000) -/** - * @} - */ - -/** @defgroup ETH_Transmit_Store_Forward - * @{ - */ -#define ETH_TRANSMITSTOREFORWARD_ENABLE ((uint32_t)0x00200000) -#define ETH_TRANSMITSTOREFORWARD_DISABLE ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup ETH_Transmit_Threshold_Control - * @{ - */ -#define ETH_TRANSMITTHRESHOLDCONTROL_64BYTES ((uint32_t)0x00000000) -#define ETH_TRANSMITTHRESHOLDCONTROL_128BYTES ((uint32_t)0x00004000) -#define ETH_TRANSMITTHRESHOLDCONTROL_192BYTES ((uint32_t)0x00008000) -#define ETH_TRANSMITTHRESHOLDCONTROL_256BYTES ((uint32_t)0x0000C000) -#define ETH_TRANSMITTHRESHOLDCONTROL_40BYTES ((uint32_t)0x00010000) -#define ETH_TRANSMITTHRESHOLDCONTROL_32BYTES ((uint32_t)0x00014000) -#define ETH_TRANSMITTHRESHOLDCONTROL_24BYTES ((uint32_t)0x00018000) -#define ETH_TRANSMITTHRESHOLDCONTROL_16BYTES ((uint32_t)0x0001C000) -/** - * @} - */ - -/** @defgroup ETH_Forward_Error_Frames - * @{ - */ -#define ETH_FORWARDERRORFRAMES_ENABLE ((uint32_t)0x00000080) -#define ETH_FORWARDERRORFRAMES_DISABLE ((uint32_t)0x00000000) -/** - * @} - */ - -/** @defgroup ETH_Forward_Undersized_Good_Frames - * @{ - */ -#define ETH_FORWARDUNDERSIZEDGOODFRAMES_ENABLE ((uint32_t)0x00000040) -#define ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Receive_Threshold_Control - * @{ - */ -#define ETH_RECEIVETHRESHOLDCONTROL_64BYTES ((uint32_t)0x00000000) -#define ETH_RECEIVETHRESHOLDCONTROL_32BYTES ((uint32_t)0x00000008) -#define ETH_RECEIVETHRESHOLDCONTROL_96BYTES ((uint32_t)0x00000010) -#define ETH_RECEIVETHRESHOLDCONTROL_128BYTES ((uint32_t)0x00000018) -/** - * @} - */ - -/** @defgroup ETH_Second_Frame_Operate - * @{ - */ -#define ETH_SECONDFRAMEOPERATE_ENABLE ((uint32_t)0x00000004) -#define ETH_SECONDFRAMEOPERATE_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Address_Aligned - * @{ - */ -#define ETH_ADDRESSALIGNED_ENABLE ((uint32_t)0x02000000) -#define ETH_ADDRESSALIGNED_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Fixed_Burst - * @{ - */ -#define ETH_FIXEDBURST_ENABLE ((uint32_t)0x00010000) -#define ETH_FIXEDBURST_DISABLE ((uint32_t)0x00000000) - -/** - * @} - */ - -/** @defgroup ETH_Rx_DMA_Burst_Length - * @{ - */ -#define ETH_RXDMABURSTLENGTH_1BEAT ((uint32_t)0x00020000) -#define ETH_RXDMABURSTLENGTH_2BEAT ((uint32_t)0x00040000) -#define ETH_RXDMABURSTLENGTH_4BEAT ((uint32_t)0x00080000) -#define ETH_RXDMABURSTLENGTH_8BEAT ((uint32_t)0x00100000) -#define ETH_RXDMABURSTLENGTH_16BEAT ((uint32_t)0x00200000) -#define ETH_RXDMABURSTLENGTH_32BEAT ((uint32_t)0x00400000) -#define ETH_RXDMABURSTLENGTH_4XPBL_4BEAT ((uint32_t)0x01020000) -#define ETH_RXDMABURSTLENGTH_4XPBL_8BEAT ((uint32_t)0x01040000) -#define ETH_RXDMABURSTLENGTH_4XPBL_16BEAT ((uint32_t)0x01080000) -#define ETH_RXDMABURSTLENGTH_4XPBL_32BEAT ((uint32_t)0x01100000) -#define ETH_RXDMABURSTLENGTH_4XPBL_64BEAT ((uint32_t)0x01200000) -#define ETH_RXDMABURSTLENGTH_4XPBL_128BEAT ((uint32_t)0x01400000) -/** - * @} - */ - -/** @defgroup ETH_Tx_DMA_Burst_Length - * @{ - */ -#define ETH_TXDMABURSTLENGTH_1BEAT ((uint32_t)0x00000100) -#define ETH_TXDMABURSTLENGTH_2BEAT ((uint32_t)0x00000200) -#define ETH_TXDMABURSTLENGTH_4BEAT ((uint32_t)0x00000400) -#define ETH_TXDMABURSTLENGTH_8BEAT ((uint32_t)0x00000800) -#define ETH_TXDMABURSTLENGTH_16BEAT ((uint32_t)0x00001000) -#define ETH_TXDMABURSTLENGTH_32BEAT ((uint32_t)0x00002000) -#define ETH_TXDMABURSTLENGTH_4XPBL_4BEAT ((uint32_t)0x01000100) -#define ETH_TXDMABURSTLENGTH_4XPBL_8BEAT ((uint32_t)0x01000200) -#define ETH_TXDMABURSTLENGTH_4XPBL_16BEAT ((uint32_t)0x01000400) -#define ETH_TXDMABURSTLENGTH_4XPBL_32BEAT ((uint32_t)0x01000800) -#define ETH_TXDMABURSTLENGTH_4XPBL_64BEAT ((uint32_t)0x01001000) -#define ETH_TXDMABURSTLENGTH_4XPBL_128BEAT ((uint32_t)0x01002000) - -/** - * @} - */ - -/** @defgroup ETH_DMA_Arbitration - * @{ - */ -#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1 ((uint32_t)0x00000000) -#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1 ((uint32_t)0x00004000) -#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_3_1 ((uint32_t)0x00008000) -#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1 ((uint32_t)0x0000C000) -#define ETH_DMAARBITRATION_RXPRIORTX ((uint32_t)0x00000002) - -/** - * @} - */ - -/** @defgroup ETH_DMA_Flags - * @{ - */ -#define ETH_DMA_FLAG_TST ((uint32_t)0x20000000) /*!< Time-stamp trigger interrupt (on DMA) */ -#define ETH_DMA_FLAG_WUM ((uint32_t)0x10000000) /*!< WUM interrupt (on DMA) */ -#define ETH_DMA_FLAG_MSC ((uint32_t)0x08000000) /*!< MSC interrupt (on DMA) */ -#define ETH_DMA_FLAG_DATATRANSFERERROR ((uint32_t)0x00800000) /*!< Error bits 0-Rx DMA, 1-Tx DMA */ -#define ETH_DMA_FLAG_READWRITEERROR ((uint32_t)0x01000000) /*!< Error bits 0-write trnsf, 1-read transfr */ -#define ETH_DMA_FLAG_ACCESSERROR ((uint32_t)0x02000000) /*!< Error bits 0-data buffer, 1-desc. access */ -#define ETH_DMA_FLAG_NIS ((uint32_t)0x00010000) /*!< Normal interrupt summary flag */ -#define ETH_DMA_FLAG_AIS ((uint32_t)0x00008000) /*!< Abnormal interrupt summary flag */ -#define ETH_DMA_FLAG_ER ((uint32_t)0x00004000) /*!< Early receive flag */ -#define ETH_DMA_FLAG_FBE ((uint32_t)0x00002000) /*!< Fatal bus error flag */ -#define ETH_DMA_FLAG_ET ((uint32_t)0x00000400) /*!< Early transmit flag */ -#define ETH_DMA_FLAG_RWT ((uint32_t)0x00000200) /*!< Receive watchdog timeout flag */ -#define ETH_DMA_FLAG_RPS ((uint32_t)0x00000100) /*!< Receive process stopped flag */ -#define ETH_DMA_FLAG_RBU ((uint32_t)0x00000080) /*!< Receive buffer unavailable flag */ -#define ETH_DMA_FLAG_R ((uint32_t)0x00000040) /*!< Receive flag */ -#define ETH_DMA_FLAG_TU ((uint32_t)0x00000020) /*!< Transmit Underflow flag */ -#define ETH_DMA_FLAG_RO ((uint32_t)0x00000010) /*!< Receive Overflow flag */ -#define ETH_DMA_FLAG_TJT ((uint32_t)0x00000008) /*!< Transmit jabber timeout flag */ -#define ETH_DMA_FLAG_TBU ((uint32_t)0x00000004) /*!< Transmit buffer unavailable flag */ -#define ETH_DMA_FLAG_TPS ((uint32_t)0x00000002) /*!< Transmit process stopped flag */ -#define ETH_DMA_FLAG_T ((uint32_t)0x00000001) /*!< Transmit flag */ - -/** - * @} - */ - -/** @defgroup ETH_DMA_Interrupts - * @{ - */ -#define ETH_DMA_INT_TST ((uint32_t)0x20000000) /*!< Time-stamp trigger interrupt (on DMA) */ -#define ETH_DMA_INT_WUM ((uint32_t)0x10000000) /*!< WUM interrupt (on DMA) */ -#define ETH_DMA_INT_MSC ((uint32_t)0x08000000) /*!< MSC interrupt (on DMA) */ -#define ETH_DMA_INT_NIS ((uint32_t)0x00010000) /*!< Normal interrupt summary */ -#define ETH_DMA_INT_AIS ((uint32_t)0x00008000) /*!< Abnormal interrupt summary */ -#define ETH_DMA_INT_ER ((uint32_t)0x00004000) /*!< Early receive interrupt */ -#define ETH_DMA_INT_FBE ((uint32_t)0x00002000) /*!< Fatal bus error interrupt */ -#define ETH_DMA_INT_ET ((uint32_t)0x00000400) /*!< Early transmit interrupt */ -#define ETH_DMA_INT_RWT ((uint32_t)0x00000200) /*!< Receive watchdog timeout interrupt */ -#define ETH_DMA_INT_RPS ((uint32_t)0x00000100) /*!< Receive process stopped interrupt */ -#define ETH_DMA_INT_RBU ((uint32_t)0x00000080) /*!< Receive buffer unavailable interrupt */ -#define ETH_DMA_INT_R ((uint32_t)0x00000040) /*!< Receive interrupt */ -#define ETH_DMA_INT_TU ((uint32_t)0x00000020) /*!< Transmit Underflow interrupt */ -#define ETH_DMA_INT_RO ((uint32_t)0x00000010) /*!< Receive Overflow interrupt */ -#define ETH_DMA_INT_TJT ((uint32_t)0x00000008) /*!< Transmit jabber timeout interrupt */ -#define ETH_DMA_INT_TBU ((uint32_t)0x00000004) /*!< Transmit buffer unavailable interrupt */ -#define ETH_DMA_INT_TPS ((uint32_t)0x00000002) /*!< Transmit process stopped interrupt */ -#define ETH_DMA_INT_T ((uint32_t)0x00000001) /*!< Transmit interrupt */ - - -/** - * @} - */ - -/** @defgroup ETH_DMA_transmit_process_state_ - * @{ - */ -#define ETH_DMA_TRANSMITPROCESS_STOPPED ((uint32_t)0x00000000) -#define ETH_DMA_TRANSMITPROCESS_FETCHING ((uint32_t)0x00100000) -#define ETH_DMA_TRANSMITPROCESS_WAITING ((uint32_t)0x00200000) -#define ETH_DMA_TRANSMITPROCESS_READING ((uint32_t)0x00300000) -#define ETH_DMA_TRANSMITPROCESS_SUSPENDED ((uint32_t)0x00600000) -#define ETH_DMA_TRANSMITPROCESS_CLOSING ((uint32_t)0x00700000) - -/** - * @} - */ - - -/** @defgroup ETH_DMA_receive_process_state_ - * @{ - */ -#define ETH_DMA_RECEIVEPROCESS_STOPPED ((uint32_t)0x00000000) -#define ETH_DMA_RECEIVEPROCESS_FETCHING ((uint32_t)0x00020000) -#define ETH_DMA_RECEIVEPROCESS_WAITING ((uint32_t)0x00060000) -#define ETH_DMA_RECEIVEPROCESS_SUSPENDED ((uint32_t)0x00080000) -#define ETH_DMA_RECEIVEPROCESS_CLOSING ((uint32_t)0x000A0000) -#define ETH_DMA_RECEIVEPROCESS_QUEUING ((uint32_t)0x000E0000) - -/** - * @} - */ - -/** @defgroup ETH_DMA_overflow_ - * @{ - */ -#define ETH_DMA_OVERFLOW_RXFIFOCOUNTER ((uint32_t)0x10000000) -#define ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER ((uint32_t)0x00010000) - -/** - * @} - */ - -/** @defgroup ETH_WUM_Flags - * @{ - */ -#define ETH_WUM_FLAG_WUFFRPR ((uint32_t)0x80000000) /*!< Wake-Up Frame Filter Register Poniter Reset */ -#define ETH_WUM_FLAG_WUFR ((uint32_t)0x00000040) /*!< Wake-Up Frame Received */ -#define ETH_WUM_FLAG_MPKR ((uint32_t)0x00000020) /*!< Magic Packet Received */ - -/** - * @} - */ - -/** @defgroup ETH_MSC_Tx_Interrupts - * @{ - */ -#define ETH_MSC_INT_TGF ((uint32_t)0x00200000) /*!< When Tx good frame counter reaches half the maximum value */ -#define ETH_MSC_INT_TGFMSC ((uint32_t)0x00008000) /*!< When Tx good multi col counter reaches half the maximum value */ -#define ETH_MSC_INT_TGFSC ((uint32_t)0x00004000) /*!< When Tx good single col counter reaches half the maximum value */ - -/** - * @} - */ - -/** @defgroup ETH_MSC_Rx_Interrupts - * @{ - */ -#define ETH_MSC_INT_RGUF ((uint32_t)0x10020000) /*!< When Rx good unicast frames counter reaches half the maximum value */ -#define ETH_MSC_INT_RFAE ((uint32_t)0x10000040) /*!< When Rx alignment error counter reaches half the maximum value */ -#define ETH_MSC_INT_RFCE ((uint32_t)0x10000020) /*!< When Rx crc error counter reaches half the maximum value */ -/** - * @} - */ - -/** @defgroup ETH_MSC_Registers - * @{ - */ -#define ETH_MSC_CTLR ((uint32_t)0x00000100) -#define ETH_MSC_RISR ((uint32_t)0x00000104) -#define ETH_MSC_TISR ((uint32_t)0x00000108) -#define ETH_MSC_RIMR ((uint32_t)0x0000010C) -#define ETH_MSC_TIMR ((uint32_t)0x00000110) -#define ETH_MSC_SCCNT ((uint32_t)0x0000014C) -#define ETH_MSC_MSCCNT ((uint32_t)0x00000150) -#define ETH_MSC_TGFCNT ((uint32_t)0x00000168) -#define ETH_MSC_RFCECNT ((uint32_t)0x00000194) -#define ETH_MSC_RFAECNT ((uint32_t)0x00000198) -#define ETH_MSC_RGUFCNT ((uint32_t)0x000001C4) - - -/** - * @} - */ - -/** @defgroup ETH_PTP_time_update_mode - * @{ - */ -#define ETH_PTP_FINEMODE ((uint32_t)0x00000001) -#define ETH_PTP_COARSEMODE ((uint32_t)0x00000000) - -/** - * @} - */ - - -/** @defgroup ETH_PTP_Flags - * @{ - */ -#define ETH_PTP_FLAG_TMSARU ((uint32_t)0x00000020) /*!< Addend Register Update */ -#define ETH_PTP_FLAG_TMSITEN ((uint32_t)0x00000010) /*!< Time Stamp Interrupt Trigger Enable */ -#define ETH_PTP_FLAG_TMSSTU ((uint32_t)0x00000008) /*!< Time Stamp Update */ -#define ETH_PTP_FLAG_TMSSTI ((uint32_t)0x00000004) /*!< Time Stamp Initialize */ - -/** - * @} - */ - -/** @defgroup ETH_PTP_time_sign - * @{ - */ -#define ETH_PTP_POSITIVETIME ((uint32_t)0x00000000) -#define ETH_PTP_NEGATIVETIME ((uint32_t)0x80000000) - -/** - * @brief ETH PTP registers - */ -#define ETH_PTP_TSCTLR ((uint32_t)0x00000700) -#define ETH_PTP_SSINCR ((uint32_t)0x00000704) -#define ETH_PTP_TMSHR ((uint32_t)0x00000708) -#define ETH_PTP_TMSLR ((uint32_t)0x0000070C) -#define ETH_PTP_TMSHUR ((uint32_t)0x00000710) -#define ETH_PTP_TMSLUR ((uint32_t)0x00000714) -#define ETH_PTP_TSACNT ((uint32_t)0x00000718) -#define ETH_PTP_ETHR ((uint32_t)0x0000071C) -#define ETH_PTP_ETLR ((uint32_t)0x00000720) - -/** - * @} - */ - - -/** - * @} - */ - - -/** @defgroup ETH_Exported_Functions - * @{ - */ -void ETH_DeInit(void); -void ETH_MDIOInit(void); -uint32_t ETH_Init(ETH_InitPara *ETH_InitParaStruct, u16 PHYAddress); -void ETH_ParaInit(ETH_InitPara *ETH_InitParaStruct); -void ETH_SoftReset(void); -TypeState ETH_GetSoftResetStatus(void); -void ETH_Enable(TypeState NewValue); -uint32_t ETH_HandleTxPkt(uint8_t *pbuf, uint16_t size); -uint32_t ETH_HandleRxPkt(uint8_t *pbuf); -uint32_t ETH_GetRxPktSize(void); -void ETH_DropRxPkt(void); -/** - * @brief PHY - */ -uint16_t ETH_GetPHYRegisterValue(uint16_t PHYAddr, uint16_t PHYReg); -uint32_t ETH_SetPHYRegisterValue(uint16_t PHYAddr, uint16_t PHYReg, uint16_t PHYValue); -uint32_t ETH_PHYLoopBack_Enable(uint16_t PHYAddr, TypeState NewValue); - -/** - * @brief MAC - */ -void ETH_MACTransmission_Enable(TypeState NewValue); -void ETH_MACReception_Enable(TypeState NewValue); -TypeState ETH_GetFlowControlBusyBitState(void); -void ETH_PauseFrameInit(void) ; -void ETH_BackPressureActivation_Enable(TypeState NewValue); -TypeState ETH_GetMACBitState(uint32_t ETH_MAC_FLAG); -TypeState ETH_GetMACIntBitState(uint32_t ETH_MAC_IT); -void ETH_MACINTConfig(uint32_t ETH_MAC_IT, TypeState NewValue); -void ETH_SetMACAddress(uint32_t addr, uint8_t *buf); -void ETH_GetMACAddress(uint32_t addr, uint8_t *buf); -void ETH_MACAddressPerfectFilter_Enable(uint32_t addr, TypeState NewValue); -void ETH_MACAddressFilterConfig(uint32_t addr, uint32_t Filterfield); -void ETH_MACAddressFilterMaskBytesConfig(uint32_t addr, uint32_t addrmask); - -/** - * @brief DMA Tx/Rx descriptors - */ -void ETH_DMATxDescChainModeInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *pTxBuff, uint32_t TxBuffCnt); -void ETH_DMATxDescRingModeInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *pTxBuff1, uint8_t *pTxBuff2, uint32_t TxBuffCnt); -TypeState ETH_GetDMATxDescBitState(ETH_DMADESCTypeDef *DMATxDesc, uint32_t ETH_DMATxDescFlag); -uint32_t ETH_GetDMATxDescCollisionCount(ETH_DMADESCTypeDef *DMATxDesc); -void ETH_SetDMATxDescBusyBit(ETH_DMADESCTypeDef *DMATxDesc); -void ETH_DMATxDescTransmitINTConfig(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue); -void ETH_SetDMATxDescFrameSegment(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_Segment); -void ETH_SetDMATxDescChecksumInsertion(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_Checksum); -void ETH_DMATxDescCRC_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue); -void ETH_DMATxDescEndOfRing_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue); -void ETH_DMATxDescSecondAddressChained_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue); -void ETH_DMATxDescShortFramePadding_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue); -void ETH_DMATxDescTimeStamp_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue); -void ETH_SetDMATxDescBufferSize(ETH_DMADESCTypeDef *DMATxDesc, uint32_t Buffer1Size, uint32_t Buffer2Size); -void ETH_DMARxDescChainModeInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *pRxBuff, uint32_t RxBuffCnt); -void ETH_DMARxDescRingModeInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *pRxBuff1, uint8_t *pRxBuff2, uint32_t RxBuffCnt); -TypeState ETH_GetDMARxDescBitState(ETH_DMADESCTypeDef *DMARxDesc, uint32_t ETH_DMARxDescFlag); -void ETH_SetDMARxDescBusyBit(ETH_DMADESCTypeDef *DMARxDesc); -uint32_t ETH_GetDMARxDescFrameLength(ETH_DMADESCTypeDef *DMARxDesc); -void ETH_DMARxDescReceiveINTConfig(ETH_DMADESCTypeDef *DMARxDesc, TypeState NewValue); -void ETH_DMARxDescEndOfRing_Enable(ETH_DMADESCTypeDef *DMARxDesc, TypeState NewValue); -void ETH_DMARxDescSecondAddressChained_Enable(ETH_DMADESCTypeDef *DMARxDesc, TypeState NewValue); -uint32_t ETH_GetDMARxDescBufferSize(ETH_DMADESCTypeDef *DMARxDesc, uint32_t DMARxDesc_Buffer); - -/** - * @brief DMA - */ -TypeState ETH_GetDMABitState(uint32_t ETH_DMA_FLAG); -void ETH_DMAClearBitState(uint32_t ETH_DMA_FLAG); -TypeState ETH_GetDMAIntBitState(uint32_t ETH_DMA_IT); -void ETH_DMAClearIntBitState(uint32_t ETH_DMA_IT); -uint32_t ETH_GetTransmitProcessState(void); -uint32_t ETH_GetReceiveProcessState(void); -void ETH_CleanTransmitFIFO(void); -TypeState ETH_GetFlushTransmitFIFOStatus(void); -void ETH_DMATransmission_Enable(TypeState NewValue); -void ETH_DMAReception_Enable(TypeState NewValue); -void ETH_DMAINTConfig(uint32_t ETH_DMA_IT, TypeState NewValue); -TypeState ETH_GetDMAOverflowStatus(uint32_t ETH_DMA_Overflow); -uint32_t ETH_GetRxOverflowMissedFrameCounter(void); -uint32_t ETH_GetBufferUnavailableMissedFrameCounter(void); -uint32_t ETH_GetCurrentTxDescStartAddress(void); -uint32_t ETH_GetCurrentRxDescStartAddress(void); -uint32_t ETH_GetCurrentTxBufferAddress(void); -uint32_t ETH_GetCurrentRxBufferAddress(void); -void ETH_ResumeDMATransmission(void); -void ETH_ResumeDMAReception(void); - -/** - * @brief WUM - */ -void ETH_ResetWakeUpFrameFilterRegister(void); -void ETH_SetWakeUpFrameFilterRegister(uint32_t *pBuffer); -void ETH_GlobalUnicastWakeUp_Enable(TypeState NewValue); -TypeState ETH_GetWUMBitState(uint32_t ETH_WUM_FLAG); -void ETH_WakeUpFrameDetection_Enable(TypeState NewValue); -void ETH_MagicPacketDetection_Enable(TypeState NewValue); -void ETH_PowerDown_Enable(TypeState NewValue); - -/** - * @brief MSC - */ -void ETH_MSCCounterFreeze_Enable(TypeState NewValue); -void ETH_MSCResetOnRead_Enable(TypeState NewValue); -void ETH_MSCCounterRollover_Enable(TypeState NewValue); -void ETH_ResetMSCCounters(void); -void ETH_MSCINTConfig(uint32_t ETH_MSC_IT, TypeState NewValue); -TypeState ETH_GetMSCINTStatus(uint32_t ETH_MSC_IT); -uint32_t ETH_GetMSCRegister(uint32_t ETH_MSC_Register); - -/** - * @brief PTP - */ -void ETH_PTPTimeStampAddendUpdate(void); -void ETH_PTPTimeStampIntTrigger_Enable(TypeState NewValue); -void ETH_PTPTimeStampUpdate_Enable(TypeState NewValue); -void ETH_PTPTimeStampInit(void); -void ETH_PTPUpdateModeConfig(uint32_t UpdateMode); -void ETH_PTPTimeStamp_Enable(TypeState NewValue); -TypeState ETH_GetPTPBitState(uint32_t ETH_PTP_FLAG); -void ETH_SetPTPSubSecondIncrement(uint32_t SubSecond); -void ETH_SetPTPUpdateTimeValue(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue); -void ETH_SetPTPTimeStampAddend(uint32_t add); -void ETH_SetPTPTargetTime(uint32_t HighReg_Value, uint32_t LowReg_Value); -uint32_t ETH_GetPTPRegister(uint32_t ETH_PTPRegister); -void ETH_DMAPTPTxDescChainModeInit(ETH_DMADESCTypeDef *DMATxDescTab, ETH_DMADESCTypeDef *DMAPTPTxDescTab, - uint8_t *pTxBuff, uint32_t TxBuffCnt); -void ETH_DMAPTPRxDescChainModeInit(ETH_DMADESCTypeDef *DMARxDescTab, ETH_DMADESCTypeDef *DMAPTPRxDescTab, - uint8_t *pRxBuff, uint32_t RxBuffCnt); -uint32_t ETH_HandlePTPTxPkt(uint8_t *pbuf, uint16_t size, uint32_t *PTPTxTab); -uint32_t ETH_HandlePTPRxPkt(uint8_t *pbuf, uint32_t *PTPRxTab); - - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_ETH_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exmc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exmc.h deleted file mode 100644 index 864efe9371..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exmc.h +++ /dev/null @@ -1,454 +0,0 @@ -/** - ****************************************************************************** - * @brief EXMC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_EXMC_H -#define __GD32F10X_EXMC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup EXMC - * @{ - */ - -/** @defgroup EXMC_Exported_Types - * @{ - */ - -/** - * @brief Initial Timing Parameters For NOR/SRAM Banks - */ -typedef struct { - uint32_t EXMC_AsynAccessMode; /*!< The asynchronous access mode, detailed in @ref EXMC_AsynAccess_Mode*/ - uint32_t EXMC_SynDataLatency; /*!< The number of CLK cycles to configure the data latency, - which may assume a value between 0x0 and 0xF. */ - uint32_t EXMC_SynCLKDivision; /*!< The number of HCLK cycles to configure the clock divide ratio, - which can be a value between 0x0 and 0xF. */ - uint32_t EXMC_BusLatency; /*!< The number of HCLK cycles to configure the bus latency, - which can be a value between 0x0 and 0xF. */ - uint32_t EXMC_AsynDataSetupTime; /*!< The number of HCLK cycles to configure the data setup time - while in the asynchronous access mode, which can be a value - between 0x00 and 0xFF. */ - uint32_t EXMC_AsynAddressHoldTime; /*!< The number of HCLK cycles to configure the address hold time - while in the asynchronous access mode, which can be a value - between 0x0 and 0xF. */ - uint32_t EXMC_AsynAddressSetupTime; /*!< The number of HCLK cycles to configure the data setup time - while in the asynchronous access mode, which can be a value - between 0x0 and 0xF. */ -} EXMC_NORSRAMTimingInitPara; - -/** - * @brief EXMC NOR/SRAM Init structure definition - */ -typedef struct { - uint32_t EXMC_NORSRAMBank; /*!< The specified region of NORSRAM Bank1, - choose one from @ref EXMC_NORSRAMBank. */ - uint32_t EXMC_WriteMode; /*!< The write mode, details in @ref EXMC_WriteMode. */ - uint32_t EXMC_ExtendedMode; /*!< Enable or Disable the extended mode, details in - @ref EXMC_ExtendedMode. */ - uint32_t EXMC_AsynWait; /*!< Enable or disable the asynchronous wait feature,detial - in @ref EXMC_AsynWait. */ - uint32_t EXMC_NWAITSignal; /*!< Enable or Disable the NWAIT signal while in synchronous - bust mode, details in @ref EXMC_NWAITSignal. */ - uint32_t EXMC_MemoryWrite; /*!< Enable or Disable the write operation, details in - @ref EXMC_MemoryWrite. */ - uint32_t EXMC_NWAITConfig; /*!< NWAIT signal configuration, details in @ref EXMC_NWAITConfig */ - uint32_t EXMC_WrapBurstMode; /*!< Enable or Disable the wrap burst mode, details in - @ref EXMC_WrapBurstMode. */ - uint32_t EXMC_NWAITPolarity; /*!< Specifies the polarity of NWAIT signal from memory, - details in @ref EXMC_NWAITPolarity. */ - uint32_t EXMC_BurstMode; /*!< Enable or Disable the burst mode, details in - @ref EXMC_BurstMode. */ - uint32_t EXMC_DatabusWidth; /*!< Specifies the databus width of external memory, - details in @ref EXMC_DatabusWidth. */ - uint32_t EXMC_MemoryType; /*!< Specifies the type of external memory, details in - @ref EXMC_MemoryType. */ - uint32_t EXMC_AddressDataMux; /*!< Specifies whether the data bus and address bus are multiplexed - or not,details in @ref EXMC_AddressDataMux. */ - - EXMC_NORSRAMTimingInitPara *EXMC_ReadWriteTimingParaStruct; /*!< The struct EXMC_NORSRAMTimingInitPara pointer,which is - used to define the timing parameters for read and write - if the ExtendedMode is not used or define the timing - parameters for read if the ExtendedMode is used. */ - - EXMC_NORSRAMTimingInitPara *EXMC_WriteTimingParaStruct; /*!< The struct EXMC_NORSRAMTimingInitPara pointer,which is - only used to define the timing parameters for write when - the ExtendedMode is used. */ -} EXMC_NORSRAMInitPara; - -/** - * @brief Timing parameters For EXMC NAND and PCCARD Banks - */ - -typedef struct { - uint32_t EXMC_DatabusHiZTime; /*!< The number of HCLK cycles to configure the dadtabus HiZ time - for write operation, which can be a value between 0x00 and 0xFF. */ - uint32_t EXMC_HoldTime; /*!< The number of HCLK cycles to configure the address hold time - (or the data hold time for write operation),which can be a value - between 0x00 and 0xFF. */ - uint32_t EXMC_WaitTime; /*!< The number of HCLK cycles to configure the minimum wait time, - which can be a value between 0x00 and 0xFF. */ - uint32_t EXMC_SetupTime; /*!< The number of HCLK cycles to configure the address setup time , - which can be a value between 0x00 and 0xFF. */ -} EXMC_NAND_PCCARDTimingInitPara; - -/** - * @brief EXMC NAND Init structure definition - */ -typedef struct { - uint32_t EXMC_NANDBank; /*!< The specified Bank of NAND FLASH, choose one - from @ref EXMC_NANDBank. */ - uint32_t EXMC_ECCSize; /*!< The page size for the ECC calculation,details - in @ref EXMC_ECCSize. */ - uint32_t EXMC_ATRLatency; /*!< The number of HCLK cycles to configure the - latency of ALE low to RB low, which can be a - value between 0x0 and 0xF. */ - uint32_t EXMC_CTRLatency; /*!< The number of HCLK cycles to configure the - latency of CLE low to RB low, which can be a - value between 0x0 and 0xF. */ - uint32_t EXMC_ECCLogic; /*!< Enable or Disable the ECC calculation logic, - details in @ref EXMC_ECCLogic. */ - uint32_t EXMC_DatabusWidth; /*!< the NAND flash databus width, details in - @ref EXMC_DatabusWidth. */ - uint32_t EXMC_WaitFeature; /*!< Enables or Disables the Wait feature,details - in @ref EXMC_WaitFeature. */ - EXMC_NAND_PCCARDTimingInitPara *EXMC_CommonSpaceTimingParaStruct; /*!< The struct EXMC_NAND_PCCARDTimingInitPara - pointer, which is used to define the timing - parameters for NAND flash Common Space. */ - EXMC_NAND_PCCARDTimingInitPara *EXMC_AttributeSpaceTimingParaStruct; /*!< The struct EXMC_NAND_PCCARDTimingInitPara - pointer, which is used to define the timing - parameters for NAND flash Attribute Space. */ -} EXMC_NANDInitPara; - -/** - * @brief EXMC PCCARD Init structure definition - */ - -typedef struct { - uint32_t EXMC_ATRLatency; /*!< The number of HCLK cycles to configure - the latency of ALE low to RB low, which can - be a value between 0x0 and 0xF. */ - uint32_t EXMC_CTRLatency; /*!< The number of HCLK cycles to configure - the latency of CLE low to RB low, which can - be a value between 0x0 and 0xF. */ - uint32_t EXMC_WaitFeature; /*!< Enables or Disables the Wait feature,details - in @ref EXMC_WaitFeature. */ - EXMC_NAND_PCCARDTimingInitPara *EXMC_CommonSpaceTimingParaStruct; /*!< The struct EXMC_NAND_PCCARDTimingInitPara - pointer, which is used to define the timing - parameters for PC CARD Common Space. */ - EXMC_NAND_PCCARDTimingInitPara *EXMC_AttributeSpaceTimingParaStruct; /*!< The struct EXMC_NAND_PCCARDTimingInitPara - pointer, which is used to define the timing - parameters for PC CARD Attribute Space. */ - EXMC_NAND_PCCARDTimingInitPara *EXMC_IOSpaceTimingParaStruct; /*!< The struct EXMC_NAND_PCCARDTimingInitPara - pointer, which is used to define the timing - parameters for PC CARD I/O Space. */ -} EXMC_PCCARDInitPara; - -/** - * @} - */ - -/** @defgroup EXMC_Exported_Constants - * @{ - */ - -/** @defgroup EXMC_NORSRAMBank - * @{ - */ -#define EXMC_BANK1_NORSRAM1 ((uint32_t)0x00000001) -#define EXMC_BANK1_NORSRAM2 ((uint32_t)0x00000002) -#define EXMC_BANK1_NORSRAM3 ((uint32_t)0x00000003) -#define EXMC_BANK1_NORSRAM4 ((uint32_t)0x00000004) -/** - * @} - */ - -/** @defgroup EXMC_NANDBank - * @{ - */ -#define EXMC_BANK2_NAND ((uint32_t)0x00000010) -#define EXMC_BANK3_NAND ((uint32_t)0x00000100) -/** - * @} - */ - -/** @defgroup EXMC_PCCARD_Bank - * @{ - */ -#define EXMC_BANK4_PCCARD ((uint32_t)0x00001000) - -/** - * @} - */ - -/** @defgroup NORSRAM_Controller - * @{ - */ - -/** @defgroup EXMC_AddressDataMux - * @{ - */ -#define EXMC_ADDRESS_DATA_MUX_DISABLE ((uint32_t)0x00000000) -#define EXMC_ADDRESS_DATA_MUX_ENABLE ((uint32_t)0x00000002) - -/** - * @} - */ - -/** @defgroup EXMC_MemoryType - * @{ - */ -#define EXMC_MEMORY_TYPE_SRAM ((uint32_t)0x00000000) -#define EXMC_MEMORY_TYPE_PSRAM ((uint32_t)0x00000004) -#define EXMC_MEMORY_TYPE_NOR ((uint32_t)0x00000008) - -/** - * @} - */ - -/** @defgroup EXMC_DatabusWidth - * @{ - */ -#define EXMC_DATABUS_WIDTH_8B ((uint32_t)0x00000000) -#define EXMC_DATABUS_WIDTH_16B ((uint32_t)0x00000010) - -/** - * @} - */ - -/** @defgroup EXMC_NORFlash_Access - * @{ - */ -#define EXMC_NORFLASH_ACCESS_DISABLE ((uint32_t)0x00000000) -#define EXMC_NORFLASH_ACCESS_ENABLE ((uint32_t)0x00000040) - -/** - * @} - */ - -/** @defgroup EXMC_BurstMode - * @{ - */ -#define EXMC_BURST_MODE_DISABLE ((uint32_t)0x00000000) -#define EXMC_BURST_MODE_ENABLE ((uint32_t)0x00000100) - -/** - * @} - */ - -/** @defgroup EXMC_AsynWait - * @{ - */ -#define EXMC_ASYN_WAIT_DISABLE ((uint32_t)0x00000000) -#define EXMC_ASYN_WAIT_ENABLE ((uint32_t)0x00008000) - -/** - * @} - */ - -/** @defgroup EXMC_NWAITPolarity - * @{ - */ -#define EXMC_NWAIT_POLARITY_LOW ((uint32_t)0x00000000) -#define EXMC_NWAIT_POLARITY_HIGH ((uint32_t)0x00000200) - -/** - * @} - */ - -/** @defgroup EXMC_WrapBurstMode - * @{ - */ -#define EXMC_WRAP_BURST_MODE_DISABLE ((uint32_t)0x00000000) -#define EXMC_WRAP_BURST_MODE_ENABLE ((uint32_t)0x00000400) - -/** - * @} - */ - -/** @defgroup EXMC_NWAITConfig - * @{ - */ -#define EXMC_NWAIT_CONFIG_BEFORE ((uint32_t)0x00000000) -#define EXMC_NWAIT_CONFIG_DURING ((uint32_t)0x00000800) - -/** - * @} - */ - -/** @defgroup EXMC_MemoryWrite - * @{ - */ -#define EXMC_MEMORY_WRITE_DISABLE ((uint32_t)0x00000000) -#define EXMC_MEMORY_WRITE_ENABLE ((uint32_t)0x00001000) - -/** - * @} - */ - -/** @defgroup EXMC_NWAITSignal - * @{ - */ -#define EXMC_NWAIT_SIGNAL_DISABLE ((uint32_t)0x00000000) -#define EXMC_NWAIT_SIGNAL_ENABLE ((uint32_t)0x00002000) - -/** - * @} - */ - -/** @defgroup EXMC_ExtendedMode - * @{ - */ -#define EXMC_EXTENDED_MODE_DISABLE ((uint32_t)0x00000000) -#define EXMC_EXTENDED_MODE_ENABLE ((uint32_t)0x00004000) - -/** - * @} - */ - -/** @defgroup EXMC_WriteMode - * @{ - */ -#define EXMC_ASYN_WRITE ((uint32_t)0x00000000) -#define EXMC_SYN_WRITE ((uint32_t)0x00080000) - -/** - * @} - */ - -/** @defgroup EXMC_AsynAccess_Mode - * @{ - */ -#define EXMC_ACCESS_MODE_A ((uint32_t)0x00000000) -#define EXMC_ACCESS_MODE_B ((uint32_t)0x10000000) -#define EXMC_ACCESS_MODE_C ((uint32_t)0x20000000) -#define EXMC_ACCESS_MODE_D ((uint32_t)0x30000000) - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup NAND_PCCARD_Controller - * @{ - */ - -/** @defgroup EXMC_WaitFeature - * @{ - */ -#define EXMC_WAIT_FEATURE_DISABLE ((uint32_t)0x00000000) -#define EXMC_WAIT_FEATURE_ENABLE ((uint32_t)0x00000002) - -/** - * @} - */ - -/** @defgroup EXMC_ECCLogic - * @{ - */ -#define EXMC_ECC_LOGIC_DISABLE ((uint32_t)0x00000000) -#define EXMC_ECC_LOGIC_ENABLE ((uint32_t)0x00000040) - -/** - * @} - */ - -/** @defgroup EXMC_ECCSize - * @{ - */ -#define EXMC_ECC_SIZE_256BYTES ((uint32_t)0x00000000) -#define EXMC_ECC_SIZE_512BYTES ((uint32_t)0x00020000) -#define EXMC_ECC_SIZE_1024BYTES ((uint32_t)0x00040000) -#define EXMC_ECC_SIZE_2048BYTES ((uint32_t)0x00060000) -#define EXMC_ECC_SIZE_4096BYTES ((uint32_t)0x00080000) -#define EXMC_ECC_SIZE_8192BYTES ((uint32_t)0x000A0000) - -/** - * @} - */ - -/** @defgroup EXMC_Interrupt_Source - * @{ - */ -#define EXMC_INT_RISE ((uint32_t)0x00000008) -#define EXMC_INT_LEVEL ((uint32_t)0x00000010) -#define EXMC_INT_FALL ((uint32_t)0x00000020) - -/** - * @} - */ - -/** @defgroup EXMC_FLAG - * @{ - */ -#define EXMC_FLAG_RISE ((uint32_t)0x00000001) -#define EXMC_FLAG_LEVEL ((uint32_t)0x00000002) -#define EXMC_FLAG_FALL ((uint32_t)0x00000004) -#define EXMC_FLAG_FIFOE ((uint32_t)0x00000040) - -/** - * @} - */ - -/** - * @} - */ - -/** -* @} -*/ - -/** @defgroup EXMC_Exported_Functions - * @{ - */ -void EXMC_NORSRAM_DeInit(uint32_t EXMC_NORSRAMBank); -void EXMC_NAND_DeInit(uint32_t EXMC_NANDBank); -void EXMC_PCCARD_DeInit(void); -void EXMC_NORSRAM_Init(EXMC_NORSRAMInitPara *EXMC_NORSRAMInitParaStruct); -void EXMC_NAND_Init(EXMC_NANDInitPara *EXMC_NANDInitParaStruct); -void EXMC_PCCARD_Init(EXMC_PCCARDInitPara *EXMC_PCCARDInitParaStruct); -void EXMC_NORSRAMStruct_Init(EXMC_NORSRAMInitPara *EXMC_NORSRAMInitParaStruct); -void EXMC_NANDStruct_Init(EXMC_NANDInitPara *EXMC_NANDInitParaStruct); -void EXMC_PCCARDStruct_Init(EXMC_PCCARDInitPara *EXMC_PCCARDInitParaStruct); -void EXMC_NORSRAM_Enable(uint32_t EXMC_NORSRAMBank, TypeState NewValue); -void EXMC_NAND_Enable(uint32_t EXMC_NANDBank, TypeState NewValue); -void EXMC_PCCARD_Enable(TypeState NewValue); -void EXMC_NANDECC_Enable(uint32_t EXMC_NANDBank, TypeState NewValue); -uint32_t EXMC_GetECC(uint32_t EXMC_NANDBank); -void EXMC_INTConfig(uint32_t EXMC_PCNANDBank, uint32_t EXMC_INT, TypeState NewValue); -TypeState EXMC_GetBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_FLAG); -void EXMC_ClearBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_FLAG); -TypeState EXMC_GetIntBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_INT); -void EXMC_ClearIntBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_INT); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10x_EXMC_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exti.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exti.h deleted file mode 100644 index b36af10142..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_exti.h +++ /dev/null @@ -1,130 +0,0 @@ -/** - ****************************************************************************** - * @brief EXTI header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_EXTI_H -#define __GD32F10X_EXTI_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup EXTI - * @{ - */ - -/** @defgroup EXTI_Exported_Types - * @{ - */ - -/** - * @brief EXTI Mode enumeration - */ -typedef enum { - EXTI_Mode_Interrupt = 0x00, - EXTI_Mode_Event = 0x04 -} EXTI_ModePara; - -/** - * @brief EXTI Trigger enumeration - */ -typedef enum { - EXTI_Trigger_Rising = 0x08, - EXTI_Trigger_Falling = 0x0C, - EXTI_Trigger_Rising_Falling = 0x10 -} EXTI_TriggerPara; - -/** - * @brief EXTI Initial Parameters - */ -typedef struct { - uint32_t EXTI_LINE; /*!< The selection of EXTI lines. */ - EXTI_ModePara EXTI_Mode; /*!< The mode for the EXTI lines, detailed in @ref EXTIMode_Para. */ - EXTI_TriggerPara EXTI_Trigger; /*!< The trigger edge for the EXTI lines, detailed in EXTI_TriggerPara. */ - TypeState EXTI_LINEEnable; /*!< The new value of the selected EXTI lines. */ -} EXTI_InitPara; - -/** - * @} - */ - -/** @defgroup EXTI_Exported_Constants - * @{ - */ - -/** @defgroup EXTI_lines - * @{ - */ -#define EXTI_LINE0 ((uint32_t)0x00000001) /*!< External interrupt line 0 */ -#define EXTI_LINE1 ((uint32_t)0x00000002) /*!< External interrupt line 1 */ -#define EXTI_LINE2 ((uint32_t)0x00000004) /*!< External interrupt line 2 */ -#define EXTI_LINE3 ((uint32_t)0x00000008) /*!< External interrupt line 3 */ -#define EXTI_LINE4 ((uint32_t)0x00000010) /*!< External interrupt line 4 */ -#define EXTI_LINE5 ((uint32_t)0x00000020) /*!< External interrupt line 5 */ -#define EXTI_LINE6 ((uint32_t)0x00000040) /*!< External interrupt line 6 */ -#define EXTI_LINE7 ((uint32_t)0x00000080) /*!< External interrupt line 7 */ -#define EXTI_LINE8 ((uint32_t)0x00000100) /*!< External interrupt line 8 */ -#define EXTI_LINE9 ((uint32_t)0x00000200) /*!< External interrupt line 9 */ -#define EXTI_LINE10 ((uint32_t)0x00000400) /*!< External interrupt line 10 */ -#define EXTI_LINE11 ((uint32_t)0x00000800) /*!< External interrupt line 11 */ -#define EXTI_LINE12 ((uint32_t)0x00001000) /*!< External interrupt line 12 */ -#define EXTI_LINE13 ((uint32_t)0x00002000) /*!< External interrupt line 13 */ -#define EXTI_LINE14 ((uint32_t)0x00004000) /*!< External interrupt line 14 */ -#define EXTI_LINE15 ((uint32_t)0x00008000) /*!< External interrupt line 15 */ - -#define EXTI_LINE16 ((uint32_t)0x00010000) /*!< External interrupt line 16 - Connected to the LVD */ -#define EXTI_LINE17 ((uint32_t)0x00020000) /*!< External interrupt line 17 - Connected to the RTC Alarm */ -#define EXTI_LINE18 ((uint32_t)0x00040000) /*!< External interrupt line 18 - Connected to the USB Wakeup */ -#define EXTI_LINE19 ((uint32_t)0x00080000) /*!< External interrupt line 19 - Connected to the Ethernet Wakeup */ - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup EXTI_Exported_Functions - * @{ - */ -void EXTI_DeInit(EXTI_InitPara *EXTI_InitParaStruct); -void EXTI_Init(EXTI_InitPara *EXTI_InitParaStruct); -void EXTI_SWINT_Enable(uint32_t EXTI_LINE); -TypeState EXTI_GetBitState(uint32_t EXTI_LINE); -void EXTI_ClearBitState(uint32_t EXTI_LINE); -TypeState EXTI_GetIntBitState(uint32_t EXTI_LINE); -void EXTI_ClearIntBitState(uint32_t EXTI_LINE); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_EXTI_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_fmc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_fmc.h deleted file mode 100644 index e57bf6b951..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_fmc.h +++ /dev/null @@ -1,263 +0,0 @@ -/** - ****************************************************************************** - * @brief FMC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_FMC_H -#define __GD32F10X_FMC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup FMC - * @{ - */ - -/* Exported types ------------------------------------------------------------*/ - -/** @defgroup FMC_Exported_Types - * @{ - */ - -/** - * @brief FMC State - */ -typedef enum { - FMC_READY, - FMC_BSY, - FMC_WRPERR, - FMC_PGERR, - FMC_TIMEOUT_ERR -} FMC_State; - -/** - * @} - */ - -/* Exported constants --------------------------------------------------------*/ - -/** @defgroup FMC_Exported_Constants - * @{ - */ - -/** @defgroup FMC_Interrupts - * @{ - */ - -#define FMC_INT_EOP FMC_CMR_ENDIE /*!< End of programming interrupt source */ -#define FMC_INT_ERR FMC_CMR_ERIE /*!< Error interrupt source */ -#define FMC_INT_B2_EOP ((uint32_t)0x80000400) /*!< Bank2 End of programming interrupt source */ -#define FMC_INT_B2_ERR ((uint32_t)0x80001000) /*!< Bank2 Error interrupt source */ -/** - * @} - */ - -/** @defgroup FMC_Option_Bytes_Write_Protection - * @{ - */ - - -#define WRP_SECTOR0 ((uint32_t)0x00000001) /*!< Write protection of sector 0 */ -#define WRP_SECTOR1 ((uint32_t)0x00000002) /*!< Write protection of sector 1 */ -#define WRP_SECTOR2 ((uint32_t)0x00000004) /*!< Write protection of sector 2 */ -#define WRP_SECTOR3 ((uint32_t)0x00000008) /*!< Write protection of sector 3 */ -#define WRP_SECTOR4 ((uint32_t)0x00000010) /*!< Write protection of sector 4 */ -#define WRP_SECTOR5 ((uint32_t)0x00000020) /*!< Write protection of sector 5 */ -#define WRP_SECTOR6 ((uint32_t)0x00000040) /*!< Write protection of sector 6 */ -#define WRP_SECTOR7 ((uint32_t)0x00000080) /*!< Write protection of sector 7 */ -#define WRP_SECTOR8 ((uint32_t)0x00000100) /*!< Write protection of sector 8 */ -#define WRP_SECTOR9 ((uint32_t)0x00000200) /*!< Write protection of sector 9 */ -#define WRP_SECTOR10 ((uint32_t)0x00000400) /*!< Write protection of sector 10 */ -#define WRP_SECTOR11 ((uint32_t)0x00000800) /*!< Write protection of sector 11 */ -#define WRP_SECTOR12 ((uint32_t)0x00001000) /*!< Write protection of sector 12 */ -#define WRP_SECTOR13 ((uint32_t)0x00002000) /*!< Write protection of sector 13 */ -#define WRP_SECTOR14 ((uint32_t)0x00004000) /*!< Write protection of sector 14 */ -#define WRP_SECTOR15 ((uint32_t)0x00008000) /*!< Write protection of sector 15 */ -#define WRP_SECTOR16 ((uint32_t)0x00010000) /*!< Write protection of sector 16 */ -#define WRP_SECTOR17 ((uint32_t)0x00020000) /*!< Write protection of sector 17 */ -#define WRP_SECTOR18 ((uint32_t)0x00040000) /*!< Write protection of sector 18 */ -#define WRP_SECTOR19 ((uint32_t)0x00080000) /*!< Write protection of sector 19 */ -#define WRP_SECTOR20 ((uint32_t)0x00100000) /*!< Write protection of sector 20 */ -#define WRP_SECTOR21 ((uint32_t)0x00200000) /*!< Write protection of sector 21 */ -#define WRP_SECTOR22 ((uint32_t)0x00400000) /*!< Write protection of sector 22 */ -#define WRP_SECTOR23 ((uint32_t)0x00800000) /*!< Write protection of sector 23 */ -#define WRP_SECTOR24 ((uint32_t)0x01000000) /*!< Write protection of sector 24 */ -#define WRP_SECTOR25 ((uint32_t)0x02000000) /*!< Write protection of sector 25 */ -#define WRP_SECTOR26 ((uint32_t)0x04000000) /*!< Write protection of sector 26 */ -#define WRP_SECTOR27 ((uint32_t)0x08000000) /*!< Write protection of sector 27 */ -#define WRP_SECTOR28 ((uint32_t)0x10000000) /*!< Write protection of sector 28 */ -#define WRP_SECTOR29 ((uint32_t)0x20000000) /*!< Write protection of sector 29 */ -#define WRP_SECTOR30 ((uint32_t)0x40000000) /*!< Write protection of sector 30 */ -#define WRP_SECTOR31 ((uint32_t)0x80000000) /*!< Write protection of sector 31 */ - -#define WRP_ALLSECTORS ((uint32_t)0xFFFFFFFF) /*!< Write protection of all Sectors */ - -/** - * @} - */ - -/** @defgroup FMC_Option_Bytes_Read_Protection - * @{ - */ - - -/** - * @brief FMC_Read Protection Level - */ -#define RDP_LEVEL_0 ((uint8_t)0xA5) -#define RDP_LEVEL_1 ((uint8_t)0xBB) - -/** - * @} - */ - -/** @defgroup FMC_Option_Bytes_IWatchdog - * @{ - */ -#define OB_IWDG_SW ((uint8_t)0x01) /*!< Software IWDG selected */ -#define OB_IWDG_HW ((uint8_t)0x00) /*!< Hardware IWDG selected */ - -/** - * @} - */ - -/** @defgroup FMC_Option_Bytes_nRST_DEEPSLEEP - * @{ - */ -#define OB_DEEPSLEEP_NORST ((uint8_t)0x02) /*!< No reset generated when entering in DEEPSLEEP */ -#define OB_DEEPSLEEP_RST ((uint8_t)0x00) /*!< Reset generated when entering in DEEPSLEEP */ - -/** - * @} - */ - -/** @defgroup FMC_Option_Bytes_nRST_STDBY - * @{ - */ -#define OB_STDBY_NORST ((uint8_t)0x04) /*!< No reset generated when entering in STANDBY */ -#define OB_STDBY_RST ((uint8_t)0x00) /*!< Reset generated when entering in STANDBY */ - -/** - * @} - */ - -/** @defgroup FMC_Option_Bytes_BOOT - * @{ - */ -#define OB_BOOT_B1 ((uint8_t)0x08) /*!< BOOT from Bank1 */ -#define OB_BOOT_B2 ((uint8_t)0x00) /*!< BOOT from Bank2 */ -#define OB_USER_BFB2 ((uint16_t)0x0008) /*!< Configure BOOT from Bank1 */ -/** - * @} - */ - - - -/** @defgroup FMC_Flags - * @{ - */ - -#define FMC_FLAG_BSY FMC_CSR_BUSY /*!< FMC Busy flag */ -#define FMC_FLAG_PERR FMC_CSR_PGEF /*!< FMC Programming error flag */ -#define FMC_FLAG_WERR FMC_CSR_WPEF /*!< FMC Write protected error flag */ -#define FMC_FLAG_EOP FMC_CSR_ENDF /*!< FMC End of Programming flag */ -#define FMC_FLAG_OPTERR ((uint32_t)0x00000001) /*!< FMC Option Byte error flag */ -#define FMC_FLAG_B2_BSY ((uint32_t)0x80000001) /*!< FMC Busy flag */ -#define FMC_FLAG_B2_PERR ((uint32_t)0x80000004) /*!< FMC Programming error flag */ -#define FMC_FLAG_B2_WERR ((uint32_t)0x80000010) /*!< FMC Write protected error flag */ -#define FMC_FLAG_B2_EOP ((uint32_t)0x80000020) /*!< FMC End of Programming flag */ -/** - * @} - */ - -/** @defgroup FMC_Timeout_definition - * @{ - */ -#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000) -/** - * @} - */ -/* FMC BANK address */ -#define FMC_B1_END_ADDRESS ((uint32_t)0x807FFFF) -#define FMC_BANK1_SIZE 0x0200 -#define FMC_SIZE (*(uint16_t *)0x1ffff7e0) -/** - * @} - */ - -/** @defgroup FMC_Exported_Functions - * @{ - */ - -/** - * @brief FMC memory functions. - */ -/* FMC Main Memory Programming functions *****************************************/ -void FMC_Unlock(void); -void FMC_UnlockB1(void); -void FMC_UnlockB2(void); -void FMC_Lock(void); -void FMC_LockB1(void); -void FMC_LockB2(void); -FMC_State FMC_ErasePage(uint32_t Page_Address); -FMC_State FMC_MassErase(void); -FMC_State FMC_MassB1Erase(void); -FMC_State FMC_MassB2Erase(void); -FMC_State FMC_ProgramWord(uint32_t Address, uint32_t Data); - -/* FMC Option Bytes Programming functions *****************************************/ -void FMC_OB_Unlock(void); -void FMC_OB_Lock(void); -void FMC_OB_Reset(void); -FMC_State FMC_OB_Erase(void); -FMC_State FMC_OB_EnableWRP(uint32_t OB_WRP); -FMC_State FMC_ReadOutProtection(TypeState NewValue); -FMC_State FMC_OB_RDPConfig(uint8_t OB_RDP); -FMC_State FMC_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_DEEPSLEEP, uint8_t OB_STDBY); -FMC_State FMC_OB_BOOTConfig(uint8_t OB_BOOT); -FMC_State FMC_OB_WriteUser(uint8_t OB_USER); -FMC_State FMC_ProgramOptionByteData(uint32_t Address, uint8_t Data); -uint8_t FMC_OB_GetUser(void); -uint32_t FMC_OB_GetWRP(void); -TypeState FMC_OB_GetRDP(void); - -/* FMC Interrupts and flags management functions **********************************/ -void FMC_INTConfig(uint32_t FMC_INT, TypeState NewValue); -TypeState FMC_GetBitState(uint32_t FMC_FLAG); -void FMC_ClearBitState(uint32_t FMC_FLAG); -FMC_State FMC_GetState(void); -FMC_State FMC_GetB1State(void); -FMC_State FMC_GetB2State(void); -FMC_State FMC_WaitReady(uint32_t uCount); -FMC_State FMC_B1_WaitReady(uint32_t uCount); -FMC_State FMC_B2_WaitReady(uint32_t uCount); - - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_FMC_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_gpio.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_gpio.h deleted file mode 100644 index d32c81a7f9..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_gpio.h +++ /dev/null @@ -1,281 +0,0 @@ -/** - ****************************************************************************** - * @brief GPIO header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10x_GPIO_H -#define __GD32F10x_GPIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup GPIO - * @{ - */ - -/** @defgroup GPIO_Exported_Types - * @{ - */ - -/** - * @brief Output_Maximum_frequency_enumeration - */ -typedef enum { - GPIO_SPEED_10MHZ = 1, - GPIO_SPEED_2MHZ, - GPIO_SPEED_50MHZ -} GPIO_SpeedPara; - -/** - * @brief GPIO_Mode_enumeration - */ -typedef enum { - GPIO_MODE_AIN = 0x0, - GPIO_MODE_IN_FLOATING = 0x04, - GPIO_MODE_IPD = 0x28, - GPIO_MODE_IPU = 0x48, - GPIO_MODE_OUT_OD = 0x14, - GPIO_MODE_OUT_PP = 0X10, - GPIO_MODE_AF_OD = 0X1C, - GPIO_MODE_AF_PP = 0X18 -} GPIO_ModePara; - -/** - * @brief GPIO Initial Parameters - */ -typedef struct { - uint16_t GPIO_Pin; /*!< The GPIO pins to be configured. choose several from @ref GPIO_pins_define */ - GPIO_SpeedPara GPIO_Speed; /*!< The speed for This parameter can be a value of @ref GPIOSpeed_TypeDef */ - GPIO_ModePara GPIO_Mode; /*!< The operating mode for the selected pins. choose one from @ref GPIO_ModePara */ -} GPIO_InitPara; - -/** - * @brief Bit_State_enumeration - */ -typedef enum { - Bit_RESET = 0, - Bit_SET -} BitState; - -/** - * @} - */ - -/** @defgroup GPIO_Exported_Constants - * @{ - */ - -/** @defgroup GPIO_pins_define - * @{ - */ -#define GPIO_PIN_0 ((uint16_t)0x0001) -#define GPIO_PIN_1 ((uint16_t)0x0002) -#define GPIO_PIN_2 ((uint16_t)0x0004) -#define GPIO_PIN_3 ((uint16_t)0x0008) -#define GPIO_PIN_4 ((uint16_t)0x0010) -#define GPIO_PIN_5 ((uint16_t)0x0020) -#define GPIO_PIN_6 ((uint16_t)0x0040) -#define GPIO_PIN_7 ((uint16_t)0x0080) -#define GPIO_PIN_8 ((uint16_t)0x0100) -#define GPIO_PIN_9 ((uint16_t)0x0200) -#define GPIO_PIN_10 ((uint16_t)0x0400) -#define GPIO_PIN_11 ((uint16_t)0x0800) -#define GPIO_PIN_12 ((uint16_t)0x1000) -#define GPIO_PIN_13 ((uint16_t)0x2000) -#define GPIO_PIN_14 ((uint16_t)0x4000) -#define GPIO_PIN_15 ((uint16_t)0x8000) -#define GPIO_PIN_ALL ((uint16_t)0xFFFF) - -/** - * @} - */ - -/** @defgroup GPIO_Remap_define - * @{ - */ -#define GPIO_REMAP_SPI1 ((uint32_t)0x00000001) -#define GPIO_REMAP_I2C1 ((uint32_t)0x00000002) -#define GPIO_REMAP_USART1 ((uint32_t)0x00000004) -#define GPIO_REMAP_USART2 ((uint32_t)0x00000008) -#define GPIO_PARTIAL_REMAP_USART3 ((uint32_t)0x00140010) -#define GPIO_FULL_REMAP_USART3 ((uint32_t)0x00140030) -#define GPIO_PARTIAL_REMAP_TIMER1 ((uint32_t)0x00160040) -#define GPIO_FULL_REMAP_TIMER1 ((uint32_t)0x001600C0) -#define GPIO_PARTIAL_REMAP1_TIMER2 ((uint32_t)0x00180100) -#define GPIO_PARTIAL_REMAP2_TIMER2 ((uint32_t)0x00180200) -#define GPIO_FULL_REMAP_TIMER2 ((uint32_t)0x00180300) -#define GPIO_PARTIAL_REMAP_TIMER3 ((uint32_t)0x001A0800) -#define GPIO_FULL_REMAP_TIMER3 ((uint32_t)0x001A0C00) -#define GPIO_REMAP_TIMER4 ((uint32_t)0x00001000) -#define GPIO_REMAP1_CAN1 ((uint32_t)0x001D4000) -#define GPIO_REMAP2_CAN1 ((uint32_t)0x001D6000) -#define GPIO_REMAP_PD01 ((uint32_t)0x00008000) -#define GPIO_REMAP_TIMER5CH4_LSI ((uint32_t)0x00200001) -#define GPIO_REMAP_ADC1_ETRGINJ ((uint32_t)0x00200002) -#define GPIO_REMAP_ADC1_ETRGREG ((uint32_t)0x00200004) -#define GPIO_REMAP_ADC2_ETRGINJ ((uint32_t)0x00200008) -#define GPIO_REMAP_ADC2_ETRGREG ((uint32_t)0x00200010) -#define GPIO_REMAP_ETH ((uint32_t)0x00200020) -#define GPIO_REMAP_CAN2 ((uint32_t)0x00200040) -#define GPIO_REMAP_SWJ_NOJTRST ((uint32_t)0x00300100) -#define GPIO_REMAP_SWJ_JTAGDISABLE ((uint32_t)0x00300200) -#define GPIO_REMAP_SWJ_DISABLE ((uint32_t)0x00300400) -#define GPIO_REMAP_SPI3 ((uint32_t)0x00201100) -#define GPIO_REMAP_TIMER2ITR1_PTP_SOF ((uint32_t)0x00202000) -#define GPIO_REMAP_PTP_PPS ((uint32_t)0x00204000) -#define GPIO_REMAP_TIMER15 ((uint32_t)0x80000001) -#define GPIO_REMAP_TIMER16 ((uint32_t)0x80000002) -#define GPIO_REMAP_TIMER17 ((uint32_t)0x80000004) -#define GPIO_REMAP_CEC ((uint32_t)0x80000008) -#define GPIO_REMAP_TIMER1_DMA ((uint32_t)0x80000010) -#define GPIO_REMAP_TIMER9 ((uint32_t)0x80000020) -#define GPIO_REMAP_TIMER10 ((uint32_t)0x80000040) -#define GPIO_REMAP_TIMER11 ((uint32_t)0x80000080) -#define GPIO_REMAP_TIMER13 ((uint32_t)0x80000100) -#define GPIO_REMAP_TIMER14 ((uint32_t)0x80000200) -#define GPIO_REMAP_EXMC_NADV ((uint32_t)0x80000400) -#define GPIO_REMAP_TIMER67_DAC_DMA ((uint32_t)0x80000800) -#define GPIO_REMAP_TIMER12 ((uint32_t)0x80001000) -#define GPIO_REMAP_MISC ((uint32_t)0x80002000) - -/** - * @} - */ - -/** @defgroup GPIO_Port_Sources - * @{ - */ -#define GPIO_PORT_SOURCE_GPIOA ((uint8_t)0x00) -#define GPIO_PORT_SOURCE_GPIOB ((uint8_t)0x01) -#define GPIO_PORT_SOURCE_GPIOC ((uint8_t)0x02) -#define GPIO_PORT_SOURCE_GPIOD ((uint8_t)0x03) -#define GPIO_PORT_SOURCE_GPIOE ((uint8_t)0x04) -#define GPIO_PORT_SOURCE_GPIOF ((uint8_t)0x05) -#define GPIO_PORT_SOURCE_GPIOG ((uint8_t)0x06) - -/** - * @} - */ - -/** @defgroup GPIO_Pin_sources - * @{ - */ -#define GPIO_PINSOURCE0 ((uint8_t)0x00) -#define GPIO_PINSOURCE1 ((uint8_t)0x01) -#define GPIO_PINSOURCE2 ((uint8_t)0x02) -#define GPIO_PINSOURCE3 ((uint8_t)0x03) -#define GPIO_PINSOURCE4 ((uint8_t)0x04) -#define GPIO_PINSOURCE5 ((uint8_t)0x05) -#define GPIO_PINSOURCE6 ((uint8_t)0x06) -#define GPIO_PINSOURCE7 ((uint8_t)0x07) -#define GPIO_PINSOURCE8 ((uint8_t)0x08) -#define GPIO_PINSOURCE9 ((uint8_t)0x09) -#define GPIO_PINSOURCE10 ((uint8_t)0x0A) -#define GPIO_PINSOURCE11 ((uint8_t)0x0B) -#define GPIO_PINSOURCE12 ((uint8_t)0x0C) -#define GPIO_PINSOURCE13 ((uint8_t)0x0D) -#define GPIO_PINSOURCE14 ((uint8_t)0x0E) -#define GPIO_PINSOURCE15 ((uint8_t)0x0F) - -/** - * @} - */ - -/** @defgroup Ethernet_Media_Interface - * @{ - */ -#define GPIO_ETH_MEDIAINTERFACE_MII ((uint32_t)0x00000000) -#define GPIO_ETH_MEDIAINTERFACE_RMII ((uint32_t)0x00800000) - -/** - * @} - */ - -/* output mode definitions */ -#define CTL_CLTR(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define GPIO_MODE_INPUT CTL_CLTR(0) /*!< input mode */ -#define GPIO_MODE_OUTPUT CTL_CLTR(1) /*!< output mode */ -#define GPIO_MODE_AF CTL_CLTR(2) /*!< alternate function mode */ -#define GPIO_MODE_ANALOG CTL_CLTR(3) /*!< analog mode */ - -/** @defgroup AFIO_Event_Output - * @{ - */ -#define AFIO_ECR_EVOE_SET ((uint32_t)0x00000080) -#define AFIO_ECR_EVOE_RESET ((uint32_t)0xffffff7f) - -/* gpio alternate function */ -#define AF(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) -#define GPIO_AF_0 AF(0) /*!< alternate function selected 0 */ -#define GPIO_AF_1 AF(1) /*!< alternate function selected 1 */ -#define GPIO_AF_2 AF(2) /*!< alternate function selected 2 */ -#define GPIO_AF_3 AF(3) /*!< alternate function selected 3 */ -#define GPIO_AF_4 AF(4) /*!< alternate function selected 4 */ -#define GPIO_AF_5 AF(5) /*!< alternate function selected 5 */ -#define GPIO_AF_6 AF(6) /*!< alternate function selected 6 */ -#define GPIO_AF_7 AF(7) /*!< alternate function selected 7 */ -#define GPIO_AF_8 AF(8) /*!< alternate function selected 8 */ -#define GPIO_AF_9 AF(9) /*!< alternate function selected 9 */ -#define GPIO_AF_10 AF(10) /*!< alternate function selected 10 */ -#define GPIO_AF_11 AF(11) /*!< alternate function selected 11 */ -#define GPIO_AF_12 AF(12) /*!< alternate function selected 12 */ -#define GPIO_AF_13 AF(13) /*!< alternate function selected 13 */ -#define GPIO_AF_14 AF(14) /*!< alternate function selected 14 */ -#define GPIO_AF_15 AF(15) /*!< alternate function selected 15 */ - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup GPIO_Exported_Functions - * @{ - */ -void GPIO_DeInit(GPIO_TypeDef *GPIOx); -void GPIO_AFDeInit(void); -void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitPara *GPIO_InitStruct); -void GPIO_ParaInit(GPIO_InitPara *GPIO_InitStruct); -uint8_t GPIO_ReadInputBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin); -uint16_t GPIO_ReadInputData(GPIO_TypeDef *GPIOx); -uint8_t GPIO_ReadOutputBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin); -uint16_t GPIO_ReadOutputData(GPIO_TypeDef *GPIOx); -void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin); -void GPIO_ResetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin); -void GPIO_WriteBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, BitState BitVal); -void GPIO_Write(GPIO_TypeDef *GPIOx, uint16_t PortVal); -void GPIO_PinLockConfig(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin); -void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); -void GPIO_EventOutputEnable(TypeState NewState); -void GPIO_PinRemapConfig(uint32_t GPIO_Remap, TypeState NewState); -void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); -void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_GPIO_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_i2c.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_i2c.h deleted file mode 100644 index 8017f10a33..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_i2c.h +++ /dev/null @@ -1,289 +0,0 @@ -/** - ****************************************************************************** - * @brief I2C header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_I2C_H -#define __GD32F10X_I2C_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup I2C - * @{ - */ - -/** @defgroup I2C_Exported_Types - * @{ - */ - -/** - * @brief I2C Initial Parameters - */ -typedef struct { - uint16_t I2C_Protocol; /*!< The protocol type, detailed in @ref I2C_Protocol */ - uint16_t I2C_DutyCycle; /*!< The fast mode duty cycle, detailed in @ref I2C_Duty_Cycle */ - uint32_t I2C_BitRate; /*!< The I2C bit rate which must be lower than 400k bit/s */ - uint16_t I2C_AddressingMode; /*!< The I2C addressing mode, detailed in @ref I2C_Addressing_Mode */ - uint16_t I2C_DeviceAddress; /*!< The device address */ -} I2C_InitPara; - -/** - * @} - */ - -/** @defgroup I2C_Exported_Constants - * @{ - */ - -/** @defgroup I2C_Protocol - * @{ - */ -#define I2C_PROTOCOL_I2C ((uint16_t)0x0000) -#define I2C_PROTOCOL_SMBUSDEVICE ((uint16_t)0x0002) -#define I2C_PROTOCOL_SMBUSHOST ((uint16_t)0x000A) - -/** - * @} - */ - -/** @defgroup I2C_Duty_Cycle - * @{ - */ -#define I2C_DUTYCYCLE_16_9 ((uint16_t)0x4000) /*!< I2C fast mode Tlow/Thigh = 16/9 */ -#define I2C_DUTYCYCLE_2 ((uint16_t)0xBFFF) /*!< I2C fast mode Tlow/Thigh = 2 */ - -/** - * @} - */ - -/** @defgroup I2C_Addressing_Mode - * @{ - */ -#define I2C_ADDRESSING_MODE_7BIT ((uint16_t)0x4000) -#define I2C_ADDRESSING_MODE_10BIT ((uint16_t)0xC000) - -/** - * @} - */ - -/** @defgroup I2C_Direction - * @{ - */ -#define I2C_DIRECTION_TRANSMITTER ((uint8_t)0x00) -#define I2C_DIRECTION_RECEIVER ((uint8_t)0x01) - -/** - * @} - */ - -/** @defgroup I2C_Registers - * @{ - */ -#define I2C_REGISTER_CTLR1 ((uint8_t)0x00) -#define I2C_REGISTER_CTLR2 ((uint8_t)0x04) -#define I2C_REGISTER_AR1 ((uint8_t)0x08) -#define I2C_REGISTER_AR2 ((uint8_t)0x0C) -#define I2C_REGISTER_DTR ((uint8_t)0x10) -#define I2C_REGISTER_STR1 ((uint8_t)0x14) -#define I2C_REGISTER_STR2 ((uint8_t)0x18) -#define I2C_REGISTER_CLKR ((uint8_t)0x1C) -#define I2C_REGISTER_RTR ((uint8_t)0x20) - -/** - * @} - */ - -/** @defgroup I2C_PEC_Position - * @{ - */ -#define I2C_PECPOSITION_NEXT I2C_CTLR1_POAP -#define I2C_PECPOSITION_CURRENT ((uint16_t)~I2C_CTLR1_POAP) - -/** - * @} - */ - -/** @defgroup I2C_NACK_Position - * @{ - */ -#define I2C_NACKPOSITION_NEXT I2C_CTLR1_POAP -#define I2C_NACKPOSITION_CURRENT ((uint16_t)~I2C_CTLR1_POAP) - -/** - * @} - */ - -/** @defgroup I2C_Interrupt_Control - * @{ - */ -#define I2C_INT_EIE I2C_CTLR2_EIE -#define I2C_INT_EE I2C_CTLR2_EE -#define I2C_INT_BIE I2C_CTLR2_BIE - -/** - * @} - */ - -/** @defgroup I2C_Interrupt_Source - * @{ - */ -#define I2C_INT_SMBALTS ((uint32_t)0x01008000) -#define I2C_INT_SMBTO ((uint32_t)0x01004000) -#define I2C_INT_PECE ((uint32_t)0x01001000) -#define I2C_INT_RXORE ((uint32_t)0x01000800) -#define I2C_INT_AE ((uint32_t)0x01000400) -#define I2C_INT_LOSTARB ((uint32_t)0x01000200) -#define I2C_INT_BE ((uint32_t)0x01000100) -#define I2C_INT_TBE ((uint32_t)0x06000080) -#define I2C_INT_RBNE ((uint32_t)0x06000040) -#define I2C_INT_STPSEND ((uint32_t)0x02000010) -#define I2C_INT_ADD10SEND ((uint32_t)0x02000008) -#define I2C_INT_BTC ((uint32_t)0x02000004) -#define I2C_INT_ADDSEND ((uint32_t)0x02000002) -#define I2C_INT_SBSEND ((uint32_t)0x02000001) - -/** - * @} - */ - -/** @defgroup I2C_FLAG - * @{ - */ - -/** - * @brief STR2 register flags - */ -#define I2C_FLAG_DUMODF ((uint32_t)0x00800000) -#define I2C_FLAG_HSTSMB ((uint32_t)0x00400000) -#define I2C_FLAG_DEFSMB ((uint32_t)0x00200000) -#define I2C_FLAG_RXGC ((uint32_t)0x00100000) -#define I2C_FLAG_TRS ((uint32_t)0x00040000) -#define I2C_FLAG_I2CBSY ((uint32_t)0x00020000) -#define I2C_FLAG_MASTER ((uint32_t)0x00010000) - -/** - * @brief STR1 register flags - */ -#define I2C_FLAG_SMBALTS ((uint32_t)0x10008000) -#define I2C_FLAG_SMBTO ((uint32_t)0x10004000) -#define I2C_FLAG_PECE ((uint32_t)0x10001000) -#define I2C_FLAG_RXORE ((uint32_t)0x10000800) -#define I2C_FLAG_AE ((uint32_t)0x10000400) -#define I2C_FLAG_LOSTARB ((uint32_t)0x10000200) -#define I2C_FLAG_BE ((uint32_t)0x10000100) -#define I2C_FLAG_TBE ((uint32_t)0x10000080) -#define I2C_FLAG_RBNE ((uint32_t)0x10000040) -#define I2C_FLAG_STPSEND ((uint32_t)0x10000010) -#define I2C_FLAG_ADD10SEND ((uint32_t)0x10000008) -#define I2C_FLAG_BTC ((uint32_t)0x10000004) -#define I2C_FLAG_ADDSEND ((uint32_t)0x10000002) -#define I2C_FLAG_SBSEND ((uint32_t)0x10000001) - -/** - * @} - */ - -/** @defgroup I2C_ProgrammingMode - * @{ - */ -#define I2C_PROGRAMMINGMODE_MASTER_SBSEND ((uint32_t)0x00030001) /*!< I2CBSY, MASTER and SBSEND flag */ - -#define I2C_PROGRAMMINGMODE_MASTER_TRANSMITTER_ADDSEND ((uint32_t)0x00070002) /*!< I2CBSY, MASTER, ADDSEND and TRS flags */ -#define I2C_PROGRAMMINGMODE_MASTER_RECEIVER_ADDSEND ((uint32_t)0x00030002) /*!< I2CBSY, MASTER and ADDSEND flags */ - -#define I2C_PROGRAMMINGMODE_MASTER_ADD10SEND ((uint32_t)0x00030008) /*!< I2CBSY, MASTER and ADD10SEND flags */ - -#define I2C_PROGRAMMINGMODE_MASTER_BYTE_RECEIVED ((uint32_t)0x00030040) /*!< I2CBSY, MASTER and RBNE flags */ -#define I2C_PROGRAMMINGMODE_MASTER_BYTE_TRANSMITTING ((uint32_t)0x00070080) /*!< TRS, I2CBSY, MASTER, TBE flags */ -#define I2C_PROGRAMMINGMODE_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084) /*!< TRS, I2CBSY, MASTER, TBE and BTC flags */ - -#define I2C_PROGRAMMINGMODE_SLAVE_RECEIVER_ADDSEND ((uint32_t)0x00020002) /*!< I2CBSY and ADDSEND flags */ -#define I2C_PROGRAMMINGMODE_SLAVE_TRANSMITTER_ADDSEND ((uint32_t)0x00060002) /*!< TRS, I2CBSY and ADDSEND flags */ - -#define I2C_PROGRAMMINGMODE_SLAVE_RECEIVER_SECONDADDRESS_SELECTED ((uint32_t)0x00820000) /*!< DUMODF and I2CBSY flags */ -#define I2C_PROGRAMMINGMODE_SLAVE_TRANSMITTER_SECONDADDRESS_SELECTED ((uint32_t)0x00860080) /*!< DUMODF, TRS, I2CBSY and TBE flags */ - -#define I2C_PROGRAMMINGMODE_SLAVE_GENERALCALLADDRESS_SELECTED ((uint32_t)0x00120000) /*!< RXGC and I2CBSY flags */ - -#define I2C_PROGRAMMINGMODE_SLAVE_BYTE_RECEIVED ((uint32_t)0x00020040) /*!< I2CBSY and RBNE flags */ -#define I2C_PROGRAMMINGMODE_SLAVE_STOP_DETECTED ((uint32_t)0x00000010) /*!< STPSEND flag */ - -#define I2C_PROGRAMMINGMODE_SLAVE_BYTE_TRANSMITTED ((uint32_t)0x00060084) /*!< TRS, I2CBSY, TBE and BTC flags */ -#define I2C_PROGRAMMINGMODE_SLAVE_BYTE_TRANSMITTING ((uint32_t)0x00060080) /*!< TRS, I2CBSY and TBE flags */ -#define I2C_PROGRAMMINGMODE_SLAVE_ACK_FAILURE ((uint32_t)0x00000400) /*!< AE flag */ - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup I2C_Exported_Functions - * @{ - */ -void I2C_DeInit(I2C_TypeDef *I2Cx); -void I2C_Init(I2C_TypeDef *I2Cx, I2C_InitPara *I2C_InitParaStruct); -void I2C_ParaInit(I2C_InitPara *I2C_InitParaStruct); -void I2C_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_DMA_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_DMALastTransfer_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_StartOnBus_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_StopOnBus_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_Acknowledge_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_OwnAddress2(I2C_TypeDef *I2Cx, uint8_t Address); -void I2C_DualAddress_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_GeneralCall_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_INTConfig(I2C_TypeDef *I2Cx, uint16_t I2C_INT, TypeState NewValue); -void I2C_SendData(I2C_TypeDef *I2Cx, uint8_t Data); -uint8_t I2C_ReceiveData(I2C_TypeDef *I2Cx); -void I2C_AddressingDevice_7bit(I2C_TypeDef *I2Cx, uint8_t Address, uint8_t I2C_Direction); -uint16_t I2C_ReadRegister(I2C_TypeDef *I2Cx, uint8_t I2C_Register); -void I2C_SoftwareReset_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_NACKPosition_Enable(I2C_TypeDef *I2Cx, uint16_t I2C_NACKPosition); -void I2C_SMBusAlertSend_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_PECTransmit_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_PECPosition_Enable(I2C_TypeDef *I2Cx, uint16_t I2C_PECPosition); -void I2C_PEC_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -uint8_t I2C_GetPECValue(I2C_TypeDef *I2Cx); -void I2C_ARP_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_StretchClock_Enable(I2C_TypeDef *I2Cx, TypeState NewValue); -void I2C_FastModeDutyCycle(I2C_TypeDef *I2Cx, uint16_t I2C_DutyCycle); - -TypeState I2C_StateDetect(I2C_TypeDef *I2Cx, uint32_t I2C_State); -uint32_t I2C_GetCurrentState(I2C_TypeDef *I2Cx); -TypeState I2C_GetBitState(I2C_TypeDef *I2Cx, uint32_t I2C_FLAG); -void I2C_ClearBitState(I2C_TypeDef *I2Cx, uint32_t I2C_FLAG); -TypeState I2C_GetIntBitState(I2C_TypeDef *I2Cx, uint32_t I2C_INT); -void I2C_ClearIntBitState(I2C_TypeDef *I2Cx, uint32_t I2C_INT); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_I2C_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_iwdg.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_iwdg.h deleted file mode 100644 index 6d3e319fb7..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_iwdg.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - ****************************************************************************** - * @brief IWDG header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_IWDG_H -#define __GD32F10X_IWDG_H - -/* Exported macro ------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup IWDG - * @{ - */ - -/** @defgroup IWDG_Exported_Constants - * @{ - */ - -/** @defgroup IWDG_WriteAccess - * @{ - */ -#define IWDG_WRITEACCESS_ENABLE ((uint16_t)0x5555) -#define IWDG_WRITEACCESS_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup IWDG_prescaler - * @{ - */ -#define IWDG_PRESCALER_4 ((uint8_t)0x00) -#define IWDG_PRESCALER_8 ((uint8_t)0x01) -#define IWDG_PRESCALER_16 ((uint8_t)0x02) -#define IWDG_PRESCALER_32 ((uint8_t)0x03) -#define IWDG_PRESCALER_64 ((uint8_t)0x04) -#define IWDG_PRESCALER_128 ((uint8_t)0x05) -#define IWDG_PRESCALER_256 ((uint8_t)0x06) - -/** - * @} - */ - -/** @defgroup IWDG_Flag - * @{ - */ -#define IWDG_BIT_PUD IWDG_STR_PUD -#define IWDG_BIT_RUD IWDG_STR_RUD -#define IWDG_BIT_WUD IWDG_STR_WUD - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup IWDG_Exported_functions - * @{ - */ -/* Prescaler and Counter configuration functions ******************************/ -void IWDG_Write_Enable(uint16_t IWDG_WriteAccess); -void IWDG_SetPrescaler(uint8_t PrescalerValue); -void IWDG_SetReloadValue(uint16_t ReloadValue); -void IWDG_ReloadCounter(void); - -/* IWDG activation function ***************************************************/ -void IWDG_Enable(void); - -/* Flag management function ***************************************************/ -TypeState IWDG_GetBitState(uint16_t IWDG_FLAG); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __IWDG_GD32F10X_H */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_mcudbg.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_mcudbg.h deleted file mode 100644 index f6f1f0902f..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_mcudbg.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - ****************************************************************************** - * @brief MCUDBG header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_MCUDBG_H -#define __GD32F10X_MCUDBG_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup MCUDBG - * @{ - */ - -/* Exported types ------------------------------------------------------------*/ - - - -/* Exported constants --------------------------------------------------------*/ - -/** @defgroup MCUDBG_Exported_Constants - * @{ - */ -#define MCUDBG_SLEEP_HOLD ((uint32_t)0x00000001) -#define MCUDBG_DEEPSLEEP_HOLD ((uint32_t)0x00000002) -#define MCUDBG_STDBY_HOLD ((uint32_t)0x00000004) -#define MCUDBG_IWDG_HOLD ((uint32_t)0x00000100) -#define MCUDBG_WWDG_HOLD ((uint32_t)0x00000200) -#define MCUDBG_TIMER1_HOLD ((uint32_t)0x00000400) -#define MCUDBG_TIMER2_HOLD ((uint32_t)0x00000800) -#define MCUDBG_TIMER3_HOLD ((uint32_t)0x00001000) -#define MCUDBG_TIMER4_HOLD ((uint32_t)0x00002000) -#define MCUDBG_CAN1_HOLD ((uint32_t)0x00004000) -#define MCUDBG_I2C1_HOLD ((uint32_t)0x00008000) -#define MCUDBG_I2C2_HOLD ((uint32_t)0x00010000) -#define MCUDBG_TIMER5_HOLD ((uint32_t)0x00020000) -#define MCUDBG_TIMER6_HOLD ((uint32_t)0x00040000) -#define MCUDBG_TIMER7_HOLD ((uint32_t)0x00080000) -#define MCUDBG_TIMER8_HOLD ((uint32_t)0x00100000) -#define MCUDBG_CAN2_HOLD ((uint32_t)0x00200000) -#define MCUDBG_TIMER12_HOLD ((uint32_t)0x02000000) -#define MCUDBG_TIMER13_HOLD ((uint32_t)0x04000000) -#define MCUDBG_TIMER14_HOLD ((uint32_t)0x08000000) -#define MCUDBG_TIMER9_HOLD ((uint32_t)0x10000000) -#define MCUDBG_TIMER10_HOLD ((uint32_t)0x20000000) -#define MCUDBG_TIMER11_HOLD ((uint32_t)0x40000000) - -/** - * @} - */ - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ - -/** @defgroup MCUDBG_Exported_Functions - * @{ - */ - -uint32_t MCUDBG_GetREVID(void); -uint32_t MCUDBG_GetDEVID(void); -void MCUDBG_PeriphConfig(uint32_t MCUDBG_Periph, TypeState NewValue); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_MCUDBG_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_misc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_misc.h deleted file mode 100644 index 8ca8a6315f..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_misc.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - ****************************************************************************** - * @brief MISC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_MISC_H -#define __GD32F10X_MISC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup MISC - * @{ - */ - -/** @defgroup MISC_Exported_Types - * @{ - */ - -/** - * @brief MISC Initial Parameters - */ -typedef struct { - uint8_t NVIC_IRQ; /*!< The IRQ type,detailed in @ref IRQn_Type */ - - uint8_t NVIC_IRQPreemptPriority; /*!< The pre-emption priority of NVIC_IRQ, detailed in @ref NVIC_Priority_Table */ - - uint8_t NVIC_IRQSubPriority; /*!< The SubPriority of NVIC_IRQ, detailed in @ref NVIC_Priority_Table */ - - TypeState NVIC_IRQEnable; /*!< Enable or disable the IRQ,this parameter can be ENABLE or DISABLE */ - -} NVIC_InitPara; - -/** - * @} - */ - -/** @defgroup MISC_Exported_Constants - * @{ - */ - -/** @defgroup MISC_System_Low_Power - * @{ - */ -#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) -#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) -#define NVIC_LOWPOWER_SEVONPEND ((uint8_t)0x10) -#define NVIC_LOWPOWER_SLEEPDEEP ((uint8_t)0x04) -#define NVIC_LOWPOWER_SLEEPONEXIT ((uint8_t)0x02) - -/** - * @} - */ - -/** @defgroup MISC_Preemption_Priority_Group - * @{ - */ - -/* Preemption Priority Group -------------------------------------------------*/ -#define NVIC_PRIGROUP_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ -#define NVIC_PRIGROUP_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ -#define NVIC_PRIGROUP_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ -#define NVIC_PRIGROUP_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ -#define NVIC_PRIGROUP_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ - -/** - * @} - */ - -/** @defgroup MISC_SysTick_clock_source - * @{ - */ -#define SYSTICK_CKSOURCE_HCLK_DIV8 ((uint32_t)0xFFFFFFFB) -#define SYSTICK_CKSOURCE_HCLK ((uint32_t)0x00000004) - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup MISC_Exported_Functions - * @{ - */ -void NVIC_Init(NVIC_InitPara *NVIC_InitStruct); -void NVIC_SystemLowPowerConfig(uint8_t LowPowerMode, TypeState NewValue); -void SysTick_CKSource_Enable(uint32_t SysTick_CKSource); -void NVIC_VectTableSet(uint32_t NVIC_VectTab, uint32_t Offset); -void NVIC_PRIGroup_Enable(uint32_t NVIC_PRIGroup); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_MISC_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_pwr.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_pwr.h deleted file mode 100644 index 36cd112d18..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_pwr.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - ****************************************************************************** - * @brief PWR header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_PWR_H -#define __GD32F10X_PWR_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup PWR - * @{ - */ - -/** @defgroup PWR_Exported_Constants - * @{ - */ - -/** @defgroup PWR_Low_Voltage_Detector_Threshold - * @{ - */ -#define PWR_LVDT_0 PWR_CTLR_LVDT_2V2 -#define PWR_LVDT_1 PWR_CTLR_LVDT_2V3 -#define PWR_LVDT_2 PWR_CTLR_LVDT_2V4 -#define PWR_LVDT_3 PWR_CTLR_LVDT_2V5 -#define PWR_LVDT_4 PWR_CTLR_LVDT_2V6 -#define PWR_LVDT_5 PWR_CTLR_LVDT_2V7 -#define PWR_LVDT_6 PWR_CTLR_LVDT_2V8 -#define PWR_LVDT_7 PWR_CTLR_LVDT_2V9 - -/** - * @} - */ - -/** @defgroup PWR_LDO_state_in_Deep-sleep_mode - * @{ - */ -#define PWR_LDO_ON ((uint32_t)0x00000000) -#define PWR_LDO_LOWPOWER PWR_CTLR_LDOLP - -/** - * @} - */ - -/** @defgroup PWR_Sleep_mode_entry - * @{ - */ -#define PWR_SLEEPENTRY_WFI ((uint8_t)0x01) -#define PWR_SLEEPENTRY_WFE ((uint8_t)0x02) - -/** - * @} - */ - -/** @defgroup PWR_Deep-sleep_mode_entry - * @{ - */ -#define PWR_DEEPSLEEPENTRY_WFI ((uint8_t)0x01) -#define PWR_DEEPSLEEPENTRY_WFE ((uint8_t)0x02) - -/** - * @} - */ - -/** @defgroup PWR_Standby_mode_entry - * @{ - */ -#define PWR_STDBYENTRY_WFI ((uint8_t)0x01) -#define PWR_STDBYENTRY_WFE ((uint8_t)0x02) - -/** - * @} - */ - -/** @defgroup PWR_Flag - * @{ - */ -#define PWR_FLAG_WKUP PWR_STR_WUF -#define PWR_FLAG_STB PWR_STR_SBF -#define PWR_FLAG_LVDF PWR_STR_LVDF - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup PWR_Exported_Functions - * @{ - */ -void PWR_DeInit(void); -void PWR_BackupAccess_Enable(TypeState NewValue); -void PWR_LVDConfig(uint32_t PWR_LVDT, TypeState NewValue); -void PWR_WKUP_Pin_Enable(TypeState NewValue); -void PWR_SLEEPMode_Entry(uint8_t PWR_SLEEPENTRY); -void PWR_DEEPSLEEPMode_Entry(uint32_t PWR_LDO, uint8_t PWR_DEEPSLEEPENTRY); -void PWR_STDBYMode_Entry(uint8_t PWR_STDBYENTRY); -TypeState PWR_GetBitState(uint32_t PWR_FLAG); -void PWR_ClearBitState(uint32_t PWR_FLAG); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_PWR_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcc.h deleted file mode 100644 index 9772751542..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcc.h +++ /dev/null @@ -1,690 +0,0 @@ -/** - ****************************************************************************** - * @brief RCC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_RCC_H -#define __GD32F10X_RCC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup RCC - * @{ - */ - -/** @defgroup RCC_Exported_Types - * @{ - */ - -/** - * @brief RCC Initial Parameters - */ - -typedef struct { - uint32_t CK_SYS_Frequency; /*!< The frequency of the CK_SYS. */ - uint32_t AHB_Frequency; /*!< The frequency of the AHB. */ - uint32_t APB1_Frequency; /*!< The frequency of the APB1. */ - uint32_t APB2_Frequency; /*!< The frequency of the APB2. */ - uint32_t ADCCLK_Frequency; /*!< The frequency of the ADCCLK. */ -} RCC_ClocksPara; - -/** - * @} - */ - -/** @defgroup RCC_Exported_Constants - * @{ - */ - -/** @defgroup RCC_HSE_configuration - * @{ - */ - -#define RCC_HSE_OFF ((uint32_t)0x00000000) -#define RCC_HSE_ON RCC_GCCR_HSEEN -#define RCC_HSE_BYPASS RCC_GCCR_HSEEN | RCC_GCCR_HSEBPS - -/** - * @} - */ - -/** @defgroup RCC_PLL_input_clock_source - * @{ - */ - -#define RCC_PLLSOURCE_HSI_DIV2 RCC_GCFGR_PLLSEL_HSI_DIV2 - -#ifdef GD32F10X_CL -#define RCC_PLLSOURCE_PREDIV1 RCC_GCFGR_PLLSEL_PREDIV1 - -#else -#define RCC_PLLSOURCE_HSE_DIV1 ((uint32_t)0x00010000) -#define RCC_PLLSOURCE_HSE_DIV2 ((uint32_t)0x00030000) -#endif /* GD32F10X_CL */ -/** - * @} - */ - -/** @defgroup RCC_PLL_Multiplication_factor - * @{ - */ - - -#define RCC_PLLMUL_2 RCC_GCFGR_PLLMF2 -#define RCC_PLLMUL_3 RCC_GCFGR_PLLMF3 -#define RCC_PLLMUL_4 RCC_GCFGR_PLLMF4 -#define RCC_PLLMUL_5 RCC_GCFGR_PLLMF5 -#define RCC_PLLMUL_6 RCC_GCFGR_PLLMF6 -#define RCC_PLLMUL_7 RCC_GCFGR_PLLMF7 -#define RCC_PLLMUL_8 RCC_GCFGR_PLLMF8 -#define RCC_PLLMUL_9 RCC_GCFGR_PLLMF9 -#define RCC_PLLMUL_10 RCC_GCFGR_PLLMF10 -#define RCC_PLLMUL_11 RCC_GCFGR_PLLMF11 -#define RCC_PLLMUL_12 RCC_GCFGR_PLLMF12 -#define RCC_PLLMUL_13 RCC_GCFGR_PLLMF13 -#define RCC_PLLMUL_14 RCC_GCFGR_PLLMF14 - -#define RCC_PLLMUL_16 RCC_GCFGR_PLLMF16 -#define RCC_PLLMUL_17 RCC_GCFGR_PLLMF17 -#define RCC_PLLMUL_18 RCC_GCFGR_PLLMF18 -#define RCC_PLLMUL_19 RCC_GCFGR_PLLMF19 -#define RCC_PLLMUL_20 RCC_GCFGR_PLLMF20 -#define RCC_PLLMUL_21 RCC_GCFGR_PLLMF21 -#define RCC_PLLMUL_22 RCC_GCFGR_PLLMF22 -#define RCC_PLLMUL_23 RCC_GCFGR_PLLMF23 -#define RCC_PLLMUL_24 RCC_GCFGR_PLLMF24 -#define RCC_PLLMUL_25 RCC_GCFGR_PLLMF25 -#define RCC_PLLMUL_26 RCC_GCFGR_PLLMF26 -#define RCC_PLLMUL_27 RCC_GCFGR_PLLMF27 -#define RCC_PLLMUL_28 RCC_GCFGR_PLLMF28 -#define RCC_PLLMUL_29 RCC_GCFGR_PLLMF29 -#define RCC_PLLMUL_30 RCC_GCFGR_PLLMF30 -#define RCC_PLLMUL_31 RCC_GCFGR_PLLMF31 -#define RCC_PLLMUL_32 RCC_GCFGR_PLLMF32 - -#ifdef GD32F10X_CL -#define RCC_PLLMUL_6_5 RCC_GCFGR_PLLMF6_5 -#else -#define RCC_PLLMUL_15 RCC_GCFGR_PLLMF15 - -#endif /* GD32F10X_CL */ -/** - * @} - */ - -#ifdef GD32F10X_CL -/** @defgroup RCC_PREDIV1_division_factor - * @{ - */ - -#define RCC_PREDIV1_DIV1 RCC_GCFGR2_PREDV1_DIV1 -#define RCC_PREDIV1_DIV2 RCC_GCFGR2_PREDV1_DIV2 -#define RCC_PREDIV1_DIV3 RCC_GCFGR2_PREDV1_DIV3 -#define RCC_PREDIV1_DIV4 RCC_GCFGR2_PREDV1_DIV4 -#define RCC_PREDIV1_DIV5 RCC_GCFGR2_PREDV1_DIV5 -#define RCC_PREDIV1_DIV6 RCC_GCFGR2_PREDV1_DIV6 -#define RCC_PREDIV1_DIV7 RCC_GCFGR2_PREDV1_DIV7 -#define RCC_PREDIV1_DIV8 RCC_GCFGR2_PREDV1_DIV8 -#define RCC_PREDIV1_DIV9 RCC_GCFGR2_PREDV1_DIV9 -#define RCC_PREDIV1_DIV10 RCC_GCFGR2_PREDV1_DIV10 -#define RCC_PREDIV1_DIV11 RCC_GCFGR2_PREDV1_DIV11 -#define RCC_PREDIV1_DIV12 RCC_GCFGR2_PREDV1_DIV12 -#define RCC_PREDIV1_DIV13 RCC_GCFGR2_PREDV1_DIV13 -#define RCC_PREDIV1_DIV14 RCC_GCFGR2_PREDV1_DIV14 -#define RCC_PREDIV1_DIV15 RCC_GCFGR2_PREDV1_DIV15 -#define RCC_PREDIV1_DIV16 RCC_GCFGR2_PREDV1_DIV16 - -/** - * @} - */ - - -/** @defgroup RCC_PREDIV1_clock_source - * @{ - */ - -#define RCC_PREDIV1_SOURCE_HSE RCC_GCFGR2_PREDV1SEL_HSE -#define RCC_PREDIV1_SOURCE_PLL2 RCC_GCFGR2_PREDV1SEL_PLL2 - -/** - * @} - */ - - -/** @defgroup RCC_PREDIV2_division_factor - * @{ - */ -#define RCC_PREDIV2_DIV1 RCC_GCFGR2_PREDV2_DIV1 -#define RCC_PREDIV2_DIV2 RCC_GCFGR2_PREDV2_DIV2 -#define RCC_PREDIV2_DIV3 RCC_GCFGR2_PREDV2_DIV3 -#define RCC_PREDIV2_DIV4 RCC_GCFGR2_PREDV2_DIV4 -#define RCC_PREDIV2_DIV5 RCC_GCFGR2_PREDV2_DIV5 -#define RCC_PREDIV2_DIV6 RCC_GCFGR2_PREDV2_DIV6 -#define RCC_PREDIV2_DIV7 RCC_GCFGR2_PREDV2_DIV7 -#define RCC_PREDIV2_DIV8 RCC_GCFGR2_PREDV2_DIV8 -#define RCC_PREDIV2_DIV9 RCC_GCFGR2_PREDV2_DIV9 -#define RCC_PREDIV2_DIV10 RCC_GCFGR2_PREDV2_DIV10 -#define RCC_PREDIV2_DIV11 RCC_GCFGR2_PREDV2_DIV11 -#define RCC_PREDIV2_DIV12 RCC_GCFGR2_PREDV2_DIV12 -#define RCC_PREDIV2_DIV13 RCC_GCFGR2_PREDV2_DIV13 -#define RCC_PREDIV2_DIV14 RCC_GCFGR2_PREDV2_DIV14 -#define RCC_PREDIV2_DIV15 RCC_GCFGR2_PREDV2_DIV15 -#define RCC_PREDIV2_DIV16 RCC_GCFGR2_PREDV2_DIV16 - -/** - * @} - */ - - -/** @defgroup RCC_PLL2_multiplication_factor - * @{ - */ -#define RCC_PLL2MUL_8 RCC_GCFGR2_PLL2MF8 -#define RCC_PLL2MUL_9 RCC_GCFGR2_PLL2MF9 -#define RCC_PLL2MUL_10 RCC_GCFGR2_PLL2MF10 -#define RCC_PLL2MUL_11 RCC_GCFGR2_PLL2MF11 -#define RCC_PLL2MUL_12 RCC_GCFGR2_PLL2MF12 -#define RCC_PLL2MUL_13 RCC_GCFGR2_PLL2MF13 -#define RCC_PLL2MUL_14 RCC_GCFGR2_PLL2MF14 -#define RCC_PLL2MUL_16 RCC_GCFGR2_PLL2MF16 -#define RCC_PLL2MUL_20 RCC_GCFGR2_PLL2MF20 - -/** - * @} - */ - - -/** @defgroup RCC_PLL3_multiplication_factor - * @{ - */ -#define RCC_PLL3MUL_8 RCC_GCFGR2_PLL3MF8 -#define RCC_PLL3MUL_9 RCC_GCFGR2_PLL3MF9 -#define RCC_PLL3MUL_10 RCC_GCFGR2_PLL3MF10 -#define RCC_PLL3MUL_11 RCC_GCFGR2_PLL3MF11 -#define RCC_PLL3MUL_12 RCC_GCFGR2_PLL3MF12 -#define RCC_PLL3MUL_13 RCC_GCFGR2_PLL3MF13 -#define RCC_PLL3MUL_14 RCC_GCFGR2_PLL3MF14 -#define RCC_PLL3MUL_16 RCC_GCFGR2_PLL3MF16 -#define RCC_PLL3MUL_20 RCC_GCFGR2_PLL3MF20 - -/** - * @} - */ -#endif /* GD32F10X_CL */ - - -/** @defgroup RCC_System_Clock_Source - * @{ - */ -#define RCC_SYSCLKSOURCE_HSI RCC_GCFGR_SCS_HSI -#define RCC_SYSCLKSOURCE_HSE RCC_GCFGR_SCS_HSE -#define RCC_SYSCLKSOURCE_PLLCLK RCC_GCFGR_SCS_PLL - -/** - * @} - */ - -/** @defgroup RCC_AHB_Clock_Source - * @{ - */ -#define RCC_SYSCLK_DIV1 RCC_GCFGR_AHBPS_DIV1 -#define RCC_SYSCLK_DIV2 RCC_GCFGR_AHBPS_DIV2 -#define RCC_SYSCLK_DIV4 RCC_GCFGR_AHBPS_DIV4 -#define RCC_SYSCLK_DIV8 RCC_GCFGR_AHBPS_DIV8 -#define RCC_SYSCLK_DIV16 RCC_GCFGR_AHBPS_DIV16 -#define RCC_SYSCLK_DIV64 RCC_GCFGR_AHBPS_DIV64 -#define RCC_SYSCLK_DIV128 RCC_GCFGR_AHBPS_DIV128 -#define RCC_SYSCLK_DIV256 RCC_GCFGR_AHBPS_DIV256 -#define RCC_SYSCLK_DIV512 RCC_GCFGR_AHBPS_DIV512 - -/** - * @} - */ - -/** @defgroup RCC_APB_Clock_Source - * @{ - */ -#define RCC_APB1AHB_DIV1 RCC_GCFGR_APB1PS_DIV1 -#define RCC_APB1AHB_DIV2 RCC_GCFGR_APB1PS_DIV2 -#define RCC_APB1AHB_DIV4 RCC_GCFGR_APB1PS_DIV4 -#define RCC_APB1AHB_DIV8 RCC_GCFGR_APB1PS_DIV8 -#define RCC_APB1AHB_DIV16 RCC_GCFGR_APB1PS_DIV16 - -#define RCC_APB2AHB_DIV1 RCC_GCFGR_APB2PS_DIV1 -#define RCC_APB2AHB_DIV2 RCC_GCFGR_APB2PS_DIV2 -#define RCC_APB2AHB_DIV4 RCC_GCFGR_APB2PS_DIV4 -#define RCC_APB2AHB_DIV8 RCC_GCFGR_APB2PS_DIV8 -#define RCC_APB2AHB_DIV16 RCC_GCFGR_APB2PS_DIV16 -/** - * @} - */ - -/** @defgroup RCC_ADC_clock_source - * @{ - */ -#define RCC_ADCCLK_APB2_DIV2 RCC_GCFGR_ADCPS_DIV2 -#define RCC_ADCCLK_APB2_DIV4 RCC_GCFGR_ADCPS_DIV4 -#define RCC_ADCCLK_APB2_DIV6 RCC_GCFGR_ADCPS_DIV6 -#define RCC_ADCCLK_APB2_DIV8 RCC_GCFGR_ADCPS_DIV8 -#define RCC_ADCCLK_APB2_DIV12 RCC_GCFGR_ADCPS_DIV12 -#define RCC_ADCCLK_APB2_DIV16 RCC_GCFGR_ADCPS_DIV16 - -/** - * @} - */ - -#ifdef GD32F10X_CL -/** @defgroup RCC_USB_OTG_clock_source - * @{ - */ -#define RCC_OTGCLK_PLL_DIV1 RCC_GCFGR_OTGFSPS_Div1 -#define RCC_OTGCLK_PLL_DIV1_5 RCC_GCFGR_OTGFSPS_Div1_5 -#define RCC_OTGCLK_PLL_DIV2 RCC_GCFGR_OTGFSPS_Div2 -#define RCC_OTGCLK_PLL_DIV2_5 RCC_GCFGR_OTGFSPS_Div2_5 - -/** - * @} - */ - -#else -/** @defgroup RCC_USB_clock_source - * @{ - */ -#define RCC_USBCLK_PLL_DIV1 RCC_GCFGR_USBPS_Div1 -#define RCC_USBCLK_PLL_DIV1_5 RCC_GCFGR_USBPS_Div1_5 -#define RCC_USBCLK_PLL_DIV2 RCC_GCFGR_USBPS_Div2 -#define RCC_USBCLK_PLL_DIV2_5 RCC_GCFGR_USBPS_Div2_5 - -/** - * @} - */ -#endif /* GD32F10X_CL */ - - - -/** @defgroup RCC_CK_OUT_Clock_Source - * @{ - */ -#ifdef GD32F10X_CL -#define RCC_CKOUTSRC_NOCLOCK RCC_GCFGR_CKOUTSEL_NoClock -#define RCC_CKOUTSRC_SYSCLK RCC_GCFGR_CKOUTSEL_SYSCLK -#define RCC_CKOUTSRC_HSI RCC_GCFGR_CKOUTSEL_HSI -#define RCC_CKOUTSRC_HSE RCC_GCFGR_CKOUTSEL_HSE -#define RCC_CKOUTSRC_PLLCLK_DIV2 RCC_GCFGR_CKOUTSEL_PLL_DIV2 -#define RCC_CKOUTSRC_PLL2CLK RCC_GCFGR_CKOUTSEL_PLL2 -#define RCC_CKOUTSRC_PLL3CLK RCC_GCFGR_CKOUTSEL_PLL3 -#define RCC_CKOUTSRC_PLL3CLK_DIV2 RCC_GCFGR_CKOUTSEL_PLL3_DIV2 -#define RCC_CKOUTSRC_EXT1 RCC_GCFGR_CKOUTSEL_EXT1 - -#else -#define RCC_CKOUTSRC_NOCLOCK RCC_GCFGR_CKOUTSEL_NoClock -#define RCC_CKOUTSRC_SYSCLK RCC_GCFGR_CKOUTSEL_SYSCLK -#define RCC_CKOUTSRC_HSI RCC_GCFGR_CKOUTSEL_HSI -#define RCC_CKOUTSRC_HSE RCC_GCFGR_CKOUTSEL_HSE -#define RCC_CKOUTSRC_PLLCLK_DIV2 RCC_GCFGR_CKOUTSEL_PLL_DIV2 - -#endif /* GD32F10X_CL */ - -/** - * @} - */ - -/** @defgroup RCC_Interrupt_Source - * @{ - */ -#define RCC_INT_LSISTB ((uint8_t)0x01) -#define RCC_INT_LSESTB ((uint8_t)0x02) -#define RCC_INT_HSISTB ((uint8_t)0x04) -#define RCC_INT_HSESTB ((uint8_t)0x08) -#define RCC_INT_PLLSTB ((uint8_t)0x10) -#define RCC_INT_CKM ((uint8_t)0x80) - -#ifdef GD32F10X_CL -#define RCC_INT_PLL2STB ((uint8_t)0x20) -#define RCC_INT_PLL3STB ((uint8_t)0x40) -#endif /* GD32F10X_CL */ - -/** - * @} - */ - -#ifdef GD32F10X_CL -/** @defgroup RCC_I2S2_clock_source - * @{ - */ -#define RCC_I2S2CLK_SYSCLK RCC_GCFGR2_I2S2SEL_CK_SYS -#define RCC_I2S2CLK_PLL3 RCC_GCFGR2_I2S2SEL_PLL3 - -/** - * @} - */ - -/** @defgroup RCC_I2S3_clock_source - * @{ - */ -#define RCC_I2S3CLK_SYSCLK RCC_GCFGR2_I2S3SEL_CK_SYS -#define RCC_I2S3CLK_PLL3 RCC_GCFGR2_I2S3SEL_PLL3 - -/** - * @} - */ -#endif /* GD32F10X_CL */ - - - -/** @defgroup RCC_LSE_configuration - * @{ - */ -#define RCC_LSE_OFF ((uint32_t)0x00000000) -#define RCC_LSE_EN RCC_BDCR_LSEEN -#define RCC_LSE_BYPASS ((uint32_t)(RCC_BDCR_LSEEN | RCC_BDCR_LSEBPS)) - -/** - * @} - */ - -/** @defgroup RCC_RTC_clock_source - * @{ - */ -#define RCC_RTCCLKSOURCE_LSE RCC_BDCR_RTCSEL_LSE -#define RCC_RTCCLKSOURCE_LSI RCC_BDCR_RTCSEL_LSI -#define RCC_RTCCLKSOURCE_HSE_DIV128 RCC_BDCR_RTCSEL_HSE128 - -/** - * @} - */ - -/** @defgroup RCC_AHB_peripheral - * @{ - */ -#define RCC_AHBPERIPH_DMA1 RCC_AHBCCR_DMA1EN -#define RCC_AHBPERIPH_DMA2 RCC_AHBCCR_DMA2EN -#define RCC_AHBPERIPH_SRAM RCC_AHBCCR_SRAMEN -#define RCC_AHBPERIPH_FMC RCC_AHBCCR_FMCEN -#define RCC_AHBPERIPH_CRC RCC_AHBCCR_CRCEN -#define RCC_AHBPERIPH_EXMC RCC_AHBCCR_EXMCEN - -#ifdef GD32F10X_CL -#define RCC_AHBPERIPH_OTG_FS RCC_AHBCCR_OTGFSEN -#define RCC_AHBPERIPH_ETH_MAC RCC_AHBCCR_ETHMACEN -#define RCC_AHBPERIPH_ETH_MAC_RX RCC_AHBCCR_ETHMACRXEN -#define RCC_AHBPERIPH_ETH_MAC_TX RCC_AHBCCR_ETHMACTXEN - -#else -#define RCC_AHBPERIPH_SDIO RCC_AHBCCR_SDIOEN -#endif/* GD32F10X_CL */ - -/** - * @} - */ - -/** @defgroup RCC_AHB_Peripherals_RST - * @{ - */ -#ifdef GD32F10X_CL -#define RCC_AHBPERIPH_OTGFSRST RCC_AHBRCR_OTGFSRST -#define RCC_AHBPERIPH_ETHMACRST RCC_AHBRCR_ETHMACRST - -#endif/* GD32F10X_CL */ - -/** - * @} - */ - -/** @defgroup RCC_APB2_peripheral - * @{ - */ -#define RCC_APB2PERIPH_AF RCC_APB2CCR_AFEN -#define RCC_APB2PERIPH_GPIOA RCC_APB2CCR_PAEN -#define RCC_APB2PERIPH_GPIOB RCC_APB2CCR_PBEN -#define RCC_APB2PERIPH_GPIOC RCC_APB2CCR_PCEN -#define RCC_APB2PERIPH_GPIOD RCC_APB2CCR_PDEN -#define RCC_APB2PERIPH_GPIOE RCC_APB2CCR_PEEN -#define RCC_APB2PERIPH_GPIOF RCC_APB2CCR_PFEN -#define RCC_APB2PERIPH_GPIOG RCC_APB2CCR_PGEN -#define RCC_APB2PERIPH_ADC0 RCC_APB2CCR_ADC0EN -#define RCC_APB2PERIPH_ADC1 RCC_APB2CCR_ADC1EN -#define RCC_APB2PERIPH_TIMER0 RCC_APB2CCR_TIMER0EN -#define RCC_APB2PERIPH_SPI1 RCC_APB2CCR_SPI1EN -#define RCC_APB2PERIPH_TIMER7 RCC_APB2CCR_TIMER7EN -#define RCC_APB2PERIPH_USART1 RCC_APB2CCR_USART1EN -#define RCC_APB2PERIPH_ADC2 RCC_APB2CCR_ADC2EN -#define RCC_APB2PERIPH_TIMER8 RCC_APB2CCR_TIMER8EN -#define RCC_APB2PERIPH_TIMER9 RCC_APB2CCR_TIMER9EN -#define RCC_APB2PERIPH_TIMER10 RCC_APB2CCR_TIMER10EN - -/** - * @} - */ - -/** @defgroup RCC_APB2_Peripherals_RST - * @{ - */ -#define RCC_APB2PERIPH_AFRST RCC_APB2RCR_AFRST -#define RCC_APB2PERIPH_GPIOARST RCC_APB2RCR_PARST -#define RCC_APB2PERIPH_GPIOBRST RCC_APB2RCR_PBRST -#define RCC_APB2PERIPH_GPIOCRST RCC_APB2RCR_PCRST -#define RCC_APB2PERIPH_GPIODRST RCC_APB2RCR_PDRST -#define RCC_APB2PERIPH_GPIOERST RCC_APB2RCR_PERST -#define RCC_APB2PERIPH_GPIOFRST RCC_APB2RCR_PFRST -#define RCC_APB2PERIPH_GPIOGRST RCC_APB2RCR_PGRST -#define RCC_APB2PERIPH_ADC0RST RCC_APB2RCR_ADC0RST -#define RCC_APB2PERIPH_ADC1RST RCC_APB2RCR_ADC1RST -#define RCC_APB2PERIPH_TIMER0RST RCC_APB2RCR_TIMER0RST -#define RCC_APB2PERIPH_SPI1RST RCC_APB2RCR_SPI1RST -#define RCC_APB2PERIPH_TIMER7RST RCC_APB2RCR_TIMER7RST -#define RCC_APB2PERIPH_USART0RST RCC_APB2RCR_USART0RST -#define RCC_APB2PERIPH_ADC2RST RCC_APB2RCR_ADC2RST -#define RCC_APB2PERIPH_TIMER8RST RCC_APB2RCR_TIMER8RST -#define RCC_APB2PERIPH_TIMER9RST RCC_APB2RCR_TIMER9RST -#define RCC_APB2PERIPH_TIMER10RST RCC_APB2RCR_TIMER10RST - -/** - * @} - */ - -/** @defgroup RCC_APB1_peripheral - * @{ - */ -#define RCC_APB1PERIPH_TIMER1 RCC_APB1CCR_TIMER1EN -#define RCC_APB1PERIPH_TIMER2 RCC_APB1CCR_TIMER2EN -#define RCC_APB1PERIPH_TIMER3 RCC_APB1CCR_TIMER3EN -#define RCC_APB1PERIPH_TIMER4 RCC_APB1CCR_TIMER4EN -#define RCC_APB1PERIPH_TIMER5 RCC_APB1CCR_TIMER5EN -#define RCC_APB1PERIPH_TIMER6 RCC_APB1CCR_TIMER6EN -#define RCC_APB1PERIPH_TIMER11 RCC_APB1CCR_TIMER11EN -#define RCC_APB1PERIPH_TIMER12 RCC_APB1CCR_TIMER12EN -#define RCC_APB1PERIPH_TIMER13 RCC_APB1CCR_TIMER13EN -#define RCC_APB1PERIPH_WWDG RCC_APB1CCR_WWDGEN -#define RCC_APB1PERIPH_SPI2 RCC_APB1CCR_SPI2EN -#define RCC_APB1PERIPH_SPI3 RCC_APB1CCR_SPI3EN -#define RCC_APB1PERIPH_USART2 RCC_APB1CCR_USART2EN -#define RCC_APB1PERIPH_USART3 RCC_APB1CCR_USART3EN -#define RCC_APB1PERIPH_UART4 RCC_APB1CCR_UART4EN -#define RCC_APB1PERIPH_UART5 RCC_APB1CCR_UART5EN -#define RCC_APB1PERIPH_I2C1 RCC_APB1CCR_I2C1EN -#define RCC_APB1PERIPH_I2C2 RCC_APB1CCR_I2C2EN -#define RCC_APB1PERIPH_USB RCC_APB1CCR_USBEN -#define RCC_APB1PERIPH_CAN1 RCC_APB1CCR_CAN1EN -#define RCC_APB1PERIPH_CAN2 RCC_APB1CCR_CAN2EN -#define RCC_APB1PERIPH_BKP RCC_APB1CCR_BKPEN -#define RCC_APB1PERIPH_PWR RCC_APB1CCR_PWREN -#define RCC_APB1PERIPH_DAC RCC_APB1CCR_DACEN - -/** - * @} - */ - -/** @defgroup RCC_APB1_Peripherals_RST - * @{ - */ -#define RCC_APB1PERIPH_TIMER1RST RCC_APB1RCR_TIMER1RST -#define RCC_APB1PERIPH_TIMER2RST RCC_APB1RCR_TIMER2RST -#define RCC_APB1PERIPH_TIMER3RST RCC_APB1RCR_TIMER3RST -#define RCC_APB1PERIPH_TIMER4RST RCC_APB1RCR_TIMER4RST -#define RCC_APB1PERIPH_TIMER5RST RCC_APB1RCR_TIMER5RST -#define RCC_APB1PERIPH_TIMER6RST RCC_APB1RCR_TIMER6RST -#define RCC_APB1PERIPH_TIMER11RST RCC_APB1RCR_TIMER11RST -#define RCC_APB1PERIPH_TIMER12RST RCC_APB1RCR_TIMER12RST -#define RCC_APB1PERIPH_TIMER13RST RCC_APB1RCR_TIMER13RST -#define RCC_APB1PERIPH_WWDGRST RCC_APB1RCR_WWDGRST -#define RCC_APB1PERIPH_SPI2RST RCC_APB1RCR_SPI2RST -#define RCC_APB1PERIPH_SPI3RST RCC_APB1RCR_SPI3RST -#define RCC_APB1PERIPH_USART1RST RCC_APB1RCR_USART1RST -#define RCC_APB1PERIPH_USART2RST RCC_APB1RCR_USART2RST -#define RCC_APB1PERIPH_UART3RST RCC_APB1RCR_UART3RST -#define RCC_APB1PERIPH_UART4RST RCC_APB1RCR_UART4RST -#define RCC_APB1PERIPH_I2C1RST RCC_APB1RCR_I2C1RST -#define RCC_APB1PERIPH_I2C2RST RCC_APB1RCR_I2C2RST -#define RCC_APB1PERIPH_USBRST RCC_APB1RCR_USBRST -#define RCC_APB1PERIPH_CAN1RST RCC_APB1RCR_CAN1RST -#define RCC_APB1PERIPH_CAN2RST RCC_APB1RCR_CAN2RST -#define RCC_APB1PERIPH_BKPRST RCC_APB1RCR_BKPRST -#define RCC_APB1PERIPH_PWRRST RCC_APB1RCR_PWRRST -#define RCC_APB1PERIPH_DACRST RCC_APB1RCR_DACRST - -/** - * @} - */ - -/** @defgroup RCC_Flag - * @{ - */ -/* The flag to check is in GCCR register */ -#define RCC_FLAG_HSISTB ((uint8_t)0x21) -#define RCC_FLAG_HSESTB ((uint8_t)0x31) -#define RCC_FLAG_PLLSTB ((uint8_t)0x39) - -/* The flag to check is in BDCR register */ -#define RCC_FLAG_LSESTB ((uint8_t)0x41) - -/* The flag to check is in GCSR register */ -#define RCC_FLAG_LSISTB ((uint8_t)0x61) - -#define RCC_FLAG_EPRST ((uint8_t)0x7A) -#define RCC_FLAG_POPDRST ((uint8_t)0x7B) -#define RCC_FLAG_SWRRST ((uint8_t)0x7C) -#define RCC_FLAG_IWDGRST ((uint8_t)0x7D) -#define RCC_FLAG_WWDGRST ((uint8_t)0x7E) -#define RCC_FLAG_LPRRST ((uint8_t)0x7F) - -#ifdef GD32F10X_CL -/* The flag to check is in GCCR register */ -#define RCC_FLAG_PLL2STB ((uint8_t)0x3B) -#define RCC_FLAG_PLL3STB ((uint8_t)0x3D) - -#endif/* GD32F10X_CL */ -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup RCC_Exported_Functions - * @{ - */ -/* Reset the RCC clock configuration to the default reset state */ - -void RCC_DeInit(void); - -/* Internal/external clocks, PLL, CKM and CK_OUT configuration functions */ - -void RCC_HSEConfig(uint32_t RCC_HSE); -TypeState RCC_WaitForHSEStartUp(void); -void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue); -void RCC_HSI_Enable(TypeState NewValue); -void RCC_PLLConfig(uint32_t RCC_PLLSelect, uint32_t RCC_PLLMF); -void RCC_PLL_Enable(TypeState NewValue); -void RCC_LSEConfig(uint32_t RCC_LSE); -void RCC_LSI_Enable(TypeState NewValue); -void RCC_HSEClockMonitor_Enable(TypeState NewValue); -void RCC_CKOUTSRCConfig(uint32_t RCC_CKOUTSRC); - -#ifdef GD32F10X_CL -void RCC_PREDV1Config(uint32_t RCC_PREDV1_Source, uint32_t RCC_PREDV1_Div); -void RCC_PREDV2Config(uint32_t RCC_PREDV2_Div); -void RCC_PLL2Config(uint32_t RCC_PLL2MF); -void RCC_PLL2_Enable(TypeState NewValue); -void RCC_PLL3Config(uint32_t RCC_PLL3MF); -void RCC_PLL3_Enable(TypeState NewValue); -#endif /* GD32F10X_CL */ - -/* System, AHB, APB1 and APB2 busses clocks configuration functions */ - -void RCC_CK_SYSConfig(uint32_t RCC_SYSCLKSource); -uint8_t RCC_GetCK_SYSSource(void); -void RCC_AHBConfig(uint32_t RCC_CK_SYSDiv); -void RCC_APB1Config(uint32_t RCC_APB1); -void RCC_APB2Config(uint32_t RCC_APB2); - -#ifndef GD32F10X_CL -void RCC_USBCLKConfig(uint32_t RCC_USBCLK); -#else -void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLK); -#endif /* GD32F10X_CL */ - -void RCC_ADCCLKConfig(uint32_t RCC_ADCCLK); - -#ifdef GD32F10X_CL -void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLK); -void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLK); -#endif /* GD32F10X_CL */ - -void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource); -void RCC_GetClocksFreq(RCC_ClocksPara *RCC_Clocks); - -/* Peripheral clocks configuration functions */ - -void RCC_AHBPeriphClock_Enable(uint32_t RCC_AHBPeriph, TypeState NewValue); -void RCC_APB2PeriphClock_Enable(uint32_t RCC_APB2Periph, TypeState NewValue); -void RCC_APB1PeriphClock_Enable(uint32_t RCC_APB1Periph, TypeState NewValue); -void RCC_RTCCLK_Enable(TypeState NewValue); - -#ifdef GD32F10X_CL -void RCC_AHBPeriphReset_Enable(uint32_t RCC_AHBPeriphRST, TypeState NewValue); -#endif /* GD32F10X_CL */ - -void RCC_APB2PeriphReset_Enable(uint32_t RCC_APB2PeriphRST, TypeState NewValue); -void RCC_APB1PeriphReset_Enable(uint32_t RCC_APB1PeriphRST, TypeState NewValue); -void RCC_BackupReset_Enable(TypeState NewValue); - -/* Interrupts and flags management functions */ - -void RCC_INTConfig(uint8_t RCC_INT, TypeState NewValue); -TypeState RCC_GetIntBitState(uint8_t RCC_INT); -void RCC_ClearIntBitState(uint8_t RCC_INT); -TypeState RCC_GetBitState(uint8_t RCC_FLAG); -void RCC_ClearBitState(void); - -void RCC_KERNELVOLConfig(uint32_t RCC_KERNEL_VOL); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10x_RCC_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcu.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcu.h deleted file mode 100644 index d63ce98930..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rcu.h +++ /dev/null @@ -1,1019 +0,0 @@ -/*! - \file gd32f10x_rcu.h - \brief definitions for the RCU -*/ - -/* - Copyright (C) 2017 GigaDevice - - 2017-02-10, V1.0.1, firmware for GD32F30x - 2021-01-02, firmware for GD32F10x -*/ - -#ifndef GD32F10X_RCU_H -#define GD32F10X_RCU_H - -#include "gd32f10x.h" - -/* RCU definitions */ -#define RCU RCU_BASE - -/* registers definitions */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ - #define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ - #define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ - #define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ - #define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ - #define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB enable register */ - #define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ - #define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ - #define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ - #define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ - #define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ - #define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ - #define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ - #define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ - #define RCU_ADDAPB1RST REG32(RCU + 0xE0U) /*!< APB1 additional reset register */ - #define RCU_ADDAPB1EN REG32(RCU + 0xE4U) /*!< APB1 additional enable register */ -#elif defined(GD32F10X_CL) - #define RCU_CTL REG32(RCU + 0x00U) /*!< control register */ - #define RCU_CFG0 REG32(RCU + 0x04U) /*!< clock configuration register 0 */ - #define RCU_INT REG32(RCU + 0x08U) /*!< clock interrupt register */ - #define RCU_APB2RST REG32(RCU + 0x0CU) /*!< APB2 reset register */ - #define RCU_APB1RST REG32(RCU + 0x10U) /*!< APB1 reset register */ - #define RCU_AHBEN REG32(RCU + 0x14U) /*!< AHB1 enable register */ - #define RCU_APB2EN REG32(RCU + 0x18U) /*!< APB2 enable register */ - #define RCU_APB1EN REG32(RCU + 0x1CU) /*!< APB1 enable register */ - #define RCU_BDCTL REG32(RCU + 0x20U) /*!< backup domain control register */ - #define RCU_RSTSCK REG32(RCU + 0x24U) /*!< reset source / clock register */ - #define RCU_AHBRST REG32(RCU + 0x28U) /*!< AHB reset register */ - #define RCU_CFG1 REG32(RCU + 0x2CU) /*!< clock configuration register 1 */ - #define RCU_DSV REG32(RCU + 0x34U) /*!< deep-sleep mode voltage register */ - #define RCU_ADDCTL REG32(RCU + 0xC0U) /*!< Additional clock control register */ - #define RCU_ADDINT REG32(RCU + 0xCCU) /*!< Additional clock interrupt register */ - #define RCU_ADDAPB1RST REG32(RCU + 0xE0U) /*!< APB1 additional reset register */ - #define RCU_ADDAPB1EN REG32(RCU + 0xE4U) /*!< APB1 additional enable register */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* bits definitions */ -/* RCU_CTL */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ - #define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ - #define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ - #define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ - #define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ - #define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ - #define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ - #define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ - #define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ - #define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ -#elif defined(GD32F10X_CL) - #define RCU_CTL_IRC8MEN BIT(0) /*!< internal high speed oscillator enable */ - #define RCU_CTL_IRC8MSTB BIT(1) /*!< IRC8M high speed internal oscillator stabilization flag */ - #define RCU_CTL_IRC8MADJ BITS(3,7) /*!< high speed internal oscillator clock trim adjust value */ - #define RCU_CTL_IRC8MCALIB BITS(8,15) /*!< high speed internal oscillator calibration value register */ - #define RCU_CTL_HXTALEN BIT(16) /*!< external high speed oscillator enable */ - #define RCU_CTL_HXTALSTB BIT(17) /*!< external crystal oscillator clock stabilization flag */ - #define RCU_CTL_HXTALBPS BIT(18) /*!< external crystal oscillator clock bypass mode enable */ - #define RCU_CTL_CKMEN BIT(19) /*!< HXTAL clock monitor enable */ - #define RCU_CTL_PLLEN BIT(24) /*!< PLL enable */ - #define RCU_CTL_PLLSTB BIT(25) /*!< PLL clock stabilization flag */ - #define RCU_CTL_PLL1EN BIT(26) /*!< PLL1 enable */ - #define RCU_CTL_PLL1STB BIT(27) /*!< PLL1 clock stabilization flag */ - #define RCU_CTL_PLL2EN BIT(28) /*!< PLL2 enable */ - #define RCU_CTL_PLL2STB BIT(29) /*!< PLL2 clock stabilization flag */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* RCU_CFG0 */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ - #define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ - #define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ - #define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ - #define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ - #define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ - #define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ - #define RCU_CFG0_PREDV0 BIT(17) /*!< PREDV0 division factor */ - #define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ - #define RCU_CFG0_USBDPSC BITS(22,23) /*!< USBD clock prescaler selection */ - #define RCU_CFG0_CKOUT0SEL BITS(24,26) /*!< CKOUT0 clock source selection */ - #define RCU_CFG0_PLLMF_4 BIT(27) /*!< bit 4 of PLLMF */ - #define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ - #define RCU_CFG0_PLLMF_5 BIT(30) /*!< bit 5 of PLLMF */ - #define RCU_CFG0_USBDPSC_2 BIT(31) /*!< bit 2 of USBDPSC */ -#elif defined(GD32F10X_CL) - #define RCU_CFG0_SCS BITS(0,1) /*!< system clock switch */ - #define RCU_CFG0_SCSS BITS(2,3) /*!< system clock switch status */ - #define RCU_CFG0_AHBPSC BITS(4,7) /*!< AHB prescaler selection */ - #define RCU_CFG0_APB1PSC BITS(8,10) /*!< APB1 prescaler selection */ - #define RCU_CFG0_APB2PSC BITS(11,13) /*!< APB2 prescaler selection */ - #define RCU_CFG0_ADCPSC BITS(14,15) /*!< ADC prescaler selection */ - #define RCU_CFG0_PLLSEL BIT(16) /*!< PLL clock source selection */ - #define RCU_CFG0_PREDV0_LSB BIT(17) /*!< the LSB of PREDV0 division factor */ - #define RCU_CFG0_PLLMF BITS(18,21) /*!< PLL clock multiplication factor */ - #define RCU_CFG0_USBFSPSC BITS(22,23) /*!< USBFS clock prescaler selection */ - #define RCU_CFG0_CKOUT0SEL BITS(24,27) /*!< CKOUT0 clock source selection */ - #define RCU_CFG0_ADCPSC_2 BIT(28) /*!< bit 2 of ADCPSC */ - #define RCU_CFG0_PLLMF_4 BIT(29) /*!< bit 4 of PLLMF */ - #define RCU_CFG0_PLLMF_5 BIT(30) /*!< bit 5 of PLLMF */ - #define RCU_CFG0_USBFSPSC_2 BIT(31) /*!< bit 2 of USBFSPSC */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* RCU_INT */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ - #define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ - #define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ - #define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ - #define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ - #define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ - #define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ - #define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ - #define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ - #define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ - #define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ - #define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K Stabilization interrupt clear */ - #define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL Stabilization interrupt clear */ - #define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M Stabilization interrupt clear */ - #define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL Stabilization interrupt clear */ - #define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ - #define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ -#elif defined(GD32F10X_CL) - #define RCU_INT_IRC40KSTBIF BIT(0) /*!< IRC40K stabilization interrupt flag */ - #define RCU_INT_LXTALSTBIF BIT(1) /*!< LXTAL stabilization interrupt flag */ - #define RCU_INT_IRC8MSTBIF BIT(2) /*!< IRC8M stabilization interrupt flag */ - #define RCU_INT_HXTALSTBIF BIT(3) /*!< HXTAL stabilization interrupt flag */ - #define RCU_INT_PLLSTBIF BIT(4) /*!< PLL stabilization interrupt flag */ - #define RCU_INT_PLL1STBIF BIT(5) /*!< PLL1 stabilization interrupt flag */ - #define RCU_INT_PLL2STBIF BIT(6) /*!< PLL2 stabilization interrupt flag */ - #define RCU_INT_CKMIF BIT(7) /*!< HXTAL clock stuck interrupt flag */ - #define RCU_INT_IRC40KSTBIE BIT(8) /*!< IRC40K stabilization interrupt enable */ - #define RCU_INT_LXTALSTBIE BIT(9) /*!< LXTAL stabilization interrupt enable */ - #define RCU_INT_IRC8MSTBIE BIT(10) /*!< IRC8M stabilization interrupt enable */ - #define RCU_INT_HXTALSTBIE BIT(11) /*!< HXTAL stabilization interrupt enable */ - #define RCU_INT_PLLSTBIE BIT(12) /*!< PLL stabilization interrupt enable */ - #define RCU_INT_PLL1STBIE BIT(13) /*!< PLL1 stabilization interrupt enable */ - #define RCU_INT_PLL2STBIE BIT(14) /*!< PLL2 stabilization interrupt enable */ - #define RCU_INT_IRC40KSTBIC BIT(16) /*!< IRC40K stabilization interrupt clear */ - #define RCU_INT_LXTALSTBIC BIT(17) /*!< LXTAL stabilization interrupt clear */ - #define RCU_INT_IRC8MSTBIC BIT(18) /*!< IRC8M stabilization interrupt clear */ - #define RCU_INT_HXTALSTBIC BIT(19) /*!< HXTAL stabilization interrupt clear */ - #define RCU_INT_PLLSTBIC BIT(20) /*!< PLL stabilization interrupt clear */ - #define RCU_INT_PLL1STBIC BIT(21) /*!< PLL1 stabilization interrupt clear */ - #define RCU_INT_PLL2STBIC BIT(22) /*!< PLL2 stabilization interrupt clear */ - #define RCU_INT_CKMIC BIT(23) /*!< HXTAL clock stuck interrupt clear */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* RCU_APB2RST */ -#define RCU_APB2RST_AFRST BIT(0) /*!< alternate function I/O reset */ -#define RCU_APB2RST_PARST BIT(2) /*!< GPIO port A reset */ -#define RCU_APB2RST_PBRST BIT(3) /*!< GPIO port B reset */ -#define RCU_APB2RST_PCRST BIT(4) /*!< GPIO port C reset */ -#define RCU_APB2RST_PDRST BIT(5) /*!< GPIO port D reset */ -#define RCU_APB2RST_PERST BIT(6) /*!< GPIO port E reset */ -#define RCU_APB2RST_PFRST BIT(7) /*!< GPIO port F reset */ -#define RCU_APB2RST_PGRST BIT(8) /*!< GPIO port G reset */ -#define RCU_APB2RST_ADC0RST BIT(9) /*!< ADC0 reset */ -#define RCU_APB2RST_ADC1RST BIT(10) /*!< ADC1 reset */ -#define RCU_APB2RST_TIMER0RST BIT(11) /*!< TIMER0 reset */ -#define RCU_APB2RST_SPI0RST BIT(12) /*!< SPI0 reset */ -#define RCU_APB2RST_TIMER7RST BIT(13) /*!< TIMER7 reset */ -#define RCU_APB2RST_USART0RST BIT(14) /*!< USART0 reset */ -#ifndef GD32F10X_CL - #define RCU_APB2RST_ADC2RST BIT(15) /*!< ADC2 reset */ -#endif /* GD32F10X_CL */ -#ifndef GD32F10X_HD - #define RCU_APB2RST_TIMER8RST BIT(19) /*!< TIMER8 reset */ - #define RCU_APB2RST_TIMER9RST BIT(20) /*!< TIMER9 reset */ - #define RCU_APB2RST_TIMER10RST BIT(21) /*!< TIMER10 reset */ -#endif /* GD32F10X_HD */ - -/* RCU_APB1RST */ -#define RCU_APB1RST_TIMER1RST BIT(0) /*!< TIMER1 reset */ -#define RCU_APB1RST_TIMER2RST BIT(1) /*!< TIMER2 reset */ -#define RCU_APB1RST_TIMER3RST BIT(2) /*!< TIMER3 reset */ -#define RCU_APB1RST_TIMER4RST BIT(3) /*!< TIMER4 reset */ -#define RCU_APB1RST_TIMER5RST BIT(4) /*!< TIMER5 reset */ -#define RCU_APB1RST_TIMER6RST BIT(5) /*!< TIMER6 reset */ -#ifndef GD32F10X_HD - #define RCU_APB1RST_TIMER11RST BIT(6) /*!< TIMER11 reset */ - #define RCU_APB1RST_TIMER12RST BIT(7) /*!< TIMER12 reset */ - #define RCU_APB1RST_TIMER13RST BIT(8) /*!< TIMER13 reset */ -#endif /* GD32F10X_HD */ -#define RCU_APB1RST_WWDGTRST BIT(11) /*!< WWDGT reset */ -#define RCU_APB1RST_SPI1RST BIT(14) /*!< SPI1 reset */ -#define RCU_APB1RST_SPI2RST BIT(15) /*!< SPI2 reset */ -#define RCU_APB1RST_USART1RST BIT(17) /*!< USART1 reset */ -#define RCU_APB1RST_USART2RST BIT(18) /*!< USART2 reset */ -#define RCU_APB1RST_UART3RST BIT(19) /*!< UART3 reset */ -#define RCU_APB1RST_UART4RST BIT(20) /*!< UART4 reset */ -#define RCU_APB1RST_I2C0RST BIT(21) /*!< I2C0 reset */ -#define RCU_APB1RST_I2C1RST BIT(22) /*!< I2C1 reset */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_APB1RST_USBDRST BIT(23) /*!< USBD reset */ -#endif /* GD32F10X_HD and GD32F10X_XD */ -#define RCU_APB1RST_CAN0RST BIT(25) /*!< CAN0 reset */ -#ifdef GD32F10X_CL - #define RCU_APB1RST_CAN1RST BIT(26) /*!< CAN1 reset */ -#endif /* GD32F10X_CL */ -#define RCU_APB1RST_BKPIRST BIT(27) /*!< backup interface reset */ -#define RCU_APB1RST_PMURST BIT(28) /*!< PMU reset */ -#define RCU_APB1RST_DACRST BIT(29) /*!< DAC reset */ - -/* RCU_AHBEN */ -#define RCU_AHBEN_DMA0EN BIT(0) /*!< DMA0 clock enable */ -#define RCU_AHBEN_DMA1EN BIT(1) /*!< DMA1 clock enable */ -#define RCU_AHBEN_SRAMSPEN BIT(2) /*!< SRAM clock enable when sleep mode */ -#define RCU_AHBEN_FMCSPEN BIT(4) /*!< FMC clock enable when sleep mode */ -#define RCU_AHBEN_CRCEN BIT(6) /*!< CRC clock enable */ -#define RCU_AHBEN_EXMCEN BIT(8) /*!< EXMC clock enable */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_AHBEN_SDIOEN BIT(10) /*!< SDIO clock enable */ -#elif defined(GD32F10X_CL) - #define RCU_AHBEN_USBFSEN BIT(12) /*!< USBFS clock enable */ - #define RCU_AHBEN_ENETEN BIT(14) /*!< ENET clock enable */ - #define RCU_AHBEN_ENETTXEN BIT(15) /*!< Ethernet TX clock enable */ - #define RCU_AHBEN_ENETRXEN BIT(16) /*!< Ethernet RX clock enable */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* RCU_APB2EN */ -#define RCU_APB2EN_AFEN BIT(0) /*!< alternate function IO clock enable */ -#define RCU_APB2EN_PAEN BIT(2) /*!< GPIO port A clock enable */ -#define RCU_APB2EN_PBEN BIT(3) /*!< GPIO port B clock enable */ -#define RCU_APB2EN_PCEN BIT(4) /*!< GPIO port C clock enable */ -#define RCU_APB2EN_PDEN BIT(5) /*!< GPIO port D clock enable */ -#define RCU_APB2EN_PEEN BIT(6) /*!< GPIO port E clock enable */ -#define RCU_APB2EN_PFEN BIT(7) /*!< GPIO port F clock enable */ -#define RCU_APB2EN_PGEN BIT(8) /*!< GPIO port G clock enable */ -#define RCU_APB2EN_ADC0EN BIT(9) /*!< ADC0 clock enable */ -#define RCU_APB2EN_ADC1EN BIT(10) /*!< ADC1 clock enable */ -#define RCU_APB2EN_TIMER0EN BIT(11) /*!< TIMER0 clock enable */ -#define RCU_APB2EN_SPI0EN BIT(12) /*!< SPI0 clock enable */ -#define RCU_APB2EN_TIMER7EN BIT(13) /*!< TIMER7 clock enable */ -#define RCU_APB2EN_USART0EN BIT(14) /*!< USART0 clock enable */ -#ifndef GD32F10X_CL - #define RCU_APB2EN_ADC2EN BIT(15) /*!< ADC2 clock enable */ -#endif /* GD32F10X_CL */ -#ifndef GD32F10X_HD - #define RCU_APB2EN_TIMER8EN BIT(19) /*!< TIMER8 clock enable */ - #define RCU_APB2EN_TIMER9EN BIT(20) /*!< TIMER9 clock enable */ - #define RCU_APB2EN_TIMER10EN BIT(21) /*!< TIMER10 clock enable */ -#endif /* GD32F10X_HD */ - -/* RCU_APB1EN */ -#define RCU_APB1EN_TIMER1EN BIT(0) /*!< TIMER1 clock enable */ -#define RCU_APB1EN_TIMER2EN BIT(1) /*!< TIMER2 clock enable */ -#define RCU_APB1EN_TIMER3EN BIT(2) /*!< TIMER3 clock enable */ -#define RCU_APB1EN_TIMER4EN BIT(3) /*!< TIMER4 clock enable */ -#define RCU_APB1EN_TIMER5EN BIT(4) /*!< TIMER5 clock enable */ -#define RCU_APB1EN_TIMER6EN BIT(5) /*!< TIMER6 clock enable */ -#ifndef GD32F10X_HD - #define RCU_APB1EN_TIMER11EN BIT(6) /*!< TIMER11 clock enable */ - #define RCU_APB1EN_TIMER12EN BIT(7) /*!< TIMER12 clock enable */ - #define RCU_APB1EN_TIMER13EN BIT(8) /*!< TIMER13 clock enable */ -#endif /* GD32F10X_HD */ -#define RCU_APB1EN_WWDGTEN BIT(11) /*!< WWDGT clock enable */ -#define RCU_APB1EN_SPI1EN BIT(14) /*!< SPI1 clock enable */ -#define RCU_APB1EN_SPI2EN BIT(15) /*!< SPI2 clock enable */ -#define RCU_APB1EN_USART1EN BIT(17) /*!< USART1 clock enable */ -#define RCU_APB1EN_USART2EN BIT(18) /*!< USART2 clock enable */ -#define RCU_APB1EN_UART3EN BIT(19) /*!< UART3 clock enable */ -#define RCU_APB1EN_UART4EN BIT(20) /*!< UART4 clock enable */ -#define RCU_APB1EN_I2C0EN BIT(21) /*!< I2C0 clock enable */ -#define RCU_APB1EN_I2C1EN BIT(22) /*!< I2C1 clock enable */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_APB1EN_USBDEN BIT(23) /*!< USBD clock enable */ -#endif /* GD32F10X_HD and GD32F10X_XD */ -#define RCU_APB1EN_CAN0EN BIT(25) /*!< CAN0 clock enable */ -#ifdef GD32F10X_CL - #define RCU_APB1EN_CAN1EN BIT(26) /*!< CAN1 clock enable */ -#endif /* GD32F10X_CL */ -#define RCU_APB1EN_BKPIEN BIT(27) /*!< backup interface clock enable */ -#define RCU_APB1EN_PMUEN BIT(28) /*!< PMU clock enable */ -#define RCU_APB1EN_DACEN BIT(29) /*!< DAC clock enable */ - -/* RCU_BDCTL */ -#define RCU_BDCTL_LXTALEN BIT(0) /*!< LXTAL enable */ -#define RCU_BDCTL_LXTALSTB BIT(1) /*!< low speed crystal oscillator stabilization flag */ -#define RCU_BDCTL_LXTALBPS BIT(2) /*!< LXTAL bypass mode enable */ -#define RCU_BDCTL_LXTALDRI BITS(3,4) /*!< LXTAL drive capability */ -#define RCU_BDCTL_RTCSRC BITS(8,9) /*!< RTC clock entry selection */ -#define RCU_BDCTL_RTCEN BIT(15) /*!< RTC clock enable */ -#define RCU_BDCTL_BKPRST BIT(16) /*!< backup domain reset */ - -/* RCU_RSTSCK */ -#define RCU_RSTSCK_IRC40KEN BIT(0) /*!< IRC40K enable */ -#define RCU_RSTSCK_IRC40KSTB BIT(1) /*!< IRC40K stabilization flag */ -#define RCU_RSTSCK_RSTFC BIT(24) /*!< reset flag clear */ -#define RCU_RSTSCK_EPRSTF BIT(26) /*!< external pin reset flag */ -#define RCU_RSTSCK_PORRSTF BIT(27) /*!< power reset flag */ -#define RCU_RSTSCK_SWRSTF BIT(28) /*!< software reset flag */ -#define RCU_RSTSCK_FWDGTRSTF BIT(29) /*!< free watchdog timer reset flag */ -#define RCU_RSTSCK_WWDGTRSTF BIT(30) /*!< window watchdog timer reset flag */ -#define RCU_RSTSCK_LPRSTF BIT(31) /*!< low-power reset flag */ - -#ifdef GD32F10X_CL - /* RCU_AHBRST */ - #define RCU_AHBRST_USBFSRST BIT(12) /*!< USBFS reset */ - #define RCU_AHBRST_ENETRST BIT(14) /*!< ENET reset */ -#endif /* GD32F10X_CL */ - -/* RCU_CFG1 */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_CFG1_ADCPSC_3 BIT(29) /*!< bit 4 of ADCPSC */ - #define RCU_CFG1_PLLPRESEL BIT(30) /*!< PLL clock source selection */ -#elif defined(GD32F10X_CL) - #define RCU_CFG1_PREDV0 BITS(0,3) /*!< PREDV0 division factor */ - #define RCU_CFG1_PREDV1 BITS(4,7) /*!< PREDV1 division factor */ - #define RCU_CFG1_PLL1MF BITS(8,11) /*!< PLL1 clock multiplication factor */ - #define RCU_CFG1_PLL2MF BITS(12,15) /*!< PLL2 clock multiplication factor */ - #define RCU_CFG1_PREDV0SEL BIT(16) /*!< PREDV0 input clock source selection */ - #define RCU_CFG1_I2S1SEL BIT(17) /*!< I2S1 clock source selection */ - #define RCU_CFG1_I2S2SEL BIT(18) /*!< I2S2 clock source selection */ - #define RCU_CFG1_ADCPSC_3 BIT(29) /*!< bit 4 of ADCPSC */ - #define RCU_CFG1_PLLPRESEL BIT(30) /*!< PLL clock source selection */ - #define RCU_CFG1_PLL2MF_4 BIT(31) /*!< bit 5 of PLL2MF */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* RCU_DSV */ -#define RCU_DSV_DSLPVS BITS(0,2) /*!< deep-sleep mode voltage select */ - -/* RCU_ADDCTL */ -#define RCU_ADDCTL_CK48MSEL BIT(0) /*!< 48MHz clock selection */ -#define RCU_ADDCTL_IRC48MEN BIT(16) /*!< internal 48MHz RC oscillator enable */ -#define RCU_ADDCTL_IRC48MSTB BIT(17) /*!< internal 48MHz RC oscillator clock stabilization flag */ -#define RCU_ADDCTL_IRC48MCAL BITS(24,31) /*!< internal 48MHz RC oscillator calibration value register */ - -/* RCU_ADDINT */ -#define RCU_ADDINT_IRC48MSTBIF BIT(6) /*!< IRC48M stabilization interrupt flag */ -#define RCU_ADDINT_IRC48MSTBIE BIT(14) /*!< internal 48 MHz RC oscillator stabilization interrupt enable */ -#define RCU_ADDINT_IRC48MSTBIC BIT(22) /*!< internal 48 MHz RC oscillator stabilization interrupt clear */ - -/* RCU_ADDAPB1RST */ -#define RCU_ADDAPB1RST_CTCRST BIT(27) /*!< CTC reset */ - -/* RCU_ADDAPB1EN */ -#define RCU_ADDAPB1EN_CTCEN BIT(27) /*!< CTC clock enable */ - - -/* constants definitions */ -/* define the peripheral clock enable bit position and its register index offset */ -#define RCU_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) -#define RCU_REG_VAL(periph) (REG32(RCU + ((uint32_t)(periph) >> 6))) -#define RCU_BIT_POS(val) ((uint32_t)(val) & 0x1FU) - -/* register offset */ -/* peripherals enable */ -#define AHBEN_REG_OFFSET 0x14U /*!< AHB enable register offset */ -#define APB1EN_REG_OFFSET 0x1CU /*!< APB1 enable register offset */ -#define APB2EN_REG_OFFSET 0x18U /*!< APB2 enable register offset */ -#define ADD_APB1EN_REG_OFFSET 0xE4U /*!< APB1 additional enable register offset */ - -/* peripherals reset */ -#define AHBRST_REG_OFFSET 0x28U /*!< AHB reset register offset */ -#define APB1RST_REG_OFFSET 0x10U /*!< APB1 reset register offset */ -#define APB2RST_REG_OFFSET 0x0CU /*!< APB2 reset register offset */ -#define ADD_APB1RST_REG_OFFSET 0xE0U /*!< APB1 additional reset register offset */ -#define RSTSCK_REG_OFFSET 0x24U /*!< reset source/clock register offset */ - -/* clock control */ -#define CTL_REG_OFFSET 0x00U /*!< control register offset */ -#define BDCTL_REG_OFFSET 0x20U /*!< backup domain control register offset */ -#define ADDCTL_REG_OFFSET 0xC0U /*!< additional clock control register offset */ - -/* clock stabilization and stuck interrupt */ -#define INT_REG_OFFSET 0x08U /*!< clock interrupt register offset */ -#define ADDINT_REG_OFFSET 0xCCU /*!< additional clock interrupt register offset */ - -/* configuration register */ -#define CFG0_REG_OFFSET 0x04U /*!< clock configuration register 0 offset */ -#define CFG1_REG_OFFSET 0x2CU /*!< clock configuration register 1 offset */ - -/* peripheral clock enable */ -typedef enum { - /* AHB peripherals */ - RCU_DMA0 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 0U), /*!< DMA0 clock */ - RCU_DMA1 = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 1U), /*!< DMA1 clock */ - RCU_CRC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 6U), /*!< CRC clock */ - RCU_EXMC = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 8U), /*!< EXMC clock */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - RCU_SDIO = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 10U), /*!< SDIO clock */ -#elif defined(GD32F10X_CL) - RCU_USBFS = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 12U), /*!< USBFS clock */ - RCU_ENET = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 14U), /*!< ENET clock */ - RCU_ENETTX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 15U), /*!< ENETTX clock */ - RCU_ENETRX = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 16U), /*!< ENETRX clock */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - - /* APB1 peripherals */ - RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ - RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ - RCU_TIMER3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 2U), /*!< TIMER3 clock */ - RCU_TIMER4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 3U), /*!< TIMER4 clock */ - RCU_TIMER5 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 4U), /*!< TIMER5 clock */ - RCU_TIMER6 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 5U), /*!< TIMER6 clock */ -#ifndef GD32F10X_HD - RCU_TIMER11 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 6U), /*!< TIMER11 clock */ - RCU_TIMER12 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 7U), /*!< TIMER12 clock */ - RCU_TIMER13 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 8U), /*!< TIMER13 clock */ -#endif /* GD32F10X_HD */ - RCU_WWDGT = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 11U), /*!< WWDGT clock */ - RCU_SPI1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 14U), /*!< SPI1 clock */ - RCU_SPI2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 15U), /*!< SPI2 clock */ - RCU_USART1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 17U), /*!< USART1 clock */ - RCU_USART2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 18U), /*!< USART2 clock */ - RCU_UART3 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 19U), /*!< UART3 clock */ - RCU_UART4 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 20U), /*!< UART4 clock */ - RCU_I2C0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 21U), /*!< I2C0 clock */ - RCU_I2C1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 22U), /*!< I2C1 clock */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - RCU_USBD = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 23U), /*!< USBD clock */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - RCU_CAN0 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 25U), /*!< CAN0 clock */ -#ifdef GD32F10X_CL - RCU_CAN1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 26U), /*!< CAN1 clock */ -#endif /* GD32F10X_CL */ - RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ - RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ - RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ - RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ - RCU_CTC = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 27U), /*!< CTC clock */ - - /* APB2 peripherals */ - RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ - RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ - RCU_GPIOB = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 3U), /*!< GPIOB clock */ - RCU_GPIOC = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 4U), /*!< GPIOC clock */ - RCU_GPIOD = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 5U), /*!< GPIOD clock */ - RCU_GPIOE = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 6U), /*!< GPIOE clock */ - RCU_GPIOF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 7U), /*!< GPIOF clock */ - RCU_GPIOG = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 8U), /*!< GPIOG clock */ - RCU_ADC0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 9U), /*!< ADC0 clock */ - RCU_ADC1 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 10U), /*!< ADC1 clock */ - RCU_TIMER0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 11U), /*!< TIMER0 clock */ - RCU_SPI0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 12U), /*!< SPI0 clock */ - RCU_TIMER7 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 13U), /*!< TIMER7 clock */ - RCU_USART0 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 14U), /*!< USART0 clock */ -#ifndef GD32F10X_CL - RCU_ADC2 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 15U), /*!< ADC2 clock */ -#endif /* GD32F10X_CL */ -#ifndef GD32F10X_HD - RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ - RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ - RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ -#endif /* GD32F10X_HD */ -} rcu_periph_enum; - -/* peripheral clock enable when sleep mode*/ -typedef enum { - /* AHB peripherals */ - RCU_SRAM_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 2U), /*!< SRAM clock */ - RCU_FMC_SLP = RCU_REGIDX_BIT(AHBEN_REG_OFFSET, 4U), /*!< FMC clock */ -} rcu_periph_sleep_enum; - -/* peripherals reset */ -typedef enum { - /* AHB peripherals */ -#ifdef GD32F10X_CL - RCU_USBFSRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 12U), /*!< USBFS clock reset */ - RCU_ENETRST = RCU_REGIDX_BIT(AHBRST_REG_OFFSET, 14U), /*!< ENET clock reset */ -#endif /* GD32F10X_CL */ - - /* APB1 peripherals */ - RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ - RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ - RCU_TIMER3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 2U), /*!< TIMER3 clock reset */ - RCU_TIMER4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 3U), /*!< TIMER4 clock reset */ - RCU_TIMER5RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 4U), /*!< TIMER5 clock reset */ - RCU_TIMER6RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 5U), /*!< TIMER6 clock reset */ -#ifndef GD32F10X_HD - RCU_TIMER11RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 6U), /*!< TIMER11 clock reset */ - RCU_TIMER12RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 7U), /*!< TIMER12 clock reset */ - RCU_TIMER13RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 8U), /*!< TIMER13 clock reset */ -#endif /* GD32F10X_HD */ - RCU_WWDGTRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 11U), /*!< WWDGT clock reset */ - RCU_SPI1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 14U), /*!< SPI1 clock reset */ - RCU_SPI2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 15U), /*!< SPI2 clock reset */ - RCU_USART1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 17U), /*!< USART1 clock reset */ - RCU_USART2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 18U), /*!< USART2 clock reset */ - RCU_UART3RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 19U), /*!< UART3 clock reset */ - RCU_UART4RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 20U), /*!< UART4 clock reset */ - RCU_I2C0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 21U), /*!< I2C0 clock reset */ - RCU_I2C1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 22U), /*!< I2C1 clock reset */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - RCU_USBDRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 23U), /*!< USBD clock reset */ -#endif /* GD32F10X_HD and GD32F10X_XD */ - RCU_CAN0RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 25U), /*!< CAN0 clock reset */ -#ifdef GD32F10X_CL - RCU_CAN1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 26U), /*!< CAN1 clock reset */ -#endif /* GD32F10X_CL */ - RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ - RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ - RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ - RCU_CTCRST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 27U), /*!< RTC clock reset */ - - /* APB2 peripherals */ - RCU_AFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 0U), /*!< alternate function clock reset */ - RCU_GPIOARST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 2U), /*!< GPIOA clock reset */ - RCU_GPIOBRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 3U), /*!< GPIOB clock reset */ - RCU_GPIOCRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 4U), /*!< GPIOC clock reset */ - RCU_GPIODRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 5U), /*!< GPIOD clock reset */ - RCU_GPIOERST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 6U), /*!< GPIOE clock reset */ - RCU_GPIOFRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 7U), /*!< GPIOF clock reset */ - RCU_GPIOGRST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 8U), /*!< GPIOG clock reset */ - RCU_ADC0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 9U), /*!< ADC0 clock reset */ - RCU_ADC1RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 10U), /*!< ADC1 clock reset */ - RCU_TIMER0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 11U), /*!< TIMER0 clock reset */ - RCU_SPI0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 12U), /*!< SPI0 clock reset */ - RCU_TIMER7RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 13U), /*!< TIMER7 clock reset */ - RCU_USART0RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 14U), /*!< USART0 clock reset */ -#ifndef GD32F10X_CL - RCU_ADC2RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 15U), /*!< ADC2 clock reset */ -#endif /* GD32F10X_CL */ -#ifndef GD32F10X_HD - RCU_TIMER8RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 19U), /*!< TIMER8 clock reset */ - RCU_TIMER9RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 20U), /*!< TIMER9 clock reset */ - RCU_TIMER10RST = RCU_REGIDX_BIT(APB2RST_REG_OFFSET, 21U), /*!< TIMER10 clock reset */ -#endif /* GD32F10X_HD */ -} rcu_periph_reset_enum; - -/* clock stabilization and peripheral reset flags */ -typedef enum { - /* clock stabilization flags */ - RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ - RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ - RCU_FLAG_PLLSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 25U), /*!< PLL stabilization flags */ -#ifdef GD32F10X_CL - RCU_FLAG_PLL1STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 27U), /*!< PLL1 stabilization flags */ - RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ -#endif /* GD32F10X_CL */ - RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ - RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ - RCU_FLAG_IRC48MSTB = RCU_REGIDX_BIT(ADDCTL_REG_OFFSET, 17U), /*!< IRC48M stabilization flags */ - /* reset source flags */ - RCU_FLAG_EPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 26U), /*!< external PIN reset flags */ - RCU_FLAG_PORRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 27U), /*!< power reset flags */ - RCU_FLAG_SWRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 28U), /*!< software reset flags */ - RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ - RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ - RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ -} rcu_flag_enum; - -/* clock stabilization and ckm interrupt flags */ -typedef enum { - RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ - RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ - RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ - RCU_INT_FLAG_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 3U), /*!< HXTAL stabilization interrupt flag */ - RCU_INT_FLAG_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 4U), /*!< PLL stabilization interrupt flag */ -#ifdef GD32F10X_CL - RCU_INT_FLAG_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 5U), /*!< PLL1 stabilization interrupt flag */ - RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ -#endif /* GD32F10X_CL */ - RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ - RCU_INT_FLAG_IRC48MSTB = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 6U), /*!< IRC48M stabilization interrupt flag */ -} rcu_int_flag_enum; - -/* clock stabilization and stuck interrupt flags clear */ -typedef enum { - RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ - RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ - RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ - RCU_INT_FLAG_HXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 19U), /*!< HXTAL stabilization interrupt flags clear */ - RCU_INT_FLAG_PLLSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 20U), /*!< PLL stabilization interrupt flags clear */ -#ifdef GD32F10X_CL - RCU_INT_FLAG_PLL1STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 21U), /*!< PLL1 stabilization interrupt flags clear */ - RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ -#endif /* GD32F10X_CL */ - RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ - RCU_INT_FLAG_IRC48MSTB_CLR = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 22U), /*!< internal 48 MHz RC oscillator stabilization interrupt clear */ -} rcu_int_flag_clear_enum; - -/* clock stabilization interrupt enable or disable */ -typedef enum { - RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ - RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ - RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ - RCU_INT_HXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 11U), /*!< HXTAL stabilization interrupt */ - RCU_INT_PLLSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 12U), /*!< PLL stabilization interrupt */ -#ifdef GD32F10X_CL - RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ - RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ -#endif /* GD32F10X_CL */ - RCU_INT_IRC48MSTB = RCU_REGIDX_BIT(ADDINT_REG_OFFSET, 14U), /*!< internal 48 MHz RC oscillator stabilization interrupt */ -} rcu_int_enum; - -/* oscillator types */ -typedef enum { - RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ - RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ - RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ - RCU_IRC48M = RCU_REGIDX_BIT(ADDCTL_REG_OFFSET, 16U), /*!< IRC48M */ - RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ - RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ -#ifdef GD32F10X_CL - RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ - RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ -#endif /* GD32F10X_CL */ -} rcu_osci_type_enum; - -/* rcu clock frequency */ -typedef enum { - CK_SYS = 0, /*!< system clock */ - CK_AHB, /*!< AHB clock */ - CK_APB1, /*!< APB1 clock */ - CK_APB2, /*!< APB2 clock */ -} rcu_clock_freq_enum; - -/* RCU_CFG0 register bit define */ -/* system clock source select */ -#define CFG0_SCS(regval) (BITS(0,1) & ((uint32_t)(regval) << 0)) -#define RCU_CKSYSSRC_IRC8M CFG0_SCS(0) /*!< system clock source select IRC8M */ -#define RCU_CKSYSSRC_HXTAL CFG0_SCS(1) /*!< system clock source select HXTAL */ -#define RCU_CKSYSSRC_PLL CFG0_SCS(2) /*!< system clock source select PLL */ - -/* system clock source select status */ -#define CFG0_SCSS(regval) (BITS(2,3) & ((uint32_t)(regval) << 2)) -#define RCU_SCSS_IRC8M CFG0_SCSS(0) /*!< system clock source select IRC8M */ -#define RCU_SCSS_HXTAL CFG0_SCSS(1) /*!< system clock source select HXTAL */ -#define RCU_SCSS_PLL CFG0_SCSS(2) /*!< system clock source select PLLP */ - -/* AHB prescaler selection */ -#define CFG0_AHBPSC(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) -#define RCU_AHB_CKSYS_DIV1 CFG0_AHBPSC(0) /*!< AHB prescaler select CK_SYS */ -#define RCU_AHB_CKSYS_DIV2 CFG0_AHBPSC(8) /*!< AHB prescaler select CK_SYS/2 */ -#define RCU_AHB_CKSYS_DIV4 CFG0_AHBPSC(9) /*!< AHB prescaler select CK_SYS/4 */ -#define RCU_AHB_CKSYS_DIV8 CFG0_AHBPSC(10) /*!< AHB prescaler select CK_SYS/8 */ -#define RCU_AHB_CKSYS_DIV16 CFG0_AHBPSC(11) /*!< AHB prescaler select CK_SYS/16 */ -#define RCU_AHB_CKSYS_DIV64 CFG0_AHBPSC(12) /*!< AHB prescaler select CK_SYS/64 */ -#define RCU_AHB_CKSYS_DIV128 CFG0_AHBPSC(13) /*!< AHB prescaler select CK_SYS/128 */ -#define RCU_AHB_CKSYS_DIV256 CFG0_AHBPSC(14) /*!< AHB prescaler select CK_SYS/256 */ -#define RCU_AHB_CKSYS_DIV512 CFG0_AHBPSC(15) /*!< AHB prescaler select CK_SYS/512 */ - -/* APB1 prescaler selection */ -#define CFG0_APB1PSC(regval) (BITS(8,10) & ((uint32_t)(regval) << 8)) -#define RCU_APB1_CKAHB_DIV1 CFG0_APB1PSC(0) /*!< APB1 prescaler select CK_AHB */ -#define RCU_APB1_CKAHB_DIV2 CFG0_APB1PSC(4) /*!< APB1 prescaler select CK_AHB/2 */ -#define RCU_APB1_CKAHB_DIV4 CFG0_APB1PSC(5) /*!< APB1 prescaler select CK_AHB/4 */ -#define RCU_APB1_CKAHB_DIV8 CFG0_APB1PSC(6) /*!< APB1 prescaler select CK_AHB/8 */ -#define RCU_APB1_CKAHB_DIV16 CFG0_APB1PSC(7) /*!< APB1 prescaler select CK_AHB/16 */ - -/* APB2 prescaler selection */ -#define CFG0_APB2PSC(regval) (BITS(11,13) & ((uint32_t)(regval) << 11)) -#define RCU_APB2_CKAHB_DIV1 CFG0_APB2PSC(0) /*!< APB2 prescaler select CK_AHB */ -#define RCU_APB2_CKAHB_DIV2 CFG0_APB2PSC(4) /*!< APB2 prescaler select CK_AHB/2 */ -#define RCU_APB2_CKAHB_DIV4 CFG0_APB2PSC(5) /*!< APB2 prescaler select CK_AHB/4 */ -#define RCU_APB2_CKAHB_DIV8 CFG0_APB2PSC(6) /*!< APB2 prescaler select CK_AHB/8 */ -#define RCU_APB2_CKAHB_DIV16 CFG0_APB2PSC(7) /*!< APB2 prescaler select CK_AHB/16 */ - -/* ADC prescaler select */ -#define RCU_CKADC_CKAPB2_DIV2 ((uint32_t)0x00000000U) /*!< ADC prescaler select CK_APB2/2 */ -#define RCU_CKADC_CKAPB2_DIV4 ((uint32_t)0x00000001U) /*!< ADC prescaler select CK_APB2/4 */ -#define RCU_CKADC_CKAPB2_DIV6 ((uint32_t)0x00000002U) /*!< ADC prescaler select CK_APB2/6 */ -#define RCU_CKADC_CKAPB2_DIV8 ((uint32_t)0x00000003U) /*!< ADC prescaler select CK_APB2/8 */ -#define RCU_CKADC_CKAPB2_DIV12 ((uint32_t)0x00000005U) /*!< ADC prescaler select CK_APB2/12 */ -#define RCU_CKADC_CKAPB2_DIV16 ((uint32_t)0x00000007U) /*!< ADC prescaler select CK_APB2/16 */ -#define RCU_CKADC_CKAHB_DIV5 ((uint32_t)0x00000008U) /*!< ADC prescaler select CK_AHB/5 */ -#define RCU_CKADC_CKAHB_DIV6 ((uint32_t)0x00000009U) /*!< ADC prescaler select CK_AHB/6 */ -#define RCU_CKADC_CKAHB_DIV10 ((uint32_t)0x0000000AU) /*!< ADC prescaler select CK_AHB/10 */ -#define RCU_CKADC_CKAHB_DIV20 ((uint32_t)0x0000000BU) /*!< ADC prescaler select CK_AHB/20 */ - -/* PLL clock source selection */ -#define RCU_PLLSRC_IRC8M_DIV2 ((uint32_t)0x00000000U) /*!< IRC8M/2 clock selected as source clock of PLL */ -#define RCU_PLLSRC_HXTAL_IRC48M RCU_CFG0_PLLSEL /*!< HXTAL or IRC48M selected as source clock of PLL */ - -/* PLL clock multiplication factor */ -#define PLLMF_4 RCU_CFG0_PLLMF_4 /* bit 4 of PLLMF */ -#define PLLMF_5 RCU_CFG0_PLLMF_5 /* bit 5 of PLLMF */ -#define PLLMF_4_5 (PLLMF_4 | PLLMF_5) /* bit 4 and 5 of PLLMF */ - -#define CFG0_PLLMF(regval) (BITS(18,21) & ((uint32_t)(regval) << 18)) -#define RCU_PLL_MUL2 CFG0_PLLMF(0) /*!< PLL source clock multiply by 2 */ -#define RCU_PLL_MUL3 CFG0_PLLMF(1) /*!< PLL source clock multiply by 3 */ -#define RCU_PLL_MUL4 CFG0_PLLMF(2) /*!< PLL source clock multiply by 4 */ -#define RCU_PLL_MUL5 CFG0_PLLMF(3) /*!< PLL source clock multiply by 5 */ -#define RCU_PLL_MUL6 CFG0_PLLMF(4) /*!< PLL source clock multiply by 6 */ -#define RCU_PLL_MUL7 CFG0_PLLMF(5) /*!< PLL source clock multiply by 7 */ -#define RCU_PLL_MUL8 CFG0_PLLMF(6) /*!< PLL source clock multiply by 8 */ -#define RCU_PLL_MUL9 CFG0_PLLMF(7) /*!< PLL source clock multiply by 9 */ -#define RCU_PLL_MUL10 CFG0_PLLMF(8) /*!< PLL source clock multiply by 10 */ -#define RCU_PLL_MUL11 CFG0_PLLMF(9) /*!< PLL source clock multiply by 11 */ -#define RCU_PLL_MUL12 CFG0_PLLMF(10) /*!< PLL source clock multiply by 12 */ -#define RCU_PLL_MUL13 CFG0_PLLMF(11) /*!< PLL source clock multiply by 13 */ -#define RCU_PLL_MUL14 CFG0_PLLMF(12) /*!< PLL source clock multiply by 14 */ -#if(defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define RCU_PLL_MUL15 CFG0_PLLMF(13) /*!< PLL source clock multiply by 15 */ -#elif defined(GD32F10X_CL) - #define RCU_PLL_MUL6_5 CFG0_PLLMF(13) /*!< PLL source clock multiply by 6.5 */ -#endif /* GD32F10X_HD and GD32F10X_XD */ -#define RCU_PLL_MUL16 CFG0_PLLMF(14) /*!< PLL source clock multiply by 16 */ -#define RCU_PLL_MUL17 (PLLMF_4 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 17 */ -#define RCU_PLL_MUL18 (PLLMF_4 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 18 */ -#define RCU_PLL_MUL19 (PLLMF_4 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 19 */ -#define RCU_PLL_MUL20 (PLLMF_4 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 20 */ -#define RCU_PLL_MUL21 (PLLMF_4 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 21 */ -#define RCU_PLL_MUL22 (PLLMF_4 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 22 */ -#define RCU_PLL_MUL23 (PLLMF_4 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 23 */ -#define RCU_PLL_MUL24 (PLLMF_4 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 24 */ -#define RCU_PLL_MUL25 (PLLMF_4 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 25 */ -#define RCU_PLL_MUL26 (PLLMF_4 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 26 */ -#define RCU_PLL_MUL27 (PLLMF_4 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 27 */ -#define RCU_PLL_MUL28 (PLLMF_4 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 28 */ -#define RCU_PLL_MUL29 (PLLMF_4 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 29 */ -#define RCU_PLL_MUL30 (PLLMF_4 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 30 */ -#define RCU_PLL_MUL31 (PLLMF_4 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 31 */ -#define RCU_PLL_MUL32 (PLLMF_4 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 32 */ -#define RCU_PLL_MUL33 (PLLMF_5 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 33 */ -#define RCU_PLL_MUL34 (PLLMF_5 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 34 */ -#define RCU_PLL_MUL35 (PLLMF_5 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 35 */ -#define RCU_PLL_MUL36 (PLLMF_5 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 36 */ -#define RCU_PLL_MUL37 (PLLMF_5 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 37 */ -#define RCU_PLL_MUL38 (PLLMF_5 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 38 */ -#define RCU_PLL_MUL39 (PLLMF_5 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 39 */ -#define RCU_PLL_MUL40 (PLLMF_5 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 40 */ -#define RCU_PLL_MUL41 (PLLMF_5 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 41 */ -#define RCU_PLL_MUL42 (PLLMF_5 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 42 */ -#define RCU_PLL_MUL43 (PLLMF_5 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 43 */ -#define RCU_PLL_MUL44 (PLLMF_5 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 44 */ -#define RCU_PLL_MUL45 (PLLMF_5 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 45 */ -#define RCU_PLL_MUL46 (PLLMF_5 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 46 */ -#define RCU_PLL_MUL47 (PLLMF_5 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 47 */ -#define RCU_PLL_MUL48 (PLLMF_5 | CFG0_PLLMF(15)) /*!< PLL source clock multiply by 48 */ -#define RCU_PLL_MUL49 (PLLMF_4_5 | CFG0_PLLMF(0)) /*!< PLL source clock multiply by 49 */ -#define RCU_PLL_MUL50 (PLLMF_4_5 | CFG0_PLLMF(1)) /*!< PLL source clock multiply by 50 */ -#define RCU_PLL_MUL51 (PLLMF_4_5 | CFG0_PLLMF(2)) /*!< PLL source clock multiply by 51 */ -#define RCU_PLL_MUL52 (PLLMF_4_5 | CFG0_PLLMF(3)) /*!< PLL source clock multiply by 52 */ -#define RCU_PLL_MUL53 (PLLMF_4_5 | CFG0_PLLMF(4)) /*!< PLL source clock multiply by 53 */ -#define RCU_PLL_MUL54 (PLLMF_4_5 | CFG0_PLLMF(5)) /*!< PLL source clock multiply by 54 */ -#define RCU_PLL_MUL55 (PLLMF_4_5 | CFG0_PLLMF(6)) /*!< PLL source clock multiply by 55 */ -#define RCU_PLL_MUL56 (PLLMF_4_5 | CFG0_PLLMF(7)) /*!< PLL source clock multiply by 56 */ -#define RCU_PLL_MUL57 (PLLMF_4_5 | CFG0_PLLMF(8)) /*!< PLL source clock multiply by 57 */ -#define RCU_PLL_MUL58 (PLLMF_4_5 | CFG0_PLLMF(9)) /*!< PLL source clock multiply by 58 */ -#define RCU_PLL_MUL59 (PLLMF_4_5 | CFG0_PLLMF(10)) /*!< PLL source clock multiply by 59 */ -#define RCU_PLL_MUL60 (PLLMF_4_5 | CFG0_PLLMF(11)) /*!< PLL source clock multiply by 60 */ -#define RCU_PLL_MUL61 (PLLMF_4_5 | CFG0_PLLMF(12)) /*!< PLL source clock multiply by 61 */ -#define RCU_PLL_MUL62 (PLLMF_4_5 | CFG0_PLLMF(13)) /*!< PLL source clock multiply by 62 */ -#define RCU_PLL_MUL63 (PLLMF_4_5 | CFG0_PLLMF(14)) /*!< PLL source clock multiply by 63 */ - -#if(defined(GD32F10X_HD) || defined(GD32F10X_XD)) - #define USBPSC_2 RCU_CFG0_USBDPSC_2 -#elif defined(GD32F10X_CL) - #define USBPSC_2 RCU_CFG0_USBFSPSC_2 -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* USBD/USBFS prescaler select */ -#define CFG0_USBPSC(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) -#define RCU_CKUSB_CKPLL_DIV1_5 CFG0_USBPSC(0) /*!< USBD/USBFS prescaler select CK_PLL/1.5 */ -#define RCU_CKUSB_CKPLL_DIV1 CFG0_USBPSC(1) /*!< USBD/USBFS prescaler select CK_PLL/1 */ -#define RCU_CKUSB_CKPLL_DIV2_5 CFG0_USBPSC(2) /*!< USBD/USBFS prescaler select CK_PLL/2.5 */ -#define RCU_CKUSB_CKPLL_DIV2 CFG0_USBPSC(3) /*!< USBD/USBFS prescaler select CK_PLL/2 */ -#define RCU_CKUSB_CKPLL_DIV3 (USBPSC_2 |CFG0_USBPSC(0)) /*!< USBD/USBFS prescaler select CK_PLL/3.5 */ -#define RCU_CKUSB_CKPLL_DIV3_5 (USBPSC_2 |CFG0_USBPSC(1)) /*!< USBD/USBFS prescaler select CK_PLL/3 */ -#define RCU_CKUSB_CKPLL_DIV4 (USBPSC_2 |CFG0_USBPSC(2)) /*!< USBD/USBFS prescaler select CK_PLL/4 */ - -/* CKOUT0 Clock source selection */ -#define CFG0_CKOUT0SEL(regval) (BITS(24,27) & ((uint32_t)(regval) << 24)) -#define RCU_CKOUT0SRC_NONE CFG0_CKOUT0SEL(0) /*!< no clock selected */ -#define RCU_CKOUT0SRC_CKSYS CFG0_CKOUT0SEL(4) /*!< system clock selected */ -#define RCU_CKOUT0SRC_IRC8M CFG0_CKOUT0SEL(5) /*!< internal 8M RC oscillator clock selected */ -#define RCU_CKOUT0SRC_HXTAL CFG0_CKOUT0SEL(6) /*!< high speed crystal oscillator clock (HXTAL) selected */ -#define RCU_CKOUT0SRC_CKPLL_DIV2 CFG0_CKOUT0SEL(7) /*!< CK_PLL/2 clock selected */ -#ifdef GD32F10X_CL - #define RCU_CKOUT0SRC_CKPLL1 CFG0_CKOUT0SEL(8) /*!< CK_PLL1 clock selected */ - #define RCU_CKOUT0SRC_CKPLL2_DIV2 CFG0_CKOUT0SEL(9) /*!< CK_PLL2/2 clock selected */ - #define RCU_CKOUT0SRC_EXT1 CFG0_CKOUT0SEL(10) /*!< EXT1 selected, to provide the external clock for ENET */ - #define RCU_CKOUT0SRC_CKPLL2 CFG0_CKOUT0SEL(11) /*!< CK_PLL2 clock selected */ -#endif /* GD32F10X_CL */ - -/* LXTAL drive capability */ -#define BDCTL_LXTALDRI(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) -#define RCU_LXTAL_LOWDRI BDCTL_LXTALDRI(0) /*!< lower driving capability */ -#define RCU_LXTAL_MED_LOWDRI BDCTL_LXTALDRI(1) /*!< medium low driving capability */ -#define RCU_LXTAL_MED_HIGHDRI BDCTL_LXTALDRI(2) /*!< medium high driving capability */ -#define RCU_LXTAL_HIGHDRI BDCTL_LXTALDRI(3) /*!< higher driving capability */ - -/* RTC clock entry selection */ -#define BDCTL_RTCSRC(regval) (BITS(8,9) & ((uint32_t)(regval) << 8)) -#define RCU_RTCSRC_NONE BDCTL_RTCSRC(0) /*!< no clock selected */ -#define RCU_RTCSRC_LXTAL BDCTL_RTCSRC(1) /*!< RTC source clock select LXTAL */ -#define RCU_RTCSRC_IRC40K BDCTL_RTCSRC(2) /*!< RTC source clock select IRC40K */ -#define RCU_RTCSRC_HXTAL_DIV_128 BDCTL_RTCSRC(3) /*!< RTC source clock select HXTAL/128 */ - -/* PREDV0 division factor */ -#define CFG1_PREDV0(regval) (BITS(0,3) & ((uint32_t)(regval) << 0)) -#define RCU_PREDV0_DIV1 CFG1_PREDV0(0) /*!< PREDV0 input source clock not divided */ -#define RCU_PREDV0_DIV2 CFG1_PREDV0(1) /*!< PREDV0 input source clock divided by 2 */ -#define RCU_PREDV0_DIV3 CFG1_PREDV0(2) /*!< PREDV0 input source clock divided by 3 */ -#define RCU_PREDV0_DIV4 CFG1_PREDV0(3) /*!< PREDV0 input source clock divided by 4 */ -#define RCU_PREDV0_DIV5 CFG1_PREDV0(4) /*!< PREDV0 input source clock divided by 5 */ -#define RCU_PREDV0_DIV6 CFG1_PREDV0(5) /*!< PREDV0 input source clock divided by 6 */ -#define RCU_PREDV0_DIV7 CFG1_PREDV0(6) /*!< PREDV0 input source clock divided by 7 */ -#define RCU_PREDV0_DIV8 CFG1_PREDV0(7) /*!< PREDV0 input source clock divided by 8 */ -#define RCU_PREDV0_DIV9 CFG1_PREDV0(8) /*!< PREDV0 input source clock divided by 9 */ -#define RCU_PREDV0_DIV10 CFG1_PREDV0(9) /*!< PREDV0 input source clock divided by 10 */ -#define RCU_PREDV0_DIV11 CFG1_PREDV0(10) /*!< PREDV0 input source clock divided by 11 */ -#define RCU_PREDV0_DIV12 CFG1_PREDV0(11) /*!< PREDV0 input source clock divided by 12 */ -#define RCU_PREDV0_DIV13 CFG1_PREDV0(12) /*!< PREDV0 input source clock divided by 13 */ -#define RCU_PREDV0_DIV14 CFG1_PREDV0(13) /*!< PREDV0 input source clock divided by 14 */ -#define RCU_PREDV0_DIV15 CFG1_PREDV0(14) /*!< PREDV0 input source clock divided by 15 */ -#define RCU_PREDV0_DIV16 CFG1_PREDV0(15) /*!< PREDV0 input source clock divided by 16 */ - -/* PREDV1 division factor */ -#define CFG1_PREDV1(regval) (BITS(4,7) & ((uint32_t)(regval) << 4)) -#define RCU_PREDV1_DIV1 CFG1_PREDV1(0) /*!< PREDV1 input source clock not divided */ -#define RCU_PREDV1_DIV2 CFG1_PREDV1(1) /*!< PREDV1 input source clock divided by 2 */ -#define RCU_PREDV1_DIV3 CFG1_PREDV1(2) /*!< PREDV1 input source clock divided by 3 */ -#define RCU_PREDV1_DIV4 CFG1_PREDV1(3) /*!< PREDV1 input source clock divided by 4 */ -#define RCU_PREDV1_DIV5 CFG1_PREDV1(4) /*!< PREDV1 input source clock divided by 5 */ -#define RCU_PREDV1_DIV6 CFG1_PREDV1(5) /*!< PREDV1 input source clock divided by 6 */ -#define RCU_PREDV1_DIV7 CFG1_PREDV1(6) /*!< PREDV1 input source clock divided by 7 */ -#define RCU_PREDV1_DIV8 CFG1_PREDV1(7) /*!< PREDV1 input source clock divided by 8 */ -#define RCU_PREDV1_DIV9 CFG1_PREDV1(8) /*!< PREDV1 input source clock divided by 9 */ -#define RCU_PREDV1_DIV10 CFG1_PREDV1(9) /*!< PREDV1 input source clock divided by 10 */ -#define RCU_PREDV1_DIV11 CFG1_PREDV1(10) /*!< PREDV1 input source clock divided by 11 */ -#define RCU_PREDV1_DIV12 CFG1_PREDV1(11) /*!< PREDV1 input source clock divided by 12 */ -#define RCU_PREDV1_DIV13 CFG1_PREDV1(12) /*!< PREDV1 input source clock divided by 13 */ -#define RCU_PREDV1_DIV14 CFG1_PREDV1(13) /*!< PREDV1 input source clock divided by 14 */ -#define RCU_PREDV1_DIV15 CFG1_PREDV1(14) /*!< PREDV1 input source clock divided by 15 */ -#define RCU_PREDV1_DIV16 CFG1_PREDV1(15) /*!< PREDV1 input source clock divided by 16 */ - -/* PLL1 clock multiplication factor */ -#define CFG1_PLL1MF(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) -#define RCU_PLL1_MUL8 CFG1_PLL1MF(6) /*!< PLL1 source clock multiply by 8 */ -#define RCU_PLL1_MUL9 CFG1_PLL1MF(7) /*!< PLL1 source clock multiply by 9 */ -#define RCU_PLL1_MUL10 CFG1_PLL1MF(8) /*!< PLL1 source clock multiply by 10 */ -#define RCU_PLL1_MUL11 CFG1_PLL1MF(9) /*!< PLL1 source clock multiply by 11 */ -#define RCU_PLL1_MUL12 CFG1_PLL1MF(10) /*!< PLL1 source clock multiply by 12 */ -#define RCU_PLL1_MUL13 CFG1_PLL1MF(11) /*!< PLL1 source clock multiply by 13 */ -#define RCU_PLL1_MUL14 CFG1_PLL1MF(12) /*!< PLL1 source clock multiply by 14 */ -#define RCU_PLL1_MUL15 CFG1_PLL1MF(13) /*!< PLL1 source clock multiply by 15 */ -#define RCU_PLL1_MUL16 CFG1_PLL1MF(14) /*!< PLL1 source clock multiply by 16 */ -#define RCU_PLL1_MUL20 CFG1_PLL1MF(15) /*!< PLL1 source clock multiply by 20 */ - -/* PLL2 clock multiplication factor */ -#define PLL2MF_4 RCU_CFG1_PLL2MF_4 /* bit 4 of PLL2MF */ - -#define CFG1_PLL2MF(regval) (BITS(12,15) & ((uint32_t)(regval) << 12)) -#define RCU_PLL2_MUL8 CFG1_PLL2MF(6) /*!< PLL2 source clock multiply by 8 */ -#define RCU_PLL2_MUL9 CFG1_PLL2MF(7) /*!< PLL2 source clock multiply by 9 */ -#define RCU_PLL2_MUL10 CFG1_PLL2MF(8) /*!< PLL2 source clock multiply by 10 */ -#define RCU_PLL2_MUL11 CFG1_PLL2MF(9) /*!< PLL2 source clock multiply by 11 */ -#define RCU_PLL2_MUL12 CFG1_PLL2MF(10) /*!< PLL2 source clock multiply by 12 */ -#define RCU_PLL2_MUL13 CFG1_PLL2MF(11) /*!< PLL2 source clock multiply by 13 */ -#define RCU_PLL2_MUL14 CFG1_PLL2MF(12) /*!< PLL2 source clock multiply by 14 */ -#define RCU_PLL2_MUL15 CFG1_PLL2MF(13) /*!< PLL2 source clock multiply by 15 */ -#define RCU_PLL2_MUL16 CFG1_PLL2MF(14) /*!< PLL2 source clock multiply by 16 */ -#define RCU_PLL2_MUL20 CFG1_PLL2MF(15) /*!< PLL2 source clock multiply by 20 */ -#define RCU_PLL2_MUL18 (PLL2MF_4 | CFG1_PLL2MF(0)) /*!< PLL2 source clock multiply by 18 */ -#define RCU_PLL2_MUL19 (PLL2MF_4 | CFG1_PLL2MF(1)) /*!< PLL2 source clock multiply by 19 */ -#define RCU_PLL2_MUL21 (PLL2MF_4 | CFG1_PLL2MF(3)) /*!< PLL2 source clock multiply by 21 */ -#define RCU_PLL2_MUL22 (PLL2MF_4 | CFG1_PLL2MF(4)) /*!< PLL2 source clock multiply by 22 */ -#define RCU_PLL2_MUL23 (PLL2MF_4 | CFG1_PLL2MF(5)) /*!< PLL2 source clock multiply by 23 */ -#define RCU_PLL2_MUL24 (PLL2MF_4 | CFG1_PLL2MF(6)) /*!< PLL2 source clock multiply by 24 */ -#define RCU_PLL2_MUL25 (PLL2MF_4 | CFG1_PLL2MF(7)) /*!< PLL2 source clock multiply by 25 */ -#define RCU_PLL2_MUL26 (PLL2MF_4 | CFG1_PLL2MF(8)) /*!< PLL2 source clock multiply by 26 */ -#define RCU_PLL2_MUL27 (PLL2MF_4 | CFG1_PLL2MF(9)) /*!< PLL2 source clock multiply by 27 */ -#define RCU_PLL2_MUL28 (PLL2MF_4 | CFG1_PLL2MF(10)) /*!< PLL2 source clock multiply by 28 */ -#define RCU_PLL2_MUL29 (PLL2MF_4 | CFG1_PLL2MF(11)) /*!< PLL2 source clock multiply by 29 */ -#define RCU_PLL2_MUL30 (PLL2MF_4 | CFG1_PLL2MF(12)) /*!< PLL2 source clock multiply by 30 */ -#define RCU_PLL2_MUL31 (PLL2MF_4 | CFG1_PLL2MF(13)) /*!< PLL2 source clock multiply by 31 */ -#define RCU_PLL2_MUL32 (PLL2MF_4 | CFG1_PLL2MF(14)) /*!< PLL2 source clock multiply by 32 */ -#define RCU_PLL2_MUL40 (PLL2MF_4 | CFG1_PLL2MF(15)) /*!< PLL2 source clock multiply by 40 */ - -#ifdef GD32F10X_CL - /* PREDV0 input clock source selection */ - #define RCU_PREDV0SRC_HXTAL_IRC48M ((uint32_t)0x00000000U) /*!< HXTAL or IRC48M selected as PREDV0 input source clock */ - #define RCU_PREDV0SRC_CKPLL1 RCU_CFG1_PREDV0SEL /*!< CK_PLL1 selected as PREDV0 input source clock */ - - /* I2S1 clock source selection */ - #define RCU_I2S1SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S1 source clock */ - #define RCU_I2S1SRC_CKPLL2_MUL2 RCU_CFG1_I2S1SEL /*!< (CK_PLL2 x 2) selected as I2S1 source clock */ - - /* I2S2 clock source selection */ - #define RCU_I2S2SRC_CKSYS ((uint32_t)0x00000000U) /*!< system clock selected as I2S2 source clock */ - #define RCU_I2S2SRC_CKPLL2_MUL2 RCU_CFG1_I2S2SEL /*!< (CK_PLL2 x 2) selected as I2S2 source clock */ -#endif /* GD32F10X_CL */ - -/* PLL input clock source selection */ -#define RCU_PLLPRESRC_HXTAL ((uint32_t)0x00000000U) /*!< HXTAL selected as PLL source clock */ -#define RCU_PLLPRESRC_IRC48M RCU_CFG1_PLLPRESEL /*!< CK_PLL selected as PREDV0 input source clock */ - -/* deep-sleep mode voltage */ -#define DSV_DSLPVS(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) -#define RCU_DEEPSLEEP_V_1_0 DSV_DSLPVS(0) /*!< core voltage is 1.0V in deep-sleep mode */ -#define RCU_DEEPSLEEP_V_0_9 DSV_DSLPVS(1) /*!< core voltage is 0.9V in deep-sleep mode */ -#define RCU_DEEPSLEEP_V_0_8 DSV_DSLPVS(2) /*!< core voltage is 0.8V in deep-sleep mode */ -#define RCU_DEEPSLEEP_V_0_7 DSV_DSLPVS(3) /*!< core voltage is 0.7V in deep-sleep mode */ - -/* 48MHz clock selection */ -#define RCU_CK48MSRC_CKPLL ((uint32_t)0x00000000U) /*!< use CK_PLL clock */ -#define RCU_CK48MSRC_IRC48M RCU_ADDCTL_CK48MSEL /*!< select IRC48M clock */ - -/* function declarations */ -/* deinitialize the RCU */ -void rcu_deinit(void); -/* enable the peripherals clock */ -void rcu_periph_clock_enable(rcu_periph_enum periph); -/* disable the peripherals clock */ -void rcu_periph_clock_disable(rcu_periph_enum periph); -/* enable the peripherals clock when sleep mode */ -void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph); -/* disable the peripherals clock when sleep mode */ -void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph); -/* reset the peripherals */ -void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset); -/* disable reset the peripheral */ -void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset); -/* reset the BKP domain */ -void rcu_bkp_reset_enable(void); -/* disable the BKP domain reset */ -void rcu_bkp_reset_disable(void); - -/* configure the system clock source */ -void rcu_system_clock_source_config(uint32_t ck_sys); -/* get the system clock source */ -uint32_t rcu_system_clock_source_get(void); -/* configure the AHB prescaler selection */ -void rcu_ahb_clock_config(uint32_t ck_ahb); -/* configure the APB1 prescaler selection */ -void rcu_apb1_clock_config(uint32_t ck_apb1); -/* configure the APB2 prescaler selection */ -void rcu_apb2_clock_config(uint32_t ck_apb2); -/* configure the CK_OUT0 clock source and divider */ -void rcu_ckout0_config(uint32_t ckout0_src); -/* configure the PLL clock source selection and PLL multiply factor */ -void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); -/* configure the PLL clock source preselection */ -void rcu_pllpresel_config(uint32_t pll_presel); -#if(defined(GD32F10X_HD) || defined(GD32F10X_XD)) - /* configure the PREDV0 division factor and clock source */ - void rcu_predv0_config(uint32_t predv0_div); -#elif defined(GD32F10X_CL) - /* configure the PREDV0 division factor and clock source */ - void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); - /* configure the PREDV1 division factor */ - void rcu_predv1_config(uint32_t predv1_div); - /* configure the PLL1 clock */ - void rcu_pll1_config(uint32_t pll_mul); - /* configure the PLL2 clock */ - void rcu_pll2_config(uint32_t pll_mul); -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/* configure the ADC division factor */ -void rcu_adc_clock_config(uint32_t adc_psc); -/* configure the USBD/USBFS prescaler factor */ -void rcu_usb_clock_config(uint32_t usb_psc); -/* configure the RTC clock source selection */ -void rcu_rtc_clock_config(uint32_t rtc_clock_source); -#ifdef GD32F10X_CL - /* configure the I2S1 clock source selection */ - void rcu_i2s1_clock_config(uint32_t i2s_clock_source); - /* configure the I2S2 clock source selection */ - void rcu_i2s2_clock_config(uint32_t i2s_clock_source); -#endif /* GD32F10X_CL */ -/* configure the CK48M clock selection */ -void rcu_ck48m_clock_config(uint32_t ck48m_clock_source); - - -/* get the clock stabilization and periphral reset flags */ -FlagStatus rcu_flag_get(rcu_flag_enum flag); -/* clear the reset flag */ -void rcu_all_reset_flag_clear(void); -/* get the clock stabilization interrupt and ckm flags */ -FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); -/* clear the interrupt flags */ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); -/* enable the stabilization interrupt */ -void rcu_interrupt_enable(rcu_int_enum stab_int); -/* disable the stabilization interrupt */ -void rcu_interrupt_disable(rcu_int_enum stab_int); - -/* configure the LXTAL drive capability */ -void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); -/* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ -ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci); -/* turn on the oscillator */ -void rcu_osci_on(rcu_osci_type_enum osci); -/* turn off the oscillator */ -void rcu_osci_off(rcu_osci_type_enum osci); -/* enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ -void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci); -/* disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it */ -void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); -/* enable the HXTAL clock monitor */ -void rcu_hxtal_clock_monitor_enable(void); -/* disable the HXTAL clock monitor */ -void rcu_hxtal_clock_monitor_disable(void); - -/* set the IRC8M adjust value */ -void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval); - -/* set the deep sleep mode voltage */ -void rcu_deepsleep_voltage_set(uint32_t dsvol); - -/* get the system clock, bus and peripheral clock frequency */ -uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); - -#endif /* GD32F10X_RCU_H */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rtc.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rtc.h deleted file mode 100644 index 65d57f06c2..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_rtc.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - ****************************************************************************** - * @brief RTC header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_RTC_H -#define __GD32F10X_RTC_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup RTC - * @{ - */ - -/** @defgroup RTC_Exported_Defines - * @{ - */ - -/** @defgroup RTC_Interrupt_Def - * @{ - */ -#define RTC_INT_OVF ((uint16_t)0x0004) /*!< Overflow interrupt */ -#define RTC_INT_AF ((uint16_t)0x0002) /*!< Alarm interrupt */ -#define RTC_INT_SF ((uint16_t)0x0001) /*!< Second interrupt */ - -/** - * @} - */ - -/** @defgroup RTC_Interrupts_Flags - * @{ - */ -#define RTC_FLAG_LWOFF ((uint16_t)0x0020) /*!< Last write operation finished flag */ -#define RTC_FLAG_RSF ((uint16_t)0x0008) /*!< Registers Synchronized flag */ -#define RTC_FLAG_OVF ((uint16_t)0x0004) /*!< Overflow flag */ -#define RTC_FLAG_AF ((uint16_t)0x0002) /*!< Alarm flag */ -#define RTC_FLAG_SF ((uint16_t)0x0001) /*!< Second flag */ - -/** - * @} - */ - -/** - * @} - */ - -/** @defgroup RTC_Exported_Functions - * @{ - */ -void RTC_INT_Enable(uint16_t RTC_int, TypeState NewValue); -void RTC_EnterConfigMode(void); -void RTC_ExitConfigMode(void); -uint32_t RTC_GetCounter(void); -void RTC_SetCounter(uint32_t CounterValue); -void RTC_SetPrescaler(uint32_t PrescalerValue); -void RTC_SetAlarm(uint32_t AlarmTime); -uint32_t RTC_GetDividerValue(void); -void RTC_WaitLWOFF(void); -void RTC_WaitRSF(void); -TypeState RTC_GetBitState(uint16_t RTC_flag); -void RTC_ClearBitState(uint16_t RTC_flag); -TypeState RTC_GetIntBitState(uint16_t RTC_INT); -void RTC_ClearIntBitState(uint16_t RTC_INT); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_RTC_H */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_sdio.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_sdio.h deleted file mode 100644 index 16c4d97b12..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_sdio.h +++ /dev/null @@ -1,369 +0,0 @@ -/** - ****************************************************************************** - * @brief SDIO header file of the firmware library - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_SDIO_H -#define __GD32F10X_SDIO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup SDIO - * @{ - */ - -/** @defgroup SDIO_Exported_Types - * @{ - */ - -typedef struct { - uint32_t SDIO_ClockEdge; /*!< Configure the SDIO Clock edge on which the bit capture is made. - This parameter can be a value of @ref SDIO_Clock_Edge*/ - uint32_t SDIO_ClockBypassState; /*!< Configure the SDIO Clock divider bypass mode - This parameter can be a value of @ref SDIO_Clock_Bypass_State */ - uint32_t SDIO_ClockPWRSave; /*!< Configure the SDIO Clock output powersave mode when the bus is idle. - This parameter can be a value of @ref SDIO_Clock_Power_Save */ - uint32_t SDIO_BusMode; /*!< Configure the SDIO bus mode. - This parameter can be a value of @ref SDIO_Bus_Mode */ - uint32_t SDIO_HWFlowCtrlState; /*!< Configure the SDIO hardware flow control is enabled or disabled. - This parameter can be a value of @ref SDIO_HW_Flow_Control_State */ - uint8_t SDIO_ClockDiv; /*!< Configure the clock frequency prescaler of the SDIO controller. - This parameter can be a value between 0x00 and 0xFF. */ -} SDIO_InitPara; - -typedef struct { - uint32_t SDIO_CMDParameter; /*!< Configure the SDIO command parameter which is sent to - a card as part of a command message. */ - uint32_t SDIO_CMDIndex; /*!< Configure the SDIO command index. */ - - uint32_t SDIO_ResponseType; /*!< Configure the SDIO response type. - This parameter can be a value of @ref SDIO_Response_Type */ - uint32_t SDIO_WaitINTState; /*!< Configure whether SDIO wait-for-interrupt request is enabled or disabled. - This parameter can be a value of @ref SDIO_Wait_Interrupt_State */ - uint32_t SDIO_CSMState; /*!< Configure SDIO Command state machine (CSM) is enabled or disabled. - This parameter can be a value of @ref SDIO_CSM_State */ -} SDIO_CmdInitPara; - -typedef struct { - uint32_t SDIO_DataTimeOut; /*!< Configure the data timeout period in card bus clock periods. */ - - uint32_t SDIO_DataLength; /*!< Configure the number of data bytes to be transferred. */ - - uint32_t SDIO_DataBlockSize; /*!< Configure the data block size for block transfer. - This parameter can be a value of @ref SDIO_Data_Block_Size */ - uint32_t SDIO_TransDirection; /*!< Configure the data transfer direction, read or write. - This parameter can be a value of @ref SDIO_Transfer_Direction */ - uint32_t SDIO_TransMode; /*!< Configure whether data transfer is in stream or block mode. - This parameter can be a value of @ref SDIO_Transfer_Mode */ - uint32_t SDIO_DSMState; /*!< Configure whether SDIO Data state machine (DSM) is enabled or disabled. - This parameter can be a value of @ref SDIO_DSM_State */ -} SDIO_DataInitPara; - -/** - * @} - */ - -/** @defgroup SDIO_Exported_Constants - * @{ - */ - -/** @defgroup SDIO_Clock_Edge - * @{ - */ -#define SDIO_CLOCKEDGE_RISING ((uint32_t)0x00000000) -#define SDIO_CLOCKEDGE_FALLING ((uint32_t)0x00002000) - -/** - * @} - */ - -/** @defgroup SDIO_Clock_Bypass_State - * @{ - */ -#define SDIO_CLOCKBYPASSSTATE_DISABLE ((uint32_t)0x00000000) -#define SDIO_CLOCKBYPASSSTATE_ENABLE ((uint32_t)0x00000400) - -/** - * @} - */ - -/** @defgroup SDIO_Clock_PWR_Save - * @{ - */ -#define SDIO_CLOCKPWRSAVE_DISABLE ((uint32_t)0x00000000) -#define SDIO_CLOCKPWRSAVE_ENABLE ((uint32_t)0x00000200) - -/** - * @} - */ - -/** @defgroup SDIO_Bus_Mode - * @{ - */ -#define SDIO_BUSMODE_1B ((uint32_t)0x00000000) -#define SDIO_BUSMODE_4B ((uint32_t)0x00000800) -#define SDIO_BUSMODE_8B ((uint32_t)0x00001000) - -/** - * @} - */ - -/** @defgroup SDIO_HW_Flow_Control_State - * @{ - */ - -#define SDIO_HWFLOWCTRLSTATE_DISABLE ((uint32_t)0x00000000) -#define SDIO_HWFLOWCTRLSTATE_ENABLE ((uint32_t)0x00004000) - -/** - * @} - */ - -/** @defgroup SDIO_Power_State - * @{ - */ -#define SDIO_PWRSTATE_OFF ((uint32_t)0x00000000) -#define SDIO_PWRSTATE_ON ((uint32_t)0x00000003) - -/** - * @} - */ - -/** @defgroup SDIO_Interrupt_sources - * @{ - */ -#define SDIO_INT_CCRCFAIL ((uint32_t)0x00000001) -#define SDIO_INT_DTCRCFAIL ((uint32_t)0x00000002) -#define SDIO_INT_CMDTMOUT ((uint32_t)0x00000004) -#define SDIO_INT_DTTMOUT ((uint32_t)0x00000008) -#define SDIO_INT_TXURE ((uint32_t)0x00000010) -#define SDIO_INT_RXORE ((uint32_t)0x00000020) -#define SDIO_INT_CMDREND ((uint32_t)0x00000040) -#define SDIO_INT_CMDSENT ((uint32_t)0x00000080) -#define SDIO_INT_DTEND ((uint32_t)0x00000100) -#define SDIO_INT_STBITE ((uint32_t)0x00000200) -#define SDIO_INT_DTBLKEND ((uint32_t)0x00000400) -#define SDIO_INT_CMDRUN ((uint32_t)0x00000800) -#define SDIO_INT_TXRUN ((uint32_t)0x00001000) -#define SDIO_INT_RXRUN ((uint32_t)0x00002000) -#define SDIO_INT_TXFIFOHE ((uint32_t)0x00004000) -#define SDIO_INT_RXFIFOHF ((uint32_t)0x00008000) -#define SDIO_INT_TXFIFOF ((uint32_t)0x00010000) -#define SDIO_INT_RXFIFOF ((uint32_t)0x00020000) -#define SDIO_INT_TXFIFOE ((uint32_t)0x00040000) -#define SDIO_INT_RXFIFOE ((uint32_t)0x00080000) -#define SDIO_INT_TXDTVAL ((uint32_t)0x00100000) -#define SDIO_INT_RXDTVAL ((uint32_t)0x00200000) -#define SDIO_INT_SDIOINT ((uint32_t)0x00400000) -#define SDIO_INT_ATAEND ((uint32_t)0x00800000) - -/** - * @} - */ - -/** @defgroup SDIO_Response_Type - * @{ - */ -#define SDIO_RESPONSETYPE_NO ((uint32_t)0x00000000) -#define SDIO_RESPONSETYPE_SHORT ((uint32_t)0x00000040) -#define SDIO_RESPONSETYPE_LONG ((uint32_t)0x000000C0) - -/** - * @} - */ - -/** @defgroup SDIO_Wait_Interrupt_State - * @{ - */ -#define SDIO_WAITINTSTATE_NO ((uint32_t)0x00000000) -#define SDIO_WAITINTSTATE_INT ((uint32_t)0x00000100) -#define SDIO_WAITINTSTATE_PEND ((uint32_t)0x00000200) - -/** - * @} - */ - -/** @defgroup SDIO_CSM_State - * @{ - */ -#define SDIO_CSMSTATE_DISABLE ((uint32_t)0x00000000) -#define SDIO_CSMSTATE_ENABLE ((uint32_t)0x00000400) - -/** - * @} - */ - -/** @defgroup SDIO_Response_Registers - * @{ - */ -#define SDIO_RESP1 ((uint32_t)0x00000000) -#define SDIO_RESP2 ((uint32_t)0x00000004) -#define SDIO_RESP3 ((uint32_t)0x00000008) -#define SDIO_RESP4 ((uint32_t)0x0000000C) - -/** - * @} - */ - -/** @defgroup SDIO_Data_Block_Size - * @{ - */ -#define SDIO_DATABLOCKSIZE_1B ((uint32_t)0x00000000) -#define SDIO_DATABLOCKSIZE_2B ((uint32_t)0x00000010) -#define SDIO_DATABLOCKSIZE_4B ((uint32_t)0x00000020) -#define SDIO_DATABLOCKSIZE_8B ((uint32_t)0x00000030) -#define SDIO_DATABLOCKSIZE_16B ((uint32_t)0x00000040) -#define SDIO_DATABLOCKSIZE_32B ((uint32_t)0x00000050) -#define SDIO_DATABLOCKSIZE_64B ((uint32_t)0x00000060) -#define SDIO_DATABLOCKSIZE_128B ((uint32_t)0x00000070) -#define SDIO_DATABLOCKSIZE_256B ((uint32_t)0x00000080) -#define SDIO_DATABLOCKSIZE_512B ((uint32_t)0x00000090) -#define SDIO_DATABLOCKSIZE_1024B ((uint32_t)0x000000A0) -#define SDIO_DATABLOCKSIZE_2048B ((uint32_t)0x000000B0) -#define SDIO_DATABLOCKSIZE_4096B ((uint32_t)0x000000C0) -#define SDIO_DATABLOCKSIZE_8192B ((uint32_t)0x000000D0) -#define SDIO_DATABLOCKSIZE_16384B ((uint32_t)0x000000E0) - -/** - * @} - */ - -/** @defgroup SDIO_Transfer_Direction - * @{ - */ -#define SDIO_TRANSDIRECTION_TOCARD ((uint32_t)0x00000000) -#define SDIO_TRANSDIRECTION_TOSDIO ((uint32_t)0x00000002) - -/** - * @} - */ - -/** @defgroup SDIO_Transfer_Mode - * @{ - */ -#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000) -#define SDIO_TRANSMODE_STREAM ((uint32_t)0x00000004) - -/** - * @} - */ - -/** @defgroup SDIO_DSM_State - * @{ - */ -#define SDIO_DSMSTATE_DISABLE ((uint32_t)0x00000000) -#define SDIO_DSMSTATE_ENABLE ((uint32_t)0x00000001) - -/** - * @} - */ - -/** @defgroup SDIO_Flag - * @{ - */ -#define SDIO_FLAG_CCRCFAIL ((uint32_t)0x00000001) -#define SDIO_FLAG_DTCRCFAIL ((uint32_t)0x00000002) -#define SDIO_FLAG_CMDTMOUT ((uint32_t)0x00000004) -#define SDIO_FLAG_DTTMOUT ((uint32_t)0x00000008) -#define SDIO_FLAG_TXURE ((uint32_t)0x00000010) -#define SDIO_FLAG_RXORE ((uint32_t)0x00000020) -#define SDIO_FLAG_CMDREND ((uint32_t)0x00000040) -#define SDIO_FLAG_CMDSENT ((uint32_t)0x00000080) -#define SDIO_FLAG_DTEND ((uint32_t)0x00000100) -#define SDIO_FLAG_STBITE ((uint32_t)0x00000200) -#define SDIO_FLAG_DTBLKEND ((uint32_t)0x00000400) -#define SDIO_FLAG_CMDRUN ((uint32_t)0x00000800) -#define SDIO_FLAG_TXRUN ((uint32_t)0x00001000) -#define SDIO_FLAG_RXRUN ((uint32_t)0x00002000) -#define SDIO_FLAG_TXFIFOHE ((uint32_t)0x00004000) -#define SDIO_FLAG_RXFIFOHF ((uint32_t)0x00008000) -#define SDIO_FLAG_TXFIFOF ((uint32_t)0x00010000) -#define SDIO_FLAG_RXFIFOF ((uint32_t)0x00020000) -#define SDIO_FLAG_TXFIFOE ((uint32_t)0x00040000) -#define SDIO_FLAG_RXFIFOE ((uint32_t)0x00080000) -#define SDIO_FLAG_TXDTVAL ((uint32_t)0x00100000) -#define SDIO_FLAG_RXDTVAL ((uint32_t)0x00200000) -#define SDIO_FLAG_SDIOINT ((uint32_t)0x00400000) -#define SDIO_FLAG_ATAEND ((uint32_t)0x00800000) - -/** - * @} - */ - -/** @defgroup SDIO_Read_Wait_Mode - * @{ - */ -#define SDIO_READWAITMODE_CLK ((uint32_t)0x00000001) -#define SDIO_READWAITMODE_DAT2 ((uint32_t)0x00000000) - -/** - * @} - */ - -/** - * @} - */ - - -/** @defgroup SDIO_Exported_Functions - * @{ - */ -void SDIO_DeInit(void); -void SDIO_Init(SDIO_InitPara *SDIO_InitParaStruct); -void SDIO_ParaInit(SDIO_InitPara *SDIO_InitParaStruct); -void SDIO_Clock_Enable(TypeState NewState); -void SDIO_SetPWRState(uint32_t SDIO_PWRState); -uint32_t SDIO_GetPWRState(void); -void SDIO_INTConfig(uint32_t SDIO_INT, TypeState NewState); -void SDIO_DMA_Enable(TypeState NewState); -void SDIO_SendCMD(SDIO_CmdInitPara *SDIO_CmdInitParaStruct); -void SDIO_CMDParaInit(SDIO_CmdInitPara *SDIO_CmdInitParaStruct); -uint8_t SDIO_GetCMDResponse(void); -uint32_t SDIO_GetResponse(uint32_t SDIO_RESP); -void SDIO_DataConfig(SDIO_DataInitPara *SDIO_DataInitParaStruct); -void SDIO_DataParaInit(SDIO_DataInitPara *SDIO_DataInitParaStruct); -uint32_t SDIO_GetDataCount(void); -uint32_t SDIO_ReadData(void); -void SDIO_WriteData(uint32_t Data); -uint32_t SDIO_GetFIFOCount(void); -void SDIO_StartSDIOReadWait(TypeState NewState); -void SDIO_StopSDIOReadWait(TypeState NewState); -void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode); -void SDIO_SetSDIOOperation(TypeState NewState); -void SDIO_SendSDIOSuspend_Enable(TypeState NewState); -void SDIO_CMDCompletion_Enable(TypeState NewState); -void SDIO_CEATAInt_Enable(TypeState NewState); -void SDIO_SendCEATA_Enable(TypeState NewState); - -TypeState SDIO_GetBitState(uint32_t SDIO_FLAG); -void SDIO_ClearBitState(uint32_t SDIO_FLAG); -TypeState SDIO_GetIntBitState(uint32_t SDIO_INT); -void SDIO_ClearIntBitState(uint32_t SDIO_INT); - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_SDIO_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_spi.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_spi.h deleted file mode 100644 index cf0e88e26f..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_spi.h +++ /dev/null @@ -1,353 +0,0 @@ -/** - ****************************************************************************** - * @brief SPI header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_SPI_H -#define __GD32F10X_SPI_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup SPI - * @{ - */ - -/** @defgroup SPI_Exported_Types - * @{ - */ - -/** - * @brief SPI Initial Parameters - */ -typedef struct { - uint16_t SPI_TransType; /*!< The transfer type, choose one from @ref SPI_transfer_type. */ - uint16_t SPI_Mode; /*!< The operating mode, choose one from @ref SPI_mode. */ - uint16_t SPI_FrameFormat; /*!< The SPI data frame format, choose one from @ref SPI_data_frame_format. */ - uint16_t SPI_SCKPL; /*!< The clock polarity in idel state, choose one from @ref SPI_Clock_Polarity. */ - uint16_t SPI_SCKPH; /*!< The clock phase, choose one from @ref SPI_Clock_Phase. */ - uint16_t SPI_SWNSSEN; /*!< The NSS signal management, choose one from @ref SPI_Software_NSS_management. */ - uint16_t SPI_PSC; /*!< The Baud Rate prescaler value, choose one from @ref SPI_BaudRate_Prescaler. */ - uint16_t SPI_FirstBit; /*!< The data transfers start from MSB or LSB bit, choose one from @ref SPI_MSB_LSB_transmission. */ - uint16_t SPI_CRCPOL; /*!< The polynomial used for the CRC calculation. */ -} SPI_InitPara; - -/** - * @brief I2S Initial Parameters - */ -typedef struct { - uint16_t I2S_Mode; /*!< The operating mode and transfer direction, choose one from @ref I2S_Mode. */ - uint16_t I2S_STD; /*!< The I2S standard, choose one from @ref I2S_Standard. */ - uint16_t I2S_FrameFormat; /*!< The I2S data length and channel length, choose one from @ref I2S_Data_Format. */ - uint16_t I2S_MCKOE; /*!< The I2S MCK output is enabled or disable, choose one from @ref I2S_MCLK_Output. */ - uint32_t I2S_AudioFreq; /*!< The audio sampling frequency, choose one from @ref I2S_Audio_Frequency. */ - uint16_t I2S_CKPL; /*!< The clock polarity in idel state, choose one from @ref I2S_Clock_Polarity. */ -} I2S_InitPara; - -/** - * @} - */ - -/** @defgroup SPI_Exported_Constants - * @{ - */ - -/** @defgroup SPI_transfer_type - * @{ - */ -#define SPI_TRANSTYPE_FULLDUPLEX ((uint16_t)0x0000) -#define SPI_TRANSTYPE_RXONLY SPI_CTLR1_RO -#define SPI_TRANSTYPE_BDMRX SPI_CTLR1_BDM -#define SPI_TRANSTYPE_BDMTX (SPI_CTLR1_BDM | SPI_CTLR1_BDOE) - -/** - * @} - */ - -/** @defgroup SPI_mode - * @{ - */ -#define SPI_MODE_MASTER (SPI_CTLR1_MSTMODE|SPI_CTLR1_SWNSS) -#define SPI_MODE_SLAVE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup SPI_data_frame_format - * @{ - */ -#define SPI_FRAMEFORMAT_16BIT SPI_CTLR1_FF16 -#define SPI_FRAMEFORMAT_8BIT ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup SPI_Clock_Polarity - * @{ - */ -#define SPI_SCKPL_LOW ((uint16_t)0x0000) -#define SPI_SCKPL_HIGH SPI_CTLR1_SCKPL - -/** - * @} - */ - -/** @defgroup SPI_Clock_Phase - * @{ - */ -#define SPI_SCKPH_1EDGE ((uint16_t)0x0000) -#define SPI_SCKPH_2EDGE SPI_CTLR1_SCKPH - -/** - * @} - */ - -/** @defgroup SPI_Software_NSS_management - * @{ - */ -#define SPI_SWNSS_SOFT SPI_CTLR1_SWNSSEN -#define SPI_SWNSS_HARD ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup SPI_BaudRate_Prescaler - * @{ - */ -#define SPI_PSC_2 ((uint16_t)0x0000) -#define SPI_PSC_4 ((uint16_t)0x0008) -#define SPI_PSC_8 ((uint16_t)0x0010) -#define SPI_PSC_16 ((uint16_t)0x0018) -#define SPI_PSC_32 ((uint16_t)0x0020) -#define SPI_PSC_64 ((uint16_t)0x0028) -#define SPI_PSC_128 ((uint16_t)0x0030) -#define SPI_PSC_256 ((uint16_t)0x0038) - -/** - * @} - */ - -/** @defgroup SPI_MSB_LSB_transmission - * @{ - */ -#define SPI_FIRSTBIT_MSB ((uint16_t)0x0000) -#define SPI_FIRSTBIT_LSB SPI_CTLR1_LF - -/** - * @} - */ - -/** @defgroup I2S_Mode - * @{ - */ -#define I2S_MODE_SLAVETX ((uint16_t)0x0000) -#define I2S_MODE_SLAVERX ((uint16_t)0x0100) -#define I2S_MODE_MASTERTX ((uint16_t)0x0200) -#define I2S_MODE_MASTERRX ((uint16_t)0x0300) - -/** - * @} - */ - -/** @defgroup I2S_Standard - * @{ - */ -#define I2S_STD_PHILLIPS ((uint16_t)0x0000) -#define I2S_STD_MSB ((uint16_t)0x0010) -#define I2S_STD_LSB ((uint16_t)0x0020) -#define I2S_STD_PCMSHORT ((uint16_t)0x0030) -#define I2S_STD_PCMLONG ((uint16_t)0x00B0) - -/** - * @} - */ - -/** @defgroup I2S_Data_Format - * @{ - */ -#define I2S_FRAMEFORMAT_DL16b_CL16b ((uint16_t)0x0000) -#define I2S_FRAMEFORMAT_DL16b_CL32b ((uint16_t)0x0001) -#define I2S_FRAMEFORMAT_DL24b_CL32b ((uint16_t)0x0003) -#define I2S_FRAMEFORMAT_DL32b_CL32b ((uint16_t)0x0005) - -/** - * @} - */ - -/** @defgroup I2S_MCLK_Output - * @{ - */ -#define I2S_MCK_ENABLE SPI_I2SCKP_MCKOE -#define I2S_MCK_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup I2S_Audio_Frequency - * @{ - */ -#define I2S_AUDIOFREQ_DEFAULT ((uint32_t)2) -#define I2S_AUDIOFREQ_8K ((uint32_t)8000) -#define I2S_AUDIOFREQ_11K ((uint32_t)11025) -#define I2S_AUDIOFREQ_16K ((uint32_t)16000) -#define I2S_AUDIOFREQ_22K ((uint32_t)22050) -#define I2S_AUDIOFREQ_32K ((uint32_t)32000) -#define I2S_AUDIOFREQ_44K ((uint32_t)44100) -#define I2S_AUDIOFREQ_48K ((uint32_t)48000) -#define I2S_AUDIOFREQ_96K ((uint32_t)96000) -#define I2S_AUDIOFREQ_192K ((uint32_t)192000) - -/** - * @} - */ - -/** @defgroup I2S_Clock_Polarity - * @{ - */ -#define I2S_CKPL_LOW ((uint16_t)0x0000) -#define I2S_CKPL_HIGH SPI_I2SCTLR_CKPL - -/** - * @} - */ - -/** @defgroup SPI_I2S_DMA_transfer_requests - * @{ - */ -#define SPI_I2S_DMA_TX SPI_CTLR2_DMATE -#define SPI_I2S_DMA_RX SPI_CTLR2_DMARE - -/** - * @} - */ - -/** @defgroup SPI_NSS_internal_software_management - * @{ - */ -#define SPI_SWNSS_SET ((uint16_t)0x0001) -#define SPI_SWNSS_RESET ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup SPI_CRC_Transmit_Receive - * @{ - */ -#define SPI_CRC_TX ((uint8_t)0x00) -#define SPI_CRC_RX ((uint8_t)0x01) - -/** - * @} - */ - -/** @defgroup SPI_direction_transmit_receive - * @{ - */ -#define SPI_BDOE_RX (~SPI_CTLR1_BDOE) -#define SPI_BDOE_TX SPI_CTLR1_BDOE - -/** - * @} - */ - -/** @defgroup SPI_I2S_interrupts_definition - * @{ - */ -#define SPI_I2S_INT_TBE ((uint8_t)0x71) -#define SPI_I2S_INT_RBNE ((uint8_t)0x60) -#define SPI_I2S_INT_ERR ((uint8_t)0x50) -#define SPI_I2S_INT_OVR ((uint8_t)0x56) -#define SPI_INT_MODF ((uint8_t)0x55) -#define SPI_INT_CRCERR ((uint8_t)0x54) -#define I2S_INT_UDR ((uint8_t)0x53) - -/** - * @} - */ - -/** @defgroup SPI_I2S_flags_definition - * @{ - */ -#define SPI_FLAG_RBNE SPI_STR_RBNE -#define SPI_FLAG_TBE SPI_STR_TBE -#define SPI_FLAG_CRCERR SPI_STR_CRCE -#define SPI_FLAG_MODF SPI_STR_CONFE -#define SPI_FLAG_OVR SPI_STR_RXORE -#define SPI_FLAG_BSY SPI_STR_TRANS - -#define I2S_FLAG_RBNE SPI_STR_RBNE -#define I2S_FLAG_TBE SPI_STR_TBE -#define I2S_FLAG_CHSIDE SPI_STR_I2SCH -#define I2S_FLAG_UDR SPI_STR_TXURE -#define I2S_FLAG_OVR SPI_STR_RXORE -#define I2S_FLAG_BSY SPI_STR_TRANS - -/** - * @} - */ - -/** - * @} - */ - - -/** @defgroup SPI_Exported_Functions - * @{ - */ -void SPI_I2S_DeInit(SPI_TypeDef *SPIx); -void SPI_Init(SPI_TypeDef *SPIx, SPI_InitPara *SPI_InitParameter); -void I2S_Init(SPI_TypeDef *SPIx, I2S_InitPara *I2S_InitParameter); -void SPI_ParaInit(SPI_InitPara *SPI_InitParameter); -void I2S_ParaInit(I2S_InitPara *I2S_InitParameter); -void SPI_Enable(SPI_TypeDef *SPIx, TypeState NewValue); -void I2S_Enable(SPI_TypeDef *SPIx, TypeState NewValue); -void SPI_I2S_INTConfig(SPI_TypeDef *SPIx, uint8_t SPI_I2S_INT, TypeState NewValue); -void SPI_I2S_DMA_Enable(SPI_TypeDef *SPIx, uint16_t SPI_I2S_DMAReq, TypeState NewValue); -void SPI_I2S_SendData(SPI_TypeDef *SPIx, uint16_t Data); -uint16_t SPI_I2S_ReceiveData(SPI_TypeDef *SPIx); -void SPI_SWNSSConfig(SPI_TypeDef *SPIx, uint16_t SPI_SWNSS); -void SPI_NSSDRV(SPI_TypeDef *SPIx, TypeState NewValue); -void SPI_FrameFormatConfig(SPI_TypeDef *SPIx, uint16_t SPI_DataSize); -void SPI_SendCRCNext(SPI_TypeDef *SPIx); -void SPI_CRC_Enable(SPI_TypeDef *SPIx, TypeState NewValue); -uint16_t SPI_GetCRC(SPI_TypeDef *SPIx, uint8_t SPI_CRC); -uint16_t SPI_GetCRCPolynomial(SPI_TypeDef *SPIx); -void SPI_BDOEConfig(SPI_TypeDef *SPIx, uint16_t SPI_BDOE); -TypeState SPI_I2S_GetBitState(SPI_TypeDef *SPIx, uint16_t SPI_I2S_FLAG); -void SPI_I2S_ClearBitState(SPI_TypeDef *SPIx, uint16_t SPI_I2S_FLAG); -TypeState SPI_I2S_GetIntBitState(SPI_TypeDef *SPIx, uint8_t SPI_I2S_INT); -void SPI_I2S_ClearIntBitState(SPI_TypeDef *SPIx, uint8_t SPI_I2S_INT); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_SPI_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_timer.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_timer.h deleted file mode 100644 index a720a1cd3e..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_timer.h +++ /dev/null @@ -1,758 +0,0 @@ -/** - ****************************************************************************** - * @brief TIMER header file of the firmware library - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_TIMER_H -#define __GD32F10X_TIMER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup TIMER - * @{ - */ - -/** @defgroup TIMER_Exported_Types - * @{ - */ - -/** - * @brief Timer base init structure - */ -typedef struct { - uint16_t TIMER_Prescaler; /*!< Clock prescaler value . */ - uint16_t TIMER_CounterMode; /*!< Counter mode , - a value of @ref TIMER_Counter_Mode. */ - uint32_t TIMER_Period; /*!< Value to be loaded into the active CARL at the next update event. */ - uint16_t TIMER_ClockDivision; /*!< Clock division , - a value of @ref TIMER_Clock_Division_CDIV. */ - uint8_t TIMER_RepetitionCounter; /*!< Repetition counter value , only valid in TIMER1/8. */ -} TIMER_BaseInitPara; - -/** - * @brief Timer output compare init structure - */ -typedef struct { - uint16_t TIMER_OCMode; /*!< Out mode, - a value of @ref TIMER_Output_Compare_and_PWM_modes */ - - uint16_t TIMER_OutputState; /*!< Output Compare state , - a value of @ref TIMER_Output_Compare_State */ - uint16_t TIMER_OutputNState; /*!< Complementary Output Compare state , - a value of @ref TIMER_Output_Compare_N_State, - valid only for TIMER1. */ - uint32_t TIMER_Pulse; /*!< Pulse value to be loaded into the CHCCx. */ - uint16_t TIMER_OCPolarity; /*!< Output polarity , - a value of @ref TIMER_Output_Compare_Polarity */ - uint16_t TIMER_OCNPolarity; /*!< Complementary output polarity , - a value of @ref TIMER_Output_Compare_N_Polarity */ - uint16_t TIMER_OCIdleState; /*!< TIM Output Compare pin state during Idle state , - a value of @ref TIMER_Output_Compare_Idle_State, - valid only for TIMER1. */ - uint16_t TIMER_OCNIdleState; /*!< TIM Complementary Output Compare pin state during Idle state. - a value of @ref TIMER_Output_Compare_N_Idle_State , - valid only for TIMER1. */ -} TIMER_OCInitPara; - -/** - * @brief Timer input capture init structure - */ -typedef struct { - uint16_t TIMER_CH; /*!< TIMER channel , - a value of @ref TIMER_Channel */ - uint16_t TIMER_ICPolarity; /*!< Active edge of the input signal , - a value of @ref TIMER_Input_Capture_Polarity */ - uint16_t TIMER_ICSelection; /*!< Input Selection , - a value of @ref TIMER_Input_Capture_Selection */ - uint16_t TIMER_ICPrescaler; /*!< Input Capture Prescaler , - a value of @ref TIMER_Input_Capture_Prescaler */ - uint16_t TIMER_ICFilter; /*!< Input capture filter , - a number between 0x0 and 0xF */ -} TIMER_ICInitPara; - -/** - * @brief Timer break and dead-time structure , valid only for TIMER1. - */ -typedef struct { - uint16_t TIMER_ROSState; /*!< Off-State selection used in Run mode , - a value of @ref TIMER_ROS_Off_State_Selection_for_Run_mode_State */ - uint16_t TIMER_IOSState; /*!< Off-State used in Idle state , - a value of @ref TIMER_IOS_Off_State_Selection_for_Idle_mode_State */ - uint16_t TIMER_LOCKLevel; /*!< LOCK level , - a value of @ref TIMER_Lock_level */ - uint16_t TIMER_DeadTime; /*!< delay time between the switching off and on of the outputs. - a number between 0x00 and 0xFF */ - uint16_t TIMER_Break; /*!< Break input is enabled or disable, - a value of @ref TIMER_Break_Input_State */ - uint16_t TIMER_BreakPolarity; /*!< Break Input pin polarity , - a value of @ref TIMER_Break_Input_Polarity */ - uint16_t TIMER_OutAuto; /*!< Automatic Output is enabled or disable. - a value of @ref TIMER_OAE_Bit_State */ -} TIMER_BKDTInitPara; - -/** - * @} - */ - -/** @defgroup TIMER_Exported_Constants - * @{ - */ - -/** @defgroup TIMER_Output_Compare_and_PWM_modes - * @{ - */ -#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000) -#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010) -#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020) -#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030) -#define TIMER_OC_MODE_PWM1 ((uint16_t)0x0060) -#define TIMER_OC_MODE_PWM2 ((uint16_t)0x0070) - -/** - * @} - */ - -/** @defgroup TIMER_Single_Pulse_Mode - * @{ - */ -#define TIMER_SP_MODE_SINGLE ((uint16_t)0x0008) -#define TIMER_SP_MODE_REPETITIVE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Channel - * @{ - */ -#define TIMER_CH_1 ((uint16_t)0x0000) -#define TIMER_CH_2 ((uint16_t)0x0004) -#define TIMER_CH_3 ((uint16_t)0x0008) -#define TIMER_CH_4 ((uint16_t)0x000C) - -/** - * @} - */ - -/** @defgroup TIMER_Clock_Division_CDIV - * @{ - */ -#define TIMER_CDIV_DIV1 ((uint16_t)0x0000) -#define TIMER_CDIV_DIV2 ((uint16_t)0x0100) -#define TIMER_CDIV_DIV4 ((uint16_t)0x0200) - -/** - * @} - */ - -/** @defgroup TIMER_Counter_Mode - * @{ - */ -#define TIMER_COUNTER_UP ((uint16_t)0x0000) -#define TIMER_COUNTER_DOWN ((uint16_t)0x0010) -#define TIMER_COUNTER_CENTER_ALIGNED1 ((uint16_t)0x0020) -#define TIMER_COUNTER_CENTER_ALIGNED2 ((uint16_t)0x0040) -#define TIMER_COUNTER_CENTER_ALIGNED3 ((uint16_t)0x0060) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_Polarity - * @{ - */ -#define TIMER_OC_POLARITY_HIGH ((uint16_t)0x0000) -#define TIMER_OC_POLARITY_LOW ((uint16_t)0x0002) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_N_Polarity - * @{ - */ -#define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000) -#define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_State - * @{ - */ -#define TIMER_OUTPUT_STATE_DISABLE ((uint16_t)0x0000) -#define TIMER_OUTPUT_STATE_ENABLE ((uint16_t)0x0001) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_N_State - * @{ - */ -#define TIMER_OUTPUTN_STATE_DISABLE ((uint16_t)0x0000) -#define TIMER_OUTPUTN_STATE_ENABLE ((uint16_t)0x0004) - -/** - * @} - */ - -/** @defgroup TIMER_Capture_Compare_State - * @{ - */ -#define TIMER_CCX_ENABLE ((uint16_t)0x0001) -#define TIMER_CCX_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Capture_Compare_N_State - * @{ - */ -#define TIMER_CCXN_ENABLE ((uint16_t)0x0004) -#define TIMER_CCXN_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Break_Input_State - * @{ - */ -#define TIMER_BREAK_ENABLE ((uint16_t)0x1000) -#define TIMER_BREAK_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Break_Input_Polarity - * @{ - */ -#define TIMER_BREAK_POLARITY_LOW ((uint16_t)0x0000) -#define TIMER_BREAK_POLARITY_HIGH ((uint16_t)0x2000) - -/** - * @} - */ - -/** @defgroup TIMER_OAE_Bit_State - * @{ - */ -#define TIMER_OUTAUTO_ENABLE ((uint16_t)0x4000) -#define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Lock_level - * @{ - */ -#define TIMER_LOCK_LEVEL_OFF ((uint16_t)0x0000) -#define TIMER_LOCK_LEVEL_1 ((uint16_t)0x0100) -#define TIMER_LOCK_LEVEL_2 ((uint16_t)0x0200) -#define TIMER_LOCK_LEVEL_3 ((uint16_t)0x0300) - -/** - * @} - */ - -/** @defgroup TIMER_IOS_Off_State_Selection_for_Idle_mode_State - * @{ - */ -#define TIMER_IOS_STATE_ENABLE ((uint16_t)0x0400) -#define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_ROS_Off_State_Selection_for_Run_mode_State - * @{ - */ -#define TIMER_ROS_STATE_ENABLE ((uint16_t)0x0800) -#define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_Idle_State - * @{ - */ -#define TIMER_OC_IDLE_STATE_SET ((uint16_t)0x0100) -#define TIMER_OC_IDLE_STATE_RESET ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_N_Idle_State - * @{ - */ -#define TIMER_OCN_IDLE_STATE_SET ((uint16_t)0x0200) -#define TIMER_OCN_IDLE_STATE_RESET ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Input_Capture_Polarity - * @{ - */ -#define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000) -#define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002) - -/** - * @} - */ - -/** @defgroup TIMER_Input_Capture_Selection - * @{ - */ -#define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001) -#define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002) -#define TIMER_IC_SELECTION_TRC ((uint16_t)0x0003) - -/** - * @} - */ - -/** @defgroup TIMER_Input_Capture_Prescaler - * @{ - */ -#define TIMER_IC_PSC_DIV1 ((uint16_t)0x0000) -#define TIMER_IC_PSC_DIV2 ((uint16_t)0x0004) -#define TIMER_IC_PSC_DIV4 ((uint16_t)0x0008) -#define TIMER_IC_PSC_DIV8 ((uint16_t)0x000C) - -/** - * @} - */ - -/** @defgroup TIMER_interrupt_sources - * @{ - */ -#define TIMER_INT_UPDATE ((uint16_t)0x0001) -#define TIMER_INT_CH1 ((uint16_t)0x0002) -#define TIMER_INT_CH2 ((uint16_t)0x0004) -#define TIMER_INT_CH3 ((uint16_t)0x0008) -#define TIMER_INT_CH4 ((uint16_t)0x0010) -#define TIMER_INT_CCUG ((uint16_t)0x0020) -#define TIMER_INT_TRIGGER ((uint16_t)0x0040) -#define TIMER_INT_BREAK ((uint16_t)0x0080) - -/** - * @} - */ - -/** @defgroup TIMER_DMA_Base_address - * @{ - */ -#define TIMER_DMA_BASE_ADDR_CTLR1 ((uint16_t)0x0000) -#define TIMER_DMA_BASE_ADDR_CTLR2 ((uint16_t)0x0001) -#define TIMER_DMA_BASE_ADDR_SMC ((uint16_t)0x0002) -#define TIMER_DMA_BASE_ADDR_DIE ((uint16_t)0x0003) -#define TIMER_DMA_BASE_ADDR_STR ((uint16_t)0x0004) -#define TIMER_DMA_BASE_ADDR_EVG ((uint16_t)0x0005) -#define TIMER_DMA_BASE_ADDR_CHCTLR1 ((uint16_t)0x0006) -#define TIMER_DMA_BASE_ADDR_CHCTLR2 ((uint16_t)0x0007) -#define TIMER_DMA_BASE_ADDR_CHE ((uint16_t)0x0008) -#define TIMER_DMA_BASE_ADDR_CNT ((uint16_t)0x0009) -#define TIMER_DMA_BASE_ADDR_PSC ((uint16_t)0x000A) -#define TIMER_DMA_BASE_ADDR_CARL ((uint16_t)0x000B) -#define TIMER_DMA_BASE_ADDR_CREP ((uint16_t)0x000C) -#define TIMER_DMA_BASE_ADDR_CHCC1 ((uint16_t)0x000D) -#define TIMER_DMA_BASE_ADDR_CHCC2 ((uint16_t)0x000E) -#define TIMER_DMA_BASE_ADDR_CHCC3 ((uint16_t)0x000F) -#define TIMER_DMA_BASE_ADDR_CHCC4 ((uint16_t)0x0010) -#define TIMER_DMA_BASE_ADDR_BKDT ((uint16_t)0x0011) -#define TIMER_DMA_BASE_ADDR_DCTLR ((uint16_t)0x0012) - -/** - * @} - */ - -/** @defgroup TIMER_DMA_Burst_Transfer_Length - * @{ - */ -#define TIMER_DMA_BURST_1TRANSFER ((uint16_t)0x0000) -#define TIMER_DMA_BURST_2TRANSFERS ((uint16_t)0x0100) -#define TIMER_DMA_BURST_3TRANSFERS ((uint16_t)0x0200) -#define TIMER_DMA_BURST_4TRANSFERS ((uint16_t)0x0300) -#define TIMER_DMA_BURST_5TRANSFERS ((uint16_t)0x0400) -#define TIMER_DMA_BURST_6TRANSFERS ((uint16_t)0x0500) -#define TIMER_DMA_BURST_7TRANSFERS ((uint16_t)0x0600) -#define TIMER_DMA_BURST_8TRANSFERS ((uint16_t)0x0700) -#define TIMER_DMA_BURST_9TRANSFERS ((uint16_t)0x0800) -#define TIMER_DMA_BURST_10TRANSFERS ((uint16_t)0x0900) -#define TIMER_DMA_BURST_11TRANSFERS ((uint16_t)0x0A00) -#define TIMER_DMA_BURST_12TRANSFERS ((uint16_t)0x0B00) -#define TIMER_DMA_BURST_13TRANSFERS ((uint16_t)0x0C00) -#define TIMER_DMA_BURST_14TRANSFERS ((uint16_t)0x0D00) -#define TIMER_DMA_BURST_15TRANSFERS ((uint16_t)0x0E00) -#define TIMER_DMA_BURST_16TRANSFERS ((uint16_t)0x0F00) -#define TIMER_DMA_BURST_17TRANSFERS ((uint16_t)0x1000) -#define TIMER_DMA_BURST_18TRANSFERS ((uint16_t)0x1100) - -/** - * @} - */ - -/** @defgroup TIMER_DMA_sources - * @{ - */ -#define TIMER_DMA_UPDATE ((uint16_t)0x0100) -#define TIMER_DMA_CH1 ((uint16_t)0x0200) -#define TIMER_DMA_CH2 ((uint16_t)0x0400) -#define TIMER_DMA_CH3 ((uint16_t)0x0800) -#define TIMER_DMA_CH4 ((uint16_t)0x1000) -#define TIMER_DMA_COM ((uint16_t)0x2000) -#define TIMER_DMA_TRIGGER ((uint16_t)0x4000) - -/** - * @} - */ - -/** @defgroup TIMER_External_Trigger_Prescaler - * @{ - */ -#define TIMER_EXT_TRI_PSC_OFF ((uint16_t)0x0000) -#define TIMER_EXT_TRI_PSC_DIV2 ((uint16_t)0x1000) -#define TIMER_EXT_TRI_PSC_DIV4 ((uint16_t)0x2000) -#define TIMER_EXT_TRI_PSC_DIV8 ((uint16_t)0x3000) - -/** - * @} - */ - -/** @defgroup TIMER_Internal_Trigger_Selection - * @{ - */ -#define TIMER_TS_ITR0 ((uint16_t)0x0000) -#define TIMER_TS_ITR1 ((uint16_t)0x0010) -#define TIMER_TS_ITR2 ((uint16_t)0x0020) -#define TIMER_TS_ITR3 ((uint16_t)0x0030) -#define TIMER_TS_TI1F_ED ((uint16_t)0x0040) -#define TIMER_TS_TI1FP1 ((uint16_t)0x0050) -#define TIMER_TS_TI2FP2 ((uint16_t)0x0060) -#define TIMER_TS_ETRF ((uint16_t)0x0070) - -/** - * @} - */ - -/** @defgroup TIMER_TIx_External_Clock_Source - * @{ - */ -#define TIMER_TIX_EXCLK1_SRC_TI1 ((uint16_t)0x0050) -#define TIMER_TIX_EXCLK1_SRC_TI2 ((uint16_t)0x0060) -#define TIMER_TIX_EXCLK1_SRC_TI1ED ((uint16_t)0x0040) - -/** - * @} - */ - -/** @defgroup TIMER_External_Trigger_Polarity - * @{ - */ -#define TIMER_EXT_TRI_POLARITY_INVERTED ((uint16_t)0x8000) -#define TIMER_EXT_TRI_POLARITY_NONINVERTED ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Prescaler_Reload_Mode - * @{ - */ -#define TIMER_PSC_RELOAD_UPDATE ((uint16_t)0x0000) -#define TIMER_PSC_RELOAD_NOW ((uint16_t)0x0001) - -/** - * @} - */ - -/** @defgroup TIMER_Forced_Output - * @{ - */ -#define TIMER_FORCED_HIGH ((uint16_t)0x0050) -#define TIMER_FORCED_LOW ((uint16_t)0x0040) - -/** - * @} - */ - -/** @defgroup TIMER_Encoder_Mode - * @{ - */ -#define TIMER_ENCODER_MODE_TI1 ((uint16_t)0x0001) -#define TIMER_ENCODER_MODE_TI2 ((uint16_t)0x0002) -#define TIMER_ENCODER_MODE_TI12 ((uint16_t)0x0003) - -/** - * @} - */ - -/** @defgroup TIMER_Event_Source - * @{ - */ -#define TIMER_EVENT_SRC_UPDATE ((uint16_t)0x0001) -#define TIMER_EVENT_SRC_CH1 ((uint16_t)0x0002) -#define TIMER_EVENT_SRC_CH2 ((uint16_t)0x0004) -#define TIMER_EVENT_SRC_CH3 ((uint16_t)0x0008) -#define TIMER_EVENT_SRC_CH4 ((uint16_t)0x0010) -#define TIMER_EVENT_SRC_COM ((uint16_t)0x0020) -#define TIMER_EVENT_SRC_TRIGGER ((uint16_t)0x0040) -#define TIMER_EVENT_SRC_BREAK ((uint16_t)0x0080) - -/** - * @} - */ - -/** @defgroup TIMER_Update_Source - * @{ - */ -#define TIMER_UPDATE_SRC_GLOBAL ((uint16_t)0x0000) -#define TIMER_UPDATE_SRC_REGULAR ((uint16_t)0x0001) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_Preload_State - * @{ - */ -#define TIMER_OC_PRELOAD_ENABLE ((uint16_t)0x0008) -#define TIMER_OC_PRELOAD_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_Fast_State - * @{ - */ -#define TIMER_OC_FAST_ENABLE ((uint16_t)0x0004) -#define TIMER_OC_FAST_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Output_Compare_Clear_State - * @{ - */ -#define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080) -#define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Trigger_Output_Source - * @{ - */ -#define TIMER_TRI_OUT_SRC_RESET ((uint16_t)0x0000) -#define TIMER_TRI_OUT_SRC_ENABLE ((uint16_t)0x0010) -#define TIMER_TRI_OUT_SRC_UPDATE ((uint16_t)0x0020) -#define TIMER_TRI_OUT_SRC_OC1 ((uint16_t)0x0030) -#define TIMER_TRI_OUT_SRC_OC1REF ((uint16_t)0x0040) -#define TIMER_TRI_OUT_SRC_OC2REF ((uint16_t)0x0050) -#define TIMER_TRI_OUT_SRC_OC3REF ((uint16_t)0x0060) -#define TIMER_TRI_OUT_SRC_OC4REF ((uint16_t)0x0070) - -/** - * @} - */ - -/** @defgroup TIMER_Slave_Mode - * @{ - */ -#define TIMER_SLAVE_MODE_RESET ((uint16_t)0x0004) -#define TIMER_SLAVE_MODE_GATED ((uint16_t)0x0005) -#define TIMER_SLAVE_MODE_TRIGGER ((uint16_t)0x0006) -#define TIMER_SLAVE_MODE_EXTERNAL1 ((uint16_t)0x0007) - -/** - * @} - */ - -/** @defgroup TIMER_Master_Slave_Mode - * @{ - */ -#define TIMER_MASTER_SLAVE_MODE_ENABLE ((uint16_t)0x0080) -#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup TIMER_Flags - * @{ - */ -#define TIMER_FLAG_UPDATE ((uint16_t)0x0001) -#define TIMER_FLAG_CH1 ((uint16_t)0x0002) -#define TIMER_FLAG_CH2 ((uint16_t)0x0004) -#define TIMER_FLAG_CH3 ((uint16_t)0x0008) -#define TIMER_FLAG_CH4 ((uint16_t)0x0010) -#define TIMER_FLAG_COM ((uint16_t)0x0020) -#define TIMER_FLAG_TRIGGER ((uint16_t)0x0040) -#define TIMER_FLAG_BREAK ((uint16_t)0x0080) -#define TIMER_FLAG_CH1OF ((uint16_t)0x0200) -#define TIMER_FLAG_CH2OF ((uint16_t)0x0400) -#define TIMER_FLAG_CH3OF ((uint16_t)0x0800) -#define TIMER_FLAG_CH4OF ((uint16_t)0x1000) - -/** - * @} - */ - - -/** - * @} - */ - - -/** @defgroup TIMER_Exported_Functions - * @{ - */ -/* TimeBase management ********************************************************/ -void TIMER_DeInit(TIMER_TypeDef *TIMERx); -void TIMER_BaseInit(TIMER_TypeDef *TIMERx, TIMER_BaseInitPara *TIMER_Init); -void TIMER_BaseStructInit(TIMER_BaseInitPara *TIMER_Init); -void TIMER_PrescalerConfig(TIMER_TypeDef *TIMERx, uint16_t Prescaler, uint16_t TIMER_PSCReloadMode); -void TIMER_CounterMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_CounterMode); -void TIMER_SetCounter(TIMER_TypeDef *TIMERx, uint32_t Counter); -void TIMER_SetAutoreload(TIMER_TypeDef *TIMERx, uint32_t AutoReloadValue); -uint32_t TIMER_GetCounter(TIMER_TypeDef *TIMERx); -uint16_t TIMER_GetPrescaler(TIMER_TypeDef *TIMERx); -void TIMER_UpdateDisableConfig(TIMER_TypeDef *TIMERx, TypeState NewValue); -void TIMER_UpdateRequestConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_UpdateSrc); -void TIMER_CARLPreloadConfig(TIMER_TypeDef *TIMERx, TypeState NewValue); -void TIMER_SinglePulseMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_SPMode); -void TIMER_SetClockDivision(TIMER_TypeDef *TIMERx, uint16_t TIMER_CDIV); -void TIMER_Enable(TIMER_TypeDef *TIMERx, TypeState NewValue); - -/* Advanced timer features*******************/ -void TIMER_BKDTConfig(TIMER_TypeDef *TIMERx, TIMER_BKDTInitPara *TIMER_BKDTInit); -void TIMER_BKDTStructInit(TIMER_BKDTInitPara *TIMER_BKDTInit); -void TIMER_CtrlPWMOutputs(TIMER_TypeDef *TIMERx, TypeState NewValue); - -/* Output Compare management **************************************************/ -void TIMER_OC1_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit); -void TIMER_OC2_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit); -void TIMER_OC3_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit); -void TIMER_OC4_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit); -void TIMER_OCStructInit(TIMER_OCInitPara *TIMER_OCInit); -void TIMER_OCxModeConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_Ch, uint16_t TIMER_OCMode); -void TIMER_Compare1Config(TIMER_TypeDef *TIMERx, uint32_t CompValue1); -void TIMER_Compare2Config(TIMER_TypeDef *TIMERx, uint32_t CompValue2); -void TIMER_Compare3Config(TIMER_TypeDef *TIMERx, uint32_t CompValue3); -void TIMER_Compare4Config(TIMER_TypeDef *TIMERx, uint32_t CompValue4); -void TIMER_Forced_OC1(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced); -void TIMER_Forced_OC2(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced); -void TIMER_Forced_OC3(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced); -void TIMER_Forced_OC4(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced); -void TIMER_CC_PreloadControl(TIMER_TypeDef *TIMERx, TypeState NewValue); -void TIMER_OC1_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload); -void TIMER_OC2_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload); -void TIMER_OC3_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload); -void TIMER_OC4_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload); -void TIMER_OC1_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast); -void TIMER_OC2_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast); -void TIMER_OC3_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast); -void TIMER_OC4_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast); -void TIMER_OC1_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear); -void TIMER_OC2_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear); -void TIMER_OC3_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear); -void TIMER_OC4_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear); -void TIMER_OC1_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity); -void TIMER_OC1N_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCNPolarity); -void TIMER_OC2_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity); -void TIMER_OC2N_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCNPolarity); -void TIMER_OC3_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity); -void TIMER_OC3N_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCNPolarity); -void TIMER_OC4_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity); -void TIMER_SelectOCRefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCRef_Clear); -void TIMER_CCxCmd(TIMER_TypeDef *TIMERx, uint16_t TIMER_Ch, uint16_t TIMER_CCx); -void TIMER_CCxNCmd(TIMER_TypeDef *TIMERx, uint16_t TIMER_Ch, uint16_t TIMER_CCxN); -void TIMER_SelectCOM(TIMER_TypeDef *TIMERx, TypeState NewValue); - -/* Input Capture management ***************************************************/ -void TIMER_ICInit(TIMER_TypeDef *TIMERx, TIMER_ICInitPara *TIMER_ICInit); -void TIMER_ICStructInit(TIMER_ICInitPara *TIMER_ICInit); -void TIMER_PWMCaptureConfig(TIMER_TypeDef *TIMERx, TIMER_ICInitPara *TIMER_ICInit); -uint32_t TIMER_GetCapture1(TIMER_TypeDef *TIMERx); -uint32_t TIMER_GetCapture2(TIMER_TypeDef *TIMERx); -uint32_t TIMER_GetCapture3(TIMER_TypeDef *TIMERx); -uint32_t TIMER_GetCapture4(TIMER_TypeDef *TIMERx); -void TIMER_Set_IC1_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC); -void TIMER_Set_IC2_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC); -void TIMER_Set_IC3_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC); -void TIMER_Set_IC4_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC); - -/* Interrupts, DMA and flags management ***************************************/ -void TIMER_INTConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_INT, TypeState NewValue); -void TIMER_GenerateEvent(TIMER_TypeDef *TIMERx, uint16_t TIMER_EventSrc); -TypeState TIMER_GetBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_FLAG); -void TIMER_ClearBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_FLAG); -TypeState TIMER_GetIntBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_INT); -void TIMER_ClearIntBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_INT); -void TIMER_DMAConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_DMABase, uint16_t TIMER_DMABurstLength); -void TIMER_DMACmd(TIMER_TypeDef *TIMERx, uint16_t TIMER_DMASrc, TypeState NewValue); -void TIMER_CC_DMA(TIMER_TypeDef *TIMERx, TypeState NewValue); - -/* Clocks management **********************************************************/ -void TIMER_InternalClockConfig(TIMER_TypeDef *TIMERx); -void TIMER_ITRxExtClock(TIMER_TypeDef *TIMERx, uint16_t TIMER_InputTriSrc); -void TIMER_TIxExtCLkConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_TIxExCLKSrc, - uint16_t TIMER_ICPolarity, uint16_t ICFilter); -void TIMER_ETRClockMode1Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ExTriPrescaler, uint16_t TIMER_ExTriPolarity, - uint16_t ExtTriFilter); -void TIMER_ETRClockMode2Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ExTriPrescaler, - uint16_t TIMER_ExTriPolarity, uint16_t ExtTriFilter); -/* Synchronization management *************************************************/ -void TIMER_SelectInputTrigger(TIMER_TypeDef *TIMERx, uint16_t TIMER_InputTriSrc); -void TIMER_SelectOutputTrigger(TIMER_TypeDef *TIMERx, uint16_t TIMER_TriOutSrc); -void TIMER_SelectSlaveMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_SlaveMode); -void TIMER_SelectMasterSlaveMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_MasterSlaveMode); -void TIMER_ETRConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_ExTriPrescaler, uint16_t TIMER_ExTriPolarity, - uint16_t ExtTriFilter); - -/* Specific interface management **********************************************/ -void TIMER_EncoderInterfaceConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_EncoderMode, - uint16_t TIMER_IC1Polarity, uint16_t TIMER_IC2Polarity); -void TIMER_SelectHallSensor(TIMER_TypeDef *TIMERx, TypeState NewValue); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_TIMER_H */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_usart.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_usart.h deleted file mode 100644 index dec1f603a1..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_usart.h +++ /dev/null @@ -1,297 +0,0 @@ -/** - ****************************************************************************** - * @brief USART header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_USART_H -#define __GD32F10X_USART_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @addtogroup USART - * @{ - */ - -/** @defgroup USART_Exported_Types - * @{ - */ - -/** - * @brief USART Initial Parameters - */ -typedef struct { - uint32_t USART_BRR; /*!< the USART communication baud rate configuration */ - uint16_t USART_WL; /*!< Set by USART_CTLR1_WL Word length 0: 8 Data bits, - 1: 9 Data bits */ - uint16_t USART_STBits; /*!< Stop bits configuration */ - - uint16_t USART_Parity; /*!< Set by USART_CTLR1_PCEN */ - - uint16_t USART_RxorTx; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled. */ - - uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled - or disabled.This parameter can be a value of @ref USART_Hardware_Flow_Control */ -} USART_InitPara; - -/** - * @brief USART Clock Init Structure definition - */ - -typedef struct { - uint16_t USART_CKEN; /*!< USART clock enabled this parameter can be a value of @ref USART_CKEN */ - - uint16_t USART_CPL; /*!< Clock polarity of Steady state this parameter can be a value of @ref USART_Clock_Polarity */ - - uint16_t USART_CPH; /*!< Clock phase this parameter can be a value of @ref USART_Clock_Phase */ - - uint16_t USART_LBCP; /*!< Last bit clock pulse this parameter can be a value of @ref USART_Last_Bit */ -} USART_ClockInitPara; - -/** - * @} - */ - -/** @defgroup USART_Exported_Constants - * @{ - */ - -/** @defgroup USART_WL - * @{ - */ -#define USART_WL_8B ((uint16_t)0x0000) -#define USART_WL_9B USART_CTLR1_WL - -/** - * @} - */ - -/** @defgroup USART_STBits - * @{ - */ -#define USART_STBITS_1 ((uint16_t)0x0000) -#define USART_STBITS_0_5 ((uint16_t)0x1000) -#define USART_STBITS_2 USART_CTLR2_STB_1 -#define USART_STBITS_1_5 (USART_CTLR2_STB_0 | USART_CTLR2_STB_1) -/** - * @} - */ - -/** @defgroup USART_Parity - * @{ - */ -#define USART_PARITY_RESET ((uint16_t)0x0000) -#define USART_PARITY_SETEVEN USART_CTLR1_PCEN -#define USART_PARITY_SETODD (USART_CTLR1_PCEN | USART_CTLR1_PM) - -/** - * @} - */ - -/** @defgroup USART_RxorTx - * @{ - */ -#define USART_RXORTX_RX USART_CTLR1_REN -#define USART_RXORTX_TX USART_CTLR1_TEN - -/** - * @} - */ - -/** @defgroup USART_Hardware_Flow_Control - * @{ - */ -#define USART_HARDWAREFLOWCONTROL_NONE ((uint16_t)0x0000) -#define USART_HARDWAREFLOWCONTROL_RTS USART_CTLR3_RTSEN -#define USART_HARDWAREFLOWCONTROL_CTS USART_CTLR3_CTSEN -#define USART_HARDWAREFLOWCONTROL_RTS_CTS (USART_CTLR3_RTSEN | USART_CTLR3_CTSEN) - -/** - * @} - */ - -/** @defgroup USART_CKEN - * @{ - */ -#define USART_CKEN_RESET ((uint16_t)0x0000) -#define USART_CKEN_SET USART_CTLR2_CKEN - -/** - * @} - */ - -/** @defgroup USART_Clock_Polarity - * @{ - */ -#define USART_CPL_LOW ((uint16_t)0x0000) -#define USART_CPL_HIGH USART_CTLR2_CPL - -/** - * @} - */ - -/** @defgroup USART_Clock_Phase - * @{ - */ -#define USART_CPH_1EDGE ((uint16_t)0x0000) -#define USART_CPH_2EDGE USART_CTLR2_CPH - -/** - * @} - */ - -/** @defgroup USART_Last_Bit - * @{ - */ -#define USART_LBCP_DISABLE ((uint16_t)0x0000) -#define USART_LBCP_ENABLE USART_CTLR2_LBCP - -/** - * @} - */ - -/** @defgroup USART_DMA_Requests - * @{ - */ -#define USART_DMAREQ_TX USART_CTLR3_DENT -#define USART_DMAREQ_RX USART_CTLR3_DENR -/** - * @} - */ -/** @defgroup USART_Interrupt_definition - * @brief USART Interrupt definition - * USART_INT possible values - * @{ - */ -#define USART_INT_PE ((uint16_t)0x0028) -#define USART_INT_TBE ((uint16_t)0x0727) -#define USART_INT_TC ((uint16_t)0x0626) -#define USART_INT_RBNE ((uint16_t)0x0525) -#define USART_INT_IDLEF ((uint16_t)0x0424) -#define USART_INT_LBDF ((uint16_t)0x0846) -#define USART_INT_CTSF ((uint16_t)0x096A) -#define USART_INT_ERIE ((uint16_t)0x0060) -#define USART_INT_ORE ((uint16_t)0x0360) -#define USART_INT_NE ((uint16_t)0x0260) -#define USART_INT_FE ((uint16_t)0x0160) - -/** - * @} - */ - - - -/** @defgroup USART_MuteMode_WakeUp_methods - * @{ - */ -#define USART_WAKEUP_IDLELINE ((uint16_t)0x0000) -#define USART_WAKEUP_ADDRESSMARK USART_CTLR1_WM - -/** - * @} - */ - - -/** @defgroup USART_LIN_Break_Detection_Length - * @{ - */ -#define USART_LINBREAKDETECTLENGTH_10B ((uint16_t)0x0000) -#define USART_LINBREAKDETECTLENGTH_11B USART_CTLR2_LBDL - -/** - * @} - */ - -/** @defgroup USART_IrDA_Low_Power - * @{ - */ -#define USART_IRDAMODE_LOWPOWER USART_CTLR3_IRLP -#define USART_IRDAMODE_NORMAL ((uint16_t)0x0000) - -/** - * @} - */ - -/** @defgroup USART_Flags - * @{ - */ - -#define USART_FLAG_CTSF ((uint16_t)0x0200) -#define USART_FLAG_LBDF ((uint16_t)0x0100) -#define USART_FLAG_TBE ((uint16_t)0x0080) -#define USART_FLAG_TC ((uint16_t)0x0040) -#define USART_FLAG_RBNE ((uint16_t)0x0020) -#define USART_FLAG_IDLEF ((uint16_t)0x0010) -#define USART_FLAG_ORE ((uint16_t)0x0008) -#define USART_FLAG_NE ((uint16_t)0x0004) -#define USART_FLAG_FE ((uint16_t)0x0002) -#define USART_FLAG_PE ((uint16_t)0x0001) -/** - * @} - */ - - - -/** - * @} - */ - -/** @defgroup USART_Exported_Functions - * @{ - */ - -void USART_DeInit(USART_TypeDef *USARTx); -void USART_Init(USART_TypeDef *USARTx, USART_InitPara *USART_InitParaStruct); -void USART_ParaInit(USART_InitPara *USART_InitParaStruct); -void USART_ClockInit(USART_TypeDef *USARTx, USART_ClockInitPara *USART_ClockInitStruct); -void USART_ClockStructInit(USART_ClockInitPara *USART_ClockInitParaStruct); -void USART_Enable(USART_TypeDef *USARTx, TypeState NewValue); -void USART_HalfDuplex_Enable(USART_TypeDef *USARTx, TypeState NewValue); -void USART_SetPrescaler(USART_TypeDef *USARTx, uint8_t USART_Prescaler); -void USART_DataSend(USART_TypeDef *USARTx, uint16_t Data); -uint16_t USART_DataReceive(USART_TypeDef *USARTx); -void USART_Address(USART_TypeDef *USARTx, uint8_t USART_Address); -void USART_MuteMode_Enable(USART_TypeDef *USARTx, TypeState NewState); -void USART_MuteModeWakeUp_Set(USART_TypeDef *USARTx, uint16_t USART_WakeUp); -void USART_SetLINBDLength(USART_TypeDef *USARTx, uint16_t USART_LINBreakDetectLength); -void USART_LIN_Enable(USART_TypeDef *USARTx, TypeState NewValue); -void USART_GuardTime_Set(USART_TypeDef *USARTx, uint8_t USART_GuardTime); -void USART_SmartCard_Enable(USART_TypeDef *USARTx, TypeState NewValue); -void USART_SmartCardNACK_Enable(USART_TypeDef *USARTx, TypeState NewValue); -void USART_IrDA_Set(USART_TypeDef *USARTx, uint16_t USART_IrDAMode); -void USART_IrDA_Enable(USART_TypeDef *USARTx, TypeState NewValue); -void USART_DMA_Enable(USART_TypeDef *USARTx, uint16_t USART_DMAEnable, TypeState NewValue); -void USART_INT_Set(USART_TypeDef *USARTx, uint16_t USART_INT, TypeState NewValue); -TypeState USART_GetBitState(USART_TypeDef *USARTx, uint16_t USART_FLAG); -void USART_ClearBitState(USART_TypeDef *USARTx, uint16_t USART_FLAG); -TypeState USART_GetIntBitState(USART_TypeDef *USARTx, uint16_t USART_INT); -void USART_ClearIntBitState(USART_TypeDef *USARTx, uint16_t USART_INT); -void USART_SendBreak(USART_TypeDef *USARTx); - -#ifdef __cplusplus -} -#endif - -#endif /*__GD32F10X_USART_H */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_wwdg.h b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_wwdg.h deleted file mode 100644 index 751defeb8e..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Include/gd32f10x_wwdg.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - ****************************************************************************** - * @brief WWDG header file of the firmware library. - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __GD32F10X_WWDG_H -#define __GD32F10X_WWDG_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup WWDG - * @{ - */ - -/** @defgroup WWDG_Exported_Constants - * @{ - */ - -/** @defgroup WWDG_PRESCALER - * @{ - */ -#define WWDG_PRESCALER_1 ((uint32_t)0x00000000) -#define WWDG_PRESCALER_2 ((uint32_t)0x00000080) -#define WWDG_PRESCALER_4 ((uint32_t)0x00000100) -#define WWDG_PRESCALER_8 ((uint32_t)0x00000180) - -/** - * @} - */ - -/** - * @} - */ - -/* Exported functions ------------------------------------------------------- */ -/** @defgroup WWDG_Exported_Functions - * @{ - */ - -void WWDG_DeInit(void); -void WWDG_SetPrescalerValue(uint32_t PrescalerValue); -void WWDG_SetWindowValue(uint8_t WindowValue); -void WWDG_EnableInt(void); -void WWDG_SetCounterValue(uint8_t CounterValue); -void WWDG_Enable(uint8_t CounterValue); -TypeState WWDG_GetBitState(void); -void WWDG_ClearBitState(void); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __GD32F10X_WWDG_H */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_adc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_adc.c deleted file mode 100644 index 9d6205e1b2..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_adc.c +++ /dev/null @@ -1,977 +0,0 @@ -/** - ****************************************************************************** - * @brief ADC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_adc.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup ADC - * @brief ADC driver modules - * @{ - */ - -/** @defgroup ADC_Private_Defines - * @{ - */ - -/* ADC CTLR1_DISNUM mask */ -#define CTLR1_DISNUM_RESET ((uint32_t)0xFFFF1FFF) - -/* ADC CTLR1_DISRC mask */ -#define CTLR1_DISRC_SET ((uint32_t)0x00000800) - -/* ADC CTLR1_ICA mask */ -#define CTLR1_ICA_SET ((uint32_t)0x00000400) - -/* ADC CTLR1_DISIC mask */ -#define CTLR1_DISIC_SET ((uint32_t)0x00001000) - -/* ADC CTLR1_AWCS mask */ -#define CTLR1_AWCS_RESET ((uint32_t)0xFFFFFFE0) - -/* ADC CTLR1_AWDMode mask */ -#define CTLR1_AWDMODE_RESET ((uint32_t)0xFF3FFDFF) - -/* CTLR1 register mask */ -#define CTLR1_BITS_CLEAR ((uint32_t)0xFFF0FEFF) - -/* ADC CTLR2_ADCON mask */ -#define CTLR2_ADCON_SET ((uint32_t)0x00000001) - -/* ADC CTLR2_DMA mask */ -#define CTLR2_DMA_SET ((uint32_t)0x00000100) - -/* ADC CTLR2_RSTCLB mask */ -#define CTLR2_RSTCLB_SET ((uint32_t)0x00000008) - -/* ADC CTLR2_CLB mask */ -#define CTLR2_CLB_SET ((uint32_t)0x00000004) - -/* ADC CTLR2_SWRCST mask */ -#define CTLR2_SWRCST_SET ((uint32_t)0x00400000) - -/* ADC CTLR2_ETERC mask */ -#define CTLR2_ETERC_SET ((uint32_t)0x00100000) - -/* ADC CTLR2_ETERC_SWRCST mask */ -#define CTLR2_ETERC_SWRCST_SET ((uint32_t)0x00500000) - -/* ADC CTLR2_ETSIC mask */ -#define CTLR2_ETSIC_RESET ((uint32_t)0xFFFF8FFF) - -/* ADC CTLR2_ETEIC mask */ -#define CTLR2_ETEIC_SET ((uint32_t)0x00008000) - -/* ADC CTLR2_SWICST mask */ -#define CTLR2_SWICST_SET ((uint32_t)0x00200000) - -/* ADC CTLR2_ETEIC_SWICST mask */ -#define CTLR2_ETEIC_SWICST_SET ((uint32_t)0x00208000) - -/* ADC CTLR2_TSVREN mask */ -#define CTLR2_TSVREN_SET ((uint32_t)0x00800000) - -/* CTLR2 register mask */ -#define CTLR2_BITS_CLEAR ((uint32_t)0xFFF1F7FD) - -/* ADC RSQx mask */ -#define RSQ3_RSQ_SET ((uint32_t)0x0000001F) -#define RSQ2_RSQ_SET ((uint32_t)0x0000001F) -#define RSQ1_RSQ_SET ((uint32_t)0x0000001F) - -/* RSQ1 register mask */ -#define RSQ1_BITS_CLEAR ((uint32_t)0xFF0FFFFF) - -/* ADC ISQx mask */ -#define ISQ_ISQ_SET ((uint32_t)0x0000001F) - -/* ADC IL mask */ -#define ISQ_IL_SET ((uint32_t)0x00300000) - -/* ADC SPTx mask */ -#define SPT1_SPT_SET ((uint32_t)0x00000007) -#define SPT2_SPT_SET ((uint32_t)0x00000007) - -/* ADC IDTRx registers offset */ -#define IDTR_OFFSET ((uint8_t)0x28) - -/* ADC0 RDTR register base address */ -#define RDTR_ADDRESS ((uint32_t)0x4001244C) - -/** - * @} - */ - -/** @defgroup ADC_Private_Functions - * @{ - */ - -/** - * @brief Reset the ADC interface and init the sturct ADC_InitPara. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_InitParaStruct : the sturct ADC_InitPara pointer. - * @retval None - */ -void ADC_DeInit(ADC_TypeDef *ADCx, ADC_InitPara *ADC_InitParaStruct) -{ - if (ADCx == ADC0) { - /* Enable ADC0 reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_ADC0RST, ENABLE); - /* Release ADC0 from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_ADC0RST, DISABLE); - } else if (ADCx == ADC1) { - /* Enable ADC1 reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_ADC1RST, ENABLE); - /* Release ADC1 from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_ADC1RST, DISABLE); - } - /* Initialize the ADC_Mode member,independent mode */ - ADC_InitParaStruct->ADC_Mode = ADC_MODE_INDEPENDENT; - /* Initialize the ADC_Mode_Scan member,disable scan mode */ - ADC_InitParaStruct->ADC_Mode_Scan = DISABLE; - /* Initialize the ADC_Mode_Continuous member,disable continuous mode */ - ADC_InitParaStruct->ADC_Mode_Continuous = DISABLE; - /* Initialize the ADC_Trig_External member,choose T1 CC1 as external trigger */ - ADC_InitParaStruct->ADC_Trig_External = ADC_EXTERNAL_TRIGGER_MODE_T1_CC1; - /* Initialize the ADC_Data_Align member,specifies the ADC data alignment right */ - ADC_InitParaStruct->ADC_Data_Align = ADC_DATAALIGN_RIGHT; - /* Initialize the ADC_Channel_Number member,only 1 channel */ - ADC_InitParaStruct->ADC_Channel_Number = 1; -} - -/** - * @brief Initialize the ADCx interface parameters. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_InitParaStruct: the sturct ADC_InitPara pointer. - * @retval None - */ -void ADC_Init(ADC_TypeDef *ADCx, ADC_InitPara *ADC_InitParaStruct) -{ - uint32_t temp1 = 0; - uint8_t temp2 = 0; - /* ADCx CTLR1 Configuration */ - /* Get the ADCx CTLR1 previous value */ - temp1 = ADCx->CTLR1; - /* Clear SM bits */ - temp1 &= CTLR1_BITS_CLEAR; - /* Configure ADCx: Dual mode and scan conversion mode */ - /* Set DUALMOD bits according to ADC_Mode value */ - /* Configure SCAN bit according to ADC_Mode_Scan value */ - temp1 |= (uint32_t)(ADC_InitParaStruct->ADC_Mode | ((uint32_t)ADC_InitParaStruct->ADC_Mode_Scan << 8)); - /* Write new value to ADCx CTLR1 */ - ADCx->CTLR1 = temp1; - - /* ADCx CTLR2 Configuration */ - /* Get the ADCx CTLR2 previous value */ - temp1 = ADCx->CTLR2; - /* Clear CTN, DAL and ETSRC bits */ - temp1 &= CTLR2_BITS_CLEAR; - /* Configure ADCx: select external trigger mode and continuous conversion mode */ - /* Configure DAL bit according to ADC_Data_Align value */ - /* Configure ETSRC bits according to ADC_Trig_External value */ - /* Configure CTN bit according to ADC_Mode_Continuous value */ - temp1 |= (uint32_t)(ADC_InitParaStruct->ADC_Data_Align | ADC_InitParaStruct->ADC_Trig_External | - ((uint32_t)ADC_InitParaStruct->ADC_Mode_Continuous << 1)); - /* Write new value to ADCx CTLR2 */ - ADCx->CTLR2 = temp1; - - /* ADCx RSQ1 Configuration */ - /* Get the ADCx RSQ1 previous value */ - temp1 = ADCx->RSQ1; - /* Clear RL bits */ - temp1 &= RSQ1_BITS_CLEAR; - /* Configure ADCx: regular channel sequence length */ - /* Configure RL bits according to ADC_Channel_Number value */ - temp2 |= (uint8_t)(ADC_InitParaStruct->ADC_Channel_Number - (uint8_t)1); - temp1 |= (uint32_t)temp2 << 20; - /* Write new value to ADCx RSQ1 */ - ADCx->RSQ1 = temp1; -} - -/** - * @brief Enable or disable the ADCx interface. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: New state of the ADCx interface. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ADCx interface */ - ADCx->CTLR2 |= CTLR2_ADCON_SET; - } else { - /* Disable the ADCx interface */ - ADCx->CTLR2 &= ~CTLR2_ADCON_SET; - } -} - -/** - * @brief Enable or disable the ADCx DMA request. - * @param ADCx: the ADC interface where x can be 1..3. - * Note: ADC1 doesn't support DMA function. - * @param NewValue: New state of ADCx DMA transfer. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_DMA_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable ADCx DMA request */ - ADCx->CTLR2 |= CTLR2_DMA_SET; - } else { - /* Disable ADCx DMA request */ - ADCx->CTLR2 &= ~CTLR2_DMA_SET; - } -} - -/** - * @brief Enable or disable ADCx interrupts. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_INT: ADCx interrupt sources. - * This parameter can be any combination of the following values: - * @arg ADC_INT_EOC: Regular conversion over interrupt mask - * @arg ADC_INT_AWE: Analog watchdog interrupt mask - * @arg ADC_INT_EOIC: Inserted conversion over interrupt mask - * @param NewValue: ADCx interrupts state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_INTConfig(ADC_TypeDef *ADCx, uint16_t ADC_INT, TypeState NewValue) -{ - uint8_t temp_it = 0; - /* ADCx INT old state */ - temp_it = (uint8_t)ADC_INT; - if (NewValue != DISABLE) { - /* Enable the ADCx interrupt */ - ADCx->CTLR1 |= temp_it; - } else { - /* Disable the ADCx interrupt */ - ADCx->CTLR1 &= (~(uint32_t)temp_it); - } -} - -/** - * @brief ADCx calibration. - * @param ADCx: the ADC interface where x can be 1..3. - * @retval None - */ -void ADC_Calibration(ADC_TypeDef *ADCx) -{ - /* Reset the selected ADCx calibration registers */ - ADCx->CTLR2 |= CTLR2_RSTCLB_SET; - /* Check the RSTCLB bit state */ - while ((ADCx->CTLR2 & CTLR2_RSTCLB_SET)); - /* Enable ADCx calibration process */ - ADCx->CTLR2 |= CTLR2_CLB_SET; - /* Check the CLB bit state */ - while ((ADCx->CTLR2 & CTLR2_CLB_SET) != (uint32_t)RESET); -} - -/** - * @brief Enable or disable ADCx software start conversion. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADCx software start conversion state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_SoftwareStartConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* ADCx software conversion start */ - ADCx->CTLR2 |= CTLR2_ETERC_SWRCST_SET; - } else { - /* ADCx software conversion stop */ - ADCx->CTLR2 &= ~CTLR2_ETERC_SWRCST_SET; - } -} - -/** - * @brief Get the bit state of ADCx software start conversion. - * @param ADCx: the ADC interface where x can be 1..3. - * @retval ADCx software start conversion state(SET or RESET). - */ -TypeState ADC_GetSoftwareStartConvBitState(ADC_TypeDef *ADCx) -{ - /* Check the SWRCST bit state*/ - if ((ADCx->CTLR2 & CTLR2_SWRCST_SET) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Configure the ADCx channel discontinuous mode. - * @param ADCx: the ADC interface where x can be 1..3. - * @param Number: the count value of discontinuous mode regular channel. - * This number must be 1~8. - * @retval None - */ -void ADC_DiscModeChannelCount_Config(ADC_TypeDef *ADCx, uint8_t Number) -{ - uint32_t temp1 = 0; - uint32_t temp2 = 0; - /* Get the old value of CTLR1 */ - temp1 = ADCx->CTLR1; - /* Clear discontinuous mode channel count */ - temp1 &= CTLR1_DISNUM_RESET; - /* Set the discontinuous mode channel count */ - temp2 = Number - 1; - temp1 |= temp2 << 13; - /* Write new value to CTLR1 */ - ADCx->CTLR1 = temp1; -} - -/** - * @brief Enable or disable the discontinuous mode. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADCx discontinuous mode state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_DiscMode_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable ADCx regular discontinuous mode */ - ADCx->CTLR1 |= CTLR1_DISRC_SET; - } else { - /* Disable ADCx regular discontinuous mode */ - ADCx->CTLR1 &= ~CTLR1_DISRC_SET; - } -} - -/** - * @brief Configure array and sample time. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_Channel: the selected ADC channel. - * This parameter can be as follows: - * @arg ADC_CHANNEL_0: ADC Channel0 - * @arg ADC_CHANNEL_1: ADC Channel1 - * @arg ADC_CHANNEL_2: ADC Channel2 - * @arg ADC_CHANNEL_3: ADC Channel3 - * @arg ADC_CHANNEL_4: ADC Channel4 - * @arg ADC_CHANNEL_5: ADC Channel5 - * @arg ADC_CHANNEL_6: ADC Channel6 - * @arg ADC_CHANNEL_7: ADC Channel7 - * @arg ADC_CHANNEL_8: ADC Channel8 - * @arg ADC_CHANNEL_9: ADC Channel9 - * @arg ADC_CHANNEL_10: ADC Channel10 - * @arg ADC_CHANNEL_11: ADC Channel11 - * @arg ADC_CHANNEL_12: ADC Channel12 - * @arg ADC_CHANNEL_13: ADC Channel13 - * @arg ADC_CHANNEL_14: ADC Channel14 - * @arg ADC_CHANNEL_15: ADC Channel15 - * @arg ADC_CHANNEL_16: ADC Channel16 - * @arg ADC_CHANNEL_17: ADC Channel17 - * @param Array: The regular group sequencer rank. This parameter must be between 1 to 16. - * @param ADC_SampleTime: The sample time value. - * This parameter can be one of the following values: - * @arg ADC_SAMPLETIME_1POINT5: 1.5 cycles - * @arg ADC_SAMPLETIME_7POINT5: 7.5 cycles - * @arg ADC_SAMPLETIME_13POINT5: 13.5 cycles - * @arg ADC_SAMPLETIME_28POINT5: 28.5 cycles - * @arg ADC_SAMPLETIME_41POINT5: 41.5 cycles - * @arg ADC_SAMPLETIME_55POINT5: 55.5 cycles - * @arg ADC_SAMPLETIME_71POINT5: 71.5 cycles - * @arg ADC_SAMPLETIME_239POINT5: 239.5 cycles - * @retval None - */ -void ADC_RegularChannel_Config(ADC_TypeDef *ADCx, uint8_t ADC_Channel, uint8_t Array, uint8_t ADC_SampleTime) -{ - uint32_t temp1 = 0, temp2 = 0; - - /* if ADC_Channel is between 10 to 17 */ - if (ADC_Channel > ADC_CHANNEL_9) { - /* Get SPT1 value */ - temp1 = ADCx->SPT1; - /* Calculate the mask to clear */ - temp2 = SPT1_SPT_SET << (3 * (ADC_Channel - 10)); - /* Clear sample time */ - temp1 &= ~temp2; - /* Calculate the mask to set */ - temp2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); - /* Configure sample time */ - temp1 |= temp2; - /* Write to SPT1 */ - ADCx->SPT1 = temp1; - } else { /* ADC_Channel is between 0 to 9 */ - /* Get SPT2 value */ - temp1 = ADCx->SPT2; - /* Calculate the mask to clear */ - temp2 = SPT2_SPT_SET << (3 * ADC_Channel); - /* Clear sample time */ - temp1 &= ~temp2; - /* Calculate the mask to set */ - temp2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); - /* Set sample time */ - temp1 |= temp2; - /* Write to SPT2 */ - ADCx->SPT2 = temp1; - } - /* For Array 1 to 6 */ - if (Array < 7) { - /* Get RSQ3 value */ - temp1 = ADCx->RSQ3; - /* Calculate the mask to clear */ - temp2 = RSQ3_RSQ_SET << (5 * (Array - 1)); - /* Clear RSQ3 bits */ - temp1 &= ~temp2; - /* Calculate the mask to set */ - temp2 = (uint32_t)ADC_Channel << (5 * (Array - 1)); - /* Configure the RSQ3 bits */ - temp1 |= temp2; - /* Write to RSQ3 */ - ADCx->RSQ3 = temp1; - } - /* For Array 7 to 12 */ - else if (Array < 13) { - /* Get RSQ2 value */ - temp1 = ADCx->RSQ2; - /* Calculate the mask to clear */ - temp2 = RSQ2_RSQ_SET << (5 * (Array - 7)); - /* Clear the old RSQ2 bits */ - temp1 &= ~temp2; - /* Calculate the mask to set */ - temp2 = (uint32_t)ADC_Channel << (5 * (Array - 7)); - /* Set the RSQ2 bits */ - temp1 |= temp2; - /* Write to RSQ2 */ - ADCx->RSQ2 = temp1; - } - /* For Array 13 to 16 */ - else { - /* Get RSQ1 value */ - temp1 = ADCx->RSQ1; - /* Calculate the mask to clear */ - temp2 = RSQ1_RSQ_SET << (5 * (Array - 13)); - /* Clear the old RSQ1 bits */ - temp1 &= ~temp2; - /* Calculate the mask to set */ - temp2 = (uint32_t)ADC_Channel << (5 * (Array - 13)); - /* Set the RSQ1 bits */ - temp1 |= temp2; - /* Write to RSQ1 */ - ADCx->RSQ1 = temp1; - } -} - -/** - * @brief Enable or disable the ADCx external conversion. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADCx external trigger state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_ExternalTrigConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable external trigger conversion */ - ADCx->CTLR2 |= CTLR2_ETERC_SET; - } else { - /* Disable external trigger conversion */ - ADCx->CTLR2 &= ~CTLR2_ETERC_SET; - } -} - -/** - * @brief Return the ADCx regular channel conversion data. - * @param ADCx: the ADC interface where x can be 1..3. - * @retval conversion data. - */ -uint16_t ADC_GetConversionValue(ADC_TypeDef *ADCx) -{ - /* Return ADCx conversion data */ - return (uint16_t) ADCx->RDTR; -} - -/** - * @brief Return the last ADC0 and ADC1 conversion result data in dual mode. - * @retval The Data conversion value. - */ -uint32_t ADC_GetDualModeConversionValue(void) -{ - /* Return conversion value */ - return (*(__IO uint32_t *) RDTR_ADDRESS); -} -/** - * @brief Enable or disable ADCx automatic inserted conversion. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADCx auto inserted conversion state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_AutoInsertedConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable ADCx automatic inserted conversion */ - ADCx->CTLR1 |= CTLR1_ICA_SET; - } else { - /* Disable ADCx automatic inserted conversion */ - ADCx->CTLR1 &= ~CTLR1_ICA_SET; - } -} - -/** - * @brief Enable or disable the discontinuous mode for ADCx inserted group channel. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADCx discontinuous mode state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_InsertedDiscMode_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the inserted discontinuous mode of the selected ADC channel */ - ADCx->CTLR1 |= CTLR1_DISIC_SET; - } else { - /* Disable the inserted discontinuous mode of the selected ADC channel */ - ADCx->CTLR1 &= ~CTLR1_DISIC_SET; - } -} - -/** - * @brief Configure the ADCx inserted channels external trigger conversion. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_ExternalTrigInsertConv: ADC inserted conversion trigger. - * This parameter can be as follows: - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T1_TRGO: Timer1 TRIG event (used in ADC0, ADC1 and ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T1_CC4: Timer1 capture compare4 (used in ADC0, ADC1 and ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T2_TRGO: Timer2 TRIG event (used in ADC0 and ADC1) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T2_CC1: Timer2 capture compare1 (used in ADC0 and ADC1) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T3_CC4: Timer3 capture compare4 (used in ADC0 and ADC1) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T4_TRGO: Timer4 TRIG event (used in ADC0 and ADC1) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_EXT_IT15_T8_CC4: External interrupt line 15 or Timer8 - * capture compare4 (used in ADC0 and ADC1) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T4_CC3: Timer4 capture compare3 (used in ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T8_CC2: Timer8 capture compare2 (used in ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T8_CC4: Timer8 capture compare4 (used in ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T5_TRGO: Timer5 TRIG event (used in ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_T5_CC4: Timer5 capture compare4 (used in ADC2) - * @arg ADC_EXTERNAL_TRIG_INSERTCONV_NONE: Inserted conversion started by software (used in ADC0, ADC1 and ADC2) - * @retval None - */ -void ADC_ExternalTrigInsertedConv_Config(ADC_TypeDef *ADCx, uint32_t ADC_ExternalTrigInsertConv) -{ - uint32_t temp = 0; - /* Get CRLR2 value */ - temp = ADCx->CTLR2; - /* Clear inserted external event */ - temp &= CTLR2_ETSIC_RESET; - /* Configure inserted external event */ - temp |= ADC_ExternalTrigInsertConv; - /* Write to CTLR2 */ - ADCx->CTLR2 = temp; -} - -/** - * @brief Enable or disable the ADCx inserted channels conversion through - * external trigger - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADCx external trigger start of inserted conversion state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_ExternalTrigInsertedConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable external event */ - ADCx->CTLR2 |= CTLR2_ETEIC_SET; - } else { - /* Disable external event */ - ADCx->CTLR2 &= ~CTLR2_ETEIC_SET; - } -} - -/** - * @brief Enable or disable ADCx inserted channels conversion start. - * @param ADCx: the ADC interface where x can be 1..3. - * @param NewValue: ADC software start inserted conversion state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_SoftwareStartInsertedConv_Enable(ADC_TypeDef *ADCx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Start ADCx inserted conversion */ - ADCx->CTLR2 |= CTLR2_ETEIC_SWICST_SET; - } else { - /* Stop ADCx inserted conversion */ - ADCx->CTLR2 &= ~CTLR2_ETEIC_SWICST_SET; - } -} - -/** - * @brief Get ADC Software start inserted conversion State. - * @param ADCx: the ADC interface where x can be 1..3. - * @retval ADC software start inserted conversion state(SET or RESET). - */ -TypeState ADC_GetSoftwareStartInsertedConvCmdBitState(ADC_TypeDef *ADCx) -{ - /* Check SWICST bit */ - if ((ADCx->CTLR2 & CTLR2_SWICST_SET) != (uint32_t)RESET) { - /* Set SWICST bit */ - return SET; - } else { - /* Reset SWICST bit */ - return RESET; - } -} - -/** - * @brief Configure Array and sample time for the selected ADC inserted channel. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_Channel: the selected ADC channel. - * This parameter can be as follows: - * @arg ADC_CHANNEL_0: ADC Channel0 - * @arg ADC_CHANNEL_1: ADC Channel1 - * @arg ADC_CHANNEL_2: ADC Channel2 - * @arg ADC_CHANNEL_3: ADC Channel3 - * @arg ADC_CHANNEL_4: ADC Channel4 - * @arg ADC_CHANNEL_5: ADC Channel5 - * @arg ADC_CHANNEL_6: ADC Channel6 - * @arg ADC_CHANNEL_7: ADC Channel7 - * @arg ADC_CHANNEL_8: ADC Channel8 - * @arg ADC_CHANNEL_9: ADC Channel9 - * @arg ADC_CHANNEL_10: ADC Channel10 - * @arg ADC_CHANNEL_11: ADC Channel11 - * @arg ADC_CHANNEL_12: ADC Channel12 - * @arg ADC_CHANNEL_13: ADC Channel13 - * @arg ADC_CHANNEL_14: ADC Channel14 - * @arg ADC_CHANNEL_15: ADC Channel15 - * @arg ADC_CHANNEL_16: ADC Channel16 - * @arg ADC_CHANNEL_17: ADC Channel17 - * @param Array: The inserted group sequencer Array. This parameter must be between 1 and 4. - * @param ADC_SampleTime: The sample time of the selected channel. - * This parameter can be as follows: - * @arg ADC_SAMPLETIME_1POINT5: 1.5 cycles - * @arg ADC_SAMPLETIME_7POINT5: 7.5 cycles - * @arg ADC_SAMPLETIME_13POINT5: 13.5 cycles - * @arg ADC_SAMPLETIME_28POINT5: 28.5 cycles - * @arg ADC_SAMPLETIME_41POINT5: 41.5 cycles - * @arg ADC_SAMPLETIME_55POINT5: 55.5 cycles - * @arg ADC_SAMPLETIME_71POINT5: 71.5 cycles - * @arg ADC_SAMPLETIME_239POINT5: 239.5 cycles - * @retval None - */ -void ADC_InsertedChannel_Config(ADC_TypeDef *ADCx, uint8_t ADC_Channel, uint8_t Array, uint8_t ADC_SampleTime) -{ - uint32_t temp1 = 0, temp2 = 0, temp3 = 0; - - /* if ADC_Channel is between 10 to 17 */ - if (ADC_Channel > ADC_CHANNEL_9) { - /* Get SPT1 value */ - temp1 = ADCx->SPT1; - /* Calculate the sample time mask */ - temp2 = SPT1_SPT_SET << (3 * (ADC_Channel - 10)); - /* Clear sample time */ - temp1 &= ~temp2; - /* Calculate the sample time mask */ - temp2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); - /* Set sample time */ - temp1 |= temp2; - /* Write to SPT1 */ - ADCx->SPT1 = temp1; - } else { /* ADC_Channel is between 0 to 9 */ - /* Get SPT2 value */ - temp1 = ADCx->SPT2; - /* Calculate the sample time mask */ - temp2 = SPT2_SPT_SET << (3 * ADC_Channel); - /* Clear sample time */ - temp1 &= ~temp2; - /* Calculate the sample time mask */ - temp2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); - /* Set sample time */ - temp1 |= temp2; - /* Write to SPT2 */ - ADCx->SPT2 = temp1; - } - /* Array configuration */ - /* Get ISQ value */ - temp1 = ADCx->ISQ; - /* Get IL value: Number = IL+1 */ - temp3 = (temp1 & ISQ_IL_SET) >> 20; - /* Calculate the ISQ mask : ((Array-1)+(4-IL-1)) */ - temp2 = ISQ_ISQ_SET << (5 * (uint8_t)((Array + 3) - (temp3 + 1))); - /* Clear ISQx bits */ - temp1 &= ~temp2; - /* Calculate the ISQ mask: ((Array-1)+(4-IL-1)) */ - temp2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Array + 3) - (temp3 + 1))); - /* Set ISQx bits */ - temp1 |= temp2; - /* Write to ISQ */ - ADCx->ISQ = temp1; -} - -/** - * @brief Configure the sequencer length of inserted channels - * @param ADCx: the ADC interface where x can be 1..3. - * @param Length: The sequencer length. - * This parameter must be a number between 1 to 4. - * @retval None - */ -void ADC_InsertedSequencerLength_Config(ADC_TypeDef *ADCx, uint8_t Length) -{ - uint32_t temp1 = 0; - uint32_t temp2 = 0; - /* Get ISQ value */ - temp1 = ADCx->ISQ; - /* Clear IL bits */ - temp1 &= ~ISQ_IL_SET; - /* Set IL bits */ - temp2 = Length - 1; - temp1 |= temp2 << 20; - /* Write to ISQ */ - ADCx->ISQ = temp1; -} - -/** - * @brief Set the offset of the inserted channels conversion value. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_InsertedChannel: one of the four inserted channels to set its offset. - * This parameter can be one of the following values: - * @arg ADC_INSERTEDCHANNEL_1: Inserted Channel1 - * @arg ADC_INSERTEDCHANNEL_2: Inserted Channel2 - * @arg ADC_INSERTEDCHANNEL_3: Inserted Channel3 - * @arg ADC_INSERTEDCHANNEL_4: Inserted Channel4 - * @param Offset: the offset value of the selected ADC inserted channel - * This parameter must be a 12bit value. - * @retval None - */ -void ADC_SetInsertedOffset(ADC_TypeDef *ADCx, uint8_t ADC_InsertedChannel, uint16_t Offset) -{ - __IO uint32_t temp = 0; - temp = (uint32_t)ADCx; - temp += ADC_InsertedChannel; - - /* Set the offset of the selected inserted channel */ - *(__IO uint32_t *) temp = (uint32_t)Offset; -} - -/** - * @brief Get the ADC inserted channel conversion result - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_InsertedChannel: ADC inserted channel. - * This parameter can be one of the following values: - * @arg ADC_INSERTEDCHANNEL_1: Inserted Channel1 - * @arg ADC_INSERTEDCHANNEL_2: Inserted Channel2 - * @arg ADC_INSERTEDCHANNEL_3: Inserted Channel3 - * @arg ADC_INSERTEDCHANNEL_4: Inserted Channel4 - * @retval The conversion value. - */ -uint16_t ADC_GetInsertedConversionValue(ADC_TypeDef *ADCx, uint8_t ADC_InsertedChannel) -{ - __IO uint32_t temp = 0; - temp = (uint32_t)ADCx; - temp += ADC_InsertedChannel + IDTR_OFFSET; - - /* Return the result of the selected inserted channel conversion */ - return (uint16_t)(*(__IO uint32_t *) temp); -} - -/** - * @brief Enable or disable the analog watchdog. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_AnalogWatchdog: the ADC analog watchdog configuration. - * This parameter can be one of the following values: - * @arg ADC_ANALOGWATCHDOG_SINGLEREGENABLE: single regular channel - * @arg ADC_ANALOGWATCHDOG_SINGLEINSERTENABLE: single inserted channel - * @arg ADC_ANALOGWATCHDOG_SINGLEREGORINSERTENABLE: single regular or inserted channel - * @arg ADC_ANALOGWATCHDOG_ALLREGENABLE: all regular channel - * @arg ADC_ANALOGWATCHDOG_ALLINSERTENABLE: all inserted channel - * @arg ADC_ANALOGWATCHDOG_ALLREGALLINSERTENABLE: all regular and inserted channels - * @arg ADC_ANALOGWATCHDOG_NONE: No channel - * @retval None - */ -void ADC_AnalogWatchdog_Enable(ADC_TypeDef *ADCx, uint32_t ADC_AnalogWatchdog) -{ - uint32_t temp = 0; - /* Get CTLR1 value */ - temp = ADCx->CTLR1; - /* Clear AWDEN, AWDENJ and AWDSGL bits */ - temp &= CTLR1_AWDMODE_RESET; - /* Set the analog watchdog mode */ - temp |= ADC_AnalogWatchdog; - /* Write to CTLR1 */ - ADCx->CTLR1 = temp; -} - -/** - * @brief Configure the high and low thresholds of the analog watchdog. - * @param ADCx: the ADC interface where x can be 1..3. - * @param HighThreshold: the ADC analog watchdog High threshold value. - * This parameter must be a 12bit value. - * @param LowThreshold: the ADC analog watchdog Low threshold value. - * This parameter must be a 12bit value. - * @retval None - */ -void ADC_AnalogWatchdogThresholds_Config(ADC_TypeDef *ADCx, uint16_t HighThreshold, - uint16_t LowThreshold) -{ - /* Set the ADCx high threshold */ - ADCx->AWHT = HighThreshold; - /* Set the ADCx low threshold */ - ADCx->AWLT = LowThreshold; -} - -/** - * @brief Configure the analog watchdog on single channel mode. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_Channel: ADC channel. - * This parameter can be as follows: - * @arg ADC_CHANNEL_0: ADC Channel0 - * @arg ADC_CHANNEL_1: ADC Channel1 - * @arg ADC_CHANNEL_2: ADC Channel2 - * @arg ADC_CHANNEL_3: ADC Channel3 - * @arg ADC_CHANNEL_4: ADC Channel4 - * @arg ADC_CHANNEL_5: ADC Channel5 - * @arg ADC_CHANNEL_6: ADC Channel6 - * @arg ADC_CHANNEL_7: ADC Channel7 - * @arg ADC_CHANNEL_8: ADC Channel8 - * @arg ADC_CHANNEL_9: ADC Channel9 - * @arg ADC_CHANNEL_10: ADC Channel10 - * @arg ADC_CHANNEL_11: ADC Channel11 - * @arg ADC_CHANNEL_12: ADC Channel12 - * @arg ADC_CHANNEL_13: ADC Channel13 - * @arg ADC_CHANNEL_14: ADC Channel14 - * @arg ADC_CHANNEL_15: ADC Channel15 - * @arg ADC_CHANNEL_16: ADC Channel16 - * @arg ADC_CHANNEL_17: ADC Channel17 - * @retval None - */ -void ADC_AnalogWatchdogSingleChannel_Config(ADC_TypeDef *ADCx, uint8_t ADC_Channel) -{ - uint32_t temp = 0; - /* Get CTLR1 value */ - temp = ADCx->CTLR1; - /* Clear AWCS */ - temp &= CTLR1_AWCS_RESET; - /* Set the Analog watchdog channel */ - temp |= ADC_Channel; - /* Write to CTLR1 */ - ADCx->CTLR1 = temp; -} - -/** - * @brief Enable or disable the temperature sensor and Vrefint channel. - * @param NewValue: the state of the temperature sensor. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ADC_TempSensorVrefint_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the temperature sensor and Vrefint channel*/ - ADC0->CTLR2 |= CTLR2_TSVREN_SET; - } else { - /* Disable the temperature sensor and Vrefint channel*/ - ADC0->CTLR2 &= ~CTLR2_TSVREN_SET; - } -} - -/** - * @brief Check the ADC flag. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_FLAG: the flag to check. - * This parameter can be as follows: - * @arg ADC_FLAG_AWE: The flag of the analog watchdog - * @arg ADC_FLAG_EOC: The flag of the end of conversion - * @arg ADC_FLAG_EOIC: The flag of the end of inserted group conversion - * @arg ADC_FLAG_STIC: The flag of the start of inserted group conversion - * @arg ADC_FLAG_STRC: The flag of the start of regular group conversion - * @retval ADC_FLAG state(SET or RESET). - */ -TypeState ADC_GetBitState(ADC_TypeDef *ADCx, uint8_t ADC_FLAG) -{ - /* Check the specified ADC flag state */ - if ((ADCx->STR & ADC_FLAG) != (uint8_t)RESET) { - /* ADC_FLAG is set */ - return SET; - } else { - /* ADC_FLAG is reset */ - return RESET; - } -} - -/** - * @brief Clear the ADCx's pending flags. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_FLAG: the flag to clear. - * This parameter can be any combination of the following values: - * @arg ADC_FLAG_AWE: The flag of the analog watchdog - * @arg ADC_FLAG_EOC: The flag of the end of conversion - * @arg ADC_FLAG_EOIC: The flag of the end of inserted group conversion - * @arg ADC_FLAG_STIC: The flag of the start of inserted group conversion - * @arg ADC_FLAG_STRC: The flag of the start of regular group conversion - * @retval None - */ -void ADC_ClearBitState(ADC_TypeDef *ADCx, uint8_t ADC_FLAG) -{ - /* Clear the selected ADC flags */ - ADCx->STR = ~(uint32_t)ADC_FLAG; -} - -/** - * @brief Check the specified ADC interrupt. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_INT: ADC interrupt source. - * This parameter can be one of the following values: - * @arg ADC_INT_EOC: The interrupt mask of the end of conversion - * @arg ADC_INT_AWE: The interrupt mask of the analog watchdog - * @arg ADC_INT_EOIC: The interrupt mask of the end of inserted conversion - * @retval The new value of ADC_INT (SET or RESET). - */ -TypeState ADC_GetIntState(ADC_TypeDef *ADCx, uint16_t ADC_INT) -{ - uint32_t temp_it = 0, temp_enable = 0; - /* Get the ADC interrupt mask index */ - temp_it = ADC_INT >> 8; - /* Get the ADC_INT enable bit state */ - temp_enable = (ADCx->CTLR1 & (uint8_t)ADC_INT) ; - /* Check the state of the specified ADC interrupt */ - if (((ADCx->STR & temp_it) != (uint32_t)RESET) && temp_enable) { - /* ADC_INT is set */ - return SET; - } else { - /* ADC_INT is reset */ - return RESET; - } -} - -/** - * @brief Clear the ADCx's interrupt pending bits. - * @param ADCx: the ADC interface where x can be 1..3. - * @param ADC_INT: the ADC interrupt pending bit. - * This parameter can be any combination of the following values: - * @arg ADC_INT_EOC: The interrupt mask of the end of conversion - * @arg ADC_INT_AWE: The interrupt mask of the analog watchdog - * @arg ADC_INT_EOIC: The interrupt mask of the end of inserted conversion - * @retval None - */ -void ADC_ClearIntBitState(ADC_TypeDef *ADCx, uint16_t ADC_INT) -{ - uint8_t temp_it = 0; - /* Get the ADC interrupt mask index */ - temp_it = (uint8_t)(ADC_INT >> 8); - /* Clear ADCx interrupt pending bits */ - ADCx->STR = ~(uint32_t)temp_it; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_bkp.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_bkp.c deleted file mode 100644 index 28f219825b..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_bkp.c +++ /dev/null @@ -1,250 +0,0 @@ -/** - ****************************************************************************** - * @brief BKP functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_bkp.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup BKP - * @brief BKP driver modules - * @{ - */ - -/** @defgroup BKP_Private_Defines - * @{ - */ -/* RTCOUTPUT bit is masked in BKP_RCCR register */ -#define RTCOUTPUT_MASK ((uint16_t)0xFC7F) - -/** - * @} - */ - - -/** @defgroup BKP_Private_Functions - * @{ - */ - -/** - * @brief Reset the BKP peripheral registers. - * @param None - * @retval None - */ -void BKP_DeInit(void) -{ - RCC_BackupReset_Enable(ENABLE); - RCC_BackupReset_Enable(DISABLE); -} - -/** - * @brief Write user data to the BKP_DRx register. - * @param BKP_DR: the Backup Data Register. - * This parameter can be BKP_DRx where x can be (1..42) - * @param Data: data to write - * @retval None - */ -void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) -{ - __IO uint32_t temp = 0; - - temp = (uint32_t)BKP_BASE; - temp += BKP_DR; - - /* Store the write data */ - *(__IO uint16_t *) temp = Data; -} - -/** - * @brief Read data from the BKP_DRx register. - * @param BKP_DR: The Backup Data Register. - * This parameter can be BKP_DRx where x can be (1..42) - * @retval The content of the BKP_DRx register. - */ -uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR) -{ - __IO uint32_t temp = 0; - - temp = (uint32_t)BKP_BASE; - temp += BKP_DR; - - /* Return the BKP_DRx register value */ - return (*(__IO uint16_t *) temp); -} - -/** - * @brief Configure the RTC output on the Tamper pin. - * @param BKP_RTCOUTPUT: the RTC output. - * This parameter can be one of the following values: - * @arg BKP_RTCOUTPUT_NULL: no RTC output on the TAMPER pin. - * @arg BKP_RTCOUTPUT_CLKCAL: output the RTC clock with frequency - * divided by 64 on the TAMPER pin. - * @arg BKP_RTCOUTPUT_ALARM: output the RTC Alarm pulse signal on - * the TAMPER pin. - * @arg BKP_RTCOUTPUT_SECOND: output the RTC Second pulse signal on - * the TAMPER pin. - * @retval None - */ -void BKP_RTCOutputConfig(uint16_t BKP_RTCOUTPUT) -{ - uint16_t temp = 0; - - temp = BKP->RCCR; - - /* Clear RCCOE, ROE and ROS bits */ - temp &= RTCOUTPUT_MASK; - - /* Set RCCOE, ROE and ROS bits according to BKP_RTCOUTPUT value */ - temp |= BKP_RTCOUTPUT; - - /* Store the new value */ - BKP->RCCR = temp; -} - -/** - * @brief Set RTC Clock Calibration value. - * @param CalibrationValue: the RTC Clock Calibration value. - * This parameter must be a number between 0 and 0x7F. - * @retval None - */ -void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue) -{ - uint16_t temp = 0; - - temp = BKP->RCCR; - - /* Clear RCCV[6:0] bits */ - temp &= ~BKP_RCCR_RCCV; - - /* Set CAL[6:0] bits according to CalibrationValue */ - temp |= CalibrationValue; - - /* Store the new value */ - BKP->RCCR = temp; -} - -/** - * @brief Configure the TAMPER pin active level. - * @param BKP_TPAL: the TAMPER pin active level. - * This parameter can be one of the following values: - * @arg BKP_TPAL_HIGH: TAMPER pin active on high level - * @arg BKP_TPAL_LOW: TAMPER pin active on low level - * @param NewValue: New value of the TAMPER pin state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void BKP_TamperPinConfig(uint16_t BKP_TPAL, TypeState NewValue) -{ - uint16_t temp = 0; - - temp = BKP->TPCR; - - /* Clear TPE bit */ - temp &= ~((uint16_t)BKP_TPCR_TPE); - - /* Configure TPAL bit according to BKP_TPAL value */ - temp |= BKP_TPAL; - - /* Store the new value */ - BKP->TPCR = temp; - - /* Enable the TAMPER pin */ - if (NewValue != DISABLE) { - /* The TAMPER pin is dedicated for the Backup Reset function */ - BKP->TPCR |= BKP_TPCR_TPE; - } else { - /* The TAMPER pin is free for GPIO functions */ - BKP->TPCR &= ~((uint16_t)BKP_TPCR_TPE); - } -} - -/** - * @brief Enable or disable the Tamper Interrupt. - * @param NewValue: New value of the Tamper Interrupt. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void BKP_TamperINT_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the tamper interrupt */ - BKP->TIER |= BKP_TIER_TIE; - } else { - /* Disable the tamper interrupt */ - BKP->TIER &= ~BKP_TIER_TIE; - } -} - -/** - * @brief Get the bit flag of Tamper Event. - * @param None - * @retval The new value of Tamper Event flag (SET or RESET). - */ -TypeState BKP_GetBitState(void) -{ - /* Check and get the Tamper Event flag */ - if ((BKP->TIER & BKP_TIER_TEF) != (uint16_t)RESET) { - /* Tamper Event occured */ - return SET; - } else { - /* No Tamper Event occured */ - return RESET; - } -} - -/** - * @brief Clear the bit flag of Tamper Event. - * @param None - * @retval None - */ -void BKP_ClearBitState(void) -{ - /* Set the TER bit to clear Tamper Event flag */ - BKP->TIER |= BKP_TIER_TER; -} - -/** - * @brief Get the interrupt bit flag of Tamper Interrupt. - * @param None - * @retval The new value of the Tamper Interrupt flag (SET or RESET). - */ -TypeState BKP_GetIntBitState(void) -{ - /* Check and get the Tamper Interrupt flag */ - if ((BKP->TIER & BKP_TIER_TIF) != (uint16_t)RESET) { - /* Tamper Interrupt occured */ - return SET; - } else { - /* No Tamper Interrupt occured */ - return RESET; - } -} - -/** - * @brief Clear the interrupt bit flag of Tamper Interrupt. - * @param None - * @retval None - */ -void BKP_ClearIntBitState(void) -{ - /* Set the TIR bit to clear Tamper Interrupt flag */ - BKP->TIER |= BKP_TIER_TIR; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_can.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_can.c deleted file mode 100644 index 604dca5caa..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_can.c +++ /dev/null @@ -1,1120 +0,0 @@ -/** - ****************************************************************************** - * @brief CAN functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_can.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup CAN - * @brief CAN driver modules - * @{ - */ - -/** @defgroup CAN_Private_Defines - * @{ - */ - - -/* CAN Mailbox Transmit Request */ -#define CAN_TMIR_TE ((uint32_t)0x00000001) - -/* CAN Filter Master Register bits */ -#define FMR_FINIT ((uint32_t)0x00000001) - -/* Time out for IWS bit */ -#define IWS_TIMEOUT ((uint32_t)0x0000FFFF) -/* Time out for SWS bit */ -#define SWS_TIMEOUT ((uint32_t)0x0000FFFF) - -/* CAN TMIR_StdId masks */ -#define CAN_TMIR_StdId_Mask ((uint32_t)0x000007FF) - -/* CAN TMIR_ExtId masks */ -#define CAN_TMIR_ExtId_Mask ((uint32_t)0x1FFFFFFF) - -/* CAN TMIR_ExtId masks */ -#define CAN_FLAG_Mask ((uint32_t)0x000FFFFF) - -/* Flags in TSTR register */ -#define CAN_FLAGS_TSTR ((uint32_t)0x08000000) - -/* Flags in RFR1 register */ -#define CAN_FLAGS_RFR1 ((uint32_t)0x04000000) - -/* Flags in RFR0register */ -#define CAN_FLAGS_RFR0 ((uint32_t)0x02000000) - -/* Flags in STR register */ -#define CAN_FLAGS_STR ((uint32_t)0x01000000) - -/* Flags in ER register */ -#define CAN_FLAGS_ER ((uint32_t)0x00F00000) - -/* Mailboxes definition */ -#define CAN_TXMAILBOX_0 ((uint8_t)0x00) -#define CAN_TXMAILBOX_1 ((uint8_t)0x01) -#define CAN_TXMAILBOX_2 ((uint8_t)0x02) - -/* CAN Master Control Register bit */ -#define MCR_DBF ((uint32_t)0x00010000) - - -#define CAN_MODE_MASK ((uint32_t)0x00000003) -/** - * @} - */ - - -/** @defgroup CAN_Private_Functions - * @{ - */ - -/** - * @brief Deinitialize the CAN peripheral registers. - * @param CANx: where x:[1,2] to select the CAN peripheral. - * @retval None. - */ -void CAN_DeInit(CAN_TypeDef *CANx) -{ - if (CANx == CAN1) { - /* Force CAN1 reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_CAN1, ENABLE); - /* Release CAN1 from reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_CAN1, DISABLE); - } else { - /* Force CAN2 reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_CAN2, ENABLE); - /* Release CAN2 from reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_CAN2, DISABLE); - } -} - -/** - * @brief Initialize the CAN peripheral according to the CAN_InitParaStruct. - * @param CANx:where x:[1,2] - * @param CAN_InitParaStruct: contain the configuration information for the CAN peripheral. - * @retval It will be returned the status of CAN_INITSTATE_FAILED or CAN_INITSTATE_SUCCESS. - */ -uint8_t CAN_Init(CAN_TypeDef *CANx, CAN_InitPara *CAN_InitParaStruct) -{ - uint32_t wait_ack = 0x00000000; - - /* Out of sleep mode */ - CANx->CTLR &= (~(uint32_t)CAN_CTLR_SWM); - - /* Enable initial working */ - CANx->CTLR |= CAN_CTLR_IWM ; - - /* Wait the acknowledge */ - while (((CANx->STR & CAN_STR_IWS) != CAN_STR_IWS) && (wait_ack != IWS_TIMEOUT)) { - wait_ack++; - } - - /* Check whether initial working is success */ - if ((CANx->STR & CAN_STR_IWS) != CAN_STR_IWS) { - return CAN_INITSTATE_FAILED; - } else { - /* Set the time triggered communication mode */ - if (CAN_InitParaStruct->CAN_TTC == ENABLE) { - CANx->CTLR |= CAN_CTLR_TTC; - } else { - CANx->CTLR &= ~(uint32_t)CAN_CTLR_TTC; - } - - /* Set the automatic bus-off management */ - if (CAN_InitParaStruct->CAN_ABOR == ENABLE) { - CANx->CTLR |= CAN_CTLR_ABOR; - } else { - CANx->CTLR &= ~(uint32_t)CAN_CTLR_ABOR; - } - - /* Set the automatic wake-up mode */ - if (CAN_InitParaStruct->CAN_AWK == ENABLE) { - CANx->CTLR |= CAN_CTLR_AWK; - } else { - CANx->CTLR &= ~(uint32_t)CAN_CTLR_AWK; - } - - /* Set the automatic retransmission mode */ - if (CAN_InitParaStruct->CAN_ARD == ENABLE) { - CANx->CTLR |= CAN_CTLR_ARD; - } else { - CANx->CTLR &= ~(uint32_t)CAN_CTLR_ARD; - } - - /* Set receive FIFO overwrite mode */ - if (CAN_InitParaStruct->CAN_RFOD == ENABLE) { - CANx->CTLR |= CAN_CTLR_RFOD; - } else { - CANx->CTLR &= ~(uint32_t)CAN_CTLR_RFOD; - } - - /* Set the Transmit FIFO order */ - if (CAN_InitParaStruct->CAN_TFO == ENABLE) { - CANx->CTLR |= CAN_CTLR_TFO; - } else { - CANx->CTLR &= ~(uint32_t)CAN_CTLR_TFO; - } - - /* Set the bit timing register */ - CANx->BTR = (uint32_t)((uint32_t)CAN_InitParaStruct->CAN_Mode << 30) | \ - ((uint32_t)CAN_InitParaStruct->CAN_SJW << 24) | \ - ((uint32_t)CAN_InitParaStruct->CAN_BS1 << 16) | \ - ((uint32_t)CAN_InitParaStruct->CAN_BS2 << 20) | \ - ((uint32_t)CAN_InitParaStruct->CAN_Prescaler - 1); - - /* leave initialisation */ - CANx->CTLR &= ~(uint32_t)CAN_CTLR_IWM; - - /* Wait the acknowledge */ - wait_ack = 0; - - while (((CANx->STR & CAN_STR_IWS) == CAN_STR_IWS) && (wait_ack != IWS_TIMEOUT)) { - wait_ack++; - } - - /* Check whether qiut initial working mode */ - if ((CANx->STR & CAN_STR_IWS) == CAN_STR_IWS) { - return CAN_INITSTATE_FAILED; - } else { - return CAN_INITSTATE_SUCCESS; - } - } - -} - -/** - * @brief Initialize the CAN peripheral according to the CAN_FilterInitStruct. - * @param CAN_FilterInitParaStruct:contain the information for the CAN peripheral. - * @retval None. - */ -void CAN_FilterInit(CAN_FilterInitPara *CAN_FilterInitParaStruct) -{ - uint32_t filter_number = 0; - - filter_number = ((uint32_t)1) << CAN_FilterInitParaStruct->CAN_FilterNumber; - - /* Set filter lock disable */ - CAN1->FCTLR |= CAN_FCTLR_FLD; - - /* Disable Filter */ - CAN1->FWR &= ~(uint32_t)filter_number; - - /* Filter Scale */ - if (CAN_FilterInitParaStruct->CAN_FilterScale == CAN_FILTERSCALE_16BIT) { - /* Set the filter 16-bit scale*/ - CAN1->FSR &= ~(uint32_t)filter_number; - - /* First 16-bit list and First 16-bit mask */ - /* Or First 16-bit list and Second 16-bit list */ - CAN1->FilterRegister[CAN_FilterInitParaStruct->CAN_FilterNumber].FD0R = - ((0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterMaskListLow) << 16) | - (0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterListLow); - - /* Second 16-bit identifier and Second 16-bit mask */ - /* Or Third 16-bit identifier and Fourth 16-bit identifier */ - CAN1->FilterRegister[CAN_FilterInitParaStruct->CAN_FilterNumber].FD1R = - ((0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterMaskListHigh) << 16) | - (0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterListHigh); - } - - if (CAN_FilterInitParaStruct->CAN_FilterScale == CAN_FILTERSCALE_32BIT) { - /* 32-bit scale for the filter */ - CAN1->FSR |= filter_number; - /* 32-bit identifier or First 32-bit identifier */ - CAN1->FilterRegister[CAN_FilterInitParaStruct->CAN_FilterNumber].FD0R = - ((0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterListHigh) << 16) | - (0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterListLow); - /* 32-bit mask or Second 32-bit identifier */ - CAN1->FilterRegister[CAN_FilterInitParaStruct->CAN_FilterNumber].FD1R = - ((0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterMaskListHigh) << 16) | - (0x0000FFFF & (uint32_t)CAN_FilterInitParaStruct->CAN_FilterMaskListLow); - } - - /* Filter Mode */ - if (CAN_FilterInitParaStruct->CAN_FilterMode == CAN_FILTERMODE_MASK) { - /*Filter with Mask mode*/ - CAN1->FMR &= ~(uint32_t)filter_number; - } else { /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FILTERMODE_LIST */ - /*Filter with List mode*/ - CAN1->FMR |= (uint32_t)filter_number; - } - - /* Filter associated with FIFO */ - if (CAN_FilterInitParaStruct->CAN_FilterFIFOAssociation == CAN_FILTER_FIFO0) { - /* Filter associated with FIFO 0 */ - CAN1->FAFR &= ~(uint32_t)filter_number; - } - - if (CAN_FilterInitParaStruct->CAN_FilterFIFOAssociation == CAN_FILTER_FIFO1) { - /* Filter associated with FIFO 1 */ - CAN1->FAFR |= (uint32_t)filter_number; - } - - /* Filter working */ - if (CAN_FilterInitParaStruct->CAN_FilterWork == ENABLE) { - CAN1->FWR |= filter_number; - } - - /* Exit the initialisation mode for the filter */ - CAN1->FCTLR &= ~CAN_FCTLR_FLD; -} - -/** - * @brief Configure each CAN_InitParaStruct member with default value. - * @param CAN_InitParaStruct: pointer to a CAN_InitPara structure to initialize. - * @retval None. - */ -void CAN_StructInit(CAN_InitPara *CAN_InitParaStruct) -{ - /* Set the time triggered communication mode */ - CAN_InitParaStruct->CAN_TTC = DISABLE; - - /* Set the automatic bus-off recovery */ - CAN_InitParaStruct->CAN_ABOR = DISABLE; - - /* Set the automatic wake up mode */ - CAN_InitParaStruct->CAN_AWK = DISABLE; - - /* Set the automatic retransmission disable */ - CAN_InitParaStruct->CAN_ARD = DISABLE; - - /* Set the receive FIFO overwrite mode */ - CAN_InitParaStruct->CAN_RFOD = DISABLE; - - /* Set the transmit FIFO order */ - CAN_InitParaStruct->CAN_TFO = DISABLE; - - /* Set the CAN_Mode member */ - CAN_InitParaStruct->CAN_Mode = CAN_MODE_NORMAL; - - /* Set the CAN_SJW member */ - CAN_InitParaStruct->CAN_SJW = CAN_SJW_1TQ; - - /* Set the CAN_BS1 member */ - CAN_InitParaStruct->CAN_BS1 = CAN_BS1_4TQ; - - /* Set the CAN_BS2 member */ - CAN_InitParaStruct->CAN_BS2 = CAN_BS2_3TQ; - - /* Set the CAN_Prescaler member */ - CAN_InitParaStruct->CAN_Prescaler = 1; -} - -/** - * @brief Set header bank of CAN2 filter. - * @param CAN2_HeaderBankNumber: Select header bank of CAN2 filter.It can be 1 to 27. - * @retval None. - */ -void CAN_HeaderBank(uint8_t CAN_HeaderBankNumber) -{ - /* Set filter lock disable */ - CAN1->FCTLR |= CAN_FCTLR_FLD; - - /* Select filter start number for slave CAN */ - CAN1->FCTLR &= (uint32_t)0xFFFFC0F1 ; - CAN1->FCTLR |= (uint32_t)(CAN_HeaderBankNumber) << 8; - - /* Filter out the initialization mode */ - CAN1->FCTLR |= ~CAN_FCTLR_FLD; -} - -/** - * @brief Enable or disable the Debug Freeze for CAN. - * @param CANx: where x :[1,2] for selecting the CAN peripheral. - * @param NewValue: new state of the CAN peripheral. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void CAN_DebugFreeze(CAN_TypeDef *CANx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - CANx->CTLR |= CAN_CTLR_DFZ; - } else { - CANx->CTLR &= ~CAN_CTLR_DFZ; - } -} - - -/** - * @brief Enable or disabe the CAN Time Triggered communication mode. - * @param CANx:where x :[1,2] for selecting the CAN peripheral. - * @param NewValue : Mode new state , This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void CAN_TimeTrigComMode_Enable(CAN_TypeDef *CANx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the TTC mode */ - CANx->CTLR |= CAN_CTLR_TTC; - - /* Set TSEbits */ - CANx->TxMailBox[0].TMPR |= ((uint32_t)CAN_TMPR0_TSE); - CANx->TxMailBox[1].TMPR |= ((uint32_t)CAN_TMPR1_TSE); - CANx->TxMailBox[2].TMPR |= ((uint32_t)CAN_TMPR2_TSE); - } else { - /* Disable the TTC mode */ - CANx->CTLR &= (uint32_t)(~(uint32_t)CAN_CTLR_TTC); - - /* Reset TSE bits */ - CANx->TxMailBox[0].TMPR &= ((uint32_t)~CAN_TMPR0_TSE); - CANx->TxMailBox[1].TMPR &= ((uint32_t)~CAN_TMPR1_TSE); - CANx->TxMailBox[2].TMPR &= ((uint32_t)~CAN_TMPR2_TSE); - } -} -/** - * @brief Initiate to transmit a message. - * @param CANx: where x:[1,2]to to select the CAN peripheral. - * @param TxMessage: contain CAN Id, CAN DLC and CAN data for the structure. - * @retval The number of the mailbox that is used for transmission - * or CAN_TxState_NoMailBox if there is no empty mailbox. - */ -uint8_t CAN_Transmit(CAN_TypeDef *CANx, CanTxMessage *TxMessage) -{ - uint8_t transmit_mailbox_number = 0; - - /* Select one empty transmit mailbox */ - if ((CANx->TSTR & CAN_TSTR_TME0) == CAN_TSTR_TME0) { - transmit_mailbox_number = 0; - } else if ((CANx->TSTR & CAN_TSTR_TME1) == CAN_TSTR_TME1) { - transmit_mailbox_number = 1; - } else if ((CANx->TSTR & CAN_TSTR_TME2) == CAN_TSTR_TME2) { - transmit_mailbox_number = 2; - } else { - transmit_mailbox_number = CAN_TXSTATE_NOMAILBOX; - } - - if (transmit_mailbox_number != CAN_TXSTATE_NOMAILBOX) { - /* Set up the Id */ - CANx->TxMailBox[transmit_mailbox_number].TMIR &= CAN_TMIR_TE; - if (TxMessage->FF == CAN_FF_STANDARD) { - CANx->TxMailBox[transmit_mailbox_number].TMIR |= ((TxMessage->StdId << 21) | \ - TxMessage->FT); - } else { - CANx->TxMailBox[transmit_mailbox_number].TMIR |= ((TxMessage->ExtId << 3) | \ - TxMessage->FF | \ - TxMessage->FT); - } - - /* Set up the DLC */ - TxMessage->DLC &= ((uint8_t)CAN_TMPR0_DLC); - CANx->TxMailBox[transmit_mailbox_number].TMPR &= ((uint32_t)~CAN_TMPR0_DLC); - CANx->TxMailBox[transmit_mailbox_number].TMPR |= TxMessage->DLC; - - /* Set up the data field */ - CANx->TxMailBox[transmit_mailbox_number].TMD0R = (((uint32_t)TxMessage->Data[3] << 24) | - ((uint32_t)TxMessage->Data[2] << 16) | - ((uint32_t)TxMessage->Data[1] << 8) | - ((uint32_t)TxMessage->Data[0])); - CANx->TxMailBox[transmit_mailbox_number].TMD1R = (((uint32_t)TxMessage->Data[7] << 24) | - ((uint32_t)TxMessage->Data[6] << 16) | - ((uint32_t)TxMessage->Data[5] << 8) | - ((uint32_t)TxMessage->Data[4])); - /* Request transmission */ - CANx->TxMailBox[transmit_mailbox_number].TMIR |= CAN_TMIR0_TE; - } - return transmit_mailbox_number; -} - -/** - * @brief Check the state of message transmission. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param TransmitMailbox: the number of the used transmission mailbox. - * @retval Return CAN_TXSTATE_OK or CAN_TXSTATE_FAILED. - */ -uint8_t CAN_TransmitState(CAN_TypeDef *CANx, uint8_t TransmitMailbox) -{ - uint32_t state = 0; - - switch (TransmitMailbox) { - case (CAN_TXMAILBOX_0): - state = CANx->TSTR & (CAN_TSTR_MTF0 | CAN_TSTR_MTFNE0 | CAN_TSTR_TME0); - break; - case (CAN_TXMAILBOX_1): - state = CANx->TSTR & (CAN_TSTR_MTF1 | CAN_TSTR_MTFNE1 | CAN_TSTR_TME1); - break; - case (CAN_TXMAILBOX_2): - state = CANx->TSTR & (CAN_TSTR_MTF2 | CAN_TSTR_MTFNE2 | CAN_TSTR_TME2); - break; - default: - state = CAN_TXSTATE_FAILED; - break; - } - switch (state) { - /* transmit pending */ - case (0x0): - state = CAN_TXSTATE_PENDING; - break; - /* transmit failed */ - case (CAN_TSTR_MTF0 | CAN_TSTR_TME0): - state = CAN_TXSTATE_FAILED; - break; - case (CAN_TSTR_MTF1 | CAN_TSTR_TME1): - state = CAN_TXSTATE_FAILED; - break; - case (CAN_TSTR_MTF2 | CAN_TSTR_TME2): - state = CAN_TXSTATE_FAILED; - break; - /* transmit succeeded */ - case (CAN_TSTR_MTF0 | CAN_TSTR_MTFNE0 | CAN_TSTR_TME0): - state = CAN_TXSTATE_OK; - break; - case (CAN_TSTR_MTF1 | CAN_TSTR_MTFNE1 | CAN_TSTR_TME1): - state = CAN_TXSTATE_OK; - break; - case (CAN_TSTR_MTF2 | CAN_TSTR_MTFNE2 | CAN_TSTR_TME2): - state = CAN_TXSTATE_OK; - break; - default: - state = CAN_TXSTATE_FAILED; - break; - } - return (uint8_t) state; -} - -/** - * @brief Stop a transmit mission. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param Mailbox: Mailbox number. - * @retval None. - */ -void CAN_StopTransmit(CAN_TypeDef *CANx, uint8_t Mailbox) -{ - /* Stop transmission */ - switch (Mailbox) { - case (CAN_TXMAILBOX_0): - CANx->TSTR |= CAN_TSTR_MST0; - break; - case (CAN_TXMAILBOX_1): - CANx->TSTR |= CAN_TSTR_MST1; - break; - case (CAN_TXMAILBOX_2): - CANx->TSTR |= CAN_TSTR_MST2; - break; - default: - break; - } -} - - -/** - * @brief Receive a message. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1. - * @param RxMessage: a structure receive message which contains - * CAN Id, CAN DLC, CAN datas and FI number. - * @retval None. - */ -void CAN_Receive(CAN_TypeDef *CANx, uint8_t FIFONumber, CanRxMessage *RxMessage) -{ - /* Get the frame identifier */ - RxMessage->FF = (uint8_t)0x04 & CANx->FIFOMailBox[FIFONumber].RFMIR; - if (RxMessage->FF == CAN_FF_STANDARD) { - RxMessage->StdId = CAN_TMIR_StdId_Mask & (CANx->FIFOMailBox[FIFONumber].RFMIR >> 21); - } else { - RxMessage->ExtId = CAN_TMIR_ExtId_Mask & (CANx->FIFOMailBox[FIFONumber].RFMIR >> 3); - } - - RxMessage->FT = (uint8_t)0x02 & CANx->FIFOMailBox[FIFONumber].RFMIR; - /* Get the data length code */ - RxMessage->DLC = (uint8_t)0x0F & CANx->FIFOMailBox[FIFONumber].RFMPR; - /* Get the filtering index */ - RxMessage->FI = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMPR >> 8); - /* Get FIFO mailbox data */ - RxMessage->Data[0] = (uint8_t)0xFF & CANx->FIFOMailBox[FIFONumber].RFMD0R; - RxMessage->Data[1] = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMD0R >> 8); - RxMessage->Data[2] = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMD0R >> 16); - RxMessage->Data[3] = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMD0R >> 24); - RxMessage->Data[4] = (uint8_t)0xFF & CANx->FIFOMailBox[FIFONumber].RFMD1R; - RxMessage->Data[5] = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMD1R >> 8); - RxMessage->Data[6] = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMD1R >> 16); - RxMessage->Data[7] = (uint8_t)0xFF & (CANx->FIFOMailBox[FIFONumber].RFMD1R >> 24); - /* Release the FIFO */ - if (FIFONumber == CAN_FIFO0) { - CANx->RFR0 |= CAN_RFR0_RFD0; - } - - /* FIFONumber == CAN_FIFO1 */ - else { - CANx->RFR1 |= CAN_RFR1_RFD1; - } -} - -/** - * @brief Dequeue the FIFO. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param FIFONumber: FIFO to dequeue, it can be CAN_FIFO0 or CAN_FIFO1. - * @retval None. - */ -void CAN_FIFODequeue(CAN_TypeDef *CANx, uint8_t FIFONumber) -{ - - if (FIFONumber == CAN_FIFO0) { - /* Release FIFO 0 */ - CANx->RFR0 |= CAN_RFR0_RFD0; - } else { /* FIFONumber == CAN_FIFO1 */ - /* Release FIFO1 */ - CANx->RFR1 |= CAN_RFR1_RFD1; - } -} - -/** - * @brief Return the length of receiving messages. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1. - * @retval message_length : which is the Length of pending message. - */ -uint8_t CAN_MessageLength(CAN_TypeDef *CANx, uint8_t FIFONumber) -{ - uint8_t message_length = 0; - if (FIFONumber == CAN_FIFO0) { - message_length = (uint8_t)(CANx->RFR0 & (uint32_t)0x03); - } else if (FIFONumber == CAN_FIFO1) { - message_length = (uint8_t)(CANx->RFR1 & (uint32_t)0x03); - } else { - message_length = 0; - } - return message_length; -} - - -/** - * @brief Select the CAN Working mode. - * @param CAN_WorkingMode : CAN Working Mode.It can be the following one. - * @arg CAN_WORKINGMODE_INITIAL - * @arg CAN_WORKINGMODE_NORMAL - * @arg CAN_WORKINGMODE_SLEEP - * @retval state of the requested mode which can be - * @arg CAN_MODESTATE_FAILED - * @arg CAN_MODESTATE_SUCCESS - */ -uint8_t CAN_WorkingMode(CAN_TypeDef *CANx, uint8_t CAN_WorkingMode) -{ - uint8_t state = CAN_MODESTATE_FAILED; - - /* Timeout for IWS or also for SWS bits*/ - uint32_t timeout = IWS_TIMEOUT; - - if (CAN_WorkingMode == CAN_WORKINGMODE_INITIAL) { - /* Set initialisation */ - CANx->CTLR = (uint32_t)((CANx->CTLR & (uint32_t)(~(uint32_t)CAN_CTLR_SWM)) | CAN_CTLR_IWM); - - /* Wait the acknowledge */ - while (((CANx->STR & CAN_MODE_MASK) != CAN_STR_IWS) && (timeout != 0)) { - timeout--; - } - if ((CANx->STR & CAN_MODE_MASK) != CAN_STR_IWS) { - state = CAN_MODESTATE_FAILED; - } else { - state = CAN_MODESTATE_SUCCESS; - } - } else if (CAN_WorkingMode == CAN_WORKINGMODE_NORMAL) { - /* Enter Normal mode */ - CANx->CTLR &= (uint32_t)(~(CAN_CTLR_SWM | CAN_CTLR_IWM)); - - /* Wait the acknowledge */ - while (((CANx->STR & CAN_MODE_MASK) != 0) && (timeout != 0)) { - timeout--; - } - if ((CANx->STR & CAN_MODE_MASK) != 0) { - state = CAN_MODESTATE_FAILED; - } else { - state = CAN_MODESTATE_SUCCESS; - } - } else if (CAN_WorkingMode == CAN_WORKINGMODE_SLEEP) { - /* Set Sleep mode */ - CANx->CTLR = (uint32_t)((CANx->CTLR & (uint32_t)(~(uint32_t)CAN_CTLR_IWM)) | CAN_CTLR_SWM); - - /* Wait the acknowledge */ - while (((CANx->STR & CAN_MODE_MASK) != CAN_STR_SWS) && (timeout != 0)) { - timeout--; - } - if ((CANx->STR & CAN_MODE_MASK) != CAN_STR_SWS) { - state = CAN_MODESTATE_FAILED; - } else { - state = CAN_MODESTATE_SUCCESS; - } - } else { - state = CAN_MODESTATE_FAILED; - } - - return (uint8_t) state; -} - -/** - * @brief Enter the Sleep mode. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @retval state: CAN_SLEEP_OK or CAN_SLEEP_FAILED. - */ -uint8_t CAN_EnterSleep(CAN_TypeDef *CANx) -{ - /* Set Sleep mode */ - CANx->CTLR = (((CANx->CTLR) & (uint32_t)(~(uint32_t)CAN_CTLR_IWM)) | CAN_CTLR_SWM); - - if ((CANx->STR & (CAN_STR_SWS | CAN_STR_IWS)) == CAN_STR_SWS) { - /* Sleep mode entered success*/ - return (uint8_t)CAN_SLEEP_OK; - } else { - /* Sleep mode entered failure */ - return (uint8_t)CAN_SLEEP_FAILED; - } -} - -/** - * @brief Wake up CAN. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @retval status: CAN_WAKEUP_OK or CAN_WAKEUP_FAILED. - */ -uint8_t CAN_WakeUp(CAN_TypeDef *CANx) -{ - uint32_t wait_sws = SWS_TIMEOUT; - - /*set wake up */ - CANx->CTLR &= ~(uint32_t)CAN_CTLR_SWM; - - /* Sleep mode state */ - while (((CANx->CTLR & CAN_CTLR_SWM) == CAN_CTLR_SWM) && (wait_sws != 0x00)) { - wait_sws--; - } - if ((CANx->CTLR & CAN_CTLR_SWM) != CAN_CTLR_SWM) { - /*Sleep mode exited */ - return (uint8_t)CAN_WAKEUP_OK; - } else { - /*Sleep mode exited failure */ - return (uint8_t)CAN_WAKEUP_FAILED; - } -} - - -/** - * @brief Return the CANx's last error type (LEC). - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @retval CAN_ErrorType: specify the Error type: - * @arg CAN_ERRORTYPE_NOERR - * @arg CAN_ERRORTYPE_STUFFERR - * @arg CAN_ERRORTYPE_FORMERR - * @arg CAN_ERRORTYPE_ACKERR - * @arg CAN_ERRORTYPE_BITRECESSIVEERR - * @arg CAN_ERRORTYPE_BITDOMINANTERR - * @arg CAN_ERRORTYPE_CRCERR - * @arg CAN_ERRORTYPE_SOFTWARESETERR - */ - -uint8_t CAN_GetErrorType(CAN_TypeDef *CANx) -{ - uint8_t error_type = 0; - - /* Get the error type*/ - error_type = (((uint8_t)CANx->ER) & (uint8_t)CAN_ER_ET); - - /* Return the error type*/ - return error_type; -} - -/** - * @brief Get the Counter of CANx Receive Error(REC). - * @note According to the error condition as defined by the CAN standard, - * the counter of CANx Receive Error is increased by 1 or by 8. - * When CAN received success everytime, the counter is decreased by 1 - * or reset to 120 if its value was over than 128. - * When the counter value is over 127, the CAN controller enters the - * error passive state. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @retval CAN Receive Error Counter. - */ -uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef *CANx) -{ - uint8_t receive_counter = 0; - - /* Get the counter of CANx Receive Error*/ - receive_counter = (uint8_t)((CANx->ER & CAN_ER_REC) >> 24); - - /* Return the Receive Error Counter*/ - return receive_counter; -} - - -/** - * @brief Get the Counter of CANx Transmit Error (TEC). - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @retval CAN Transmit Error Counter. - */ -uint8_t CAN_GetTransmitErrorCounter(CAN_TypeDef *CANx) -{ - uint8_t transmit_counter = 0; - - /* Get the Counter of CANx Transmit Error(TEC) */ - transmit_counter = (uint8_t)((CANx->ER & CAN_ER_TEC) >> 16); - - /* Return the Transmit Error Counter*/ - return transmit_counter; -} - - -/** - * @brief Enable or disable the specified CANx interrupts. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param CAN_INT: specify the CAN interrupt sources to be enabled or disabled. - * This parameter can be: - * @arg CAN_INT_TME - * @arg CAN_INT_RFNE0 - * @arg CAN_INT_RFF0 - * @arg CAN_INT_RFO0 - * @arg CAN_INT_RFNE1 - * @arg CAN_INT_RFF1 - * @arg CAN_INT_RFO1 - * @arg CAN_INT_WE - * @arg CAN_INT_PE - * @arg CAN_INT_BOE - * @arg CAN_INT_ET - * @arg CAN_INT_ERR - * @arg CAN_INT_WU - * @arg CAN_INT_SLP - * @param NewValue: new state of the CAN interrupts. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void CAN_INTConfig(CAN_TypeDef *CANx, uint32_t CAN_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable interrupt */ - CANx->IER |= CAN_INT; - } else { - /* Disable interrupt */ - CANx->IER &= ~CAN_INT; - } -} -/** - * @brief Check whether the specified CAN flag is set or not. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param CAN_FLAG: specify the flag to check. - * This parameter can be one of the following flags: - * @arg CAN_FLAG_WE: Warning error Flag - * @arg CAN_FLAG_PE: Passive error Flag - * @arg CAN_FLAG_BOE: Bus-off error Flag - * @arg CAN_FLAG_MTF0: Mailbox 0 transmit finished Flag - * @arg CAN_FLAG_MTF1: Mailbox 1 transmit finished Flag - * @arg CAN_FLAG_MTF2: Mailbox 2 transmit finished Flag - * @arg CAN_FLAG_RFL0: the length of the receive FIFO0 Flag - * @arg CAN_FLAG_RFF0: Receive FIFO 0 full Flag - * @arg CAN_FLAG_RFO0: Receive FIFO 0 overfull Flag - * @arg CAN_FLAG_RFL1: the length of the receive FIFO1 Flag - * @arg CAN_FLAG_RFF1: Receive FIFO 1 full Flag - * @arg CAN_FLAG_RFO1: Receive FIFO 0 overfull Flag - * @arg CAN_FLAG_WU: Wake up Flag - * @arg CAN_FLAG_SLP: Sleep working state Flag - * @arg CAN_FLAG_ET: Error type Flag - * @retval The new state of CAN_FLAG (SET or RESET). - */ -TypeState CAN_GetBitState(CAN_TypeDef *CANx, uint32_t CAN_FLAG) -{ - if ((CAN_FLAG & CAN_FLAGS_ER) != (uint32_t)RESET) { - /* Check the state of the specified CAN flag */ - if ((CANx->ER & (CAN_FLAG & CAN_FLAG_Mask)) != (uint32_t)RESET) { - /* CAN_FLAG is set */ - return SET; - } else { - /* CAN_FLAG is reset */ - return RESET; - } - } else if ((CAN_FLAG & CAN_FLAGS_STR) != (uint32_t)RESET) { - /* Check the state of the specified CAN flag */ - if ((CANx->STR & (CAN_FLAG & CAN_FLAG_Mask)) != (uint32_t)RESET) { - /* CAN_FLAG is set */ - return SET; - } else { - /* CAN_FLAG is reset */ - return RESET; - } - } else if ((CAN_FLAG & CAN_FLAGS_TSTR) != (uint32_t)RESET) { - /* Check the state of the specified CAN flag */ - if ((CANx->TSTR & (CAN_FLAG & CAN_FLAG_Mask)) != (uint32_t)RESET) { - /* CAN_FLAG is set */ - return SET; - } else { - /* CAN_FLAG is reset */ - return RESET; - } - } else if ((CAN_FLAG & CAN_FLAGS_RFR0) != (uint32_t)RESET) { - /* Check the state of the specified CAN flag */ - if ((CANx->RFR0 & (CAN_FLAG & CAN_FLAG_Mask)) != (uint32_t)RESET) { - /* CAN_FLAG is set */ - return SET; - } else { - /* CAN_FLAG is reset */ - return RESET; - } - } - /* If(CAN_FLAG & CAN_FLAGS_RFR1 != (uint32_t)RESET) */ - else { - /* Check the state of the specified CAN flag */ - if ((uint32_t)(CANx->RFR1 & (CAN_FLAG & CAN_FLAG_Mask)) != (uint32_t)RESET) { - /* CAN_FLAG is set */ - return SET; - } else { - /* CAN_FLAG is reset */ - return RESET; - } - } -} - -/** - * @brief Clear the CAN's flags. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param CAN_FLAG: specify the flag to clear. - * This parameter can be one of the following flags: - * @arg CAN_FLAG_MTF0: Mailbox 0 transmit finished Flag - * @arg CAN_FLAG_MTF1: Mailbox 1 transmit finished Flag - * @arg CAN_FLAG_MTF2: Mailbox 2 transmit finished Flag - * @arg CAN_FLAG_RFF0: Receive FIFO 0 full Flag - * @arg CAN_FLAG_RFO0: Receive FIFO 0 overfull Flag - * @arg CAN_FLAG_RFF1: Receive FIFO 1 full Flag - * @arg CAN_FLAG_RFO1: Receive FIFO 0 overfull Flag - * @arg CAN_FLAG_WU: Wake up Flag - * @arg CAN_FLAG_SLP: Sleep working state Flag - * @arg CAN_FLAG_ET: Error type Flag - * @retval None. - */ -void CAN_ClearBitState(CAN_TypeDef *CANx, uint32_t CAN_FLAG) -{ - uint32_t temp = 0; - - /* ER register */ - if (CAN_FLAG == CAN_FLAG_ET) { - /* Clear the selected CAN flags */ - CANx->ER = (uint32_t)RESET; - } - /* STR or TSTR or RFR0 or RFR1 */ - else { - temp = CAN_FLAG & CAN_FLAG_Mask; - - if ((CAN_FLAG & CAN_FLAGS_RFR0) != (uint32_t)RESET) { - /* Receive Flags */ - CANx->RFR0 = (uint32_t)(temp); - } else if ((CAN_FLAG & CAN_FLAGS_RFR1) != (uint32_t)RESET) { - /* Receive Flags */ - CANx->RFR1 = (uint32_t)(temp); - } else if ((CAN_FLAG & CAN_FLAGS_TSTR) != (uint32_t)RESET) { - /* Transmit Flags */ - CANx->TSTR = (uint32_t)(temp); - } - /* If((CAN_FLAG & CAN_FLAGS_STR)!=(uint32_t)RESET) */ - else { - CANx->STR = (uint32_t)(temp); - } - } -} - -/** - * @brief Check whether the specified CANx interrupt has occurred or not. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param CAN_INT: specify the CAN interrupt source to check. - * This parameter can be: - * @arg CAN_INT_TME - * @arg CAN_INT_RFNE0 - * @arg CAN_INT_RFF0 - * @arg CAN_INT_RFO0 - * @arg CAN_INT_RFNE1 - * @arg CAN_INT_RFF1 - * @arg CAN_INT_RFO1 - * @arg CAN_INT_WE - * @arg CAN_INT_PE - * @arg CAN_INT_BOE - * @arg CAN_INT_ET - * @arg CAN_INT_ERR - * @arg CAN_INT_WU - * @arg CAN_INT_SLP - * @retval The current state of CAN_INT (SET or RESET). - */ -TypeState CAN_GetIntBitState(CAN_TypeDef *CANx, uint32_t CAN_INT) -{ - TypeState intstate = RESET; - - /* Get the enable interrupt bit */ - if ((CANx->IER & CAN_INT) != RESET) { - switch (CAN_INT) { - case CAN_INT_TME: - /* Check CAN_TSTR_MTFx bits */ - intstate = CheckINTState(CANx->TSTR, CAN_TSTR_MTF0 | CAN_TSTR_MTF1 | CAN_TSTR_MTF2); - break; - case CAN_INT_RFNE0: - /* Check CAN_RFR0_RFL0 bit */ - intstate = CheckINTState(CANx->RFR0, CAN_RFR0_RFL0); - break; - case CAN_INT_RFF0: - /* Check CAN_RFR0_RFF0 bit */ - intstate = CheckINTState(CANx->RFR0, CAN_RFR0_RFF0); - break; - case CAN_INT_RFO0: - /* Check CAN_RFR0_RFO0 bit */ - intstate = CheckINTState(CANx->RFR0, CAN_RFR0_RFO0); - break; - case CAN_INT_RFNE1: - /* Check CAN_RFR1_RFL1 bit */ - intstate = CheckINTState(CANx->RFR1, CAN_RFR1_RFL1); - break; - case CAN_INT_RFF1: - /* Check CAN_RFR1_RFF1 bit */ - intstate = CheckINTState(CANx->RFR1, CAN_RFR1_RFF1); - break; - case CAN_INT_RFO1: - /* Check CAN_RFR1_RFO1 bit */ - intstate = CheckINTState(CANx->RFR1, CAN_RFR1_RFO1); - break; - case CAN_INT_WU: - /* Check CAN_STR_WIF bit */ - intstate = CheckINTState(CANx->STR, CAN_STR_WIF); - break; - case CAN_INT_SLP: - /* Check CAN_STR_SEIF bit */ - intstate = CheckINTState(CANx->STR, CAN_STR_SEIF); - break; - case CAN_INT_WE: - /* Check CAN_INT_WE bit */ - intstate = CheckINTState(CANx->ER, CAN_ER_WE); - break; - case CAN_INT_PE: - /* Check CAN_INT_EP bit */ - intstate = CheckINTState(CANx->ER, CAN_ER_PE); - break; - case CAN_INT_BOE: - /* Check CAN_ER_BOE bit */ - intstate = CheckINTState(CANx->ER, CAN_ER_BOE); - break; - case CAN_INT_ET: - /* Check CAN_ER_ET bit */ - intstate = CheckINTState(CANx->ER, CAN_ER_ET); - break; - case CAN_INT_ERR: - /* Check CAN_STR_EIF bit */ - intstate = CheckINTState(CANx->STR, CAN_STR_EIF); - break; - default : - /* in case of error, return RESET */ - intstate = RESET; - break; - } - } else { - /* in case the Interrupt is not enabled, return RESET */ - intstate = RESET; - } - - /* Return the CAN_INT status */ - return intstate; -} - -/** - * @brief Clear the CANx's interrupt pending bits. - * @param CANx: where x:[1,2] to to select the CAN peripheral. - * @param CAN_INT: specify the interrupt pending bit to clear. - * This parameter can be: - * @arg CAN_INT_TME - * @arg CAN_INT_RFF0 - * @arg CAN_INT_RFO0 - * @arg CAN_INT_RFF1 - * @arg CAN_INT_RFO1 - * @arg CAN_INT_WE - * @arg CAN_INT_PE - * @arg CAN_INT_BOE - * @arg CAN_INT_ET - * @arg CAN_INT_ERR - * @arg CAN_INT_WU - * @arg CAN_INT_SLP - * @retval None. - */ -void CAN_ClearIntBitState(CAN_TypeDef *CANx, uint32_t CAN_INT) -{ - switch (CAN_INT) { - case CAN_INT_TME: - /* Clear CAN_TSTR_MTFx (rc_w1)*/ - CANx->TSTR = CAN_TSTR_MTF0 | CAN_TSTR_MTF1 | CAN_TSTR_MTF2; - break; - case CAN_INT_RFF0: - /* Clear CAN_RFR0_RFF0 (rc_w1)*/ - CANx->RFR0 = CAN_RFR0_RFF0; - break; - case CAN_INT_RFO0: - /* Clear CAN_RFR0_RFO0 (rc_w1)*/ - CANx->RFR0 = CAN_RFR0_RFO0; - break; - case CAN_INT_RFF1: - /* Clear CAN_RFR1_RFF1 (rc_w1)*/ - CANx->RFR1 = CAN_RFR1_RFF1; - break; - case CAN_INT_RFO1: - /* Clear CAN_RFR1_RFO1 (rc_w1)*/ - CANx->RFR1 = CAN_RFR1_RFO1; - break; - case CAN_INT_WU: - /* Clear CAN_STR_WIF (rc_w1)*/ - CANx->STR = CAN_STR_WIF; - break; - case CAN_INT_SLP: - /* Clear CAN_STR_SEIF (rc_w1)*/ - CANx->STR = CAN_STR_SEIF; - break; - case CAN_INT_WE: - /* Clear CAN_STR_EIF (rc_w1) */ - CANx->STR = CAN_STR_EIF; - break; - case CAN_INT_PE: - /* Clear CAN_MSR_ERRI (rc_w1) */ - CANx->STR = CAN_STR_EIF; - break; - case CAN_INT_BOE: - /* Clear CAN_STR_EIF (rc_w1) */ - CANx->STR = CAN_STR_EIF; - break; - case CAN_INT_ET: - /* Clear ET bits */ - CANx->ER = RESET; - /* Clear CAN_STR_EIF (rc_w1) */ - CANx->STR = CAN_STR_EIF; - break; - case CAN_INT_ERR: - /*Clear ET bits */ - CANx->ER = RESET; - /* Clear CAN_STR_EIF (rc_w1) */ - CANx->STR = CAN_STR_EIF; - break; - default : - break; - } -} - -/** - * @brief Check whether the CAN interrupt has occurred or not. - * @param CAN_Reg: the register of CAN interrupt to check. - * @param Int_Bit: the bit of interrupt source to check. - * @retval The new state of the CAN Interrupt (SET or RESET). - */ -static TypeState CheckINTState(uint32_t CAN_Reg, uint32_t Int_Bit) -{ - if ((CAN_Reg & Int_Bit) != (uint32_t)RESET) { - /* CAN_INT is set */ - return SET; - } else { - /* CAN_IT is reset */ - return RESET; - } -} - - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_crc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_crc.c deleted file mode 100644 index e081db43d0..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_crc.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - ****************************************************************************** - * @brief CRC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_crc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup CRC - * @brief CRC driver modules - * @{ - */ - -/** @defgroup CRC_Private_Functions - * @{ - */ - -/** - * @brief Reset CRC DTR register to the value of 0xFFFFFFFF. - * @param None - * @retval None - */ -void CRC_ResetDTR(void) -{ - CRC->CTLR = CRC_CTLR_RESET; -} - -/** - * @brief Compute the 32-bit CRC value of a 32-bit data. - * @param CRC_data: data to compute its CRC value - * @retval 32-bit CRC value - */ -uint32_t CRC_CalcSingleData(uint32_t CRC_data) -{ - CRC->DTR = CRC_data; - - return (CRC->DTR); -} - -/** - * @brief Compute the 32-bit CRC value of a 32-bit data array. - * @param pbuffer[]: pointer to the data array - * @param buffer_length: length of the data array - * @retval 32-bit CRC value - */ -uint32_t CRC_CalcDataFlow(uint32_t pbuffer[], uint32_t buffer_length) -{ - uint32_t index = 0; - - for (index = 0; index < buffer_length; index++) { - CRC->DTR = pbuffer[index]; - } - return (CRC->DTR); -} - -/** - * @brief Read current CRC value. - * @param None - * @retval 32-bit CRC value - */ -uint32_t CRC_ReadDTR(void) -{ - return (CRC->DTR); -} - -/** - * @brief Write an 8-bit data in FDTR. - * @param CRC_fdtr: 8-bit data to write - * @retval None - */ -void CRC_WriteFDTR(uint8_t CRC_fdtr) -{ - CRC->FDTR = CRC_fdtr; -} - -/** - * @brief Read the 8-bit data stored in FDTR - * @param None - * @retval 8-bit data - */ -uint8_t CRC_ReadFDTR(void) -{ - return (CRC->FDTR); -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dac.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dac.c deleted file mode 100644 index d50c031de6..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dac.c +++ /dev/null @@ -1,326 +0,0 @@ -/** - ****************************************************************************** - * @brief DAC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_dac.h" -#include "gd32f10x_rcc.h" -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup DAC - * @brief DAC driver modules - * @{ - */ - -/** @defgroup DAC_Private_Defines - * @{ - */ -/* CTLR register bits mask */ -#define CTLR_BITS_CLEAR ((uint32_t)0x00000FFE) -/* DAC Dual Channels SWTRIG masks */ -#define DUAL_SWTRIG_SET ((uint32_t)0x00000003) -/* DHR registers offsets */ -#define DHR12R1_OFFSET ((uint32_t)0x00000008) -#define DHR12R2_OFFSET ((uint32_t)0x00000014) -#define DHR12RD_OFFSET ((uint32_t)0x00000020) -/* DOR register offset */ -#define DOR_OFFSET ((uint32_t)0x0000002C) - -/** - * @} - */ - -/** @defgroup DAC_Private_Functions - * @{ - */ - -/** - * @brief Deinitialize the DAC peripheral registers. - * @param DAC_InitParaStruct: DAC_InitPara structure that contains the - * configuration information for the selected DAC channel. - * @retval None - */ -void DAC_DeInit(DAC_InitPara *DAC_InitParaStruct) -{ - /* Enable DAC reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_DACRST, ENABLE); - /* Release DAC from reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_DACRST, DISABLE); - /* Initialize the DAC_Trigger */ - DAC_InitParaStruct->DAC_Trigger = DAC_TRIGGER_NONE; - /* Initialize the DAC_WaveGeneration */ - DAC_InitParaStruct->DAC_WaveType = DAC_WAVEGENE_NONE; - /* Initialize the DAC_LFSRUnmask_TriangleAmplitude */ - DAC_InitParaStruct->DAC_LFSRNoise_AmplitudeTriangle = DAC_LFSR_BIT0; - /* Initialize the DAC_OutputBuffer */ - DAC_InitParaStruct->DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; -} - -/** - * @brief Initialize the DAC peripheral. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: select DAC Channel1 - * @arg DAC_Channel_2: select DAC Channel2 - * @param DAC_InitStruct: DAC_InitTypeDef structure . - * @retval None - */ -void DAC_Init(uint32_t DAC_Channel, DAC_InitPara *DAC_InitParaStruct) -{ - uint32_t temp1 = 0, temp2 = 0; - - /* DAC CTLR Configuration */ - /* Get the DAC CTLR value */ - temp1 = DAC->CTLR; - - /* Clear BOFF, TEN, TSEL, WAVE and MAMP bits */ - temp1 &= ~(CTLR_BITS_CLEAR << DAC_Channel); - - /* Configure for the DAC channel: buffer output, trigger, wave generation, - mask/amplitude for wave generation */ - /* Set TSEL and TEN bits according to DAC_Trigger */ - /* Set WAVE bits according to DAC_WaveType */ - /* Set MAMP bits according to DAC_LFSRNoise_AmplitudeTriangle */ - /* Set BOFF bit according to DAC_OutputBuffer */ - temp2 = (DAC_InitParaStruct->DAC_Trigger | DAC_InitParaStruct->DAC_OutputBuffer | - DAC_InitParaStruct->DAC_WaveType | DAC_InitParaStruct->DAC_LFSRNoise_AmplitudeTriangle); - /* Calculate CTLR register value */ - temp1 |= temp2 << DAC_Channel; - - /* Write to DAC CTLR */ - DAC->CTLR = temp1; -} - -/** - * @brief Enable or disable the DAC channel. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: select DAC Channel1. - * @arg DAC_Channel_2: select DAC Channel2. - * @param NewValue: New value of the DAC channel. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DAC_Enable(uint32_t DAC_Channel, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the selected DAC channel */ - DAC->CTLR |= (DAC_CTLR_DEN1 << DAC_Channel) ; - } else { - /* Disable the selected DAC channel */ - DAC->CTLR &= ~(DAC_CTLR_DEN1 << DAC_Channel); - } -} - -/** - * @brief Enable or disable the selected DAC channel software trigger. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: select DAC Channel1 - * @arg DAC_Channel_2: select DAC Channel2 - * @param NewValue: New value of the selected DAC channel software trigger. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DAC_SoftwareTrigger_Enable(uint32_t DAC_Channel, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable software trigger for DAC channel1 */ - DAC->SWTR |= (uint32_t)DAC_SWTR_SWTR1 << (DAC_Channel >> 4); - } else { - /* Disable software trigger for DAC channel1 */ - DAC->SWTR &= ~((uint32_t)DAC_SWTR_SWTR1 << (DAC_Channel >> 4)); - } -} - -/** - * @brief Enable or disable simultaneously the two DAC channels software - * triggers. - * @param NewValue: new value of the DAC channels software triggers. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DAC_DualSoftwareTrigger_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable software trigger */ - DAC->SWTR |= DUAL_SWTRIG_SET ; - } else { - /* Disable software trigger */ - DAC->SWTR &= ~DUAL_SWTRIG_SET; - } -} - -/** - * @brief Enable or disable the selected DAC channel wave generation. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: select DAC Channel1 - * @arg DAC_Channel_2: select DAC Channel2 - * @param DAC_Wave: the wave type to enable or disable. - * This parameter can be one of the following values: - * @arg DAC_WAVE_NOISE: noise wave generation - * @arg DAC_WAVE_TRIANGLE: triangle wave generation - * @param NewValue: new value of the selected DAC channel wave generation. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DAC_WaveGeneration_Enable(uint32_t DAC_Channel, uint32_t DAC_Wave, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the selected DAC channel wave generation */ - DAC->CTLR |= DAC_Wave << DAC_Channel; - } else { - /* Disable the selected DAC channel wave generation */ - DAC->CTLR &= ~(DAC_Wave << DAC_Channel); - } -} - -/** - * @brief Set the specified data holding register value for DAC channel1. - * @param DAC_Align: the data alignment for DAC channel1. - * This parameter can be one of the following values: - * @arg DAC_ALIGN_8B_R: select 8bit right data alignment - * @arg DAC_ALIGN_12B_L: select 12bit left data alignment - * @arg DAC_ALIGN_12B_R: select 12bit right data alignment - * @param Data: Data to be loaded. - * @retval None - */ -void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) -{ - __IO uint32_t temp = 0; - - temp = (uint32_t)DAC_BASE; - temp += DHR12R1_OFFSET + DAC_Align; - - /* Set the DAC channel1 */ - *(__IO uint32_t *) temp = Data; -} - -/** - * @brief Set the specified data holding register value for DAC channel2. - * @param DAC_Align: the data alignment for DAC channel2. - * This parameter can be one of the following values: - * @arg DAC_ALIGN_8B_R: select 8bit right data alignment - * @arg DAC_ALIGN_12B_L: select 12bit left data alignment - * @arg DAC_ALIGN_12B_R: select 12bit right data alignment - * @param Data: Data to be loaded. - * @retval None - */ -void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data) -{ - __IO uint32_t temp = 0; - - temp = (uint32_t)DAC_BASE; - temp += DHR12R2_OFFSET + DAC_Align; - - /* Set the DAC channel2 */ - *(__IO uint32_t *) temp = Data; -} - -/** - * @brief Set the specified data for dual channel - * @param DAC_Align: the data alignment for dual channel DAC. - * This parameter can be one of the following values: - * @arg DAC_Align_8b_R: select 8bit right data alignment - * @arg DAC_Align_12b_L: select 12bit left data alignment - * @arg DAC_Align_12b_R: select 12bit right data alignment - * @param Data2: Data for DAC Channel2. - * @param Data1: Data for DAC Channel1. - * @retval None - */ -void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) -{ - uint32_t data = 0, temp = 0; - - /* set dual DAC data holding register value */ - if (DAC_Align == DAC_ALIGN_8B_R) { - data = ((uint32_t)Data2 << 8) | Data1; - } else { - data = ((uint32_t)Data2 << 16) | Data1; - } - - temp = (uint32_t)DAC_BASE; - temp += DHR12RD_OFFSET + DAC_Align; - - /* Set the dual DAC selected data holding register */ - *(__IO uint32_t *)temp = data; -} - -/** - * @brief Return the last data output value. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: select DAC Channel1 - * @arg DAC_Channel_2: select DAC Channel2 - * @retval The DAC channel1 data output value. - */ -uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel) -{ - __IO uint32_t temp = 0; - - temp = (uint32_t) DAC_BASE; - temp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2); - - /* Returns the DAC channel data */ - return (uint16_t)(*(__IO uint32_t *) temp); -} - -/** - * @brief Enable or disable DMA request. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: select DAC Channel1 - * @arg DAC_Channel_2: select DAC Channel2 - * @param NewValue: New value of the selected DAC channel DMA request. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DAC_DMA_Enable(uint32_t DAC_Channel, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable DMA request */ - DAC->CTLR |= (DAC_CTLR_DDMAEN1 << DAC_Channel); - } else { - /* Disable DMA request */ - DAC->CTLR &= ~(DAC_CTLR_DDMAEN1 << DAC_Channel); - } -} - -/** - * @brief Enable or disable the specified DAC interrupts. - * @param DAC_Channel: the selected DAC channel. - * This parameter can be one of the following values: - * @arg DAC_Channel_1: DAC Channel1 selected - * @arg DAC_Channel_2: DAC Channel2 selected - * @param NewValue: Alternative state of the specified DAC interrupts. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DAC_INTConfig(uint32_t DAC_Channel, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DAC DMAUDR interrupts */ - DAC->CTLR |= (DAC_INT_DMAUDR << DAC_Channel); - } else { - /* Disable the DAC DMAUDR interrupts */ - DAC->CTLR &= (~(uint32_t)(DAC_INT_DMAUDR << DAC_Channel)); - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dma.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dma.c deleted file mode 100644 index a519b30b9a..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_dma.c +++ /dev/null @@ -1,553 +0,0 @@ -/** - ****************************************************************************** - * @brief DMA functions of the firmware library. - ****************************************************************************** - */ - - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_dma.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup DMA - * @brief DMA driver modules - * @{ - */ - -/** @defgroup DMA_Private_Defines - * @{ - */ - -/* DMA Reset registers mask */ -#define DMA_REGISTERS_RESET ((uint32_t)0x00000000) - -/* DMA Channel config registers Masks */ -#define CTLR_CLEAR_MASK ((uint32_t)0xFFFF800F) - -/* DMA Reset registers mask */ -#define DMA_INT_RESET ((uint32_t)0x00000000) - -/* DMA2 FLAG mask */ -#define DMA2_FLAG_Mask ((uint32_t)0x10000000) - -/* DMA1 Channelx interrupt pending bit masks */ -#define DMA1_Channel1_INT_Mask ((uint32_t)(DMA_IFR_GIF1 | DMA_IFR_TCIF1 | DMA_IFR_HTIF1 | DMA_IFR_ERRIF1)) -#define DMA1_Channel2_INT_Mask ((uint32_t)(DMA_IFR_GIF2 | DMA_IFR_TCIF2 | DMA_IFR_HTIF2 | DMA_IFR_ERRIF2)) -#define DMA1_Channel3_INT_Mask ((uint32_t)(DMA_IFR_GIF3 | DMA_IFR_TCIF3 | DMA_IFR_HTIF3 | DMA_IFR_ERRIF3)) -#define DMA1_Channel4_INT_Mask ((uint32_t)(DMA_IFR_GIF4 | DMA_IFR_TCIF4 | DMA_IFR_HTIF4 | DMA_IFR_ERRIF4)) -#define DMA1_Channel5_INT_Mask ((uint32_t)(DMA_IFR_GIF5 | DMA_IFR_TCIF5 | DMA_IFR_HTIF5 | DMA_IFR_ERRIF5)) -#define DMA1_Channel6_INT_Mask ((uint32_t)(DMA_IFR_GIF6 | DMA_IFR_TCIF6 | DMA_IFR_HTIF6 | DMA_IFR_ERRIF6)) -#define DMA1_Channel7_INT_Mask ((uint32_t)(DMA_IFR_GIF7 | DMA_IFR_TCIF7 | DMA_IFR_HTIF7 | DMA_IFR_ERRIF7)) - -/* DMA2 Channelx interrupt pending bit masks */ -#define DMA2_Channel1_INT_Mask ((uint32_t)(DMA_IFR_GIF1 | DMA_IFR_TCIF1 | DMA_IFR_HTIF1 | DMA_IFR_ERRIF1)) -#define DMA2_Channel2_INT_Mask ((uint32_t)(DMA_IFR_GIF2 | DMA_IFR_TCIF2 | DMA_IFR_HTIF2 | DMA_IFR_ERRIF2)) -#define DMA2_Channel3_INT_Mask ((uint32_t)(DMA_IFR_GIF3 | DMA_IFR_TCIF3 | DMA_IFR_HTIF3 | DMA_IFR_ERRIF3)) -#define DMA2_Channel4_INT_Mask ((uint32_t)(DMA_IFR_GIF4 | DMA_IFR_TCIF4 | DMA_IFR_HTIF4 | DMA_IFR_ERRIF4)) -#define DMA2_Channel5_INT_Mask ((uint32_t)(DMA_IFR_GIF5 | DMA_IFR_TCIF5 | DMA_IFR_HTIF5 | DMA_IFR_ERRIF5)) - -/** - * @} - */ - - -/** @defgroup DMA_Private_Functions - * @{ - */ - -/** - * @brief Deinitialize the DMAy Channelx registers - * @param DMAy_Channelx: where y:[1,2] to select the DMA , x:[1,7] for DMA1 and x:[1,5] for DMA2 to select the DMA Channel. - * @retval None - */ -void DMA_DeInit(DMA_Channel_TypeDef *DMAy_Channelx) -{ - /* Disable the selected DMAy Channelx */ - DMAy_Channelx->CTLR &= (uint16_t)(~DMA_CTLR_CHEN); - - /* Reset DMAy Channelx control register */ - DMAy_Channelx->CTLR = DMA_REGISTERS_RESET; - - /* Reset DMAy Channelx remaining bytes register */ - DMAy_Channelx->RCNT = DMA_REGISTERS_RESET; - - /* Reset DMAy Channelx peripheral address register */ - DMAy_Channelx->PBAR = DMA_REGISTERS_RESET; - - /* Reset DMAy Channelx memory address register */ - DMAy_Channelx->MBAR = DMA_REGISTERS_RESET; - - if (DMAy_Channelx == DMA1_CHANNEL1) { - /* Reset interrupt pending bits for DMA1 Channel1 */ - DMA1->ICR |= DMA1_Channel1_INT_Mask; - } else if (DMAy_Channelx == DMA1_CHANNEL2) { - /* Reset interrupt pending bits for DMA1 Channel2 */ - DMA1->ICR |= DMA1_Channel2_INT_Mask; - } else if (DMAy_Channelx == DMA1_CHANNEL3) { - /* Reset interrupt pending bits for DMA1 Channel3 */ - DMA1->ICR |= DMA1_Channel3_INT_Mask; - } else if (DMAy_Channelx == DMA1_CHANNEL4) { - /* Reset interrupt pending bits for DMA1 Channel4 */ - DMA1->ICR |= DMA1_Channel4_INT_Mask; - } else if (DMAy_Channelx == DMA1_CHANNEL5) { - /* Reset interrupt pending bits for DMA1 Channel5 */ - DMA1->ICR |= DMA1_Channel5_INT_Mask; - } else if (DMAy_Channelx == DMA1_CHANNEL6) { - /* Reset interrupt pending bits for DMA1 Channel6 */ - DMA1->ICR |= DMA1_Channel6_INT_Mask; - } else if (DMAy_Channelx == DMA1_CHANNEL7) { - /* Reset interrupt pending bits for DMA1 Channel7 */ - DMA1->ICR |= DMA1_Channel7_INT_Mask; - } else if (DMAy_Channelx == DMA2_CHANNEL1) { - /* Reset interrupt pending bits for DMA2 Channel1 */ - DMA2->ICR |= DMA2_Channel1_INT_Mask; - } else if (DMAy_Channelx == DMA2_CHANNEL2) { - /* Reset interrupt pending bits for DMA2 Channel2 */ - DMA2->ICR |= DMA2_Channel2_INT_Mask; - } else if (DMAy_Channelx == DMA2_CHANNEL3) { - /* Reset interrupt pending bits for DMA2 Channel3 */ - DMA2->ICR |= DMA2_Channel3_INT_Mask; - } else if (DMAy_Channelx == DMA2_CHANNEL4) { - /* Reset interrupt pending bits for DMA2 Channel4 */ - DMA2->ICR |= DMA2_Channel4_INT_Mask; - } else { - if (DMAy_Channelx == DMA2_CHANNEL5) { - /* Reset interrupt pending bits for DMA2 Channel5 */ - DMA2->ICR |= DMA2_Channel5_INT_Mask; - } - } -} - - -/** - * @brief Initialize the DMAy Channelx according to the DMA_InitParaStruct. - * @param DMAy_Channelx: where y:[1:2] to select the DMA , x:[1,7] for DMA1 and x:[1,5] for DMA2 to select the DMA Channel. - * @param DMA_InitParaStruct: contain the configuration information for the specified DMA Channel. - * @retval None - */ -void DMA_Init(DMA_Channel_TypeDef *DMAy_Channelx, DMA_InitPara *DMA_InitParaStruct) -{ - uint32_t temp = 0; - - /* Get the DMAy_Channelx CCR value */ - temp = DMAy_Channelx->CTLR; - - /* Clear MEMTOMEM, PRIO, MSIZE, PSIZE, MNAGA, PNAGA, CIRC and DIR bits */ - temp &= CTLR_CLEAR_MASK; - /* Configure DMAy Channelx: data transfer, data size, priority level and mode */ - /* Set MEMTOMEM, PRIO, MSIZE, PSIZE, MNAGA, PNAGA, CIRC and DIR bits according to DMA_InitParaStruct */ - temp |= DMA_InitParaStruct->DMA_DIR | DMA_InitParaStruct->DMA_Mode | - DMA_InitParaStruct->DMA_PeripheralInc | DMA_InitParaStruct->DMA_MemoryInc | - DMA_InitParaStruct->DMA_PeripheralDataSize | DMA_InitParaStruct->DMA_MemoryDataSize | - DMA_InitParaStruct->DMA_Priority | DMA_InitParaStruct->DMA_MTOM; - - /* Write to DMAy Channelx CTLR */ - DMAy_Channelx->CTLR = temp; - - /* Write to DMAy Channelx RCNT */ - DMAy_Channelx->RCNT = DMA_InitParaStruct->DMA_BufferSize; - - /* Write to DMAy Channelx PBAR */ - DMAy_Channelx->PBAR = DMA_InitParaStruct->DMA_PeripheralBaseAddr; - - /* Write to DMAy Channelx MBAR */ - DMAy_Channelx->MBAR = DMA_InitParaStruct->DMA_MemoryBaseAddr; -} - -/** - * @brief Set each DMA_InitParaStruct member to its default value. - * @param DMA_InitParaStruct: The structure pointer to DMA_InitParaStruct will be initialized. - * @retval None - */ -void DMA_ParaInit(DMA_InitPara *DMA_InitParaStruct) -{ - /* Reset DMA init structure parameters values */ - DMA_InitParaStruct->DMA_PeripheralBaseAddr = DMA_INT_RESET; - - DMA_InitParaStruct->DMA_MemoryBaseAddr = DMA_INT_RESET; - - DMA_InitParaStruct->DMA_DIR = DMA_DIR_PERIPHERALSRC; - - DMA_InitParaStruct->DMA_BufferSize = DMA_INT_RESET; - - DMA_InitParaStruct->DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE; - - DMA_InitParaStruct->DMA_MemoryInc = DMA_MEMORYINC_DISABLE; - - DMA_InitParaStruct->DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_BYTE; - - DMA_InitParaStruct->DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE; - - DMA_InitParaStruct->DMA_Mode = DMA_MODE_NORMAL; - - DMA_InitParaStruct->DMA_Priority = DMA_PRIORITY_LOW; - - DMA_InitParaStruct->DMA_MTOM = DMA_MEMTOMEM_DISABLE; -} - -/** - * @brief Enable or disable the DMAy Channelx. - * @param DMAy_Channelx: where y:[1:2] to select the DMA , x:[1,7] for DMA1 and x:[1,5] for DMA2 to select the DMA Channel. - * @param NewValue: new state of the DMAy Channelx. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DMA_Enable(DMA_Channel_TypeDef *DMAy_Channelx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMAy Channelx */ - DMAy_Channelx->CTLR |= DMA_CTLR_CHEN; - } else { - /* Disable the DMAy Channelx */ - DMAy_Channelx->CTLR &= (uint16_t)(~DMA_CTLR_CHEN); - } -} - -/** - * @brief Enable or disable the DMAy Channelx interrupts. - * @param DMAy_Channelx: where y:[1:2] to select the DMA , x:[1,7] for DMA1 and x:[1,5] for DMA2 to select the DMA Channel. - * @param DMA_INT: specify the DMA interrupts sources to be enabled or disabled. - * This parameter can be any combination of the following values: - * @arg DMA_INT_TC: Transfer complete interrupt mask - * @arg DMA_INT_HT: Half transfer interrupt mask - * @arg DMA_INT_ERR: Transfer error interrupt mask - * @param NewValue: new state of the DMA interrupts. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void DMA_INTConfig(DMA_Channel_TypeDef *DMAy_Channelx, uint32_t DMA_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMA interrupts */ - DMAy_Channelx->CTLR |= DMA_INT; - } else { - /* Disable the DMA interrupts */ - DMAy_Channelx->CTLR &= ~DMA_INT; - } -} - -/** - * @brief Set the number of the remaining counter in the current DMAy Channelx transfer. - * @param DMAy_Channelx: where y:[1:2] to select the DMA , x:[1,7] for DMA1 and x:[1,5] for DMA2 to select the DMA Channel. - * @param DataNumber: The number of the remaining counter in the current DMAy Channelx transfer. - * @retval None. - */ -void DMA_SetCurrDataCounter(DMA_Channel_TypeDef *DMAy_Channelx, uint16_t DataNumber) -{ - /* Write to DMAy Channelx RCNT */ - DMAy_Channelx->RCNT = DataNumber; -} - -/** - * @brief Return the number of remaining counter in the current DMAy Channelx transfer. - * @param DMAy_Channelx: where y:[1:2] to select the DMA , x:[1,7] for DMA1 and x:[1,5] for DMA2 to select the DMA Channel. - * @retval The number of remaining counter in the current DMAy Channelx transfer. - */ -uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef *DMAy_Channelx) -{ - /* Return the number of remaining counter for DMAy Channelx */ - return ((uint16_t)(DMAy_Channelx->RCNT)); -} - -/** - * @brief Check whether the DMAy Channelx flag is set or not. - * @param DMAy_FLAG: specifies the flag to check. - * This parameter can be one of the following values: - * @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag. - * @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. - * @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. - * @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. - * @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag. - * @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. - * @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. - * @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. - * @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag. - * @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. - * @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. - * @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. - * @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag. - * @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. - * @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. - * @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. - * @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag. - * @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. - * @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. - * @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. - * @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag. - * @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. - * @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. - * @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. - * @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag. - * @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. - * @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. - * @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. - * @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag. - * @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. - * @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. - * @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. - * @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag. - * @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. - * @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. - * @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. - * @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag. - * @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. - * @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. - * @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. - * @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag. - * @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. - * @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. - * @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. - * @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag. - * @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. - * @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. - * @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. - * @retval The new state of DMAy_FLAG (SET or RESET). - */ -TypeState DMA_GetBitState(uint32_t DMAy_FLAG) -{ - uint32_t temp = 0; - - /* Check the used DMAy */ - if ((DMAy_FLAG & DMA2_FLAG_Mask) != (uint32_t)RESET) { - /* Get DMA2 ISR register value */ - temp = DMA2->IFR ; - } else { - /* Get DMA1 ISR register value */ - temp = DMA1->IFR ; - } - - /* Check the status of the DMAy flag */ - if ((temp & DMAy_FLAG) != (uint32_t)RESET) { - /* DMAy_FLAG is set */ - return SET; - } else { - /* DMAy_FLAG is reset */ - return RESET; - } -} - -/** - * @brief Clear the DMAy Channelx's bit flags. - * @param DMAy_FLAG: specifies the flag to clear. - * This parameter can be any combination (for the same DMA) of the following values: - * @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag. - * @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. - * @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. - * @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. - * @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag. - * @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. - * @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. - * @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. - * @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag. - * @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. - * @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. - * @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. - * @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag. - * @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. - * @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. - * @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. - * @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag. - * @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. - * @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. - * @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. - * @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag. - * @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. - * @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. - * @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. - * @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag. - * @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. - * @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. - * @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. - * @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag. - * @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. - * @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. - * @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. - * @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag. - * @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. - * @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. - * @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. - * @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag. - * @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. - * @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. - * @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. - * @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag. - * @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. - * @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. - * @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. - * @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag. - * @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. - * @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. - * @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. - * @retval None - */ -void DMA_ClearBitState(uint32_t DMAy_FLAG) -{ - /* Check the used DMAy */ - if ((DMAy_FLAG & DMA2_FLAG_Mask) != (uint32_t)RESET) { - /* Clear the selected DMAy flags */ - DMA2->ICR = DMAy_FLAG; - } else { - /* Clear the selected DMAy flags */ - DMA1->ICR = DMAy_FLAG; - } -} - -/** - * @brief Check whether the DMAy Channelx interrupt has occurred or not. - * @param DMAy_INT: specify the DMAy interrupt source to check. - * This parameter can be one of the following values: - * @arg DMA1_INT_GL1: DMA1 Channel1 global interrupt. - * @arg DMA1_INT_TC1: DMA1 Channel1 transfer complete interrupt. - * @arg DMA1_INT_HT1: DMA1 Channel1 half transfer interrupt. - * @arg DMA1_INT_TE1: DMA1 Channel1 transfer error interrupt. - * @arg DMA1_INT_GL2: DMA1 Channel2 global interrupt. - * @arg DMA1_INT_TC2: DMA1 Channel2 transfer complete interrupt. - * @arg DMA1_INT_HT2: DMA1 Channel2 half transfer interrupt. - * @arg DMA1_INT_TE2: DMA1 Channel2 transfer error interrupt. - * @arg DMA1_INT_GL3: DMA1 Channel3 global interrupt. - * @arg DMA1_INT_TC3: DMA1 Channel3 transfer complete interrupt. - * @arg DMA1_INT_HT3: DMA1 Channel3 half transfer interrupt. - * @arg DMA1_INT_TE3: DMA1 Channel3 transfer error interrupt. - * @arg DMA1_INT_GL4: DMA1 Channel4 global interrupt. - * @arg DMA1_INT_TC4: DMA1 Channel4 transfer complete interrupt. - * @arg DMA1_INT_HT4: DMA1 Channel4 half transfer interrupt. - * @arg DMA1_INT_TE4: DMA1 Channel4 transfer error interrupt. - * @arg DMA1_INT_GL5: DMA1 Channel5 global interrupt. - * @arg DMA1_INT_TC5: DMA1 Channel5 transfer complete interrupt. - * @arg DMA1_INT_HT5: DMA1 Channel5 half transfer interrupt. - * @arg DMA1_INT_TE5: DMA1 Channel5 transfer error interrupt. - * @arg DMA1_INT_GL6: DMA1 Channel6 global interrupt. - * @arg DMA1_INT_TC6: DMA1 Channel6 transfer complete interrupt. - * @arg DMA1_INT_HT6: DMA1 Channel6 half transfer interrupt. - * @arg DMA1_INT_TE6: DMA1 Channel6 transfer error interrupt. - * @arg DMA1_INT_GL7: DMA1 Channel7 global interrupt. - * @arg DMA1_INT_TC7: DMA1 Channel7 transfer complete interrupt. - * @arg DMA1_INT_HT7: DMA1 Channel7 half transfer interrupt. - * @arg DMA1_INT_TE7: DMA1 Channel7 transfer error interrupt. - * @arg DMA2_INT_GL1: DMA2 Channel1 global interrupt. - * @arg DMA2_INT_TC1: DMA2 Channel1 transfer complete interrupt. - * @arg DMA2_INT_HT1: DMA2 Channel1 half transfer interrupt. - * @arg DMA2_INT_TE1: DMA2 Channel1 transfer error interrupt. - * @arg DMA2_INT_GL2: DMA2 Channel2 global interrupt. - * @arg DMA2_INT_TC2: DMA2 Channel2 transfer complete interrupt. - * @arg DMA2_INT_HT2: DMA2 Channel2 half transfer interrupt. - * @arg DMA2_INT_TE2: DMA2 Channel2 transfer error interrupt. - * @arg DMA2_INT_GL3: DMA2 Channel3 global interrupt. - * @arg DMA2_INT_TC3: DMA2 Channel3 transfer complete interrupt. - * @arg DMA2_INT_HT3: DMA2 Channel3 half transfer interrupt. - * @arg DMA2_INT_TE3: DMA2 Channel3 transfer error interrupt. - * @arg DMA2_INT_GL4: DMA2 Channel4 global interrupt. - * @arg DMA2_INT_TC4: DMA2 Channel4 transfer complete interrupt. - * @arg DMA2_INT_HT4: DMA2 Channel4 half transfer interrupt. - * @arg DMA2_INT_TE4: DMA2 Channel4 transfer error interrupt. - * @arg DMA2_INT_GL5: DMA2 Channel5 global interrupt. - * @arg DMA2_INT_TC5: DMA2 Channel5 transfer complete interrupt. - * @arg DMA2_INT_HT5: DMA2 Channel5 half transfer interrupt. - * @arg DMA2_INT_TE5: DMA2 Channel5 transfer error interrupt. - * @retval The new state of DMAy_IT (SET or RESET). - */ -TypeState DMA_GetIntBitState(uint32_t DMAy_INT) -{ - uint32_t temp = 0; - - /* Calculate the used DMA */ - if ((DMAy_INT & DMA2_FLAG_Mask) != (uint32_t)RESET) { - /* Get DMA2 IFR register value */ - temp = DMA2->IFR; - } else { - /* Get DMA1 IFR register value */ - temp = DMA1->IFR; - } - - /* Check the status of the DMAy interrupt */ - if ((temp & DMAy_INT) != (uint32_t)RESET) { - /* DMA_INT is set */ - return SET; - } else { - /* DMA_INT is reset */ - return RESET; - } -} - -/** - * @brief Clear the DMAy Channelx's interrupt bits. - * @param DMAy_INT: specify the DMAy interrupt pending bit to clear. - * This parameter can be any combination (for the same DMA) of the following values: - * @arg DMA1_INT_GL1: DMA1 Channel1 global interrupt. - * @arg DMA1_INT_TC1: DMA1 Channel1 transfer complete interrupt. - * @arg DMA1_INT_HT1: DMA1 Channel1 half transfer interrupt. - * @arg DMA1_INT_TE1: DMA1 Channel1 transfer error interrupt. - * @arg DMA1_INT_GL2: DMA1 Channel2 global interrupt. - * @arg DMA1_INT_TC2: DMA1 Channel2 transfer complete interrupt. - * @arg DMA1_INT_HT2: DMA1 Channel2 half transfer interrupt. - * @arg DMA1_INT_TE2: DMA1 Channel2 transfer error interrupt. - * @arg DMA1_INT_GL3: DMA1 Channel3 global interrupt. - * @arg DMA1_INT_TC3: DMA1 Channel3 transfer complete interrupt. - * @arg DMA1_INT_HT3: DMA1 Channel3 half transfer interrupt. - * @arg DMA1_INT_TE3: DMA1 Channel3 transfer error interrupt. - * @arg DMA1_INT_GL4: DMA1 Channel4 global interrupt. - * @arg DMA1_INT_TC4: DMA1 Channel4 transfer complete interrupt. - * @arg DMA1_INT_HT4: DMA1 Channel4 half transfer interrupt. - * @arg DMA1_INT_TE4: DMA1 Channel4 transfer error interrupt. - * @arg DMA1_INT_GL5: DMA1 Channel5 global interrupt. - * @arg DMA1_INT_TC5: DMA1 Channel5 transfer complete interrupt. - * @arg DMA1_INT_HT5: DMA1 Channel5 half transfer interrupt. - * @arg DMA1_INT_TE5: DMA1 Channel5 transfer error interrupt. - * @arg DMA1_INT_GL6: DMA1 Channel6 global interrupt. - * @arg DMA1_INT_TC6: DMA1 Channel6 transfer complete interrupt. - * @arg DMA1_INT_HT6: DMA1 Channel6 half transfer interrupt. - * @arg DMA1_INT_TE6: DMA1 Channel6 transfer error interrupt. - * @arg DMA1_INT_GL7: DMA1 Channel7 global interrupt. - * @arg DMA1_INT_TC7: DMA1 Channel7 transfer complete interrupt. - * @arg DMA1_INT_HT7: DMA1 Channel7 half transfer interrupt. - * @arg DMA1_INT_TE7: DMA1 Channel7 transfer error interrupt. - * @arg DMA2_INT_GL1: DMA2 Channel1 global interrupt. - * @arg DMA2_INT_TC1: DMA2 Channel1 transfer complete interrupt. - * @arg DMA2_INT_HT1: DMA2 Channel1 half transfer interrupt. - * @arg DMA2_INT_TE1: DMA2 Channel1 transfer error interrupt. - * @arg DMA2_INT_GL2: DMA2 Channel2 global interrupt. - * @arg DMA2_INT_TC2: DMA2 Channel2 transfer complete interrupt. - * @arg DMA2_INT_HT2: DMA2 Channel2 half transfer interrupt. - * @arg DMA2_INT_TE2: DMA2 Channel2 transfer error interrupt. - * @arg DMA2_INT_GL3: DMA2 Channel3 global interrupt. - * @arg DMA2_INT_TC3: DMA2 Channel3 transfer complete interrupt. - * @arg DMA2_INT_HT3: DMA2 Channel3 half transfer interrupt. - * @arg DMA2_INT_TE3: DMA2 Channel3 transfer error interrupt. - * @arg DMA2_INT_GL4: DMA2 Channel4 global interrupt. - * @arg DMA2_INT_TC4: DMA2 Channel4 transfer complete interrupt. - * @arg DMA2_INT_HT4: DMA2 Channel4 half transfer interrupt. - * @arg DMA2_INT_TE4: DMA2 Channel4 transfer error interrupt. - * @arg DMA2_INT_GL5: DMA2 Channel5 global interrupt. - * @arg DMA2_INT_TC5: DMA2 Channel5 transfer complete interrupt. - * @arg DMA2_INT_HT5: DMA2 Channel5 half transfer interrupt. - * @arg DMA2_INT_TE5: DMA2 Channel5 transfer error interrupt. - * @retval None - */ -void DMA_ClearIntBitState(uint32_t DMAy_INT) -{ - - /* Check the used DMAy */ - if ((DMAy_INT & DMA2_FLAG_Mask) != (uint32_t)RESET) { - /* Clear the DMA2 interrupt bits */ - DMA2->ICR = DMAy_INT; - } else { - /* Clear the DMA1 interrupt bits */ - DMA1->ICR = DMAy_INT; - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_eth.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_eth.c deleted file mode 100644 index fa83328d47..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_eth.c +++ /dev/null @@ -1,2587 +0,0 @@ -/** - ****************************************************************************** - * @brief ETH header file of the firmware library. - ****************************************************************************** - */ -#ifdef GD32F10X_CL -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_eth.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup ETH - * @brief ETH driver modules - * @{ - */ - -/** @defgroup ETH_Private_Defines - * @{ - */ - -/* Global transmit and receive descriptors pointers */ -ETH_DMADESCTypeDef *DMACurrentTxDesc; -ETH_DMADESCTypeDef *DMACurrentRxDesc; -ETH_DMADESCTypeDef *DMACurrentPTPTxDesc; -ETH_DMADESCTypeDef *DMACurrentPTPRxDesc; - -/* ETHERNET MAC address offsets */ -#define ETH_MAC_ADDR_HBASE (ETH_MAC_BASE + 0x40) /* ETHERNET MAC address high offset */ -#define ETH_MAC_ADDR_LBASE (ETH_MAC_BASE + 0x44) /* ETHERNET MAC address low offset */ - -/* ETHERNET MAC_PHYAR register Mask */ -#define MAC_PHYAR_CLR_MASK ((uint32_t)0xFFFFFFE3) - -/* ETHERNET MAC_PHYAR register PHY address shift */ -#define MAC_PHYAR_PHYADDRSHIFT 11 - -/* ETHERNET MAC_PHYAR register PHY register shift */ -#define MAC_PHYAR_PHYREGSHIFT 6 - -/* ETHERNET MAC_CFR register Mask */ -#define MAC_CFR_CLEAR_MASK ((uint32_t)0xFF20810F) - -/* ETHERNET MAC_FCTLR register Mask */ -#define MAC_FCTLR_CLEAR_MASK ((uint32_t)0x0000FF41) - -/* ETHERNET DMA_CTLR register Mask */ -#define DMA_CTLR_CLEAR_MASK ((uint32_t)0xF8DE3F23) - -/* ETHERNET Remote Wake-up frame register length */ -#define ETH_WAKEUP_REGISTER_LENGTH 8 - -/* ETHERNET Missed frames counter Shift */ -#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT 17 - -/* ETHERNET DMA Tx descriptors Collision Count Shift */ -#define ETH_DMATXDESC_COLLISION_COUNTSHIFT 3 - -/* ETHERNET DMA Tx descriptors size */ -#define ETH_DMATXDESC_SIZE 0x10 - -/* ETHERNET DMA Rx descriptors size */ -#define ETH_DMARXDESC_SIZE 0x10 - -/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */ -#define ETH_DMATXDESC_BUFFER2_SIZESHIFT 16 - -/* ETHERNET DMA Rx descriptors Frame Length Shift */ -#define ETH_DMARXDESC_FRAME_LENGTHSHIFT 16 - -/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */ -#define ETH_DMARXDESC_BUFFER2_SIZESHIFT 16 - -/* ETHERNET errors */ -#define ERROR ((uint32_t)0) -#define SUCCESS ((uint32_t)1) -/** - * @} - */ - -/** @defgroup ETH_Private_FunctionPrototypes - * @{ - */ - -#ifndef USE_Delay - static void ETH_Delay(__IO uint32_t nCount); -#endif /* USE_Delay*/ - -/** - * @} - */ - -/** @defgroup ETH_Private_Functions - * @{ - */ - -/** - * @brief Reset the ETH registers. - * @param None - * @retval None - */ -void ETH_DeInit(void) -{ - RCC_AHBPeriphReset_Enable(RCC_AHBPERIPH_ETH_MAC, ENABLE); - RCC_AHBPeriphReset_Enable(RCC_AHBPERIPH_ETH_MAC, DISABLE); -} - -/** - * @brief Initialize MDIO parameters. - * @param None - * @retval None - */ -void ETH_MDIOInit(void) -{ - uint32_t temp = 0; - RCC_ClocksPara rcc_clocks; - uint32_t hclk; - - /* ETHERNET MAC_PHYAR Configuration */ - /* Get the ETH_MAC_PHYAR value */ - temp = ETH_MAC->PHYAR; - /* Clear Clock Range CLR[2:0] bits */ - temp &= MAC_PHYAR_CLR_MASK; - /* Get hclk frequency value */ - RCC_GetClocksFreq(&rcc_clocks); - hclk = rcc_clocks.AHB_Frequency; - /* Set CLR bits depending on hclk value */ - if ((hclk >= 20000000) && (hclk < 35000000)) { - /* Clock Range between 20-35 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV16; - } else if ((hclk >= 35000000) && (hclk < 60000000)) { - /* Clock Range between 35-60 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV26; - } else if ((hclk >= 60000000) && (hclk < 90000000)) { - /* Clock Range between 60-90 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV42; - } - /* ((hclk >= 90000000)&&(hclk <= 108000000)) */ - else { - /* Clock Range between 90-108 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV64; - } - /* Write to ETHERNET MAC PHYAR */ - ETH_MAC->PHYAR = (uint32_t)temp; -} - -/** - * @brief Initial the ETH parameters. - * @param ETH_InitParaStruct: The ETH_InitPara structure pointer. - * @param PHYAddress: external PHY address - * @retval The Initialize result(ERROR or SUCCESS) - */ -uint32_t ETH_Init(ETH_InitPara *ETH_InitParaStruct, uint16_t PHYAddress) -{ - uint32_t RegValue = 0, temp = 0; - __IO uint32_t i = 0; - RCC_ClocksPara rcc_clocks; - uint32_t hclk; - __IO uint32_t timeout = 0; - - /* MAC Config */ - /* ETH_MAC_PHYAR Configuration */ - /* Get the ETH_MAC_PHYAR value */ - temp = ETH_MAC->PHYAR; - /* Clear Clock Range CLR[2:0] bits */ - temp &= MAC_PHYAR_CLR_MASK; - /* Get hclk frequency value */ - RCC_GetClocksFreq(&rcc_clocks); - hclk = rcc_clocks.AHB_Frequency; - /* Set CLR bits depending on hclk value */ - if ((hclk >= 20000000) && (hclk < 35000000)) { - /* Clock Range between 20-35 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV16; - } else if ((hclk >= 35000000) && (hclk < 60000000)) { - /* Clock Range between 35-60 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV26; - } else if ((hclk >= 60000000) && (hclk < 90000000)) { - /* Clock Range between 60-90 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV42; - } - /* ((hclk >= 90000000)&&(hclk <= 108000000)) */ - else { - /* Clock Range between 90-108 MHz */ - temp |= (uint32_t)ETH_MAC_PHYAR_CLR_DIV64; - } - ETH_MAC->PHYAR = (uint32_t)temp; - /* PHY initialization and configuration */ - /* Set the PHY into reset mode */ - if (!(ETH_SetPHYRegisterValue(PHYAddress, PHY_BCR, PHY_RESET))) { - /* Return ERROR due to write timeout */ - return ERROR; - } - - /* PHY reset need some time */ - _eth_delay_(PHY_RESETDELAY); - - if (ETH_InitParaStruct->ETH_MAC_AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) { - /* Wait for PHY_LINKED_STATUS bit be set */ - do { - timeout++; - } while (!(ETH_GetPHYRegisterValue(PHYAddress, PHY_BSR) & PHY_LINKED_STATUS) && (timeout < PHY_READ_TO)); - /* Return ERROR due to timeout */ - if (timeout == PHY_READ_TO) { - return ERROR; - } - /* Reset Timeout counter */ - timeout = 0; - - /* Enable Auto-Negotiation */ - if (!(ETH_SetPHYRegisterValue(PHYAddress, PHY_BCR, PHY_AUTONEGOTIATION))) { - /* Return ERROR due to write timeout */ - return ERROR; - } - - /* Wait for the PHY_AUTONEGO_COMPLETE bit be set */ - do { - timeout++; - } while (!(ETH_GetPHYRegisterValue(PHYAddress, PHY_BSR) & PHY_AUTONEGO_COMPLETE) && (timeout < (uint32_t)PHY_READ_TO)); - /* Return ERROR due to timeout */ - if (timeout == PHY_READ_TO) { - return ERROR; - } - /* Reset Timeout counter */ - timeout = 0; - - /* Read the result of the autonegotiation */ - RegValue = ETH_GetPHYRegisterValue(PHYAddress, PHY_SR); - - /* Configure the Duplex Mode of MAC following the autonegotiation result */ - if ((RegValue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) { - ETH_InitParaStruct->ETH_MAC_Mode = ETH_MODE_FULLDUPLEX; - - } else { - ETH_InitParaStruct->ETH_MAC_Mode = ETH_MODE_HALFDUPLEX; - } - /* Configure the Communication speed of MAC following the autonegotiation result */ - if (RegValue & PHY_Speed_Status) { - ETH_InitParaStruct->ETH_MAC_Speed = ETH_SPEEDMODE_10M; - } else { - ETH_InitParaStruct->ETH_MAC_Speed = ETH_SPEEDMODE_100M; - } - } else { - if (!ETH_SetPHYRegisterValue(PHYAddress, PHY_BCR, ((uint16_t)(ETH_InitParaStruct->ETH_MAC_Mode >> 3) | - (uint16_t)(ETH_InitParaStruct->ETH_MAC_Speed >> 1)))) { - /* Return ERROR due to write timeout */ - return ERROR; - } - /* PHY configuration need some time */ - _eth_delay_(PHY_CONFIGDELAY); - } - /* ETH_MAC_CFR Configuration */ - /* Get the ETH_MAC_CFR value */ - temp = ETH_MAC->CFR; - temp &= MAC_CFR_CLEAR_MASK; - /* Set the WDD bit according to ETH_MAC_Watchdog value */ - /* Set the JBD: bit according to ETH_MAC_Jabber value */ - /* Set the IG bit according to ETH_MAC_InterFrameGap value */ - /* Set the CSD bit according to ETH_MAC_CarrierSense value */ - /* Set the SPD bit according to ETH_MAC_Speed value */ - /* Set the ROD bit according to ETH_MAC_ReceiveOwn value */ - /* Set the LBM bit according to ETH_MAC_LoopbackMode value */ - /* Set the DPM bit according to ETH_MAC_Mode value */ - /* Set the IP4CO bit according to ETH_MAC_ChecksumOffload value */ - /* Set the RTD bit according to ETH_MAC_RetryTransmission value */ - /* Set the APCD bit according to ETH_MAC_AutomaticPadCRCDrop value */ - /* Set the BOL bit according to ETH_MAC_BackOffLimit value */ - /* Set the DFC bit according to ETH_MAC_DeferralCheck value */ - temp |= (uint32_t)(ETH_InitParaStruct->ETH_MAC_Watchdog | - ETH_InitParaStruct->ETH_MAC_Jabber | - ETH_InitParaStruct->ETH_MAC_InterFrameGap | - ETH_InitParaStruct->ETH_MAC_CarrierSense | - ETH_InitParaStruct->ETH_MAC_Speed | - ETH_InitParaStruct->ETH_MAC_ReceiveOwn | - ETH_InitParaStruct->ETH_MAC_LoopbackMode | - ETH_InitParaStruct->ETH_MAC_Mode | - ETH_InitParaStruct->ETH_MAC_ChecksumOffload | - ETH_InitParaStruct->ETH_MAC_RetryTransmission | - ETH_InitParaStruct->ETH_MAC_AutomaticPadCRCDrop | - ETH_InitParaStruct->ETH_MAC_BackOffLimit | - ETH_InitParaStruct->ETH_MAC_DeferralCheck); - /* Write to ETH_MAC_CFR */ - ETH_MAC->CFR = (uint32_t)temp; - - /* ETH_MAC_FRMFR Configuration */ - /* Set the FD bit according to ETH_MAC_FilterDisable value */ - /* Set the SAFLT and SAIFLT bits according to ETH_MAC_SourceAddrFilter value */ - /* Set the PCFRM bit according to ETH_MAC_PassControlFrames value */ - /* Set the DBF bit according to ETH_MAC_BroadcastFramesReception value */ - /* Set the DAIFLT bit according to ETH_MAC_DestinationAddrFilter value */ - /* Set the PM bit according to ETH_MAC_PromiscuousMode value */ - /* Set the PM, HMF and HPFLT bits according to ETH_MAC_MulticastFramesFilter value */ - /* Set the HUF and HPFLT bits according to ETH_MAC_UnicastFramesFilter value */ - /* Write to ETH_MAC_FRMFR */ - ETH_MAC->FRMFR = (uint32_t)(ETH_InitParaStruct->ETH_MAC_FilterDisable | - ETH_InitParaStruct->ETH_MAC_SourceAddrFilter | - ETH_InitParaStruct->ETH_MAC_PassControlFrames | - ETH_InitParaStruct->ETH_MAC_BroadcastFramesReception | - ETH_InitParaStruct->ETH_MAC_DestinationAddrFilter | - ETH_InitParaStruct->ETH_MAC_PromiscuousMode | - ETH_InitParaStruct->ETH_MAC_MulticastFramesFilter | - ETH_InitParaStruct->ETH_MAC_UnicastFramesFilter); - /* ETH_MAC_HLHR and MAC_HLLR Configuration */ - /* Write to ETHERNET MAC_HLHR */ - ETH_MAC->HLHR = (uint32_t)ETH_InitParaStruct->ETH_MAC_HashListHigh; - /* Write to ETHERNET MAC_HLLR */ - ETH_MAC->HLLR = (uint32_t)ETH_InitParaStruct->ETH_MAC_HashListLow; - /* ETH_MAC_FCTLR Configuration */ - /* Get the ETH_MAC_FCTLR value */ - temp = ETH_MAC->FCTLR; - temp &= MAC_FCTLR_CLEAR_MASK; - - /* Set the PTM bit according to ETH_MAC_PauseTime value */ - /* Set the ZQPD bit according to ETH_MAC_ZeroQuantaPause value */ - /* Set the PLTS bit according to ETH_MAC_PauseLowThreshold value */ - /* Set the UPFDT bit according to ETH_MAC_UnicastPauseFrameDetect value */ - /* Set the RFCEN bit according to ETH_MAC_ReceiveFlowControl value */ - /* Set the TFCEN bit according to ETH_MAC_TransmitFlowControl value */ - temp |= (uint32_t)((ETH_InitParaStruct->ETH_MAC_PauseTime << 16) | - ETH_InitParaStruct->ETH_MAC_ZeroQuantaPause | - ETH_InitParaStruct->ETH_MAC_PauseLowThreshold | - ETH_InitParaStruct->ETH_MAC_UnicastPauseFrameDetect | - ETH_InitParaStruct->ETH_MAC_ReceiveFlowControl | - ETH_InitParaStruct->ETH_MAC_TransmitFlowControl); - /* Write to ETH_MAC_FCTLR */ - ETH_MAC->FCTLR = (uint32_t)temp; - /* ETH_MAC_FCTHR Configuration */ - temp = ETH_MAC->FCTHR; - temp |= (uint32_t)(ETH_InitParaStruct->ETH_MAC_FlowControlDeactiveThreshold | - ETH_InitParaStruct->ETH_MAC_FlowControlActiveThreshold); - ETH_MAC->FCTHR = (uint32_t)temp; - /* ETH_MAC_VLTR Configuration */ - /* Set the VLTC bit according to ETH_MAC_VLANTagComparison value */ - /* Set the VLTI bit according to ETH_MAC_VLANTagIdentifier value */ - ETH_MAC->VLTR = (uint32_t)(ETH_InitParaStruct->ETH_MAC_VLANTagComparison | - ETH_InitParaStruct->ETH_MAC_VLANTagIdentifier); - - /* DMA Config */ - /* ETH_DMA_CTLR Configuration */ - /* Get the ETHERNET DMA_CTLR value */ - temp = ETH_DMA->CTLR; - temp &= DMA_CTLR_CLEAR_MASK; - - /* Set the DTCERFD bit according to ETH_DMA_DropTCPIPChecksumErrorFrame value */ - /* Set the RSFD bit according to ETH_DMA_ReceiveStoreForward value */ - /* Set the DAFRF bit according to ETH_DMA_FlushReceivedFrame value */ - /* Set the TSFD bit according to ETH_DMA_TransmitStoreForward value */ - /* Set the TTCH bit according to ETH_DMA_TransmitThresholdControl value */ - /* Set the FERF bit according to ETH_DMA_ForwardErrorFrames value */ - /* Set the FUF bit according to ETH_DMA_ForwardUndersizedGoodFrames value */ - /* Set the RTHC bit according to ETH_DMA_ReceiveThresholdControl value */ - /* Set the OSF bit according to ETH_DMA_SecondFrameOperate value */ - temp |= (uint32_t)(ETH_InitParaStruct->ETH_DMA_DropTCPIPChecksumErrorFrame | - ETH_InitParaStruct->ETH_DMA_ReceiveStoreForward | - ETH_InitParaStruct->ETH_DMA_FlushReceivedFrame | - ETH_InitParaStruct->ETH_DMA_TransmitStoreForward | - ETH_InitParaStruct->ETH_DMA_TransmitThresholdControl | - ETH_InitParaStruct->ETH_DMA_ForwardErrorFrames | - ETH_InitParaStruct->ETH_DMA_ForwardUndersizedGoodFrames | - ETH_InitParaStruct->ETH_DMA_ReceiveThresholdControl | - ETH_InitParaStruct->ETH_DMA_SecondFrameOperate); - /* Write to ETH_DMA_CTLR */ - ETH_DMA->CTLR = (uint32_t)temp; - - /* ETH_DMA_BCR Configuration */ - /* Set the AA bit according to ETH_DMA_AddressAligned value */ - /* Set the FB bit according to ETH_DMA_FixedBurst value */ - /* Set the RXDP and 4*PBL bits according to ETH_DMA_RxDMABurstLength value */ - /* Set the FPBL and 4*PBL bits according to ETH_DMA_TxDMABurstLength value */ - /* Set the DPSL bit according to ETH_DesciptorSkipLength value */ - /* Set the RTPR and DAB bits according to ETH_DMA_Arbitration value */ - ETH_DMA->BCR = (uint32_t)(ETH_InitParaStruct->ETH_DMA_AddressAligned | - ETH_InitParaStruct->ETH_DMA_FixedBurst | - ETH_InitParaStruct->ETH_DMA_RxDMABurstLength | /* If 4xPBL is selected for Tx or Rx it is applied for the other */ - ETH_InitParaStruct->ETH_DMA_TxDMABurstLength | - (ETH_InitParaStruct->ETH_DMA_DescriptorSkipLength << 2) | - ETH_InitParaStruct->ETH_DMA_Arbitration | - ETH_DMA_BCR_UIP); /* Enable use of separate PBL for Rx and Tx */ - /* Return Ethernet configuration success */ - return SUCCESS; -} - -/** - * @brief Initial the sturct ETH_InitPara. - * @param ETH_InitParaStruct: pointer to a ETH_InitPara structure. - * @retval None - */ -void ETH_ParaInit(ETH_InitPara *ETH_InitParaStruct) -{ - /* Reset ETH init structure parameters values */ - /* MAC */ - ETH_InitParaStruct->ETH_MAC_AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE; - ETH_InitParaStruct->ETH_MAC_Watchdog = ETH_WATCHDOG_ENABLE; - ETH_InitParaStruct->ETH_MAC_Jabber = ETH_JABBER_ENABLE; - ETH_InitParaStruct->ETH_MAC_InterFrameGap = ETH_INTERFRAMEGAP_96BIT; - ETH_InitParaStruct->ETH_MAC_CarrierSense = ETH_CARRIERSENSE_ENABLE; - ETH_InitParaStruct->ETH_MAC_Speed = ETH_SPEEDMODE_10M; - ETH_InitParaStruct->ETH_MAC_ReceiveOwn = ETH_RECEIVEOWN_ENABLE; - ETH_InitParaStruct->ETH_MAC_LoopbackMode = ETH_LOOPBACKMODE_DISABLE; - ETH_InitParaStruct->ETH_MAC_Mode = ETH_MODE_HALFDUPLEX; - ETH_InitParaStruct->ETH_MAC_ChecksumOffload = ETH_CHECKSUMOFFLOAD_DISABLE; - ETH_InitParaStruct->ETH_MAC_RetryTransmission = ETH_RETRYTRANSMISSION_ENABLE; - ETH_InitParaStruct->ETH_MAC_AutomaticPadCRCDrop = ETH_AUTOMATICPADCRCDROP_DISABLE; - ETH_InitParaStruct->ETH_MAC_BackOffLimit = ETH_BACKOFFLIMIT_10; - ETH_InitParaStruct->ETH_MAC_DeferralCheck = ETH_DEFERRALCHECK_DISABLE; - ETH_InitParaStruct->ETH_MAC_FilterDisable = ETH_FILTERDISABLE_DISABLE; - ETH_InitParaStruct->ETH_MAC_SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE; - ETH_InitParaStruct->ETH_MAC_PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL; - ETH_InitParaStruct->ETH_MAC_BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_DISABLE; - ETH_InitParaStruct->ETH_MAC_DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; - ETH_InitParaStruct->ETH_MAC_PromiscuousMode = ETH_PROMISCUOUSMODE_DISABLE; - ETH_InitParaStruct->ETH_MAC_MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; - ETH_InitParaStruct->ETH_MAC_UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; - ETH_InitParaStruct->ETH_MAC_HashListHigh = 0x0; - ETH_InitParaStruct->ETH_MAC_HashListLow = 0x0; - ETH_InitParaStruct->ETH_MAC_PauseTime = 0x0; - ETH_InitParaStruct->ETH_MAC_ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE; - ETH_InitParaStruct->ETH_MAC_PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; - ETH_InitParaStruct->ETH_MAC_FlowControlDeactiveThreshold = ETH_RFD_512BYTES; - ETH_InitParaStruct->ETH_MAC_FlowControlActiveThreshold = ETH_RFA_1536BYTES; - ETH_InitParaStruct->ETH_MAC_UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE; - ETH_InitParaStruct->ETH_MAC_ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; - ETH_InitParaStruct->ETH_MAC_TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; - ETH_InitParaStruct->ETH_MAC_VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT; - ETH_InitParaStruct->ETH_MAC_VLANTagIdentifier = 0x0; - /* DMA */ - ETH_InitParaStruct->ETH_DMA_DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE; - ETH_InitParaStruct->ETH_DMA_ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE; - ETH_InitParaStruct->ETH_DMA_FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_DISABLE; - ETH_InitParaStruct->ETH_DMA_TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE; - ETH_InitParaStruct->ETH_DMA_TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; - ETH_InitParaStruct->ETH_DMA_ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE; - ETH_InitParaStruct->ETH_DMA_ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE; - ETH_InitParaStruct->ETH_DMA_ReceiveThresholdControl = ETH_RECEIVETHRESHOLDCONTROL_64BYTES; - ETH_InitParaStruct->ETH_DMA_SecondFrameOperate = ETH_SECONDFRAMEOPERATE_DISABLE; - ETH_InitParaStruct->ETH_DMA_AddressAligned = ETH_ADDRESSALIGNED_ENABLE; - ETH_InitParaStruct->ETH_DMA_FixedBurst = ETH_FIXEDBURST_DISABLE; - ETH_InitParaStruct->ETH_DMA_RxDMABurstLength = ETH_RXDMABURSTLENGTH_1BEAT; - ETH_InitParaStruct->ETH_DMA_TxDMABurstLength = ETH_TXDMABURSTLENGTH_1BEAT; - ETH_InitParaStruct->ETH_DMA_DescriptorSkipLength = 0x0; - ETH_InitParaStruct->ETH_DMA_Arbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; -} - -/** - * @brief Enable or disable the ETH's receive and transmit. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void ETH_Enable(TypeState NewValue) -{ - /* Enable or Disable the ETH module */ - if (NewValue != DISABLE) { - /* Enable MAC transmit */ - ETH_MACTransmission_Enable(ENABLE); - /* Flush ETHERNET DMA Transmit FIFO */ - ETH_CleanTransmitFIFO(); - /* Enable MAC receive */ - ETH_MACReception_Enable(ENABLE); - - /* Enable DMA transmission */ - ETH_DMATransmission_Enable(ENABLE); - /* Enable DMA reception */ - ETH_DMAReception_Enable(ENABLE); - } else { - /* Disable MAC transmit */ - ETH_MACTransmission_Enable(DISABLE); - /* Flush ETHERNET DMA Transmit FIFO */ - ETH_CleanTransmitFIFO(); - /* Disable MAC receive */ - ETH_MACReception_Enable(DISABLE); - - /* Disable DMA transmission */ - ETH_DMATransmission_Enable(DISABLE); - /* Disable DMA reception */ - ETH_DMAReception_Enable(DISABLE); - } -} - -/** - * @brief Send data of application buffer as a transmit packet. - * @param pbuf: Pointer to the application buffer. - * @param size: the application buffer size. - * @retval The transmission result(ERROR or SUCCESS) - */ -uint32_t ETH_HandleTxPkt(uint8_t *pbuf, uint16_t size) -{ - uint32_t offset = 0; - - /* Check the busy bit of Tx descriptor status */ - if ((DMACurrentTxDesc->Status & ETH_DMATXDESC_BUSY) != (uint32_t)RESET) { - /* Return ERROR: the descriptor is busy due to own by the DMA */ - return ERROR; - } - - for (offset = 0; offset < size; offset++) { - (*(__IO uint8_t *)((DMACurrentTxDesc->Buffer1Addr) + offset)) = (*(pbuf + offset)); - } - - /* Setting the Frame Length */ - DMACurrentTxDesc->ControlBufferSize = (size & ETH_DMATXDESC_TB1S); - /* Setting the segment of frame (ETH_DMATXDESC_LSG and ETH_DMATXDESC_FSG are SET that frame is transmitted in one descriptor) */ - DMACurrentTxDesc->Status |= ETH_DMATXDESC_LSG | ETH_DMATXDESC_FSG; - /* Enable the DMA transmission */ - DMACurrentTxDesc->Status |= ETH_DMATXDESC_BUSY; - /* Check Tx Buffer unavailable flag status */ - if ((ETH_DMA->STR & ETH_DMA_STR_TBU) != (uint32_t)RESET) { - /* Clear TBU ETHERNET DMA flag */ - ETH_DMA->STR = ETH_DMA_STR_TBU; - /* Resume DMA transmission by writing to the TPER register*/ - ETH_DMA->TPER = 0; - } - - /* Update the ETHERNET DMA current Tx descriptor pointer to the next Tx decriptor in DMA Tx decriptor talbe*/ - /* Chained Mode */ - if ((DMACurrentTxDesc->Status & ETH_DMATXDESC_TCHM) != (uint32_t)RESET) { - DMACurrentTxDesc = (ETH_DMADESCTypeDef *)(DMACurrentTxDesc->Buffer2NextDescAddr); - } - /* Ring Mode */ - else { - if ((DMACurrentTxDesc->Status & ETH_DMATXDESC_TERM) != (uint32_t)RESET) { - DMACurrentTxDesc = (ETH_DMADESCTypeDef *)(ETH_DMA->TDTAR); - } else { - DMACurrentTxDesc = (ETH_DMADESCTypeDef *)((uint32_t)DMACurrentTxDesc + ETH_DMATXDESC_SIZE + ((ETH_DMA->BCR & ETH_DMA_BCR_DPSL) >> 2)); - } - } - /* Return SUCCESS */ - return SUCCESS; -} - -/** - * @brief Receive a packet data to application buffer. - * @param pbuf: Pointer on the application buffer. - * @retval The Receive size(If framelength is equal to ERROR, the receiving unsuccessful) - */ -uint32_t ETH_HandleRxPkt(uint8_t *pbuf) -{ - uint32_t offset = 0, size = 0; - - /* Check the busy bit of Rx descriptor status */ - if ((DMACurrentRxDesc->Status & ETH_DMARXDESC_BUSY) != (uint32_t)RESET) { - /* Return ERROR: the descriptor is busy due to own by the DMA */ - return ERROR; - } - - if (((DMACurrentRxDesc->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET)) { - /* Get the Frame Length exclusive CRC */ - size = ((DMACurrentRxDesc->Status & ETH_DMARXDESC_FRML) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4; - for (offset = 0; offset < size; offset++) { - (*(pbuf + offset)) = (*(__IO uint8_t *)((DMACurrentRxDesc->Buffer1Addr) + offset)); - } - } else { - /* Return ERROR */ - size = ERROR; - } - /* Enable reception */ - DMACurrentRxDesc->Status = ETH_DMARXDESC_BUSY; - - /* Check Rx Buffer unavailable flag status */ - if ((ETH_DMA->STR & ETH_DMA_STR_RBU) != (uint32_t)RESET) { - /* Clear RBU ETHERNET DMA flag */ - ETH_DMA->STR = ETH_DMA_STR_RBU; - /* Resume DMA reception by writing to the RPER register*/ - ETH_DMA->RPER = 0; - } - - /* Update the ETHERNET DMA current Rx descriptor pointer to the next Rx decriptor in DMA Rx decriptor talbe*/ - /* Chained Mode */ - if ((DMACurrentRxDesc->ControlBufferSize & ETH_DMARXDESC_RCHM) != (uint32_t)RESET) { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)(DMACurrentRxDesc->Buffer2NextDescAddr); - } - /* Ring Mode */ - else { - if ((DMACurrentRxDesc->ControlBufferSize & ETH_DMARXDESC_RERR) != (uint32_t)RESET) { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)(ETH_DMA->RDTAR); - } else { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)((uint32_t)DMACurrentRxDesc + ETH_DMARXDESC_SIZE + ((ETH_DMA->BCR & ETH_DMA_BCR_DPSL) >> 2)); - } - } - - /* Return Frame size or ERROR */ - return (size); -} - -/** - * @brief To obtain the received data length - * @param None - * @retval Received frame length. - */ -uint32_t ETH_GetRxPktSize(void) -{ - uint32_t size = 0; - - if ((DMACurrentRxDesc->Status & ETH_DMARXDESC_BUSY) != (uint32_t)RESET) { - return 0; - } - - if (((DMACurrentRxDesc->Status & ETH_DMARXDESC_ERRS) != (uint32_t)RESET) || - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_LDES) == (uint32_t)RESET) || - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_FDES) == (uint32_t)RESET)) { - ETH_DropRxPkt(); - - return 0; - } - - if (((DMACurrentRxDesc->Status & ETH_DMARXDESC_BUSY) == (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET)) { - /* Get the size of the received data including CRC */ - size = ETH_GetDMARxDescFrameLength(DMACurrentRxDesc); - } - - /* Return Packet size */ - return size; -} - -/** - * @brief Discard a Received packet - * @param None - * @retval None - */ -void ETH_DropRxPkt(void) -{ - /* Enable reception */ - DMACurrentRxDesc->Status = ETH_DMARXDESC_BUSY; - /* Chained Mode */ - if ((DMACurrentRxDesc->ControlBufferSize & ETH_DMARXDESC_RCHM) != (uint32_t)RESET) { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)(DMACurrentRxDesc->Buffer2NextDescAddr); - } - /* Ring Mode */ - else { - if ((DMACurrentRxDesc->ControlBufferSize & ETH_DMARXDESC_RERM) != (uint32_t)RESET) { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)(ETH_DMA->RDTAR); - } else { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)((uint32_t)DMACurrentRxDesc + ETH_DMARXDESC_SIZE + ((ETH_DMA->BCR & ETH_DMA_BCR_DPSL) >> 2)); - } - } -} - -/* PHY */ -/** - * @brief Get PHY of ETHERNET parameters. - * @param PHYAddr: PHY device address, devices number max is 32. - * @param PHYReg: PHY register address, register address max is 32. - * Select one of the follwing values : - * @arg PHY_BCR: Tranceiver Basic Control Register - * @arg PHY_BSR: Tranceiver Basic Status Register - * @arg PHY_SR : Tranceiver Status Register - * @arg More PHY register could be read depending on the used PHY - * @retval value read from the selected PHY register (if timeout return ERROR) - */ -uint16_t ETH_GetPHYRegisterValue(uint16_t PHYAddr, uint16_t PHYReg) -{ - uint32_t temp = 0; - __IO uint32_t timeout = 0; - - /* Get the ETHERNET MAC_PHYAR value */ - temp = ETH_MAC->PHYAR; - temp &= ~MAC_PHYAR_CLR_MASK; - /* Configuration the PHY address register value */ - /* Set the PHY device address */ - temp |= (((uint32_t)PHYAddr << MAC_PHYAR_PHYADDRSHIFT) & ETH_MAC_PHYAR_PA); - /* Set the PHY register address */ - temp |= (((uint32_t)PHYReg << MAC_PHYAR_PHYREGSHIFT) & ETH_MAC_PHYAR_PR); - /* Set the read mode */ - temp &= ~ETH_MAC_PHYAR_PW; - /* Set the PHY Busy bit */ - temp |= ETH_MAC_PHYAR_PB; - ETH_MAC->PHYAR = temp; - /* Check the PHY Busy flag status */ - do { - timeout++; - temp = ETH_MAC->PHYAR; - } while ((temp & ETH_MAC_PHYAR_PB) && (timeout < (uint32_t)PHY_READ_TO)); - /* Return ERROR due to timeout */ - if (timeout == PHY_READ_TO) { - return (uint16_t)ERROR; - } - - /* Return PHY register selected value */ - return (uint16_t)(ETH_MAC->PHYDR); -} - -/** - * @brief Set PHY of ETHERNET parameters. - * @param PHYAddr: PHY device address, devices number max is 32. - * @param PHYReg: PHY register address, register address max is 32. - * Select one of the follwing values : - * @arg PHY_BCR : Tranceiver Control Register - * @arg More PHY register could be written depending on the used PHY - * @param PHYValue: write to register value - * @retval The Write to the selected PHY register result(ERROR or SUCCESS) - */ -uint32_t ETH_SetPHYRegisterValue(uint16_t PHYAddr, uint16_t PHYReg, uint16_t PHYValue) -{ - uint32_t temp = 0; - __IO uint32_t timeout = 0; - - /* Get the ETHERNET MAC_PHYAR value */ - temp = ETH_MAC->PHYAR; - temp &= ~MAC_PHYAR_CLR_MASK; - /* Configuration the PHY register address value */ - /* Set the PHY device address */ - temp |= (((uint32_t)PHYAddr << MAC_PHYAR_PHYADDRSHIFT) & ETH_MAC_PHYAR_PA); - /* Set the PHY register address */ - temp |= (((uint32_t)PHYReg << MAC_PHYAR_PHYREGSHIFT) & ETH_MAC_PHYAR_PR); - /* Set the write mode */ - temp |= ETH_MAC_PHYAR_PW; - /* Set the PHY Busy bit */ - temp |= ETH_MAC_PHYAR_PB; - /* Set the PHY selected register value */ - ETH_MAC->PHYDR = PHYValue; - ETH_MAC->PHYAR = temp; - /* Check the PHY Busy flag status */ - do { - timeout++; - temp = ETH_MAC->PHYAR; - } while ((temp & ETH_MAC_PHYAR_PB) && (timeout < (uint32_t)PHY_WRITE_TO)); - /* Return ERROR due to timeout */ - if (timeout == PHY_WRITE_TO) { - return ERROR; - } - - return SUCCESS; -} - -/** - * @brief Enable or disable the PHY loopBack function by write PHY register. - * @param PHYAddr: PHY device address, devices number max is 32. - * @param NewValue: new value of the PHY loopBack mode. - * This parameter can be: ENABLE or DISABLE. - * @retval The Set PHYLoopBack mode result(ERROR or SUCCESS) - */ -uint32_t ETH_PHYLoopBack_Enable(uint16_t PHYAddr, TypeState NewValue) -{ - uint16_t temp = 0; - - /* Get the PHY BCR register value */ - temp = ETH_GetPHYRegisterValue(PHYAddr, PHY_BCR); - - if (NewValue != DISABLE) { - /* Enable the PHY loopback mode */ - temp |= PHY_LOOPBACK; - } else { - /* Disable the PHY loopback mode (change to normal mode) */ - temp &= (uint16_t)(~(uint16_t)PHY_LOOPBACK); - } - /* Set the PHY BCR register with the new value */ - if (ETH_SetPHYRegisterValue(PHYAddr, PHY_BCR, temp) != (uint32_t)RESET) { - return SUCCESS; - } else { - return ERROR; - } -} - -/* MAC */ -/** - * @brief Enable or disable the MAC transmit function. - * @param NewValue: new value of the MAC transmit function. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MACTransmission_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the MAC transmission */ - ETH_MAC->CFR |= ETH_MAC_CFR_TEN; - } else { - /* Disable the MAC transmission */ - ETH_MAC->CFR &= ~ETH_MAC_CFR_TEN; - } -} - -/** - * @brief Enable or disable the MAC receive function. - * @param NewValue: new value of the MAC reception. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MACReception_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the MAC reception */ - ETH_MAC->CFR |= ETH_MAC_CFR_REN; - } else { - /* Disable the MAC reception */ - ETH_MAC->CFR &= ~ETH_MAC_CFR_REN; - } -} - -/** - * @brief Get the bit flag of the ETHERNET flow control busy status. - * @param None - * @retval current flow control busy bit status - */ -TypeState ETH_GetFlowControlBusyBitState(void) -{ - /* Check the flow control busy bit status */ - if ((ETH_MAC->FCTLR & ETH_MAC_FCTLR_FLCBBKPA) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Initiate a Pause Frame in Full-duplex mode only. - * @param None - * @retval None - */ -void ETH_PauseFrameInit(void) -{ - /* Initiate pause control frame in full duplex mode*/ - ETH_MAC->FCTLR |= ETH_MAC_FCTLR_FLCBBKPA; -} - -/** - * @brief Enable or disable the BackPressure requests in Half-duplex only. - * @param NewValue: new value of the BackPressure operation requests. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_BackPressureActivation_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the BackPressure requests */ - ETH_MAC->FCTLR |= ETH_MAC_FCTLR_FLCBBKPA; - } else { - /* Disable the BackPressure requests */ - ETH_MAC->FCTLR &= ~ETH_MAC_FCTLR_FLCBBKPA; - } -} - -/** - * @brief Get the status flag of ETH_MAC_ISR register. - * @param ETH_MAC_FLAG: the status flag of ETH_MAC_ISR register. - * Select one of the follwing values : - * @arg ETH_MAC_FLAG_TST : Time stamp trigger flag - * @arg ETH_MAC_FLAG_MSCT : MSC transmit flag - * @arg ETH_MAC_FLAG_MSCR : MSC receive flag - * @arg ETH_MAC_FLAG_MSC : MSC flag - * @arg ETH_MAC_FLAG_WUM : WUM flag - * @retval The current MAC bit selected status(SET or RESET). - */ -TypeState ETH_GetMACBitState(uint32_t ETH_MAC_FLAG) -{ - /* Check the ETH_MAC_FLAG status */ - if ((ETH_MAC->ISR & ETH_MAC_FLAG) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Get the interrupt flag of ETH_MAC_ISR register. - * @param ETH_MAC_INT: the interrupt flag of ETH_MAC_ISR register. - * Select one of the follwing values : - * @arg ETH_MAC_INT_TST : Time stamp trigger interrupt - * @arg ETH_MAC_INT_MSCT : MSC transmit interrupt - * @arg ETH_MAC_INT_MSCR : MSC receive interrupt - * @arg ETH_MAC_INT_MSC : MSC interrupt - * @arg ETH_MAC_INT_WUM : WUM interrupt - * @retval The current MAC interrupt bit selected status(SET or RESET). - */ -TypeState ETH_GetMACIntBitState(uint32_t ETH_MAC_INT) -{ - /* Check the ETH_MAC_INT status */ - if ((ETH_MAC->ISR & ETH_MAC_INT) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Enable or disable the ETH_MAC_INT control bit. - * @param ETH_MAC_INT: the interrupt bit flag. - * Select one of the follwing values : - * @arg ETH_MAC_INT_TST : Time stamp trigger interrupt - * @arg ETH_MAC_INT_WUM : WUM interrupt - * @param NewValue: new value of the ETH_MAC_INT value. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MACINTConfig(uint32_t ETH_MAC_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the MAC interrupt */ - ETH_MAC->IMR &= (~(uint32_t)ETH_MAC_INT); - } else { - /* Disable the MAC interrupt */ - ETH_MAC->IMR |= ETH_MAC_INT; - } -} - -/** - * @brief Set the MAC address to MAC address register selected. - * @param addr: The MAC address register to selected. - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESS0 : MAC Address0 - * @arg ETH_MAC_ADDRESS1 : MAC Address1 - * @arg ETH_MAC_ADDRESS2 : MAC Address2 - * @arg ETH_MAC_ADDRESS3 : MAC Address3 - * @param buf: Pointer to application MAC address buffer(6 bytes). - * @retval None - */ -void ETH_SetMACAddress(uint32_t addr, uint8_t *buf) -{ - uint32_t temp; - - temp = ((uint32_t)buf[5] << 8) | (uint32_t)buf[4]; - /* Set the selectecd MAC address high register */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) = temp; - temp = ((uint32_t)buf[3] << 24) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[1] << 8) | buf[0]; - - /* Set the selectecd MAC address low register */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_LBASE + addr)) = temp; -} - -/** - * @brief Get the MAC address from MAC address register selected. - * @param addr: The MAC addres to selected. - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESS0 : MAC Address0 - * @arg ETH_MAC_ADDRESS1 : MAC Address1 - * @arg ETH_MAC_ADDRESS2 : MAC Address2 - * @arg ETH_MAC_ADDRESS3 : MAC Address3 - * @param buf: Pointer to application MAC address buffer(6 bytes). - * @retval None - */ -void ETH_GetMACAddress(uint32_t addr, uint8_t *buf) -{ - uint32_t temp; - - /* Get the selectecd MAC address high register */ - temp = (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)); - - buf[5] = ((temp >> 8) & (uint8_t)0xFF); - buf[4] = (temp & (uint8_t)0xFF); - /* Get the selectecd MAC address low register */ - temp = (*(__IO uint32_t *)(ETH_MAC_ADDR_LBASE + addr)); - buf[3] = ((temp >> 24) & (uint8_t)0xFF); - buf[2] = ((temp >> 16) & (uint8_t)0xFF); - buf[1] = ((temp >> 8) & (uint8_t)0xFF); - buf[0] = (temp & (uint8_t)0xFF); -} - -/** - * @brief Enable or disable the Address perfect filtering. - * @param addr: the MAC address register selected for prfect filtering. - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESS1 : MAC Address1 - * @arg ETH_MAC_ADDRESS2 : MAC Address2 - * @arg ETH_MAC_ADDRESS3 : MAC Address3 - * @param NewValue: new value of the MAC address register selected for perfect filtering. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MACAddressPerfectFilter_Enable(uint32_t addr, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the perfect filtering to the MAC address register selected */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) |= ETH_MAC_A1HR_AFE; - } else { - /* Disable the perfect filtering to the MAC address register selected */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) &= (~(uint32_t)ETH_MAC_A1HR_AFE); - } -} - -/** - * @brief Set the selected MAC address filter type mode. - * @param addr: the MAC address to be used for filtering. - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESS1 : MAC Address1 - * @arg ETH_MAC_ADDRESS2 : MAC Address2 - * @arg ETH_MAC_ADDRESS3 : MAC Address3 - * @param Filterfield: the mode of receiving field for comparaison - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESSFILTER_SA : Compare with the SA fields of the received frame. - * @arg ETH_MAC_ADDRESSFILTER_DA : Compare with the DA fields of the received frame. - * @retval None - */ -void ETH_MACAddressFilterConfig(uint32_t addr, uint32_t Filterfield) -{ - if (Filterfield != ETH_MAC_ADDRESSFILTER_DA) { - /* Compare with the SA fields of the received frame. */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) |= ETH_MAC_A1HR_SAF; - } else { - /* compare with the DA fields of the received frame. */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) &= (~(uint32_t)ETH_MAC_A1HR_SAF); - } -} - -/** - * @brief Set the selected MAC address filter maskbyte. - * @param addr: the MAC address to be used for filtering - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESS1 : MAC Address1 - * @arg ETH_MAC_ADDRESS2 : MAC Address2 - * @arg ETH_MAC_ADDRESS3 : MAC Address3 - * @param addrmask: the address bytes be selected for address filtering comparaison - * Select one of the follwing values : - * @arg ETH_MAC_ADDRESSMASK_BYTE6 : Mask MAC Address high register bits [15:8]. - * @arg ETH_MAC_ADDRESSMASK_BYTE5 : Mask MAC Address high register bits [7:0]. - * @arg ETH_MAC_ADDRESSMASK_BYTE4 : Mask MAC Address low register bits [31:24]. - * @arg ETH_MAC_ADDRESSMASK_BYTE3 : Mask MAC Address low register bits [23:16]. - * @arg ETH_MAC_ADDRESSMASK_BYTE2 : Mask MAC Address low register bits [15:8]. - * @arg ETH_MAC_ADDRESSMASK_BYTE1 : Mask MAC Address low register bits [7:0]. - * @retval None - */ -void ETH_MACAddressFilterMaskBytesConfig(uint32_t addr, uint32_t addrmask) -{ - /* Clear the MB bit of selected MAC address */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) &= (~(uint32_t)ETH_MAC_A1HR_MB); - /* Set the mask bytes of selected Filetr */ - (*(__IO uint32_t *)(ETH_MAC_ADDR_HBASE + addr)) |= addrmask; -} - -/* DMA Tx/Rx Desciptors */ - -/** - * @brief Initialize the DMA Tx descriptors's parameters in chain mode. - * @param DMATxDescTab: Pointer to the first Tx descriptor table - * @param pTxBuff: Pointer to the first TxBuffer table - * @param TxBuffCnt: the used Tx desc num in the table - * @retval None - */ -void ETH_DMATxDescChainModeInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *pTxBuff, uint32_t TxBuffCnt) -{ - uint32_t num = 0; - ETH_DMADESCTypeDef *DMATxDesc; - - DMACurrentTxDesc = DMATxDescTab; - /* Configuration each DMATxDesc descriptor */ - for (num = 0; num < TxBuffCnt; num++) { - /* Get the pointer to the next descriptor of the Tx Desc table */ - DMATxDesc = DMATxDescTab + num; - /* Set TCH bit with desc status */ - DMATxDesc->Status = ETH_DMATXDESC_TCHM; - - /* Set Buffer1 address pointer to application buffer */ - DMATxDesc->Buffer1Addr = (uint32_t)(&pTxBuff[num * ETH_MAX_FRAME_SIZE]); - - if (num < (TxBuffCnt - 1)) { - /* Buffer2NextDescAddr equal to next descriptor address in the Tx Desc table */ - DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab + num + 1); - } else { - /* When it is the last descriptor, Buffer2NextDescAddr equal to first descriptor address in the Tx Desc table */ - DMATxDesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab; - } - } - ETH_DMA->TDTAR = (uint32_t) DMATxDescTab; -} - -/** - * @brief Initialize the DMA Tx descriptors's parameters in ring mode. - * @param DMATxDescTab: Pointer to the first Tx descriptor table - * @param pTxBuff1: Pointer to the first TxBuffer1 table - * @param pTxBuff2: Pointer to the first TxBuffer2 table - * @param TxBuffCnt: the used Tx desc num in the table - * @retval None - */ -void ETH_DMATxDescRingModeInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *pTxBuff1, uint8_t *pTxBuff2, uint32_t TxBuffCnt) -{ - uint32_t num = 0; - ETH_DMADESCTypeDef *DMATxDesc; - - DMACurrentTxDesc = DMATxDescTab; - /* Configuration each DMATxDesc descriptor */ - for (num = 0; num < TxBuffCnt; num++) { - /* Get the pointer to the next descriptor of the Tx Desc table */ - DMATxDesc = DMATxDescTab + num; - /* Set Buffer1 address pointer to application buffer1 */ - DMATxDesc->Buffer1Addr = (uint32_t)(&pTxBuff1[num * ETH_MAX_FRAME_SIZE]); - - /* Set Buffer2 address pointer to application buffer2 */ - DMATxDesc->Buffer2NextDescAddr = (uint32_t)(&pTxBuff2[num * ETH_MAX_FRAME_SIZE]); - - if (num == (TxBuffCnt - 1)) { - /* Set ETH_DMATXDESC_TERM bit as transmitting End */ - DMATxDesc->Status = ETH_DMATXDESC_TERM; - } - } - ETH_DMA->TDTAR = (uint32_t) DMATxDescTab; -} - -/** - * @brief Get the bit flag of ETHERNET DMA Tx Desc. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param ETH_DMATxDescFlag: the flag of Tx descriptor status. - * Select one of the follwing values : - * @arg ETH_DMATXDESC_BUSY : BUSY bit: descriptor is owned by DMA engine - * @arg ETH_DMATXDESC_INTC : Interrupt on completetion - * @arg ETH_DMATXDESC_LSG : Last Segment - * @arg ETH_DMATXDESC_FSG : First Segment - * @arg ETH_DMATXDESC_DCRC : Disable CRC - * @arg ETH_DMATXDESC_DPAD : Disable Pad - * @arg ETH_DMATXDESC_TTSEN : Transmit Time Stamp Enable - * @arg ETH_DMATXDESC_TERM : Transmit End of Ring - * @arg ETH_DMATXDESC_TCHM : Second Address Chained - * @arg ETH_DMATXDESC_TTMSS : Tx Time Stamp Status - * @arg ETH_DMATXDESC_IPHE : IP Header Error - * @arg ETH_DMATXDESC_ES : Error summary - * @arg ETH_DMATXDESC_JT : Jabber Timeout - * @arg ETH_DMATXDESC_FRMF : Frame Flushed: DMA/MTL flushed the frame due to SW flush - * @arg ETH_DMATXDESC_IPPE : IP Payload Error - * @arg ETH_DMATXDESC_LCA : Loss of Carrier: carrier lost during tramsmission - * @arg ETH_DMATXDESC_NCA : No Carrier: no carrier signal from the tranceiver - * @arg ETH_DMATXDESC_LCO : Late Collision: transmission aborted due to collision - * @arg ETH_DMATXDESC_ECO : Excessive Collision: transmission aborted after 16 collisions - * @arg ETH_DMATXDESC_VFRM : VLAN Frame - * @arg ETH_DMATXDESC_COCNT : Collision Count - * @arg ETH_DMATXDESC_EXD : Excessive Deferral - * @arg ETH_DMATXDESC_UFE : Underflow Error: late data arrival from the memory - * @arg ETH_DMATXDESC_DB : Deferred Bit - * @retval The current ETH_DMATxDescFlag selected bit status(SET or RESET). - */ -TypeState ETH_GetDMATxDescBitState(ETH_DMADESCTypeDef *DMATxDesc, uint32_t ETH_DMATxDescFlag) -{ - if ((DMATxDesc->Status & ETH_DMATxDescFlag) != (uint32_t)RESET) { - /* ETH_DMATxDescFlag is set */ - return SET; - } else { - /* ETH_DMATxDescFlag is reset */ - return RESET; - } -} - -/** - * @brief Get the DMA Tx Desc collision count. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @retval The value of Transmit descriptor collision counter. - */ -uint32_t ETH_GetDMATxDescCollisionCount(ETH_DMADESCTypeDef *DMATxDesc) -{ - return ((DMATxDesc->Status & ETH_DMATXDESC_COCNT) >> ETH_DMATXDESC_COLLISION_COUNTSHIFT); -} - -/** - * @brief Set the DMA Tx Desc Busy bit for DMA or CPU. - * @param DMATxDesc: Pointer on a Transmit descriptor - * @retval None - */ -void ETH_SetDMATxDescBusyBit(ETH_DMADESCTypeDef *DMATxDesc) -{ - DMATxDesc->Status |= ETH_DMATXDESC_BUSY; -} - -/** - * @brief Enable or disable the ETH_DMATXDESC_INTC control bit. - * @param DMATxDesc: Pointer to a Tx descriptor - * @param NewValue: new value of the ETH_DMATXDESC_INTC control bit. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATxDescTransmitINTConfig(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMA Tx Desc after the frame has been transmitted Set Transmit interrupt */ - DMATxDesc->Status |= ETH_DMATXDESC_INTC; - } else { - /* Disable the DMA Tx Desc after the frame has been transmitted Set Transmit interrupt */ - DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_INTC); - } -} - -/** - * @brief Enable or disable the DMATxDesc_FrameSegment control bit. - * @param DMATxDesc: Pointer to a Tx descriptor - * @param DMATxDesc_Segment: the actual Tx buffer contain first or last segment. - * Select one of the follwing values : - * @arg ETH_DMATXDESC_LASTSEGMENT : current Tx desc selected contain last segment - * @arg ETH_DMATXDESC_FIRSTSEGMENT : current Tx desc selected contain first segment - * @retval None - */ -void ETH_SetDMATxDescFrameSegment(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_Segment) -{ - DMATxDesc->Status |= DMATxDesc_Segment; -} - -/** - * @brief Set the DMA Tx Desc Checksum Insertion mode. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param DMATxDesc_Checksum: the type of DMA Tx descriptor checksum insertion. - * Select one of the follwing values : - * @arg ETH_DMATXDESC_CHECKSUMDISABLE : Checksum bypass - * @arg ETH_DMATXDESC_CHECKSUMIPV4HEADER : IPv4 header checksum - * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT : TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present - * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL : TCP/UDP/ICMP checksum fully in hardware including pseudo header - * @retval None - */ -void ETH_SetDMATxDescChecksumInsertion(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_Checksum) -{ - DMATxDesc->Status |= DMATxDesc_Checksum; -} - -/** - * @brief Enable or disable the DMA Tx descriptor CRC function. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param NewValue: new value of the DMA Tx descriptor CRC function. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATxDescCRC_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMATxDesc CRC */ - DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_DCRC); - } else { - /* Disable the DMATxDesc CRC */ - DMATxDesc->Status |= ETH_DMATXDESC_DCRC; - } -} - -/** - * @brief Enable or disable the DMA Tx descriptor end of ring. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param NewValue: new value of the DMA Tx descriptor end of ring. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATxDescEndOfRing_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMATxDesc end of ring */ - DMATxDesc->Status |= ETH_DMATXDESC_TERM; - } else { - /* Disable the DMATxDesc end of ring */ - DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_TERM); - } -} - -/** - * @brief Enable or disable the DMA Tx descriptor second address chained. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param NewValue: new value of the DMA Tx descriptor second address chained. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATxDescSecondAddressChained_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMATxDesc second address chained */ - DMATxDesc->Status |= ETH_DMATXDESC_TCHM; - } else { - /* Disable the DMATxDesc second address chained */ - DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_TCHM); - } -} - -/** - * @brief Enable or disable auto padding when transmit frame shorter than 64 bytes. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param NewValue: new value of the auto padding status. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATxDescShortFramePadding_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMATxDesc short frame padding */ - DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_DPAD); - } else { - /* Disable the DMATxDesc short frame padding */ - DMATxDesc->Status |= ETH_DMATXDESC_DPAD; - } -} - -/** - * @brief Enable or disable the DMA Tx descriptor time stamp function. - * @param DMATxDesc: pointer to a DMA Tx descriptor - * @param NewValue: new value of the DMA Tx descriptor time stamp. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATxDescTimeStamp_Enable(ETH_DMADESCTypeDef *DMATxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMATxDesc time stamp */ - DMATxDesc->Status |= ETH_DMATXDESC_TTSEN; - } else { - /* Disable the DMATxDesc time stamp */ - DMATxDesc->Status &= (~(uint32_t)ETH_DMATXDESC_TTSEN); - } -} - -/** - * @brief Set the frame length by configures the DMA Tx Desc buffer1 and buffer2 sizes. - * @param DMATxDesc: Pointer to a Tx descriptor - * @param Buffer1Size: the Tx buffer1 size. - * @param Buffer2Size: the Tx buffer2 size, set to 0 indicates it is not being used. - * @retval None - */ -void ETH_SetDMATxDescBufferSize(ETH_DMADESCTypeDef *DMATxDesc, uint32_t Buffer1Size, uint32_t Buffer2Size) -{ - DMATxDesc->ControlBufferSize |= (Buffer1Size | (Buffer2Size << ETH_DMATXDESC_BUFFER2_SIZESHIFT)); -} - -/** - * @brief Initialize the DMA Rx descriptors's parameters in chain mode. - * @param DMARxDescTab: Pointer to the first Rx descriptor table - * @param pRxBuff: Pointer to the first RxBuffer table - * @param RxBuffCnt: the used Rx desc num in the table - * @retval None - */ -void ETH_DMARxDescChainModeInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *pRxBuff, uint32_t RxBuffCnt) -{ - uint32_t num = 0; - ETH_DMADESCTypeDef *DMARxDesc; - - DMACurrentRxDesc = DMARxDescTab; - /* Configuration each DMARxDesc descriptor */ - for (num = 0; num < RxBuffCnt; num++) { - /* Get the pointer to the next descriptor of the Rx Desc table */ - DMARxDesc = DMARxDescTab + num; - DMARxDesc->Status = ETH_DMARXDESC_BUSY; - - /* Set TCH bit and buffer1 size */ - DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RCHM | (uint32_t)ETH_MAX_FRAME_SIZE; - /* Set Buffer1 address pointer to application buffer */ - DMARxDesc->Buffer1Addr = (uint32_t)(&pRxBuff[num * ETH_MAX_FRAME_SIZE]); - - if (num < (RxBuffCnt - 1)) { - /* Buffer2NextDescAddr equal to next descriptor address in the Rx Desc table */ - DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab + num + 1); - } else { - /* When it is the last descriptor, Buffer2NextDescAddr equal to first descriptor address in the Rx Desc table */ - DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); - } - } - - ETH_DMA->RDTAR = (uint32_t) DMARxDescTab; -} - -/** - * @brief Initialize the DMA Rx descriptors's parameters in ring mode. - * @param DMARxDescTab: Pointer to the first Rx descriptor table - * @param pRxBuff1: Pointer to the first RxBuffer1 table - * @param pRxBuff2: Pointer to the first RxBuffer2 table - * @param RxBuffCnt: the used Rx descriptor num in the table - * @retval None - */ -void ETH_DMARxDescRingModeInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *pRxBuff1, uint8_t *pRxBuff2, uint32_t RxBuffCnt) -{ - uint32_t num = 0; - ETH_DMADESCTypeDef *DMARxDesc; - - DMACurrentRxDesc = DMARxDescTab; - /* Configuration each DMARxDesc descriptor */ - for (num = 0; num < RxBuffCnt; num++) { - /* Get the pointer to the next descriptor of the Rx Desc table */ - DMARxDesc = DMARxDescTab + num; - DMARxDesc->Status = ETH_DMARXDESC_BUSY; - DMARxDesc->ControlBufferSize = ETH_MAX_FRAME_SIZE; - /* Set Buffer1 address pointer to application buffer1 */ - DMARxDesc->Buffer1Addr = (uint32_t)(&pRxBuff1[num * ETH_MAX_FRAME_SIZE]); - - /* Set Buffer2 address pointer to application buffer2 */ - DMARxDesc->Buffer2NextDescAddr = (uint32_t)(&pRxBuff2[num * ETH_MAX_FRAME_SIZE]); - - if (num == (RxBuffCnt - 1)) { - /* Set ETH_DMARXDESC_RERR bit as Receive End */ - DMARxDesc->ControlBufferSize |= ETH_DMARXDESC_RERR; - } - } - - ETH_DMA->RDTAR = (uint32_t) DMARxDescTab; -} - -/** - * @brief Get the bit flag of ETHERNET Rx descriptor. - * @param DMARxDesc: pointer to a DMA Rx descriptor - * @param ETH_DMARxDescFlag: the flag of Rx descriptor status. - * Select one of the follwing values : - * @arg ETH_DMARXDESC_BUSY : Descriptor is owned by DMA engine - * @arg ETH_DMARXDESC_DAFF : DA Filter Fail for the rx frame - * @arg ETH_DMARXDESC_ERRS : Error summary - * @arg ETH_DMARXDESC_DERR : Desciptor error: no more descriptors for receive frame - * @arg ETH_DMARXDESC_SAFF : SA Filter Fail for the received frame - * @arg ETH_DMARXDESC_LERR : Frame size not matching with length field - * @arg ETH_DMARXDESC_OERR : Overflow Error: Frame was damaged due to buffer overflow - * @arg ETH_DMARXDESC_VTAG : VLAN Tag: received frame is a VLAN frame - * @arg ETH_DMARXDESC_FDES : First descriptor of the frame - * @arg ETH_DMARXDESC_LDES : Last descriptor of the frame - * @arg ETH_DMARXDESC_IPHCERR : IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error - * @arg ETH_DMARXDESC_LCO : Late collision occurred during reception - * @arg ETH_DMARXDESC_FRMT : Frame type - Ethernet, otherwise 802.3 - * @arg ETH_DMARXDESC_RWDT : Receive Watchdog Timeout: watchdog timer expired during reception - * @arg ETH_DMARXDESC_RERR : Receive error: error reported by MII interface - * @arg ETH_DMARXDESC_DERR : Dribble bit error: frame contains non int multiple of 8 bits - * @arg ETH_DMARXDESC_CERR : CRC error - * @arg ETH_DMARXDESC_PCERR : Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error - * @retval The current ETH_DMARxDescFlag selected bit status(SET or RESET). - */ -TypeState ETH_GetDMARxDescBitState(ETH_DMADESCTypeDef *DMARxDesc, uint32_t ETH_DMARxDescFlag) -{ - if ((DMARxDesc->Status & ETH_DMARxDescFlag) != (uint32_t)RESET) { - /* ETH_DMARxDescFlag is set */ - return SET; - } else { - /* ETH_DMARxDescFlag is reset */ - return RESET; - } -} - -/** - * @brief Set the DMA Rx Desc busy bit for DMA or CPU - * @param DMARxDesc: Pointer to a Rx descriptor - * @retval None - */ -void ETH_SetDMARxDescBusyBit(ETH_DMADESCTypeDef *DMARxDesc) -{ - DMARxDesc->Status |= ETH_DMARXDESC_BUSY; -} - -/** - * @brief Get the DMA Rx Desc frame length. - * @param DMARxDesc: pointer to a DMA Rx descriptor - * @retval Received frame length of the Rx descriptor selected. - */ -uint32_t ETH_GetDMARxDescFrameLength(ETH_DMADESCTypeDef *DMARxDesc) -{ - return ((DMARxDesc->Status & ETH_DMARXDESC_FRML) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT); -} - -/** - * @brief Enable or disable the DMA Rx descriptor receive interrupt. - * @param DMARxDesc: Pointer to a Rx descriptor - * @param NewValue: new value of the DMA Rx descriptor interrupt. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMARxDescReceiveINTConfig(ETH_DMADESCTypeDef *DMARxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMARxDesc receive interrupt */ - DMARxDesc->ControlBufferSize &= (~(uint32_t)ETH_DMARXDESC_DINTC); - } else { - /* Disable the DMARxDesc receive interrupt */ - DMARxDesc->ControlBufferSize |= ETH_DMARXDESC_DINTC; - } -} - -/** - * @brief Enable or disable the DMA Rx descriptor end of ring. - * @param DMARxDesc: pointer to a DMA Rx descriptor - * @param NewValue: new value of the DMA Rx descriptor end of ring. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMARxDescEndOfRing_Enable(ETH_DMADESCTypeDef *DMARxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMARxDesc end of ring */ - DMARxDesc->ControlBufferSize |= ETH_DMARXDESC_RERR; - } else { - /* Disable the DMARxDesc end of ring */ - DMARxDesc->ControlBufferSize &= (~(uint32_t)ETH_DMARXDESC_RERR); - } -} - -/** - * @brief Enable or disable the DMA Rx descriptor second address chained. - * @param DMARxDesc: pointer to a DMA Rx descriptor - * @param NewValue: new value of the DMA Rx descriptor second address chained. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMARxDescSecondAddressChained_Enable(ETH_DMADESCTypeDef *DMARxDesc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMARxDesc second address chained */ - DMARxDesc->ControlBufferSize |= ETH_DMARXDESC_RCHM; - } else { - /* Disable the DMARxDesc second address chained */ - DMARxDesc->ControlBufferSize &= (~(uint32_t)ETH_DMARXDESC_RCHM); - } -} - -/** - * @brief Get the ETHERNET DMA Rx Desc buffer size. - * @param DMARxDesc: pointer to a DMA Rx descriptor - * @param DMARxDesc_BufferSelect: the DMA Rx descriptor buffer. - * Select one of the follwing values : - * @arg ETH_DMARXDESC_BUFFER1 : DMA Rx Desc Buffer1 - * @arg ETH_DMARXDESC_BUFFER2 : DMA Rx Desc Buffer2 - * @retval The Receive descriptor selected buffer size(buffer1 or buffer2). - */ -uint32_t ETH_GetDMARxDescBufferSize(ETH_DMADESCTypeDef *DMARxDesc, uint32_t DMARxDesc_BufferSelect) -{ - if (DMARxDesc_BufferSelect != ETH_DMARXDESC_BUFFER1) { - return ((DMARxDesc->ControlBufferSize & ETH_DMARXDESC_RB2S) >> ETH_DMARXDESC_BUFFER2_SIZESHIFT); - } else { - return (DMARxDesc->ControlBufferSize & ETH_DMARXDESC_RB1S); - } -} - -/* DMA */ -/** - * @brief Resets all MAC subsystem. - * @param None - * @retval None - */ -void ETH_SoftReset(void) -{ - ETH_DMA->BCR |= ETH_DMA_BCR_SWR; -} - -/** - * @brief Get the bit flag of ETHERNET software reset. - * @param None - * @retval The current DMA Bus Mode register SWR bit status(SET or RESET). - */ -TypeState ETH_GetSoftResetStatus(void) -{ - if ((ETH_DMA->BCR & ETH_DMA_BCR_SWR) != (uint32_t)RESET) { - /* The ETH_DMA_BCR_SWR bit is set */ - return SET; - } else { - /* The ETH_DMA_BCR_SWR bit is reset */ - return RESET; - } -} - -/** - * @brief Get the bit flag of specified ETHERNET DMA. - * @param ETH_DMA_FLAG: the flag of ETHERNET DMA_STR register. - * Select one of the follwing values : - * @arg ETH_DMA_FLAG_TST : Time-stamp trigger flag - * @arg ETH_DMA_FLAG_WUM : WUM flag - * @arg ETH_DMA_FLAG_MSC : MSC flag - * @arg ETH_DMA_FLAG_DATATRANSFERERROR : Error bits 0-data buffer, 1-desc. access - * @arg ETH_DMA_FLAG_READWRITEERROR : Error bits 0-write trnsf, 1-read transfr - * @arg ETH_DMA_FLAG_ACCESSERROR : Error bits 0-Rx DMA, 1-Tx DMA - * @arg ETH_DMA_FLAG_NIS : Normal interrupt summary flag - * @arg ETH_DMA_FLAG_AIS : Abnormal interrupt summary flag - * @arg ETH_DMA_FLAG_ER : Early receive flag - * @arg ETH_DMA_FLAG_FBE : Fatal bus error flag - * @arg ETH_DMA_FLAG_ET : Early transmit flag - * @arg ETH_DMA_FLAG_RWT : Receive watchdog timeout flag - * @arg ETH_DMA_FLAG_RPS : Receive process stopped flag - * @arg ETH_DMA_FLAG_RBU : Receive buffer unavailable flag - * @arg ETH_DMA_FLAG_R : Receive flag - * @arg ETH_DMA_FLAG_TU : Underflow flag - * @arg ETH_DMA_FLAG_RO : Overflow flag - * @arg ETH_DMA_FLAG_TJT : Transmit jabber timeout flag - * @arg ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag - * @arg ETH_DMA_FLAG_TPS : Transmit process stopped flag - * @arg ETH_DMA_FLAG_T : Transmit flag - * @retval The current ETH_DMA_FLAG selected bit status(SET or RESET). - */ -TypeState ETH_GetDMABitState(uint32_t ETH_DMA_FLAG) -{ - if ((ETH_DMA->STR & ETH_DMA_FLAG) != (uint32_t)RESET) { - /* ETH_DMA_FLAG is set */ - return SET; - } else { - /* ETH_DMA_FLAG is reset */ - return RESET; - } -} - -/** - * @brief Clear the ETHERNET¡¯s DMA bit flag. - * @param ETH_DMA_FLAG: the flag of ETH_DMA_STR register to clear. - * Select one of the follwing values : - * @arg ETH_DMA_FLAG_NIS : Normal interrupt summary flag - * @arg ETH_DMA_FLAG_AIS : Abnormal interrupt summary flag - * @arg ETH_DMA_FLAG_ER : Early receive flag - * @arg ETH_DMA_FLAG_FBE : Fatal bus error flag - * @arg ETH_DMA_FLAG_ETI : Early transmit flag - * @arg ETH_DMA_FLAG_RWT : Receive watchdog timeout flag - * @arg ETH_DMA_FLAG_RPS : Receive process stopped flag - * @arg ETH_DMA_FLAG_RBU : Receive buffer unavailable flag - * @arg ETH_DMA_FLAG_R : Receive flag - * @arg ETH_DMA_FLAG_TU : Transmit Underflow flag - * @arg ETH_DMA_FLAG_RO : Receive Overflow flag - * @arg ETH_DMA_FLAG_TJT : Transmit jabber timeout flag - * @arg ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag - * @arg ETH_DMA_FLAG_TPS : Transmit process stopped flag - * @arg ETH_DMA_FLAG_T : Transmit flag - * @retval None - */ -void ETH_DMAClearBitState(uint32_t ETH_DMA_FLAG) -{ - ETH_DMA->STR = (uint32_t) ETH_DMA_FLAG; -} - -/** - * @brief Get the bit flag of DMA interrupt. - * @param ETH_DMA_INT: the interrupt source flag of ETHERNET DMA_STR register. - * Select one of the follwing values : - * @arg ETH_DMA_INT_TST : Time-stamp trigger interrupt - * @arg ETH_DMA_INT_WUM : WUM interrupt - * @arg ETH_DMA_INT_MSC : MSC interrupt - * @arg ETH_DMA_INT_NIS : Normal interrupt summary - * @arg ETH_DMA_INT_AIS : Abnormal interrupt summary - * @arg ETH_DMA_INT_ER : Early receive interrupt - * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt - * @arg ETH_DMA_INT_ET : Early transmit interrupt - * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt - * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt - * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt - * @arg ETH_DMA_INT_R : Receive interrupt - * @arg ETH_DMA_INT_TU : Underflow interrupt - * @arg ETH_DMA_INT_RO : Overflow interrupt - * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt - * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt - * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt - * @arg ETH_DMA_INT_T : Transmit interrupt - * @retval The current ETH_DMA_INT selected bit status(SET or RESET). - */ -TypeState ETH_GetDMAIntBitState(uint32_t ETH_DMA_INT) -{ - if ((ETH_DMA->STR & ETH_DMA_INT) != (uint32_t)RESET) { - /* ETH_DMA_INT is set */ - return SET; - } else { - /* ETH_DMA_INT is reset */ - return RESET; - } -} - -/** - * @brief Clear the ETHERNET¡¯s DMA IT bit flag. - * @param ETH_DMA_INT: the interrupt source flag of ETH_DMA_STR register to clear. - * Select one of the follwing values : - * @arg ETH_DMA_INT_NIS : Normal interrupt summary - * @arg ETH_DMA_INT_AIS : Abnormal interrupt summary - * @arg ETH_DMA_INT_ER : Early receive interrupt - * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt - * @arg ETH_DMA_INT_ETI : Early transmit interrupt - * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt - * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt - * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt - * @arg ETH_DMA_INT_R : Receive interrupt - * @arg ETH_DMA_INT_TU : Transmit Underflow interrupt - * @arg ETH_DMA_INT_RO : Receive Overflow interrupt - * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt - * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt - * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt - * @arg ETH_DMA_INT_T : Transmit interrupt - * @retval None - */ -void ETH_DMAClearIntBitState(uint32_t ETH_DMA_INT) -{ - ETH_DMA->STR = (uint32_t) ETH_DMA_INT; -} - -/** - * @brief Get the DMA Transmit Process State. - * @param None - * @retval The current DMA Transmit Process State: - * Select one of the follwing values : - * - ETH_DMA_TransmitProcess_Stopped : Stopped - Reset or Stop Tx Command issued - * - ETH_DMA_TransmitProcess_Fetching : Running - fetching the Tx descriptor - * - ETH_DMA_TransmitProcess_Waiting : Running - waiting for status - * - ETH_DMA_TransmitProcess_Reading : unning - reading the data from host memory - * - ETH_DMA_TransmitProcess_Suspended : Suspended - Tx Desciptor unavailabe - * - ETH_DMA_TransmitProcess_Closing : Running - closing Rx descriptor - */ -uint32_t ETH_GetTransmitProcessState(void) -{ - return ((uint32_t)(ETH_DMA->STR & ETH_DMA_STR_TS)); -} - -/** - * @brief Get the DMA Receive Process State. - * @param None - * @retval The current DMA Receive Process State: - * Select one of the follwing values : - * - ETH_DMA_ReceiveProcess_Stopped : Stopped - Reset or Stop Rx Command issued - * - ETH_DMA_ReceiveProcess_Fetching : Running - fetching the Rx descriptor - * - ETH_DMA_ReceiveProcess_Waiting : Running - waiting for packet - * - ETH_DMA_ReceiveProcess_Suspended : Suspended - Rx Desciptor unavailable - * - ETH_DMA_ReceiveProcess_Closing : Running - closing descriptor - * - ETH_DMA_ReceiveProcess_Queuing : Running - queuing the recieve frame into host memory - */ -uint32_t ETH_GetReceiveProcessState(void) -{ - return ((uint32_t)(ETH_DMA->STR & ETH_DMA_STR_RS)); -} - -/** - * @brief Flush the ETHERNET transmit FIFO. - * @param None - * @retval None - */ -void ETH_CleanTransmitFIFO(void) -{ - /* Set the FTF bit for Flushing Transmit FIFO */ - ETH_DMA->CTLR |= ETH_DMA_CTLR_FTF; -} - -/** - * @brief Get the bit flag of ETHERNET transmit FIFO. - * @param None - * @retval The current ETHERNET flush transmit FIFO bit status(SET or RESET). - */ -TypeState ETH_GetFlushTransmitFIFOStatus(void) -{ - if ((ETH_DMA->CTLR & ETH_DMA_CTLR_FTF) != (uint32_t)RESET) { - /* Flush transmit FIFO bit is set */ - return SET; - } else { - /* Flush transmit FIFO bit is reset */ - return RESET; - } -} - -/** - * @brief Enable or disable the DMA transmission function. - * @param NewValue: new value of the DMA transmission status. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMATransmission_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Set the STE bit for Enable the DMA transmission */ - ETH_DMA->CTLR |= ETH_DMA_CTLR_STE; - } else { - /* Reset the STE bit for Disable the DMA transmission */ - ETH_DMA->CTLR &= ~ETH_DMA_CTLR_STE; - } -} - -/** - * @brief Enable or disable the DMA reception function. - * @param NewValue: new value of the DMA reception status. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMAReception_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable DMA reception */ - ETH_DMA->CTLR |= ETH_DMA_CTLR_SRE; - } else { - /* Disable DMA reception */ - ETH_DMA->CTLR &= ~ETH_DMA_CTLR_SRE; - } -} - -/** - * @brief Enable or disable the ETH_DMA_INT control bit. - * @param ETH_DMA_INT: the interrupt source flag of ETH_DMA_IER register. - * Select one of the follwing values : - * @arg ETH_DMA_INT_NIS : Normal interrupt summary - * @arg ETH_DMA_INT_AIS : Abnormal interrupt summary - * @arg ETH_DMA_INT_ER : Early receive interrupt - * @arg ETH_DMA_INT_FBE : Fatal bus error interrupt - * @arg ETH_DMA_INT_ET : Early transmit interrupt - * @arg ETH_DMA_INT_RWT : Receive watchdog timeout interrupt - * @arg ETH_DMA_INT_RPS : Receive process stopped interrupt - * @arg ETH_DMA_INT_RBU : Receive buffer unavailable interrupt - * @arg ETH_DMA_INT_R : Receive interrupt - * @arg ETH_DMA_INT_TU : Underflow interrupt - * @arg ETH_DMA_INT_RO : Overflow interrupt - * @arg ETH_DMA_INT_TJT : Transmit jabber timeout interrupt - * @arg ETH_DMA_INT_TBU : Transmit buffer unavailable interrupt - * @arg ETH_DMA_INT_TPS : Transmit process stopped interrupt - * @arg ETH_DMA_INT_T : Transmit interrupt - * @param NewValue: new value of the DMA interrupts. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_DMAINTConfig(uint32_t ETH_DMA_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_DMA_INT control bit */ - ETH_DMA->IER |= ETH_DMA_INT; - } else { - /* Disable the ETH_DMA_INT control bit */ - ETH_DMA->IER &= (~(uint32_t)ETH_DMA_INT); - } -} - -/** - * @brief Get the bit flag of ETHERNET DMA overflow. - * @param ETH_DMA_Overflow: the DMA overflow flag of ETHERNET DMA_MFBOCNT register. - * Select one of the follwing values : - * @arg ETH_DMA_OVERFLOW_RXFIFOCOUNTER : Overflow for FIFO Overflow Counter - * @arg ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER : Overflow for Missed Frame Counter - * @retval The current ETHERNET DMA overflow Flag selected bit status(SET or RESET). - */ -TypeState ETH_GetDMAOverflowStatus(uint32_t ETH_DMA_Overflow) -{ - if ((ETH_DMA->MFBOCNT & ETH_DMA_Overflow) != (uint32_t)RESET) { - /* DMA overflow Flag is set */ - return SET; - } else { - /* DMA overflow Flag is reset */ - return RESET; - } -} - -/** - * @brief Get the DMA Rx value of overflow Missed Frame Counter. - * @param None - * @retval The ETH_DMA_MFBOCNT register MFA bit value. - */ -uint32_t ETH_GetRxOverflowMissedFrameCounter(void) -{ - return ((uint32_t)((ETH_DMA->MFBOCNT & ETH_DMA_MFBOCNT_MSFA) >> ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT)); -} - -/** - * @brief Get the DMA value of Buffer unavailable Missed Frame Counter. - * @param None - * @retval The ETH_DMA_MFBOCNT register MFC bit value. - */ -uint32_t ETH_GetBufferUnavailableMissedFrameCounter(void) -{ - return ((uint32_t)(ETH_DMA->MFBOCNT) & ETH_DMA_MFBOCNT_MSFC); -} - -/** - * @brief Get the DMA value of the current Tx desc start address. - * @param None - * @retval The ETH_DMA_CTDAR register value. - */ -uint32_t ETH_GetCurrentTxDescStartAddress(void) -{ - return ((uint32_t)(ETH_DMA->CTDAR)); -} - -/** - * @brief Get the DMA value of the current Rx desc start address. - * @param None - * @retval The ETH_DMA_CRDAR register value. - */ -uint32_t ETH_GetCurrentRxDescStartAddress(void) -{ - return ((uint32_t)(ETH_DMA->CRDAR)); -} - -/** - * @brief Get the DMA value of the current Tx buffer address. - * @param None - * @retval The ETH_DMA_CTBAR register value. - */ -uint32_t ETH_GetCurrentTxBufferAddress(void) -{ - return ((uint32_t)(ETH_DMA->CTBAR)); -} - -/** - * @brief Get the DMA value of the current Rx buffer address. - * @param None - * @retval The ETH_DMA_CRBAR register value. - */ -uint32_t ETH_GetCurrentRxBufferAddress(void) -{ - return ((uint32_t)(ETH_DMA->CRBAR)); -} - -/** - * @brief Poll the DMA Transmission enable by writing any value to the ETH_DMA_TPER register. - * This will make the DMA to resume transmission. - * @param None - * @retval None. - */ -void ETH_ResumeDMATransmission(void) -{ - ETH_DMA->TPER = 0; -} - -/** - * @brief Poll the DMA Transmission enable by writing any value to the ETH_DMA_RPER register. - * This will make the DMA to resume reception. - * @param None - * @retval None. - */ -void ETH_ResumeDMAReception(void) -{ - ETH_DMA->RPER = 0; -} - -/* WUM */ -/** - * @brief Reset Wakeup frame filter register pointer. - * @param None - * @retval None - */ -void ETH_WakeUpFrameFilterRegisterReset(void) -{ - /* Set WUFFRPR bit for Reseting the ETH_MAC_RWFFR register pointer to 0 */ - ETH_MAC->WUMR |= ETH_MAC_WUMR_WUFFRPR; -} - -/** - * @brief Set the remote wakeup frame registers. - * @param pBuffer: Pointer to remote WakeUp Frame Filter Register buffer data (8 words). - * @retval None - */ -void ETH_SetWakeUpFrameFilterRegister(uint32_t *pBuffer) -{ - uint32_t num = 0; - - /* Configuration ETH_MAC_RWFFR register */ - for (num = 0; num < ETH_WAKEUP_REGISTER_LENGTH; num++) { - ETH_MAC->RWFFR = pBuffer[num]; - } -} - -/** - * @brief Enable or disable ETH_MAC_WUMR_GU control bit. - * @param NewValue: new value of the MAC Global Unicast Wake-Up. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_GlobalUnicastWakeUp_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_MAC_WUMR_GU control bit */ - ETH_MAC->WUMR |= ETH_MAC_WUMR_GU; - } else { - /* Disable the ETH_MAC_WUMR_GU control bit */ - ETH_MAC->WUMR &= ~ETH_MAC_WUMR_GU; - } -} - -/** - * @brief Get the bit flag of the WUM. - * @param ETH_WUM_FLAG: the flag of ETH_MAC_WUMR register. - * Select one of the follwing values : - * @arg ETH_WUM_FLAG_WUFFRPR : Wake-Up Frame Filter Register Poniter Reset - * @arg ETH_WUM_FLAG_WUFR : Wake-Up Frame Received - * @arg ETH_WUM_FLAG_MPKR : Magic Packet Received - * @retval The current ETHERNET WUM Flag selected bit status(SET or RESET). - */ -TypeState ETH_GetWUMBitState(uint32_t ETH_WUM_FLAG) -{ - if ((ETH_MAC->WUMR & ETH_WUM_FLAG) != (uint32_t)RESET) { - /* WUM Flag is set */ - return SET; - } else { - /* WUM Flag is reset */ - return RESET; - } -} - -/** - * @brief Enable or disable the ETH_MAC_WUMR_WFEN control bit. - * @param NewValue: new value of the ETH_MAC_WUMR_WFEN bit. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_WakeUpFrameDetection_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Active the MAC Wake-Up Frame Detection */ - ETH_MAC->WUMR |= ETH_MAC_WUMR_WFEN; - } else { - /* Deactive the MAC Wake-Up Frame Detection */ - ETH_MAC->WUMR &= ~ETH_MAC_WUMR_WFEN; - } -} - -/** - * @brief Enable or disable the ETH_MAC_WUMR_MPEN control bit. - * @param NewValue: new value of the ETH_MAC_WUMR_MPEN bit. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MagicPacketDetection_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_MAC_WUMR_MPEN control bit */ - ETH_MAC->WUMR |= ETH_MAC_WUMR_MPEN; - } else { - /* Disable the ETH_MAC_WUMR_MPEN control bit */ - ETH_MAC->WUMR &= ~ETH_MAC_WUMR_MPEN; - } -} - -/** - * @brief Enable or disable the ETH_MAC_WUMR_PWD control bit. - * @param NewValue: new value of the ETH_MAC_WUMR_PWD bit. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_PowerDown_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_MAC_WUMR_PWD control bit */ - ETH_MAC->WUMR |= ETH_MAC_WUMR_PWD; - } else { - /* Disable the ETH_MAC_WUMR_PWD control bit */ - ETH_MAC->WUMR &= ~ETH_MAC_WUMR_PWD; - } -} - -/* MSC */ -/** - * @brief Enable or disable the ETH_MSC_CTLR_MCFZ control bit. - * @param NewValue: new value of the MSC Counter Freeze. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MSCCounterFreeze_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_MSC_CTLR_MCFZ control bit */ - ETH_MSC->CTLR |= ETH_MSC_CTLR_MCFZ; - } else { - /* Disable the ETH_MSC_CTLR_MCFZ control bit */ - ETH_MSC->CTLR &= ~ETH_MSC_CTLR_MCFZ; - } -} - -/** - * @brief Enable or disable the ETH_MSC_CTLR_RTOR control bit. - * @param NewValue: new value of the MSC Reset On Read. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MSCResetOnRead_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_MSC_CTLR_RTOR control bit */ - ETH_MSC->CTLR |= ETH_MSC_CTLR_RTOR; - } else { - /* Disable the ETH_MSC_CTLR_RTOR control bit */ - ETH_MSC->CTLR &= ~ETH_MSC_CTLR_RTOR; - } -} - -/** - * @brief Enable or disable the ETH_MSC_CTLR_CTSR control bit. - * @param NewValue: new value of the ETH_MSC_CTLR_CTSR bit. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MSCCounterRollover_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_MSC_CTLR_CTSR control bit */ - ETH_MSC->CTLR &= ~ETH_MSC_CTLR_CTSR; - } else { - /* Disable the ETH_MSC_CTLR_CTSR control bit */ - ETH_MSC->CTLR |= ETH_MSC_CTLR_CTSR; - } -} - -/** - * @brief Resets the MSC Counters. - * @param None - * @retval None - */ -void ETH_MSCCountersReset(void) -{ - ETH_MSC->CTLR |= ETH_MSC_CTLR_CTR; -} - -/** - * @brief Enable or disable the ETH_MSC_INT control bit. - * @param ETH_MSC_INT: the MSC interrupt sources flag of MSC_RIMR and MSC_TIMR. - * This parameter can be any combination of Tx interrupt or - * any combination of Rx interrupt (but not both)of the following values: - * @arg ETH_MSC_INT_TGF : When Tx good frame counter reaches half the maximum value - * @arg ETH_MSC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value - * @arg ETH_MSC_INT_TGFSC : When Tx good single col counter reaches half the maximum value - * @arg ETH_MSC_INT_RGUF : When Rx good unicast frames counter reaches half the maximum value - * @arg ETH_MSC_INT_RFAE : When Rx alignment error counter reaches half the maximum value - * @arg ETH_MSC_INT_RFCE : When Rx crc error counter reaches half the maximum value - * @param NewValue: new value of the MSC interrupt sources flag of MSC_RIMR and MSC_TIMR. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_MSCINTConfig(uint32_t ETH_MSC_INT, TypeState NewValue) -{ - if ((ETH_MSC_INT & (uint32_t)0x10000000) != (uint32_t)RESET) { - /* Get MSC interrupts souce bit position */ - ETH_MSC_INT &= 0xEFFFFFFF; - - /* MSC Rx interrupts souce bit selected */ - if (NewValue != DISABLE) { - /* Enable the Rx ETH_MSC_INT control bit */ - ETH_MSC->RIMR &= (~(uint32_t)ETH_MSC_INT); - } else { - /* Disable the Rx ETH_MSC_INT control bit */ - ETH_MSC->RIMR |= ETH_MSC_INT; - } - } else { - /* MSC Tx interrupts souce bit selected */ - if (NewValue != DISABLE) { - /* Enable the Tx ETH_MSC_INT control bit */ - ETH_MSC->TIMR &= (~(uint32_t)ETH_MSC_INT); - } else { - /* Disable the Tx ETH_MSC_INT control bit */ - ETH_MSC->TIMR |= ETH_MSC_INT; - } - } -} - -/** - * @brief Get the bit flag of MSC INT. - * @param ETH_MSC_INT: the MSC interrupt flag of ETH_MSC_RISR and ETH_MSC_TISR. - * Select one of the follwing values : - * @arg ETH_MSC_INT_TGF: When Tx good frame counter reaches half the maximum value - * @arg ETH_MSC_INT_TGFMSC: When Tx good multi col counter reaches half the maximum value - * @arg ETH_MSC_INT_TGFSC: When Tx good single col counter reaches half the maximum value - * @arg ETH_MSC_INT_RGUF: When Rx good unicast frames counter reaches half the maximum value - * @arg ETH_MSC_INT_RFAE : When Rx alignment error counter reaches half the maximum value - * @arg ETH_MSC_INT_RFCE : When Rx crc error counter reaches half the maximum value - * @retval The current ETHERNET MSC IT selected bit status(SET or RESET). - */ -TypeState ETH_GetMSCINTStatus(uint32_t ETH_MSC_INT) -{ - if ((ETH_MSC_INT & (uint32_t)0x10000000) != (uint32_t)RESET) { - /* Check if the MSC interrupt flag of ETH_MSC_RISR selected is enabled and occured */ - if ((((ETH_MSC->RISR & ETH_MSC_INT) != (uint32_t)RESET)) && ((ETH_MSC->RIMR & ETH_MSC_INT) != (uint32_t)RESET)) { - /* The MSC interrupt flag of ETH_MSC_RISR is set */ - return SET; - } else { - /* The MSC interrupt flag of ETH_MSC_RISR is reset */ - return RESET; - } - } else { - /* Check if the MSC interrupt flag of ETH_MSC_TISR selected is enabled and occured */ - if ((((ETH_MSC->TISR & ETH_MSC_INT) != (uint32_t)RESET)) && ((ETH_MSC->RIMR & ETH_MSC_INT) != (uint32_t)RESET)) { - /* The MSC interrupt flag of ETH_MSC_TISR is set */ - return SET; - } else { - /* The MSC interrupt flag of ETH_MSC_TISR is reset */ - return RESET; - } - } -} - -/** - * @brief Read value of the MSC module register. - * @param ETH_MSC_Register: the MSC module register selected. - * Select one of the follwing values : - * @arg ETH_MSC_CTLR : MSC CR register - * @arg ETH_MSC_RISR : MSC RIR register - * @arg ETH_MSC_TISR : MSC TIR register - * @arg ETH_MSC_RIMR : MSC RIMR register - * @arg ETH_MSC_TIMR : MSC TIMR register - * @arg ETH_MSC_SCCNT : MSC TGFSCCR register - * @arg ETH_MSC_MSCCNT : MSC TGFMSCCR register - * @arg ETH_MSC_TGFCNT : MSC TGFCR register - * @arg ETH_MSC_RFCECNT : MSC RFCECR register - * @arg ETH_MSC_RFAECNT : MSC RFAECR register - * @arg ETH_MSC_RGUFCNT : MSC RGUFCRregister - * @retval MSC module Register selected value. - */ -uint32_t ETH_GetMSCRegister(uint32_t ETH_MSC_Register) -{ - /* Return the value of MSC module Register selected */ - return (*(__IO uint32_t *)(ETH_MAC_BASE + ETH_MSC_Register)); -} - -/* PTP */ -/** - * @brief Updated the Time Stamp Addend register value to the PTP block(used only when the system time is configured - * for Fine update mode). - * @param None - * @retval None - */ -void ETH_PTPTimeStampAddendUpdate(void) -{ - ETH_PTP->TSCTLR |= ETH_PTP_TSCTLR_TMSARU; -} - -/** - * @brief Set ETH_PTP_TSCTLR_TMSITEN bit. - * @param NewValue: new value of the MAC reception. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_PTPTimeStampIntTrigger_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable ETH_PTP_TSCTLR_TMSITEN bit */ - ETH_PTP->TSCTLR |= ETH_PTP_TSCTLR_TMSITEN; - } else { - /* Disable ETH_PTP_TSCTLR_TMSITEN bit */ - ETH_PTP->TSCTLR &= ~ETH_PTP_TSCTLR_TMSITEN; - } -} - -/** - * @brief Updated the Time Stamp Update register value to the PTP system time. - * @param NewValue: new value of the MAC reception. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_PTPTimeStampUpdate_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable PTP time stamp update */ - ETH_PTP->TSCTLR |= ETH_PTP_TSCTLR_TMSSTU; - } else { - /* Disable PTP time stamp update */ - ETH_PTP->TSCTLR &= ~ETH_PTP_TSCTLR_TMSSTU; - } -} - -/** - * @brief Initialize the PTP Time Stamp mode - * @param None - * @retval None - */ -void ETH_PTPTimeStampInit(void) -{ - ETH_PTP->TSCTLR |= ETH_PTP_TSCTLR_TMSSTI; -} - -/** - * @brief Set the PTP Time Stamp Update mode - * @param UpdateMode: the PTP Update mode selected - * Select one of the follwing values : - * @arg ETH_PTP_FINEMODE : Fine Update method - * @arg ETH_PTP_COARSEMODE : Coarse Update method - * @retval None - */ -void ETH_PTPUpdateModeConfig(uint32_t UpdateMode) -{ - if (UpdateMode != ETH_PTP_COARSEMODE) { - /* Enable the PTP Fine Update mode */ - ETH_PTP->TSCTLR |= ETH_PTP_TSCTLR_TMSFCU; - } else { - /* Disable the PTP Coarse Update mode */ - ETH_PTP->TSCTLR &= (~(uint32_t)ETH_PTP_TSCTLR_TMSFCU); - } -} - -/** - * @brief Enable or disable ETH_PTP_TSCTLR_TMSEN control bit. - * @param NewValue: new value of the ETH_PTP_TSCTLR_TMSEN control bit - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void ETH_PTPTimeStamp_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the ETH_PTP_TSCTLR_TMSEN control bit */ - ETH_PTP->TSCTLR |= ETH_PTP_TSCTLR_TMSEN; - } else { - /* Disable the ETH_PTP_TSCTLR_TMSEN control bit */ - ETH_PTP->TSCTLR &= (~(uint32_t)ETH_PTP_TSCTLR_TMSEN); - } -} - -/** - * @brief Get the bit flag of ETHERNET PTP. - * @param ETH_PTP_FLAG: the flag of PTP_TSCTLR register. - * Select one of the follwing values : - * @arg ETH_PTP_FLAG_TMSARU : Addend Register Update - * @arg ETH_PTP_FLAG_TMSITEN : Time Stamp Interrupt Trigger Enable - * @arg ETH_PTP_FLAG_TMSSTU : Time Stamp Update - * @arg ETH_PTP_FLAG_TMSSTI : Time Stamp Initialize - * @retval The current ETHERNET PTP Flag selected bit status(SET or RESET). - */ -TypeState ETH_GetPTPBitState(uint32_t ETH_PTP_FLAG) -{ - if ((ETH_PTP->TSCTLR & ETH_PTP_FLAG) != (uint32_t)RESET) { - /* ETH_PTP_FLAG is set */ - return SET; - } else { - /* ETH_PTP_FLAG is reset */ - return RESET; - } -} - -/** - * @brief Set Each HCLK cycle the system time Sub-Second Increased value. - * @param SubSecond: the PTP_SSINCR Register value. - * @retval None - */ -void ETH_SetPTPSubSecondIncrement(uint32_t SubSecond) -{ - ETH_PTP->SSINCR = SubSecond; -} - -/** - * @brief Set the system time update sign and values. - * @param Sign: the PTP Time update value sign(positive or negative). - * Select one of the follwing values : - * @arg ETH_PTP_POSITIVETIME : positive time value. - * @arg ETH_PTP_NEGATIVETIME : negative time value. - * @param Second: the PTP Time update value in second part. - * @param SubSecond: the PTP Time update value in sub-second part. - * This parameter is a 31 bit value, bit32 correspond to the sign. - * @retval None - */ -void ETH_SetPTPUpdateTimeValue(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue) -{ - /* Set the PTP Time Update High Register with second value*/ - ETH_PTP->TMSHUR = SecondValue; - - /* Set the PTP Time Update Low Register with subsecond value and sign */ - ETH_PTP->TMSLUR = Sign | SubSecondValue; -} - -/** - * @brief Set the system time Addend value(used only when the system time is configured - * for Fine update mode). - * @param add: the PTP PTP_TSACNT Register value. - * @retval None - */ -void ETH_SetPTPTimeStampAddend(uint32_t add) -{ - ETH_PTP->TSACNT = add; -} - -/** - * @brief Set the Target system Time values. - * @param HighReg_Value: the PTP Expected Time High Register value. - * @param LowReg_Value: the PTP Expected Time Low Register value. - * @retval None - */ -void ETH_SetPTPTargetTime(uint32_t HighReg_Value, uint32_t LowReg_Value) -{ - /* Set the PTP Expected Time High Register */ - ETH_PTP->ETHR = HighReg_Value; - /* Set the PTP Expected Time Low Register */ - ETH_PTP->ETLR = LowReg_Value; -} - -/** - * @brief Read the value of PTP module register . - * @param ETH_PTPRegister: the PTP module register selected. - * Select one of the follwing values : - * @arg ETH_PTP_TSCTLR : Sub-Second Increment Register - * @arg ETH_PTP_SSINCR : Sub-Second Increment Register - * @arg ETH_PTP_TMSHR : Time Stamp High Register - * @arg ETH_PTP_TMSLR : Time Stamp Low Register - * @arg ETH_PTP_TMSHUR : Time Stamp High Update Register - * @arg ETH_PTP_TMSLUR : Time Stamp Low Update Register - * @arg ETH_PTP_TSACNT : Time Stamp Addend Register - * @arg ETH_PTP_ETHR : Target Time High Register - * @arg ETH_PTP_ETLR : Target Time Low Register - * @retval ETHERNET PTP Register selected value. - */ -uint32_t ETH_GetPTPRegister(uint32_t ETH_PTPRegister) -{ - return (*(__IO uint32_t *)(ETH_MAC_BASE + ETH_PTPRegister)); -} - -/** - * @brief Initialize the DMA Tx descriptors's parameters in chain mode with PTP. - * @param DMATxDescTab: Pointer to the first Tx descriptor table - * @param DMAPTPTxDescTab: Pointer to the first PTP Tx descriptor table - * @param pTxBuff: Pointer to the first TxBuffer table - * @param TxBuffCnt: the used Tx descriptor sum in the table - * @retval None - */ -void ETH_DMAPTPTxDescChainModeInit(ETH_DMADESCTypeDef *DMATxDescTab, ETH_DMADESCTypeDef *DMAPTPTxDescTab, - uint8_t *pTxBuff, uint32_t TxBuffCnt) -{ - uint32_t num = 0; - ETH_DMADESCTypeDef *DMATxDesc; - - DMACurrentTxDesc = DMATxDescTab; - DMACurrentPTPTxDesc = DMAPTPTxDescTab; - /* Configuration each DMATxDesc descriptor */ - for (num = 0; num < TxBuffCnt; num++) { - /* Get the pointer to the next descriptor of the Tx Desc table */ - DMATxDesc = DMATxDescTab + num; - /* Set TCH bit and enable PTP with desc status */ - DMATxDesc->Status = ETH_DMATXDESC_TCHM | ETH_DMATXDESC_TTSEN; - - /* Set Buffer1 address pointer to application buffer */ - DMATxDesc->Buffer1Addr = (uint32_t)(&pTxBuff[num * ETH_MAX_FRAME_SIZE]); - - if (num < (TxBuffCnt - 1)) { - /* Buffer2NextDescAddr equal to next descriptor address in the Tx Desc table */ - DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab + num + 1); - } else { - /* When it is the last descriptor, Buffer2NextDescAddr equal to first descriptor address in the Tx Desc table */ - DMATxDesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab; - } - /* Set DMAPTPTxDescTab equal to DMATxDescTab */ - (&DMAPTPTxDescTab[num])->Buffer1Addr = DMATxDesc->Buffer1Addr; - (&DMAPTPTxDescTab[num])->Buffer2NextDescAddr = DMATxDesc->Buffer2NextDescAddr; - } - /* When it is the last PTPdescriptor, DMAPTPTxDesc status equal to the first descriptor address in the PTPTx Desc list address */ - (&DMAPTPTxDescTab[num - 1])->Status = (uint32_t) DMAPTPTxDescTab; - - ETH_DMA->TDTAR = (uint32_t) DMATxDescTab; -} - -/** - * @brief Initialize the DMA Rx descriptors's parameters in chain mode with PTP. - * @param DMARxDescTab: Pointer to the first Rx descriptor table - * @param DMAPTPRxDescTab: Pointer to the first PTP Rx descriptor table - * @param pRxBuff: Pointer to the first RxBuffer table - * @param RxBuffCnt: the used Rx descriptor sum in the table - * @retval None - */ -void ETH_DMAPTPRxDescChainModeInit(ETH_DMADESCTypeDef *DMARxDescTab, ETH_DMADESCTypeDef *DMAPTPRxDescTab, - uint8_t *pRxBuff, uint32_t RxBuffCnt) -{ - uint32_t num = 0; - ETH_DMADESCTypeDef *DMARxDesc; - - DMACurrentRxDesc = DMARxDescTab; - DMACurrentPTPRxDesc = DMAPTPRxDescTab; - /* Configuration each DMARxDesc descriptor */ - for (num = 0; num < RxBuffCnt; num++) { - /* Get the pointer to the next descriptor of the Rx Desc table */ - DMARxDesc = DMARxDescTab + num; - DMARxDesc->Status = ETH_DMARXDESC_BUSY; - - /* Set TCH bit and buffer1 size */ - DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RCHM | (uint32_t)ETH_MAX_FRAME_SIZE; - /* Set Buffer1 address pointer to application buffer */ - DMARxDesc->Buffer1Addr = (uint32_t)(&pRxBuff[num * ETH_MAX_FRAME_SIZE]); - - if (num < (RxBuffCnt - 1)) { - /* Buffer2NextDescAddr equal to next descriptor address in the Rx Desc table */ - DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab + num + 1); - } else { - /* When it is the last descriptor, Buffer2NextDescAddr equal to first descriptor address in the Rx Desc table */ - DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); - } - /* Set DMAPTPRxDescTab equal to DMARxDescTab */ - (&DMAPTPRxDescTab[num])->Buffer1Addr = DMARxDesc->Buffer1Addr; - (&DMAPTPRxDescTab[num])->Buffer2NextDescAddr = DMARxDesc->Buffer2NextDescAddr; - } - /* When it is the last PTPdescriptor, DMAPTPRxDesc status equal to the first descriptor address in the PTPRx Desc table address */ - (&DMAPTPRxDescTab[num - 1])->Status = (uint32_t) DMAPTPRxDescTab; - - /* Update Receive Desciptor Table Address Register */ - ETH_DMA->RDTAR = (uint32_t) DMARxDescTab; -} - -/** - * @brief Send data with Time Stamp values of application buffer as a transmit packet. - * @param pbuf: pointer to the applicationbuffer. - * @param size: the application buffer size. - * @param PTPTxTab: Pointer to the first PTP Tx table to store Time stamp values. - * @retval The transmission with PTP result(ERROR or SUCCESS) - */ -uint32_t ETH_HandlePTPTxPkt(uint8_t *pbuf, uint16_t size, uint32_t *PTPTxTab) -{ - uint32_t offset = 0, timeout = 0; - - if ((DMACurrentTxDesc->Status & ETH_DMATXDESC_BUSY) != (uint32_t)RESET) { - /* Return ERROR: the descriptor is busy due to own by the DMA */ - return ERROR; - } - for (offset = 0; offset < size; offset++) { - (*(__IO uint8_t *)((DMACurrentPTPTxDesc->Buffer1Addr) + offset)) = (*(pbuf + offset)); - } - /* Setting the Frame Length */ - DMACurrentTxDesc->ControlBufferSize = (size & (uint32_t)0x1FFF); - /* Setting the segment of frame (ETH_DMATXDESC_LSG and ETH_DMATXDESC_FSG are SET that frame is transmitted in one descriptor) */ - DMACurrentTxDesc->Status |= ETH_DMATXDESC_LSG | ETH_DMATXDESC_FSG; - /* Enable the DMA transmission */ - DMACurrentTxDesc->Status |= ETH_DMATXDESC_BUSY; - /* Check Tx Buffer unavailable flag status */ - if ((ETH_DMA->STR & ETH_DMA_STR_TBU) != (uint32_t)RESET) { - /* Clear TBU ETHERNET DMA flag */ - ETH_DMA->STR = ETH_DMA_STR_TBU; - /* Resume DMA transmission by writing to the TPER register*/ - ETH_DMA->TPER = 0; - } - /* Wait for ETH_DMATXDESC_TTMSS flag to be set unless timeout */ - do { - timeout++; - } while (!(DMACurrentTxDesc->Status & ETH_DMATXDESC_TTMSS) && (timeout < 0xFFFF)); - /* Return ERROR due to timeout */ - if (timeout == PHY_READ_TO) { - return ERROR; - } - /* Clear the DMACurrentTxDesc status register TTSS flag */ - DMACurrentTxDesc->Status &= ~ETH_DMATXDESC_TTMSS; - *PTPTxTab++ = DMACurrentTxDesc->Buffer1Addr; - *PTPTxTab = DMACurrentTxDesc->Buffer2NextDescAddr; - /* Update the ETHERNET DMA current Tx descriptor pointer to the next Tx decriptor in DMA Tx decriptor talbe*/ - /* Chained Mode */ - if ((DMACurrentTxDesc->Status & ETH_DMATXDESC_TCHM) != (uint32_t)RESET) { - DMACurrentTxDesc = (ETH_DMADESCTypeDef *)(DMACurrentPTPTxDesc->Buffer2NextDescAddr); - if (DMACurrentPTPTxDesc->Status != 0) { - DMACurrentPTPTxDesc = (ETH_DMADESCTypeDef *)(DMACurrentPTPTxDesc->Status); - } else { - DMACurrentPTPTxDesc++; - } - } - /* Ring Mode */ - else { - if ((DMACurrentTxDesc->Status & ETH_DMATXDESC_TERM) != (uint32_t)RESET) { - DMACurrentTxDesc = (ETH_DMADESCTypeDef *)(ETH_DMA->TDTAR); - DMACurrentPTPTxDesc = (ETH_DMADESCTypeDef *)(ETH_DMA->TDTAR); - } else { - DMACurrentTxDesc = (ETH_DMADESCTypeDef *)((uint32_t)DMACurrentTxDesc + ETH_DMATXDESC_SIZE + ((ETH_DMA->BCR & ETH_DMA_BCR_DPSL) >> 2)); - DMACurrentPTPTxDesc = (ETH_DMADESCTypeDef *)((uint32_t)DMACurrentPTPTxDesc + ETH_DMATXDESC_SIZE + ((ETH_DMA->BCR & ETH_DMA_BCR_DPSL) >> 2)); - } - } - return SUCCESS; -} - -/** - * @brief Receive a packet data with Time Stamp values to application buffer. - * @param pbuf: Pointer on the application buffer. - * @param PTPRxTab: Pointer to the first PTP Rx table to store Time stamp values. - * @retval The Receive frame length with PTP(If size is equal to ERROR, the receiving unsuccessful) - */ -uint32_t ETH_HandlePTPRxPkt(uint8_t *pbuf, uint32_t *PTPRxTab) -{ - uint32_t offset = 0, size = 0; - - if ((DMACurrentRxDesc->Status & ETH_DMARXDESC_BUSY) != (uint32_t)RESET) { - /* Return ERROR: the descriptor is busy due to own by the DMA */ - return ERROR; - } - if (((DMACurrentRxDesc->Status & ETH_DMARXDESC_ERRS) == (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_LDES) != (uint32_t)RESET) && - ((DMACurrentRxDesc->Status & ETH_DMARXDESC_FDES) != (uint32_t)RESET)) { - /* Get the Frame Length exclusive CRC */ - size = ((DMACurrentRxDesc->Status & ETH_DMARXDESC_FRML) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4; - for (offset = 0; offset < size; offset++) { - (*(pbuf + offset)) = (*(__IO uint8_t *)((DMACurrentPTPRxDesc->Buffer1Addr) + offset)); - } - } else { - /* Return ERROR */ - size = ERROR; - } - /* Check Rx Buffer unavailable flag status */ - if ((ETH_DMA->STR & ETH_DMA_STR_RBU) != (uint32_t)RESET) { - /* Clear RBU ETHERNET DMA flag */ - ETH_DMA->STR = ETH_DMA_STR_RBU; - /* Resume DMA reception by writing to the RPER register*/ - ETH_DMA->RPER = 0; - } - *PTPRxTab++ = DMACurrentRxDesc->Buffer1Addr; - *PTPRxTab = DMACurrentRxDesc->Buffer2NextDescAddr; - /* Enable reception */ - DMACurrentRxDesc->Status |= ETH_DMARXDESC_BUSY; - /* Update the ETHERNET DMA current Rx descriptor pointer to the next Rx decriptor in DMA Rx decriptor talbe*/ - /* Chained Mode */ - if ((DMACurrentRxDesc->ControlBufferSize & ETH_DMARXDESC_RCHM) != (uint32_t)RESET) { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)(DMACurrentPTPRxDesc->Buffer2NextDescAddr); - if (DMACurrentPTPRxDesc->Status != 0) { - DMACurrentPTPRxDesc = (ETH_DMADESCTypeDef *)(DMACurrentPTPRxDesc->Status); - } else { - DMACurrentPTPRxDesc++; - } - } - /* Ring Mode */ - else { - if ((DMACurrentRxDesc->ControlBufferSize & ETH_DMARXDESC_RERR) != (uint32_t)RESET) { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)(ETH_DMA->RDTAR); - } else { - DMACurrentRxDesc = (ETH_DMADESCTypeDef *)((uint32_t)DMACurrentRxDesc + ETH_DMARXDESC_SIZE + ((ETH_DMA->BCR & ETH_DMA_BCR_DPSL) >> 2)); - } - } - /* Return Frame size or ERROR */ - return (size); -} - -#ifndef USE_Delay -/** - * @brief Insert a delay time. - * @param nCount: specifies the delay time length. - * @retval None - */ -static void ETH_Delay(__IO uint32_t nCount) -{ - __IO uint32_t time = 0; - - for (time = nCount; time != 0; time--) { - } -} -#endif /* USE_Delay */ -#endif /* GD32F10X_CL */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exmc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exmc.c deleted file mode 100644 index b0a93ff71a..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exmc.c +++ /dev/null @@ -1,758 +0,0 @@ -/** - ****************************************************************************** - * @brief EXMC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_exmc.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup EXMC - * @brief EXMC driver modules - * @{ - */ - -/** @defgroup EXMC_Private_Defines - * @{ - */ - -/* EXMC Bank1 SCTLRx_BAKEN and SCTLRx_NORAEN Mask */ -#define SCTLR_BAKEN_SET ((uint32_t)0x00000001) -#define SCTLR_BAKEN_RESET ((uint32_t)0x000FFFFE) - -/* EXMC Bank1 SCTLRx_NOREN Mask */ -#define SCTLR_NOREN_SET ((uint32_t)0x00000040) - - -/* EXMC Bank2/3/4 CTLRx_BAKEN Mask */ -#define CTLR_BAKEN_SET ((uint32_t)0x00000004) -#define CTLR_BAKEN_RESET ((uint32_t)0x000FFFFB) - -/* EXMC Bank2/3/4 CTLRx_ECCEN Mask */ -#define CTLR_ECCEN_SET ((uint32_t)0x00000040) -#define CTLR_ECCEN_RESET ((uint32_t)0x000FFFBF) - -/* EXMC Bank2/3/4 CTLRx_MTYPE Mask */ -#define CTLR_EMTYP_NAND ((uint32_t)0x00000008) - -/* EXMC Bank1 Register Reset mask*/ -#define BANK1_SCTLR1_RESET ((uint32_t)0x000030DB) -#define BANK1_SCTLR_RESET ((uint32_t)0x000030D2) -#define BANK1_STR_RESET ((uint32_t)0x0FFFFFFF) -#define BANK1_SWTR_RESET ((uint32_t)0x0FFFFFFF) - -/* EXMC Bank2/3 Register Reset mask*/ -#define BANK2_3_CTLR_RESET ((uint32_t)0x00000018) -#define BANK2_3_SIR_RESET ((uint32_t)0x00000040) -#define BANK2_3_COMTR_RESET ((uint32_t)0xFCFCFCFC) -#define BANK2_3_ATTR_RESET ((uint32_t)0xFCFCFCFC) - -/* EXMC Bank4 Register Reset mask*/ -#define BANK4_CTLR_RESET ((uint32_t)0x00000018) -#define BANK4_SIR_RESET ((uint32_t)0x00000000) -#define BANK4_COMTR_RESET ((uint32_t)0xFCFCFCFC) -#define BANK4_ATTR_RESET ((uint32_t)0xFCFCFCFC) -#define BANK4_IOTR_RESET ((uint32_t)0xFCFCFCFC) - -/* EXMC register bit offset */ -#define STR_AHT_OFFSET ((uint32_t)0x00000004) -#define STR_DST_OFFSET ((uint32_t)0x00000008) -#define STR_BUSLAT_OFFSET ((uint32_t)0x00000010) -#define STR_CDIV_OFFSET ((uint32_t)0x00000014) -#define STR_DLAT_OFFSET ((uint32_t)0x00000018) - -#define SWTR_AHT_OFFSET ((uint32_t)0x00000004) -#define SWTR_DST_OFFSET ((uint32_t)0x00000008) -#define SWTR_CDIV_OFFSET ((uint32_t)0x00000014) -#define SWTR_DLAT_OFFSET ((uint32_t)0x00000018) - -#define CTLR_CTR_OFFSET ((uint32_t)0x00000009) -#define CTLR_ATR_OFFSET ((uint32_t)0x0000000D) - -#define COMTR_COMWT_OFFSET ((uint32_t)0x00000008) -#define COMTR_COMHT_OFFSET ((uint32_t)0x00000010) -#define COMTR_COMHIZT_OFFSET ((uint32_t)0x00000018) - -#define ATTR_ATTWT_OFFSET ((uint32_t)0x00000008) -#define ATTR_ATTHT_OFFSET ((uint32_t)0x00000010) -#define ATTR_ATTHIZT_OFFSET ((uint32_t)0x00000018) - -#define IOTR_IOTWT_OFFSET ((uint32_t)0x00000008) -#define IOTR_IOHT_OFFSET ((uint32_t)0x00000010) -#define IOTR_IOHIZT_OFFSET ((uint32_t)0x00000018) - -#define SIR_INTEN_OFFSET ((uint32_t)0x00000003) - -/** - * @} - */ - -/** @defgroup EXMC_Private_Functions - * @{ - */ - -/** - * @brief Reset the Bank1 NOR/SRAM registers. - * @param EXMC_NORSRAMBank: specifies the Region of Bank1. - * This parameter can be one of the following values: - * @arg EXMC_BANK1_NORSRAM1: the Region1 of Bank1 - * @arg EXMC_BANK1_NORSRAM2: the Region2 of Bank1 - * @arg EXMC_BANK1_NORSRAM3: the Region3 of Bank1 - * @arg EXMC_BANK1_NORSRAM4: the Region4 of Bank1 - * @retval None - */ -void EXMC_NORSRAM_DeInit(uint32_t EXMC_NORSRAMBank) -{ - switch (EXMC_NORSRAMBank) { - case EXMC_BANK1_NORSRAM1: { - /* the Region1 of Bank1 */ - EXMC_BANK1->SCTLR1 = BANK1_SCTLR1_RESET; - EXMC_BANK1->STR1 = BANK1_STR_RESET; - EXMC_BANK1_WT->SWTR1 = BANK1_SWTR_RESET; - break; - } - case EXMC_BANK1_NORSRAM2: { - /* the Region2 of Bank1 */ - EXMC_BANK1->SCTLR2 = BANK1_SCTLR_RESET; - EXMC_BANK1->STR2 = BANK1_STR_RESET; - EXMC_BANK1_WT->SWTR2 = BANK1_SWTR_RESET; - break; - } - case EXMC_BANK1_NORSRAM3: { - /* the Region3 of Bank1 */ - EXMC_BANK1->SCTLR3 = BANK1_SCTLR_RESET; - EXMC_BANK1->STR3 = BANK1_STR_RESET; - EXMC_BANK1_WT->SWTR3 = BANK1_SWTR_RESET; - break; - } - case EXMC_BANK1_NORSRAM4: { - /* the Region4 of Bank1 */ - EXMC_BANK1->SCTLR4 = BANK1_SCTLR_RESET; - EXMC_BANK1->STR4 = BANK1_STR_RESET; - EXMC_BANK1_WT->SWTR4 = BANK1_SWTR_RESET; - break; - } - default: - break; - } -} - -/** - * @brief Reset the Bank2 or Bank3 NAND registers. - * @param EXMC_NANDBank: specifies the Bank2 or Bank3 to be used. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: Bank2 - * @arg EXMC_BANK3_NAND: Bank3 - * @retval None - */ -void EXMC_NAND_DeInit(uint32_t EXMC_NANDBank) -{ - if (EXMC_NANDBank == EXMC_BANK2_NAND) { - /* Reset the Bank2 NAND registers */ - EXMC_BANK2->CTLR2 = BANK2_3_CTLR_RESET; - EXMC_BANK2->SIR2 = BANK2_3_SIR_RESET; - EXMC_BANK2->COMTR2 = BANK2_3_COMTR_RESET; - EXMC_BANK2->ATTR2 = BANK2_3_ATTR_RESET; - } - /* EXMC_Bank3_NAND */ - else { - /* Reset the Bank3 NAND registers */ - EXMC_BANK3->CTLR3 = BANK2_3_CTLR_RESET; - EXMC_BANK3->SIR3 = BANK2_3_SIR_RESET; - EXMC_BANK3->COMTR3 = BANK2_3_COMTR_RESET; - EXMC_BANK3->ATTR3 = BANK2_3_ATTR_RESET; - } -} - -/** - * @brief Reset the Bank4 PCCARD registers. - * @param None - * @retval None - */ -void EXMC_PCCARD_DeInit(void) -{ - /* Reset EXMC Bank4 PCCARD registers */ - EXMC_BANK4->CTLR4 = BANK4_CTLR_RESET; - EXMC_BANK4->SIR4 = BANK4_SIR_RESET; - EXMC_BANK4->COMTR4 = BANK4_COMTR_RESET; - EXMC_BANK4->ATTR4 = BANK4_ATTR_RESET; - EXMC_BANK4->IOTR4 = BANK4_IOTR_RESET; -} - -/** - * @brief Initializes the EXMC Bank1 NOR/SRAM parameters. - * @param EXMC_NORSRAMInitParaStruct : the struct EXMC_NORSRAMInitPara pointer - * @retval None - */ -void EXMC_NORSRAM_Init(EXMC_NORSRAMInitPara *EXMC_NORSRAMInitParaStruct) -{ - uint32_t temp_SCTLR = 0x00000000, temp_STR = 0x00000000, temp_SWTR = 0x00000000; - - temp_SCTLR = (uint32_t)EXMC_NORSRAMInitParaStruct->EXMC_AddressDataMux | - EXMC_NORSRAMInitParaStruct->EXMC_MemoryType | - EXMC_NORSRAMInitParaStruct->EXMC_DatabusWidth | - EXMC_NORSRAMInitParaStruct->EXMC_BurstMode | - EXMC_NORSRAMInitParaStruct->EXMC_NWAITPolarity | - EXMC_NORSRAMInitParaStruct->EXMC_WrapBurstMode | - EXMC_NORSRAMInitParaStruct->EXMC_NWAITConfig | - EXMC_NORSRAMInitParaStruct->EXMC_MemoryWrite | - EXMC_NORSRAMInitParaStruct->EXMC_NWAITSignal | - EXMC_NORSRAMInitParaStruct->EXMC_ExtendedMode | - EXMC_NORSRAMInitParaStruct->EXMC_AsynWait | - EXMC_NORSRAMInitParaStruct->EXMC_WriteMode; - - temp_STR = (uint32_t)EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynAddressSetupTime | - (EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynAddressHoldTime << STR_AHT_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynDataSetupTime << STR_DST_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_BusLatency << STR_BUSLAT_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_SynCLKDivision << STR_CDIV_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_SynDataLatency << STR_DLAT_OFFSET) | - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynAccessMode; - - if (EXMC_NORSRAMInitParaStruct->EXMC_MemoryType == EXMC_MEMORY_TYPE_NOR) { - temp_SCTLR |= (uint32_t)SCTLR_NOREN_SET; - } - - if (EXMC_NORSRAMInitParaStruct->EXMC_ExtendedMode == EXMC_EXTENDED_MODE_ENABLE) { - temp_SWTR = (uint32_t)EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynAddressSetupTime | - (EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynAddressHoldTime << SWTR_AHT_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynDataSetupTime << SWTR_DST_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_SynCLKDivision << SWTR_CDIV_OFFSET) | - (EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_SynDataLatency << SWTR_DLAT_OFFSET) | - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynAccessMode; - } else { - temp_SWTR = BANK1_SWTR_RESET; - } - - switch (EXMC_NORSRAMInitParaStruct->EXMC_NORSRAMBank) { - case EXMC_BANK1_NORSRAM1: { - /* Bank1 NOR/SRAM Region1 registers configuration */ - EXMC_BANK1->SCTLR1 = temp_SCTLR; - EXMC_BANK1->STR1 = temp_STR; - EXMC_BANK1_WT->SWTR1 = temp_SWTR; - break; - } - case EXMC_BANK1_NORSRAM2: { - /* Bank1 NOR/SRAM Region2 registers configuration */ - EXMC_BANK1->SCTLR2 = temp_SCTLR; - EXMC_BANK1->STR2 = temp_STR; - EXMC_BANK1_WT->SWTR2 = temp_SWTR; - break; - } - case EXMC_BANK1_NORSRAM3: { - /* Bank1 NOR/SRAM Region3 registers configuration */ - EXMC_BANK1->SCTLR3 = temp_SCTLR; - EXMC_BANK1->STR3 = temp_STR; - EXMC_BANK1_WT->SWTR3 = temp_SWTR; - break; - } - case EXMC_BANK1_NORSRAM4: { - /* Bank1 NOR/SRAM Region4 registers configuration */ - EXMC_BANK1->SCTLR4 = temp_SCTLR; - EXMC_BANK1->STR4 = temp_STR; - EXMC_BANK1_WT->SWTR4 = temp_SWTR; - break; - } - default: - break; - } -} - -/** - * @brief Initialize the EXMC Bank2 or Bank3 NAND parameters. - * @param EXMC_NANDInitParaStruct : the struct EXMC_NANDInitPara pointer - * @retval None - */ - -void EXMC_NAND_Init(EXMC_NANDInitPara *EXMC_NANDInitParaStruct) -{ - uint32_t temp_CTLR = 0x00000000, temp_COMTR = 0x00000000, temp_ATTR = 0x00000000; - - temp_CTLR = (uint32_t)EXMC_NANDInitParaStruct->EXMC_WaitFeature | - CTLR_EMTYP_NAND | - EXMC_NANDInitParaStruct->EXMC_DatabusWidth | - EXMC_NANDInitParaStruct->EXMC_ECCLogic | - EXMC_NANDInitParaStruct->EXMC_ECCSize | - (EXMC_NANDInitParaStruct->EXMC_CTRLatency << CTLR_CTR_OFFSET) | - (EXMC_NANDInitParaStruct->EXMC_ATRLatency << CTLR_ATR_OFFSET); - - temp_COMTR = (uint32_t)EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_SetupTime | - (EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_WaitTime << COMTR_COMWT_OFFSET) | - (EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_HoldTime << COMTR_COMHT_OFFSET) | - (EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_DatabusHiZTime << COMTR_COMHIZT_OFFSET); - - temp_ATTR = (uint32_t)EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_SetupTime | - (EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_WaitTime << ATTR_ATTWT_OFFSET) | - (EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_HoldTime << ATTR_ATTHT_OFFSET) | - (EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_DatabusHiZTime << ATTR_ATTHIZT_OFFSET); - - if (EXMC_NANDInitParaStruct->EXMC_NANDBank == EXMC_BANK2_NAND) { - /* Configure the EXMC_Bank2 NAND registers using the value of parameters */ - EXMC_BANK2->CTLR2 = temp_CTLR; - EXMC_BANK2->COMTR2 = temp_COMTR; - EXMC_BANK2->ATTR2 = temp_ATTR; - } else { - /* EXMC_Bank3_NAND registers configuration */ - EXMC_BANK3->CTLR3 = temp_CTLR; - EXMC_BANK3->COMTR3 = temp_COMTR; - EXMC_BANK3->ATTR3 = temp_ATTR; - } -} - -/** - * @brief Initialize the EXMC Bank4 PCCARD parameters. - * @param EXMC_PCCARDInitParaStruct : the struct EXMC_PCCARDInitPara pointer. - * @retval None - */ -void EXMC_PCCARD_Init(EXMC_PCCARDInitPara *EXMC_PCCARDInitParaStruct) -{ - /* Configure the EXMC_Bank4_PCCARD CTLR4 register using the value of parameters */ - EXMC_BANK4->CTLR4 = (uint32_t)EXMC_PCCARDInitParaStruct->EXMC_WaitFeature | - EXMC_DATABUS_WIDTH_16B | - (EXMC_PCCARDInitParaStruct->EXMC_CTRLatency << CTLR_CTR_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_ATRLatency << CTLR_ATR_OFFSET); - - /* Configure the EXMC_Bank4_PCCARD COMTR4 register using the value of parameters */ - EXMC_BANK4->COMTR4 = (uint32_t)EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_SetupTime | - (EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_WaitTime << COMTR_COMWT_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_HoldTime << COMTR_COMHT_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_DatabusHiZTime << COMTR_COMHIZT_OFFSET); - - /* Configure the EXMC_Bank4_PCCARD ATTR4 register using the value of parameters */ - EXMC_BANK4->ATTR4 = (uint32_t)EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_SetupTime | - (EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_WaitTime << ATTR_ATTWT_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_HoldTime << ATTR_ATTHT_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_DatabusHiZTime << ATTR_ATTHIZT_OFFSET); - - /* Configure the EXMC_Bank4_PCCARD IOTR4 register using the value of parameters */ - EXMC_BANK4->IOTR4 = (uint32_t)EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_SetupTime | - (EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_WaitTime << IOTR_IOTWT_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_HoldTime << IOTR_IOHT_OFFSET) | - (EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_DatabusHiZTime << IOTR_IOHIZT_OFFSET); -} - -/** - * @brief Initialize the struct EXMC_NORSRAMInitPara - * @param EXMC_NORSRAMInitParaStruct: the struct EXMC_NORSRAMInitPara pointer - * @retval None - */ -void EXMC_NORSRAMStruct_Init(EXMC_NORSRAMInitPara *EXMC_NORSRAMInitParaStruct) -{ - EXMC_NORSRAMInitParaStruct->EXMC_NORSRAMBank = EXMC_BANK1_NORSRAM1; - EXMC_NORSRAMInitParaStruct->EXMC_AddressDataMux = EXMC_ADDRESS_DATA_MUX_ENABLE; - EXMC_NORSRAMInitParaStruct->EXMC_MemoryType = EXMC_MEMORY_TYPE_SRAM; - EXMC_NORSRAMInitParaStruct->EXMC_DatabusWidth = EXMC_DATABUS_WIDTH_8B; - EXMC_NORSRAMInitParaStruct->EXMC_BurstMode = EXMC_BURST_MODE_DISABLE; - EXMC_NORSRAMInitParaStruct->EXMC_NWAITPolarity = EXMC_NWAIT_POLARITY_LOW; - EXMC_NORSRAMInitParaStruct->EXMC_WrapBurstMode = EXMC_WRAP_BURST_MODE_DISABLE; - EXMC_NORSRAMInitParaStruct->EXMC_NWAITConfig = EXMC_NWAIT_CONFIG_BEFORE; - EXMC_NORSRAMInitParaStruct->EXMC_MemoryWrite = EXMC_MEMORY_WRITE_ENABLE; - EXMC_NORSRAMInitParaStruct->EXMC_NWAITSignal = EXMC_NWAIT_SIGNAL_ENABLE; - EXMC_NORSRAMInitParaStruct->EXMC_ExtendedMode = EXMC_EXTENDED_MODE_DISABLE; - EXMC_NORSRAMInitParaStruct->EXMC_AsynWait = EXMC_ASYN_WAIT_DISABLE; - EXMC_NORSRAMInitParaStruct->EXMC_WriteMode = EXMC_ASYN_WRITE; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynAddressSetupTime = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynAddressHoldTime = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynDataSetupTime = 0xFF; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_BusLatency = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_SynCLKDivision = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_SynDataLatency = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_ReadWriteTimingParaStruct->EXMC_AsynAccessMode = EXMC_ACCESS_MODE_A; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynAddressSetupTime = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynAddressHoldTime = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynDataSetupTime = 0xFF; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_BusLatency = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_SynCLKDivision = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_SynDataLatency = 0xF; - EXMC_NORSRAMInitParaStruct->EXMC_WriteTimingParaStruct->EXMC_AsynAccessMode = EXMC_ACCESS_MODE_A; -} - -/** - * @brief Initialize the struct EXMC_NANDInitPara - * @param EXMC_NANDInitParaStruct: the struct EXMC_NANDInitPara pointer. - * @retval None - */ -void EXMC_NANDStruct_Init(EXMC_NANDInitPara *EXMC_NANDInitParaStruct) -{ - EXMC_NANDInitParaStruct->EXMC_NANDBank = EXMC_BANK2_NAND; - EXMC_NANDInitParaStruct->EXMC_WaitFeature = EXMC_WAIT_FEATURE_DISABLE; - EXMC_NANDInitParaStruct->EXMC_DatabusWidth = EXMC_DATABUS_WIDTH_8B; - EXMC_NANDInitParaStruct->EXMC_ECCLogic = EXMC_ECC_LOGIC_DISABLE; - EXMC_NANDInitParaStruct->EXMC_ECCSize = EXMC_ECC_SIZE_256BYTES; - EXMC_NANDInitParaStruct->EXMC_CTRLatency = 0x0; - EXMC_NANDInitParaStruct->EXMC_ATRLatency = 0x0; - EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_SetupTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_WaitTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_HoldTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_DatabusHiZTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_SetupTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_WaitTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_HoldTime = 0xFC; - EXMC_NANDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_DatabusHiZTime = 0xFC; -} - -/** - * @brief Initialize the struct EXMC_PCCARDInitParaStruct - * @param EXMC_PCCARDInitPara: the struct EXMC_PCCARDInitParaStruct pointer. - * @retval None - */ -void EXMC_PCCARDStruct_Init(EXMC_PCCARDInitPara *EXMC_PCCARDInitParaStruct) -{ - EXMC_PCCARDInitParaStruct->EXMC_WaitFeature = EXMC_WAIT_FEATURE_DISABLE; - EXMC_PCCARDInitParaStruct->EXMC_CTRLatency = 0x0; - EXMC_PCCARDInitParaStruct->EXMC_ATRLatency = 0x0; - EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_SetupTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_WaitTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_HoldTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_CommonSpaceTimingParaStruct->EXMC_DatabusHiZTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_SetupTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_WaitTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_HoldTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_AttributeSpaceTimingParaStruct->EXMC_DatabusHiZTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_SetupTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_WaitTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_HoldTime = 0xFC; - EXMC_PCCARDInitParaStruct->EXMC_IOSpaceTimingParaStruct->EXMC_DatabusHiZTime = 0xFC; -} - -/** - * @brief Enable or disable the specified Region of Bank1. - * @param EXMC_NORSRAMBank: specifies the Region of Bank1. - * This parameter can be one of the following values: - * @arg EXMC_BANK1_NORSRAM1: the Region1 of Bank1 - * @arg EXMC_BANK1_NORSRAM2: the Region2 of Bank1 - * @arg EXMC_BANK1_NORSRAM3: the Region3 of Bank1 - * @arg EXMC_BANK1_NORSRAM4: the Region4 of Bank1 - * @param NewValue: new value of the specified Region of Bank1. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void EXMC_NORSRAM_Enable(uint32_t EXMC_NORSRAMBank, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the selected NOR/SRAM Bank by setting the PBKEN bit in the BCRx register */ - switch (EXMC_NORSRAMBank) { - case EXMC_BANK1_NORSRAM1: - EXMC_BANK1->SCTLR1 |= SCTLR_BAKEN_SET; - break; - case EXMC_BANK1_NORSRAM2: - EXMC_BANK1->SCTLR2 |= SCTLR_BAKEN_SET; - break; - case EXMC_BANK1_NORSRAM3: - EXMC_BANK1->SCTLR3 |= SCTLR_BAKEN_SET; - break; - case EXMC_BANK1_NORSRAM4: - EXMC_BANK1->SCTLR4 |= SCTLR_BAKEN_SET; - break; - default: - break; - } - } else { - /* Disable the selected NOR/SRAM Bank by clearing the PBKEN bit in the BCRx register */ - switch (EXMC_NORSRAMBank) { - case EXMC_BANK1_NORSRAM1: - EXMC_BANK1->SCTLR1 &= SCTLR_BAKEN_RESET; - break; - case EXMC_BANK1_NORSRAM2: - EXMC_BANK1->SCTLR2 &= SCTLR_BAKEN_RESET; - break; - case EXMC_BANK1_NORSRAM3: - EXMC_BANK1->SCTLR3 &= SCTLR_BAKEN_RESET; - break; - case EXMC_BANK1_NORSRAM4: - EXMC_BANK1->SCTLR4 &= SCTLR_BAKEN_RESET; - break; - default: - break; - } - } -} - -/** - * @brief Enable or disable the specified NAND Bank2 or Bank3. - * @param EXMC_NANDBank: specifies the NAND Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @param NewValue: new value of the specified Bank. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void EXMC_NAND_Enable(uint32_t EXMC_NANDBank, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the selected NAND Bank by setting the PBKEN bit in the PCRx register */ - if (EXMC_NANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->CTLR2 |= CTLR_BAKEN_SET; - } else { - EXMC_BANK3->CTLR3 |= CTLR_BAKEN_SET; - } - } else { - /* Disable the selected NAND Bank by clearing the PBKEN bit in the PCRx register */ - if (EXMC_NANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->CTLR2 &= CTLR_BAKEN_RESET; - } else { - EXMC_BANK3->CTLR3 &= CTLR_BAKEN_RESET; - } - } -} - -/** - * @brief Enable or disable the Bank4 of PCCARD. - * @param NewValue: new value of the PCCARD Bank. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void EXMC_PCCARD_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the PCCARD Bank */ - EXMC_BANK4->CTLR4 |= CTLR_BAKEN_SET; - } else { - /* Disable the PCCARD Bank */ - EXMC_BANK4->CTLR4 &= CTLR_BAKEN_RESET; - } -} - -/** - * @brief Enable or disable the EXMC_CTLR1_ECCEN control bit. - * @param EXMC_NANDBank: specifies the NAND Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @param NewValue: new value of the EXMC Bank2 or Bank3 ECC calculation. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void EXMC_NANDECC_Enable(uint32_t EXMC_NANDBank, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the selected NAND Bank ECC function by setting the ECCEN bit in the PCRx register */ - if (EXMC_NANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->CTLR2 |= CTLR_ECCEN_SET; - } else { - EXMC_BANK3->CTLR3 |= CTLR_ECCEN_SET; - } - } else { - /* Disable the selected NAND Bank ECC function by clearing the ECCEN bit in the PCRx register */ - if (EXMC_NANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->CTLR2 &= CTLR_ECCEN_RESET; - } else { - EXMC_BANK3->CTLR3 &= CTLR_ECCEN_RESET; - } - } -} - -/** - * @brief Get the EXMC_ECCR value. - * @param EXMC_NANDBank: specifies the NAND Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @retval The Error Correction Code (ECC) value. - */ -uint32_t EXMC_GetECC(uint32_t EXMC_NANDBank) -{ - if (EXMC_NANDBank == EXMC_BANK2_NAND) { - return (EXMC_BANK2->ECCR2); - } else { - return (EXMC_BANK3->ECCR3); - } -} - -/** - * @brief Enable or disable the specified EXMC Bank2/3/4 interrupts. - * @param EXMC_PCNANDBank: specifies the NAND Bank or PCCARD Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @arg EXMC_BANK4_PCCARD: the PCCARD Bank4 - * @param EXMC_INT: the EXMC interrupt sources. - * This parameter can be any combination of the following values: - * @arg EXMC_INT_RISE: Rising edge detection interrupt - * @arg EXMC_INT_LEVEL: Level edge detection interrupt - * @arg EXMC_INT_FALL: Falling edge detection interrupt - * @param NewValue: new value of the specified EXMC interrupts. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void EXMC_INTConfig(uint32_t EXMC_PCNANDBank, uint32_t EXMC_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the specified EXMC_Bank2 interrupts */ - if (EXMC_PCNANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->SIR2 |= EXMC_INT; - } - /* Enable the specified EXMC_Bank3 interrupts */ - else if (EXMC_PCNANDBank == EXMC_BANK3_NAND) { - EXMC_BANK3->SIR3 |= EXMC_INT; - } - /* Enable the specified EXMC_Bank4 interrupts */ - else { - EXMC_BANK4->SIR4 |= EXMC_INT; - } - } else { - /* Disable the specified EXMC_Bank2 interrupts */ - if (EXMC_PCNANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->SIR2 &= ~((uint32_t)EXMC_INT); - } - /* Disable the specified EXMC_Bank3 interrupts */ - else if (EXMC_PCNANDBank == EXMC_BANK3_NAND) { - EXMC_BANK3->SIR3 &= ~((uint32_t)EXMC_INT); - } - /* Disable the specified EXMC_Bank4 interrupts */ - else { - EXMC_BANK4->SIR4 &= ~((uint32_t)EXMC_INT); - } - } -} - -/** - * @brief Get the bit flag of EXMC_SIRx register. - * @param EXMC_PCNANDBank: specifies the NAND Bank or PCCARD Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @arg EXMC_BANK4_PCCARD: the PCCARD Bank4 - * @param EXMC_FLAG: the flag of EXMC_SIRx register. - * This parameter can be one of the following values: - * @arg EXMC_FLAG_RISE: Rising egde detection Flag - * @arg EXMC_FLAG_LEVEL: Level detection Flag - * @arg EXMC_FLAG_FALL: Falling egde detection Flag - * @arg EXMC_FLAG_FIFOE: FIFO empty Flag - * @retval The new value of EXMC_FLAG (SET or RESET). - */ -TypeState EXMC_GetBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_FLAG) -{ - uint32_t temp_SIR = 0x00000000; - /* the NAND Bank2 */ - if (EXMC_PCNANDBank == EXMC_BANK2_NAND) { - temp_SIR = EXMC_BANK2->SIR2; - } - /* the NAND Bank3 */ - else if (EXMC_PCNANDBank == EXMC_BANK3_NAND) { - temp_SIR = EXMC_BANK3->SIR3; - } - /* the PCCARD Bank4 */ - else { - temp_SIR = EXMC_BANK4->SIR4; - } - - if ((temp_SIR & EXMC_FLAG) != (uint16_t)RESET) { - /* EXMC_FLAG is set */ - return SET; - } else { - /* EXMC_FLAG is reset */ - return RESET; - } -} - -/** - * @brief Clear the bit flag of EXMC_SIRx register. - * @param EXMC_PCNANDBank: specifies the NAND Bank or PCCARD Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @arg EXMC_BANK4_PCCARD: the PCCARD Bank4 - * @param EXMC_FLAG: the flag of EXMC_SIRx register. - * This parameter can be any combination of the following values: - * @arg EXMC_FLAG_RISE: Rising egde detection Flag - * @arg EXMC_FLAG_LEVEL: Level detection Flag - * @arg EXMC_FLAG_FALL: Falling egde detection Flag - * @retval None - */ -void EXMC_ClearBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_FLAG) -{ - if (EXMC_PCNANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->SIR2 &= ~EXMC_FLAG; - } else if (EXMC_PCNANDBank == EXMC_BANK3_NAND) { - EXMC_BANK3->SIR3 &= ~EXMC_FLAG; - } - /* EXMC_Bank4_PCCARD*/ - else { - EXMC_BANK4->SIR4 &= ~EXMC_FLAG; - } -} - -/** - * @brief Get the interrupt bit flag. - * @param EXMC_PCNANDBank: specifies the NAND Bank or PCCARD Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @arg EXMC_BANK4_PCCARD: the PCCARD Bank4 - * @param EXMC_INT: the interrupt bit flag. - * This parameter can be one of the following values: - * @arg EXMC_INT_RISE: Rising edge detection interrupt - * @arg EXMC_INT_LEVEL: Level edge detection interrupt - * @arg EXMC_INT_FALL: Falling edge detection interrupt - * @retval The new value of EXMC_INT (SET or RESET). - */ -TypeState EXMC_GetIntBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_INT) -{ - uint32_t temp_SIR = 0x00000000, temp_INTState = 0x00000000, temp_INTEnable = 0x00000000; - - if (EXMC_PCNANDBank == EXMC_BANK2_NAND) { - temp_SIR = EXMC_BANK2->SIR2; - } else if (EXMC_PCNANDBank == EXMC_BANK3_NAND) { - temp_SIR = EXMC_BANK3->SIR3; - } - /* EXMC_Bank4_PCCARD*/ - else { - temp_SIR = EXMC_BANK4->SIR4; - } - - temp_INTState = temp_SIR & EXMC_INT; - - temp_INTEnable = temp_SIR & (EXMC_INT >> SIR_INTEN_OFFSET); - - if ((temp_INTState != (uint32_t)RESET) && (temp_INTEnable != (uint32_t)RESET)) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the interrupt bit flag. - * @param EXMC_PCNANDBank: specifies the NAND Bank or PCCARD Bank. - * This parameter can be one of the following values: - * @arg EXMC_BANK2_NAND: the NAND Bank2 - * @arg EXMC_BANK3_NAND: the NAND Bank3 - * @arg EXMC_BANK4_PCCARD: the PCCARD Bank4 - * @param EXMC_INT: the interrupt bit flag. - * This parameter can be any combination of the following values: - * @arg EXMC_FLAG_RISE: Rising edge detection interrupt - * @arg EXMC_FLAG_LEVEL: Level edge detection interrupt - * @arg EXMC_FLAG_FALL: Falling edge detection interrupt - * @retval None - */ -void EXMC_ClearIntBitState(uint32_t EXMC_PCNANDBank, uint32_t EXMC_INT) -{ - if (EXMC_PCNANDBank == EXMC_BANK2_NAND) { - EXMC_BANK2->SIR2 &= ~(EXMC_INT >> SIR_INTEN_OFFSET); - } else if (EXMC_PCNANDBank == EXMC_BANK3_NAND) { - EXMC_BANK3->SIR3 &= ~(EXMC_INT >> SIR_INTEN_OFFSET); - } - /* EXMC_Bank4_PCCARD*/ - else { - EXMC_BANK4->SIR4 &= ~(EXMC_INT >> SIR_INTEN_OFFSET); - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exti.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exti.c deleted file mode 100644 index d541e371f1..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_exti.c +++ /dev/null @@ -1,196 +0,0 @@ -/** - ****************************************************************************** - * @brief EXTI functions of the firmware library. - ****************************************************************************** -*/ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_exti.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup EXTI - * @brief EXTI driver modules - * @{ - */ - -/** @defgroup EXTI_Private_Defines - * @{ - */ -/* No interrupt line is selected */ -#define EXTI_LINE_NULL ((uint32_t)0x00000000) - -/* ----------------- EXTI Reset Configuration Registers ------------------ */ -/* The reset value of EXTI_IER */ -#define EXTI_IER_RST ((uint32_t)0x00000000) - -/* The reset value of EXTI_EER */ -#define EXTI_EER_RST ((uint32_t)0x00000000) - -/* The reset value of EXTI_RTE */ -#define EXTI_RTE_RST ((uint32_t)0x00000000) - -/* The reset value of EXTI_FTE */ -#define EXTI_FTE_RST ((uint32_t)0x00000000) - -/* The reset value of EXTI_PD */ -#define EXTI_PD_RST ((uint32_t)0x000FFFFF) - -/** - * @} - */ - -/** @defgroup EXTI_Private_Functions - * @{ - */ - -/** - * @brief Reset the EXTI peripheral registers and the struct EXTI_InitPara. - * @param EXTI_InitParaStruct: the struct EXTI_InitPara pointer. - * @retval None - */ -void EXTI_DeInit(EXTI_InitPara *EXTI_InitParaStruct) -{ - /* Reset the EXTI peripheral registers */ - EXTI->IER = EXTI_IER_RST; - EXTI->EER = EXTI_EER_RST; - EXTI->RTE = EXTI_RTE_RST; - EXTI->FTE = EXTI_FTE_RST; - EXTI->PD = EXTI_PD_RST; - - /* Reset the struct EXTI_InitPara */ - EXTI_InitParaStruct->EXTI_LINE = EXTI_LINE_NULL; - EXTI_InitParaStruct->EXTI_Mode = EXTI_Mode_Interrupt; - EXTI_InitParaStruct->EXTI_Trigger = EXTI_Trigger_Falling; - EXTI_InitParaStruct->EXTI_LINEEnable = DISABLE; -} - -/** - * @brief Initialize the EXTI peripheral registers. - * @param EXTI_InitParaStruct: the struct EXTI_InitPara pointer. - * @retval None - */ -void EXTI_Init(EXTI_InitPara *EXTI_InitParaStruct) -{ - uint32_t temp = 0; - - temp = (uint32_t)EXTI_BASE; - - if (EXTI_InitParaStruct->EXTI_LINEEnable != DISABLE) { - /* Clear Interrupt and Event from EXTI Lines */ - EXTI->IER &= ~EXTI_InitParaStruct->EXTI_LINE; - EXTI->EER &= ~EXTI_InitParaStruct->EXTI_LINE; - - temp += EXTI_InitParaStruct->EXTI_Mode; - - *(__IO uint32_t *) temp |= EXTI_InitParaStruct->EXTI_LINE; - - /* Clear the Rising and Falling edge trigger enable registers */ - EXTI->RTE &= ~EXTI_InitParaStruct->EXTI_LINE; - EXTI->FTE &= ~EXTI_InitParaStruct->EXTI_LINE; - - /* Select the trigger type for the selected EXTI Lines */ - if (EXTI_InitParaStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) { - /* Rising and Falling edge trigger are both selected */ - EXTI->RTE |= EXTI_InitParaStruct->EXTI_LINE; - EXTI->FTE |= EXTI_InitParaStruct->EXTI_LINE; - } else { - temp = (uint32_t)EXTI_BASE; - temp += EXTI_InitParaStruct->EXTI_Trigger; - - *(__IO uint32_t *) temp |= EXTI_InitParaStruct->EXTI_LINE; - } - } else { - temp += EXTI_InitParaStruct->EXTI_Mode; - - /* Disable the selected EXTI lines */ - *(__IO uint32_t *) temp &= ~EXTI_InitParaStruct->EXTI_LINE; - } -} - -/** - * @brief Activate the software interrupt or event request of the selected EXTI Lines. - * @param EXTI_LINE: the selected EXTI lines. - * This parameter can be any combination of EXTI_LINEx where x can be (0..19). - * @retval None - */ -void EXTI_SWINT_Enable(uint32_t EXTI_LINE) -{ - /* Enable the software interrupt or event request of the selected EXTI Lines */ - EXTI->SIE |= EXTI_LINE; -} - -/** - * @brief Get the bit flag of the selected EXTI lines. - * @param EXTI_LINE: the selected EXTI lines. - * This parameter can be any combination of EXTI_LINEx where x can be (0..19). - * @retval The new value of EXTI_LINE (SET or RESET). - */ -TypeState EXTI_GetBitState(uint32_t EXTI_LINE) -{ - /* Check and get the selected EXTI lines flag */ - if ((EXTI->PD & EXTI_LINE) != (uint32_t)RESET) { - /* EXTI_LINE bit is SET */ - return SET; - } else { - /* EXTI_LINE bit is RESET */ - return RESET; - } -} - -/** - * @brief Clear the bit flag of the selected EXTI lines. - * @param EXTI_LINE: the selected EXTI lines. - * This parameter can be any combination of EXTI_LINEx where x can be (0..19). - * @retval None - */ -void EXTI_ClearBitState(uint32_t EXTI_LINE) -{ - /* Clear the bit flag of the selected EXTI lines */ - EXTI->PD = EXTI_LINE; -} - -/** - * @brief Get the interrupt bit flag of the selected EXTI lines.. - * @param EXTI_LINE: the selected EXTI lines. - * This parameter can be any combination of EXTI_LINEx where x can be (0..19). - * @retval The new value of EXTI_LINE (SET or RESET). - */ -TypeState EXTI_GetIntBitState(uint32_t EXTI_LINE) -{ - /* Check and get the interrupt source is set or not */ - if (((EXTI->PD & EXTI_LINE) != (uint32_t)RESET) && ((EXTI->IER & EXTI_LINE) != (uint32_t)RESET)) { - /* The interrupt bit of EXTI_LINE is SET */ - return SET; - } else { - /* The interrupt bit of EXTI_LINE is RESET */ - return RESET; - } -} - -/** - * @brief Clear the interrupt bit flag of the selected EXTI lines. - * @param EXTI_LINE: the selected EXTI lines. - * This parameter can be any combination of EXTI_LINEx where x can be (0..19). - * @retval None - */ -void EXTI_ClearIntBitState(uint32_t EXTI_LINE) -{ - /* Clear the interrupt bit flag of the selected EXTI lines */ - EXTI->PD = EXTI_LINE; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_fmc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_fmc.c deleted file mode 100644 index 68d5a283a4..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_fmc.c +++ /dev/null @@ -1,1166 +0,0 @@ -/** - ****************************************************************************** - * @brief FMC functions of the firmware library. - ******************************************************************************/ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_fmc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup FMC - * @brief FMC driver modules - * @{ - */ - -/** @defgroup FMC_Private_Functions - * @{ - */ - -/** @defgroup FMC_Group1 FMC Memory Programming functions - * @brief FMC Memory Programming functions - * -@verbatim - =============================================================================== - ##### FMC Memory Programming functions ##### - =============================================================================== - - [..] The FMC Memory Programming functions, includes the following functions: - (+) void FMC_Unlock(void); - (+) void FMC_UnlockBank1(void); - (+) void FMC_UnlockBank2(void); - (+) void FMC_Lock(void); - (+) void FMC_LockBank1(void) - (+) void FMC_LockBank2(void) - (+) FMC_State FMC_ErasePage(uint32_t Page_Address); - (+) FMC_State FMC_MassErase(void); - (+) FMC_State FMC_MassBank1Erase(void) - (+) FMC_State FMC_MassBank2Erase(void) - (+) FMC_State FMC_ProgramWord(uint32_t Address, uint32_t Data); - [..] Any operation of erase or program should follow these steps: - - (#) Call the FMC_Unlock() function to unlock the FMC operation - (#) Call erase or program data - (#) Call the FMC_Lock() to lock the FMC operation - -@endverbatim - * @{ - */ -/** - * @brief Unlock the main FMC operation. - * @param None - * @retval None - */ -void FMC_Unlock(void) -{ - if ((FMC->CMR & FMC_CMR_LK) != RESET) { - /* Write the FMC key */ - FMC->UKEYR = FMC_KEY1; - FMC->UKEYR = FMC_KEY2; - } - if (FMC_SIZE > FMC_BANK1_SIZE) { - /* Authorize the FPEC of Bank2 Access */ - if ((FMC->CMR2 & FMC_CMR_LK) != RESET) { - FMC->UKEYR2 = FMC_KEY1; - FMC->UKEYR2 = FMC_KEY2; - } - } -} - -/** - * @brief Unlocks the FMC Bank1 Program Erase Controller. - * @note This function can be used for all GD32F10x devices. - * - For GD32F10X_XD and GD32F10X_CL devices this function unlocks Bank1. - * - For all other devices it unlocks Bank1 and it is - * equivalent to FLASH_Unlock function. - * @param None - * @retval None - */ -void FMC_UnlockB1(void) -{ - /* Authorize the FPEC of Bank1 Access */ - if ((FMC->CMR & FMC_CMR_LK) != RESET) { - FMC->UKEYR = FMC_KEY1; - FMC->UKEYR = FMC_KEY2; - } -} - -/** - * @brief Unlocks the FMC Bank2 Program Erase Controller. - * @note This function can be used for GD32F10X_XD and GD32F10X_CL density devices. - * @param None - * @retval None - */ -#if defined GD32F10X_XD || defined GD32F10X_CL -void FMC_UnlockB2(void) -{ - /* Authorize the FPEC of Bank2 Access */ - if ((FMC->CMR2 & FMC_CMR_LK) != RESET) { - FMC->UKEYR2 = FMC_KEY1; - FMC->UKEYR2 = FMC_KEY2; - } -} -#endif /* GD32F10X_XD and GD32F10X_CL */ - -/** - * @brief Lock the main FMC operation. - * @param None - * @retval None - */ -void FMC_Lock(void) -{ - /* Set the LOCK bit*/ - FMC->CMR |= FMC_CMR_LK; - - if (FMC_SIZE > FMC_BANK1_SIZE) { - /* Set the Lock Bit to lock the FPEC and the CR of Bank2 */ - FMC->CMR2 |= FMC_CMR_LK; - } -} - -/** - * @brief Locks the FMC Bank1 Program Erase Controller. - * @note this function can be used for all GD32F10X devices. - * - For GD32F10X_XD and GD32F10X_CL devices this function Locks Bank1. - * - For all other devices it Locks Bank1 and it is equivalent - * to FMC_Lock function. - * @param None - * @retval None - */ -void FMC_LockB1(void) -{ - /* Set the Lock Bit to lock the FPEC and the CMR of Bank1 */ - FMC->CMR |= FMC_CMR_LK; -} - -/** - * @brief Locks the FMC Bank2 Program Erase Controller. - * @note This function can be used for GD32F10X_XD and GD32F10X_CL density devices. - * @param None - * @retval None - */ -#if defined GD32F10X_XD || defined GD32F10X_CL -void FMC_LockB2(void) -{ - /* Set the Lock Bit to lock the FPEC and the CMR of Bank2 */ - FMC->CMR2 |= FMC_CMR_LK; -} -#endif - -/** - * @brief Erase a page. - * @param Page_Address: The page address to be erased. - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_ErasePage(uint32_t Page_Address) -{ - if (FMC_SIZE > FMC_BANK1_SIZE) { - FMC_State temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - if (Page_Address < FMC_B1_END_ADDRESS) { - /* Wait for last operation to be completed */ - FMC_State temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - FMC->CMR |= FMC_CMR_PE; - FMC->AR = Page_Address; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the PE bit */ - FMC->CMR &= ~FMC_CMR_PE; - } - } else { - /* Wait for last operation to be completed */ - FMC_State temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - FMC->CMR2 |= FMC_CMR_PE; - FMC->AR2 = Page_Address; - if (FMC->OPTR & FMC_OPTR_PLEVEL1) { - FMC->AR = Page_Address; - } - FMC->CMR2 |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the PE bit */ - FMC->CMR2 &= ~FMC_CMR_PE; - } - } - /* Return the FMC state */ - return temp_state; - } - - else { - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Start page erase */ - FMC->CMR |= FMC_CMR_PE; - FMC->AR = Page_Address; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the PE bit */ - FMC->CMR &= ~FMC_CMR_PE; - } - /* Return the FMC state */ - return temp_state; - } -} - -/** - * @brief Erase all main FMC. - * @param None - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_MassErase(void) -{ - if (FMC_SIZE > FMC_BANK1_SIZE) { - /* Wait for last operation to be completed */ - FMC_State temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - if (temp_state == FMC_READY) { - /* Start chip erase */ - FMC->CMR |= FMC_CMR_ME; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the MER bit */ - FMC->CMR &= ~FMC_CMR_ME; - } - temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - if (temp_state == FMC_READY) { - /* Start chip erase */ - FMC->CMR2 |= FMC_CMR_ME; - FMC->CMR2 |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the MER bit */ - FMC->CMR2 &= ~FMC_CMR_ME; - } - /* Return the FMC state */ - return temp_state; - } else { - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Start chip erase */ - FMC->CMR |= FMC_CMR_ME; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the MER bit */ - FMC->CMR &= ~FMC_CMR_ME; - } - /* Return the FMC state */ - return temp_state; - } -} - -/** - * @brief Erases all Bank1 FMC pages. - * @note This function can be used for all GD32F10x devices. - * - For GD32F10X_XD and GD32F10X_CL devices this function erases all Bank1 pages. - * - For all other devices it erases all Bank1 pages and it is equivalent - * to FLASH_EraseAllPages function. - * @param None - * @retval FLASH Status: FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_MassB1Erase(void) -{ - FMC_State temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Start chip erase */ - FMC->CMR |= FMC_CMR_ME; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the MER bit */ - FMC->CMR &= ~FMC_CMR_ME; - } - /* Return the Erase Status */ - return temp_state; -} - -/** - * @brief Erases all Bank2 FMC pages. - * @note This function can be used for GD32F10X_XD and GD32F10X_CL density devices. - * @param None - * @retval FMC Status: FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ - -FMC_State FMC_MassB2Erase(void) -{ - FMC_State temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Start chip erase */ - FMC->CMR2 |= FMC_CMR_ME; - FMC->CMR2 |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the MER bit */ - FMC->CMR2 &= ~FMC_CMR_ME; - } - /* Return the Erase Status */ - return temp_state; -} - - -/** - * @brief Program a word at the corresponding address. - * @param Address: The address to be programmed. - * @param Data: The data to be programmed. - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_ProgramWord(uint32_t Address, uint32_t Data) -{ - if (FMC_SIZE > FMC_BANK1_SIZE) { - FMC_State temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - if (Address < FMC_B1_END_ADDRESS) { - FMC_State temp_state = FMC_B1_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Set the PG bit to start program */ - FMC->CMR |= FMC_CMR_PG; - - *(__IO uint32_t *)Address = Data; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the PG bit */ - FMC->CMR &= ~FMC_CMR_PG; - } - } else { - FMC_State temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Set the PG bit to start program */ - FMC->CMR2 |= FMC_CMR_PG; - - *(__IO uint32_t *)Address = Data; - - /* Wait for the FMC ready */ - temp_state = FMC_B2_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the PG bit */ - FMC->CMR2 &= ~FMC_CMR_PG; - } - } - - /* Return the FMC state */ - return temp_state; - } else { - - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Set the PG bit to start program */ - FMC->CMR |= FMC_CMR_PG; - - *(__IO uint32_t *)Address = Data; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - /* Reset the PG bit */ - FMC->CMR &= ~FMC_CMR_PG; - } - - /* Return the FMC state */ - return temp_state; - - } - -} - -/** - * @} - */ - -/** @defgroup FMC_Group2 Option Bytes Programming functions - * @brief Option Bytes Programming functions - * -@verbatim - =============================================================================== - ##### Option Bytes Programming functions ##### - =============================================================================== - - [..] The FMC_Option Bytes Programming_functions, includes the following functions: - (+) void FMC_OB_Unlock(void); - (+) void FMC_OB_Lock(void); - (+) void FMC_OB_Reset(void); - (+) FMC_State FMC_OB_Erase(void); - (+) FMC_State FMC_OB_WRPConfig(uint32_t OB_WRP); - (+) FMC_State FMC_OB_RDPConfig(uint8_t OB_RDP); - (+) FMC_State FMC_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_DEEPSLEEP, uint8_t OB_STDBY); - (+) FMC_State FMC_OB_BOOTConfig(uint8_t OB_BOOT); - (+) FMC_State FMC_OB_WriteUser(uint8_t OB_USER); - (+) FMC_ProgramOptionByteData(uint32_t Address, uint8_t Data); - (+) uint8_t FMC_OB_GetUser(void); - (+) uint32_t FMC_OB_GetWRP(void); - (+) FlagStatus FMC_OB_GetRDP(void); - [..] Any operation of erase or program should follow these steps: - - (#) Call the FMC_OB_Unlock() function to enable the Option Bytes registers access - - (#) Call one or several functions to program the desired option bytes - (++) FMC_State FMC_OB_RDPConfig(uint8_t OB_RDP) => to set the desired read Protection Level - (++) FMC_State FMC_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState) - => to Enable/Disable the desired sector write protection - (++) FMC_State FMC_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_DEEPSLEEP, uint8_t OB_STDBY) - => to configure the user option Bytes: IWDG, DEEPSLEEP and the Standby. - (++) FMC_State FMC_OB_BOOTConfig(uint8_t OB_BOOT1) - => to set or reset BOOT1 - (++) FMC_State FMC_OB_VDDAConfig(uint8_t OB_VDDA_ANALOG) - => to enable or disable the VDDA Analog Monitoring - (++) You can write all User Options bytes at once using a single function - by calling FMC_State FMC_OB_WriteUser(uint8_t OB_USER) - (++) FMC_ProgramOptionByteData(uint32_t Address, uint8_t Data) to program the - two half word in the option bytes - - (#) Once all needed option bytes to be programmed are correctly written, call the - FMC_OB_Launch(void) function to launch the Option Bytes programming process. - - (#) Call the FMC_OB_Lock() to disable the Option Bytes registers access (recommended - to protect the option Bytes against possible unwanted operations) - -@endverbatim - * @{ - */ - -/** - * @brief Unlock the option byte operation - * @param None - * @retval None - */ -void FMC_OB_Unlock(void) -{ - if ((FMC->CMR & FMC_CMR_OBWE) == RESET) { - /* Write the FMC key */ - FMC->OBKEYR = FMC_KEY1; - FMC->OBKEYR = FMC_KEY2; - } -} - -/** - * @brief Lock the option byte operation. - * @param None - * @retval None - */ -void FMC_OB_Lock(void) -{ - /* Reset the OBWE bit */ - FMC->CMR &= ~FMC_CMR_OBWE; -} - -/** - * @brief Generate a system reset to reload the option byte. - * @param None - * @retval None - */ -void FMC_OB_Reset(void) -{ - /* Set the OPTR bit */ - FMC->CMR |= FMC_CMR_OPTR; -} - -/** - * @brief Erase the FMC option byte. - * @param None - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_OB_Erase(void) -{ - uint16_t temp_rdp = RDP_LEVEL_0; - - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - /* Check the ReadOut Protection Option Byte */ - if (FMC_OB_GetRDP() != RESET) { - temp_rdp = 0x00; - } - - if (temp_state == FMC_READY) { - /* Start erase the option byte */ - FMC->CMR |= FMC_CMR_OBER; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Reset the OPER bit */ - FMC->CMR &= ~FMC_CMR_OBER; - - /* Set the OBPG bit */ - FMC->CMR |= FMC_CMR_OBPG; - - /* Set default RDP level */ - OB->RDP = (uint16_t)temp_rdp; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } else { - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Program Write protect Byte - * @param OB_WRP: specify the address of the pages to be write protected. - * The legal parameter can be: - * @arg WRP_SECTOR0 ... WRP_SECTOR31 - * @arg WRP_ALLSECTORS - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_OB_EnableWRP(uint32_t OB_WRP) -{ - uint16_t temp_WRP0, temp_WRP1, temp_WRP2, temp_WRP3; - - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - OB_WRP = (uint32_t)(~OB_WRP); - temp_WRP0 = (uint16_t)(OB_WRP & OB_WRP0_WRP0); - temp_WRP1 = (uint16_t)((OB_WRP & OB_WRP0_nWRP0) >> 8); - temp_WRP2 = (uint16_t)((OB_WRP & OB_WRP1_WRP1) >> 16); - temp_WRP3 = (uint16_t)((OB_WRP & OB_WRP1_nWRP1) >> 24); - - if (temp_state == FMC_READY) { - FMC->OBKEYR = FMC_KEY1; - FMC->OBKEYR = FMC_KEY2; - /* Set the OBPG bit*/ - FMC->CMR |= FMC_CMR_OBPG; - - if (temp_WRP0 != 0xFF) { - OB->WRP0 = temp_WRP0; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - } - if ((temp_state == FMC_READY) && (temp_WRP1 != 0xFF)) { - OB->WRP1 = temp_WRP1; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - } - if ((temp_state == FMC_READY) && (temp_WRP2 != 0xFF)) { - OB->WRP2 = temp_WRP2; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - } - if ((temp_state == FMC_READY) && (temp_WRP3 != 0xFF)) { - OB->WRP3 = temp_WRP3; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - } - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Enable or disable the read out protection,this function erases all option bytes. - * @param NewValue: ENABLE or DISABLE. - * @retval FMC state: FMC_READY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_ReadOutProtection(TypeState NewValue) -{ - FMC_State temp_state = FMC_READY; - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - if (temp_state == FMC_READY) { - /* Unlock option bytes */ - FMC->OBKEYR = FMC_KEY1; - FMC->OBKEYR = FMC_KEY2; - while ((FMC->CMR & FMC_CMR_OBWE) != FMC_CMR_OBWE) - {} - FMC->CMR |= FMC_CMR_OBER; - FMC->CMR |= FMC_CMR_START; - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - if (temp_state == FMC_READY) { - /* Disable the OBER Bit */ - FMC->CMR &= ~FMC_CMR_OBER ; - /* Enable the OBPG Bit */ - FMC->CMR |= FMC_CMR_OBPG; - if (NewValue != DISABLE) { - OB->RDP = 0x00; - } else { - OB->RDP = RDP_LEVEL_0; - } - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Enable the OBPG Bit */ - FMC->CMR &= ~FMC_CMR_OBPG ; - } - } else { - if (temp_state != FMC_TIMEOUT_ERR) { - /* Disable the OBER Bit */ - FMC->CMR &= ~FMC_CMR_OBER ; - } - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Config the Read Out Protection bit. - * @param FMC_ReadProtection_Level: The Read Out Protection level. - * This parameter can be: - * @arg RDP_LEVEL_0: No protection - * @arg RDP_LEVEL_1: Read Outprotection of the memory - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_OB_RDPConfig(uint8_t OB_RDP) -{ - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - FMC->CMR |= FMC_CMR_OBER; - FMC->CMR |= FMC_CMR_START; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Reset the OBER bit */ - FMC->CMR &= ~FMC_CMR_OBER; - - /* Start the Option Bytes Programming */ - FMC->CMR |= FMC_CMR_OBPG; - - OB->RDP = OB_RDP; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } else { - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBER Bit */ - FMC->CMR &= ~FMC_CMR_OBER; - } - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Program the FMC User Option Byte: IWDG_SW / RST_DEEPSLEEP / RST_STDBY. - * @param OB_IWDG: Config the WDG mode - * @arg OB_IWDG_SW: Software WDG selected - * @arg OB_IWDG_HW: Hardware WDG selected - * @param OB_DEEPSLEEP: Config Reset event when entering DEEPSLEEP mode. - * @arg OB_DEEPSLEEP_NORST: No reset generated when entering in DEEPSLEEP - * @arg OB_DEEPSLEEP_RST: Reset generated when entering in DEEPSLEEP - * @param OB_STDBY: Config Reset event when entering Standby mode. - * @arg OB_STDBY_NORST: No reset generated when entering in STANDBY - * @arg OB_STDBY_RST: Reset generated when entering in STANDBY - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_OB_UserConfig(uint8_t OB_IWDG, uint8_t OB_DEEPSLEEP, uint8_t OB_STDBY) -{ - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Set the OBPG bit*/ - FMC->CMR |= FMC_CMR_OBPG; - - OB->USER = (uint16_t)((uint16_t)(OB_IWDG | OB_DEEPSLEEP) | (uint16_t)(OB_STDBY | 0xF8)); - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Program the BOOT option bit. - * @param OB_BOOT: The legal parameter can be one of the following value: - * @arg OB_BOOT_B1:Start up from Bank1 - * @arg OB_BOOT_B2:Start up from Bank2 - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_OB_BOOTConfig(uint8_t OB_BOOT) -{ - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - FMC->OBKEYR = FMC_KEY1; - FMC->OBKEYR = FMC_KEY2; - - if (temp_state == FMC_READY) { - /* Set the OBPG bit*/ - FMC->CMR |= FMC_CMR_OBPG; - - if (OB_BOOT == OB_BOOT_B1) { - OB->USER |= OB_USER_BFB2; - } else { - OB->USER &= (uint16_t)(~(uint16_t)(OB_USER_BFB2)); - } - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Program the FMC User Option Byte. - * @param OB_USER: Select all user option byte - * The legal parameter is one of the following values: - * @arg OB_IWDG_SW - * @arg OB_IWDG_HW - * @arg OB_DEEPSLEEP_NORST - * @arg OB_DEEPSLEEP_RST - * @arg OB_STDBY_NORST - * @arg OB_STDBY_RST - * @arg OB_BOOT_B1 - * @arg OB_BOOT_B2 - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_OB_WriteUser(uint8_t OB_USER) -{ - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* Set the OBPG bit */ - FMC->CMR |= FMC_CMR_OBPG; - - OB->USER = OB_USER | 0xf0; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OBPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Program Option Byte Data. - * @param Address: The Option Byte address to be programmed. - * The legal parameter can be 0x1FFFF804 or 0x1FFFF806. - * @param Data: The Byte to be programmed. - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_ProgramOptionByteData(uint32_t Address, uint8_t Data) -{ - FMC_State temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state == FMC_READY) { - /* SET the OPTPG bit */ - FMC->CMR |= FMC_CMR_OBPG; - *(__IO uint16_t *)Address = Data; - - /* Wait for the FMC ready */ - temp_state = FMC_WaitReady(FMC_TIMEOUT_COUNT); - - if (temp_state != FMC_TIMEOUT_ERR) { - /* Reset the OPTPG bit */ - FMC->CMR &= ~FMC_CMR_OBPG; - } - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Get the FMC User Option Byte. - * @param None - * @retval The FMC User Option Byte. - */ -uint8_t FMC_OB_GetUser(void) -{ - return (uint8_t)(FMC->OPTR >> 8); -} - -/** - * @brief Get the FMC Write Protection Option Byte. - * @param None - * @retval The FMC Write Protection Option Byte - */ -uint32_t FMC_OB_GetWRP(void) -{ - return (uint32_t)(FMC->WPR); -} - -/** - * @brief Check whether the FMC Read out Protection Status is SET or RESET. - * @param None - * @retval FMC ReadOut Protection state - */ -TypeState FMC_OB_GetRDP(void) -{ - TypeState RDPState = RESET; - - if ((uint8_t)(FMC->OPTR & (FMC_OPTR_PLEVEL1)) != RESET) { - RDPState = SET; - } else { - RDPState = RESET; - } - return RDPState; -} - -/** - * @} - */ - -/** @defgroup FMC_Group3 Interrupts and flags management functions - * @brief Interrupts and flags management functions - * -@verbatim - =============================================================================== - ##### Interrupts and flags management functions ##### - =============================================================================== - -@endverbatim - * @{ - */ - -/** - * @brief Enable or disable the corresponding FMC interrupt source. - * @param FMC_INT: The FMC interrupt source to be enabled or disabled. - * This parameter can be any combination of the following values: - * @arg FMC_INT_EOP: FMC end of programming Interrupt - * @arg FMC_INT_ERR: FMC Error Interrupt - * @arg FMC_INT_B2_EOP: FMC end of programming Interrupt - * @arg FMC_INT_B2_ERR: FMC Error Interrupt - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void FMC_INTConfig(uint32_t FMC_INT, TypeState NewValue) -{ - - if (FMC_SIZE > FMC_BANK1_SIZE) { - if ((FMC_INT & 0x80000000) != 0x0) { - if (NewValue != DISABLE) { - /* Enable the interrupt sources */ - FMC->CMR2 |= (FMC_INT & 0x7fffffff); - } else { - /* Disable the interrupt sources */ - FMC->CMR2 &= ~(uint32_t)(FMC_INT & 0x7fffffff); - } - } else { - if (NewValue != DISABLE) { - /* Enable the interrupt sources */ - FMC->CMR |= FMC_INT; - } else { - /* Disable the interrupt sources */ - FMC->CMR &= ~(uint32_t)FMC_INT; - } - } - } else { - if (NewValue != DISABLE) { - /* Enable the interrupt sources */ - FMC->CMR |= FMC_INT; - } else { - /* Disable the interrupt sources */ - FMC->CMR &= ~(uint32_t)FMC_INT; - } - } -} - -/** - * @brief Checks whether the FMC flag is SET or RESET. - * @param FMC_FLAG: the corresponding FMC flag. - * the legal parameter can be: - * @arg FMC_FLAG_BSY: FMC BUSY flag - * @arg FMC_FLAG_PERR: FMC Programming error flag flag - * @arg FMC_FLAG_WERR: FMC Write protection error flag - * @arg FMC_FLAG_EOP: FMC End of Programming flag - * @arg FMC_FLAG_OPTER: FMC option byte error flag - * @retval The state of the FMC flag. - */ -TypeState FMC_GetBitState(uint32_t FMC_FLAG) -{ - if (FMC_SIZE > FMC_BANK1_SIZE) { - /* Check the parameters */ - if (FMC_FLAG == FMC_FLAG_OPTERR) { - if ((FMC->OPTR & FMC_FLAG_OPTERR) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } - } else { - if ((FMC_FLAG & 0x80000000) != 0x0) { - if ((FMC->CSR2 & FMC_FLAG) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } - } else { - if ((FMC->CSR & FMC_FLAG) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } - } - } - } else { - if (FMC_FLAG == FMC_FLAG_OPTERR) { - if ((FMC->OPTR & FMC_FLAG_OPTERR) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } - } else { - if ((FMC->CSR & FMC_FLAG) != (uint32_t)RESET) { - return SET; - } - /* Return the state of corresponding FMC flag */ - else { - return RESET; - } - } - } -} - -/** - * @brief Clear the FMC pending flag. - * @param FMC_FLAG: clear the corresponding FMC flag. - * @arg FMC_FLAG_PERR: Programming error flag flag - * @arg FMC_FLAG_WERR: Write protection error flag - * @arg FMC_FLAG_EOP: End of Programming flag - * @retval None - */ -void FMC_ClearBitState(uint32_t FMC_FLAG) -{ - if (FMC_SIZE > FMC_BANK1_SIZE) { - if ((FMC_FLAG & 0x80000000) != 0x0) { - /* Clear the flags */ - FMC->CSR2 = FMC_FLAG; - } else { - /* Clear the flags */ - FMC->CSR = FMC_FLAG; - } - } else { - FMC->CSR = FMC_FLAG; - } -} - -/** - * @brief Return the FMC state. - * @param None - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, or FMC_PGERR - */ -FMC_State FMC_GetState(void) -{ - FMC_State temp_state = FMC_READY; - - if ((FMC->CSR & FMC_CSR_BUSY) == FMC_CSR_BUSY) { - temp_state = FMC_BSY; - } else { - if ((FMC->CSR & (uint32_t)FMC_CSR_WPEF) != (uint32_t)0x00) { - temp_state = FMC_WRPERR; - } else { - if ((FMC->CSR & (uint32_t)(FMC_CSR_PGEF)) != (uint32_t)0x00) { - temp_state = FMC_PGERR; - } else { - temp_state = FMC_READY; - } - } - } - - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Return the FMC bak1 state. - * @param None - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, or FMC_PGERR - */ -FMC_State FMC_GetB1State(void) -{ - FMC_State temp_state = FMC_READY; - - if ((FMC->CSR & FMC_CSR_BUSY) == FMC_CSR_BUSY) { - temp_state = FMC_BSY; - } else { - if ((FMC->CSR & (uint32_t)FMC_CSR_WPEF) != (uint32_t)0x00) { - temp_state = FMC_WRPERR; - } else { - if ((FMC->CSR & (uint32_t)(FMC_CSR_PGEF)) != (uint32_t)0x00) { - temp_state = FMC_PGERR; - } else { - temp_state = FMC_READY; - } - } - } - return temp_state; -} - -/** - * @brief Return the FMC bak2 state. - * @param None - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, or FMC_PGERR - */ - -FMC_State FMC_GetB2State(void) -{ - - FMC_State temp_state = FMC_READY; - - if ((FMC->CSR2 & FMC_CSR2_BUSY & 0x7fffffff) == (FMC_CSR2_BUSY & 0x7fffffff)) { - temp_state = FMC_BSY; - } else { - if ((FMC->CSR2 & FMC_CSR2_WPEF & 0x7fffffff) != (uint32_t)0x00) { - temp_state = FMC_WRPERR; - } else { - if ((FMC->CSR2 & FMC_CSR2_PGEF & 0x7fffffff) != (uint32_t)0x00) { - temp_state = FMC_PGERR; - } else { - temp_state = FMC_READY; - } - } - } - - /* Return the FMC state */ - return temp_state; -} - - -/** - * @brief Check whether FMC is ready or not. - * @param Timeout: Count of loop - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_WaitReady(uint32_t uCount) -{ - FMC_State temp_state = FMC_BSY; - - /* Wait for FMC ready */ - do { - /* Get FMC state */ - temp_state = FMC_GetState(); - uCount--; - } while ((temp_state == FMC_BSY) && (uCount != 0x00)); - - if (temp_state == FMC_BSY) { - temp_state = FMC_TIMEOUT_ERR; - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Check whether FMC Bank1 is ready or not. - * @param Timeout: Count of loop - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ -FMC_State FMC_B1_WaitReady(uint32_t uCount) -{ - FMC_State temp_state = FMC_BSY; - - /* Wait for FMC ready */ - do { - /* Get FMC state */ - temp_state = FMC_GetB1State(); - uCount--; - } while ((temp_state == FMC_BSY) && (uCount != 0x00)); - - if (temp_state == FMC_BSY) { - temp_state = FMC_TIMEOUT_ERR; - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @brief Check whether FMC Bank2 is ready or not. - * @param Timeout: Count of loop - * @retval FMC state: FMC_READY, FMC_BSY, FMC_WRPERR, FMC_PGERR or FMC_TIMEOUT_ERR. - */ - -FMC_State FMC_B2_WaitReady(uint32_t uCount) -{ - FMC_State temp_state = FMC_BSY; - - /* Wait for FMC ready */ - do { - /* Get FMC state */ - temp_state = FMC_GetB2State(); - uCount--; - } while ((temp_state == (FMC_BSY && 0x7FFFFFFF)) && (uCount != 0x00)); - - if (temp_state == FMC_BSY) { - temp_state = FMC_TIMEOUT_ERR; - } - /* Return the FMC state */ - return temp_state; -} - -/** - * @} - */ - -/** - * @} - */ - -/** -* @} -*/ - -/** - * @} - */ diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_gpio.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_gpio.c deleted file mode 100644 index 99a16e4d43..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_gpio.c +++ /dev/null @@ -1,511 +0,0 @@ -/** - ****************************************************************************** - * @brief GPIO functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_gpio.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup GPIO - * @brief GPIO driver modules - * @{ - */ - -/** @defgroup GPIO_Private_Defines - * @{ - */ -#define ECR_PORTPINCONFIG_MASK ((uint16_t)0xFF80) -#define LSB_MASK ((uint16_t)0xFFFF) -#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000) -#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF) -#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000) -#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000) -#define AFIO_PCFR1_MII_RMII ((uint32_t)0x00800000) -#define AFIO_ESSR1_BITS_FIELDS ((uint8_t)0x04) -#define AFIO_ESSR2_BITS_FIELDS ((uint8_t)0x08) -#define AFIO_ESSR3_BITS_FIELDS ((uint8_t)0x0c) -#define AFIO_ESSR_PIN_FIELDS ((uint8_t)0x04) -#define AFIO_ESSR_4BIT_FIELDS ((uint8_t)0x0f) -#define CTLR1_8BIT_FIELDS ((uint32_t)0x00ff) -#define CTLR2_8BIT_FIELDS ((uint32_t)0x00ff) -#define AFIO_PCFR2_FIELDS ((uint32_t)0x80000000) - -/** - * @} - */ - -/** @defgroup GPIO_Private_Functions - * @{ - */ - -/** - * @brief Reset the GPIOx peripheral. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @retval None - */ -void GPIO_DeInit(GPIO_TypeDef *GPIOx) -{ - if (GPIOx == GPIOA) { - /* Enable GPIOA reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOA, ENABLE); - /* Release GPIOA from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOA, DISABLE); - } else if (GPIOx == GPIOB) { - /* Enable GPIOB reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOB, ENABLE); - /* Release GPIOB from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOB, DISABLE); - } else if (GPIOx == GPIOC) { - /* Enable GPIOC reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOC, ENABLE); - /* Release GPIOC from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOC, DISABLE); - } else if (GPIOx == GPIOD) { - /* Enable GPIOD reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOD, ENABLE); - /* Release GPIOD from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOD, DISABLE); - } else if (GPIOx == GPIOE) { - /* Enable GPIOE reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOE, ENABLE); - /* Release GPIOE from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOE, DISABLE); - } else if (GPIOx == GPIOF) { - /* Enable GPIOF reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOF, ENABLE); - /* Release GPIOF from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOF, DISABLE); - } else if (GPIOx == GPIOG) { - /* Enable GPIOG reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOG, ENABLE); - /* Release GPIOG from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_GPIOG, DISABLE); - } -} - -/** - * @brief Deinitialize the Alternate Functions (remap, event control - * and EXTI configuration) registers to their default reset values. - * @param None - * @retval None - */ -void GPIO_AFDeInit(void) -{ - /* Enable AFIO reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_AF, ENABLE); - /* Release AFIO from reset state */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_AF, DISABLE); -} - -/** - * @brief Initialize the GPIOx peripheral. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param GPIO_InitStruct: The structuer contains configuration information. - * @retval None - */ -void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitPara *GPIO_InitStruct) -{ - uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; - uint32_t tempreg = 0x00, pinmask = 0x00; - - /* GPIO Mode Configuration */ - currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); - if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) { - /* Output mode */ - currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; - } - /* GPIO CTLR1 Configuration */ - /* Configure the eight low port pins */ - if (((uint32_t)GPIO_InitStruct->GPIO_Pin & CTLR1_8BIT_FIELDS) != 0x00) { - tempreg = GPIOx->CTLR1; - for (pinpos = 0x00; pinpos < 0x08; pinpos++) { - pos = ((uint32_t)0x01) << pinpos; - /* Get the port pins position */ - currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; - if (currentpin == pos) { - pos = pinpos << 2; - /* Clear the corresponding low control register bits */ - pinmask = ((uint32_t)0x0F) << pos; - tempreg &= ~pinmask; - /* Write the mode configuration in the corresponding bits */ - tempreg |= (currentmode << pos); - /* Reset the corresponding ODR bit */ - if (GPIO_InitStruct->GPIO_Mode == GPIO_MODE_IPD) { - GPIOx->BCR = (((uint32_t)0x01) << pinpos); - } else { - /* Set the corresponding ODR bit */ - if (GPIO_InitStruct->GPIO_Mode == GPIO_MODE_IPU) { - GPIOx->BOR = (((uint32_t)0x01) << pinpos); - } - } - } - } - GPIOx->CTLR1 = tempreg; - } - /* GPIO CTLR2 Configuration */ - /* Configure the eight high port pins */ - if (GPIO_InitStruct->GPIO_Pin > CTLR2_8BIT_FIELDS) { - tempreg = GPIOx->CTLR2; - for (pinpos = 0x00; pinpos < 0x08; pinpos++) { - pos = (((uint32_t)0x01) << (pinpos + 0x08)); - /* Get the port pins position */ - currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos); - if (currentpin == pos) { - pos = pinpos << 2; - /* Clear the corresponding high control register bits */ - pinmask = ((uint32_t)0x0F) << pos; - tempreg &= ~pinmask; - /* Write the mode configuration in the corresponding bits */ - tempreg |= (currentmode << pos); - /* Reset the corresponding DOR bit */ - if (GPIO_InitStruct->GPIO_Mode == GPIO_MODE_IPD) { - GPIOx->BCR = (((uint32_t)0x01) << (pinpos + 0x08)); - } - /* Set the corresponding DOR bit */ - if (GPIO_InitStruct->GPIO_Mode == GPIO_MODE_IPU) { - GPIOx->BOR = (((uint32_t)0x01) << (pinpos + 0x08)); - } - } - } - GPIOx->CTLR2 = tempreg; - } -} - -/** - * @brief Initial GPIO_InitParameter members. - * @param GPIO_InitParameter : pointer to a GPIO_InitPara structure. - * @retval None - */ -void GPIO_ParaInit(GPIO_InitPara *GPIO_InitStruct) -{ - /* Reset GPIO init structure parameters values */ - GPIO_InitStruct->GPIO_Pin = GPIO_PIN_ALL; - GPIO_InitStruct->GPIO_Speed = GPIO_SPEED_2MHZ; - GPIO_InitStruct->GPIO_Mode = GPIO_MODE_IN_FLOATING; -} - -/** - * @brief Read the select input port. - * @param GPIOx: Select the GPIO peripheral. - * @param GPIO_Pin: Select the port. - * @retval The input port pin value. - */ -uint8_t GPIO_ReadInputBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) -{ - uint8_t bitstatus = 0x00; - - if ((GPIOx->DIR & GPIO_Pin) != (uint32_t)Bit_RESET) { - bitstatus = (uint8_t)Bit_SET; - } else { - bitstatus = (uint8_t)Bit_RESET; - } - return bitstatus; -} - -/** - * @brief Read the specified GPIO input data port. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @retval GPIO input data port value. - */ -uint16_t GPIO_ReadInputData(GPIO_TypeDef *GPIOx) -{ - return ((uint16_t)GPIOx->DIR); -} - -/** - * @brief Read the specified output data port bit. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param GPIO_Pin: where pin can be (GPIO_PIN_0..GPIO_PIN_15) to select the GPIO peripheral. - * @retval The output port pin value. - */ -uint8_t GPIO_ReadOutputBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) -{ - uint8_t bitstatus = 0x00; - - if ((GPIOx->DOR & GPIO_Pin) != (uint32_t)Bit_RESET) { - bitstatus = (uint8_t)Bit_SET; - } else { - bitstatus = (uint8_t)Bit_RESET; - } - return bitstatus; -} - -/** - * @brief Read the specified GPIO output data port. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @retval GPIO output data port value. - */ -uint16_t GPIO_ReadOutputData(GPIO_TypeDef *GPIOx) -{ - return ((uint16_t)GPIOx->DOR); -} - -/** - * @brief Set the selected data port bits. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param GPIO_Pin: where pin can be (GPIO_PIN_0..GPIO_PIN_15) to select the GPIO peripheral. - * @retval None - */ -void GPIO_SetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) -{ - GPIOx->BOR = GPIO_Pin; -} - -/** - * @brief Clear the selected data port bits. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param GPIO_Pin: where pin can be (GPIO_PIN_0..GPIO_PIN_15) to select the GPIO peripheral. - * @retval None - */ -void GPIO_ResetBits(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) -{ - GPIOx->BCR = GPIO_Pin; -} - -/** - * @brief Set or clear the selected data port bit. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param GPIO_Pin: where pin can be (GPIO_PIN_0..GPIO_PIN_15) to select the GPIO peripheral. - * @param BitVal: specifies the state of the port.Select one of the follwing values : - * @arg Bit_RESET: clear the port pin - * @arg Bit_SET: set the port pin - * @retval None - */ -void GPIO_WriteBit(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, BitState BitVal) -{ - if (BitVal != Bit_RESET) { - GPIOx->BOR = GPIO_Pin; - } else { - GPIOx->BCR = GPIO_Pin; - } -} - -/** - * @brief Write data to the specified GPIO data port. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param PortVal: specifies the value to be written to the port data output register. - * @retval None - */ -void GPIO_WritePort(GPIO_TypeDef *GPIOx, uint16_t PortVal) -{ - GPIOx->DOR = PortVal; -} - -/** - * @brief Lock GPIO Pins configuration. - * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. - * @param GPIO_Pin: where pin can be (GPIO_PIN_0..GPIO_PIN_15) to select the GPIO peripheral. - * @retval None - */ -void GPIO_PinLockConfig(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) -{ - uint32_t temp = 0x00010000; - - temp |= GPIO_Pin; - /* Set LCKK bit */ - GPIOx->LOCKR = temp; - /* Reset LCKK bit */ - GPIOx->LOCKR = GPIO_Pin; - /* Set LCKK bit */ - GPIOx->LOCKR = temp; - /* Read LCKK bit*/ - temp = GPIOx->LOCKR; - /* Read LCKK bit*/ - temp = GPIOx->LOCKR; -} - -/** - * @brief Select the GPIO pin used as Event output. - * @param GPIO_PortSource: This parameter can be GPIO_PORT_SOURCE_GPIOx where x can be (A..G). - * @param GPIO_PinSource: This parameter can be GPIO_PINSOURCEx where x can be (0..15). - * @retval None - */ -void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) -{ - uint32_t temp = 0x00; - - temp = AFIO->AFIO_EVR; - /* Clear the PORT[6:4] and PIN[3:0] bits */ - temp &= ECR_PORTPINCONFIG_MASK; - temp |= (uint32_t)GPIO_PortSource << 0x04; - temp |= GPIO_PinSource; - AFIO->AFIO_EVR = temp; -} - -/** - * @brief Enable or disable the Event Output. - * @param AFIO_Event: AFIO_Event Enable or Disable bit. - * @param NewState: new state of the Event output. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void GPIO_EventOutput_Enable(uint32_t AFIO_Event, TypeState NewState) -{ - /* Enable or disable the Event Output */ - if (NewState != DISABLE) { - AFIO->AFIO_EVR |= AFIO_ECR_EVOE_SET; - } else { - AFIO->AFIO_EVR &= AFIO_ECR_EVOE_RESET; - } -} - -/** - * @brief Change the mapping of the specified pin. - * @param GPIO_Remap: selects the pin to remap. - * This parameter can be one of the following values: - * @arg GPIO_REMAP_SPI1 - * @arg GPIO_REMAP_I2C1 - * @arg GPIO_REMAP_USART1 - * @arg GPIO_REMAP_USART2 - * @arg GPIO_PARTIAL_REMAP_USART3 - * @arg GPIO_FULL_REMAP_USART3 - * @arg GPIO_PARTIAL_REMAP_TIMER1 - * @arg GPIO_FULL_REMAP_TIMER1 - * @arg GPIO_PARTIAL_REMAP1_TIMER2 - * @arg GPIO_PARTIAL_REMAP2_TIMER2 - * @arg GPIO_FULL_REMAP_TIMER2 - * @arg GPIO_PARTIAL_REMAP_TIMER3 - * @arg GPIO_FULL_REMAP_TIMER3 - * @arg GPIO_REMAP_TIMER4 - * @arg GPIO_REMAP1_CAN1 - * @arg GPIO_REMAP2_CAN1 - * @arg GPIO_REMAP_PD01 - * @arg GPIO_REMAP_TIMER5CH4_LSI - * @arg GPIO_REMAP_ADC1_ETRGINJ - * @arg GPIO_REMAP_ADC1_ETRGREG - * @arg GPIO_REMAP_ADC2_ETRGINJ - * @arg GPIO_REMAP_ADC2_ETRGREG - * @arg GPIO_REMAP_ETH - * @arg GPIO_REMAP_CAN2 - * @arg GPIO_REMAP_SWJ_NOJTRST - * @arg GPIO_REMAP_SWJ_JTAGDISABLE - * @arg GPIO_REMAP_SWJ_DISABLE - * @arg GPIO_REMAP_SPI3 - * @arg GPIO_REMAP_TIMER2ITR1_PTP_SOF - * @arg GPIO_REMAP_PTP_PPS - * @arg GPIO_REMAP_TIMER15 - * @arg GPIO_REMAP_TIMER16 - * @arg GPIO_REMAP_TIMER17 - * @arg GPIO_REMAP_CEC - * @arg GPIO_REMAP_TIMER1_DMA - * @arg GPIO_REMAP_TIMER9 - * @arg GPIO_REMAP_TIMER10 - * @arg GPIO_REMAP_TIMER11 - * @arg GPIO_REMAP_TIMER13 - * @arg GPIO_REMAP_TIMER14 - * @arg GPIO_REMAP_EXMC_NADV - * @arg GPIO_REMAP_TIMER67_DAC_DMA - * @arg GPIO_REMAP_TIMER12 - * @arg GPIO_REMAP_MISC - * @param NewState: new state of the port pin remapping. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void GPIO_PinRemapConfig(uint32_t GPIO_Remap, TypeState NewState) -{ - uint32_t temp = 0x00, temp1 = 0x00, tempreg = 0x00, tempmask = 0x00; - - if ((GPIO_Remap & 0x80000000) == 0x80000000) { - tempreg = AFIO->AFIO_PCFR2; - } else { - tempreg = AFIO->AFIO_PCFR1; - } - - tempmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10; - temp = GPIO_Remap & LSB_MASK; - - if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) { - tempreg &= DBGAFR_SWJCFG_MASK; - AFIO->AFIO_PCFR1 &= DBGAFR_SWJCFG_MASK; - } else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) { - temp1 = ((uint32_t)0x03) << tempmask; - tempreg &= ~temp1; - tempreg |= ~DBGAFR_SWJCFG_MASK; - } else { - tempreg &= ~(temp << ((GPIO_Remap >> 0x15) * 0x10)); - tempreg |= ~DBGAFR_SWJCFG_MASK; - } - if (NewState != DISABLE) { - tempreg |= (temp << ((GPIO_Remap >> 0x15) * 0x10)); - } - if ((GPIO_Remap & AFIO_PCFR2_FIELDS) == AFIO_PCFR2_FIELDS) { - AFIO->AFIO_PCFR2 = tempreg; - } else { - AFIO->AFIO_PCFR1 = tempreg; - } -} - -/** - * @brief Select the GPIO pin used as EXTI Line. - * @param GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines. - * This parameter can be GPIO_PORT_SOURCE_GPIOx where x can be (A..G). - * @param GPIO_PinSource: specifies the EXTI line to be configured. - * This parameter can be GPIO_PINSOURCEx where x can be (0..15). - * @retval None - */ -void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) -{ - uint32_t temp = 0x00; - - temp = ((uint32_t)0x0f) << (AFIO_ESSR_PIN_FIELDS * (GPIO_PinSource & (uint8_t)0x03)); - /* Select EXTI0->EXTI3 bit */ - if (GPIO_PinSource < AFIO_ESSR1_BITS_FIELDS) { - AFIO->AFIO_ESSR1 &= ~temp; - AFIO->AFIO_ESSR1 |= (((uint32_t)GPIO_PortSource) << (AFIO_ESSR_PIN_FIELDS * (GPIO_PinSource & (uint8_t)0x03))); - } - /* Select EXTI4->EXTI7 bit */ - else if (GPIO_PinSource < AFIO_ESSR2_BITS_FIELDS) { - AFIO->AFIO_ESSR2 &= ~temp; - AFIO->AFIO_ESSR2 |= (((uint32_t)GPIO_PortSource) << (AFIO_ESSR_PIN_FIELDS * (GPIO_PinSource & (uint8_t)0x03))); - } - /* Select EXTI8->EXTI11 bit */ - else if (GPIO_PinSource < AFIO_ESSR3_BITS_FIELDS) { - AFIO->AFIO_ESSR3 &= ~temp; - AFIO->AFIO_ESSR3 |= (((uint32_t)GPIO_PortSource) << (AFIO_ESSR_PIN_FIELDS * (GPIO_PinSource & (uint8_t)0x03))); - } - /* Select EXTI12->EXTI15 bit */ - else { - AFIO->AFIO_ESSR4 &= ~temp; - AFIO->AFIO_ESSR4 |= (((uint32_t)GPIO_PortSource) << (AFIO_ESSR_PIN_FIELDS * (GPIO_PinSource & (uint8_t)0x03))); - } -} - -/** - * @brief Select the Ethernet media interface. - * @note This function applies only to GD32 Connectivity line devices. - * @param GPIO_ETH_MediaInterface: specifies the Media Interface mode. - * This parameter can be one of the following values: - * @arg GPIO_ETH_MEDIA_INTERFACE_MII: MII mode - * @arg GPIO_ETH_MEDIA_INTERFACE_RMII: RMII mode - * @retval None - */ -void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface) -{ - uint32_t temp = 0; - temp = AFIO->AFIO_PCFR1; - /* Clear MII_RMII_SEL bit */ - temp &= ~((uint32_t)AFIO_PCFR1_MII_RMII); - /* Configure MII_RMII bit according to GPIO_ETH_MediaInterface value */ - temp |= GPIO_ETH_MediaInterface; - /* Store the new value */ - AFIO->AFIO_PCFR1 = temp; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_i2c.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_i2c.c deleted file mode 100644 index efc83ed26f..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_i2c.c +++ /dev/null @@ -1,899 +0,0 @@ -/** - ****************************************************************************** - * @brief I2C functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_i2c.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup I2C - * @brief I2C driver modules - * @{ - */ - -/** @defgroup I2C_Private_Defines - * @{ - */ - -/* I2C CTLR1_I2CEN mask */ -#define CTLR1_I2CEN_SET I2C_CTLR1_I2CEN -#define CTLR1_I2CEN_RESET ((uint16_t)~I2C_CTLR1_I2CEN) - -/* I2C CTLR1_GENSTA mask */ -#define CTLR1_GENSTA_SET I2C_CTLR1_GENSTA -#define CTLR1_GENSTA_RESET ((uint16_t)~I2C_CTLR1_GENSTA) - -/* I2C CTLR1_GENSTP mask */ -#define CTLR1_GENSTP_SET I2C_CTLR1_GENSTP -#define CTLR1_GENSTP_RESET ((uint16_t)~I2C_CTLR1_GENSTP) - -/* I2C CTLR1_ACKEN mask */ -#define CTLR1_ACKEN_SET I2C_CTLR1_ACKEN -#define CTLR1_ACKEN_RESET ((uint16_t)~I2C_CTLR1_ACKEN) - -/* I2C CTLR1_GCEN mask */ -#define CTLR1_GCEN_SET I2C_CTLR1_GCEN -#define CTLR1_GCEN_RESET ((uint16_t)~I2C_CTLR1_GCEN) - -/* I2C CTLR1_SRESET mask */ -#define CTLR1_SRESET_SET I2C_CTLR1_SRESET -#define CTLR1_SRESET_RESET ((uint16_t)~I2C_CTLR1_SRESET) - -/* I2C CTLR1_SALT mask */ -#define CTLR1_SALT_SET I2C_CTLR1_SALT -#define CTLR1_SALT_RESET ((uint16_t)~I2C_CTLR1_SALT) - -/* I2C CTLR1_PECTRANS mask */ -#define CTLR1_PECTRANS_SET I2C_CTLR1_PECTRANS -#define CTLR1_PECTRANS_RESET ((uint16_t)~I2C_CTLR1_PECTRANS) - -/* I2C CTLR1_PECEN mask */ -#define CTLR1_PECEN_SET I2C_CTLR1_PECEN -#define CTLR1_PECEN_RESET ((uint16_t)~I2C_CTLR1_PECEN) - -/* I2C CTLR1_ARPEN mask */ -#define CTLR1_ARPEN_SET I2C_CTLR1_ARPEN -#define CTLR1_ARPEN_RESET ((uint16_t)~I2C_CTLR1_ARPEN) - -/* I2C CTLR1_DISSTRC mask */ -#define CTLR1_DISSTRC_SET I2C_CTLR1_DISSTRC -#define CTLR1_DISSTRC_RESET ((uint16_t)~I2C_CTLR1_DISSTRC) - -/* I2C registers Masks */ -#define CTLR1_CLEAR_MASK ((uint16_t)0xFBF5) - -/* I2C CTLR2_DMAON mask */ -#define CTLR2_DMAON_SET I2C_CTLR2_DMAON -#define CTLR2_DMAON_RESET ((uint16_t)~I2C_CTLR2_DMAON) - -/* I2C CTLR2_DMALST mask */ -#define CTLR2_DMALST_SET I2C_CTLR2_DMALST -#define CTLR2_DMALST_RESET ((uint16_t)~I2C_CTLR2_DMALST) - -/* I2C CTLR2_I2CCLK mask */ -#define CTLR2_I2CCLK_RESET ((uint16_t)0xFFC0) - -/* I2C I2CCLK_Freq_MAX */ -#define I2CCLK_FREQ_MAX I2C_CTLR2_I2CCLK - -/* I2C AR1_ADDRESS0 mask */ -#define AR1_ADDRESS0_SET I2C_AR1_ADDRESS0 -#define AR1_ADDRESS0_RESET ((uint16_t)~I2C_AR1_ADDRESS0) - -/* I2C AR2_DUADEN mask */ -#define AR2_DUADEN_SET ((uint16_t)0x0001) -#define AR2_DUADEN_RESET ((uint16_t)0xFFFE) - -/* I2C AR2_ADDRESS2 mask */ -#define AR2_ADDRESS2_RESET ((uint16_t)0xFF01) - -/* I2C CLKR_FAST mask */ -#define CLKR_FAST_SET ((uint16_t)0x8000) - -/* I2C CLKR_CLKC mask */ -#define CLKR_CLKC_SET ((uint16_t)0x0FFF) - -/* I2C STR_FLAG mask */ -#define STR_FLAG_MASK ((uint32_t)0x00FFFFFF) - -/* I2C Interrupt Enable mask */ -#define INTEN_MASK ((uint32_t)0x07000000) - -/** - * @} - */ - -/** @defgroup I2C_Private_Functions - * @{ - */ - -/** - * @brief Reset the I2Cx interface. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @retval None. - */ -void I2C_DeInit(I2C_TypeDef *I2Cx) -{ - if (I2Cx == I2C1) { - /* Enable I2C1 reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_I2C1RST, ENABLE); - /* Release I2C1 from reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_I2C1RST, DISABLE); - } else { - /* Enable I2C2 reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_I2C2RST, ENABLE); - /* Release I2C2 from reset state */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_I2C2RST, DISABLE); - } -} - -/** - * @brief Initialize the I2Cx interface parameters. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_InitParaStruct: the sturct I2C_InitPara pointer. - * @retval None. - */ -void I2C_Init(I2C_TypeDef *I2Cx, I2C_InitPara *I2C_InitParaStruct) -{ - uint16_t temp = 0, freqrange = 0; - uint16_t result = 0x04; - uint32_t pclk1 = 8000000; - RCC_ClocksPara rcc_clocks; - - /* Disable I2C */ - I2Cx->CTLR1 &= CTLR1_I2CEN_RESET; - - /* CTLR2 */ - temp = I2Cx->CTLR2; - - /* I2CCLK[5:0] */ - temp &= CTLR2_I2CCLK_RESET; - RCC_GetClocksFreq(&rcc_clocks); - pclk1 = rcc_clocks.APB1_Frequency; - freqrange = (uint16_t)(pclk1 / 1000000); - if (freqrange > I2CCLK_FREQ_MAX) { - freqrange = I2CCLK_FREQ_MAX; - } - temp |= freqrange; - I2Cx->CTLR2 = temp; - - /* RTR and CLKR */ - temp = 0; - - if (I2C_InitParaStruct->I2C_BitRate <= 100000) { - /* Standard mode */ - result = (uint16_t)(pclk1 / (I2C_InitParaStruct->I2C_BitRate << 1)); - if (result < 0x04) { - /* The CLKR.CLKC higher than 0x04 in standard mode*/ - result = 0x04; - } - temp |= result; - I2Cx->CLKR = temp; - - /* RTR */ - if (freqrange >= I2CCLK_FREQ_MAX) { - I2Cx->RTR = I2CCLK_FREQ_MAX; - } else { - I2Cx->RTR = freqrange + 1; - } - } else { - /* Fast mode */ - if (I2C_InitParaStruct->I2C_DutyCycle == I2C_DUTYCYCLE_2) { - /* I2C_DutyCycle == 2 */ - result = (uint16_t)(pclk1 / (I2C_InitParaStruct->I2C_BitRate * 3)); - } else { - /* I2C_DutyCycle == 16/9 */ - result = (uint16_t)(pclk1 / (I2C_InitParaStruct->I2C_BitRate * 25)); - result |= I2C_DUTYCYCLE_16_9; - } - - if ((result & CLKR_CLKC_SET) == 0) { - /* The CLKR.CLKC higher than 0x01 in fast mode*/ - result |= (uint16_t)0x0001; - } - temp |= (uint16_t)(result | CLKR_FAST_SET); - - /* RTR */ - I2Cx->RTR = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1); - } - I2Cx->CLKR = temp; - - /* CTLR1 */ - I2Cx->CTLR1 |= CTLR1_I2CEN_SET; - - temp = I2Cx->CTLR1; - temp &= CTLR1_CLEAR_MASK; - temp |= (uint16_t)((uint32_t)I2C_InitParaStruct->I2C_Protocol | CTLR1_ACKEN_SET); - I2Cx->CTLR1 = temp; - - /* AR1 */ - I2Cx->AR1 = (I2C_InitParaStruct->I2C_AddressingMode | I2C_InitParaStruct->I2C_DeviceAddress); -} - -/** - * @brief Initial the sturct I2C_InitPara. - * @param I2C_InitParaStruct: the sturct I2C_InitPara pointer. - * @retval None. - */ -void I2C_ParaInit(I2C_InitPara *I2C_InitParaStruct) -{ - I2C_InitParaStruct->I2C_Protocol = I2C_PROTOCOL_I2C; - I2C_InitParaStruct->I2C_DutyCycle = I2C_DUTYCYCLE_2; - I2C_InitParaStruct->I2C_BitRate = 10000; - I2C_InitParaStruct->I2C_AddressingMode = I2C_ADDRESSING_MODE_7BIT; - I2C_InitParaStruct->I2C_DeviceAddress = 0x08; -} - -/** - * @brief Enable or disable the I2Cx interface. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2Cx interface. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the I2Cx interface */ - I2Cx->CTLR1 |= CTLR1_I2CEN_SET; - } else { - /* Disable the I2Cx interface */ - I2Cx->CTLR1 &= CTLR1_I2CEN_RESET; - } -} - -/** - * @brief Enable or disable the I2Cx DMA requests. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C DMA transfer. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_DMA_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the I2Cx DMA requests */ - I2Cx->CTLR2 |= CTLR2_DMAON_SET; - } else { - /* Disable the I2Cx DMA requests */ - I2Cx->CTLR2 &= CTLR2_DMAON_RESET; - } -} - -/** - * @brief Enable or disable the DMA last. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C DMA last transfer. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_DMALastTransfer_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Next DMA transfer is the last transfer */ - I2Cx->CTLR2 |= CTLR2_DMALST_SET; - } else { - /* Next DMA transfer is not the last transfer */ - I2Cx->CTLR2 &= CTLR2_DMALST_RESET; - } -} - -/** - * @brief Enable or disable I2C_CTLR1_GENSTA control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C START condition generation. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_StartOnBus_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_GENSTA control bit */ - I2Cx->CTLR1 |= CTLR1_GENSTA_SET; - } else { - /* Disable I2C_CTLR1_GENSTA control bit */ - I2Cx->CTLR1 &= CTLR1_GENSTA_RESET; - } -} - -/** - * @brief Enable or disable I2C_CTLR1_GENSTP control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C STOP condition generation. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_StopOnBus_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_GENSTP control bit */ - I2Cx->CTLR1 |= CTLR1_GENSTP_SET; - } else { - /* Disable I2C_CTLR1_GENSTP control bit */ - I2Cx->CTLR1 &= CTLR1_GENSTP_RESET; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_ACKEN control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C Acknowledgement. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_Acknowledge_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_ACKEN control bit */ - I2Cx->CTLR1 |= CTLR1_ACKEN_SET; - } else { - /* Disable I2C_CTLR1_ACKEN control bit */ - I2Cx->CTLR1 &= CTLR1_ACKEN_RESET; - } -} - -/** - * @brief Set the I2Cx own address2. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param Address: specifies the 7bit I2C own address2. - * @retval None. - */ -void I2C_OwnAddress2(I2C_TypeDef *I2Cx, uint8_t Address) -{ - uint16_t temp = 0; - - temp = I2Cx->AR2; - temp &= AR2_ADDRESS2_RESET; - temp |= (uint16_t)((uint16_t)Address & (uint16_t)0x00FE); - /* I2C_AR2_ADDRESS2 */ - I2Cx->AR2 = temp; -} - -/** - * @brief Enable or disable the I2C_AR2_DUADEN control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C dual addressing mode. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_DualAddress_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the I2C_AR2_DUADEN control bit */ - I2Cx->AR2 |= AR2_DUADEN_SET; - } else { - /* Disable the I2C_AR2_DUADEN control bit */ - I2Cx->AR2 &= AR2_DUADEN_RESET; - } -} - -/** - * @brief Enable or disable I2C_CTLR1_GCEN control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C General call. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_GeneralCall_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_GCEN control bit */ - I2Cx->CTLR1 |= CTLR1_GCEN_SET; - } else { - /* Disable I2C_CTLR1_GCEN control bit */ - I2Cx->CTLR1 &= CTLR1_GCEN_RESET; - } -} - -/** - * @brief Enable or disable the specified I2C interrupt. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_INT: the I2C interrupt sources. - * This parameter can be any combination of the following values: - * @arg I2C_INT_EIE: Error interrupt - * @arg I2C_INT_EE: Event interrupt - * @arg I2C_INT_BIE: Buffer interrupt - * @param NewValue: new value of the specified I2C interrupts. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_INTConfig(I2C_TypeDef *I2Cx, uint16_t I2C_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the I2C interrupt */ - I2Cx->CTLR2 |= I2C_INT; - } else { - /* Disable the I2C interrupt */ - I2Cx->CTLR2 &= (uint16_t)~I2C_INT; - } -} - -/** - * @brief Send one byte to bus. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param Data: Byte to be transmitted. - * @retval None. - */ -void I2C_SendData(I2C_TypeDef *I2Cx, uint8_t Data) -{ - /* Write Data to DTR */ - I2Cx->DTR = Data; -} - -/** - * @brief Receive one byte from the bus. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @retval The received data. - */ -uint8_t I2C_ReceiveData(I2C_TypeDef *I2Cx) -{ - /* Read the DTR register */ - return (uint8_t)I2Cx->DTR; -} - -/** - * @brief Addressing a device on the I2C bus. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param Address: the slave device's address. - * @param I2C_Direction: Transmitter or a Receiver. - * This parameter can be one of the following values: - * @arg I2C_DIRECTION_TRANSMITTER: Transmitter mode - * @arg I2C_DIRECTION_RECEIVER: Receiver mode - * @retval None. - */ -void I2C_AddressingDevice_7bit(I2C_TypeDef *I2Cx, uint8_t Address, uint8_t I2C_Direction) -{ - if (I2C_Direction != I2C_DIRECTION_TRANSMITTER) { - /* Receiver mode */ - Address |= AR1_ADDRESS0_SET; - } else { - /* Transmitter mode */ - Address &= AR1_ADDRESS0_RESET; - } - I2Cx->DTR = Address; -} - -/** - * @brief Read the I2Cx register. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_Register: the I2Cx register. - * This parameter can be one of the following values: - * @arg I2C_REGISTER_CTLR1: CTLR1 register. - * @arg I2C_REGISTER_CTLR2: CTLR2 register. - * @arg I2C_REGISTER_AR1: AR1 register. - * @arg I2C_REGISTER_AR2: AR2 register. - * @arg I2C_REGISTER_DTR: DTR register. - * @arg I2C_REGISTER_STR1: STR1 register. - * @arg I2C_REGISTER_STR2: STR2 register. - * @arg I2C_REGISTER_CLKR: CLKR register. - * @arg I2C_REGISTER_RTR: RTR register. - * @retval The value of the read register. - */ -uint16_t I2C_ReadRegister(I2C_TypeDef *I2Cx, uint8_t I2C_Register) -{ - __IO uint32_t temp = 0; - - temp = (uint32_t) I2Cx; - temp += I2C_Register; - - /* Return the selected register value */ - return (*(__IO uint16_t *) temp); -} - -/** - * @brief Enable or disable the I2C_CTLR1_SRESET control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C software reset. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_SoftwareReset_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_SRESET control bit */ - I2Cx->CTLR1 |= CTLR1_SRESET_SET; - } else { - /* Disable I2C_CTLR1_SRESET control bit */ - I2Cx->CTLR1 &= CTLR1_SRESET_RESET; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_POAP control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_NACKPosition: the position of NACK. - * This parameter can be one of the following values: - * @arg I2C_NACKPOSITION_NEXT: the next byte is the last received byte - * @arg I2C_NACKPOSITION_CURRENT: the current byte is the last received byte - * @retval None. - */ -void I2C_NACKPosition_Enable(I2C_TypeDef *I2Cx, uint16_t I2C_NACKPosition) -{ - if (I2C_NACKPosition == I2C_NACKPOSITION_NEXT) { - /* Next byte will be the last received byte */ - I2Cx->CTLR1 |= I2C_NACKPOSITION_NEXT; - } else { - /* Current byte is the last received byte */ - I2Cx->CTLR1 &= I2C_NACKPOSITION_CURRENT; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_SALT control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C software reset. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void I2C_SMBusAlertSend_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_SALT control bit */ - I2Cx->CTLR1 |= CTLR1_SALT_SET; - } else { - /* Disable I2C_CTLR1_SALT control bit */ - I2Cx->CTLR1 &= CTLR1_SALT_RESET; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_PECTRANS control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2C PEC transmission. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void I2C_PECTransmit_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_PECTRANS control bit */ - I2Cx->CTLR1 |= CTLR1_PECTRANS_SET; - } else { - /* Disable I2C_CTLR1_PECTRANS control bit */ - I2Cx->CTLR1 &= CTLR1_PECTRANS_RESET; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_POAP control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_PECPosition: the position of PEC. - * This parameter can be one of the following values: - * @arg I2C_PECPOSITION_NEXT: the next byte is PEC - * @arg I2C_PECPOSITION_CURRENT: the current byte is PEC - * @retval None. - */ -void I2C_PECPosition_Enable(I2C_TypeDef *I2Cx, uint16_t I2C_PECPosition) -{ - if (I2C_PECPosition == I2C_PECPOSITION_NEXT) { - /* The next byte is PEC */ - I2Cx->CTLR1 |= I2C_PECPOSITION_NEXT; - } else { - /* The current byte is PEC */ - I2Cx->CTLR1 &= I2C_PECPOSITION_CURRENT; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_PECEN control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2Cx PEC value calculation. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_PEC_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_PECEN control bit */ - I2Cx->CTLR1 |= CTLR1_PECEN_SET; - } else { - /* Disable I2C_CTLR1_PECEN control bit */ - I2Cx->CTLR1 &= CTLR1_PECEN_RESET; - } -} - -/** - * @brief The Packet Error Checking value. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @retval The PEC value. - */ -uint8_t I2C_GetPECValue(I2C_TypeDef *I2Cx) -{ - /* I2C_STR2_ECV */ - return ((I2Cx->STR2) >> 8); -} - -/** - * @brief Enable or disable the I2C_CTLR1_ARPEN control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2Cx ARP. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_ARP_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I2C_CTLR1_ARPEN control bit */ - I2Cx->CTLR1 |= CTLR1_ARPEN_SET; - } else { - /* Disable I2C_CTLR1_ARPEN control bit */ - I2Cx->CTLR1 &= CTLR1_ARPEN_RESET; - } -} - -/** - * @brief Enable or disable the I2C_CTLR1_DISSTRC control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param NewValue: new value of the I2Cx Clock stretching. - * This parameter can be: ENABLE or DISABLE. - * @retval None. - */ -void I2C_StretchClock_Enable(I2C_TypeDef *I2Cx, TypeState NewValue) -{ - if (NewValue == DISABLE) { - /* Enable I2C_CTLR1_DISSTRC control bit */ - I2Cx->CTLR1 |= CTLR1_DISSTRC_SET; - } else { - /* Enable I2C_CTLR1_DISSTRC control bit */ - I2Cx->CTLR1 &= CTLR1_DISSTRC_RESET; - } -} - -/** - * @brief Enable or disable the I2C_CLKR_DTCY control bit. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_DutyCycle: the duty cycle in fast mode. - * This parameter can be one of the following values: - * @arg I2C_DUTYCYCLE_2: I2C fast mode Tlow/Thigh = 2 - * @arg I2C_DUTYCYCLE_16_9: I2C fast mode Tlow/Thigh = 16/9 - * @retval None. - */ -void I2C_FastModeDutyCycle(I2C_TypeDef *I2Cx, uint16_t I2C_DutyCycle) -{ - if (I2C_DutyCycle != I2C_DUTYCYCLE_16_9) { - /* DutyCycle=2:1 */ - I2Cx->CLKR &= I2C_DUTYCYCLE_2; - } else { - /* DutyCycle=16:9 */ - I2Cx->CLKR |= I2C_DUTYCYCLE_16_9; - } -} - -/** - * @brief Detect I2Cx State Machine. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_State: I2Cx State Machine. - * This parameter can be one of the following values: - * @arg I2C_PROGRAMMINGMODE_SLAVE_TRANSMITTER_ADDSEND - * @arg I2C_PROGRAMMINGMODE_SLAVE_RECEIVER_ADDSEND - * @arg I2C_PROGRAMMINGMODE_SLAVE_TRANSMITTER_SECONDADDRESS_SELECTED - * @arg I2C_PROGRAMMINGMODE_SLAVE_RECEIVER_SECONDADDRESS_SELECTED - * @arg I2C_PROGRAMMINGMODE_SLAVE_GENERALCALLADDRESS_SELECTED - * @arg I2C_PROGRAMMINGMODE_SLAVE_BYTE_RECEIVED - * @arg (I2C_PROGRAMMINGMODE_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUMODF) - * @arg (I2C_PROGRAMMINGMODE_SLAVE_BYTE_RECEIVED | I2C_FLAG_RXGC) - * @arg I2C_PROGRAMMINGMODE_SLAVE_BYTE_TRANSMITTED - * @arg (I2C_PROGRAMMINGMODE_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUMODF) - * @arg (I2C_PROGRAMMINGMODE_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_RXGC) - * @arg I2C_PROGRAMMINGMODE_SLAVE_ACK_FAILURE - * @arg I2C_PROGRAMMINGMODE_SLAVE_STOP_DETECTED - * @arg I2C_PROGRAMMINGMODE_MASTER_SBSEND - * @arg I2C_PROGRAMMINGMODE_MASTER_TRANSMITTER_ADDSEND - * @arg I2C_PROGRAMMINGMODE_MASTER_RECEIVER_ADDSEND - * @arg I2C_PROGRAMMINGMODE_MASTER_BYTE_RECEIVED - * @arg I2C_PROGRAMMINGMODE_MASTER_BYTE_TRANSMITTING - * @arg I2C_PROGRAMMINGMODE_MASTER_BYTE_TRANSMITTED - * @arg I2C_PROGRAMMINGMODE_MASTER_ADD10SEND - * @retval The detected result(SUCCESS or ERROR). - */ -TypeState I2C_StateDetect(I2C_TypeDef *I2Cx, uint32_t I2C_State) -{ - uint32_t currentstate = 0; - uint32_t flag1 = 0, flag2 = 0; - TypeState state = ERROR; - - /* Read the I2Cx status register */ - flag1 = I2Cx->STR1; - flag2 = I2Cx->STR2; - flag2 = flag2 << 16; - - /* Get the state value from I2C status register */ - currentstate = (flag1 | flag2) & STR_FLAG_MASK; - - if ((currentstate & I2C_State) == I2C_State) { - /* I2C_State is detected */ - state = SUCCESS; - } else { - /* I2C_State is not detected */ - state = ERROR; - } - return state; -} - -/** - * @brief Get the I2Cx Current State. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @retval The current state. - */ -uint32_t I2C_GetCurrentState(I2C_TypeDef *I2Cx) -{ - uint32_t currentstate = 0; - uint32_t flag1 = 0, flag2 = 0; - - /* Read the I2Cx status register */ - flag1 = I2Cx->STR1; - flag2 = I2Cx->STR2; - flag2 = flag2 << 16; - - /* Get the last event value from I2C status register */ - currentstate = (flag1 | flag2) & STR_FLAG_MASK; - - return currentstate; -} - -/** - * @brief Get the bit flag of STRx registers. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_FLAG: the flag of STRx registers. - * This parameter can be one of the following values: - * @arg I2C_FLAG_DUMODF: Dual flag (Slave mode) - * @arg I2C_FLAG_HSTSMB: SMBus host header (Slave mode) - * @arg I2C_FLAG_DEFSMB: SMBus default header (Slave mode) - * @arg I2C_FLAG_RXGC: General call header flag (Slave mode) - * @arg I2C_FLAG_TRS: Transmitter or Receiver flag - * @arg I2C_FLAG_I2CBSY: Bus busy flag - * @arg I2C_FLAG_MASTER: Master or Slave flag - * @arg I2C_FLAG_SMBALTS: SMBus Alert flag - * @arg I2C_FLAG_SMBTO: Timeout or Tlow error flag - * @arg I2C_FLAG_PECE: PEC error in reception flag - * @arg I2C_FLAG_RXORE: Overrun or Underrun flag (Slave mode) - * @arg I2C_FLAG_AE: Acknowledge failure flag - * @arg I2C_FLAG_LOSTARB: Arbitration lost flag (Master mode) - * @arg I2C_FLAG_BE: Bus error flag - * @arg I2C_FLAG_TBE: Data register empty flag (Transmitter) - * @arg I2C_FLAG_RBNE: Data register not empty (Receiver) flag - * @arg I2C_FLAG_STPSEND: Stop detection flag (Slave mode) - * @arg I2C_FLAG_ADD10SEND: 10-bit header sent flag (Master mode) - * @arg I2C_FLAG_BTC: Byte transfer finished flag - * @arg I2C_FLAG_ADDSEND: Address sent flag (Master mode) or Address matched flag (Slave mode) - * @arg I2C_FLAG_SBSEND: Start bit flag (Master mode) - * @retval The new value of I2C_FLAG (SET or RESET). - */ -TypeState I2C_GetBitState(I2C_TypeDef *I2Cx, uint32_t I2C_FLAG) -{ - __IO uint32_t i2creg = 0, i2cxbase = 0; - - /* Get the I2Cx peripheral base address */ - i2cxbase = (uint32_t)I2Cx; - - /* Read flag register index */ - i2creg = I2C_FLAG >> 28; - - /* Get bit[23:0] of the flag */ - I2C_FLAG &= STR_FLAG_MASK; - - if (i2creg != 0) { - /* Flag in I2Cx STR1 register */ - i2cxbase += 0x14; - } else { - /* Flag in I2Cx STR2 Register */ - I2C_FLAG = (uint32_t)(I2C_FLAG >> 16); - /* Get the I2Cx STR2 register address */ - i2cxbase += 0x18; - } - - if (((*(__IO uint32_t *)i2cxbase) & I2C_FLAG) != (uint32_t)RESET) { - /* I2C_FLAG is set */ - return SET; - } else { - /* I2C_FLAG is reset */ - return RESET; - } -} - -/** - * @brief Clear the bit flag of STRx registers. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_FLAG: the flag of STRx registers. - * This parameter can be any combination of the following values: - * @arg I2C_FLAG_SMBALTS: SMBus Alert flag - * @arg I2C_FLAG_SMBTO: Timeout or Tlow error flag - * @arg I2C_FLAG_PECE: PEC error in reception flag - * @arg I2C_FLAG_RXORE: Overrun or Underrun flag (Slave mode) - * @arg I2C_FLAG_AE: Acknowledge failure flag - * @arg I2C_FLAG_LOSTARB: Arbitration lost flag (Master mode) - * @arg I2C_FLAG_BE: Bus error flag - * @retval None. - */ -void I2C_ClearBitState(I2C_TypeDef *I2Cx, uint32_t I2C_FLAG) -{ - uint32_t flagpos = 0; - - /* Get the I2C flag position */ - flagpos = I2C_FLAG & STR_FLAG_MASK; - /* Clear the selected I2C flag */ - I2Cx->STR1 = (uint16_t)~flagpos; -} - -/** - * @brief Get the interrupt bit flag. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_INT: the interrupt bit flag. - * This parameter can be one of the following values: - * @arg I2C_INT_SMBALTS: SMBus Alert flag - * @arg I2C_INT_SMBTO: Timeout or Tlow error flag - * @arg I2C_INT_PECE: PEC error in reception flag - * @arg I2C_INT_RXORE: Overrun or Underrun flag (Slave mode) - * @arg I2C_INT_AE: Acknowledge failure flag - * @arg I2C_INT_LOSTARB: Arbitration lost flag (Master mode) - * @arg I2C_INT_BE: Bus error flag - * @arg I2C_INT_TBE: Data register empty flag (Transmitter) - * @arg I2C_INT_RBNE: Data register not empty (Receiver) flag - * @arg I2C_INT_STPSEND: Stop detection flag (Slave mode) - * @arg I2C_INT_ADD10SEND: 10-bit header sent flag (Master mode) - * @arg I2C_INT_BTC: Byte transfer finished flag - * @arg I2C_INT_ADDSEND: Address sent flag (Master mode) or Address matched flag (Slave mode) - * @arg I2C_INT_SBSEND: Start bit flag (Master mode) - * @retval The new value of I2C_INT (SET or RESET). - */ -TypeState I2C_GetIntBitState(I2C_TypeDef *I2Cx, uint32_t I2C_INT) -{ - uint32_t enablestatus = 0; - - /* Check if the interrupt source is enabled or not */ - enablestatus = (uint32_t)(((I2C_INT & INTEN_MASK) >> 16) & (I2Cx->CTLR2)) ; - - /* Get bit[23:0] of the flag */ - I2C_INT &= STR_FLAG_MASK; - - if (((I2Cx->STR1 & I2C_INT) != (uint32_t)RESET) && enablestatus) { - /* I2C_INT is set */ - return SET; - } else { - /* I2C_INT is reset */ - return RESET; - } -} - -/** - * @brief Clear the interrupt bit flag. - * @param I2Cx: the I2C interface where x can be 1 or 2. - * @param I2C_INT: the interrupt bit flag. - * This parameter can be any combination of the following values: - * @arg I2C_INT_SMBALTS: SMBus Alert interrupt - * @arg I2C_INT_SMBTO: Timeout or Tlow error interrupt - * @arg I2C_INT_PECE: PEC error in reception interrupt - * @arg I2C_INT_RXORE: Overrun or Underrun interrupt (Slave mode) - * @arg I2C_INT_AE: Acknowledge failure interrupt - * @arg I2C_INT_LOSTARB: Arbitration lost interrupt (Master mode) - * @arg I2C_INT_BE: Bus error interrupt - * @retval None. - */ -void I2C_ClearIntBitState(I2C_TypeDef *I2Cx, uint32_t I2C_INT) -{ - uint32_t flagpos = 0; - - /* Get the I2C flag position */ - flagpos = I2C_INT & STR_FLAG_MASK; - /* Clear the selected I2C flag */ - I2Cx->STR1 = (uint16_t)~flagpos; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_iwdg.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_iwdg.c deleted file mode 100644 index 1032f064e5..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_iwdg.c +++ /dev/null @@ -1,130 +0,0 @@ -/** - ****************************************************************************** - * @brief IWDG functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_iwdg.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup IWDG - * @brief IWDG driver modules - * @{ - */ - -/** @defgroup IWDG_Private_Variables - * @{ - */ - -/* CTLR register bit mask */ -#define CTLR_KEY_RELOAD ((uint16_t)0xAAAA) -#define CTLR_KEY_ENABLE ((uint16_t)0xCCCC) - -/** - * @} - */ - -/** @defgroup IWDG_Private_Functions - * @{ - */ - -/** - * @brief Enable or disable the IWDG_PSR, IWDG_RLDR and IWDG_WND write protection. - * @param IWDG_WriteAccess: value to enable or disable the write access to registers. - * This parameter can be one of the following values: - * @arg IWDG_WRITEACCESS_ENABLE: Enable write access to IWDG_PSR, IWDG_RLDR and IWDG_WND registers - * @arg IWDG_WRITEACCESS_DISABLE: Disable write access to IWDG_PSR, IWDG_RLDR and IWDG_WND registers - * @retval None - */ -void IWDG_Write_Enable(uint16_t IWDG_WriteAccess) -{ - IWDG->CTLR = IWDG_WriteAccess; -} - -/** - * @brief Set IWDG prescaler value. - * @param PrescalerValue: IWDG Prescaler value. - * This parameter can be one of the following values: - * @arg IWDG_PRESCALER_4: IWDG prescaler set to 4 - * @arg IWDG_PRESCALER_8: IWDG prescaler set to 8 - * @arg IWDG_PRESCALER_16: IWDG prescaler set to 16 - * @arg IWDG_PRESCALER_32: IWDG prescaler set to 32 - * @arg IWDG_PRESCALER_64: IWDG prescaler set to 64 - * @arg IWDG_PRESCALER_128: IWDG prescaler set to 128 - * @arg IWDG_PRESCALER_256: IWDG prescaler set to 256 - * @retval None - */ -void IWDG_SetPrescaler(uint8_t PrescalerValue) -{ - IWDG->PSR = PrescalerValue; -} - -/** - * @brief Set independent watchdog counter reload value. - * @param ReloadValue: IWDG Reload value. - * This parameter must be between 0 and 0x0FFF. - * @retval None - */ -void IWDG_SetReloadValue(uint16_t ReloadValue) -{ - IWDG->RLDR = ReloadValue; -} - -/** - * @brief Reload the counter. - * @param None - * @retval None - */ -void IWDG_ReloadCounter(void) -{ - IWDG->CTLR = CTLR_KEY_RELOAD; -} - -/** - * @brief Start the independent watchdog counter. - * @param None - * @retval None - */ -void IWDG_Enable(void) -{ - IWDG->CTLR = CTLR_KEY_ENABLE; -} - -/** - * @brief Check registers' bit state. - * @param IWDG_FLAG: the flag to check. - * This parameter can be one of the following values: - * @arg IWDG_BIT_PUD: A write operation to IWDG_PSR register on going - * @arg IWDG_BIT_RUD: A write operation to IWDG_RLDR register on going - * @arg IWDG_BIT_WUD: A write operation to IWDG_WND register on going - * @retval The new state of IWDG_FLAG (SET or RESET). - */ -TypeState IWDG_GetBitState(uint16_t IWDG_FLAG) -{ - if ((IWDG->STR & IWDG_FLAG) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_mcudbg.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_mcudbg.c deleted file mode 100644 index 03b0618344..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_mcudbg.c +++ /dev/null @@ -1,105 +0,0 @@ -/** - ****************************************************************************** - * @brief MCUDBG functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_mcudbg.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup MCUDBG - * @brief MCUDBG driver modules - * @{ - */ - - -/** @defgroup MCUDBG_Private_Defines - * @{ - */ - -#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF) -/** - * @} - */ - - -/** @defgroup MCUDBG_Private_Functions - * @{ - */ - -/** - * @brief Returns the device revision identifier. - * @param None - * @retval Device revision identifier - */ -uint32_t MCUDBG_GetREVID(void) -{ - return (MCUDBG->IDR >> 16); -} - -/** - * @brief Returns the device identifier. - * @param None - * @retval Device identifier - */ -uint32_t MCUDBG_GetDEVID(void) -{ - return (MCUDBG->IDR & IDCODE_DEVID_MASK); -} - -/** - * @brief Configure the specified peripheral and low power mode behavior - * when the MCU under Debug mode. - * @param MCUDBG_Periph: specifies the peripheral and low power mode. - * This parameter can be any combination of the following values: - * @arg MCUDBG_SLEEP_HOLD: Keep debugger connection during SLEEP mode - * @arg MCUDBG_DEEPSLEEP_HOLD: Keep debugger connection during DEEPSLEEP mode - * @arg MCUDBG_STDBY_HOLD: Keep debugger connection during STANDBY mode - * @arg MCUDBG_IWDG_HOLD: Debug IWDG hold when Core is halted - * @arg MCUDBG_WWDG_HOLD: Debug WWDG hold when Core is halted - * @arg MCUDBG_TIMER1_HOLD: TIMER1 counter hold when Core is halted - * @arg MCUDBG_TIMER2_HOLD: TIMER2 counter hold when Core is halted - * @arg MCUDBG_TIMER3_HOLD: TIMER3 counter hold when Core is halted - * @arg MCUDBG_TIMER4_HOLD: TIMER4 counter hold when Core is halted - * @arg MCUDBG_CAN1_HOLD: Debug CAN1 hold when Core is halted - * @arg MCUDBG_I2C1_HOLD: I2C1 SMBUS timeout mode hold when Core is halted - * @arg MCUDBG_I2C2_HOLD: I2C2 SMBUS timeout mode hold when Core is halted - * @arg MCUDBG_TIMER5_HOLD: TIMER5 counter hold when Core is halted - * @arg MCUDBG_TIMER6_HOLD: TIMER6 counter hold when Core is halted - * @arg MCUDBG_TIMER7_HOLD: TIMER7 counter hold when Core is halted - * @arg MCUDBG_TIMER8_HOLD: TIMER8 counter hold when Core is halted - * @arg MCUDBG_CAN2_HOLD: Debug CAN2 hold when Core is halted - * @arg MCUDBG_TIMER12_HOLD: TIMER12 counter hold when Core is halted - * @arg MCUDBG_TIMER13_HOLD: TIMER13 counter hold when Core is halted - * @arg MCUDBG_TIMER14_HOLD: TIMER14 counter hold when Core is halted - * @arg MCUDBG_TIMER9_HOLD: TIMER9 counter hold when Core is halted - * @arg MCUDBG_TIMER10_HOLD: TIMER10 counter hold when Core is halted - * @arg MCUDBG_TIMER11_HOLD: TIMER11 counter hold when Core is halted - * @param NewState: new state of the specified peripheral in Debug mode. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void MCUDBG_PeriphConfig(uint32_t MCUDBG_Periph, TypeState NewValue) -{ - if (NewValue != DISABLE) { - MCUDBG->CTLR |= MCUDBG_Periph; - } else { - MCUDBG->CTLR &= ~MCUDBG_Periph; - } -} -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_misc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_misc.c deleted file mode 100644 index cee195ebc5..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_misc.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - ****************************************************************************** - * @brief MISC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_misc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup MISC - * @brief MISC driver modules - * @{ - */ - -/** @defgroup MISC_Private_Defines - * @{ - */ -#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) - -/** - * @} - */ - -/** @defgroup MISC_Private_Functions - * @{ - */ - -/** - * @brief By the PRIGROUP[10:8] bits of the AIRCR register, Setting the priority grouping: - * pre-emption priority and subpriority. - * @param NVIC_PriGroup: NVIC_PRIGROUP_0, NVIC_PRIGROUP_1,...NVIC_PRIGROUP_4. - * @retval None - */ -void NVIC_PRIGroup_Enable(uint32_t NVIC_PRIGroup) -{ - /* Set the priority grouping value */ - SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PRIGroup; -} - -/** - * @brief The NVIC peripheral Initialization. - * @param NVIC_InitStruct: a NVIC_InitPara structure pointer. - * @retval None - */ -void NVIC_Init(NVIC_InitPara *NVIC_InitStruct) -{ - uint32_t temppriority = 0x00, temppreempt = 0x00, tempsub = 0x00; - - if (NVIC_InitStruct->NVIC_IRQEnable != DISABLE) { - if (((SCB->AIRCR) & (uint32_t)0x700) == NVIC_PRIGROUP_0) { - temppreempt = 0; - tempsub = 0x4; - } else if (((SCB->AIRCR) & (uint32_t)0x700) == NVIC_PRIGROUP_1) { - temppreempt = 1; - tempsub = 0x3; - } else if (((SCB->AIRCR) & (uint32_t)0x700) == NVIC_PRIGROUP_2) { - temppreempt = 2; - tempsub = 0x2; - } else if (((SCB->AIRCR) & (uint32_t)0x700) == NVIC_PRIGROUP_3) { - temppreempt = 3; - tempsub = 0x1; - } else if (((SCB->AIRCR) & (uint32_t)0x700) == NVIC_PRIGROUP_4) { - temppreempt = 4; - tempsub = 0x0; - } - - temppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQPreemptPriority << (0x4 - temppreempt); - temppriority |= NVIC_InitStruct->NVIC_IRQSubPriority & (0x0F >> (0x4 - tempsub)); - temppriority = temppriority << 0x04; - - NVIC->IP[NVIC_InitStruct->NVIC_IRQ] = temppriority; - - /* Enable the Selected IRQ Channels */ - NVIC->ISER[NVIC_InitStruct->NVIC_IRQ >> 0x05] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQ & (uint8_t)0x1F); - } else { - /* Disable the Selected IRQ Channels */ - NVIC->ICER[NVIC_InitStruct->NVIC_IRQ >> 0x05] = (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQ & (uint8_t)0x1F); - } -} - -/** - * @brief Specify the vector table in RAM or FLASH memory and its Offset. - * @param NVIC_VectTab: NVIC_VECTTAB_RAM,NVIC_VECTTAB_FLASH - * @param Offset: Vector Table start address. - * @retval None - */ -void NVIC_VectTableSet(uint32_t NVIC_VectTab, uint32_t Offset) -{ - SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); -} - -/** - * @brief Specify the state of the system to enter low power mode. - * @param LowPowerMode: NVIC_LOWPOWER_SEVONPEND,NVIC_LOWPOWER_SLEEPDEEP,NVIC_LOWPOWER_SLEEPONEXIT. - * @param NewValue: new value of Low Power state. This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void NVIC_SystemLowPowerConfig(uint8_t LowPowerMode, TypeState NewValue) -{ - if (NewValue != DISABLE) { - SCB->SCR |= LowPowerMode; - } else { - SCB->SCR &= (~(uint32_t)LowPowerMode); - } -} - -/** - * @brief Specify the SysTick clock source. - * @param SysTick_CKSource: SYSTICK_CKSOURCE_HCLK_DIV8,SYSTICK_CKSOURCE_HCLK. - * @retval None - */ -void SysTick_CKSource_Enable(uint32_t SysTick_CKSource) -{ - if (SysTick_CKSource == SYSTICK_CKSOURCE_HCLK) { - SysTick->CTRL |= SYSTICK_CKSOURCE_HCLK; - } else { - SysTick->CTRL &= SYSTICK_CKSOURCE_HCLK_DIV8; - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_pwr.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_pwr.c deleted file mode 100644 index cd44b98dfe..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_pwr.c +++ /dev/null @@ -1,333 +0,0 @@ -/** - ****************************************************************************** - * @brief PWR functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_pwr.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup PWR - * @brief PWR driver modules - * @{ - */ - -/** @defgroup PWR_Private_Defines - * @{ - */ -/* Left shift SBF or WUF(PWR_STR) to SBFR or WUFR(PWR_CTLR) */ -#define BIT_SHIFT 2 - -/** - * @} - */ - -/** @defgroup PWR_Private_Functions - * @{ - */ - -/** - * @brief Reset the PWR peripheral registers. - * @param None - * @retval None - */ -void PWR_DeInit(void) -{ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_PWRRST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_PWRRST, DISABLE); -} - -/** - * @brief Enable or disable write access to the registers in Backup domain. - * @note After reset, any write access to the registers in Backup domain is disabled. - * This bit has to be set to enable write access to these registers. - * @param NewValue: New value of write access state to the registers in Backup domain. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void PWR_BackupAccess_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the Backup Domain Access */ - PWR->CTLR |= PWR_CTLR_BKPWE; - } else { - /* Disable the Backup Domain Access */ - PWR->CTLR &= ~((uint32_t)PWR_CTLR_BKPWE); - } -} - -/** - * @brief Enable or disable the LVD(Low Voltage Detector), and configure the voltage - * threshold detected by the LVD. - * @note The LVDE bit controls whether LVD is enabled or not, while the LVDT[2:0] - * bits select the LVDT from 2.2V to 2.9V. - * @note The LVD is stopped in Standby mode. - * @param PWR_LVDT: the LVD threshold. - * This parameter can be one of the following values: - * @arg PWR_LVDT_0 - * @arg PWR_LVDT_1 - * @arg PWR_LVDT_2 - * @arg PWR_LVDT_3 - * @arg PWR_LVDT_4 - * @arg PWR_LVDT_5 - * @arg PWR_LVDT_6 - * @arg PWR_LVDT_7 - * @param NewValue: New value of the LVD state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void PWR_LVDConfig(uint32_t PWR_LVDT, TypeState NewValue) -{ - uint32_t temp = 0; - - temp = PWR->CTLR; - - /* Clear LVDT[7:5] bits */ - temp &= ~((uint32_t)PWR_CTLR_LVDT); - - /* Set LVDT[7:5] bits according to PWR_LVDT value */ - temp |= PWR_LVDT; - - /* Store the new value */ - PWR->CTLR = temp; - - /* Enable or disable the LVD */ - if (NewValue != DISABLE) { - /* Enable the LVD */ - PWR->CTLR |= PWR_CTLR_LVDE; - } else { - /* Disable the LVD */ - PWR->CTLR &= ~((uint32_t)PWR_CTLR_LVDE); - } -} - -/** - * @brief Enable or disable the WakeUp Pin(PA0 pin) function. - * @note If WUPE is set before entering the power saving mode, - * a rising edge on the WKUP Pin wakes up the system from the power - * saving mode. As the WKUP pin is active high, it will setup - * an input pull down mode when this bit is high. - * @param NewValue: New value of the WKUP Pin state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void PWR_WKUP_Pin_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the WKUP pin */ - PWR->STR |= PWR_STR_WUPE; - } else { - /* Disable the WKUP pin */ - PWR->STR &= ~PWR_STR_WUPE; - } -} - -/** - *@verbatim - - [..] The GD32F10x series of devices provide three types of power saving modes. - - *** Sleep mode *** - ================== - [..] The Sleep mode is based on the SLEEPING mode of the Cortex-M3. In Sleep - mode, only clock of Cortex-M3 is off. - (+) Entry: - (++) To enter the Sleep mode, it is only necessary to clear SLEEPDEEP bit - in the Cortex-M3 System Control Register, and execute a WFI or WFE - instruction. - (++) The Sleep mode is entered using the PWR_SLEEPMode_Entry() function. - (+) Wakeup: - (++) Any interrupt for WFI or Any event for WFE. - (+) Wakeup Latency: - (++) None - - *** Deep-sleep mode *** - ================= - [..] The Deep-sleep mode is based on the SLEEPDEEP mode of the Cortex-M3. In - Deep-sleep mode, all clocks in the 1.2V domain are off, and all of HSI, - HSE and PLL are disabled. The LDO can operate normally or in low - power mode depending on the LDOLP bit in the PWR_CTLR register. - (+) Entry: - (++) Before entering the Deep-sleep mode, it is necessary to set the - SLEEPDEEP bit in the Cortex-M3 System Control Register, and clear - the SDBM bit in the PWR_CTLR register. - (++) The Deep-sleep mode is entered using the PWR_DEEPSLEEPMode_Entry() - function. - (+) Wakeup: - (++) Any interrupt or event from EXTI Lines. - (+) Wakeup Latency: - (++) HSI wakeup time; LDO wakeup time if LDO is in low power mode. - - *** Standby mode *** - ==================== - [..] The Standby mode is based on the SLEEPDEEP mode of the Cortex-M3. In Standby - mode, the whole 1.2V domain is power off, the LDO is shut down, and all of - HSI, HSE and PLL are disabled. Besides, the contents of SRAM and - registers(except Backup Registers) are lost in Standby mode. - (+) Entry: - (++) Before entering the Standby mode, it is necessary to set the - SLEEPDEEP bit in the Cortex-M3 System Control Register, and set - the SDBM bit in the PWR_CTLR register, and clear WUF bit in the - PWR_STR register. . - (++) The Standby mode is entered using the PWR_STDBYMode_Entry() function. - (+) Wakeup: - (++) NRST pin, WKUP pin rising edge, RTC alarm, IWDG reset. - (+) Wakeup Latency: - (++) Power on sequence - *@endverbatim - */ -/** - * @brief Enter Sleep mode. - * @note By default, this function selects the Sleep-now entry mechanism (SLEEPONEXIT = 0). - * @param PWR_SLEEPENTRY: WFI or WFE instruction. - * This parameter can be one of the following values: - * @arg PWR_SLEEPENTRY_WFI: enter Sleep mode with WFI instruction - * @arg PWR_SLEEPENTRY_WFE: enter Sleep mode with WFE instruction - * @retval None - */ -void PWR_SLEEPMode_Entry(uint8_t PWR_SLEEPENTRY) -{ - /* Clear SLEEPDEEP bit of Cortex-M3 System Control Register */ - SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); - - /* Select WFI or WFE to enter Sleep mode */ - if (PWR_SLEEPENTRY == PWR_SLEEPENTRY_WFI) { - __WFI(); - } else { - __WFE(); - } -} - -/** - * @brief Enter Deep-sleep mode. - * @note When exiting Deep-sleep mode, the HSI is selected as the system clock. - * @note An additional wakeup delay will be incurred if the LDO operates in - * low power mode. - * @param PWR_LDO: the LDO state in Deep-sleep mode. - * This parameter can be one of the following values: - * @arg PWR_LDO_ON: Deep-sleep mode with LDO ON - * @arg PWR_LDO_LOWPOWER: Deep-sleep mode with LDO in low power mode - * @param PWR_DEEPSLEEPENTRY: WFI or WFE instruction. - * This parameter can be one of the following values: - * @arg PWR_DEEPSLEEPENTRY_WFI: enter Deep-sleep mode with WFI instruction - * @arg PWR_DEEPSLEEPENTRY_WFE: enter Deep-sleep mode with WFE instruction - * @retval None - */ -void PWR_DEEPSLEEPMode_Entry(uint32_t PWR_LDO, uint8_t PWR_DEEPSLEEPENTRY) -{ - uint32_t temp = 0; - - /* Select the LDO state in Deep-sleep mode */ - temp = PWR->CTLR; - - /* Clear SDBM and LDOLP bits, and select Deep-sleep mode */ - temp &= ~((uint32_t)(PWR_CTLR_SDBM | PWR_CTLR_LDOLP)); - - /* Set LDOLP bit according to PWR_LDO value, and select the LDO's state */ - temp |= PWR_LDO; - - /* Store the new value */ - PWR->CTLR = temp; - - /* Set SLEEPDEEP bit of Cortex-M3 System Control Register */ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - - /* Select WFI or WFE to enter Deep-sleep mode */ - if (PWR_DEEPSLEEPENTRY == PWR_DEEPSLEEPENTRY_WFI) { - __WFI(); - } else { - __SEV(); - __WFE(); - __WFE(); - } - /* Reset SLEEPDEEP bit of Cortex-M3 System Control Register */ - SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); -} - -/** - * @brief Enter Standby mode. - * @note The Standby mode achieves the lowest power consumption, but spends - * longest time to wake up. - * @note When exiting from the Standby mode, a power-on reset occurs and the - * Cortex-M3 will execute instructions code from the 0x0000_0000 address. - * @param PWR_STDBYENTRY: WFI or WFE instruction. - * This parameter can be one of the following values: - * @arg PWR_STDBYENTRY_WFI: enter Standby mode with WFI instruction - * @arg PWR_STDBYENTRY_WFE: enter Standby mode with WFE instruction - * @retval None - */ -void PWR_STDBYMode_Entry(uint8_t PWR_STDBYENTRY) -{ - /* Set SLEEPDEEP bit of Cortex-M3 System Control Register */ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - - /* Set SDBM bit, and select Standby mode */ - PWR->CTLR |= PWR_CTLR_SDBM; - - /* Reset Wakeup flag */ - PWR->CTLR |= PWR_CTLR_WUFR; - - /* Select WFI or WFE to enter Standby mode */ - if (PWR_STDBYENTRY == PWR_STDBYENTRY_WFI) { - __WFI(); - } else { - __WFE(); - } -} - -/** - * @brief Get the bit flag of some PWR_STR registers. - * @param PWR_FLAG: the flag of PWR_STR registers. - * This parameter can be one of the following values: - * @arg PWR_FLAG_WKUP: WakeUp flag. This flag indicates that a wakeup - * event was received from the WKUP pin or from the RTC alarm, - * IWDG reset or NRST pin. - * @arg PWR_FLAG_STB: StandBy flag. This flag indicates that the - * system has been in Standby mode. - * @arg PWR_FLAG_LVDF: LVD State flag. This flag is valid only if LVD - * is enabled by the PWR_LVD_Config()function. - * @retval The new value of PWR_FLAG (SET or RESET). - */ -TypeState PWR_GetBitState(uint32_t PWR_FLAG) -{ - /* Check and get the selected PWR flag */ - if ((PWR->STR & PWR_FLAG) != (uint32_t)RESET) { - /* PWR_FLAG bit is SET */ - return SET; - } else { - /* PWR_FLAG bit is RESET */ - return RESET; - } -} - -/** - * @brief Clear the bit flag of some PWR_STR registers. - * @param PWR_FLAG: the flag of PWR_STR registers. - * This parameter can be one of the following values: - * @arg PWR_FLAG_WKUP: Wake_Up flag - * @arg PWR_FLAG_STB: StandBy flag - * @retval None - */ -void PWR_ClearBitState(uint32_t PWR_FLAG) -{ - /* Clear the selected PWR flag */ - PWR->CTLR |= PWR_FLAG << BIT_SHIFT; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcc.c deleted file mode 100644 index f14e848695..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcc.c +++ /dev/null @@ -1,1323 +0,0 @@ -/** - ****************************************************************************** - * @brief RCC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup RCC - * @brief RCC driver modules - * @{ - */ - -/** @defgroup RCC_Private_Defines - * @{ - */ - - -/* RCC GCCR_HSIEN mask */ -#define GCCR_HSIEN_SET ((uint32_t)0x00000001) - -/* RCC GCFGR_Reset mask */ -#define GCFGR_RESET_CL ((uint32_t)0xE0FF0000) -#define GCFGR_RESET ((uint32_t)0xE8FF0000) - -/* RCC GCCR_HSEEN_CKMEN_PLLEN masks */ -#define GCCR_HSEEN_CKMEN_PLLEN_RESET ((uint32_t)0xFEF6FFFF) - -/* RCC GCCR_HSEBPS mask */ -#define GCCR_HSEBPS_RESET ((uint32_t)0xFFFBFFFF) - -/* RCC GCFGR_PLLSEL_PLLPREDV_PLLMF masks */ -#define GCFGR_PLLSEL_PLLPREDV_PLLMF_USBPS_RESET ((uint32_t)0xF700FFFF) -#define GCFGR_PLLSEL_PLLPREDV_PLLMF_OTGFSPS_RESET_CL ((uint32_t)0xDF00FFFF) - -/* RCC GCCR_PLL2EN_PLL3EN masks */ -#define GCCR_PLL2EN_PLL3EN_RESET ((uint32_t)0xEBFFFFFF) - -/* RCC GCFGR2 reset */ -#define GCFGR2_RESET ((uint32_t)0x00000000) - -/* RCC GCIR_INT ans FLAG masks */ -#define GCIR_INT_FLAG_RESET ((uint32_t)0x009F0000) -#define GCIR_INT_FLAG_RESET_CL ((uint32_t)0x00FF0000) - -#define GCCR_HSEEN_HSEBPS_RESET ((uint32_t)0xFFFAFFFF) - -/* RCC GCCR_HSIADJ masks */ -#define GCCR_HSIADJ_OFFSET ((uint32_t)0x00000003) - - -#define RCC_GCFGR_PLLMF_3_0 ((uint32_t)0x003C0000) /*!< PLLMF[3:0] Bits */ - -/* RCC HSI clock divided by 2 masks */ -#define HSI_CLOCK_DIVIDED_2 ((uint32_t)0x00000001) - -/* RCC HSE clock divided by 2 masks */ -#define HSE_CLOCK_DIVIDED_2 ((uint32_t)0x00000001) - - -static __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; -static __I uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - - -/* GCIR register byte 1 (Bits[15:8]) base address */ -#define GCIR_BYTE1_ADDRESS ((uint32_t)0x40021009) - -/* GCIR register byte 2 (Bits[23:16]) base address */ -#define GCIR_BYTE2_ADDRESS ((uint32_t)0x4002100A) - -/* RCC Flag Mask */ -#define FLAG_MASK ((uint8_t)0x1F) - -/** - * @} - */ - -/** @defgroup RCC_Private_Functions - * @{ - */ - -/** - * @brief Reset the RCC clock configuration. - * @param None - * @retval None - */ -void RCC_DeInit(void) -{ - /* Set RCC GCCR_HSIEN mask */ - RCC->GCCR |= GCCR_HSIEN_SET; - - /* Reset SCS[1:0], AHBPS[3:0], APB1PS[2:0],APB2PS[2:0], ADCPS[2:0],CKOTUSEL[2:0] bits */ -#ifdef GD32F10X_CL - RCC->GCFGR &= GCFGR_RESET_CL; -#else - RCC->GCFGR &= GCFGR_RESET; -#endif /* GD32F10X_CL */ - - /* Reset HSEEN, CKMEN and PLLEN bits */ - RCC->GCCR &= GCCR_HSEEN_CKMEN_PLLEN_RESET; - - /* Reset HSEBPS bit */ - RCC->GCCR &= GCCR_HSEBPS_RESET; - - /* Reset PLLSEL, PLLPREDV and PLLMF[4:0] USBPS/OTGFSPS bits */ -#ifdef GD32F10X_CL - RCC->GCFGR &= GCFGR_PLLSEL_PLLPREDV_PLLMF_OTGFSPS_RESET_CL; -#else - RCC->GCFGR &= GCFGR_PLLSEL_PLLPREDV_PLLMF_USBPS_RESET; -#endif /* GD32F10X_CL */ - -#ifdef GD32F10X_CL - /* Reset PLL2EN and PLL3EN bits */ - RCC->GCCR &= GCCR_PLL2EN_PLL3EN_RESET; - - /* Reset GCFGR2 register */ - RCC->GCFGR2 = GCFGR2_RESET ; - - /* Disable all interrupts and clear flag bits */ - RCC->GCIR = GCIR_INT_FLAG_RESET_CL; -#else - /* Disable all interrupts and clear flag bits */ - RCC->GCIR = GCIR_INT_FLAG_RESET; -#endif /* GD32F10X_CL */ -} - -/** - * @brief Configure the External High Speed oscillator (HSE). - * @param RCC_HSE: specify the new state of HSE. - * This parameter can be one of the following values: - * @arg RCC_HSE_OFF: turn off the HSE - * @arg RCC_HSE_ON: turn on the HSE - * @arg RCC_HSE_BYPASS: HSE bypassed with external clock - * @retval None - */ -void RCC_HSEConfig(uint32_t RCC_HSE) -{ - /* Reset HSEEN and HSEBPS bits */ - RCC->GCCR &= GCCR_HSEEN_HSEBPS_RESET; - /* Set the new state of HSE */ - RCC->GCCR |= RCC_HSE; - -} - -/** - * @brief Wait for HSE start-up. - * @param None - * @retval The HSE start-up result(SUCCESS or ERROR) - */ -TypeState RCC_WaitForHSEStartUp(void) -{ - __IO uint32_t HSE_StartOk_Counter = 0; - TypeState HSEState = RESET; - - /* Wait until HSE is ready and if timeout to exit */ - while ((HSE_StartOk_Counter != HSE_STARTUP_TIMEOUT) && (HSEState == RESET)) { - HSEState = RCC_GetBitState(RCC_FLAG_HSESTB); - HSE_StartOk_Counter++; - } - - if (RCC_GetBitState(RCC_FLAG_HSESTB) != RESET) { - return SUCCESS; - } else { - return ERROR; - } -} - -/** - * @brief Adjust the Internal High Speed oscillator (HSI) calibration value. - * @param HSICalibrationValue: the HSI calibration value. - * This parameter must be between 0 and 0x1F. - * @retval None - */ -void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue) -{ - uint32_t temp_adjust = 0; - - temp_adjust = RCC->GCCR; - - /* Clear HSIADJ[4:0] bits */ - temp_adjust &= ~RCC_GCCR_HSIADJ; - - /* Set HSIADJ[4:0] bits according to HSICalibrationValue value */ - temp_adjust |= (uint32_t)HSICalibrationValue << GCCR_HSIADJ_OFFSET ; - - /* Store the calibration value */ - RCC->GCCR = temp_adjust; -} - -/** - * @brief Enable or disable the Internal High Speed oscillator (HSI). - * @param NewValue: new value of the HSI. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_HSI_Enable(TypeState NewValue) -{ - - if (NewValue != DISABLE) { - RCC->GCCR |= RCC_GCCR_HSIEN; - } else { - RCC->GCCR &= ~RCC_GCCR_HSIEN; - } -} - -/** - * @brief Configure the PLL clock source and multiplication factor. - * @param RCC_PLLSelect: specify the PLL clock source. - * For @b GD32_Connectivity_line_devices, this parameter can be one of the following values: - * @arg RCC_PLLSOURCE_HSI_DIV2: HSI divided by 2 selected as PLL clock source - * @arg RCC_PLLSOURCE_PREDIV1: PREDIV1 clock selected as PLL clock source - * For @b other GD32_devices, this parameter can be one of the following values: - * @arg RCC_PLLSOURCE_HSI_DIV2: HSI divided by 2 selected as PLL clock source - * @arg RCC_PLLSOURCE_HSE_DIV1: HSE selected as PLL clock source - * @arg RCC_PLLSOURCE_HSE_DIV2: HSE divided by 2 selected as PLL clock source - * @param RCC_PLLMF: specify the PLL multiplication factor. - * For @b GD32_Connectivity_line_devices, this parameter can be RCC_PLLMUL_x where x:{[2,32], 6_5} - * For @b other_GD32_devices, this parameter can be RCC_PLLMUL_x where x:[2,32] - * @retval None - */ -void RCC_PLLConfig(uint32_t RCC_PLLSelect, uint32_t RCC_PLLMF) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR; - /* Clear PLLSEL [16] and PLLMF[4:0] bits */ - temp &= ~(RCC_GCFGR_PLLMF | RCC_GCFGR_PLLSEL); - /* Set the PLLSEL and PLLMF */ - temp |= RCC_PLLSelect | RCC_PLLMF; - - RCC->GCFGR = temp; -} - -/** - * @brief Enable or disable the PLL. - * @param NewValue: new value of the PLL. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_PLL_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->GCCR |= RCC_GCCR_PLLEN; - } else { - RCC->GCCR &= ~RCC_GCCR_PLLEN; - } -} - - -#ifdef GD32F10X_CL -/** - * @brief Configure the PREDV1 division factor. - * @param RCC_PREDV1_Source: specifies the PREDV1 clock source. - * This parameter can be one of the following values: - * @arg RCC_PREDIV1_SOURCE_HSE: HSE selected as PREDIV1 clock - * @arg RCC_PREDIV1_SOURCE_PLL2: PLL2 selected as PREDIV1 clock - * @param RCC_PREDV1_DIV: specify the PREDV1 division factor. - * This parameter can be RCC_PREDIV1_DIVx where x:[1,16] - * @retval None - */ -void RCC_PREDV1Config(uint32_t RCC_PREDV1_Source, uint32_t RCC_PREDV1_Div) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR2; - /* Clear PREDV1[3:0] and PREDV1SEL bits */ - temp &= ~(RCC_GCFGR2_PREDV1 | RCC_GCFGR2_PREDV1SEL); - /* Set the PREDV1 division factor and PREDV1SEL */ - temp |= (RCC_PREDV1_Div | RCC_PREDV1_Source); - - RCC->GCFGR2 = temp; -} - -/** - * @brief Configure the PREDV2 division factor. - * @param RCC_PREDV2_Div: specify the PREDV2 clock division factor. - * This parameter can be RCC_PREDIV2_DIVx where x:[1,16] - * @retval None - */ -void RCC_PREDV2Config(uint32_t RCC_PREDV2_Div) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR2; - /* Clear PREDV2[3:0] bits */ - temp &= ~RCC_GCFGR2_PREDV2; - /* Set the PREDV2 division factor */ - temp |= RCC_PREDV2_Div; - - RCC->GCFGR2 = temp; -} - -/** - * @brief Configure the PLL2 multiplication factor. - * @param RCC_PLL2MF: specify the PLL2 multiplication factor. - * This parameter can be RCC_PLL2MUL_x where x:{[8,14], 16, 20} - * @retval None - */ -void RCC_PLL2Config(uint32_t RCC_PLL2MF) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR2; - /* Clear PLL2MF[3:0] bits */ - temp &= ~RCC_GCFGR2_PLL2MF; - /* Set the PLL2 configuration bits */ - temp |= RCC_PLL2MF; - - RCC->GCFGR2 = temp; -} - - -/** - * @brief Enable or disable the PLL2. - * @param NewValue: new value of the PLL2. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_PLL2_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->GCCR |= RCC_GCCR_PLL2EN; - } else { - RCC->GCCR &= ~RCC_GCCR_PLL2EN; - } -} - - -/** - * @brief Configure the PLL3 multiplication factor. - * @param RCC_PLL3MF: specify the PLL3 multiplication factor. - * This parameter can be RCC_PLL3MUL_x where x:{[8,14], 16, 20} - * @retval None - */ -void RCC_PLL3Config(uint32_t RCC_PLL3MF) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR2; - /* Clear PLL2MF[3:0] bits */ - temp &= ~RCC_GCFGR2_PLL3MF; - /* Set the PLL3 configuration bits */ - temp |= RCC_PLL3MF; - - RCC->GCFGR2 = temp; -} - - -/** - * @brief Enable or disable the PLL3. - * @param NewValue: new value of the PLL3. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_PLL3_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->GCCR |= RCC_GCCR_PLL3EN; - } else { - RCC->GCCR &= ~RCC_GCCR_PLL3EN; - } -} -#endif /* GD32F10X_CL */ - -/** - * @brief Configure the system clock (CK_SYS) - * @param RCC_SYSCLKSource: specify the system clock source - * This parameter can be one of the following values: - * @arg RCC_SYSCLKSOURCE_HSI: selecte HSI as CK_SYS source - * @arg RCC_SYSCLKSOURCE_HSE: selecte HSE as CK_SYS source - * @arg RCC_SYSCLKSOURCE_PLLCLK: selecte PLL as CK_SYS source - * @retval None - */ -void RCC_CK_SYSConfig(uint32_t RCC_SYSCLKSource) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR; - - /* Clear SCS[1:0] bits */ - temp &= ~RCC_GCFGR_SCS; - - /* Set SCS[1:0] bits according to RCC_SYSCLKSource value */ - temp |= RCC_SYSCLKSource; - - /* Store the new value */ - RCC->GCFGR = temp; -} - -/** - * @brief Get the system clock source. - * @param None - * @retval Get the system clock source. The returned value can be one - * of the following values: - * @arg 0x00: HSI used as CK_SYS source - * @arg 0x04: HSE used as CK_SYS source - * @arg 0x08: PLL used as CK_SYS source - */ -uint8_t RCC_GetCK_SYSSource(void) -{ - return ((uint8_t)(RCC->GCFGR & RCC_GCFGR_SCSS)); -} -/** - * @brief Configure the AHB clock. - * @param RCC_CK_SYSDiv: specify the AHB clock divider. This clock is derived from - * the system clock (CK_SYS). - * This parameter can be one of the following values: - * @arg RCC_SYSCLK_DIV1: AHB clock = CK_SYS - * @arg RCC_SYSCLK_DIV2: AHB clock = CK_SYS/2 - * @arg RCC_SYSCLK_DIV4: AHB clock = CK_SYS/4 - * @arg RCC_SYSCLK_DIV8: AHB clock = CK_SYS/8 - * @arg RCC_SYSCLK_DIV16: AHB clock = CK_SYS/16 - * @arg RCC_SYSCLK_DIV64: AHB clock = CK_SYS/64 - * @arg RCC_SYSCLK_DIV128: AHB clock = CK_SYS/128 - * @arg RCC_SYSCLK_DIV256: AHB clock = CK_SYS/256 - * @arg RCC_SYSCLK_DIV512: AHB clock = CK_SYS/512 - * @retval None - */ -void RCC_AHBConfig(uint32_t RCC_CK_SYSDiv) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR; - - /* Clear AHBPS[3:0] bits */ - temp &= ~RCC_GCFGR_AHBPS; - - /* Set AHBPS[3:0] bits according to RCC_CK_SYSDiv value */ - temp |= RCC_CK_SYSDiv; - - /* Store the new value */ - RCC->GCFGR = temp; -} - -/** - * @brief Configure the APB1 clock. - * @param RCC_APB1: specify the APB1 clock divider. This clock is derived from - * the AHB clock. - * This parameter can be one of the following values: - * @arg RCC_APB1AHB_DIV1: APB1 clock = AHB - * @arg RCC_APB1AHB_DIV2: APB1 clock = AHB/2 - * @arg RCC_APB1AHB_DIV4: APB1 clock = AHB/4 - * @arg RCC_APB1AHB_DIV8: APB1 clock = AHB/8 - * @arg RCC_APB1AHB_DIV16: APB1 clock = AHB/16 - * @retval None - */ -void RCC_APB1Config(uint32_t RCC_APB1) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR; - - /* Clear APB1PS[2:0] bits */ - temp &= ~RCC_GCFGR_APB1PS; - - /* Set APB1PS[2:0] bits according to RCC_APB1 value */ - temp |= RCC_APB1; - - /* Store the new value */ - RCC->GCFGR = temp; -} - -/** - * @brief Configure the APB2 clock. - * @param RCC_APB2: specify the APB2 clock divider. This clock is derived from - * the AHB clock. - * This parameter can be one of the following values: - * @arg RCC_APB2AHB_DIV1: APB2 clock = AHB - * @arg RCC_APB2AHB_DIV2: APB2 clock = AHB/2 - * @arg RCC_APB2AHB_DIV4: APB2 clock = AHB/4 - * @arg RCC_APB2AHB_DIV8: APB2 clock = AHB/8 - * @arg RCC_APB2AHB_DIV16: APB2 clock = AHB/16 - * @retval None - */ -void RCC_APB2Config(uint32_t RCC_APB2) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR; - - /* Clear APB2PS[2:0] bits */ - temp &= ~RCC_GCFGR_APB2PS; - - /* Set APB2PS[2:0] bits according to RCC_APB2 value */ - temp |= RCC_APB2; - - /* Store the new value */ - RCC->GCFGR = temp; -} - -#ifdef GD32F10X_CL -/** - * @brief Configure the USB_OTG clock (USB_OTG CLK). - * @param RCC_OTGFSCLK: specify the USB_OTG clock source. This clock is derived - * from the PLL. - * This parameter can be one of the following values: - * @arg RCC_OTGCLK_PLL_DIV1_5: USB_OTG clock = PLL/1.5 - * @arg RCC_OTGCLK_PLL_DIV1: USB_OTG clock = PLL - * @arg RCC_OTGCLK_PLL_DIV2: USB_OTG clock = PLL/2 - * @arg RCC_OTGCLK_PLL_DIV2_5: USB-OTG clock = PLL/2.5 - * @retval None - */ -void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLK) -{ - - /* Clear OTGFSPS bit */ - RCC->GCFGR &= ~RCC_GCFGR_OTGFSPS; - /* Set OTGFSPS bits according to RCC_OTGFSCLK value */ - RCC->GCFGR |= RCC_OTGFSCLK; - -} - -#else -/** - * @brief Configure the USB clock (USBCLK). - * @param RCC_USBCLK: specify the USB clock source. This clock is derived - * from the PLL. - * This parameter can be one of the following values: - * @arg RCC_USBCLK_PLL_DIV1_5: USB clock = PLL/1.5 - * @arg RCC_USBCLK_PLL_DIV1: USB clock = PLL - * @arg RCC_USBCLK_PLL_DIV2: USB clock = PLL/2 - * @arg RCC_USBCLK_PLL_DIV2_5: USB clock = PLL/2.5 - * @retval None - */ -void RCC_USBCLKConfig(uint32_t RCC_USBCLK) -{ - - /* Clear USBPS bit */ - RCC->GCFGR &= ~RCC_GCFGR_USBPS; - /* Set USBPS bits according to RCC_USBCLK value */ - RCC->GCFGR |= RCC_USBCLK; - -} -#endif /* GD32F10X_CL */ - -/** - * @brief Configure the ADC clock (ADCCLK). - * @param RCC_ADCCLK: specify the ADC clock source. This clock is derived from APB2 clock. - * This parameter can be one of the following values: - * @arg RCC_ADCCLK_APB2_DIV2: ADC clock = APB2/2 - * @arg RCC_ADCCLK_APB2_DIV4: ADC clock = APB2/4 - * @arg RCC_ADCCLK_APB2_DIV6: ADC clock = APB2/6 - * @arg RCC_ADCCLK_APB2_DIV8: ADC clock = APB2/8 - * @arg RCC_ADCCLK_APB2_DIV12: ADC clock = APB2/12 - * @arg RCC_ADCCLK_APB2_DIV16: ADC clock = APB2/16 - * @retval None - */ -void RCC_ADCCLKConfig(uint32_t RCC_ADCCLK) -{ - - /* Clear ADCPS bit */ - RCC->GCFGR &= ~RCC_GCFGR_ADCPS; - /* Set ADCPS bits according to RCC_APB2 value */ - RCC->GCFGR |= RCC_ADCCLK; -} - -#ifdef GD32F10X_CL -/** - * @brief Configure the I2S2 clock source(I2S2CLK). - * @param RCC_I2S2CLK: specify the I2S2 clock source. - * This parameter can be one of the following values: - * @arg RCC_I2S2CLK_SYSCLK: system clock selected as I2S2 clock entry - * @arg RCC_I2S2CLK_PLL3: PLL3 clock selected as I2S2 clock entry - * @note If the RCC_I2S2CLK_PLL3 selected, the I2S2 clock is (PLL3 x 2). - * @retval None - */ -void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLK) -{ - /* Clear I2S2SEL bit */ - RCC->GCFGR2 &= ~RCC_GCFGR2_I2S2SEL; - /* Set I2S2CLK bits according to RCC_I2S2CLK value */ - RCC->GCFGR2 |= RCC_I2S2CLK; - -} - -/** - * @brief Configure the I2S3 clock source(I2S3CLK). - * @param RCC_I2S3CLK: specify the I2S3 clock source. - * This parameter can be one of the following values: - * @arg RCC_I2S3CLK_SYSCLK: system clock selected as I2S3 clock entry - * @arg RCC_I2S3CLK_PLL3: PLL3 clock selected as I2S3 clock entry - * @note If the RCC_I2S3CLK_PLL3 selected, the I2S3 clock is (PLL3 x 2). - * @retval None - */ -void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLK) -{ - /* Clear I2S3SEL bit */ - RCC->GCFGR2 &= ~RCC_GCFGR2_I2S3SEL; - /* Set I2S3CLK bits according to RCC_I2S3CLK value */ - RCC->GCFGR2 |= RCC_I2S3CLK; -} -#endif /* GD32F10X_CL */ - -/** - * @brief Configure the External Low Speed oscillator (LSE). - * @param RCC_LSE: specify the new state of the LSE. - * This parameter can be one of the following values: - * @arg RCC_LSE_OFF: turn off the LSE - * @arg RCC_LSE_EN: turn on the LSE - * @arg RCC_LSE_BYPASS: LSE bypassed with external clock - * @retval None - */ -void RCC_LSEConfig(uint32_t RCC_LSE) -{ - - /* Reset LSEEN and LSEBPS bits before configuring the LSE */ - RCC->BDCR &= ~(RCC_BDCR_LSEEN); - RCC->BDCR &= ~(RCC_BDCR_LSEBPS); - - /* Configure LSE */ - RCC->BDCR |= RCC_LSE; -} - - -/** - * @brief Enable or disable the Internal Low Speed oscillator (LSI). - * @param NewValue: new value of the LSI. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_LSI_Enable(TypeState NewValue) -{ - - if (NewValue != DISABLE) { - RCC->GCSR |= RCC_GCSR_LSIEN; - } else { - RCC->GCSR &= ~RCC_GCSR_LSIEN; - } -} - -/** - * @brief Configure the RTC clock (RTCCLK). - * @param RCC_RTCCLKSource: specify the RTC clock source. - * This parameter can be one of the following values: - * @arg RCC_RTCCLKSOURCE_LSE: selecte LSE as RTC clock - * @arg RCC_RTCCLKSOURCE_LSI: selecte LSI as RTC clock - * @arg RCC_RTCCLKSOURCE_HSE_DIV128: selecte HSE divided by 128 as RTC clock - * @note if using HSE as RTC source, the maximum clock frequency for RTC is 2 MHz. - * @retval None - */ -void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource) -{ - /* Clear RTCSEL bit */ - RCC->BDCR &= ~RCC_BDCR_RTCSEL; - /* Select the RTC clock source */ - RCC->BDCR |= RCC_RTCCLKSource; -} - -/** - * @brief Enable or disable the RTC clock. - * @param NewValue: new state of the RTC clock. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_RTCCLK_Enable(TypeState NewValue) -{ - - if (NewValue != DISABLE) { - RCC->BDCR |= RCC_BDCR_RTCEN; - } else { - RCC->BDCR &= ~RCC_BDCR_RTCEN; - } -} - -/** - * @brief Get the frequencies of the CK_SYS, AHB, APB1, APB2, ADC clocks. - * @retval None - */ -void RCC_GetClocksFreq(RCC_ClocksPara *RCC_Clocks) -{ - uint32_t temp = 0, pllmf = 0, pllmf4 = 0, pllselect = 0, presc = 0; - -#ifdef GD32F10X_CL - uint32_t prediv1select = 0, prediv1factor = 0, prediv2factor = 0, pll2mf = 0; -#endif /* GD32F10X_CL */ - - - /* Get CK_SYS source */ - temp = RCC->GCFGR & RCC_GCFGR_SCSS; - - switch (temp) { - case 0x00: /* HSI used as CK_SYS */ - RCC_Clocks->CK_SYS_Frequency = HSI_VALUE; - break; - case 0x04: /* HSE used as CK_SYS */ - RCC_Clocks->CK_SYS_Frequency = HSE_VALUE; - break; - case 0x08: /* PLL used as CK_SYS */ -#ifdef GD32F10X_CL - /* Get PLL clock source and multiplication factor */ - /* Get PLLMF[3:0] */ - pllmf = RCC->GCFGR & RCC_GCFGR_PLLMF_3_0; - /* Get PLLMF[4] */ - pllmf4 = RCC->GCFGR & RCC_GCFGR_PLLMF_4; - - pllmf4 = ((pllmf4 >> 29) * 16); - - pllmf = (pllmf >> 18) + pllmf4; - if (pllmf == 0x0D) { - /* PLL multiplication factor = PLL input clock * 6.5*/ - /* Beacause of the float number 6.5, pllmf * 2 to remove the float number */ - pllmf = 13 * 2 / 2; - - } else if (pllmf >= 0x0F) { - pllmf += 1; - /* Here is consistent with the above that pllmf * 2 to remove the float number*/ - pllmf = pllmf * 2; - } else { - pllmf += 2; - /* Here is consistent with the above that pllmf * 2 to remove the float number*/ - pllmf = pllmf * 2; - } - - pllselect = RCC->GCFGR & RCC_GCFGR_PLLSEL; - if (pllselect == 0x00) { - /* HSI clock divided by 2 selected as PLL clock source */ - /* Here is consistent with the above that pllmf / 2 */ - RCC_Clocks->CK_SYS_Frequency = (HSI_VALUE >> HSI_CLOCK_DIVIDED_2) * pllmf / 2; - } else { - /* PREDIV1 selected as PLL clock entry */ - - /* Get PREDIV1 clock source and division factor */ - prediv1select = RCC->GCFGR2 & RCC_GCFGR2_PREDV1SEL; - prediv1factor = (RCC->GCFGR2 & RCC_GCFGR2_PREDV1) + 1; - - if (prediv1select == 0) { - /* HSE clock selected as PREDIV1 clock entry */ - /* Here is consistent with the above that pllmf / 2 */ - RCC_Clocks->CK_SYS_Frequency = (HSE_VALUE / prediv1factor) * pllmf / 2; - } else { - /* PLL2 clock selected as PREDIV1 clock entry */ - /* Get PREDIV2 division factor and PLL2 multiplication factor */ - prediv2factor = ((RCC->GCFGR2 & RCC_GCFGR2_PREDV2) >> 4) + 1; - pll2mf = ((RCC->GCFGR2 & RCC_GCFGR2_PLL2MF) >> 8); - if (pll2mf != 15) { - pll2mf += 2; - } else { - pll2mf += 5; - } - /* Here is consistent with the above that pllmf / 2 */ - RCC_Clocks->CK_SYS_Frequency = (((HSE_VALUE / prediv2factor) * pll2mf) / prediv1factor) * pllmf / 2; - } - } -#else - /* Get PLL clock source and multiplication factor */ - /* Get PLLMF[3:0] */ - pllmf = RCC->GCFGR & RCC_GCFGR_PLLMF_3_0; - /* Get PLLMF[4] */ - pllmf4 = RCC->GCFGR & RCC_GCFGR_PLLMF_4; - - pllmf4 = ((pllmf4 >> 27) * 16); - pllmf = (pllmf >> 18) + pllmf4; - if (pllmf >= 0x0F) - pllmf += 1; - else - pllmf += 2; - - pllselect = RCC->GCFGR & RCC_GCFGR_PLLSEL; - if (pllselect == 0x00) { - /* HSI clock divided by 2 selected as PLL clock source */ - RCC_Clocks->CK_SYS_Frequency = (HSI_VALUE >> HSI_CLOCK_DIVIDED_2) * pllmf; - } else { - if ((RCC->GCFGR & RCC_GCFGR_PLLPREDV) != (uint32_t)RESET) { - /* HSE clock divided by 2 */ - RCC_Clocks->CK_SYS_Frequency = (HSE_VALUE >> HSE_CLOCK_DIVIDED_2) * pllmf; - } else { - RCC_Clocks->CK_SYS_Frequency = HSE_VALUE * pllmf; - } - } -#endif/* GD32F10X_CL */ - break; - default: /* HSI used as system clock */ - RCC_Clocks->CK_SYS_Frequency = HSI_VALUE; - break; - } - - /* Get AHB prescaler */ - temp = RCC->GCFGR & RCC_GCFGR_AHBPS; - temp = temp >> 4; - presc = AHBPrescTable[temp]; - /* Get AHB clock frequency */ - RCC_Clocks->AHB_Frequency = RCC_Clocks->CK_SYS_Frequency >> presc; - - /* Get APB1 prescaler */ - temp = RCC->GCFGR & RCC_GCFGR_APB1PS; - temp = temp >> 8; - presc = APBPrescTable[temp]; - /* Get APB1 clock frequency */ - RCC_Clocks->APB1_Frequency = RCC_Clocks->AHB_Frequency >> presc; - - /* Get APB2 prescaler */ - temp = RCC->GCFGR & RCC_GCFGR_APB2PS; - temp = temp >> 11; - presc = APBPrescTable[temp]; - /* Get APB2 clock frequency */ - RCC_Clocks->APB2_Frequency = RCC_Clocks->AHB_Frequency >> presc; - - /* Get ADCCLK clock frequency */ - temp = ((RCC->GCFGR & RCC_GCFGR_ADCPS_2) >> 26); - temp += ((RCC->GCFGR & (RCC_GCFGR_ADCPS_0 | RCC_GCFGR_ADCPS_1)) >> 14); - switch (temp) { - case 0x00: /* ADC Clock is derived from APB2/2 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 2); - break; - case 0x01: /* ADC Clock is derived from APB2/4 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 4); - break; - case 0x02: /* ADC Clock is derived from APB2/6 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 6); - break; - case 0x03: /* ADC Clock is derived from APB2/8 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 8); - break; - case 0x04: /* ADC Clock is derived from APB2/2 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 2); - break; - case 0x05: /* ADC Clock is derived from APB2/12 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 12); - break; - case 0x06: /* ADC Clock is derived from APB2/8 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 8); - break; - case 0x07: /* ADC Clock is derived from APB2/16 */ - RCC_Clocks->ADCCLK_Frequency = (RCC_Clocks->APB2_Frequency / 16); - break; - default: - break; - } -} - -/** - * @brief Enable or disable the AHB peripheral clock. - * @param RCC_AHBPeriph: specify the AHB peripheral clock. - * For @b GD32_Connectivity_line_devices, - * this parameter can be any combination of the following values: - * @arg RCC_AHBPERIPH_DMA1 - * @arg RCC_AHBPERIPH_DMA2 - * @arg RCC_AHBPERIPH_SRAM - * @arg RCC_AHBPERIPH_FMC - * @arg RCC_AHBPERIPH_CRC - * @arg RCC_AHBPERIPH_EXMC - * @arg RCC_AHBPERIPH_OTG_FS - * @arg RCC_AHBPERIPH_ETH_MAC - * @arg RCC_AHBPERIPH_ETH_MAC_RX - * @arg RCC_AHBPERIPH_ETH_MAC_TX - * - * For @b other_GD32_devices, this parameter can be any combination of the - * following values: - * @arg RCC_AHBPERIPH_DMA1 - * @arg RCC_AHBPERIPH_DMA2 - * @arg RCC_AHBPERIPH_SRAM - * @arg RCC_AHBPERIPH_FMC - * @arg RCC_AHBPERIPH_CRC - * @arg RCC_AHBPERIPH_EXMC - * @arg RCC_AHBPERIPH_SDIO - * @param NewValue: new state of the peripheral clock. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_AHBPeriphClock_Enable(uint32_t RCC_AHBPeriph, TypeState NewValue) -{ - - if (NewValue != DISABLE) { - RCC->AHBCCR |= RCC_AHBPeriph; - } else { - RCC->AHBCCR &= ~RCC_AHBPeriph; - } -} - -/** - * @brief Enable or disable the APB2 peripheral clock. - * @param RCC_APB2Periph: specify the APB2 peripheral clock. - * This parameter can be any combination of the following values: - * @arg RCC_APB2PERIPH_AF - * @arg RCC_APB2PERIPH_GPIOA - * @arg RCC_APB2PERIPH_GPIOB - * @arg RCC_APB2PERIPH_GPIOC - * @arg RCC_APB2PERIPH_GPIOD - * @arg RCC_APB2PERIPH_GPIOE - * @arg RCC_APB2PERIPH_GPIOF - * @arg RCC_APB2PERIPH_GPIOG - * @arg RCC_APB2PERIPH_ADC1 - * @arg RCC_APB2PERIPH_ADC2 - * @arg RCC_APB2PERIPH_TIMER1 - * @arg RCC_APB2PERIPH_SPI1 - * @arg RCC_APB2PERIPH_TIMER8 - * @arg RCC_APB2PERIPH_USART1 - * @arg RCC_APB2PERIPH_ADC3 - * @arg RCC_APB2PERIPH_TIMER9 - * @arg RCC_APB2PERIPH_TIMER10 - * @arg RCC_APB2PERIPH_TIMER11 - * @param NewValue: new state of the peripheral clock. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_APB2PeriphClock_Enable(uint32_t RCC_APB2Periph, TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->APB2CCR |= RCC_APB2Periph; - } else { - RCC->APB2CCR &= ~RCC_APB2Periph; - } -} - -/** - * @brief Enable or disable the APB1 peripheral clock. - * @param RCC_APB1Periph: specify the APB1 peripheral clock. - * This parameter can be any combination of the following values: - * @arg RCC_APB1PERIPH_TIMER2 - * @arg RCC_APB1PERIPH_TIMER3 - * @arg RCC_APB1PERIPH_TIMER4 - * @arg RCC_APB1PERIPH_TIMER5 - * @arg RCC_APB1PERIPH_TIMER6 - * @arg RCC_APB1PERIPH_TIMER7 - * @arg RCC_APB1PERIPH_TIMER12 - * @arg RCC_APB1PERIPH_TIMER13 - * @arg RCC_APB1PERIPH_TIMER14 - * @arg RCC_APB1PERIPH_WWDG - * @arg RCC_APB1PERIPH_SPI2 - * @arg RCC_APB1PERIPH_SPI3, - * @arg RCC_APB1PERIPH_USART2 - * @arg RCC_APB1PERIPH_USART3 - * @arg RCC_APB1PERIPH_UART4 - * @arg RCC_APB1PERIPH_UART5 - * @arg RCC_APB1PERIPH_I2C1 - * @arg RCC_APB1PERIPH_I2C2 - * @arg RCC_APB1PERIPH_USB - * @arg RCC_APB1PERIPH_CAN1 - * @arg RCC_APB1PERIPH_CAN2 - * @arg RCC_APB1PERIPH_BKP - * @arg RCC_APB1PERIPH_PWR - * @arg RCC_APB1PERIPH_DAC - * @param NewState: new state of the specified peripheral clock. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_APB1PeriphClock_Enable(uint32_t RCC_APB1Periph, TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->APB1CCR |= RCC_APB1Periph; - } else { - RCC->APB1CCR &= ~RCC_APB1Periph; - } -} - -#ifdef GD32F10X_CL -/** - * @brief Force or release AHB peripheral reset. - * @param RCC_AHBPeriphRST: specify the AHB peripheral to reset. - * This parameter can be any combination of the following values: - * @arg RCC_AHBPeriph_OTGFSRST - * @arg RCC_AHBPeriph_ETHMACRST - * @param NewState: new state of the specified peripheral reset. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_AHBPeriphReset_Enable(uint32_t RCC_AHBPeriphRST, TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->AHBRCR |= RCC_AHBPeriphRST; - } else { - RCC->AHBRCR &= ~RCC_AHBPeriphRST; - } -} -#endif /* GD32F10X_CL */ - -/** - * @brief Force or release APB2 peripheral reset. - * @param RCC_APB2PeriphRST: specify the APB2 peripheral to reset. - * This parameter can be any combination of the following values: - * @arg RCC_APB2PERIPH_AFRST - * @arg RCC_APB2PERIPH_GPIOARST - * @arg RCC_APB2PERIPH_GPIOBRST - * @arg RCC_APB2PERIPH_GPIOCRST - * @arg RCC_APB2PERIPH_GPIODRST - * @arg RCC_APB2PERIPH_GPIOERST - * @arg RCC_APB2PERIPH_GPIOFRST - * @arg RCC_APB2PERIPH_GPIOGRST - * @arg RCC_APB2PERIPH_ADC1RST - * @arg RCC_APB2PERIPH_ADC2RST - * @arg RCC_APB2PERIPH_TIMER1RST - * @arg RCC_APB2PERIPH_SPI1RST - * @arg RCC_APB2PERIPH_TIMER8RST - * @arg RCC_APB2PERIPH_USART1RST - * @arg RCC_APB2PERIPH_ADC3RST - * @arg RCC_APB2PERIPH_TIMER9RST - * @arg RCC_APB2PERIPH_TIMER10RST - * @arg RCC_APB2PERIPH_TIMER11RST - * @param NewValue: new state of the peripheral reset. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_APB2PeriphReset_Enable(uint32_t RCC_APB2PeriphRST, TypeState NewValue) -{ - - if (NewValue != DISABLE) { - RCC->APB2RCR |= RCC_APB2PeriphRST; - } else { - RCC->APB2RCR &= ~RCC_APB2PeriphRST; - } -} - - -/** - * @brief Force or release APB1 peripheral reset. - * @param RCC_APB1PeriphRST: specify the APB1 peripheral to reset. - * This parameter can be any combination of the following values: - * @arg RCC_APB1PERIPH_TIMER2RST - * @arg RCC_APB1PERIPH_TIMER3RST - * @arg RCC_APB1PERIPH_TIMER4RST - * @arg RCC_APB1PERIPH_TIMER5RST - * @arg RCC_APB1PERIPH_TIMER6RST - * @arg RCC_APB1PERIPH_TIMER7RST - * @arg RCC_APB1PERIPH_TIMER12RST - * @arg RCC_APB1PERIPH_TIMER13RST - * @arg RCC_APB1PERIPH_TIMER14RST - * @arg RCC_APB1PERIPH_WWDGRST - * @arg RCC_APB1PERIPH_SPI2RST - * @arg RCC_APB1PERIPH_SPI3RST - * @arg RCC_APB1PERIPH_USART2RST - * @arg RCC_APB1PERIPH_USART3RST - * @arg RCC_APB1PERIPH_UART4RST - * @arg RCC_APB1PERIPH_UART5RST - * @arg RCC_APB1PERIPH_I2C1RST - * @arg RCC_APB1PERIPH_I2C2RST - * @arg RCC_APB1PERIPH_USBRST - * @arg RCC_APB1PERIPH_CAN1RST - * @arg RCC_APB1PERIPH_CAN2RST - * @arg RCC_APB1PERIPH_BKPRST - * @arg RCC_APB1PERIPH_PWRRST - * @arg RCC_APB1PERIPH_DACRST - * @param NewValue: new state of the peripheral clock (ENABLE or DISABLE). - * @retval None - */ -void RCC_APB1PeriphReset_Enable(uint32_t RCC_APB1PeriphRST, TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->APB1RCR |= RCC_APB1PeriphRST; - } else { - RCC->APB1RCR &= ~RCC_APB1PeriphRST; - } -} - -/** - * @brief Force or release the Backup domain reset. - * @param NewValue: new state of the Backup domain reset (ENABLE or DISABLE). - * @retval None - */ -void RCC_BackupReset_Enable(TypeState NewValue) -{ - - if (NewValue != DISABLE) { - RCC->BDCR |= RCC_BDCR_BKPRST; - } else { - RCC->BDCR &= ~RCC_BDCR_BKPRST; - } -} - -/** - * @brief Enable or disable the Clock Security System. - * @param NewValue: new value of the Clock Security System. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RCC_HSEClockMonitor_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - RCC->GCCR |= RCC_GCCR_CKMEN; - } else { - RCC->GCCR &= ~RCC_GCCR_CKMEN; - } -} - -/** - * @brief Select the clock source to output on CKOUTSRC and the corresponding prescaler. - * @param RCC_CKOUTSRC: specify the clock source to output. - * For @b GD32_Connectivity_line_devices, this parameter can be one of the - * following values: - * @arg RCC_CKOUTSRC_NOCLOCK: No clock selected - * @arg RCC_CKOUTSRC_SYSCLK: System clock selected - * @arg RCC_CKOUTSRC_HSI: HSI oscillator clock selected - * @arg RCC_CKOUTSRC_HSE: HSE oscillator clock selected - * @arg RCC_CKOUTSRC_PLL2CLK: PLL2 clock selected - * @arg RCC_CKOUTSRC_PLLCLK_DIV2: PLL clock divided by 2 selected - * @arg RCC_CKOUTSRC_PLL3CLK: PLL3 clock selected - * @arg RCC_CKOUTSRC_PLL3CLK_DIV2: PLL3 clock divided by 2 selected - * @arg RCC_CKOUTSRC_EXT1: External 3-25 MHz oscillator clock selected - * For @b other_GD32_devices, this parameter can be one of the following values: - * @arg RCC_CKOUTSRC_NOCLOCK: No clock selected - * @arg RCC_CKOUTSRC_SYSCLK: System clock selected - * @arg RCC_CKOUTSRC_HSI: HSI oscillator clock selected - * @arg RCC_CKOUTSRC_HSE: HSE oscillator clock selected - * @arg RCC_CKOUTSRC_PLLCLK_DIV2: PLL clock divided by 2 selected - * @retval None - */ - -void RCC_CKOUTSRCConfig(uint32_t RCC_CKOUTSRC) -{ - uint32_t temp = 0; - - temp = RCC->GCFGR; - /* Clear CKOUTSRC[2:0] bits */ - temp &= ~(RCC_GCFGR_CKOUTSEL); - /* Set the RCC_CKOUTSRC */ - temp |= RCC_CKOUTSRC; - /* Store the new value */ - RCC->GCFGR = temp; -} - - -/** - * @brief Enable or disable RCC interrupts. - * @param RCC_INT: specify the RCC interrupt sources. - * For @b GD32_Connectivity_line_devices, this parameter can be any combination - * of the following values - * @arg RCC_INT_LSISTB: LSI ready interrupt - * @arg RCC_INT_LSESTB LSE ready interrupt - * @arg RCC_INT_HSISTB: HSI ready interrupt - * @arg RCC_INT_HSESTB: HSE ready interrupt - * @arg RCC_INT_PLLSTB: PLL ready interrupt - * @arg RCC_INT_PLL2STB: PLL2 ready interrupt - * @arg RCC_INT_PLL3STB: PLL3 ready interrupt - * - * For @b other_GD32_devices, this parameter can be any combination of the - * following values - * @arg RCC_INT_LSISTB: LSI ready interrupt - * @arg RCC_INT_LSESTB: LSE ready interrupt - * @arg RCC_INT_HSISTB: HSI ready interrupt - * @arg RCC_INT_HSESTB: HSE ready interrupt - * @arg RCC_INT_PLLSTB: PLL ready interrupt - * @param NewValue: new state of the RCC interrupts (ENABLE or DISABLE). - * @retval None - */ -void RCC_INTConfig(uint8_t RCC_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Perform Byte access to RCC_GCIR[14:8] bits to enable the selected interrupts */ - *(__IO uint8_t *) GCIR_BYTE1_ADDRESS |= RCC_INT; - } else { - /* Perform Byte access to RCC_GCIR bits to disable the selected interrupts */ - *(__IO uint8_t *) GCIR_BYTE1_ADDRESS &= (uint8_t)~RCC_INT; - } -} - - -/** - * @brief Check whether the specified RCC flag is set or not. - * @param RCC_FLAG: specify the flag to check. - * For @b GD32_Connectivity_line_devices, this parameter can be one of the - * following values: - * @arg RCC_FLAG_HSISTB: HSI clock ready - * @arg RCC_FLAG_HSESTB: HSE clock ready - * @arg RCC_FLAG_PLLSTB: PLL clock ready - * @arg RCC_FLAG_PLL2STB: PLL2 clock ready - * @arg RCC_FLAG_PLL3STB: PLL3 clock ready - * @arg RCC_FLAG_LSESTB: LSE clock ready - * @arg RCC_FLAG_LSISTB: LSI clock ready - * @arg RCC_FLAG_EPRST: Pin reset - * @arg RCC_FLAG_POPDRST: POR/PDR reset - * @arg RCC_FLAG_SWRRST: Software reset - * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset - * @arg RCC_FLAG_WWDGRST: Window Watchdog reset - * @arg RCC_FLAG_LPRRST: Low Power reset - * For @b other_GD32_devices, this parameter can be one of the following values: - * @arg RCC_FLAG_HSISTB: HSI oscillator clock ready - * @arg RCC_FLAG_HSESTB: HSE oscillator clock ready - * @arg RCC_FLAG_PLLSTB: PLL clock ready - * @arg RCC_FLAG_LSESTB: LSE oscillator clock ready - * @arg RCC_FLAG_LSISTB: LSI oscillator clock ready - * @arg RCC_FLAG_EPRST: Pin reset - * @arg RCC_FLAG_POPDRST: POR/PDR reset - * @arg RCC_FLAG_SWRRST: Software reset - * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset - * @arg RCC_FLAG_WWDGRST: Window Watchdog reset - * @arg RCC_FLAG_LPRRST: Low Power reset - * @retval The new state of RCC_FLAG (SET or RESET). - */ -TypeState RCC_GetBitState(uint8_t RCC_FLAG) -{ - uint32_t temp = 0; - uint32_t statusreg = 0; - - /* Get the RCC register index */ - temp = RCC_FLAG >> 5; - - /* The flag to check is in GCCR register */ - if (temp == 1) { - statusreg = RCC->GCCR; - } - - /* The flag to check is in BDCR register */ - else if (temp == 2) { - statusreg = RCC->BDCR; - } - - /* The flag to check is in GCSR register */ - else { - statusreg = RCC->GCSR; - } - - /* Get the flag position */ - temp = RCC_FLAG & FLAG_MASK; - if ((statusreg & ((uint32_t)(1 << temp))) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } - -} - -/** - * @brief Clear the RCC all reset flags. - * @param None - * @retval None - */ -void RCC_ClearBitState(void) -{ - /* Set RSTFC bit to clear all reset flags */ - RCC->GCSR |= RCC_GCSR_RSTFC; -} - - -/** - * @brief Check whether the RCC interrupt has occurred or not. - * @param RCC_INT: specify the RCC interrupt source to check. - * For @b GD32_Connectivity_line_devices, this parameter can be one of the - * following values: - * @arg RCC_INT_LSISTB: the flag of LSI ready interrupt - * @arg RCC_INT_LSESTB: the flag of LSE ready interrupt - * @arg RCC_INT_HSISTB: the flag of HSI ready interrupt - * @arg RCC_INT_HSESTB: the flag of HSE ready interrupt - * @arg RCC_INT_PLLSTB: the flag of PLL ready interrupt - * @arg RCC_INT_PLL2STB: the flag of PLL2 ready interrupt - * @arg RCC_INT_PLL3STB: the flag of PLL3 ready interrupt - * @arg RCC_INT_CKM: the flag of Clock Security System interrupt - * For @b other_GD32_devices, this parameter can be one of the following values: - * @arg RCC_INT_LSISTB: the flag of LSI ready interrupt - * @arg RCC_INT_LSESTB: the flag of LSE ready interrupt - * @arg RCC_INT_HSISTB: the flag of HSI ready interrupt - * @arg RCC_INT_HSESTB: the flag of HSE ready interrupt - * @arg RCC_INT_PLLSTB: the flag of PLL ready interrupt - * @arg RCC_INT_CKM: the flag of Clock Security System interrupt - * @retval The new state of RCC_INT (SET or RESET). - */ -TypeState RCC_GetIntBitState(uint8_t RCC_INT) -{ - /* Check the status of the RCC interrupt */ - if ((RCC->GCIR & RCC_INT) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} -/** - * @brief Clear the RCC interrupt bits. - * @param RCC_INT: specify the interrupt bit to clear. - * For @b GD32_Connectivity_line_devices, this parameter can be any combination - * of the following values: - * @arg RCC_INT_LSISTB: LSI ready interrupt - * @arg RCC_INT_LSESTB LSE ready interrupt - * @arg RCC_INT_HSISTB: HSI ready interrupt - * @arg RCC_INT_HSESTB: HSE ready interrupt - * @arg RCC_INT_PLLSTB: PLL ready interrupt - * @arg RCC_INT_PLL2STB: PLL2 ready interrupt - * @arg RCC_INT_PLL3STB: PLL3 ready interrupt - * @arg RCC_INT_CKM: Clock Security System interrupt - * For @b other_GD32_devices, this parameter can be any combination of the - * following values - * @arg RCC_INT_LSISTB: LSI ready interrupt - * @arg RCC_INT_LSESTB: LSE ready interrupt - * @arg RCC_INT_HSISTB: HSI ready interrupt - * @arg RCC_INT_HSESTB: HSE ready interrupt - * @arg RCC_INT_PLLSTB: PLL ready interrupt - * @arg RCC_INT_CKM: Clock Security System interrupt - * @retval None - */ - -void RCC_ClearIntBitState(uint8_t RCC_INT) -{ - - - /* Perform RCC_GCIR[23:16] bits to clear the selected interrupt bits */ - *(__IO uint8_t *) GCIR_BYTE2_ADDRESS = RCC_INT; -} - -/** - * @brief Configure the kernel voltage in Deep-sleep mode. - * @note Only unlock the power,this configuration is effective. - * @param RCC_KERNEL_VOL: specify the kernel voltage. - * This parameter can be one of the following values: - * @arg RCC_KERNEL_VOL1_2: The kernel voltage in Deep-sleep mode is 1.2V - * @arg RCC_KERNEL_VOL1_1: The kernel voltage in Deep-sleep mode is 1.1V - * @arg RCC_KERNEL_VOL1_0: The kernel voltage in Deep-sleep mode is 1.0V - * @arg RCC_KERNEL_VOL0_9: The kernel voltage in Deep-sleep mode is 0.9V - * @retval None - */ -void RCC_KERNELVOLConfig(uint32_t RCC_KERNEL_VOL) -{ - /* Clear DEEPSLEEP_VC bit */ - RCC->RCC_DEEPSLEEP_VC &= ~RCC_DEEPSLEEP_VC_CLEAR; - /* Set DEEPSLEEP_VC bits according to RCC_KERNEL_VOL value */ - RCC->RCC_DEEPSLEEP_VC |= RCC_KERNEL_VOL; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - - - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcu.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcu.c deleted file mode 100644 index 1757e170ef..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rcu.c +++ /dev/null @@ -1,1277 +0,0 @@ -/*! - \file gd32f10x_rcu.c - \brief RCU driver -*/ - -/* - Copyright (C) 2017 GigaDevice - - 2017-02-10, V1.0.1, firmware for GD32F30x - 2021-01-02, firmware for GD32F10x -*/ - -#include "gd32f10x_rcu.h" - -/* define clock source */ -#define SEL_IRC8M ((uint16_t)0U) -#define SEL_HXTAL ((uint16_t)1U) -#define SEL_PLL ((uint16_t)2U) - -/* define startup timeout count */ -#define OSC_STARTUP_TIMEOUT ((uint32_t)0xFFFFFU) -#define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x3FFFFFFU) - -/*! - \brief deinitialize the RCU - \param[in] none - \param[out] none - \retval none -*/ -void rcu_deinit(void) -{ - /* enable IRC8M */ - RCU_CTL |= RCU_CTL_IRC8MEN; - rcu_osci_stab_wait(RCU_IRC8M); - - /* reset CFG0 register */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF | - RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2); -#elif defined(GD32F10X_CL) - RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | - RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | - RCU_CFG0_USBFSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBFSPSC_2); -#endif /* GD32F10X_HD and GD32F10X_XD */ - /* reset CTL register */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); - RCU_CTL &= ~RCU_CTL_HXTALBPS; -#ifdef GD32F10X_CL - RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN); -#endif /* GD32F10X_CL */ - - /* reset INT and CFG1 register */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - RCU_INT = 0x009f0000U; - RCU_CFG1 &= ~(RCU_CFG1_ADCPSC_3 | RCU_CFG1_PLLPRESEL); -#elif defined(GD32F10X_CL) - RCU_INT = 0x00ff0000U; - RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF | - RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_ADCPSC_3 | - RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4); -#endif /* GD32F10X_HD and GD32F10X_XD */ -} - -/*! - \brief enable the peripherals clock - \param[in] periph: RCU peripherals, refer to rcu_periph_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock - \arg RCU_AF : alternate function clock - \arg RCU_CRC: CRC clock - \arg RCU_DMAx (x=0,1): DMA clock - \arg RCU_ENET: ENET clock(CL series available) - \arg RCU_ENETTX: ENETTX clock(CL series available) - \arg RCU_ENETRX: ENETRX clock(CL series available) - \arg RCU_USBD: USBD clock(HD,XD series available) - \arg RCU_USBFS: USBFS clock(CL series available) - \arg RCU_EXMC: EXMC clock - \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): TIMER clock - \arg RCU_WWDGT: WWDGT clock - \arg RCU_SPIx (x=0,1,2): SPI clock - \arg RCU_USARTx (x=0,1,2): USART clock - \arg RCU_UARTx (x=3,4): UART clock - \arg RCU_I2Cx (x=0,1): I2C clock - \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock - \arg RCU_PMU: PMU clock - \arg RCU_DAC: DAC clock - \arg RCU_RTC: RTC clock - \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock - \arg RCU_SDIO: SDIO clock(not available for CL series) - \arg RCU_CTC: CTC clock - \arg RCU_BKPI: BKP interface clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_enable(rcu_periph_enum periph) -{ - RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief disable the peripherals clock - \param[in] periph: RCU peripherals, refer to rcu_periph_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock - \arg RCU_AF: alternate function clock - \arg RCU_CRC: CRC clock - \arg RCU_DMAx (x=0,1): DMA clock - \arg RCU_ENET: ENET clock(CL series available) - \arg RCU_ENETTX: ENETTX clock(CL series available) - \arg RCU_ENETRX: ENETRX clock(CL series available) - \arg RCU_USBD: USBD clock(HD,XD series available) - \arg RCU_USBFS: USBFS clock(CL series available) - \arg RCU_EXMC: EXMC clock - \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): TIMER clock - \arg RCU_WWDGT: WWDGT clock - \arg RCU_SPIx (x=0,1,2): SPI clock - \arg RCU_USARTx (x=0,1,2): USART clock - \arg RCU_UARTx (x=3,4): UART clock - \arg RCU_I2Cx (x=0,1): I2C clock - \arg RCU_CANx (x=0,1,CAN1 is only available for CL series): CAN clock - \arg RCU_PMU: PMU clock - \arg RCU_DAC: DAC clock - \arg RCU_RTC: RTC clock - \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock - \arg RCU_SDIO: SDIO clock(not available for CL series) - \arg RCU_CTC: CTC clock - \arg RCU_BKPI: BKP interface clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_disable(rcu_periph_enum periph) -{ - RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief enable the peripherals clock when sleep mode - \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum - only one parameter can be selected which is shown as below: - \arg RCU_FMC_SLP: FMC clock - \arg RCU_SRAM_SLP: SRAM clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph) -{ - RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief disable the peripherals clock when sleep mode - \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum - only one parameter can be selected which is shown as below: - \arg RCU_FMC_SLP: FMC clock - \arg RCU_SRAM_SLP: SRAM clock - \param[out] none - \retval none -*/ -void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) -{ - RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph)); -} - -/*! - \brief reset the peripherals - \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports - \arg RCU_AFRST : reset alternate function clock - \arg RCU_ENETRST: reset ENET(CL series available) - \arg RCU_USBDRST: reset USBD(HD,XD series available) - \arg RCU_USBFSRST: reset USBFS(CL series available) - \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): reset TIMER - \arg RCU_WWDGTRST: reset WWDGT - \arg RCU_SPIxRST (x=0,1,2): reset SPI - \arg RCU_USARTxRST (x=0,1,2): reset USART - \arg RCU_UARTxRST (x=3,4): reset UART - \arg RCU_I2CxRST (x=0,1): reset I2C - \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN - \arg RCU_PMURST: reset PMU - \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC - \arg RCU_CTCRST: reset CTC - \arg RCU_BKPIRST: reset BKPI - \param[out] none - \retval none -*/ -void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) -{ - RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset)); -} - -/*! - \brief disable reset the peripheral - \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum - only one parameter can be selected which is shown as below: - \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports - \arg RCU_AFRST : reset alternate function clock - \arg RCU_ENETRST: reset ENET(CL series available) - \arg RCU_USBDRST: reset USBD(HD,XD series available) - \arg RCU_USBFSRST: reset USBFS(CL series available) - \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for HD series): reset TIMER - \arg RCU_WWDGTRST: reset WWDGT - \arg RCU_SPIxRST (x=0,1,2): reset SPI - \arg RCU_USARTxRST (x=0,1,2): reset USART - \arg RCU_UARTxRST (x=3,4): reset UART - \arg RCU_I2CxRST (x=0,1): reset I2C - \arg RCU_CANxRST (x=0,1,CAN1 is only available for CL series): reset CAN - \arg RCU_PMURST: reset PMU - \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC - \arg RCU_CTCRST: reset CTC - \arg RCU_BKPIRST: reset BKPI - \param[out] none - \retval none -*/ -void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset) -{ - RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset)); -} - -/*! - \brief reset the BKP domain - \param[in] none - \param[out] none - \retval none -*/ -void rcu_bkp_reset_enable(void) -{ - RCU_BDCTL |= RCU_BDCTL_BKPRST; -} - -/*! - \brief disable the BKP domain reset - \param[in] none - \param[out] none - \retval none -*/ -void rcu_bkp_reset_disable(void) -{ - RCU_BDCTL &= ~RCU_BDCTL_BKPRST; -} - -/*! - \brief configure the system clock source - \param[in] ck_sys: system clock source select - only one parameter can be selected which is shown as below: - \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source - \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source - \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source - \param[out] none - \retval none -*/ -void rcu_system_clock_source_config(uint32_t ck_sys) -{ - uint32_t reg; - - reg = RCU_CFG0; - /* reset the SCS bits and set according to ck_sys */ - reg &= ~RCU_CFG0_SCS; - RCU_CFG0 = (reg | ck_sys); -} - -/*! - \brief get the system clock source - \param[in] none - \param[out] none - \retval which clock is selected as CK_SYS source - \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source - \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source - \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source -*/ -uint32_t rcu_system_clock_source_get(void) -{ - return (RCU_CFG0 & RCU_CFG0_SCSS); -} - -/*! - \brief configure the AHB clock prescaler selection - \param[in] ck_ahb: AHB clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 - \param[out] none - \retval none -*/ -void rcu_ahb_clock_config(uint32_t ck_ahb) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the AHBPSC bits and set according to ck_ahb */ - reg &= ~RCU_CFG0_AHBPSC; - RCU_CFG0 = (reg | ck_ahb); -} - -/*! - \brief configure the APB1 clock prescaler selection - \param[in] ck_apb1: APB1 clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1 - \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1 - \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1 - \param[out] none - \retval none -*/ -void rcu_apb1_clock_config(uint32_t ck_apb1) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the APB1PSC and set according to ck_apb1 */ - reg &= ~RCU_CFG0_APB1PSC; - RCU_CFG0 = (reg | ck_apb1); -} - -/*! - \brief configure the APB2 clock prescaler selection - \param[in] ck_apb2: APB2 clock prescaler selection - only one parameter can be selected which is shown as below: - \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2 - \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2 - \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2 - \param[out] none - \retval none -*/ -void rcu_apb2_clock_config(uint32_t ck_apb2) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the APB2PSC and set according to ck_apb2 */ - reg &= ~RCU_CFG0_APB2PSC; - RCU_CFG0 = (reg | ck_apb2); -} - -/*! - \brief configure the CK_OUT0 clock source - \param[in] ckout0_src: CK_OUT0 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_CKOUT0SRC_NONE: no clock selected - \arg RCU_CKOUT0SRC_CKSYS: system clock selected - \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected - \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected - \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected - \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected - \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected - \arg RCU_CKOUT0SRC_EXT1: EXT1 selected - \arg RCU_CKOUT0SRC_CKPLL2: PLL selected - \param[out] none - \retval none -*/ -void rcu_ckout0_config(uint32_t ckout0_src) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* reset the CKOUT0SRC, set according to ckout0_src */ - reg &= ~RCU_CFG0_CKOUT0SEL; - RCU_CFG0 = (reg | ckout0_src); -} - -/*! - \brief configure the main PLL clock - \param[in] pll_src: PLL clock source selection - \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL - \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL - \param[in] pll_mul: PLL clock multiplication factor - \arg RCU_PLL_MULx (XD series x = 2..63, CL series x = 2..14, 16..63, 6.5) - \param[out] none - \retval none -*/ -void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) -{ - uint32_t reg = 0U; - - reg = RCU_CFG0; - - /* PLL clock source and multiplication factor configuration */ - reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5); - reg |= (pll_src | pll_mul); - - RCU_CFG0 = reg; -} - -/*! - \brief configure the PLL clock source preselection - \param[in] pll_presel: PLL clock source preselection - \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PLL source clock - \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock - \param[out] none - \retval none -*/ -void rcu_pllpresel_config(uint32_t pll_presel) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - - /* PLL clock source preselection */ - reg &= ~RCU_CFG1_PLLPRESEL; - reg |= pll_presel; - - RCU_CFG1 = reg; -} - -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) -/*! - \brief configure the PREDV0 division factor - \param[in] predv0_div: PREDV0 division factor - \arg RCU_PREDV0_DIVx, x = 1,2 - \param[out] none - \retval none -*/ -void rcu_predv0_config(uint32_t predv0_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG0; - /* reset PREDV0 bit */ - reg &= ~RCU_CFG0_PREDV0; - if (RCU_PREDV0_DIV2 == predv0_div) { - /* set the PREDV0 bit */ - reg |= RCU_CFG0_PREDV0; - } - - RCU_CFG0 = reg; -} -#elif defined(GD32F10X_CL) -/*! - \brief configure the PREDV0 division factor and clock source - \param[in] predv0_source: PREDV0 input clock source selection - \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock - \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock - \param[in] predv0_div: PREDV0 division factor - \arg RCU_PREDV0_DIVx, x = 1..16 - \param[out] none - \retval none -*/ -void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - /* reset PREDV0SEL and PREDV0 bits */ - reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); - /* set the PREDV0SEL and PREDV0 division factor */ - reg |= (predv0_source | predv0_div); - - RCU_CFG1 = reg; -} - -/*! - \brief configure the PREDV1 division factor - \param[in] predv1_div: PREDV1 division factor - \arg RCU_PREDV1_DIVx, x = 1..16 - \param[out] none - \retval none -*/ -void rcu_predv1_config(uint32_t predv1_div) -{ - uint32_t reg = 0U; - - reg = RCU_CFG1; - /* reset the PREDV1 bits */ - reg &= ~RCU_CFG1_PREDV1; - /* set the PREDV1 division factor */ - reg |= predv1_div; - - RCU_CFG1 = reg; -} - -/*! - \brief configure the PLL1 clock - \param[in] pll_mul: PLL clock multiplication factor - \arg RCU_PLL1_MULx (x = 8..16, 20) - \param[out] none - \retval none -*/ -void rcu_pll1_config(uint32_t pll_mul) -{ - RCU_CFG1 &= ~RCU_CFG1_PLL1MF; - RCU_CFG1 |= pll_mul; -} - -/*! - \brief configure the PLL2 clock - \param[in] pll_mul: PLL clock multiplication factor - \arg RCU_PLL2_MULx (x = 8..16, 18..32, 40) - \param[out] none - \retval none -*/ -void rcu_pll2_config(uint32_t pll_mul) -{ - RCU_CFG1 &= ~RCU_CFG1_PLL2MF; - RCU_CFG1 |= pll_mul; -} -#endif /* GD32F10X_HD and GD32F10X_XD */ - -/*! - \brief configure the ADC prescaler factor - \param[in] adc_psc: ADC prescaler factor - \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2 - \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4 - \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6 - \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8 - \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12 - \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16 - \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB/5 - \arg RCU_CKADC_CKAHB_DIV6: ADC prescaler select CK_AHB/6 - \arg RCU_CKADC_CKAHB_DIV10: ADC prescaler select CK_AHB/10 - \arg RCU_CKADC_CKAHB_DIV20: ADC prescaler select CK_AHB/20 - \param[out] none - \retval none -*/ -void rcu_adc_clock_config(uint32_t adc_psc) -{ - uint32_t reg0, reg1; - - /* reset the ADCPSC bits */ - reg0 = RCU_CFG0; - reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); - reg1 = RCU_CFG1; - reg1 &= ~RCU_CFG1_ADCPSC_3; - - /* set the ADC prescaler factor */ - switch (adc_psc) { - case RCU_CKADC_CKAPB2_DIV2: - case RCU_CKADC_CKAPB2_DIV4: - case RCU_CKADC_CKAPB2_DIV6: - case RCU_CKADC_CKAPB2_DIV8: - reg0 |= (adc_psc << 14); - break; - - case RCU_CKADC_CKAPB2_DIV12: - case RCU_CKADC_CKAPB2_DIV16: - adc_psc &= ~BIT(2); - reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); - break; - - case RCU_CKADC_CKAHB_DIV5: - case RCU_CKADC_CKAHB_DIV6: - case RCU_CKADC_CKAHB_DIV10: - case RCU_CKADC_CKAHB_DIV20: - adc_psc &= ~BITS(2, 3); - reg0 |= (adc_psc << 14); - reg1 |= RCU_CFG1_ADCPSC_3; - break; - - default: - break; - } - - /* set the register */ - RCU_CFG0 = reg0; - RCU_CFG1 = reg1; -} - -/*! - \brief configure the USBD/USBFS prescaler factor - \param[in] adc_div: USB prescaler factor - \arg RCU_CKUSB_CKPLL_DIV1_5: USBD/USBFS prescaler select CK_PLL/1.5 - \arg RCU_CKUSB_CKPLL_DIV1: USBD/USBFS prescaler select CK_PLL/1 - \arg RCU_CKUSB_CKPLL_DIV2_5: USBD/USBFS prescaler select CK_PLL/2.5 - \arg RCU_CKUSB_CKPLL_DIV2: USBD/USBFS prescaler select CK_PLL/2 - \arg RCU_CKUSB_CKPLL_DIV3: USBD/USBFS prescaler select CK_PLL/3 - \arg RCU_CKUSB_CKPLL_DIV3_5: USBD/USBFS prescaler select CK_PLL/3.5 - \arg RCU_CKUSB_CKPLL_DIV4: USBD/USBFS prescaler select CK_PLL/4 - \param[out] none - \retval none -*/ -void rcu_usb_clock_config(uint32_t usb_psc) -{ - uint32_t reg; - - reg = RCU_CFG0; - - /* configure the USBD/USBFS prescaler factor */ -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - reg &= ~RCU_CFG0_USBDPSC; -#elif defined(GD32F10X_CL) - reg &= ~RCU_CFG0_USBFSPSC; -#endif /* GD32F10X_HD and GD32F10X_XD */ - - RCU_CFG0 = (reg | usb_psc); -} - -/*! - \brief configure the RTC clock source selection - \param[in] rtc_clock_source: RTC clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_RTCSRC_NONE: no clock selected - \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock - \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock - \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock - \param[out] none - \retval none -*/ -void rcu_rtc_clock_config(uint32_t rtc_clock_source) -{ - uint32_t reg; - - reg = RCU_BDCTL; - /* reset the RTCSRC bits and set according to rtc_clock_source */ - reg &= ~RCU_BDCTL_RTCSRC; - RCU_BDCTL = (reg | rtc_clock_source); -} - -#ifdef GD32F10X_CL -/*! - \brief configure the I2S1 clock source selection - \param[in] i2s_clock_source: I2S1 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock - \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock - \param[out] none - \retval none -*/ -void rcu_i2s1_clock_config(uint32_t i2s_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S1SEL bit and set according to i2s_clock_source */ - reg &= ~RCU_CFG1_I2S1SEL; - RCU_CFG1 = (reg | i2s_clock_source); -} - -/*! - \brief configure the I2S2 clock source selection - \param[in] i2s_clock_source: I2S2 clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock - \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock - \param[out] none - \retval none -*/ -void rcu_i2s2_clock_config(uint32_t i2s_clock_source) -{ - uint32_t reg; - - reg = RCU_CFG1; - /* reset the I2S2SEL bit and set according to i2s_clock_source */ - reg &= ~RCU_CFG1_I2S2SEL; - RCU_CFG1 = (reg | i2s_clock_source); -} -#endif /* GD32F10X_CL */ - -/*! - \brief configure the CK48M clock source selection - \param[in] ck48m_clock_source: CK48M clock source selection - only one parameter can be selected which is shown as below: - \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock - \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock - \param[out] none - \retval none -*/ -void rcu_ck48m_clock_config(uint32_t ck48m_clock_source) -{ - uint32_t reg; - - reg = RCU_ADDCTL; - /* reset the CK48MSEL bit and set according to ck48m_clock_source */ - reg &= ~RCU_ADDCTL_CK48MSEL; - RCU_ADDCTL = (reg | ck48m_clock_source); -} - -/*! - \brief get the clock stabilization and periphral reset flags - \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag - \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag - \arg RCU_FLAG_PLLSTB: PLL stabilization flag - \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only) - \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only) - \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag - \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag - \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag - \arg RCU_FLAG_EPRST: external PIN reset flag - \arg RCU_FLAG_PORRST: power reset flag - \arg RCU_FLAG_SWRST: software reset flag - \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag - \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag - \arg RCU_FLAG_LPRST: low-power reset flag - \param[out] none - \retval none -*/ -FlagStatus rcu_flag_get(rcu_flag_enum flag) -{ - /* get the rcu flag */ - if (RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))) { - return SET; - } else { - return RESET; - } -} - -/*! - \brief clear all the reset flag - \param[in] none - \param[out] none - \retval none -*/ -void rcu_all_reset_flag_clear(void) -{ - RCU_RSTSCK |= RCU_RSTSCK_RSTFC; -} - -/*! - \brief get the clock stabilization interrupt and ckm flags - \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag - \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag - \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag - \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only) - \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only) - \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag - \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) -{ - /* get the rcu interrupt flag */ - if (RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))) { - return SET; - } else { - return RESET; - } -} - -/*! - \brief clear the interrupt flags - \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear - \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear - \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only) - \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only) - \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear - \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear - \param[out] none - \retval none -*/ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) -{ - RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); -} - -/*! - \brief enable the stabilization interrupt - \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum - Only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) - \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_enable(rcu_int_enum stab_int) -{ - RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); -} - -/*! - \brief disable the stabilization interrupt - \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only) - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only) - \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_disable(rcu_int_enum stab_int) -{ - RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); -} - -/*! - \brief configure the LXTAL drive capability - \param[in] lxtal_dricap: drive capability of LXTAL - only one parameter can be selected which is shown as below: - \arg RCU_LXTAL_LOWDRI: lower driving capability - \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability - \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability - \arg RCU_LXTAL_HIGHDRI: higher driving capability - \param[out] none - \retval none -*/ -void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) -{ - uint32_t reg; - - reg = RCU_BDCTL; - - /* reset the LXTALDRI bits and set according to lxtal_dricap */ - reg &= ~RCU_BDCTL_LXTALDRI; - RCU_BDCTL = (reg | lxtal_dricap); -} - -/*! - \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL series only) - \arg RCU_PLL2_CK: phase locked loop 2(CL series only) - \param[out] none - \retval ErrStatus: SUCCESS or ERROR -*/ -ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) -{ - uint32_t stb_cnt = 0U; - ErrStatus reval = ERROR; - FlagStatus osci_stat = RESET; - - switch (osci) { - /* wait HXTAL stable */ - case RCU_HXTAL: - while ((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)) { - reval = SUCCESS; - } - break; - - /* wait LXTAL stable */ - case RCU_LXTAL: - while ((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)) { - reval = SUCCESS; - } - break; - - /* wait IRC8M stable */ - case RCU_IRC8M: - while ((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)) { - reval = SUCCESS; - } - break; - - /* wait IRC48M stable */ - case RCU_IRC48M: - while ((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)) { - reval = SUCCESS; - } - break; - - /* wait IRC40K stable */ - case RCU_IRC40K: - while ((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)) { - reval = SUCCESS; - } - break; - - /* wait PLL stable */ - case RCU_PLL_CK: - while ((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_PLLSTB)) { - reval = SUCCESS; - } - break; - -#ifdef GD32F10X_CL - /* wait PLL1 stable */ - case RCU_PLL1_CK: - while ((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_PLL1STB)) { - reval = SUCCESS; - } - break; - /* wait PLL2 stable */ - case RCU_PLL2_CK: - while ((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { - osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); - stb_cnt++; - } - - /* check whether flag is set or not */ - if (RESET != rcu_flag_get(RCU_FLAG_PLL2STB)) { - reval = SUCCESS; - } - break; -#endif /* GD32F10X_CL */ - - default: - break; - } - - /* return value */ - return reval; -} - -/*! - \brief turn on the oscillator - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL series only) - \arg RCU_PLL2_CK: phase locked loop 2(CL series only) - \param[out] none - \retval none -*/ -void rcu_osci_on(rcu_osci_type_enum osci) -{ - RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci)); -} - -/*! - \brief turn off the oscillator - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M) - \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M) - \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K) - \arg RCU_PLL_CK: phase locked loop(PLL) - \arg RCU_PLL1_CK: phase locked loop 1(CL series only) - \arg RCU_PLL2_CK: phase locked loop 2(CL series only) - \param[out] none - \retval none -*/ -void rcu_osci_off(rcu_osci_type_enum osci) -{ - RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci)); -} - -/*! - \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \param[out] none - \retval none -*/ -void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) -{ - uint32_t reg; - - switch (osci) { - /* enable HXTAL to bypass mode */ - case RCU_HXTAL: - reg = RCU_CTL; - RCU_CTL &= ~RCU_CTL_HXTALEN; - RCU_CTL = (reg | RCU_CTL_HXTALBPS); - break; - /* enable LXTAL to bypass mode */ - case RCU_LXTAL: - reg = RCU_BDCTL; - RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; - RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS); - break; - case RCU_IRC8M: - case RCU_IRC48M: - case RCU_IRC40K: - case RCU_PLL_CK: -#ifdef GD32F10X_CL - case RCU_PLL1_CK: - case RCU_PLL2_CK: -#endif /* GD32F10X_CL */ - break; - default: - break; - } -} - -/*! - \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it - \param[in] osci: oscillator types, refer to rcu_osci_type_enum - only one parameter can be selected which is shown as below: - \arg RCU_HXTAL: high speed crystal oscillator(HXTAL) - \arg RCU_LXTAL: low speed crystal oscillator(LXTAL) - \param[out] none - \retval none -*/ -void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) -{ - uint32_t reg; - - switch (osci) { - /* disable HXTAL to bypass mode */ - case RCU_HXTAL: - reg = RCU_CTL; - RCU_CTL &= ~RCU_CTL_HXTALEN; - RCU_CTL = (reg & ~RCU_CTL_HXTALBPS); - break; - /* disable LXTAL to bypass mode */ - case RCU_LXTAL: - reg = RCU_BDCTL; - RCU_BDCTL &= ~RCU_BDCTL_LXTALEN; - RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS); - break; - case RCU_IRC8M: - case RCU_IRC48M: - case RCU_IRC40K: - case RCU_PLL_CK: -#ifdef GD32F10X_CL - case RCU_PLL1_CK: - case RCU_PLL2_CK: -#endif /* GD32F10X_CL */ - break; - default: - break; - } -} - -/*! - \brief enable the HXTAL clock monitor - \param[in] none - \param[out] none - \retval none -*/ - -void rcu_hxtal_clock_monitor_enable(void) -{ - RCU_CTL |= RCU_CTL_CKMEN; -} - -/*! - \brief disable the HXTAL clock monitor - \param[in] none - \param[out] none - \retval none -*/ -void rcu_hxtal_clock_monitor_disable(void) -{ - RCU_CTL &= ~RCU_CTL_CKMEN; -} - -/*! - \brief set the IRC8M adjust value - \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F - \param[out] none - \retval none -*/ -void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval) -{ - uint32_t reg; - - reg = RCU_CTL; - /* reset the IRC8MADJ bits and set according to irc8m_adjval */ - reg &= ~RCU_CTL_IRC8MADJ; - RCU_CTL = (reg | ((irc8m_adjval & 0x1FU) << 3)); -} - -/*! - \brief deep-sleep mode voltage select - \param[in] dsvol: deep sleep mode voltage - only one parameter can be selected which is shown as below: - \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V - \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V - \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V - \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V - \param[out] none - \retval none -*/ -void rcu_deepsleep_voltage_set(uint32_t dsvol) -{ - dsvol &= RCU_DSV_DSLPVS; - RCU_DSV = dsvol; -} - -/*! - \brief get the system clock, bus and peripheral clock frequency - \param[in] clock: the clock frequency which to get - only one parameter can be selected which is shown as below: - \arg CK_SYS: system clock frequency - \arg CK_AHB: AHB clock frequency - \arg CK_APB1: APB1 clock frequency - \arg CK_APB2: APB2 clock frequency - \param[out] none - \retval clock frequency of system, AHB, APB1, APB2 -*/ -uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) -{ - uint32_t sws, ck_freq = 0U; - uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; - uint32_t pllsel, pllpresel, predv0sel, pllmf, ck_src, idx, clk_exp; -#ifdef GD32F10X_CL - uint32_t predv0, predv1, pll1mf; -#endif /* GD32F10X_CL */ - - /* exponent of AHB, APB1 and APB2 clock divider */ - uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; - - sws = GET_BITS(RCU_CFG0, 2, 3); - switch (sws) { - /* IRC8M is selected as CK_SYS */ - case SEL_IRC8M: - cksys_freq = IRC8M_VALUE; - break; - /* HXTAL is selected as CK_SYS */ - case SEL_HXTAL: - cksys_freq = HXTAL_VALUE; - break; - /* PLL is selected as CK_SYS */ - case SEL_PLL: - /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */ - pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - - if (RCU_PLLSRC_HXTAL_IRC48M == pllsel) { - /* PLL clock source is HXTAL or IRC48M */ - pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL); - - if (RCU_PLLPRESRC_HXTAL == pllpresel) { - /* PLL clock source is HXTAL */ - ck_src = HXTAL_VALUE; - } else { - /* PLL clock source is IRC48 */ - ck_src = IRC48M_VALUE; - } - -#if (defined(GD32F10X_HD) || defined(GD32F10X_XD)) - predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0); - /* PREDV0 input source clock divided by 2 */ - if (RCU_CFG0_PREDV0 == predv0sel) { - ck_src = HXTAL_VALUE / 2U; - } -#elif defined(GD32F10X_CL) - predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); - /* source clock use PLL1 */ - if (RCU_PREDV0SRC_CKPLL1 == predv0sel) { - predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; - pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; - if (17U == pll1mf) { - pll1mf = 20U; - } - ck_src = (ck_src / predv1) * pll1mf; - } - predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; - ck_src /= predv0; -#endif /* GD32F10X_HD and GD32F10X_XD */ - } else { - /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE / 2U; - } - - /* PLL multiplication factor */ - pllmf = GET_BITS(RCU_CFG0, 18, 21); - if ((RCU_CFG0 & RCU_CFG0_PLLMF_4)) { - pllmf |= 0x10U; - } - if ((RCU_CFG0 & RCU_CFG0_PLLMF_5)) { - pllmf |= 0x20U; - } - if (pllmf < 15U) { - pllmf += 2U; - } else if ((pllmf >= 15U) && (pllmf <= 62U)) { - pllmf += 1U; - } else { - pllmf = 63U; - } - cksys_freq = ck_src * pllmf; -#ifdef GD32F10X_CL - if (15U == pllmf) { - cksys_freq = ck_src * 6U + ck_src / 2U; - } -#endif /* GD32F10X_CL */ - - break; - /* IRC8M is selected as CK_SYS */ - default: - cksys_freq = IRC8M_VALUE; - break; - } - - /* calculate AHB clock frequency */ - idx = GET_BITS(RCU_CFG0, 4, 7); - clk_exp = ahb_exp[idx]; - ahb_freq = cksys_freq >> clk_exp; - - /* calculate APB1 clock frequency */ - idx = GET_BITS(RCU_CFG0, 8, 10); - clk_exp = apb1_exp[idx]; - apb1_freq = ahb_freq >> clk_exp; - - /* calculate APB2 clock frequency */ - idx = GET_BITS(RCU_CFG0, 11, 13); - clk_exp = apb2_exp[idx]; - apb2_freq = ahb_freq >> clk_exp; - - /* return the clocks frequency */ - switch (clock) { - case CK_SYS: - ck_freq = cksys_freq; - break; - case CK_AHB: - ck_freq = ahb_freq; - break; - case CK_APB1: - ck_freq = apb1_freq; - break; - case CK_APB2: - ck_freq = apb2_freq; - break; - default: - break; - } - return ck_freq; -} diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rtc.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rtc.c deleted file mode 100644 index 5080fc07f7..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_rtc.c +++ /dev/null @@ -1,263 +0,0 @@ -/** - ****************************************************************************** - * @brief RTC functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_rtc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup RTC - * @brief RTC driver modules - * @{ - */ - -/** @defgroup RTC_Private_Defines - * @{ - */ - -/* RTC LSB Mask */ -#define RTC_LSB_MASK ((uint32_t)0x0000FFFF) - -/* RTC Prescaler MSB Mask */ -#define PRL1_MSB_MASK ((uint32_t)0x000F0000) - -/** - * @} - */ - -/** @defgroup RTC_Private_Functions - * @{ - */ - -/** - * @brief Enable or disable the specified RTC interrupts. - * @param RTC_INT: specify the RTC interrupt sources - * This parameter can be any combination of the following value: - * @arg RTC_INT_OVI: Overflow event interrupt - * @arg RTC_INT_AI: Alarm event interrupt - * @arg RTC_INT_SI: Tamper event interrupt - * @param NewValue: RTC interrupt state to configure - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void RTC_INT_Enable(uint16_t RTC_INT, TypeState NewValue) -{ - if (NewValue == ENABLE) { - /* Enable the interrupts in RTC_CTLR register */ - RTC->CTLR1 |= RTC_INT; - } else { - /* Disable the interrupts in RTC_CTLR register */ - RTC->CTLR1 &= ~((uint16_t)RTC_INT); - } -} - -/** - * @brief Enter the RTC configuration mode. - * @param None - * @retval None - */ -void RTC_EnterConfigMode(void) -{ - /* Enter in the Configuration Mode by set the CMF flag */ - RTC->CTLR2 |= RTC_CTLR2_CMF; -} - -/** - * @brief Exit from the RTC configuration mode. - * @param None - * @retval None - */ -void RTC_ExitConfigMode(void) -{ - /* Exit from the Configuration Mode by reset the CMF flag */ - RTC->CTLR2 &= ~((uint16_t)RTC_CTLR2_CMF); -} - -/** - * @brief Get the RTC counter value. - * @param None - * @retval The value of RTC counter. - */ -uint32_t RTC_GetCounter(void) -{ - uint16_t temp = 0; - temp = RTC->CNT2; - return (((uint32_t)RTC->CNT1 << 16) | temp) ; -} - -/** - * @brief Set the RTC counter value. - * @param CounterValue: New value of the RTC counter. - * @retval None - */ -void RTC_SetCounter(uint32_t CounterValue) -{ - RTC_EnterConfigMode(); - /* Set the RTC counter MSB word */ - RTC->CNT1 = CounterValue >> 16; - /* Set the RTC counter LSB word */ - RTC->CNT2 = (CounterValue & RTC_LSB_MASK); - RTC_ExitConfigMode(); -} - -/** - * @brief Set the RTC prescaler value. - * @param PrescalerValue: New value of the RTC prescaler. - * @retval None - */ -void RTC_SetPrescaler(uint32_t PrescalerValue) -{ - RTC_EnterConfigMode(); - /* Set the RTC prescaler MSB word */ - RTC->PLR1 = (PrescalerValue & PRL1_MSB_MASK) >> 16; - /* Set the RTC prescaler LSB word */ - RTC->PLR2 = (PrescalerValue & RTC_LSB_MASK); - RTC_ExitConfigMode(); -} - -/** - * @brief Set the RTC alarm value. - * @param AlarmValue: New value of the RTC alarm. - * @retval None - */ -void RTC_SetAlarm(uint32_t AlarmValue) -{ - RTC_EnterConfigMode(); - /* Set the alarm MSB word */ - RTC->ALRMR1 = AlarmValue >> 16; - /* Set the alarm LSB word */ - RTC->ALRMR2 = (AlarmValue & RTC_LSB_MASK); - RTC_ExitConfigMode(); -} - -/** - * @brief Get the RTC divider value. - * @param None - * @retval The value of RTC Divider. - */ -uint32_t RTC_GetDivider(void) -{ - uint32_t temp = 0x00; - temp = ((uint32_t)RTC->PREDIV1 & (uint32_t)0x000F) << 16; - temp |= RTC->PREDIV2; - return temp; -} - -/** - * @brief Wait until last write operation on RTC registers has finished. - * @note This function must be called before any write to RTC registers. - * @param None - * @retval None - */ -void RTC_WaitLWOFF(void) -{ - /* Loop until RTOFF flag is set */ - while ((RTC->CTLR2 & RTC_FLAG_LWOFF) == (uint16_t)RESET) { - } -} - -/** - * @brief Wait until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL) - * are synchronized with RTC APB clock. - * @note This function must be called before any read operation after an APB reset - * or an APB clock stop. - * @param None - * @retval None - */ -void RTC_WaitRSF(void) -{ - /* Clear RSF flag */ - RTC->CTLR2 &= ~((uint16_t)RTC_FLAG_RSF); - /* Loop until RSF flag is set */ - while ((RTC->CTLR2 & RTC_FLAG_RSF) == (uint16_t)RESET) { - } -} - -/** - * @brief Check whether the specified RTC flag is set or not. - * @param RTC_FLAG: specifie the flag to check. - * This parameter can be one the following values: - * @arg RTC_FLAG_LWOFF: RTC Operation Off flag - * @arg RTC_FLAG_RSF: Registers Synchronized flag - * @arg RTC_FLAG_OVF: Overflow flag - * @arg RTC_FLAG_AF: Alarm flag - * @arg RTC_FLAG_SF: Second flag - * @retval The new bitstate of RTC_FLAG (SET or RESET). - */ -TypeState RTC_GetBitState(uint16_t RTC_FLAG) -{ - if ((RTC->CTLR2 & RTC_FLAG) != (uint16_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the RTC's pending flags. - * @param RTC_FLAG: specifie the flag to clear. - * This parameter can be any combination of the following values: - * @arg RTC_FLAG_RSF: Registers Synchronized flag. This flag is cleared only after - * an APB reset or an APB Clock stop. - * @arg RTC_FLAG_OVF: Overflow flag - * @arg RTC_FLAG_AF: Alarm flag - * @arg RTC_FLAG_SF: Second flag - * @retval None - */ -void RTC_ClearBitState(uint16_t RTC_flag) -{ - /* Clear the corresponding RTC flag */ - RTC->CTLR2 &= ~((uint16_t)RTC_flag); -} - -/** - * @brief Check whether the specified RTC interrupt has occurred or not. - * @param RTC_INT: specifie the RTC interrupts sources to check. - * This parameter can be one of the following values: - * @arg RTC_INT_OVI: Overflow event interrupt - * @arg RTC_INT_AI: Alarm event interrupt - * @arg RTC_INT_SI: Tamper event interrupt - * @retval The new state of the RTC_IT (SET or RESET). - */ -TypeState RTC_GetIntBitState(uint16_t RTC_INT) -{ - - if (((RTC->CTLR1 & RTC_INT) != (uint16_t)RESET) && ((RTC->CTLR2 & RTC_INT) != (uint16_t)RESET)) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the RTC's interrupt bit. - * @param RTC_INT: specifie the interrupt bit to clear. - * This parameter can be any combination of the following values: - * @arg RTC_INT_OVI: Overflow event interrupt - * @arg RTC_INT_AI: Alarm event interrupt - * @arg RTC_INT_SI: Tamper event interrupt - * @retval None - */ -void RTC_ClearIntBitState(uint16_t RTC_INT) -{ - /* Clear the RTC's interrupt bitstate */ - RTC->CTLR2 &= ~((uint16_t)RTC_INT); -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_sdio.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_sdio.c deleted file mode 100644 index 110fe8f410..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_sdio.c +++ /dev/null @@ -1,636 +0,0 @@ -/** - ****************************************************************************** - * @brief SDIO functions of the firmware library. - ****************************************************************************** - */ -#ifdef GD32F10X_HD -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_sdio.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup SDIO - * @brief SDIO driver modules - * @{ - */ - -/** @defgroup SDIO_Private_Defines - * @{ - */ - -/* SDIO registers bit mask */ -/* CLKCTLR register mask */ -#define CLKCTLR_CLEAR_MASK ((uint32_t)0xFFFF8100) -/* POWER_PWRSTATE mask */ -#define POWER_PWRSTATE_MASK ((uint32_t)0xFFFFFFFC) -/* DTCTLR register mask */ -#define DTCTLR_CLEAR_MASK ((uint32_t)0xFFFFFF08) -/* CMD register mask */ -#define CMD_CLEAR_MASK ((uint32_t)0xFFFFF800) - -/* SDIO RESP Registers Address */ -#define SDIO_RESP_ADDR ((uint32_t)(SDIO_BASE + 0x14)) - -/** - * @} - */ - -/** @defgroup SDIO_Private_Functions - * @{ - */ - -/** - * @brief Deinitialize the SDIO . - * @param None - * @retval None - */ -void SDIO_DeInit(void) -{ - SDIO->POWER = 0x00000000; - SDIO->CLKCTLR = 0x00000000; - SDIO->PARA = 0x00000000; - SDIO->CMD = 0x00000000; - SDIO->DTTR = 0x00000000; - SDIO->DTLEN = 0x00000000; - SDIO->DTCTLR = 0x00000000; - SDIO->ICR = 0x00C007FF; - SDIO->IER = 0x00000000; -} - -/** - * @brief Initialize the SDIO . - * @param SDIO_InitParaStruct : pointer to a SDIO_InitPara structure . - * @retval None - */ -void SDIO_Init(SDIO_InitPara *SDIO_InitParaStruct) -{ - uint32_t temp = 0; - - /* SDIO CLKCTLR Configuration */ - /* Get the SDIO CLKCTLR value */ - temp = SDIO->CLKCTLR; - - /* Clear CLKCTLR register */ - temp &= CLKCTLR_CLEAR_MASK; - - /* Configure the SDIO_ClockDiv value */ - /* Configure the SDIO_ClockPWRSave value */ - /* Configure the SDIO_ClockBypassState value */ - /* Configure the SDIO_BusMode value */ - /* Configure the SDIO_ClockEdge value */ - /* Configure the SDIO_HWFlowCtrlState value */ - temp |= (SDIO_InitParaStruct->SDIO_ClockDiv | SDIO_InitParaStruct->SDIO_ClockPWRSave | - SDIO_InitParaStruct->SDIO_ClockBypassState | SDIO_InitParaStruct->SDIO_BusMode | - SDIO_InitParaStruct->SDIO_ClockEdge | SDIO_InitParaStruct->SDIO_HWFlowCtrlState); - - /* Update the SDIO CLKCTLR */ - SDIO->CLKCTLR = temp; -} - -/** - * @brief Fill each SDIO_InitParaStruct Struct member with a default value. - * @param SDIO_InitParaStruct: pointer to an SDIO_InitPara structure. - * @retval None - */ -void SDIO_ParaInit(SDIO_InitPara *SDIO_InitParaStruct) -{ - /* Fill the default value */ - SDIO_InitParaStruct->SDIO_ClockDiv = 0x00; - SDIO_InitParaStruct->SDIO_ClockEdge = SDIO_CLOCKEDGE_RISING; - SDIO_InitParaStruct->SDIO_ClockBypassState = SDIO_CLOCKBYPASSSTATE_DISABLE; - SDIO_InitParaStruct->SDIO_ClockPWRSave = SDIO_CLOCKPWRSAVE_DISABLE; - SDIO_InitParaStruct->SDIO_BusMode = SDIO_BUSMODE_1B; - SDIO_InitParaStruct->SDIO_HWFlowCtrlState = SDIO_HWFLOWCTRLSTATE_DISABLE; -} - -/** - * @brief ENABLE or DISABLE the SDIO Clock. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_Clock_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - SDIO->CLKCTLR |= SDIO_CLKCTLR_CKEN; - } else { - SDIO->CLKCTLR &= (uint16_t)~(SDIO_CLKCTLR_CKEN); - } -} - -/** - * @brief Configure the power state of SDIO. - * @param SDIO_PwrState: new Power state for SDIO. - * This value will be : - * @arg SDIO_PWRSTATE_ON - * @arg SDIO_PWRSTATE_OFF - * @retval None - */ -void SDIO_SetPWRState(uint32_t SDIO_PwrState) -{ - /* Update the SDIO POWER */ - SDIO->POWER |= SDIO_PwrState; -} - -/** - * @brief Get the power state of SDIO. - * @param None - * @retval Power state for SDIO. - * This value will be : - * - 0x00: Power OFF - * - 0x02: Power UP - * - 0x03: Power ON - */ -uint32_t SDIO_GetPWRState(void) -{ - return (SDIO->POWER & (~POWER_PWRSTATE_MASK)); -} - -/** - * @brief Configure interrupts enables. - * @param SDIO_INT: The interrupts sources to configure. - * This value will be : - * @arg SDIO_INT_CCRCFAIL: Command response CRC failed interrupt - * @arg SDIO_INT_DTCRCFAIL: Data CRC failed interrupt - * @arg SDIO_INT_CMDTMOUT: Command response timeout interrupt - * @arg SDIO_INT_DTTMOUT: Data timeout interrupt - * @arg SDIO_INT_TXURE: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXORE: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDREND: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DTEND: Data end (data counter, SDIDTCNT, is zero) interrupt - * @arg SDIO_INT_STBITE: Start bit not detected on all data signals in wide bus mode interrupt - * @arg SDIO_INT_DTBLKEND: Data block sent/received (CRC check passed) interrupt - * @arg SDIO_INT_CMDRUN: Command transfer in progress interrupt - * @arg SDIO_INT_TXRUN: Data transmit in progress interrupt - * @arg SDIO_INT_RXRUN: Data receive in progress interrupt - * @arg SDIO_INT_TXFIFOHE: Transmit FIFO Half Empty interrupt - * @arg SDIO_INT_RXFIFOHF: Receive FIFO Half Full interrupt - * @arg SDIO_INT_TXFIFOF: Transmit FIFO full interrupt - * @arg SDIO_INT_RXFIFOF: Receive FIFO full interrupt - * @arg SDIO_INT_TXFIFOE: Transmit FIFO empty interrupt - * @arg SDIO_INT_RXFIFOE: Receive FIFO empty interrupt - * @arg SDIO_INT_TXDTVAL: Data valid in transmit FIFO interrupt - * @arg SDIO_INT_RXDTVAL: Data valid in receive FIFO interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_INTConfig(uint32_t SDIO_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the interrupt */ - SDIO->IER |= SDIO_INT; - } else { - /* Disable the interrupt */ - SDIO->IER &= ~SDIO_INT; - } -} - -/** - * @brief Enable or disable the DMA request for SDIO. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_DMA_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable DMA request */ - SDIO->DTCTLR |= SDIO_DTCTLR_DMAEN; - } else { - /* Disenable DMA request */ - SDIO->DTCTLR &= (uint16_t)~((uint16_t)SDIO_DTCTLR_DMAEN); - } -} - -/** - * @brief Initialize the SDIO Command. - * @param SDIO_CmdInitParaStruct : pointer to a SDIO_CmdInitPara structure. - * @retval None - */ -void SDIO_SendCMD(SDIO_CmdInitPara *SDIO_CmdInitParaStruct) -{ - uint32_t temp = 0; - - /* SDIO PARA Configuration */ - /* Configure the SDIO_CMDParameter value */ - SDIO->PARA = SDIO_CmdInitParaStruct->SDIO_CMDParameter; - - /* SDIO CMD Configuration */ - /* Get the SDIO CMD value */ - temp = SDIO->CMD; - /* Clear CMD register */ - temp &= CMD_CLEAR_MASK; - /* Configure the SDIO_CMDIndex value */ - /* Configure the SDIO_ResponseType value */ - /* Configure the SDIO_WaitINTState value */ - /* Configure the SDIO_CSMState value */ - temp |= (uint32_t)SDIO_CmdInitParaStruct->SDIO_CMDIndex | SDIO_CmdInitParaStruct->SDIO_ResponseType - | SDIO_CmdInitParaStruct->SDIO_WaitINTState | SDIO_CmdInitParaStruct->SDIO_CSMState; - - /* Update the SDIO CMD */ - SDIO->CMD = temp; -} - -/** - * @brief Fill SDIO_CmdInitStruct member with a default value. - * @param SDIO_CmdInitParaStruct: pointer to an SDIO_CmdInitPara structure. - * @retval None - */ -void SDIO_CMDParaInit(SDIO_CmdInitPara *SDIO_CmdInitParaStruct) -{ - /* Fill the default value */ - SDIO_CmdInitParaStruct->SDIO_CMDParameter = 0x00; - SDIO_CmdInitParaStruct->SDIO_CMDIndex = 0x00; - SDIO_CmdInitParaStruct->SDIO_ResponseType = SDIO_RESPONSETYPE_NO ; - SDIO_CmdInitParaStruct->SDIO_WaitINTState = SDIO_WAITINTSTATE_NO; - SDIO_CmdInitParaStruct->SDIO_CSMState = SDIO_CSMSTATE_DISABLE; -} - -/** - * @brief Return last response command index. - * @param None - * @retval Return last response command index. - */ -uint8_t SDIO_GetCMDResponse(void) -{ - return (uint8_t)(SDIO->RESPCMD); -} - -/** - * @brief Return the response for the last received command. - * @param SDIO_RESP: The SDIO response registers. - * This value will be : - * @arg SDIO_RESP1: Response Register 1 - * @arg SDIO_RESP2: Response Register 2 - * @arg SDIO_RESP3: Response Register 3 - * @arg SDIO_RESP4: Response Register 4 - * @retval The Corresponding response register value. - */ -uint32_t SDIO_GetResponse(uint32_t SDIO_RESP) -{ - __IO uint32_t temp = 0; - - temp = SDIO_RESP_ADDR + SDIO_RESP; - - return (*(__IO uint32_t *) temp); -} - -/** - * @brief Initialize the SDIO SDIO_DataInitParaStruct members. - * @param SDIO_DataInitParaStruct : pointer to a SDIO_DataInitPara structure. - * @retval None - */ -void SDIO_DataConfig(SDIO_DataInitPara *SDIO_DataInitParaStruct) -{ - uint32_t temp = 0; - - /* SDIO DTTR Configuration */ - /* Set the SDIO SDIO_DataTimeOut value */ - SDIO->DTTR = SDIO_DataInitParaStruct->SDIO_DataTimeOut; - - /* SDIO DTLEN Configuration */ - /* Set the SDIO SDIO_DataLength value */ - SDIO->DTLEN = SDIO_DataInitParaStruct->SDIO_DataLength; - - /* SDIO DTCTLR Configuration */ - /* Get the SDIO DTCTLR value */ - temp = SDIO->DTCTLR; - /* Clear DTCTLR register */ - temp &= DTCTLR_CLEAR_MASK; - /* Configure the SDIO_DataBlockSize value */ - /* Configure the SDIO_TransDirection value */ - /* Configure the SDIO_TransMode value */ - /* Configure the SDIO_DSMState value */ - temp |= (uint32_t)SDIO_DataInitParaStruct->SDIO_DataBlockSize | SDIO_DataInitParaStruct->SDIO_TransDirection - | SDIO_DataInitParaStruct->SDIO_TransMode | SDIO_DataInitParaStruct->SDIO_DSMState; - - /* Update the SDIO DTCTLR */ - SDIO->DTCTLR = temp; -} - -/** - * @brief Fill each SDIO_DataInitParaStruct member with a default value. - * @param SDIO_DataInitParaStruct: pointer to an SDIO_DataInitPara structure. - * @retval None - */ -void SDIO_DataParaInit(SDIO_DataInitPara *SDIO_DataInitParaStruct) -{ - /* Fill the default value */ - SDIO_DataInitParaStruct->SDIO_DataTimeOut = 0xFFFFFFFF; - SDIO_DataInitParaStruct->SDIO_DataLength = 0x00; - SDIO_DataInitParaStruct->SDIO_DataBlockSize = SDIO_DATABLOCKSIZE_1B; - SDIO_DataInitParaStruct->SDIO_TransDirection = SDIO_TRANSDIRECTION_TOCARD; - SDIO_DataInitParaStruct->SDIO_TransMode = SDIO_TRANSMODE_BLOCK; - SDIO_DataInitParaStruct->SDIO_DSMState = SDIO_DSMSTATE_DISABLE; -} - -/** - * @brief Return the number of remaining data bytes to be transferred to card. - * @param None - * @retval Number of remaining data bytes to be transferred - */ -uint32_t SDIO_GetDataCount(void) -{ - return SDIO->DTCNT; -} - -/** - * @brief Read one word from receive FIFO. - * @param None - * @retval Data received - */ -uint32_t SDIO_ReadData(void) -{ - return SDIO->FIFO; -} - -/** - * @brief Write one word to transmit FIFO. - * @param Data: 32-bit data write to the card. - * @retval None - */ -void SDIO_WriteData(uint32_t Data) -{ - SDIO->FIFO = Data; -} - -/** - * @brief Return the number of words remaining to be written or read from FIFO. - * @param None - * @retval Remaining number of words. - */ -uint32_t SDIO_GetFIFOCount(void) -{ - return SDIO->FIFOCNT; -} - -/** - * @brief Start SD I/O Read Wait operation. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_StartSDIOReadWait(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Start Read Wait operation */ - SDIO->DTCTLR |= SDIO_DTCTLR_RWSTART; - } else { - SDIO->DTCTLR &= (uint16_t)~((uint16_t)SDIO_DTCTLR_RWSTART); - } -} - -/** - * @brief Stop the SD I/O Read Wait operation. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_StopSDIOReadWait(TypeState NewValue) -{ - if (NewValue != DISABLE) { - SDIO->DTCTLR |= SDIO_DTCTLR_RWSTOP; - } else { - /* Stop Read Wait operation */ - SDIO->DTCTLR &= (uint16_t)~((uint16_t)SDIO_DTCTLR_RWSTOP); - } -} - -/** - * @brief Configure the SD I/O read wait mode. - * @param SDIO_ReadWaitMode: SD I/O Read Wait operation mode. - * This value will be : - * @arg SDIO_READWAITMODE_CLK: Read Wait operation realize by stopping SDIOCLK - * @arg SDIO_READWAITMODE_DAT2: Read Wait operation use SDIO_DAT2 - * @retval None - */ -void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode) -{ - if (SDIO_ReadWaitMode == SDIO_READWAITMODE_CLK) { - /* Read Wait operation stop SDIOCLK */ - SDIO->DTCTLR |= SDIO_DTCTLR_RWMODE; - } else { - /* Read Wait operation use SDIO_DAT2 */ - SDIO->DTCTLR &= (uint16_t)~((uint16_t)SDIO_DTCTLR_RWMODE); - } -} - -/** - * @brief SD I/O Mode Operation configuration. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_SetSDIOOperation(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable I/O Mode Operation */ - SDIO->DTCTLR |= SDIO_DTCTLR_SDIOEN; - } else { - /* Disenable I/O Mode Operation */ - SDIO->DTCTLR &= (uint16_t)~((uint16_t)SDIO_DTCTLR_SDIOEN); - } -} - -/** - * @brief Enable or disable the SD I/O suspend operation. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_SendSDIOSuspend_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable suspend operation */ - SDIO->CMD |= SDIO_CMD_SDIOSUSPEND; - } else { - /* Disenable suspend operation */ - SDIO->CMD &= (uint16_t)~((uint16_t)SDIO_CMD_SDIOSUSPEND); - } -} - -/** - * @brief Enable or disable the CE-ATA command completion signal. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_CMDCompletion_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable CE-ATA command completion signal */ - SDIO->CMD |= SDIO_CMD_ENCMDC; - } else { - /* Disenable CE-ATA command completion signal */ - SDIO->CMD &= (uint16_t)~((uint16_t)SDIO_CMD_ENCMDC); - } -} - -/** - * @brief Enable or disable the CE-ATA interrupt. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_CEATAInt_Enable(TypeState NewValue) -{ - if (NewValue != ENABLE) { - /* Enable CE-ATA interrupt */ - SDIO->CMD |= SDIO_CMD_NIEN; - } else { - /* Disenable CE-ATA interrupt */ - SDIO->CMD &= (uint16_t)~((uint16_t)SDIO_CMD_NIEN); - } -} - -/** - * @brief Send CE-ATA command (CMD61). - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SDIO_SendCEATA_Enable(TypeState NewValue) -{ - if (NewValue != DISABLE) { - SDIO->CMD |= SDIO_CMD_ATACMD; - } else { - SDIO->CMD &= (uint16_t)~((uint16_t)SDIO_CMD_ATACMD); - } -} - -/** - * @brief Check whether the flag is set or not. - * @param SDIO_FLAG: the flag to check. - * This value will be : - * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC failed) - * @arg SDIO_FLAG_DTCRCFAIL: Data block sent/received (CRC failed) - * @arg SDIO_FLAG_CMDTMOUT: Command response timeout - * @arg SDIO_FLAG_DTTMOUT: Data timeout - * @arg SDIO_FLAG_TXURE: Transmit FIFO underrun error - * @arg SDIO_FLAG_RXORE: Received FIFO overrun error - * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) - * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) - * @arg SDIO_FLAG_DTEND: Data end (data counter, SDIDTCNT, is zero) - * @arg SDIO_FLAG_STBITE: Start bit not detected on all data signals in wide - * bus mode. - * @arg SDIO_FLAG_DTBLKEND: Data block sent/received (CRC check passed) - * @arg SDIO_FLAG_CMDRUN: Command transfer in progress - * @arg SDIO_FLAG_TXRUN: Data transmit in progress - * @arg SDIO_FLAG_RXRUN: Data receive in progress - * @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty - * @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full - * @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full - * @arg SDIO_FLAG_RXFIFOF: Receive FIFO full - * @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty - * @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty - * @arg SDIO_FLAG_TXDTVAL: Data available in transmit FIFO - * @arg SDIO_FLAG_RXDTVAL: Data available in receive FIFO - * @arg SDIO_FLAG_SDIOINT: SD I/O interrupt received - * @arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received for CMD61 - * @retval The new state of SDIO_FLAG (SET or RESET). - */ -TypeState SDIO_GetBitState(uint32_t SDIO_FLAG) -{ - if ((SDIO->STR & SDIO_FLAG) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the pending flags. - * @param SDIO_FLAG: the flag to clear. - * This value will be : - * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) - * @arg SDIO_FLAG_DTCRCFAIL: Data block sent/received (CRC check failed) - * @arg SDIO_FLAG_CMDTMOUT: Command response timeout - * @arg SDIO_FLAG_DTTMOUT: Data timeout - * @arg SDIO_FLAG_TXURE: Transmit FIFO underrun error - * @arg SDIO_FLAG_RXORE: Received FIFO overrun error - * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) - * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) - * @arg SDIO_FLAG_DTEND: Data end (data counter, SDIO_DTCNT, is zero) - * @arg SDIO_FLAG_STBITE: Start bit not detected on all data signals in wide bus mode - * @arg SDIO_FLAG_DTBLKEND: Data block sent/received (CRC check passed) - * @arg SDIO_FLAG_SDIOINT: SD I/O interrupt received - * @arg SDIO_FLAG_ATAEND: CE-ATA command completion signal received for CMD61 - * @retval None - */ -void SDIO_ClearBitState(uint32_t SDIO_FLAG) -{ - SDIO->ICR = SDIO_FLAG; -} - -/** - * @brief Check whether the interrupt is pending or not. - * @param SDIO_INT: the SDIO interrupt source to check. - * This value will be : - * @arg SDIO_INT_CCRCFAIL: Command response received (CRC check failed) interrupt - * @arg SDIO_INT_DTCRCFAIL: Data block sent/received (CRC check failed) interrupt - * @arg SDIO_INT_CMDTMOUT: Command response timeout interrupt - * @arg SDIO_INT_DTTMOUT: Data timeout interrupt - * @arg SDIO_INT_TXURE: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXORE: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDREND: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DTEND: Data end (data counter, SDIDTCNT, is zero) interrupt - * @arg SDIO_INT_STBITE: Start bit not detected on all data signals in wide bus mode interrupt - * @arg SDIO_INT_DTBLKEND: Data block sent/received (CRC check passed) interrupt - * @arg SDIO_INT_CMDRUN: Command transfer in progress interrupt - * @arg SDIO_INT_TXRUN: Data transmit in progress interrupt - * @arg SDIO_INT_RXRUN: Data receive in progress interrupt - * @arg SDIO_INT_TXFIFOHE: Transmit FIFO Half Empty interrupt - * @arg SDIO_INT_RXFIFOHF: Receive FIFO Half Full interrupt - * @arg SDIO_INT_TXFIFOF: Transmit FIFO full interrupt - * @arg SDIO_INT_RXFIFOF: Receive FIFO full interrupt - * @arg SDIO_INT_TXFIFOE: Transmit FIFO empty interrupt - * @arg SDIO_INT_RXFIFOE: Receive FIFO empty interrupt - * @arg SDIO_INT_TXDTVAL: Data available in transmit FIFO interrupt - * @arg SDIO_INT_RXDTVAL: Data available in receive FIFO interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 interrupt - * @retval The new state of SDIO_INT (SET or RESET). - */ -TypeState SDIO_GetIntBitState(uint32_t SDIO_INT) -{ - if ((SDIO->STR & SDIO_INT) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the interrupt pending bits. - * @param SDIO_INT: the interrupt pending bit to clear. - * This value will be : - * @arg SDIO_INT_CCRCFAIL: Command response received (CRC check failed) interrupt - * @arg SDIO_INT_DTCRCFAIL: Data block sent/received (CRC check failed) interrupt - * @arg SDIO_INT_CMDTMOUT: Command response timeout interrupt - * @arg SDIO_INT_DTTMOUT: Data timeout interrupt - * @arg SDIO_INT_TXURE: Transmit FIFO underrun error interrupt - * @arg SDIO_INT_RXORE: Received FIFO overrun error interrupt - * @arg SDIO_INT_CMDREND: Command response received (CRC check passed) interrupt - * @arg SDIO_INT_CMDSENT: Command sent (no response required) interrupt - * @arg SDIO_INT_DTEND: Data end (data counter, SDIDTCNT, is zero) interrupt - * @arg SDIO_INT_STBITE: Start bit not detected on all data signals in wide - * bus mode interrupt - * @arg SDIO_INT_SDIOINT: SD I/O interrupt received interrupt - * @arg SDIO_INT_ATAEND: CE-ATA command completion signal received for CMD61 - * @retval None - */ -void SDIO_ClearIntBitState(uint32_t SDIO_INT) -{ - SDIO->ICR = SDIO_INT; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -#endif diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_spi.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_spi.c deleted file mode 100644 index b55a6dc911..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_spi.c +++ /dev/null @@ -1,554 +0,0 @@ -/** - ****************************************************************************** - * @brief SPI functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_spi.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup SPI - * @brief SPI driver modules - * @{ - */ - -/** @defgroup SPI_Private_Defines - * @{ - */ - -/* SPI registers Masks */ -#define CTLR1_CLEAR_MASK ((uint16_t)0x3040) -#define I2SCTLR_CLEAR_MASK ((uint16_t)0xF040) - -/* I2S clock source selection Masks */ -#define I2S2_CLOCK_SRC ((uint32_t)(0x00020000)) -#define I2S3_CLOCK_SRC ((uint32_t)(0x00040000)) -#define I2S_MUL_MASK ((uint32_t)(0x0000F000)) -#define I2S_DIV_MASK ((uint32_t)(0x000000F0)) -/** - * @} - */ - -/** @defgroup SPI_Private_Functions - * @{ - */ - -/** - * @brief Reset the SPIx and the I2Sx peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @retval None - */ -void SPI_I2S_DeInit(SPI_TypeDef *SPIx) -{ - if (SPIx == SPI1) { - /* Reset SPI1 */ - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_SPI1RST, ENABLE); - - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_SPI1RST, DISABLE); - } else if (SPIx == SPI2) { - /* Reset SPI2 and I2S2 peripheral */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_SPI2RST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_SPI2RST, DISABLE); - } else if (SPIx == SPI3) { - /* Reset SPI3 and I2S3 peripheral */ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_SPI3RST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_SPI3RST, DISABLE); - } -} - -/** - * @brief Initialize the SPIx peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_InitParameter: The structuer contains configuration information. - * @retval None - */ -void SPI_Init(SPI_TypeDef *SPIx, SPI_InitPara *SPI_InitParameter) -{ - uint16_t temp_ctrl1 = 0; - - /* Configure SPIx CTRL1 according to the SPI_InitParameter */ - temp_ctrl1 = SPIx->CTLR1; - temp_ctrl1 &= CTLR1_CLEAR_MASK; - temp_ctrl1 |= (uint16_t)((uint32_t)SPI_InitParameter->SPI_TransType | SPI_InitParameter->SPI_Mode | - SPI_InitParameter->SPI_FrameFormat | SPI_InitParameter->SPI_SCKPL | - SPI_InitParameter->SPI_SCKPH | SPI_InitParameter->SPI_SWNSSEN | - SPI_InitParameter->SPI_PSC | SPI_InitParameter->SPI_FirstBit); - SPIx->CTLR1 = temp_ctrl1; - - /* Configure SPIx CRC Polynomial */ - SPIx->CPR = SPI_InitParameter->SPI_CRCPOL; - - /* Configure the I2SSEL bit in I2SCTLR register as SPI mode */ - SPIx->I2SCTLR &= ~SPI_I2SCTLR_I2SSEL; - -} - -/** - * @brief Initialize the I2Sx peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 2 or 3. - * @param I2S_InitParameter: The structuer contains configuration information. - * @retval None - */ -void I2S_Init(SPI_TypeDef *SPIx, I2S_InitPara *I2S_InitParameter) -{ - uint16_t temp_i2sctrl = 0, div = 2, of = 0; - uint32_t temp = 0; - RCC_ClocksPara RCC_Clocks; - uint32_t sourceclock = 0; - - /* SPIx I2SCTLR & I2SCKP Configuration */ - /* Deinit I2SCTLR I2SCKP register */ - SPIx->I2SCTLR &= I2SCTLR_CLEAR_MASK; - SPIx->I2SCKP = 0x0002; - - /* Default config of the prescaler*/ - if (I2S_InitParameter->I2S_AudioFreq == I2S_AUDIOFREQ_DEFAULT) { - of = (uint16_t)0; - div = (uint16_t)2; - } else { - /* Get the I2S clock source */ - if (((uint32_t)SPIx) == SPI2_BASE) { - temp = I2S2_CLOCK_SRC; - } else { - temp = I2S3_CLOCK_SRC; - } - - /* I2S clock source configuration depend on different device */ -#ifdef GD32F10X_CL - if ((RCC->GCFGR2 & temp) != 0) { - /* Get RCC PLL3 multiplier */ - temp = (uint32_t)((RCC->GCFGR2 & I2S_MUL_MASK) >> 12); - - if ((temp > 5) && (temp < 15)) { - /* Multiplier is between 8 and 14 (value 15 is forbidden) */ - temp += 2; - } else { - if (temp == 15) { - /* Multiplier is 20 */ - temp = 20; - } - } - /* Get the PREDV2 value */ - sourceclock = (uint32_t)(((RCC->GCFGR2 & I2S_DIV_MASK) >> 4) + 1); - - /* Calculate sourceclock based on PLL3 and PREDV2 */ - sourceclock = (uint32_t)((HSE_VALUE / sourceclock) * temp * 2); - } else { - /* Get system clock */ - RCC_GetClocksFreq(&RCC_Clocks); - sourceclock = RCC_Clocks.CK_SYS_Frequency; - } -#else - /* Get system clock */ - RCC_GetClocksFreq(&RCC_Clocks); - sourceclock = RCC_Clocks.CK_SYS_Frequency; -#endif /* GD32F10X_CL */ - - /* Calculate the prescaler depending on the MCLK output state and the data format with a flaoting point. */ - if (I2S_InitParameter->I2S_MCKOE == I2S_MCK_ENABLE) { - temp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitParameter->I2S_AudioFreq)) + 5); - } else { - if (I2S_InitParameter->I2S_FrameFormat == I2S_FRAMEFORMAT_DL16b_CL16b) { - temp = (uint16_t)(((((sourceclock / 32) * 10) / I2S_InitParameter->I2S_AudioFreq)) + 5); - } else { - temp = (uint16_t)(((((sourceclock / 64) * 10) / I2S_InitParameter->I2S_AudioFreq)) + 5); - } - } - - /* Remove the flaoting point */ - temp = temp / 10; - of = (uint16_t)(temp & (uint16_t)0x0001); - div = (uint16_t)((temp - of) / 2); - of = (uint16_t)(of << 8); - } - - /* Inappropriate prescaler, Set the default values */ - if ((div < 1) || (div > 0xFF)) { - div = 2; - of = 0; - } - - /* Configure SPIx I2SCKP */ - SPIx->I2SCKP = (uint16_t)(div | (uint16_t)(of | (uint16_t)I2S_InitParameter->I2S_MCKOE)); - - /* Configure SPIx I2SCTLR according to the I2S_InitParameter */ - temp_i2sctrl = SPIx->I2SCTLR; - temp_i2sctrl |= (uint16_t)(SPI_I2SCTLR_I2SSEL | (uint16_t)(I2S_InitParameter->I2S_Mode | \ - (uint16_t)(I2S_InitParameter->I2S_STD | (uint16_t)(I2S_InitParameter->I2S_FrameFormat | \ - (uint16_t)I2S_InitParameter->I2S_CKPL)))); - SPIx->I2SCTLR = temp_i2sctrl; - -} - -/** - * @brief Initial SPI_InitParameter members. - * @param SPI_InitParameter : pointer to a SPI_InitPara structure. - * @retval None - */ -void SPI_ParaInit(SPI_InitPara *SPI_InitParameter) -{ - /* Reset SPI init structure parameters values */ - SPI_InitParameter->SPI_TransType = SPI_TRANSTYPE_FULLDUPLEX; - SPI_InitParameter->SPI_Mode = SPI_MODE_SLAVE; - SPI_InitParameter->SPI_FrameFormat = SPI_FRAMEFORMAT_8BIT; - SPI_InitParameter->SPI_SCKPL = SPI_SCKPL_LOW; - SPI_InitParameter->SPI_SCKPH = SPI_SCKPH_1EDGE; - SPI_InitParameter->SPI_SWNSSEN = SPI_SWNSS_HARD; - SPI_InitParameter->SPI_PSC = SPI_PSC_2; - SPI_InitParameter->SPI_FirstBit = SPI_FIRSTBIT_MSB; - SPI_InitParameter->SPI_CRCPOL = 7; -} - -/** - * @brief Initial I2S_InitParameter members. - * @param I2S_InitParameter : pointer to a I2S_InitPara structure. - * @retval None - */ -void I2S_ParaInit(I2S_InitPara *I2S_InitParameter) -{ - /* Reset I2S init structure parameters values */ - I2S_InitParameter->I2S_Mode = I2S_MODE_SLAVETX; - I2S_InitParameter->I2S_STD = I2S_STD_PHILLIPS; - I2S_InitParameter->I2S_FrameFormat = I2S_FRAMEFORMAT_DL16b_CL16b; - I2S_InitParameter->I2S_MCKOE = I2S_MCK_DISABLE; - I2S_InitParameter->I2S_AudioFreq = I2S_AUDIOFREQ_DEFAULT; - I2S_InitParameter->I2S_CKPL = I2S_CKPL_LOW; -} - -/** - * @brief Enable or disable the SPI peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SPI_Enable(SPI_TypeDef *SPIx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - SPIx->CTLR1 |= SPI_CTLR1_SPIEN; - } else { - SPIx->CTLR1 &= ~SPI_CTLR1_SPIEN; - } -} - -/** - * @brief Enable or disable the I2S peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 2 or 3. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void I2S_Enable(SPI_TypeDef *SPIx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - SPIx->I2SCTLR |= SPI_I2SCTLR_I2SEN; - } else { - SPIx->I2SCTLR &= ~SPI_I2SCTLR_I2SEN; - } -} - -/** - * @brief Enable or disable the SPI or I2S interrupts. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_I2S_INT: specifies the SPI or I2S interrupt source. Select one of the follwing values : - * @arg SPI_I2S_INT_TBE: Tx buffer empty interrupt mask - * @arg SPI_I2S_INT_RBNE: Rx buffer not empty interrupt mask - * @arg SPI_I2S_INT_ERR: Error interrupt mask - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SPI_I2S_INTConfig(SPI_TypeDef *SPIx, uint8_t SPI_I2S_INT, TypeState NewValue) -{ - uint16_t intmask = 0 ; - - /* Get the interrupt enable bit in CTRL2 */ - intmask = (uint16_t)1 << (uint16_t)(SPI_I2S_INT >> 4); - - /* Enable or disable the selected interrupt */ - if (NewValue != DISABLE) { - SPIx->CTLR2 |= intmask; - } else { - SPIx->CTLR2 &= (uint16_t)~intmask; - } -} - -/** - * @brief Enable or disable the SPIx or I2Sx DMA transfer request. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_I2S_DMAReq: Select the SPI or I2S DMA transfer request. Select one of the follwing values : - * @arg SPI_I2S_DMA_TX: Tx buffer DMA transfer request - * @arg SPI_I2S_DMA_RX: Rx buffer DMA transfer request - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SPI_I2S_DMA_Enable(SPI_TypeDef *SPIx, uint16_t SPI_I2S_DMAReq, TypeState NewValue) -{ - if (NewValue != DISABLE) { - SPIx->CTLR2 |= SPI_I2S_DMAReq; - } else { - SPIx->CTLR2 &= (uint16_t)~SPI_I2S_DMAReq; - } -} - -/** - * @brief Send a Data by the SPIx or I2Sx peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param Data : Data to be Send. - * @retval None - */ -void SPI_I2S_SendData(SPI_TypeDef *SPIx, uint16_t Data) -{ - SPIx->DTR = Data; -} - -/** - * @brief Return the received data by the SPIx or I2Sx peripheral. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @retval The value of the received data. - */ -uint16_t SPI_I2S_ReceiveData(SPI_TypeDef *SPIx) -{ - return SPIx->DTR; -} - -/** - * @brief NSS pin internal software management. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_SWNSS: specifies the SPI NSS internal state. Select one of the follwing values : - * @arg SPI_SWNSS_SET: Set NSS pin internally - * @arg SPI_SWNSS_RESET: Reset NSS pin internally - * @retval None - */ -void SPI_SWNSSConfig(SPI_TypeDef *SPIx, uint16_t SPI_SWNSS) -{ - if (SPI_SWNSS != SPI_SWNSS_RESET) { - /* Set NSS pin */ - SPIx->CTLR1 |= SPI_CTLR1_SWNSS; - } else { - /* Reset NSS pin */ - SPIx->CTLR1 &= ~SPI_CTLR1_SWNSS; - } -} - -/** - * @brief Enable or disable the NSS output. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SPI_NSSDRV(SPI_TypeDef *SPIx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - SPIx->CTLR2 |= SPI_CTLR2_NSSDRV; - } else { - SPIx->CTLR2 &= ~SPI_CTLR2_NSSDRV; - } -} - -/** - * @brief Configure the data frame format. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_FrameFormat: Select the data frame format. Select one of the follwing values : - * @arg SPI_FRAMEFORMAT_16BIT: Set data frame format to 16bit - * @arg SPI_FRAMEFORMAT_8BIT: Set data frame format to 8bit - * @retval None - */ -void SPI_FrameFormatConfig(SPI_TypeDef *SPIx, uint16_t SPI_FrameFormat) -{ - /* Clear FF16 bit */ - SPIx->CTLR1 &= (uint16_t)~SPI_FRAMEFORMAT_16BIT; - /* Set new FF16 bit value */ - SPIx->CTLR1 |= SPI_FrameFormat; -} - -/** - * @brief Send the SPIx CRC value. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @retval None - */ -void SPI_SendCRCNext(SPI_TypeDef *SPIx) -{ - /* Enable the CRC transmission */ - SPIx->CTLR1 |= SPI_CTLR1_CRCNT; -} - -/** - * @brief Enable or disable the CRC calculation. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void SPI_CRC_Enable(SPI_TypeDef *SPIx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the CRC calculation */ - SPIx->CTLR1 |= SPI_CTLR1_CRCEN; - } else { - /* Disable the CRC calculation */ - SPIx->CTLR1 &= ~SPI_CTLR1_CRCEN; - } -} - -/** - * @brief Get the transmit or the receive CRC register value. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_CRC: Select the transmit or the receive CRC register. Select one of the follwing values : - * @arg SPI_CRC_TX: Selects Tx CRC register - * @arg SPI_CRC_RX: Selects Rx CRC register - * @retval The selected CRC register value. - */ -uint16_t SPI_GetCRC(SPI_TypeDef *SPIx, uint8_t SPI_CRC) -{ - if (SPI_CRC != SPI_CRC_RX) { - /* Transmit CRC value */ - return SPIx->TCR; - } else { - /* Receive CRC value */ - return SPIx->RCR; - } -} - -/** - * @brief Get the CRC Polynomial value. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @retval The CRC Polynomial value. - */ -uint16_t SPI_GetCRCPolynomial(SPI_TypeDef *SPIx) -{ - return SPIx->CPR; -} - -/** - * @brief Select the transfer direction in bidirectional mode. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_BDOE: The transfer direction in bi-directional mode. Select one of the follwing values : - * @arg SPI_BDOE_TX: Selects Tx transmission direction - * @arg SPI_BDOE_RX: Selects Rx receive direction - * @retval None - */ -void SPI_BDOEConfig(SPI_TypeDef *SPIx, uint16_t SPI_BDOE) -{ - if (SPI_BDOE == SPI_BDOE_TX) { - /* Transmit only mode*/ - SPIx->CTLR1 |= SPI_BDOE_TX; - } else { - /* Receive only mode */ - SPIx->CTLR1 &= SPI_BDOE_RX; - } -} - -/** - * @brief Check whether the flag is set or not. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_I2S_FLAG: Select the flag. Select one of the follwing values : - * @arg SPI_FLAG_TBE: Transmit buffer empty flag. - * @arg SPI_FLAG_RBNE: Receive buffer not empty flag. - * @arg SPI_FLAG_BSY: Busy flag. - * @arg SPI_FLAG_OVR: Overrun flag. - * @arg SPI_FLAG_MODF: Mode Fault flag. - * @arg SPI_FLAG_CRCERR: CRC Error flag. - * @arg I2S_FLAG_TBE: Transmit buffer empty flag. - * @arg I2S_FLAG_RBNE: Receive buffer not empty flag. - * @arg I2S_FLAG_BSY: Busy flag. - * @arg I2S_FLAG_OVR: Overrun flag. - * @arg I2S_FLAG_UDR: Underrun Error flag. - * @arg I2S_FLAG_CHSIDE: Channel Side flag. - * @retval The new state of SPI_I2S_FLAG. - */ -TypeState SPI_I2S_GetBitState(SPI_TypeDef *SPIx, uint16_t SPI_I2S_FLAG) -{ - /* Check the status of the selected flag */ - if ((SPIx->STR & SPI_I2S_FLAG) != (uint16_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the flag, only used for clear CRCERR flag. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_I2S_FLAG: Select the flag. This parametric only can be SPI_FLAG_CRCERR. - * @note - * The other flags are cleared by software sequences: - * - OVR (OverRun error) flag is cleared by software sequence: a read - * operation to SPI_DTR register (SPI_I2S_ReceiveData()) followed by a read - * operation to SPI_STR register (SPI_I2S_GetBitState()). - * - UDR (UnderRun error) flag is cleared by a read operation to - * SPI_STR register (SPI_I2S_GetBitState()). - * - MODF (Mode Fault) flag is cleared by software sequence: a read/write - * operation to SPI_STR register (SPI_I2S_GetBitState()) followed by a - * write operation to SPI_CTLR1 register (SPI_Enable() to enable the SPI). - * @retval None - */ -void SPI_I2S_ClearBitState(SPI_TypeDef *SPIx, uint16_t SPI_I2S_FLAG) -{ - SPIx->STR = (uint16_t)~SPI_I2S_FLAG; -} - -/** - * @brief Check whether interrupt has occurred. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_I2S_INT: Select the SPI/I2S interrupt. Select one of the follwing values : - * @arg SPI_I2S_INT_TBE: Transmit buffer empty interrupt. - * @arg SPI_I2S_INT_RBNE: Receive buffer not empty interrupt. - * @arg SPI_I2S_INT_OVR: Overrun interrupt. - * @arg SPI_INT_MODF: Mode Fault interrupt. - * @arg SPI_INT_CRCERR: CRC Error interrupt. - * @arg I2S_INT_UDR: Underrun Error interrupt. - * @retval The new state of SPI_I2S_INT. - */ -TypeState SPI_I2S_GetIntBitState(SPI_TypeDef *SPIx, uint8_t SPI_I2S_INT) -{ - uint16_t intposition = 0, intmask = 0; - /* Get the interrupt pending bit and enable bit */ - intposition = 0x01 << (SPI_I2S_INT & 0x0F); - intmask = 0x01 << (SPI_I2S_INT >> 4); - - /* Check the status of the interrupt */ - if (((SPIx->STR & intposition) != (uint16_t)RESET) && (SPIx->CTLR2 & intmask)) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the SPIx or I2S interrupt pending bit, only uesd for clear CRCERR interrupt. - * @param SPIx: the SPI/I2S peripheral where x can be 1..3. - * @param SPI_I2S_INT: Select the SPI or I2S interrupt. This parametric only can be SPI_INT_CRCERR. - * @note - * The other flags are cleared by software sequences: - * - OVR (OverRun error) flag is cleared by software sequence: a read - * operation to SPI_DTR register (SPI_I2S_ReceiveData()) followed by a read - * operation to SPI_STR register (SPI_I2S_GetBitState()). - * - UDR (UnderRun error) flag is cleared by a read operation to - * SPI_STR register (SPI_I2S_GetBitState()). - * - MODF (Mode Fault) flag is cleared by software sequence: a read/write - * operation to SPI_STR register (SPI_I2S_GetBitState()) followed by a - * write operation to SPI_CTLR1 register (SPI_Enable() to enable the SPI). - * @retval None - */ -void SPI_I2S_ClearIntBitState(SPI_TypeDef *SPIx, uint8_t SPI_I2S_INT) -{ - uint16_t itpos = 0; - - /* Clear the select interrupt pending bit. */ - itpos = 0x01 << (SPI_I2S_INT & 0x0F); - SPIx->STR = (uint16_t)~itpos; -} -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_timer.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_timer.c deleted file mode 100644 index d5fd7fdf74..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_timer.c +++ /dev/null @@ -1,2360 +0,0 @@ -/** - ****************************************************************************** - * @brief TIMER functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_timer.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup TIMER - * @brief TIMER driver modules - * @{ - */ - -/** @defgroup TIMER_Private_Defines - * @{ - */ -/* TIMER registers bit mask */ -#define SMC_ETR_MASK ((uint16_t)0x00FF) -#define CHCTLR_OFFSET ((uint16_t)0x0018) -#define CHE_CHE_SET ((uint16_t)0x0001) -#define CHE_CHNE_SET ((uint16_t)0x0004) -/** - * @} - */ - -/* Private function prototypes */ -static void TI1_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter); -static void TI2_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter); -static void TI3_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter); -static void TI4_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter); - -/** @defgroup TIMER_Private_Functions - * @{ - */ - -/** - * @brief Deinitialize the TIMER . - * @param TIMERx: x ={ 0-13 } . - * @retval None - */ -void TIMER_DeInit(TIMER_TypeDef *TIMERx) -{ - if (TIMERx == TIMER0) { - RCC->APB2RCR |= RCC_APB2PERIPH_TIMER0RST; - RCC->APB2RCR &= ~RCC_APB2PERIPH_TIMER0; - } else if (TIMERx == TIMER1) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER1RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER1; - } else if (TIMERx == TIMER2) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER2RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER2; - } else if (TIMERx == TIMER3) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER3RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER3; - } else if (TIMERx == TIMER4) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER4RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER4; - } else if (TIMERx == TIMER5) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER5RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER5; - } else if (TIMERx == TIMER6) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER6RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER6; - } else if (TIMERx == TIMER7) { - RCC->APB2RCR |= RCC_APB2PERIPH_TIMER7RST; - RCC->APB2RCR &= ~RCC_APB2PERIPH_TIMER7; - } else if (TIMERx == TIMER8) { - RCC->APB2RCR |= RCC_APB2PERIPH_TIMER8RST; - RCC->APB2RCR &= ~RCC_APB2PERIPH_TIMER8; - } else if (TIMERx == TIMER9) { - RCC->APB2RCR |= RCC_APB2PERIPH_TIMER9RST; - RCC->APB2RCR &= ~RCC_APB2PERIPH_TIMER9; - } else if (TIMERx == TIMER10) { - RCC->APB2RCR |= RCC_APB2PERIPH_TIMER10RST; - RCC->APB2RCR &= ~RCC_APB2PERIPH_TIMER10; - } else if (TIMERx == TIMER11) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER11RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER11; - } else if (TIMERx == TIMER12) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER12RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER12; - } else if (TIMERx == TIMER13) { - RCC->APB1RCR |= RCC_APB1PERIPH_TIMER13RST; - RCC->APB1RCR &= ~RCC_APB1PERIPH_TIMER13; - } -} - -/** - * @brief Initialize the specified Timer - * @param TIMERx: x ={ 0 -13 } . - * @param TIMER_Init: pointer to a TIMER_BaseInitPara structure. - * @retval None - */ -void TIMER_BaseInit(TIMER_TypeDef *TIMERx, TIMER_BaseInitPara *TIMER_Init) -{ - uint16_t tmpctlr1 = 0; - - tmpctlr1 = TIMERx->CTLR1; - - if ((TIMERx == TIMER0) || (TIMERx == TIMER7) || (TIMERx == TIMER1) || (TIMERx == TIMER2) || - (TIMERx == TIMER3) || (TIMERx == TIMER4) || (TIMERx == TIMER8) || (TIMERx == TIMER9) - || (TIMERx == TIMER10) || (TIMERx == TIMER11) || (TIMERx == TIMER12) || (TIMERx == TIMER13)) { - /* Configure the Counter Mode */ - tmpctlr1 &= (uint16_t)(~((uint16_t)(TIMER_CTLR1_DIR | TIMER_CTLR1_CAM))); - tmpctlr1 |= (uint32_t)TIMER_Init->TIMER_CounterMode; - } - - if ((TIMERx != TIMER5) && (TIMERx != TIMER6)) { - /* Configure the clock division */ - tmpctlr1 &= (uint16_t)(~((uint16_t)TIMER_CTLR1_CDIV)); - tmpctlr1 |= (uint32_t)TIMER_Init->TIMER_ClockDivision; - } - - TIMERx->CTLR1 = tmpctlr1; - - /* Configure the Autoreload value */ - TIMERx->CARL = TIMER_Init->TIMER_Period ; - - /* Configure the Prescaler value */ - TIMERx->PSC = TIMER_Init->TIMER_Prescaler; - - if ((TIMERx == TIMER0) || - (TIMERx == TIMER7)) { - /* Configure the Repetition Counter value */ - TIMERx->CREP = TIMER_Init->TIMER_RepetitionCounter; - } - - /* Generate an update event */ - TIMERx->EVG = TIMER_PSC_RELOAD_NOW; -} - -/** - * @brief Fill each TIMER_BaseInitPara Struct member with a default value. - * @param TIMER_Init: pointer to a TIMER_BaseInitPara structure. - * @retval None - */ -void TIMER_BaseStructInit(TIMER_BaseInitPara *TIMER_Init) -{ - /* Fill the default value */ - TIMER_Init->TIMER_Period = 0xFFFFFFFF; - TIMER_Init->TIMER_Prescaler = 0x0000; - TIMER_Init->TIMER_ClockDivision = TIMER_CDIV_DIV1; - TIMER_Init->TIMER_CounterMode = TIMER_COUNTER_UP; - TIMER_Init->TIMER_RepetitionCounter = 0x0000; -} - -/** - * @brief Configure the TIMER Prescaler. - * @param TIMERx: x ={ 0-13 } - * @param Prescaler: Prescaler value - * @param TIMER_PSCReloadMode: Prescaler Reload mode - * This value will be : - * @arg TIMER_PSC_RELOAD_UPDATE : The Prescaler is loaded at the next update event. - * @arg TIMER_PSC_RELOAD_NOW : The Prescaler is loaded right now. - * @retval None - */ -void TIMER_PrescalerConfig(TIMER_TypeDef *TIMERx, uint16_t Prescaler, uint16_t TIMER_PSCReloadMode) -{ - /* Set PSC */ - TIMERx->PSC = Prescaler; - - /* Choose reload mode */ - TIMERx->EVG = TIMER_PSCReloadMode; -} - -/** - * @brief Configure the TIMER Counter Mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_CounterMode: the Counter Mode - * This value will be : - * @arg TIMER_COUNTER_UP : Up Counting Mode - * @arg TIMER_COUNTER_DOWN : Down Counting Mode - * @arg TIMER_COUNTER_CENTER_ALIGNED1: Center Aligned Counting Mode1 - * @arg TIMER_COUNTER_CENTER_ALIGNED2: Center Aligned Counting Mode2 - * @arg TIMER_COUNTER_CENTER_ALIGNED3: Center Aligned Counting Mode3 - * @retval None - */ -void TIMER_CounterMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_CounterMode) -{ - uint16_t tmpctlr1 = 0; - - tmpctlr1 = TIMERx->CTLR1; - - /* Reset the CAM and DIR Bits */ - tmpctlr1 &= (uint16_t)(~((uint16_t)(TIMER_CTLR1_DIR | TIMER_CTLR1_CAM))); - - /* Configures the Counter Mode */ - tmpctlr1 |= TIMER_CounterMode; - - /* Update the TIMER CTLR1 */ - TIMERx->CTLR1 = tmpctlr1; -} - -/** - * @brief Configure the TIMER Counter Register value - * @param TIMERx: x ={ 0-13 } . - * @param Counter: the Counter register new value. - * @retval None - */ -void TIMER_SetCounter(TIMER_TypeDef *TIMERx, uint32_t Counter) -{ - TIMERx->CNT = Counter; -} - -/** - * @brief Configure the Autoreload value - * @param TIMERx: x ={ 0-13 } . - * @param AutoReloadValue: - * @retval None - */ -void TIMER_SetAutoreload(TIMER_TypeDef *TIMERx, uint32_t AutoReloadValue) -{ - TIMERx->CARL = AutoReloadValue; -} - -/** - * @brief Get the Counter value. - * @param TIMERx: x ={ 0-13 } . - * @retval Counter Register value. - */ -uint32_t TIMER_GetCounter(TIMER_TypeDef *TIMERx) -{ - return TIMERx->CNT; -} - -/** - * @brief Get the Prescaler value. - * @param TIMERx: x ={ 0-13 } . - * @retval Prescaler Register value - */ -uint16_t TIMER_GetPrescaler(TIMER_TypeDef *TIMERx) -{ - return TIMERx->PSC; -} - -/** - * @brief Configure the TIMERx Update event. - * @param TIMERx: x ={ 0-13 } . - * @param NewValue: new value of the TIMERx UPDIS bit - * This value will be : - * @arg ENABLE : Update Enbale - * @arg DISABLE : Update Disable - * @retval None - */ -void TIMER_UpdateDisableConfig(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - TIMERx->CTLR1 |= TIMER_CTLR1_UPDIS; - } else { - TIMERx->CTLR1 &= (uint16_t)~((uint16_t)TIMER_CTLR1_UPDIS); - } -} - -/** - * @brief Configure the TIMER Update Request source. - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_UpdateSrc: Configures the Update source. - * This value will be : - * @arg TIMER_UPDATE_SRC_GLOBAL : Update generate by setting of UPG bit or the counter - * overflow/underflow , or the slave mode controller trigger. - * @arg TIMER_UPDATE_SRC_REGULAR : Update generate only by counter overflow/underflow. - * @retval None - */ -void TIMER_UpdateRequestConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_UpdateSrc) -{ - if (TIMER_UpdateSrc != TIMER_UPDATE_SRC_GLOBAL) { - TIMERx->CTLR1 |= TIMER_CTLR1_UPS; - } else { - TIMERx->CTLR1 &= (uint16_t)~((uint16_t)TIMER_CTLR1_UPS); - } -} - -/** - * @brief Configure the CARL Preload function - * @param TIMERx: x ={ 0-13 } . - * @param NewValue: the state of the Preload function on CARL. - * This value will be : - * @arg ENABLE - * @arg DISABLE - * @retval None - */ -void TIMER_CARLPreloadConfig(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Set the CARL Preload Bit */ - TIMERx->CTLR1 |= TIMER_CTLR1_ARSE; - } else { - /* Reset the CARL Preload Bit */ - TIMERx->CTLR1 &= (uint16_t)~((uint16_t)TIMER_CTLR1_ARSE); - } -} - -/** - * @brief Select the TIMER Single Pulse Mode. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_SPMode: specifies the SPM Mode to be used. - * This value will be : - * @arg TIMER_SP_MODE_SINGLE - * @arg TIMER_SP_MODE_REPETITIVE - * @retval None - */ -void TIMER_SinglePulseMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_SPMode) -{ - /* Reset the SPM Bit */ - TIMERx->CTLR1 &= (uint16_t)~((uint16_t)TIMER_CTLR1_SPM); - - /* Set the SPM Bit */ - TIMERx->CTLR1 |= TIMER_SPMode; -} - -/** - * @brief Configure the TIMERx Clock Division value. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_CDIV: the clock division value. - * This value will be : - * @arg TIMER_CDIV_DIV1: TDTS = Tck_tim - * @arg TIMER_CDIV_DIV2: TDTS = 2*Tck_tim - * @arg TIMER_CDIV_DIV4: TDTS = 4*Tck_tim - * @retval None - */ -void TIMER_SetClockDivision(TIMER_TypeDef *TIMERx, uint16_t TIMER_CDIV) -{ - /* Reset the CDIV value*/ - TIMERx->CTLR1 &= (uint16_t)~((uint16_t)TIMER_CTLR1_CDIV); - - /* Set the CDIV value */ - TIMERx->CTLR1 |= TIMER_CDIV; -} - -/** - * @brief ENABLE or DISABLE the TIMER. - * @param TIMERx: x ={ 0-13 } . - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void TIMER_Enable(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the TIMER */ - TIMERx->CTLR1 |= TIMER_CTLR1_CNTE; - } else { - /* Disable the TIMER */ - TIMERx->CTLR1 &= (uint16_t)(~((uint16_t)TIMER_CTLR1_CNTE)); - } -} - -/** - * @brief Configure the: Break feature, dead time, Lock level, ROS/IOS State and the OAE - * @param TIMERx: x ={ 1 , 8 } . - * @param TIMER_BKDTInit: pointer to a TIMER_BKDTInitPara structure that - * contains the BKDT Register configuration information for the TIMER. - * @retval None - */ -void TIMER_BKDTConfig(TIMER_TypeDef *TIMERx, TIMER_BKDTInitPara *TIMER_BKDTInit) -{ - TIMERx->BKDT = (uint32_t)TIMER_BKDTInit->TIMER_ROSState | - TIMER_BKDTInit->TIMER_IOSState | - TIMER_BKDTInit->TIMER_LOCKLevel | - TIMER_BKDTInit->TIMER_DeadTime | - TIMER_BKDTInit->TIMER_Break | - TIMER_BKDTInit->TIMER_BreakPolarity | - TIMER_BKDTInit->TIMER_OutAuto; -} - -/** - * @brief Fill TIMER_BKDTInit structure member with default value. - * @param TIMER_BKDTInit : pointer to a TIMER_BKDTInitPara structure which will be initialized. - * @retval None - */ -void TIMER_BKDTStructInit(TIMER_BKDTInitPara *TIMER_BKDTInit) -{ - TIMER_BKDTInit->TIMER_ROSState = TIMER_ROS_STATE_DISABLE; - TIMER_BKDTInit->TIMER_IOSState = TIMER_IOS_STATE_DISABLE; - TIMER_BKDTInit->TIMER_LOCKLevel = TIMER_LOCK_LEVEL_OFF; - TIMER_BKDTInit->TIMER_DeadTime = 0x00; - TIMER_BKDTInit->TIMER_Break = TIMER_BREAK_DISABLE; - TIMER_BKDTInit->TIMER_BreakPolarity = TIMER_BREAK_POLARITY_LOW; - TIMER_BKDTInit->TIMER_OutAuto = TIMER_OUTAUTO_DISABLE; -} - -/** - * @brief Enable or disable the TIMER ALL Outputs. - * @param TIMERx: x ={ 1 , 8 } . - * @param NewValue: ENABLE or DISABLE . - * @retval None - */ -void TIMER_CtrlPWMOutputs(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the TIMER ALL Output */ - TIMERx->BKDT |= TIMER_BKDT_POE; - } else { - /* Disable the TIMER ALL Output */ - TIMERx->BKDT &= (uint16_t)(~((uint16_t)TIMER_BKDT_POE)); - } -} - -/** - * @brief Initialize the TIMERx Channel1 with TIMER_OCInitPara . - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_OCInit : pointer to a TIMER_OCInitPara structure . - * @retval None - */ -void TIMER_OC1_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit) -{ - uint16_t tmpchctlrx = 0, tmpche = 0, tmpctlr2 = 0; - - /* Disable the Channel 1: Reset the CH1E Bit */ - TIMERx->CHE &= (uint16_t)(~(uint16_t)TIMER_CHE_CH1E); - - /* Get the TIMERx CHE register value */ - tmpche = TIMERx->CHE; - - /* Get the TIMERx CTLR2 register value */ - tmpctlr2 = TIMERx->CTLR2; - - /* Get the TIMERx CHCTLR1 register value */ - tmpchctlrx = TIMERx->CHCTLR1; - - /* Reset the Output Compare Mode Bits */ - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR1_CH1OM)); - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR1_CH1M)); - - /* Select the Output Compare Mode */ - tmpchctlrx |= TIMER_OCInit->TIMER_OCMode; - - /* Reset the Output Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH1P)); - - /* Set the Output Compare Polarity */ - tmpche |= TIMER_OCInit->TIMER_OCPolarity; - - /* Set the Output State */ - tmpche |= TIMER_OCInit->TIMER_OutputState; - - if ((TIMERx == TIMER0) || (TIMERx == TIMER7)) { - /* Reset the Output complementary Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH1NP)); - - /* Set the Output complementary Polarity */ - tmpche |= TIMER_OCInit->TIMER_OCNPolarity; - - /* Reset the Output complementary State */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH1NE)); - - /* Set the Output complementary State */ - tmpche |= TIMER_OCInit->TIMER_OutputNState; - - /* Reset the Ouput Compare and Output Compare complementary IDLE State */ - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO1)); - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO1N)); - - /* Set the Output Idle state */ - tmpctlr2 |= TIMER_OCInit->TIMER_OCIdleState; - - /* Set the Output complementary Idle state */ - tmpctlr2 |= TIMER_OCInit->TIMER_OCNIdleState; - } - - /* Write to TIMERx CTLR2 */ - TIMERx->CTLR2 = tmpctlr2; - - /* Write to TIMERx CHCTLR1 */ - TIMERx->CHCTLR1 = tmpchctlrx; - - /* Set the Capture / Compare Register value */ - TIMERx->CHCC1 = TIMER_OCInit->TIMER_Pulse; - - /* Write to TIMERx CHE */ - TIMERx->CHE = tmpche; -} - -/** - * @brief Initialize the TIMERx Channel2 with TIMER_OCInitPara . - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_OCInit : pointer to a TIMER_OCInitPara structure . - * @retval None - */ -void TIMER_OC2_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit) -{ - uint16_t tmpchctlrx = 0, tmpche = 0, tmpctlr2 = 0; - - /* Disable the Channel 2: Reset the CH2E Bit */ - TIMERx->CHE &= (uint16_t)(~((uint16_t)TIMER_CHE_CH2E)); - - /* Get the TIMERx CHE register value */ - tmpche = TIMERx->CHE; - - /* Get the TIMERx CTLR2 register value */ - tmpctlr2 = TIMERx->CTLR2; - - /* Get the TIMERx CHCTLR1 register value */ - tmpchctlrx = TIMERx->CHCTLR1; - - /* Reset the Output Compare Mode Bits */ - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR1_CH2OM)); - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR1_CH2M)); - - /* Select the Output Compare Mode */ - tmpchctlrx |= (uint16_t)(TIMER_OCInit->TIMER_OCMode << 8); - - /* Reset the Output Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH2P)); - - /* Set the Output Compare Polarity */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OCPolarity << 4); - - /* Set the Output State */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OutputState << 4); - - if ((TIMERx == TIMER0) || (TIMERx == TIMER7)) { - /* Reset the Output complementary Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH2NP)); - - /* Set the Output complementary Polarity */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OCNPolarity << 4); - - /* Reset the Output complementary State */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH2NE)); - - /* Set the Output complementary State */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OutputNState << 4); - - /* Reset the Ouput Compare and Output Compare complementary IDLE State */ - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO2)); - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO2N)); - - /* Set the Output Idle state */ - tmpctlr2 |= (uint16_t)(TIMER_OCInit->TIMER_OCIdleState << 2); - - /* Set the Output complementary Idle state */ - tmpctlr2 |= (uint16_t)(TIMER_OCInit->TIMER_OCNIdleState << 2); - } - - /* Write to TIMERx CTLR2 */ - TIMERx->CTLR2 = tmpctlr2; - - /* Write to TIMERx CHCTLR1 */ - TIMERx->CHCTLR1 = tmpchctlrx; - - /* Set the Capture / Compare Register value */ - TIMERx->CHCC2 = TIMER_OCInit->TIMER_Pulse; - - /* Write to TIMERx CHE */ - TIMERx->CHE = tmpche; -} - -/** - * @brief Initialize the TIMERx Channel3 with TIMER_OCInitPara . - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8} . - * @param TIMER_OCInit : pointer to a TIMER_OCInitPara structure . - * @retval None - */ -void TIMER_OC3_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit) -{ - uint16_t tmpchctlrx = 0, tmpche = 0, tmpctlr2 = 0; - - /* Disable the Channel 3: Reset the CH3E Bit */ - TIMERx->CHE &= (uint16_t)(~((uint16_t)TIMER_CHE_CH3E)); - - /* Get the TIMERx CHE register value */ - tmpche = TIMERx->CHE; - - /* Get the TIMERx CTLR2 register value */ - tmpctlr2 = TIMERx->CTLR2; - - /* Get the TIMERx CHCTLR2 register value */ - tmpchctlrx = TIMERx->CHCTLR2; - - /* Reset the Output Compare Mode Bits */ - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR2_CH3OM)); - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR2_CH3M)); - - /* Select the Output Compare Mode */ - tmpchctlrx |= TIMER_OCInit->TIMER_OCMode; - - /* Reset the Output Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH3P)); - - /* Set the Output Compare Polarity */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OCPolarity << 8); - - /* Set the Output State */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OutputState << 8); - - if ((TIMERx == TIMER0) || (TIMERx == TIMER7)) { - /* Reset the Output complementary Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH3NP)); - - /* Set the Output complementary Polarity */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OCNPolarity << 8); - - /* Reset the Output complementary State */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH3NE)); - - /* Set the Output complementary State */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OutputNState << 8); - - /* Reset the Ouput Compare and Output Compare complementary IDLE State */ - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO3)); - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO3N)); - - /* Set the Output Idle state */ - tmpctlr2 |= (uint16_t)(TIMER_OCInit->TIMER_OCIdleState << 4); - - /* Set the Output complementary Idle state */ - tmpctlr2 |= (uint16_t)(TIMER_OCInit->TIMER_OCNIdleState << 4); - } - /* Write to TIMERx CTLR2 */ - TIMERx->CTLR2 = tmpctlr2; - - /* Write to TIMERx CHCTLR2 */ - TIMERx->CHCTLR2 = tmpchctlrx; - - /* Set the Capture / Compare Register value */ - TIMERx->CHCC3 = TIMER_OCInit->TIMER_Pulse; - - /* Write to TIMERx CHE */ - TIMERx->CHE = tmpche; -} - -/** - * @brief Initialize the TIMERx Channel4 with TIMER_OCInitPara . - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8} . - * @param TIMER_OCInit : pointer to a TIMER_OCInitPara structure . - * @retval None - */ -void TIMER_OC4_Init(TIMER_TypeDef *TIMERx, TIMER_OCInitPara *TIMER_OCInit) -{ - uint16_t tmpchctlrx = 0, tmpche = 0, tmpctlr2 = 0; - - /* Disable the Channel 4: Reset the CH4E Bit */ - TIMERx->CHE &= (uint16_t)(~((uint16_t)TIMER_CHE_CH4E)); - - /* Get the TIMERx CHE register value */ - tmpche = TIMERx->CHE; - - /* Get the TIMERx CTLR2 register value */ - tmpctlr2 = TIMERx->CTLR2; - - /* Get the TIMERx CHCTLR2 register value */ - tmpchctlrx = TIMERx->CHCTLR2; - - /* Reset the Output Compare Mode Bits */ - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR2_CH4OM)); - tmpchctlrx &= (uint16_t)(~((uint16_t)TIMER_CHCTLR2_CH4M)); - - /* Select the Output Compare Mode */ - tmpchctlrx |= (uint16_t)(TIMER_OCInit->TIMER_OCMode << 8); - - /* Reset the Output Polarity */ - tmpche &= (uint16_t)(~((uint16_t)TIMER_CHE_CH4P)); - - /* Set the Output Compare Polarity */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OCPolarity << 12); - - /* Set the Output State */ - tmpche |= (uint16_t)(TIMER_OCInit->TIMER_OutputState << 12); - - if ((TIMERx == TIMER0) || (TIMERx == TIMER7)) { - /* Reset the Ouput Compare IDLE State */ - tmpctlr2 &= (uint16_t)(~((uint16_t)TIMER_CTLR2_ISO4)); - - /* Set the Output Idle state */ - tmpctlr2 |= (uint16_t)(TIMER_OCInit->TIMER_OCIdleState << 6); - } - - /* Write to TIMERx CTLR2 */ - TIMERx->CTLR2 = tmpctlr2; - - /* Write to TIMERx CHCTLR2 */ - TIMERx->CHCTLR2 = tmpchctlrx; - - /* Set the Capture Compare Register value */ - TIMERx->CHCC4 = TIMER_OCInit->TIMER_Pulse; - - /* Write to TIMERx CHE */ - TIMERx->CHE = tmpche; -} - -/** - * @brief Fill TIMER_OCInitPara member with default value. - * @param TIMER_OCInit: pointer to a TIMER_OCInitPara structure. - * @retval None - */ -void TIMER_OCStructInit(TIMER_OCInitPara *TIMER_OCInit) -{ - TIMER_OCInit->TIMER_OCMode = TIMER_OC_MODE_TIMING; - TIMER_OCInit->TIMER_OutputState = TIMER_OUTPUT_STATE_DISABLE; - TIMER_OCInit->TIMER_OutputNState = TIMER_OUTPUTN_STATE_DISABLE; - TIMER_OCInit->TIMER_Pulse = 0x0000000; - TIMER_OCInit->TIMER_OCPolarity = TIMER_OC_POLARITY_HIGH; - TIMER_OCInit->TIMER_OCNPolarity = TIMER_OC_POLARITY_HIGH; - TIMER_OCInit->TIMER_OCIdleState = TIMER_OC_IDLE_STATE_RESET; - TIMER_OCInit->TIMER_OCNIdleState = TIMER_OCN_IDLE_STATE_RESET; -} - -/** - * @brief Configure the TIMER Output Compare Mode. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_Ch: - * This value will be : - * @arg TIMER_CH_1 - * @arg TIMER_CH_2 - * @arg TIMER_CH_3 - * @arg TIMER_CH_4 - * @param TIMER_OCMode: the TIMER Output Compare Mode. - * This value will be : - * @arg TIMER_OC_MODE_TIMING - * @arg TIMER_OC_MODE_ACTIVE - * @arg TIMER_OC_MODE_TOGGLE - * @arg TIMER_OC_MODE_PWM1 - * @arg TIMER_OC_MODE_PWM2 - * @arg TIMER_FORCED_HIGH - * @arg TIMER_FORCED_LOW - * @retval None - */ -void TIMER_OCxModeConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_Ch, uint16_t TIMER_OCMode) -{ - uint32_t tmp = 0; - uint16_t tmp1 = 0; - - tmp = (uint32_t) TIMERx; - tmp += CHCTLR_OFFSET; - - tmp1 = CHE_CHE_SET << (uint16_t)TIMER_Ch; - - /* Disable the Channel: Reset the CHxE Bit */ - TIMERx->CHE &= (uint16_t) ~tmp1; - - if ((TIMER_Ch == TIMER_CH_1) || (TIMER_Ch == TIMER_CH_3)) { - tmp += (TIMER_Ch >> 1); - - /* Reset the CHxOM bits in the CHCTLRx register */ - *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIMER_CHCTLR1_CH1OM); - - /* Configure the CHxOM bits in the CHCTLRx register */ - *(__IO uint32_t *) tmp |= TIMER_OCMode; - } else { - tmp += (uint16_t)(TIMER_Ch - (uint16_t)4) >> (uint16_t)1; - - /* Reset the CHxOM bits in the CHCTLRx register */ - *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIMER_CHCTLR1_CH2OM); - - /* Configure the CHxOM bits in the CHCTLRx register */ - *(__IO uint32_t *) tmp |= (uint16_t)(TIMER_OCMode << 8); - } -} - -/** - * @brief Configure the TIMERx Capture or Compare Register value - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param CompValue1: the Capture / Compare1 register new value - * @retval None - */ -void TIMER_Compare1Config(TIMER_TypeDef *TIMERx, uint32_t CompValue1) -{ - TIMERx->CHCC1 = CompValue1 ; -} - -/** - * @brief Configure the TIMERx Capture or Compare Register value - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param CompValue2: the Capture / Compare1 register new value - * @retval None - */ -void TIMER_Compare2Config(TIMER_TypeDef *TIMERx, uint32_t CompValue2) -{ - TIMERx->CHCC2 = CompValue2; -} - -/** - * @brief Configure the TIMERx Capture or Compare Register value - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param CompValue3: the Capture / Compare1 register new value - * @retval None - */ -void TIMER_Compare3Config(TIMER_TypeDef *TIMERx, uint32_t CompValue3) -{ - TIMERx->CHCC3 = CompValue3; -} - -/** - * @brief Configure the TIMERx Capture or Compare Register value - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param CompValue4: the Capture / Compare1 register new value - * @retval None - */ -void TIMER_Compare4Config(TIMER_TypeDef *TIMERx, uint32_t CompValue4) -{ - TIMERx->CHCC4 = CompValue4; -} - -/** - * @brief Force the TIMERx output level to high or low - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_Forced: forced the output level. - * This value will be : - * @arg TIMER_FORCED_HIGH: Force output high level - * @arg TIMER_FORCED_LOW : Force output low level - * @retval None - */ -void TIMER_Forced_OC1(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH1OM Bits */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1OM); - - /* Configure The Forced output Mode */ - tmpchctlr1 |= TIMER_Forced ; - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief Force the TIMERx output level to high or low - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_Forced: forced the output level. - * This value will be : - * @arg TIMER_FORCED_HIGH: Force output high level - * @arg TIMER_FORCED_LOW : Force output low level - * @retval None - */ -void TIMER_Forced_OC2(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH2OM Bits */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2OM); - - /* Configure The Forced output Mode */ - tmpchctlr1 |= (uint16_t)(TIMER_Forced << 8); - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief Force the TIMERx output level to high or low - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_Forced: forced the output level. - * This value will be : - * @arg TIMER_FORCED_HIGH: Force output high level - * @arg TIMER_FORCED_LOW : Force output low level - * @retval None - */ -void TIMER_Forced_OC3(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH3OM Bits */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3OM); - - /* Configure The Forced output Mode */ - tmpchctlr2 |= TIMER_Forced ; - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief Force the TIMERx output level to high or low - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_Forced: forced the output level. - * This value will be : - * @arg TIMER_FORCED_HIGH: Force output high level - * @arg TIMER_FORCED_LOW : Force output low level - * @retval None - */ -void TIMER_Forced_OC4(TIMER_TypeDef *TIMERx, uint16_t TIMER_Forced) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH4OM Bits */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH4OM); - - /* Configure The Forced output Mode */ - tmpchctlr2 |= (uint16_t)(TIMER_Forced << 8); - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief Configure the TIMER Capture or Compare Preload Control bit - * @param TIMERx: x ={ 1 , 8 } . - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void TIMER_CC_PreloadControl(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Set the CCSE Bit */ - TIMERx->CTLR2 |= TIMER_CTLR2_CCSE; - } else { - /* Reset the CCSE Bit */ - TIMERx->CTLR2 &= (uint16_t)~((uint16_t)TIMER_CTLR2_CCSE); - } -} - -/** - * @brief Configure the TIMER channel 1 Capture or Compare Preload register - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_OCPreload : state of the TIMERx Preload register - * This value will be : - * @arg TIMER_OC_PRELOAD_ENABLE - * @arg TIMER_OC_PRELOAD_DISABLE - * @retval None - */ -void TIMER_OC1_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH1OSE Bit */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1OSE); - - /* Enable or Disable the Output Compare Preload */ - tmpchctlr1 |= TIMER_OCPreload; - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief Configure the TIMER channel 2 Capture or Compare Preload register - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_OCPreload : state of the TIMERx Preload register - * This value will be : - * @arg TIMER_OC_PRELOAD_ENABLE - * @arg TIMER_OC_PRELOAD_DISABLE - * @retval None - */ -void TIMER_OC2_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH2OSE Bit */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2OSE); - - /* Enable or Disable the Output Compare Preload */ - tmpchctlr1 |= (uint16_t)(TIMER_OCPreload << 8); - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief Configure the TIMER channel 3 Capture or Compare Preload register - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCPreload : state of the TIMERx Preload register - * This value will be : - * @arg TIMER_OC_PRELOAD_ENABLE - * @arg TIMER_OC_PRELOAD_DISABLE - * @retval None - */ -void TIMER_OC3_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH3OSE Bit */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3OSE); - - /* Enable or Disable the Output Compare Preload */ - tmpchctlr2 |= TIMER_OCPreload; - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief Configure the TIMER channel 4 Capture or Compare Preload register - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCPreload : state of the TIMERx Preload register - * This value will be : - * @arg TIMER_OC_PRELOAD_ENABLE - * @arg TIMER_OC_PRELOAD_DISABLE - * @retval None - */ -void TIMER_OC4_Preload(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPreload) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH4OSE Bit */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH4OSE); - - /* Enable or Disable the Output Compare Preload */ - tmpchctlr2 |= (uint16_t)(TIMER_OCPreload << 8); - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief Configure the TIMER channel 1 Compare output Fast mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_OCFast: state of the Compare Output Fast Enable Bit. - * This value will be : - * @arg TIMER_OC_FAST_ENABLE : output fast enable - * @arg TIMER_OC_FAST_DISABLE: output fast disable - * @retval None - */ -void TIMER_OC1_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH1OFE Bit */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1OFE); - - /* Enable or Disable the Output Compare Fast Bit */ - tmpchctlr1 |= TIMER_OCFast; - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief Configure the TIMER channel 2 Compare output Fast mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_OCFast: state of the Compare Output Fast Enable Bit. - * This value will be : - * @arg TIMER_OC_FAST_ENABLE : output fast enable - * @arg TIMER_OC_FAST_DISABLE: output fast disable - * @retval None - */ -void TIMER_OC2_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH2OFE Bit */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2OFE); - - /* Enable or Disable the Output Compare Fast Bit */ - tmpchctlr1 |= (uint16_t)(TIMER_OCFast << 8); - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief Configure the TIMER channel 3 Compare output Fast mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCFast: state of the Compare Output Fast Enable Bit. - * This value will be : - * @arg TIMER_OC_FAST_ENABLE : output fast enable - * @arg TIMER_OC_FAST_DISABLE: output fast disable - * @retval None - */ -void TIMER_OC3_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH3OFE Bit */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3OFE); - - /* Enable or Disable the Output Compare Fast Bit */ - tmpchctlr2 |= TIMER_OCFast; - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief Configure the TIMER channel 4 Compare output Fast mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCFast: state of the Compare Output Fast Enable Bit. - * This value will be : - * @arg TIMER_OC_FAST_ENABLE : output fast enable - * @arg TIMER_OC_FAST_DISABLE: output fast disable - * @retval None - */ -void TIMER_OC4_FastConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCFast) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH4OFE Bit */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH4OFE); - - /* Enable or Disable the Output Compare Fast Bit */ - tmpchctlr2 |= (uint16_t)(TIMER_OCFast << 8); - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief If Clear the OCREF signal on an external event - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_OCClear: new state of the Output Compare Clear Enable Bit. - * This value will be : - * @arg TIMER_OC_CLEAR_ENABLE : Output clear enable - * @arg TIMER_OC_CLEAR_DISABLE: Output clear disable - * @retval None - */ -void TIMER_OC1_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the CH1OCE Bit */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1OCE); - - /* Enable or Disable the Output Compare Clear Bit */ - tmpchctlr1 |= TIMER_OCClear; - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief If Clear the OCREF signal on an external event - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_OCClear: new state the Output Compare Clear Enable Bit. - * This value will be : - * @arg TIMER_OC_CLEAR_ENABLE : Output clear enable - * @arg TIMER_OC_CLEAR_DISABLE: Output clear disable - * @retval None - */ -void TIMER_OC2_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear) -{ - uint16_t tmpchctlr1 = 0; - - tmpchctlr1 = TIMERx->CHCTLR1; - - /* Reset the OC2CE Bit */ - tmpchctlr1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2OCE); - - /* Enable or Disable the Output Compare Clear Bit */ - tmpchctlr1 |= (uint16_t)(TIMER_OCClear << 8); - - TIMERx->CHCTLR1 = tmpchctlr1; -} - -/** - * @brief If Clear the OCREF signal on an external event - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCClear: new state the Output Compare Clear Enable Bit. - * This value will be : - * @arg TIMER_OC_CLEAR_ENABLE : Output clear enable - * @arg TIMER_OC_CLEAR_DISABLE: Output clear disable - * @retval None - */ -void TIMER_OC3_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the CH3OCE Bit */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3OCE); - - /* Enable or Disable the Output Compare Clear Bit */ - tmpchctlr2 |= TIMER_OCClear; - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief If Clear the OCREF signal on an external event - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCClear: new state the Output Compare Clear Enable Bit. - * This value will be : - * @arg TIMER_OC_CLEAR_ENABLE : Output clear enable - * @arg TIMER_OC_CLEAR_DISABLE: Output clear disable - * @retval None - */ -void TIMER_OC4_RefClear(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCClear) -{ - uint16_t tmpchctlr2 = 0; - - tmpchctlr2 = TIMERx->CHCTLR2; - - /* Reset the OC4CE Bit */ - tmpchctlr2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH4OCE); - - /* Enable or Disable the Output Compare Clear Bit */ - tmpchctlr2 |= (uint16_t)(TIMER_OCClear << 8); - - TIMERx->CHCTLR2 = tmpchctlr2; -} - -/** - * @brief Configure the TIMERx channel 1 polarity. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_OCPolarity : - * This value will be : - * @arg TIMER_OC_POLARITY_HIGH: active high - * @arg TIMER_OC_POLARITY_LOW : active low - * @retval None - */ -void TIMER_OC1_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configures the CH1P Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH1P); - tmpche |= TIMER_OCPolarity; - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TIMERx Channel 1 complementary polarity. - * @param TIMERx: x ={ 1 , 8 } . - * @param TIMER_OCNPolarity: - * This value will be : - * @arg TIMER_OCN_POLARITY_HIGH: active high - * @arg TIMER_OCN_POLARITY_LOW: active low - * @retval None - */ -void TIMER_OC1N_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCNPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configures the CH1NP Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH1NP); - tmpche |= TIMER_OCNPolarity; - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TIMERx channel 2 polarity. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_OCPolarity : - * This value will be : - * @arg TIMER_OC_POLARITY_HIGH: active high - * @arg TIMER_OC_POLARITY_LOW : active low - * @retval None - */ -void TIMER_OC2_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configure the CH2P Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH2P); - tmpche |= (uint16_t)(TIMER_OCPolarity << 4); - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TIMERx Channel 2 complementary polarity. - * @param TIMERx: x ={ 1 , 8 } . - * @param TIMER_OCNPolarity: - * This value will be : - * @arg TIMER_OCN_POLARITY_HIGH: active high - * @arg TIMER_OCN_POLARITY_LOW: active low - * @retval None - */ -void TIMER_OC2N_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCNPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configure the CH2NP Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH2NP); - tmpche |= (uint16_t)(TIMER_OCNPolarity << 4); - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TIMERx channel 3 polarity. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCPolarity : - * This value will be : - * @arg TIMER_OC_POLARITY_HIGH: active high - * @arg TIMER_OC_POLARITY_LOW : active low - * @retval None - */ -void TIMER_OC3_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configure the CH3P Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH3P); - tmpche |= (uint16_t)(TIMER_OCPolarity << 8); - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TIMERx Channel 3 complementary polarity. - * @param TIMERx: x ={ 1 , 8 } . - * @param TIMER_OCNPolarity: - * This value will be : - * @arg TIMER_OCN_POLARITY_HIGH: active high - * @arg TIMER_OCN_POLARITY_LOW : active low - * @retval None - */ -void TIMER_OC3N_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCNPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configure the CH3NP Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH3NP); - tmpche |= (uint16_t)(TIMER_OCNPolarity << 8); - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TIMERx channel 4 polarity. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_OCPolarity : - * This value will be : - * @arg TIMER_OC_POLARITY_HIGH: active high - * @arg TIMER_OC_POLARITY_LOW : active low - * @retval None - */ -void TIMER_OC4_Polarity(TIMER_TypeDef *TIMERx, uint16_t TIMER_OCPolarity) -{ - uint16_t tmpche = 0; - - tmpche = TIMERx->CHE; - - /* Configure the CH4P Bit */ - tmpche &= (uint16_t)~((uint16_t)TIMER_CHE_CH4P); - tmpche |= (uint16_t)(TIMER_OCPolarity << 12); - - - TIMERx->CHE = tmpche; -} - -/** - * @brief Turn-on or off the Channel x Capture or Compare . - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_Ch: - * This value will be : - * @arg TIMER_CH_1: - * @arg TIMER_CH_2: - * @arg TIMER_CH_3: - * @arg TIMER_CH_4: - * @param TIMER_CCx: the TIMER Channel CCxE bit new value. - * This value will be: - * @arg TIMER_CCX_ENABLE - * @arg TIMER_CCX_DISABLE - * @retval None - */ -void TIMER_CCxCmd(TIMER_TypeDef *TIMERx, uint16_t TIMER_Ch, uint16_t TIMER_CCx) -{ - uint16_t tmp = 0; - - tmp = CHE_CHE_SET << TIMER_Ch; - - /* Reset the CCx Bit */ - TIMERx->CHE &= (uint16_t)~ tmp; - - /* Configure the CCx Bit */ - TIMERx->CHE |= (uint16_t)(TIMER_CCx << TIMER_Ch); -} - -/** - * @brief Turn-on or off the Channel x complementary Capture or Compare - * @param TIMERx: x ={ 1 , 8 } . - * @param TIMER_Ch: - * This value will be : - * @arg TIMER_CH_1: - * @arg TIMER_CH_2: - * @arg TIMER_CH_3: - * @param TIMER_CCxN: the Channel CCxN bit new value. - * This value will be: - * @arg TIMER_CCXN_ENABLE - * @arg TIMER_CCXN_DISABLE - * @retval None - */ -void TIMER_CCxNCmd(TIMER_TypeDef *TIMERx, uint16_t TIMER_Ch, uint16_t TIMER_CCxN) -{ - uint16_t tmp = 0; - - tmp = CHE_CHNE_SET << TIMER_Ch; - - /* Reset the CCxN Bit */ - TIMERx->CHE &= (uint16_t) ~tmp; - - /* Configure the CCxN Bit */ - TIMERx->CHE |= (uint16_t)(TIMER_CCxN << TIMER_Ch); -} - -/** - * @brief Select control shadow register update control. - * @param TIMERx: x ={ 1, 8 } . - * @param NewState: ENABLE or DISABLE. - * @retval None - */ -void TIMER_SelectCOM(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - - if (NewValue != DISABLE) { - /* Set the CCUC Bit */ - TIMERx->CTLR2 |= TIMER_CTLR2_CCUC; - } else { - /* Reset the CCUC Bit */ - TIMERx->CTLR2 &= (uint16_t)~((uint16_t)TIMER_CTLR2_CCUC); - } -} - -/** - * @brief Initialize the Input Capture parameters of the timer - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_ICInit: pointer to a TIMER_ICInitPara structure - * @retval None - */ -void TIMER_ICInit(TIMER_TypeDef *TIMERx, TIMER_ICInitPara *TIMER_ICInit) -{ - - if (TIMER_ICInit->TIMER_CH == TIMER_CH_1) { - TI1_Config(TIMERx, TIMER_ICInit->TIMER_ICPolarity, - TIMER_ICInit->TIMER_ICSelection, - TIMER_ICInit->TIMER_ICFilter); - - /* Set the Input Capture Prescaler value */ - TIMER_Set_IC1_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - } else if (TIMER_ICInit->TIMER_CH == TIMER_CH_2) { - TI2_Config(TIMERx, TIMER_ICInit->TIMER_ICPolarity, - TIMER_ICInit->TIMER_ICSelection, - TIMER_ICInit->TIMER_ICFilter); - - /* Set the Input Capture Prescaler value */ - TIMER_Set_IC2_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - } else if (TIMER_ICInit->TIMER_CH == TIMER_CH_3) { - TI3_Config(TIMERx, TIMER_ICInit->TIMER_ICPolarity, - TIMER_ICInit->TIMER_ICSelection, - TIMER_ICInit->TIMER_ICFilter); - - /* Set the Input Capture Prescaler value */ - TIMER_Set_IC3_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - } else { - TI4_Config(TIMERx, TIMER_ICInit->TIMER_ICPolarity, - TIMER_ICInit->TIMER_ICSelection, - TIMER_ICInit->TIMER_ICFilter); - - /* Set the Input Capture Prescaler value */ - TIMER_Set_IC4_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - } -} - -/** - * @brief Fill TIMER_ICInitPara member with default value. - * @param TIMER_ICInit : pointer to a TIMER_ICInitPara structure - * @retval None - */ -void TIMER_ICStructInit(TIMER_ICInitPara *TIMER_ICInit) -{ - TIMER_ICInit->TIMER_CH = TIMER_CH_1; - TIMER_ICInit->TIMER_ICPolarity = TIMER_IC_POLARITY_RISING; - TIMER_ICInit->TIMER_ICSelection = TIMER_IC_SELECTION_DIRECTTI; - TIMER_ICInit->TIMER_ICPrescaler = TIMER_IC_PSC_DIV1; - TIMER_ICInit->TIMER_ICFilter = 0x00; -} - -/** - * @brief Configure the TIMER PWM input Capture mode parameters - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_ICInit: pointer to a TIMER_ICInitPara structure - * @retval None - */ -void TIMER_PWMCaptureConfig(TIMER_TypeDef *TIMERx, TIMER_ICInitPara *TIMER_ICInit) -{ - uint16_t icoppositepolarity = TIMER_IC_POLARITY_RISING; - uint16_t icoppositeselection = TIMER_IC_SELECTION_DIRECTTI; - - /* Select the Opposite Input Polarity */ - if (TIMER_ICInit->TIMER_ICPolarity == TIMER_IC_POLARITY_RISING) { - icoppositepolarity = TIMER_IC_POLARITY_FALLING; - } else { - icoppositepolarity = TIMER_IC_POLARITY_RISING; - } - - /* Select the Opposite Input */ - if (TIMER_ICInit->TIMER_ICSelection == TIMER_IC_SELECTION_DIRECTTI) { - icoppositeselection = TIMER_IC_SELECTION_INDIRECTTI; - } else { - icoppositeselection = TIMER_IC_SELECTION_DIRECTTI; - } - - if (TIMER_ICInit->TIMER_CH == TIMER_CH_1) { - TI1_Config(TIMERx, TIMER_ICInit->TIMER_ICPolarity, - TIMER_ICInit->TIMER_ICSelection, - TIMER_ICInit->TIMER_ICFilter); - - TIMER_Set_IC1_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - - TI2_Config(TIMERx, icoppositepolarity, icoppositeselection, TIMER_ICInit->TIMER_ICFilter); - - TIMER_Set_IC2_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - } else { - TI2_Config(TIMERx, TIMER_ICInit->TIMER_ICPolarity, - TIMER_ICInit->TIMER_ICSelection, - TIMER_ICInit->TIMER_ICFilter); - - TIMER_Set_IC2_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - - TI1_Config(TIMERx, icoppositepolarity, icoppositeselection, TIMER_ICInit->TIMER_ICFilter); - - TIMER_Set_IC1_Prescaler(TIMERx, TIMER_ICInit->TIMER_ICPrescaler); - } -} - -/** - * @brief Read the TIMERx Input Capture value. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @retval None - */ -uint32_t TIMER_GetCapture1(TIMER_TypeDef *TIMERx) -{ - return TIMERx->CHCC1; -} - -/** - * @brief Read the TIMERx Input Capture value. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @retval None - */ -uint32_t TIMER_GetCapture2(TIMER_TypeDef *TIMERx) -{ - return TIMERx->CHCC2; -} - -/** - * @brief Read the TIMERx Input Capture value. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @retval None - */ -uint32_t TIMER_GetCapture3(TIMER_TypeDef *TIMERx) -{ - return TIMERx->CHCC3; -} - -/** - * @brief Read the TIMERx Input Capture value. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @retval None - */ -uint32_t TIMER_GetCapture4(TIMER_TypeDef *TIMERx) -{ - return TIMERx->CHCC4; -} - -/** - * @brief Configure the TIMERx Input Capture prescaler. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_ICPSC: the Input Capture1 prescaler value. - * This value will be : - * @arg TIMER_IC_PSC_DIV1: no prescaler - * @arg TIMER_IC_PSC_DIV2: divided by 2 - * @arg TIMER_IC_PSC_DIV4: divided by 4 - * @arg TIMER_IC_PSC_DIV8: divided by 8 - * @retval None - */ -void TIMER_Set_IC1_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC) -{ - TIMERx->CHCTLR1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1ICP); - - TIMERx->CHCTLR1 |= TIMER_ICPSC; -} - -/** - * @brief Configure the TIMERx Input Capture prescaler. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_ICPSC: the Input Capture1 prescaler value. - * This value will be : - * @arg TIMER_IC_PSC_DIV1: no prescaler - * @arg TIMER_IC_PSC_DIV2: divided by 2 - * @arg TIMER_IC_PSC_DIV4: divided by 4 - * @arg TIMER_IC_PSC_DIV8: divided by 8 - * @retval None - */ -void TIMER_Set_IC2_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC) -{ - TIMERx->CHCTLR1 &= (uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2ICP); - - TIMERx->CHCTLR1 |= (uint16_t)(TIMER_ICPSC << 8); -} - -/** - * @brief Configure the TIMERx Input Capture prescaler. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ICPSC: the Input Capture1 prescaler value. - * This value will be : - * @arg TIMER_IC_PSC_DIV1: no prescaler - * @arg TIMER_IC_PSC_DIV2: divided by 2 - * @arg TIMER_IC_PSC_DIV4: divided by 4 - * @arg TIMER_IC_PSC_DIV8: divided by 8 - * @retval None - */ -void TIMER_Set_IC3_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC) -{ - TIMERx->CHCTLR2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3ICP); - - TIMERx->CHCTLR2 |= TIMER_ICPSC; -} - -/** - * @brief Configure the TIMERx Input Capture prescaler. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ICPSC: the Input Capture1 prescaler value. - * This value will be : - * @arg TIMER_IC_PSC_DIV1: no prescaler - * @arg TIMER_IC_PSC_DIV2: divided by 2 - * @arg TIMER_IC_PSC_DIV4: divided by 4 - * @arg TIMER_IC_PSC_DIV8: divided by 8 - * @retval None - */ -void TIMER_Set_IC4_Prescaler(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPSC) -{ - TIMERx->CHCTLR2 &= (uint16_t)~((uint16_t)TIMER_CHCTLR2_CH4ICP); - - TIMERx->CHCTLR2 |= (uint16_t)(TIMER_ICPSC << 8); -} - -/** - * @brief Configure interrupts Enables - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_INT: the interrupts sources to Configure. - * This value will be : - * @arg TIMER_INT_UPDATE : update Interrupt - * @arg TIMER_INT_CH1 : Channel 1 Capture or Compare Interrupt - * @arg TIMER_INT_CH2 : Channel 2 Capture or Compare Interrupt - * @arg TIMER_INT_CH3 : Channel 3 Capture or Compare Interrupt - * @arg TIMER_INT_CH4 : Channel 4 Capture or Compare Interrupt - * @arg TIMER_INT_CCUG : Commutation Interrupt - * @arg TIMER_INT_TRIGGER : Trigger Interrupt - * @arg TIMER_INT_BREAK : Break Interrupt - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void TIMER_INTConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_INT, TypeState NewValue) -{ - if (NewValue != DISABLE) { - TIMERx->DIE |= TIMER_INT; - } else { - TIMERx->DIE &= (uint16_t)~TIMER_INT; - } -} - -/** - * @brief Generate the software event - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_EventSrc: - * This value will be : - * @arg TIMER_EVENT_SRC_UPDATE : update Event - * @arg TIMER_EVENT_SRC_CH1 : Channel 1 Capture or Compare Event - * @arg TIMER_EVENT_SRC_CH2 : Channel 2 Capture or Compare Event - * @arg TIMER_EVENT_SRC_CH3 : Channel 3 Capture or Compare Event - * @arg TIMER_EVENT_SRC_CH4 : Channel 4 Capture or Compare Event - * @arg TIMER_EVENT_SRC_COM : COM event - * @arg TIMER_EVENT_SRC_TRIGGER : Trigger Event - * @arg TIMER_EVENT_SRC_BREAK : Break event - * @retval None - */ -void TIMER_GenerateEvent(TIMER_TypeDef *TIMERx, uint16_t TIMER_EventSrc) -{ - TIMERx->EVG = TIMER_EventSrc; -} - -/** - * @brief Get current flag status - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_FLAG: - * This value will be : - * @arg TIMER_FLAG_UPDATE : update Flag - * @arg TIMER_FLAG_CH1 : Channel 1 Capture or Compare Flag - * @arg TIMER_FLAG_CH2 : Channel 2 Capture or Compare Flag - * @arg TIMER_FLAG_CH3 : Channel 3 Capture or Compare Flag - * @arg TIMER_FLAG_CH4 : Channel 4 Capture or Compare Flag - * @arg TIMER_FLAG_COM : Commutation Flag - * @arg TIMER_FLAG_TRIGGER : Trigger Flag - * @arg TIMER_FLAG_BREAK : Break Flag - * @arg TIMER_FLAG_CH1OF : Channel 1 Capture or Compare overcapture Flag - * @arg TIMER_FLAG_CH2OF : Channel 2 Capture or Compare overcapture Flag - * @arg TIMER_FLAG_CH3OF : Channel 3 Capture or Compare overcapture Flag - * @arg TIMER_FLAG_CH4OF : Channel 4 Capture or Compare overcapture Flag - * @retval The state of TIMER_FLAG ( SET or RESET ). - */ -TypeState TIMER_GetBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_FLAG) -{ - if ((TIMERx->STR & TIMER_FLAG) != (uint16_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the flags - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_FLAG: the flag bit to clear. - * This value will be : - * @arg TIMER_FLAG_UPDATE : update Flag - * @arg TIMER_FLAG_CH1 : Channel 1 Capture or Compare Flag - * @arg TIMER_FLAG_CH2 : Channel 2 Capture or Compare Flag - * @arg TIMER_FLAG_CH3 : Channel 3 Capture or Compare Flag - * @arg TIMER_FLAG_CH4 : Channel 4 Capture or Compare Flag - * @arg TIMER_FLAG_COM : Commutation Flag - * @arg TIMER_FLAG_TRIGGER : Trigger Flag - * @arg TIMER_FLAG_BREAK : Break Flag - * @arg TIMER_FLAG_CH1OF : Channel 1 Capture or Compare overcapture Flag - * @arg TIMER_FLAG_CH2OF : Channel 2 Capture or Compare overcapture Flag - * @arg TIMER_FLAG_CH3OF : Channel 3 Capture or Compare overcapture Flag - * @arg TIMER_FLAG_CH4OF : Channel 4 Capture or Compare overcapture Flag - * @retval None - */ -void TIMER_ClearBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_FLAG) -{ - TIMERx->STR = (uint16_t)~TIMER_FLAG; -} - -/** - * @brief Get interrupt state - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_INT: - * This value will be : - * @arg TIMER_INT_UPDATE: update Interrupt - * @arg TIMER_INT_CH1 : Channel 1 Capture or Compare Interrupt - * @arg TIMER_INT_CH2 : Channel 2 Capture or Compare Interrupt - * @arg TIMER_INT_CH3 : Channel 3 Capture or Compare Interrupt - * @arg TIMER_INT_CH4 : Channel 4 Capture or Compare Interrupt - * @arg TIMER_INT_CCUG : Commutation Interrupt - * @arg TIMER_INT_TRIGGER : Trigger Interrupt - * @arg TIMER_INT_BREAK : Break Interrupt - * @retval The new state of the TIMER_INT(SET or RESET). - */ -TypeState TIMER_GetIntBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_INT) -{ - uint16_t TypeState = 0x0, itenable = 0x0; - - TypeState = TIMERx->STR & TIMER_INT; - itenable = TIMERx->DIE & TIMER_INT; - - if ((TypeState != (uint16_t)RESET) && (itenable != (uint16_t)RESET)) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the interrupt pending bits - * @param TIMERx: x ={ 0-13 } . - * @param TIMER_INT: - * This value will be : - * @arg TIMER_INT_UPDATE: update Interrupt - * @arg TIMER_INT_CH1 : Channel 1 Capture or Compare Interrupt - * @arg TIMER_INT_CH2 : Channel 2 Capture or Compare Interrupt - * @arg TIMER_INT_CH3 : Channel 3 Capture or Compare Interrupt - * @arg TIMER_INT_CH4 : Channel 4 Capture or Compare Interrupt - * @arg TIMER_INT_CCUG : Commutation Interrupt - * @arg TIMER_INT_TRIGGER : Trigger Interrupt - * @arg TIMER_INT_BREAK : Break Interrupt - * @retval None - */ -void TIMER_ClearIntBitState(TIMER_TypeDef *TIMERx, uint16_t TIMER_INT) -{ - TIMERx->STR = (uint16_t)~TIMER_INT; -} - -/** - * @brief Configure the DMA . - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_DMABase: DMA Base address. - * This value will be : - * @arg TIMER_DMA_BASE_ADDR_CTLR1 - * @arg TIMER_DMA_BASE_ADDR_CTLR2 - * @arg TIMER_DMA_BASE_ADDR_SMC - * @arg TIMER_DMA_BASE_ADDR_DIE - * @arg TIMER_DMA_BASE_ADDR_STR - * @arg TIMER_DMA_BASE_ADDR_EVG - * @arg TIMER_DMA_BASE_ADDR_CHCTLR1 - * @arg TIMER_DMA_BASE_ADDR_CHCTLR2 - * @arg TIMER_DMA_BASE_ADDR_CHE - * @arg TIMER_DMA_BASE_ADDR_CNT - * @arg TIMER_DMA_BASE_ADDR_PSC - * @arg TIMER_DMA_BASE_ADDR_CARL - * @arg TIMER_DMA_BASE_ADDR_CREP - * @arg TIMER_DMA_BASE_ADDR_CHCC1 - * @arg TIMER_DMA_BASE_ADDR_CHCC2 - * @arg TIMER_DMA_BASE_ADDR_CHCC3 - * @arg TIMER_DMA_BASE_ADDR_CHCC4 - * @arg TIMER_DMA_BASE_ADDR_BKDT - * @arg TIMER_DMA_BASE_ADDR_DCTLR - * @arg TIMER_DMA_BASE_ADDR_DTRSF - * @param TIMER_DMABurstLength: DMA Burst length. - * This value will be : - * [ TIMER_DMA_BURST_1TRANSFER , TIMER_DMA_BURST_18TRANSFERS ] - * @retval None - */ -void TIMER_DMAConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_DMABase, uint16_t TIMER_DMABurstLength) -{ - TIMERx->DCTLR = TIMER_DMABase | TIMER_DMABurstLength; -} - -/** - * @brief Configure the TIMERx's DMA Requests - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } . - * @param TIMER_DMASrc: the DMA Request sources. - * This value will be : - * @arg TIMER_DMA_UPDATE : update start DMA - * @arg TIMER_DMA_CH1 : Channel 1 Capture or Compare start DMA - * @arg TIMER_DMA_CH2 : Channel 2 Capture or Compare start DMA - * @arg TIMER_DMA_CH3 : Channel 3 Capture or Compare start DMA - * @arg TIMER_DMA_CH4 : Channel 4 Capture or Compare start DMA - * @arg TIMER_DMA_COM : Commutation DMA - * @arg TIMER_DMA_TRIGGER : Trigger DMA - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void TIMER_DMACmd(TIMER_TypeDef *TIMERx, uint16_t TIMER_DMASrc, TypeState NewValue) -{ - if (NewValue != DISABLE) { - /* Enable the DMA */ - TIMERx->DIE |= TIMER_DMASrc; - } else { - /* Disable the DMA */ - TIMERx->DIE &= (uint16_t)~TIMER_DMASrc; - } -} - -/** - * @brief Select the Capture or Compare DMA source - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param NewValue: ENABLE or DISABLE - * @retval None - */ -void TIMER_CC_DMA(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - TIMERx->CTLR2 |= TIMER_CTLR2_DMAS; - } else { - TIMERx->CTLR2 &= (uint16_t)~((uint16_t)TIMER_CTLR2_DMAS); - } -} - -/** - * @brief Configure the internal Clock - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } - * @retval None - */ -void TIMER_InternalClockConfig(TIMER_TypeDef *TIMERx) -{ - TIMERx->SMC &= (uint16_t)(~((uint16_t)TIMER_SMC_SMC)); -} - -/** - * @brief Configure the Internal Trigger as External Input Clock - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_InputTriSrc: - * This value will be : - * @arg TIMER_TS_ITR0 : Internal Trigger 0 - * @arg TIMER_TS_ITR1 : Internal Trigger 1 - * @arg TIMER_TS_ITR2 : Internal Trigger 2 - * @arg TIMER_TS_ITR3 : Internal Trigger 3 - * @retval None - */ -void TIMER_ITRxExtClock(TIMER_TypeDef *TIMERx, uint16_t TIMER_InputTriSrc) -{ - /* Select the Internal Trigger */ - TIMER_SelectInputTrigger(TIMERx, TIMER_InputTriSrc); - - /* Select the External clock mode1 */ - TIMERx->SMC |= TIMER_SLAVE_MODE_EXTERNAL1; -} - -/** - * @brief Configure the External Trigger as External Input Clock - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_TIxExCLKSrc: Trigger source. - * This value will be : - * @arg TIMER_TIX_EXCLK1_SRC_TI1ED : TI1 Edge Detector - * @arg TIMER_TIX_EXCLK1_SRC_TI1 : Filtered Timer Input 1 - * @arg TIMER_TIX_EXCLK1_SRC_TI2 : Filtered Timer Input 2 - * @param TIMER_ICPolarity: - * This value will be : - * @arg TIMER_IC_POLARITY_RISING - * @arg TIMER_IC_POLARITY_FALLING - * @param ICFilter: specifies the filter value. - * This parameter must be a value between 0x0 and 0xF. - * @retval None - */ -void TIMER_TIxExtCLkConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_TIxExCLKSrc, - uint16_t TIMER_ICPolarity, uint16_t ICFilter) -{ - /* Select the Input Clock Source */ - if (TIMER_TIxExCLKSrc == TIMER_TIX_EXCLK1_SRC_TI2) { - TI2_Config(TIMERx, TIMER_ICPolarity, TIMER_IC_SELECTION_DIRECTTI, ICFilter); - } else { - TI1_Config(TIMERx, TIMER_ICPolarity, TIMER_IC_SELECTION_DIRECTTI, ICFilter); - } - - /* Select the Trigger source */ - TIMER_SelectInputTrigger(TIMERx, TIMER_TIxExCLKSrc); - - /* Enter the External clock mode1 */ - TIMERx->SMC |= TIMER_SLAVE_MODE_EXTERNAL1; -} - -/** - * @brief Configure the External clock Mode1 - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ExtTriPrescaler: The external Trigger Prescaler. - * This value will be : - * @arg TIMER_EXT_TRI_PSC_OFF: no divided. - * @arg TIMER_EXT_TRI_PSC_DIV2: divided by 2. - * @arg TIMER_EXT_TRI_PSC_DIV4: divided by 4. - * @arg TIMER_EXT_TRI_PSC_DIV8: divided by 8. - * @param TIMER_ExtTriPolarity: Trigger Polarity. - * This value will be : - * @arg TIMER_EXT_TRI_POLARITY_INVERTED : active low or falling edge active. - * @arg TIMER_EXT_TRI_POLARITY_NONINVERTED: active high or rising edge active. - * @param ExtTriFilter: External Trigger Filter. - * This parameter must be a value between 0x00 and 0x0F - * @retval None - */ -void TIMER_ETRClockMode1Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ExTriPrescaler, uint16_t TIMER_ExTriPolarity, - uint16_t ExtTriFilter) -{ - uint16_t tmpsmc = 0; - - /* Configure the external Trigger Clock source */ - TIMER_ETRConfig(TIMERx, TIMER_ExTriPrescaler, TIMER_ExTriPolarity, ExtTriFilter); - - /* Get the TIMERx SMC register value */ - tmpsmc = TIMERx->SMC; - - tmpsmc &= (uint16_t)(~((uint16_t)TIMER_SMC_SMC)); - - /* Select the External clock mode1 */ - tmpsmc |= TIMER_SLAVE_MODE_EXTERNAL1; - - /* Select the Trigger selection : ETRF */ - tmpsmc &= (uint16_t)(~((uint16_t)TIMER_SMC_TRGS)); - tmpsmc |= TIMER_TS_ETRF; - - TIMERx->SMC = tmpsmc; -} - -/** - * @brief Configure the External clock Mode2 - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ExtTriPrescaler: The external Trigger Prescaler. - * This value will be : - * @arg TIMER_EXT_TRI_PSC_OFF: no divided. - * @arg TIMER_EXT_TRI_PSC_DIV2: divided by 2. - * @arg TIMER_EXT_TRI_PSC_DIV4: divided by 4. - * @arg TIMER_EXT_TRI_PSC_DIV8: divided by 8. - * @param TIMER_ExtTriPolarity: Trigger Polarity. - * This value will be : - * @arg TIMER_EXT_TRI_POLARITY_INVERTED : active low or falling edge active. - * @arg TIMER_EXT_TRI_POLARITY_NONINVERTED: active high or rising edge active. - * @param ExtTriFilter: External Trigger Filter. - * This parameter must be a value between 0x00 and 0x0F - * @retval None - */ -void TIMER_ETRClockMode2Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ExTriPrescaler, - uint16_t TIMER_ExTriPolarity, uint16_t ExtTriFilter) -{ - /* Configure the ETR Clock source */ - TIMER_ETRConfig(TIMERx, TIMER_ExTriPrescaler, TIMER_ExTriPolarity, ExtTriFilter); - - /* Select the External clock mode2 */ - TIMERx->SMC |= TIMER_SMC_ECM2E; -} - -/** - * @brief Select the Input Trigger source - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_InputTriSrc: The Input Trigger source. - * This value will be : - * @arg TIMER_TS_ITR0 : Internal Trigger 0 - * @arg TIMER_TS_ITR1 : Internal Trigger 1 - * @arg TIMER_TS_ITR2 : Internal Trigger 2 - * @arg TIMER_TS_ITR3 : Internal Trigger 3 - * @arg TIMER_TS_TI1F_ED : TI1 Edge Detector - * @arg TIMER_TS_TI1FP1 : Filtered Timer Input 1 - * @arg TIMER_TS_TI2FP2 : Filtered Timer Input 2 - * @arg TIMER_TS_ETRF : External Trigger input - * @retval None - */ -void TIMER_SelectInputTrigger(TIMER_TypeDef *TIMERx, uint16_t TIMER_InputTriSrc) -{ - uint16_t tmpsmc = 0; - - tmpsmc = TIMERx->SMC; - - /* Reset the TS Bits */ - tmpsmc &= (uint16_t)(~((uint16_t)TIMER_SMC_TRGS)); - - /* Set the Input Trigger source */ - tmpsmc |= TIMER_InputTriSrc ; - - TIMERx->SMC = tmpsmc; -} - -/** - * @brief Configure the TIMERx Trigger Output Mode. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,10 , 11 , 13 , 14} . - * @param TIMER_TriOutSrc: - * This value will be : - * @arg TIMER_TRI_OUT_SRC_RESET : The UPG bit in the TIMERx_EVG register as TriO. - * @arg TIMER_TRI_OUT_SRC_ENABLE : The CEN bit in TIMERx_CTLR1 as TriO. - * @arg TIMER_TRI_OUT_SRC_UPDATE : Update event as TriO. - * @arg TIMER_TRI_OUT_SRC_OC1 : capture or compare match ( CC1IF bit set ) as TriO. - * @arg TIMER_TRI_OUT_SRC_OC1REF : OC1REF as TriO. - * @arg TIMER_TRI_OUT_SRC_OC2REF : OC2REF as TriO. - * @arg TIMER_TRI_OUT_SRC_OC3REF : OC3REF as TriO. - * @arg TIMER_TRI_OUT_SRC_OC4REF : OC4REF as TriO. - * @retval None - */ -void TIMER_SelectOutputTrigger(TIMER_TypeDef *TIMERx, uint16_t TIMER_TriOutSrc) -{ - /* Reset the MMC Bits */ - TIMERx->CTLR2 &= (uint16_t)~((uint16_t)TIMER_CTLR2_MMC); - - /* Configures the TriO source */ - TIMERx->CTLR2 |= TIMER_TriOutSrc; -} - -/** - * @brief Configure the TIMERx Slave Mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_SlaveMode: - * This value will be : - * @arg TIMER_SLAVE_MODE_RESET : The trigger signal reset the timer - * @arg TIMER_SLAVE_MODE_GATED : The trigger signal enable the counter when high. - * @arg TIMER_SLAVE_MODE_TRIGGER : The trigger signal starts the counter. - * @arg TIMER_SLAVE_MODE_EXTERNAL1 : The trigger signal as a counter clock. - * @retval None - */ -void TIMER_SelectSlaveMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_SlaveMode) -{ - /* Reset the SMC Bits */ - TIMERx->SMC &= (uint16_t)~((uint16_t)TIMER_SMC_SMC); - - /* Configure the Slave Mode */ - TIMERx->SMC |= TIMER_SlaveMode; -} - -/** - * @brief Configure the TIMERx Master or Slave Mode - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 10 , 11 , 13 , 14} . - * @param TIMER_MasterSlaveMode: - * This value will be : - * @arg TIMER_MASTER_SLAVE_MODE_ENABLE : synchronize master and slave by TriO - * @arg TIMER_MASTER_SLAVE_MODE_DISABLE : Don't synchronize - * @retval None - */ -void TIMER_SelectMasterSlaveMode(TIMER_TypeDef *TIMERx, uint16_t TIMER_MasterSlaveMode) -{ - /* Reset the MSM Bit */ - TIMERx->SMC &= (uint16_t)~((uint16_t)TIMER_SMC_MSM); - - /* Configure the MSM Bit */ - TIMERx->SMC |= TIMER_MasterSlaveMode; -} - -/** - * @brief Configure the External Trigger (ETR) - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ExTriPrescaler: external Trigger Prescaler. - * This value will be : - * @arg TIMER_EXT_TRI_PSC_OFF : no divided. - * @arg TIMER_EXT_TRI_PSC_DIV2: divided by 2. - * @arg TIMER_EXT_TRI_PSC_DIV4: divided by 4. - * @arg TIMER_EXT_TRI_PSC_DIV8: divided by 8. - * @param TIMER_ExtTriPolarity: Trigger Polarity. - * This value will be : - * @arg TIMER_EXT_TRI_POLARITY_INVERTED : active low or falling edge active. - * @arg TIMER_EXT_TRI_POLARITY_NONINVERTED: active high or rising edge active. - * @param ExtTRGFilter: The External Trigger signal Filter. - * This parameter must be a value between 0x00 and 0x0F - * @retval None - */ -void TIMER_ETRConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_ExTriPrescaler, uint16_t TIMER_ExTriPolarity, - uint16_t ExtTriFilter) -{ - uint16_t tmpsmc = 0; - - tmpsmc = TIMERx->SMC; - - /*Reset the ETR Bits */ - tmpsmc &= SMC_ETR_MASK; - - /* Configure the Prescaler, the Filter value and the Polarity */ - tmpsmc |= (uint16_t)(TIMER_ExTriPrescaler | (uint16_t)(TIMER_ExTriPolarity | (uint16_t)(ExtTriFilter << (uint16_t)8))); - - TIMERx->SMC = tmpsmc; -} - -/** - * @brief Configure the Encoder Interface. - * @param TIMERx: x ={ 1 , 8 , 9 , 12 } . - * @param TIMER_EncoderMode: - * This value will be : - * @arg TIMER_ENCODER_MODE_TI1 : Counter counts on TI1FP1 edge depending on TI2FP2 level. - * @arg TIMER_ENCODER_MODE_TI2 : Counter counts on TI2FP2 edge depending on TI1FP1 level. - * @arg TIMER_ENCODER_MODE_TI12 : Counter counts on both TI1FP1 and TI2FP2 edges depending - * on the level of the other input. - * @param TIMER_IC1Polarity: input capture 1 Polarity - * This value will be : - * @arg TIMER_IC_POLARITY_FALLING : capture Falling edge. - * @arg TIMER_IC_POLARITY_RISING : capture Rising edge. - * @param TIMER_IC2Polarity: input capture 2 Polarity - * This value will be : - * @arg TIMER_IC_POLARITY_FALLING : capture Falling edge. - * @arg TIMER_IC_POLARITY_RISING : capture Rising edge. - * @retval None - */ -void TIMER_EncoderInterfaceConfig(TIMER_TypeDef *TIMERx, uint16_t TIMER_EncoderMode, - uint16_t TIMER_IC1Polarity, uint16_t TIMER_IC2Polarity) -{ - uint16_t tmpsmc = 0; - uint16_t tmpchctlr1 = 0; - uint16_t tmpche = 0; - - tmpsmc = TIMERx->SMC; - - tmpchctlr1 = TIMERx->CHCTLR1; - - tmpche = TIMERx->CHE; - - /* select the encoder Mode */ - tmpsmc &= (uint16_t)(~((uint16_t)TIMER_SMC_SMC)); - tmpsmc |= TIMER_EncoderMode; - - tmpchctlr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1M)) & (uint16_t)(~((uint16_t)TIMER_CHCTLR1_CH2M))); - tmpchctlr1 |= TIMER_CHCTLR1_CH1M_0 | TIMER_CHCTLR1_CH2M_0; - - /* select the TI1 and the TI2 Polarities*/ - tmpche &= (uint16_t)~((uint16_t)(TIMER_CHE_CH1P | TIMER_CHE_CH1NP)) & (uint16_t)~((uint16_t)(TIMER_CHE_CH2P | TIMER_CHE_CH2NP)); - tmpche |= (uint16_t)(TIMER_IC1Polarity | (uint16_t)(TIMER_IC2Polarity << (uint16_t)4)); - - TIMERx->SMC = tmpsmc; - - TIMERx->CHCTLR1 = tmpchctlr1; - - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the Hall sensor interface - * @param TIMERx: x ={ 1 , 8 } . - * @param NewValue: ENABLE or DISABLE. - * @retval None - */ -void TIMER_SelectHallSensor(TIMER_TypeDef *TIMERx, TypeState NewValue) -{ - if (NewValue != DISABLE) { - TIMERx->CTLR2 |= TIMER_CTLR2_TI1S; - } else { - TIMERx->CTLR2 &= (uint16_t)~((uint16_t)TIMER_CTLR2_TI1S); - } -} - -/* Private functions */ -/** - * @brief Configure the TI1 as Capture Input. - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 10 , 11 , 12 , 13 , 14} . - * @param TIMER_ICPolarity: Input Capture Polarity. - * This value will be : - * @arg TIMER_IC_POLARITY_RISING : Capture rising edge - * @arg TIMER_IC_POLARITY_FALLING : Capture falling edge - * @param TIMER_ICSelection: Input Capture source. - * This value will be : - * @arg TIMER_IC_SELECTION_DIRECTTI : connected to IC1. - * @arg TIMER_IC_SELECTION_INDIRECTTI : connected to IC2. - * @arg TIMER_IC_SELECTION_TRC : connected to TRC. - * @param TIMER_ICFilter: Input Capture Filter. - * This parameter must be a value between 0x00 and 0x0F. - * @retval None - */ -static void TI1_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter) -{ - uint16_t tmpchctlr1 = 0, tmpche = 0; - - /* Disable the Channel 1 */ - TIMERx->CHE &= (uint16_t)~((uint16_t)TIMER_CHE_CH1E); - tmpchctlr1 = TIMERx->CHCTLR1; - tmpche = TIMERx->CHE; - - /* Select the Input and Configure the filter */ - tmpchctlr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1M)) & ((uint16_t)~((uint16_t)TIMER_CHCTLR1_CH1ICF))); - tmpchctlr1 |= (uint16_t)(TIMER_ICSelection | (uint16_t)(TIMER_ICFilter << (uint16_t)4)); - - /* Configure the Polarity and channel enable Bit */ - tmpche &= (uint16_t)~((uint16_t)(TIMER_CHE_CH1P | TIMER_CHE_CH1NP)); - tmpche |= (uint16_t)(TIMER_ICPolarity | (uint16_t)TIMER_CHE_CH1E); - - TIMERx->CHCTLR1 = tmpchctlr1; - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TI2 as Capture Input. - * @note None - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 , 9 , 12 } . - * @param TIMER_ICPolarity: Input Capture Polarity. - * This value will be : - * @arg TIMER_IC_POLARITY_RISING : Capture rising edge - * @arg TIMER_IC_POLARITY_FALLING : Capture falling edge - * @param TIMER_ICSelection: Input Capture source. - * This value will be : - * @arg TIMER_IC_SELECTION_DIRECTTI : connected to IC2. - * @arg TIMER_IC_SELECTION_INDIRECTTI : connected to IC1. - * @arg TIMER_IC_SELECTION_TRC : connected to TRC. - * @param TIMER_ICFilter: Input Capture Filter. - * This parameter must be a value between 0x00 and 0x0F. - * @retval None - */ -static void TI2_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter) -{ - uint16_t tmpchctlr1 = 0, tmpche = 0, tmp = 0; - - /* Disable the Channel 2 */ - TIMERx->CHE &= (uint16_t)~((uint16_t)TIMER_CHE_CH2E); - tmpchctlr1 = TIMERx->CHCTLR1; - tmpche = TIMERx->CHE; - tmp = (uint16_t)(TIMER_ICPolarity << 4); - - /* Select the Input and Configure the filter */ - tmpchctlr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2M)) & ((uint16_t)~((uint16_t)TIMER_CHCTLR1_CH2ICF))); - tmpchctlr1 |= (uint16_t)(TIMER_ICFilter << 12); - tmpchctlr1 |= (uint16_t)(TIMER_ICSelection << 8); - - /* Configure the Polarity and channel enable Bit */ - tmpche &= (uint16_t)~((uint16_t)(TIMER_CHE_CH2P | TIMER_CHE_CH2NP)); - tmpche |= (uint16_t)(tmp | (uint16_t)TIMER_CHE_CH2E); - - TIMERx->CHCTLR1 = tmpchctlr1 ; - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TI3 as Capture Input - * @note None - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ICPolarity: Input Capture Polarity. - * This value will be : - * @arg TIMER_IC_POLARITY_RISING : Capture rising edge - * @arg TIMER_IC_POLARITY_FALLING : Capture falling edge - * @param TIMER_ICSelection: Input Capture source. - * This value will be : - * @arg TIMER_IC_SELECTION_DIRECTTI : connected to IC3. - * @arg TIMER_IC_SELECTION_INDIRECTTI : connected to IC4. - * @arg TIMER_IC_SELECTION_TRC : connected to TRC. - * @param TIMER_ICFilter: Input Capture Filter. - * This parameter must be a value between 0x00 and 0x0F. - * @retval None - */ -static void TI3_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter) -{ - uint16_t tmpchctlr2 = 0, tmpche = 0, tmp = 0; - - /* Disable the Channel 3 */ - TIMERx->CHE &= (uint16_t)~((uint16_t)TIMER_CHE_CH3E); - tmpchctlr2 = TIMERx->CHCTLR2; - tmpche = TIMERx->CHE; - tmp = (uint16_t)(TIMER_ICPolarity << 8); - - /* Select the Input and Configure the filter */ - tmpchctlr2 &= (uint16_t)(((uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3M)) & ((uint16_t)~((uint16_t)TIMER_CHCTLR2_CH3ICF))); - tmpchctlr2 |= (uint16_t)(TIMER_ICSelection | (uint16_t)(TIMER_ICFilter << (uint16_t)4)); - - /* Configure the Polarity and channel enable Bit */ - tmpche &= (uint16_t)~((uint16_t)(TIMER_CHE_CH3P | TIMER_CHE_CH3NP)); - tmpche |= (uint16_t)(tmp | (uint16_t)TIMER_CHE_CH3E); - - TIMERx->CHCTLR2 = tmpchctlr2; - TIMERx->CHE = tmpche; -} - -/** - * @brief Configure the TI4 as Capture Input - * @param TIMERx: x ={ 1 , 2 , 3 , 4 , 5 , 8 } . - * @param TIMER_ICPolarity: Input Capture Polarity. - * This value will be : - * @arg TIMER_IC_POLARITY_RISING : Capture rising edge - * @arg TIMER_IC_POLARITY_FALLING : Capture falling edge - * @param TIMER_ICSelection: Input Capture source. - * This value will be : - * @arg TIMER_IC_SELECTION_DIRECTTI : connected to IC4. - * @arg TIMER_IC_SELECTION_INDIRECTTI : connected to IC3. - * @arg TIMER_IC_SELECTION_TRC : connected to TRC. - * @param TIMER_ICFilter: Input Capture Filter. - * This parameter must be a value between 0x00 and 0x0F. - * @retval None - */ -static void TI4_Config(TIMER_TypeDef *TIMERx, uint16_t TIMER_ICPolarity, uint16_t TIMER_ICSelection, - uint16_t TIMER_ICFilter) -{ - uint16_t tmpchctlr2 = 0, tmpche = 0, tmp = 0; - - /* Disable the Channel 4 */ - TIMERx->CHE &= (uint16_t)~((uint16_t)TIMER_CHE_CH4E); - tmpchctlr2 = TIMERx->CHCTLR2; - tmpche = TIMERx->CHE; - tmp = (uint16_t)(TIMER_ICPolarity << 12); - - /* Select the Input and Configure the filter */ - tmpchctlr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIMER_CHCTLR2_CH4M) & ((uint16_t)~((uint16_t)TIMER_CHCTLR2_CH4ICF))); - tmpchctlr2 |= (uint16_t)(TIMER_ICSelection << 8); - tmpchctlr2 |= (uint16_t)(TIMER_ICFilter << 12); - - /* Configure the Polarity and channel enable Bit */ - tmpche &= (uint16_t)~((uint16_t)(TIMER_CHE_CH4P | TIMER_CHE_CH4NP)); - tmpche &= (uint16_t)~((uint16_t)(TIMER_CHE_CH4P)); - tmpche |= (uint16_t)(tmp | (uint16_t)TIMER_CHE_CH4E); - - TIMERx->CHCTLR2 = tmpchctlr2; - TIMERx->CHE = tmpche; -} -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_usart.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_usart.c deleted file mode 100644 index fa9304dd7b..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_usart.c +++ /dev/null @@ -1,784 +0,0 @@ -/** - ****************************************************************************** - * @brief USART functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_usart.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup USART - * @brief USART driver modules - * @{ - */ - -/** @defgroup USART_Private_Defines - * @{ - */ -/* USART Interrupts mask */ -#define INT_MASK ((uint16_t)(0x001F)) - -/* USART CTLR1 initializes bit mask */ -#define CTLR1_CLEAR_MASK ((uint16_t)(0x160C)) - -/* USART CTLR2 CLOCK initializes bit mask */ -#define CTLR2_CLOCK_CLEAR_MASK ((uint16_t)(0x0F00)) - -/* USART CTLR3 initializes bit mask */ -#define CTLR3_CLEAR_MASK ((uint16_t)(0x0300)) - -/** - * @} - */ - -/** @defgroup USART_Private_Functions - * @{ - */ - -/** - * @brief Reset the USART peripheral. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: new value of the USARTx peripheral. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_DeInit(USART_TypeDef *USARTx) -{ - if (USARTx == USART0) { - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_USART0RST, ENABLE); - RCC_APB2PeriphReset_Enable(RCC_APB2PERIPH_USART0RST, DISABLE); - } else if (USARTx == USART1) { - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_USART1RST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_USART1RST, DISABLE); - } else if (USARTx == USART2) { - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_USART2RST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_USART2RST, DISABLE); - } else if (USARTx == UART3) { - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_UART3RST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_UART3RST, DISABLE); - } else { - if (USARTx == UART4) { - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_UART4RST, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_UART4RST, DISABLE); - } - } -} - -/** - * @brief Initialize the USART peripheral interface parameters. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_InitParaStruct: the struct USART_InitPara pointer. - * @retval None - */ -void USART_Init(USART_TypeDef *USARTx, USART_InitPara *USART_InitParaStruct) -{ - uint32_t divider = 0, apbclock = 0, temp = 0; - RCC_ClocksPara RCC_ClocksState; - - USARTx->CTLR1 &= ~((uint32_t)USART_CTLR1_UEN); - /* Initialize CTLR2 */ - temp = USARTx->CTLR2; - /* Reset stop bits then set it use USART_STBits */ - temp &= ~((uint32_t)USART_CTLR2_STB); - temp |= (uint32_t)USART_InitParaStruct->USART_STBits; - - USARTx->CTLR2 = temp; - - /*Initialize CTLR1*/ - temp = USARTx->CTLR1; - /* Reset WL, PCEN, PM, TEN and REN bits */ - temp &= ~((uint32_t)CTLR1_CLEAR_MASK); - - /* According to USART_WL,USART_Parity,USART_RxorTx to configure the CTLR1 */ - temp |= (uint32_t)USART_InitParaStruct->USART_WL | USART_InitParaStruct->USART_Parity | - USART_InitParaStruct->USART_RxorTx; - USARTx->CTLR1 = temp; - - /*Initialize CTLR3*/ - temp = USARTx->CTLR3; - /* Reset CTSEN and RTSEN bits */ - temp &= ~((uint32_t)CTLR3_CLEAR_MASK); - - /* According to USART_HardwareFlowControl to configure the CTLR3 */ - temp |= USART_InitParaStruct->USART_HardwareFlowControl; - USARTx->CTLR3 = temp; - - /*Initialize USART BRR*/ - RCC_GetClocksFreq(&RCC_ClocksState); - - if (USARTx == USART0) { - apbclock = RCC_ClocksState.APB2_Frequency; - } else { - apbclock = RCC_ClocksState.APB1_Frequency; - } - - /* Get integer of baud-rate divide and raction of baud-rate divider */ - divider = (uint32_t)((apbclock) / ((USART_InitParaStruct->USART_BRR))); - temp = (uint32_t)((apbclock) % ((USART_InitParaStruct->USART_BRR))); - - /* Round the divider : if fractional part i greater than 0.5 increment divider */ - if (temp >= (USART_InitParaStruct->USART_BRR) / 2) { - divider++; - } - - USARTx->BRR = (uint16_t)divider; -} - -/** - * @brief Initial the struct USART_InitPara - * @param USART_InitParaStruct: the struct USART_InitPara pointer - * @retval None - */ -void USART_ParaInit(USART_InitPara *USART_InitParaStruct) -{ - /* USART_InitStruct members default value */ - USART_InitParaStruct->USART_BRR = 9600; - USART_InitParaStruct->USART_WL = USART_WL_8B; - USART_InitParaStruct->USART_STBits = USART_STBITS_1; - USART_InitParaStruct->USART_Parity = USART_PARITY_RESET; - USART_InitParaStruct->USART_RxorTx = USART_RXORTX_RX | USART_RXORTX_TX; - USART_InitParaStruct->USART_HardwareFlowControl = USART_HARDWAREFLOWCONTROL_NONE; -} - -/** - * @brief Initialize the USARTx peripheral Clock according to the - * specified parameters in the USART_ClockInitStruct. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef structure that contains - * the configuration information for the specified USART peripheral. - * @retval None - */ -void USART_ClockInit(USART_TypeDef *USARTx, USART_ClockInitPara *USART_ClockInitStruct) -{ - uint32_t temp = 0; - - temp = USARTx->CTLR2; - /* Clear CKEN, CPL, CPH, LBCP and SSM bits */ - temp &= ~(CTLR2_CLOCK_CLEAR_MASK); - - /* Reset hen set it usethe USART Clock, CPL, CPH, LBCP */ - temp |= (uint32_t)(USART_ClockInitStruct->USART_CKEN | USART_ClockInitStruct->USART_CPL | - USART_ClockInitStruct->USART_CPH | USART_ClockInitStruct->USART_LBCP); - /* Write to USART CTLR2 */ - USARTx->CTLR2 = (uint16_t)temp; -} - -/** - * @brief Initial the struct USART_ClockInitPara. - * @param USART_ClockInitParaStruct: the struct USART_ClockInitPara pointer - * @retval None - */ -void USART_ClockStructInit(USART_ClockInitPara *USART_ClockInitParaStruct) -{ - /*Reset USART_ClockInitStruct members default value */ - USART_ClockInitParaStruct->USART_CKEN = USART_CKEN_RESET; - USART_ClockInitParaStruct->USART_CPL = USART_CPL_LOW; - USART_ClockInitParaStruct->USART_CPH = USART_CPH_1EDGE; - USART_ClockInitParaStruct->USART_LBCP = USART_LBCP_DISABLE; -} - -/** - * @brief Enable or disable the specified USART peripheral. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: new value of the USARTx peripheral. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* Enable or disable the specified USART peripheral by setting the UEN bit in the CTLR1 register */ - if (NewValue != DISABLE) { - USARTx->CTLR1 |= USART_CTLR1_UEN; - } else { - USARTx->CTLR1 &= ~((uint16_t)USART_CTLR1_UEN); - } -} - -/** - * @brief Set the system clock prescaler. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_Prescaler: specifies the prescaler clock. - * @note This function has to be called before calling USART_Enable() function. - * @retval None - */ -void USART_SetPrescaler(USART_TypeDef *USARTx, uint8_t USART_Prescaler) -{ - /* Clear and set the USART prescaler */ - USARTx->GTPR &= ~((uint16_t)USART_GTPR_PSC); - - USARTx->GTPR |= USART_Prescaler; -} - -/** - * @brief Send data by the USART peripheral. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param Data: the data will be sent. - * @retval None - */ -void USART_DataSend(USART_TypeDef *USARTx, uint16_t Data) -{ - USARTx->DR = (Data & (uint16_t)0x01FF); -} - -/** - * @brief Receive data by the USART peripheral. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @retval The received data. - */ -uint16_t USART_DataReceive(USART_TypeDef *USARTx) -{ - return (uint16_t)(USARTx->DR & (uint16_t)0x01FF); -} - - -/** - * @brief Set the address of the USART terminal. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_Address: Indicates the address of the USART node. - * @retval None - */ -void USART_Address(USART_TypeDef *USARTx, uint8_t USART_Address) -{ - /* Clear the USART address and Set the USART terminal*/ - USARTx->CTLR2 &= ~USART_CTLR2_ADD; - - USARTx->CTLR2 |= USART_Address; -} - -/** - * @brief Enable or disable the USART's mute mode. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: the USART mute mode. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_MuteMode_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* By setting the MEN bit in the CTLR1 register enable or disable the USART's mute mode*/ - if (NewValue != DISABLE) { - USARTx->CTLR1 |= USART_CTLR1_RWU; - } else { - USARTx->CTLR1 &= ~USART_CTLR1_RWU; - } -} - -/** - * @brief Set the USART WakeUp method from mute mode. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_WakeUp - * This parameter can be one of the following values - * @arg USART_WAKEUP_IDLELINE - * @arg USART_WAKEUP_ADDRESSMARK - * @retval None - */ -void USART_MuteModeWakeUp_Set(USART_TypeDef *USARTx, uint16_t USART_WakeUp) -{ - USARTx->CTLR1 &= ~((uint16_t)USART_CTLR1_WM); - USARTx->CTLR1 |= USART_WakeUp; -} - - -/** - * @brief Set the USART LIN Break detection length. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_LINBreakDetectLength - * This parameter can be one of the following values - * @arg USART_LINBREAKDETECTLENGTH_10B - * @arg USART_LINBREAKDETECTLENGTH_11B - * @retval None - */ -void USART_SetLINBDLength(USART_TypeDef *USARTx, uint16_t USART_LINBreakDetectLength) -{ - USARTx->CTLR2 &= ~((uint16_t)USART_CTLR2_LBDL); - USARTx->CTLR2 |= USART_LINBreakDetectLength; -} - -/** - * @brief Enable or disable the USART's LIN mode. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: the USART LIN mode value. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_LIN_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* By setting the LINEN bit in the CTLR2 register enable or disable the USART's LIN mode */ - if (NewValue != DISABLE) { - USARTx->CTLR2 |= USART_CTLR2_LMEN; - } else { - USARTx->CTLR2 &= ~((uint16_t)USART_CTLR2_LMEN); - } -} - -/** - * @brief Enable or disable the Half-duplex mode. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: the USART Half-duplex mode value. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_HalfDuplex_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* By setting the HDEN bit in the CTLR3 register enable or disable the Half-duplex mode */ - if (NewValue != DISABLE) { - USARTx->CTLR3 |= USART_CTLR3_HDEN; - } else { - USARTx->CTLR3 &= ~USART_CTLR3_HDEN; - } -} - -/** - * @brief Set the the USART guard time. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @param USART_GuardTime: the USART guard time. - * @retval None - */ -void USART_GuardTime_Set(USART_TypeDef *USARTx, uint8_t USART_GuardTime) -{ - /* Set the USART guard time */ - USARTx->GTPR &= ~((uint16_t)USART_GTPR_GT); - - USARTx->GTPR |= (uint16_t)((uint16_t)USART_GuardTime << 0x08); -} - -/** - * @brief Enable or disable the USART's Smart Card mode. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @param NewValue: the Smart Card mode value. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_SmartCard_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* By setting the SCEN bit in the CTLR3 register enable or disable the USART's Smart Card mode */ - if (NewValue != DISABLE) { - USARTx->CTLR3 |= USART_CTLR3_SCEN; - } else { - USARTx->CTLR3 &= ~((uint16_t)USART_CTLR3_SCEN); - } -} - -/** - * @brief Enable or disable NACK transmission. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: the NACK transmission state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_SmartCardNACK_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* By setting the NACK bit in the CTLR3 register Enable or disable NACK transmission */ - if (NewValue != DISABLE) { - USARTx->CTLR3 |= USART_CTLR3_NACK; - } else { - USARTx->CTLR3 &= ~((uint32_t)USART_CTLR3_NACK); - } -} - -/** - * @brief DMA enable for transmission or reception. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_DMAEnable: the DMA request. - * This parameter can be one of the following values - * @arg USART_DMAREQ_RX - * @arg USART_DMAREQ_TX - * @param NewValue: the DMA Request sources state. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_DMA_Enable(USART_TypeDef *USARTx, uint16_t USART_DMAEnable, TypeState NewValue) -{ - /* Enable or disable the DMA transfer for transmission or reception by setting the DENT and/or - DENR bits in the USART CTLR3 register */ - if (NewValue != DISABLE) { - USARTx->CTLR3 |= USART_DMAEnable; - } else { - USARTx->CTLR3 &= ~USART_DMAEnable; - } - -} - -/** - * @brief Set the USARTX IrDA low-power. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_IrDAMode - * This parameter can be one of the following values - * @arg USART_IRDAMODE_LOWPOWER - * @arg USART_IRDAMODE_NORMAL. - * @retval None - */ -void USART_IrDA_Set(USART_TypeDef *USARTx, uint16_t USART_IrDAMode) -{ - USARTx->CTLR3 &= ~((uint16_t)USART_CTLR3_IRLP); - USARTx->CTLR3 |= USART_IrDAMode; -} - -/** - * @brief Enable or disable the USART's IrDA interface. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param NewValue: the IrDA mode value. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_IrDA_Enable(USART_TypeDef *USARTx, TypeState NewValue) -{ - /* By setting the IREN bit in the CTLR3 register enable or disable the USART's IrDA interface */ - if (NewValue != DISABLE) { - USARTx->CTLR3 |= USART_CTLR3_IREN; - } else { - USARTx->CTLR3 &= ~((uint16_t)USART_CTLR3_IREN); - } -} - -/** - * @brief Detect the bit flag of STR register. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_FLAG: the flag of STR register. - * This parameter can be one of the following values: - * @arg USART_FLAG_CTSF: CTS Change flag.(not available for UART4 and UART5) - * @arg USART_FLAG_LBDF: LIN Break detection flag - * @arg USART_FLAG_TBE: Transmit data register empty flag. - * @arg USART_FLAG_TC: Transmission Complete flag. - * @arg USART_FLAG_RBNE: Receive data register not empty flag. - * @arg USART_FLAG_IDLEF:Idle Line detection flag. - * @arg USART_FLAG_ORE: OverRun Error flag. - * @arg USART_FLAG_NE: Noise Error flag. - * @arg USART_FLAG_FE: Framing Error flag. - * @arg USART_FLAG_PE: Parity Error flag. - * @retval The new state of USART_FLAG (SET or RESET). - */ -TypeState USART_GetBitState(USART_TypeDef *USARTx, uint16_t USART_FLAG) -{ - if ((USARTx->STR & USART_FLAG) != (uint16_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Enable or disable USART interrupt. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_INT: the USART interrupt - * This parameter can be one of the following values: - * @arg USART_INT_PE - * @arg USART_INT_TBE - * @arg USART_INT_TC - * @arg USART_INT_RBNE - * @arg USART_INT_IDLEF - * @arg USART_INT_LBDF - * @arg USART_INT_CTSF (not available for UART4 and UART5) - * @arg USART_INT_ERIE - * @param NewValue: the USART interrupt State. - * This parameter can be: ENABLE or DISABLE. - * @retval None - */ -void USART_INT_Set(USART_TypeDef *USARTx, uint16_t USART_INT, TypeState NewValue) -{ - uint32_t intpos = 0, usartreg = 0; - uint32_t usartxbase = 0; - - usartxbase = (uint32_t)USARTx; - - /* Get the USART register index and the interrupt position */ - usartreg = ((uint8_t)(USART_INT) >> 0x05); - intpos = USART_INT & INT_MASK; - - /* Get the interrupt from which register: CTLR1,CTLR2 OR CTLR3 */ - if (usartreg == 0x01) { - usartxbase += 0x0C; - } else if (usartreg == 0x02) { - usartxbase += 0x10; - } else { - usartxbase += 0x14; - } - if (NewValue != DISABLE) { - *(__IO uint32_t *)usartxbase |= (((uint32_t)0x01) << intpos); - } else { - *(__IO uint32_t *)usartxbase &= ~(((uint32_t)0x01) << intpos); - } -} - -/** - * @brief Clear the bit flag. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_FLAG: the bit flag usart . - * This parameter can be one of the following values: - * @arg USART_FLAG_CTSF: CTS Change flag.(not available for UART4 and UART5) - * @arg USART_FLAG_LBDF: LIN Break detection flag - * @arg USART_FLAG_TC: Transmission Complete flag. - * @arg USART_FLAG_RBNE: Receive data register not empty flag. - * @note - * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun - * error) and IDLEF (Idle line detected) flag bits are cleared by - * software sequence: a read operation to USART_STR register - * (USART_GetBitState()) followed by a read operation to USART_DR register - * (USART_DataReceive()). - * - RBNE flag bit can be also cleared by a read to the USART_DR register - * (USART_DataReceive()). - * - TC flag bit can be also cleared by software sequence: a read - * operation to USART_STR register (USART_GetBitState()) followed by a write - * operation to USART_DR register (USART_DataSend()). - * - TBE flag bit is cleared only by a write to the USART_DR register - * (USART_DataSend()). - * @retval None - */ -void USART_ClearBitState(USART_TypeDef *USARTx, uint16_t USART_FLAG) -{ - USARTx->STR = (uint16_t)~ USART_FLAG; -} - -/** - * @brief Detect the interrupt bit flag. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_INT: the USART interrupt bit flag. - * This parameter can be one of the following values: - * @arg USART_INT_PE - * @arg USART_INT_TBE - * @arg USART_INT_TC - * @arg USART_INT_RBNE - * @arg USART_INT_IDLEF - * @arg USART_INT_LBDF - * @arg USART_INT_CTSF: CTS flag interrupt (not available for UART4 and UART5) - * @arg USART_INT_ORE - * @arg USART_INT_NE - * @arg USART_INT_FE - * @retval The new state of USART_INT (SET or RESET). - */ -TypeState USART_GetIntBitState(USART_TypeDef *USARTx, uint16_t USART_INT) -{ - uint16_t bitpos = 0, itmask = 0, usartreg = 0; - - /* Get the USART register index and the interrupt position */ - usartreg = (((uint8_t)USART_INT) >> 0x05); - - itmask = (USART_INT) & (INT_MASK); - - itmask = (uint16_t)0x01 << itmask; - - if (usartreg == 0x01) { - itmask &= USARTx->CTLR1; - } else { - if (usartreg == 0x02) { - itmask &= USARTx->CTLR2; - } else { - itmask &= USARTx->CTLR3; - } - } - - bitpos = USART_INT >> 0x08; - bitpos = (uint32_t)0x01 << bitpos; - bitpos &= USARTx->STR; - if ((itmask != (uint16_t)RESET) && (bitpos != (uint16_t)RESET)) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear the interrupt bit flag. - * @param USARTx: the USART peripheral. - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @param USART_INT: the interrupt bit flag. - * This parameter can be one of the following values: * @arg USART_INT_TC - * @arg USART_INT_LBDF - * @arg USART_INT_CTSF: CTS Flag interrupt (not available for UART4 and UART5) - * @arg USART_INT_RBNE - * @arg USART_INT_TC - * @note - * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun - * error) and IDLEF (Idle line detected flag) interrupt bits are cleared by - * software sequence: a read operation to USART_STR register - * (USART_GetINTState()) followed by a read operation to USART_DR register - * (USART_DataReceive()). - * - RBNE interrupt bit can be also cleared by a read to the USART_DR register - * (USART_DataReceive()). - * - TC interrupt bit can be also cleared by software sequence: a read - * operation to USART_STR register (USART_GetINTState()) followed by a write - * operation to USART_DR register (USART_DataSend()). - * - TBE interrupt bit is cleared only by a write to the USART_DR register - * (USART_DataSend()). - * @retval None - */ -void USART_ClearIntBitState(USART_TypeDef *USARTx, uint16_t USART_INT) -{ - uint16_t bitpos = 0, itmask = 0; - - bitpos = USART_INT >> 0x08; - itmask = ((uint16_t)0x01 << (uint16_t)bitpos); - USARTx->STR = (uint16_t)~itmask; -} - -/** - * @brief Send break command. - * @param USARTx: the USART peripheral - * This parameter can be one of the following values - * @arg USART1 - * @arg USART2 - * @arg USART3 - * @arg UART4 - * @arg UART5 - * @retval None - */ -void USART_SendBreak(USART_TypeDef *USARTx) -{ - - /* Send break command */ - USARTx->CTLR1 |= USART_CTLR1_SBKCMD; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_wwdg.c b/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_wwdg.c deleted file mode 100644 index 504aad2868..0000000000 --- a/bsp/gd32103c-eval/Libraries/GD32F1xx_standard_peripheral/Source/gd32f10x_wwdg.c +++ /dev/null @@ -1,155 +0,0 @@ -/** - ****************************************************************************** - * @brief WWDG functions of the firmware library. - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "gd32f10x_wwdg.h" -#include "gd32f10x_rcc.h" - -/** @addtogroup GD32F10x_Firmware - * @{ - */ - -/** @defgroup WWDG - * @brief WWDG driver modules - * @{ - */ - -/** @defgroup WWDG_Private_Variables - * @{ - */ - -/* CFR register bit mask */ -#define CFR_PS_MASK ((uint32_t)0xFFFFFE7F) -#define CFR_WIN_MASK ((uint32_t)0xFFFFFF80) -#define BIT_MASK ((uint8_t)0x7F) - -/** - * @} - */ - -/** @defgroup WWDG_Private_Functions - * @{ - */ - -/** - * @brief Reset the WWDG configuration. - * @param None - * @retval None - */ -void WWDG_DeInit(void) -{ - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_WWDG, ENABLE); - RCC_APB1PeriphReset_Enable(RCC_APB1PERIPH_WWDG, DISABLE); -} - -/** - * @brief Set WWDG prescaler value. - * @param PrescalerValue: WWDG Prescaler value. - * This parameter can be one of the following values: - * @arg WWDG_PRESCALER_1: the time base of watchdog counter = (PCLK1/4096)/1 - * @arg WWDG_PRESCALER_2: the time base of watchdog counter = (PCLK1/4096)/2 - * @arg WWDG_PRESCALER_4: the time base of watchdog counter = (PCLK1/4096)/4 - * @arg WWDG_PRESCALER_8: the time base of watchdog counter = (PCLK1/4096)/8 - * @retval None - */ -void WWDG_SetPrescalerValue(uint32_t PrescalerValue) -{ - uint32_t temp = 0; - - /* Clear PS[1:0] bits */ - temp = WWDG->CFR & CFR_PS_MASK; - - /* Set PS[1:0] bits */ - temp |= PrescalerValue; - WWDG->CFR = temp; -} - -/** - * @brief Set watchdog window value. - * @param WindowValue: the window value to be compared to the downcounter. - * @retval None - */ -void WWDG_SetWindowValue(uint8_t WindowValue) -{ - __IO uint32_t temp = 0; - - /* Clear WIN[6:0] bits */ - temp = WWDG->CFR & CFR_WIN_MASK; - - /* Set WIN[6:0] bits */ - temp |= WindowValue & (uint32_t) BIT_MASK; - WWDG->CFR = temp; -} - -/** - * @brief Enable the WWDG Early wakeup interrupt(EWI). - * @note An interrupt occurs when the counter reaches 0x40 if the bit is set. - * It's cleared by a hardware reset. A write of 0 has no effect. - * @param None - * @retval None - */ -void WWDG_EnableInt(void) -{ - WWDG->CFR |= WWDG_CFR_EWI; -} - -/** - * @brief Set the value of the watchdog counter. - * @param CounterValue: the watchdog counter value. - * @retval None - */ -void WWDG_SetCounterValue(uint8_t CounterValue) -{ - /* Write to CNT[6:0] bits */ - WWDG->CTLR = CounterValue & BIT_MASK; -} - -/** - * @brief Start the window watchdog counter. - * @param CounterValue: The value of the watchdog counter. - * @retval None - */ -void WWDG_Enable(uint8_t CounterValue) -{ - WWDG->CTLR = WWDG_CTLR_WDGEN | CounterValue; -} - -/** - * @brief Check the Early Wakeup interrupt bit state. - * @param None - * @retval The new state of the Early Wakeup interrupt (SET or RESET). - */ -TypeState WWDG_GetBitState(void) -{ - if ((WWDG->STR) != (uint32_t)RESET) { - return SET; - } else { - return RESET; - } -} - -/** - * @brief Clear Early Wakeup interrupt flag. - * @param None - * @retval None - */ -void WWDG_ClearBitState(void) -{ - WWDG->STR = (uint32_t)RESET; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/bsp/gd32103c-eval/Libraries/SConscript b/bsp/gd32103c-eval/Libraries/SConscript deleted file mode 100644 index a4967104cb..0000000000 --- a/bsp/gd32103c-eval/Libraries/SConscript +++ /dev/null @@ -1,26 +0,0 @@ -import rtconfig -from building import * - -# get current directory -cwd = GetCurrentDir() - -# The set of source files associated with this SConscript file. - -src = Glob('GD32F1xx_standard_peripheral/Source/*.c') -src += [cwd + '/CMSIS/GD/GD32F1xx/Source/system_gd32f1xx.c'] - -#add for startup script -if rtconfig.CROSS_TOOL == 'gcc': - src += [cwd + '/CMSIS/GD/GD32F1xx/Source/GCC/startup_gd32.s'] - src += [cwd + '/CMSIS/GD/GD32F1xx/Source/GCC/isr_tab.s'] - -path = [ - cwd + '/CMSIS/GD/GD32F1xx/Include', - cwd + '/CMSIS', - cwd + '/GD32F1xx_standard_peripheral/Include',] - -CPPDEFINES = ['USE_STDPERIPH_DRIVER', 'GD32F1XX'] - -group = DefineGroup('GD32_Lib', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) - -Return('group') diff --git a/bsp/gd32103c-eval/README.md b/bsp/gd32103c-eval/README.md deleted file mode 100644 index d55bccd908..0000000000 --- a/bsp/gd32103c-eval/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# GD32103C-EVAL - -## 简介 - -GD32103C-EVAL是-兆易创新推出的一款GD32F103VCT6系列的评估板,板载资源主要如下: - -| 硬件 | 描述 | -| --------- | ------------- | -| 芯片型号 | GD32F103VCT6 | -| CPU | ARM Cortex M3 | -| 主频 | 108M | -| 片内SRAM | 48K | -| 片内FLASH | 256K | -| 片外FLASH | 1Gb | - -## 编译说明 - -GD32103C-EVAL板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以下是具体版本信息: - -| IDE/编译器 | 已测试版本 | -| ---------- | ---------------------------- | -| GCC |gcc version 6.2.1 20161205 (release) | - -## 烧写及执行 - -供电方式:开发板使用 Mini USB 接口或者 DC-005 连接器提供 5V 电源。 - -下载程序:下载程序到开发板需要一套 JLink 或者使用 GD-Link 工具。 - -串口连接:使用串口线连接到COM1(UART0),或者使用USB转TTL模块连接PA9(MCU TX)和PA10(MCU RX)。 - -### 运行结果 - -如果编译 & 烧写无误,当复位设备后,会在串口上看到RT-Thread的启动logo信息: - -```bash - \ | / -- RT - Thread Operating System - / | \ 4.0.3 build Jan 4 2021 - 2006 - 2021 Copyright by rt-thread team -msh /> -``` -## 驱动支持情况及计划 - -| 驱动 | 支持情况 | 备注 | -| --------- | -------- | :------------------------: | -| UART | 支持 | UART0~4 | -| GPIO | 支持 | GPIOA~G | -| ADC | 支持 | ADC0~1 | -| HWTIMER | 支持 | TIMER0~7 | -| RTC | 支持 | RTC | -| WDT | 支持 | Free watchdog timer | -| IIC | 未支持 | I2C0~1 | -| SPI | 未支持 | SPI0~2 | -| ETH | 未支持 | | -| LCD | 未支持 | | -| SDRAM | 未支持 | | -| SPI FLASH | 未支持 | | - -### IO在板级支持包中的映射情况 - -| IO号 | 板级包中的定义 | -| ---- | -------------- | -| PC0 | LED1 | -| PC2 | LED2 | -| PE0 | LED3 | -| PE1 | LED4 | -| PA0 | KEY1 | -| PC13 | KEY2 | -| PB14 | KEY3 | - -## 联系人信息 - -维护人:[iysheng](https://github.com/iysheng) diff --git a/bsp/gd32103c-eval/SConscript b/bsp/gd32103c-eval/SConscript deleted file mode 100644 index fe0ae941ae..0000000000 --- a/bsp/gd32103c-eval/SConscript +++ /dev/null @@ -1,14 +0,0 @@ -# for module compiling -import os -Import('RTT_ROOT') - -cwd = str(Dir('#')) -objs = [] -list = os.listdir(cwd) - -for d in list: - path = os.path.join(cwd, d) - if os.path.isfile(os.path.join(path, 'SConscript')): - objs = objs + SConscript(os.path.join(d, 'SConscript')) - -Return('objs') diff --git a/bsp/gd32103c-eval/SConstruct b/bsp/gd32103c-eval/SConstruct deleted file mode 100644 index 6b5d561848..0000000000 --- a/bsp/gd32103c-eval/SConstruct +++ /dev/null @@ -1,40 +0,0 @@ -import os -import sys -import rtconfig - -if os.getenv('RTT_ROOT'): - RTT_ROOT = os.getenv('RTT_ROOT') -else: - RTT_ROOT = os.path.normpath(os.getcwd() + '/../..') - -sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] -try: - from building import * -except: - print('Cannot found RT-Thread root directory, please check RTT_ROOT') - print(RTT_ROOT) - exit(-1) - -TARGET = 'rtthread-gd32f4xx.' + rtconfig.TARGET_EXT - -DefaultEnvironment(tools=[]) -env = Environment(tools = ['mingw'], - AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, - AR = rtconfig.AR, ARFLAGS = '-rc', - LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) -env.PrependENVPath('PATH', rtconfig.EXEC_PATH) - -if rtconfig.PLATFORM == 'iar': - env.Replace(CCCOM = ['$CC $CFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES']) - env.Replace(ARFLAGS = ['']) - env.Replace(LINKCOM = env["LINKCOM"] + ' --map project.map') - -Export('RTT_ROOT') -Export('rtconfig') - -# prepare building environment -objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) - -# make a building -DoBuilding(TARGET, objs) diff --git a/bsp/gd32103c-eval/applications/SConscript b/bsp/gd32103c-eval/applications/SConscript deleted file mode 100644 index ca2395451a..0000000000 --- a/bsp/gd32103c-eval/applications/SConscript +++ /dev/null @@ -1,11 +0,0 @@ -Import('RTT_ROOT') -Import('rtconfig') -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd] - -group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') diff --git a/bsp/gd32103c-eval/applications/main.c b/bsp/gd32103c-eval/applications/main.c deleted file mode 100644 index e9256f1d4d..0000000000 --- a/bsp/gd32103c-eval/applications/main.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-04 iysheng first version - */ - -#include -#include -#include -#include -#include -#include "board.h" - -#define LED1 GET_PIN(C, 0) - -int main(void) -{ - rt_pin_mode(LED1, PIN_MODE_OUTPUT); - - while (1) - { - rt_pin_write(LED1, PIN_HIGH); - rt_thread_mdelay(500); - rt_pin_write(LED1, PIN_LOW); - rt_thread_mdelay(500); - } - - return 0; -} diff --git a/bsp/gd32103c-eval/drivers/SConscript b/bsp/gd32103c-eval/drivers/SConscript deleted file mode 100644 index 30a1a338d0..0000000000 --- a/bsp/gd32103c-eval/drivers/SConscript +++ /dev/null @@ -1,35 +0,0 @@ -Import('RTT_ROOT') -Import('rtconfig') -from building import * - -cwd = os.path.join(str(Dir('#')), 'drivers') - -# add the general drivers. -src = Split(""" -board.c -""") - -CPPPATH = [cwd] - -# add uart drivers. -if GetDepend('RT_USING_SERIAL'): - src += ['drv_usart.c'] - -if GetDepend('RT_USING_PIN'): - src += ['drv_gpio.c'] - -if GetDepend('RT_USING_ADC'): - src += ['drv_adc.c'] - -if GetDepend('RT_USING_HWTIMER'): - src += ['drv_hwtimer.c'] - -if GetDepend('RT_USING_RTC'): - src += ['drv_rtc.c'] - -if GetDepend('RT_USING_WDT'): - src += ['drv_iwdt.c'] - -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') diff --git a/bsp/gd32103c-eval/drivers/board.c b/bsp/gd32103c-eval/drivers/board.c deleted file mode 100644 index 0e4d1a1305..0000000000 --- a/bsp/gd32103c-eval/drivers/board.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-04 iysheng first version - */ - -#include -#include -#include - -#include -#include -#include - -/* - * System Clock Configuration - */ -void SystemClock_Config(void) -{ - SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); - NVIC_SetPriority(SysTick_IRQn, 0); -} - -/* - * This is the timer interrupt service routine. - */ -void SysTick_Handler(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - rt_tick_increase(); - - /* leave interrupt */ - rt_interrupt_leave(); -} - -/** - * This function will initial GD32 board. - */ -void rt_hw_board_init() -{ - /* NVIC Configuration */ -#define NVIC_VTOR_MASK 0x3FFFFF80 -#ifdef VECT_TAB_RAM - /* Set the Vector Table base location at 0x10000000 */ - SCB->VTOR = (0x10000000 & NVIC_VTOR_MASK); -#else /* VECT_TAB_FLASH */ - /* Set the Vector Table base location at 0x08000000 */ - SCB->VTOR = (0x08000000 & NVIC_VTOR_MASK); -#endif - - SystemClock_Config(); - -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); -#endif - -#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) - rt_console_set_device(RT_CONSOLE_DEVICE_NAME); -#endif - -#ifdef BSP_USING_SDRAM - rt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END); -#else - rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); -#endif -} - -/*@}*/ diff --git a/bsp/gd32103c-eval/drivers/board.h b/bsp/gd32103c-eval/drivers/board.h deleted file mode 100644 index 6e48eba213..0000000000 --- a/bsp/gd32103c-eval/drivers/board.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-04 iysheng first version - */ - -#ifndef __BOARD_H__ -#define __BOARD_H__ - -#include - -#include "drv_gpio.h" - -#define GD32_SRAM_SIZE 48 -#define GD32_SRAM_END (0x20000000 + GD32_SRAM_SIZE * 1024) - -extern int __bss_end; -#define HEAP_BEGIN (&__bss_end) - -#define HEAP_END GD32_SRAM_END - -#endif diff --git a/bsp/gd32103c-eval/drivers/drv_adc.h b/bsp/gd32103c-eval/drivers/drv_adc.h deleted file mode 100644 index 4fba7c093d..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_adc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-03 iysheng first release - */ - -#ifndef __DRV_ADC_H__ -#define __DRV_ADC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __DRV_ADC_H__ */ - diff --git a/bsp/gd32103c-eval/drivers/drv_comm.h b/bsp/gd32103c-eval/drivers/drv_comm.h deleted file mode 100644 index 5aef53cce2..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_comm.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-28 iysheng first version - */ - -#ifndef __DRV_COMM_H__ -#define __DRV_COMM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __DRV_HWTIMER_H__ */ - diff --git a/bsp/gd32103c-eval/drivers/drv_gpio.c b/bsp/gd32103c-eval/drivers/drv_gpio.c deleted file mode 100644 index beee11b65d..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_gpio.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-12-27 iysheng first version - * 2021-01-01 iysheng support exti interrupt - */ - -#include -#include "drv_gpio.h" - -#ifdef RT_USING_PIN - -#if defined(GPIOG) -#define __GD32_PORT_MAX 7u -#elif defined(GPIOF) -#define __GD32_PORT_MAX 6u -#elif defined(GPIOE) -#define __GD32_PORT_MAX 5u -#elif defined(GPIOD) -#define __GD32_PORT_MAX 4u -#elif defined(GPIOC) -#define __GD32_PORT_MAX 3u -#elif defined(GPIOB) -#define __GD32_PORT_MAX 2u -#elif defined(GPIOA) -#define __GD32_PORT_MAX 1u -#else -#define __GD32_PORT_MAX 0u -#error Unsupported GD32 GPIO peripheral. -#endif - -#define PIN_GDPORT_MAX __GD32_PORT_MAX - -static const struct pin_irq_map pin_irq_map[] = -{ -#if defined(SOC_SERIES_GD32F1) - {GPIO_PIN_0, EXTI0_IRQn}, - {GPIO_PIN_1, EXTI1_IRQn}, - {GPIO_PIN_2, EXTI2_IRQn}, - {GPIO_PIN_3, EXTI3_IRQn}, - {GPIO_PIN_4, EXTI4_IRQn}, - {GPIO_PIN_5, EXTI9_5_IRQn}, - {GPIO_PIN_6, EXTI9_5_IRQn}, - {GPIO_PIN_7, EXTI9_5_IRQn}, - {GPIO_PIN_8, EXTI9_5_IRQn}, - {GPIO_PIN_9, EXTI9_5_IRQn}, - {GPIO_PIN_10, EXTI15_10_IRQn}, - {GPIO_PIN_11, EXTI15_10_IRQn}, - {GPIO_PIN_12, EXTI15_10_IRQn}, - {GPIO_PIN_13, EXTI15_10_IRQn}, - {GPIO_PIN_14, EXTI15_10_IRQn}, - {GPIO_PIN_15, EXTI15_10_IRQn}, -#else -#error "Unsupported soc series" -#endif -}; - -static struct rt_pin_irq_hdr pin_irq_hdr_tab[] = -{ - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, - {-1, 0, RT_NULL, RT_NULL}, -}; -static uint32_t pin_irq_enable_mask = 0; - -#define ITEM_NUM(items) sizeof(items) / sizeof(items[0]) - -static rt_base_t gd32_pin_get(const char *name) -{ - rt_base_t pin = 0; - int hw_port_num, hw_pin_num = 0; - int i, name_len; - - name_len = rt_strlen(name); - - if ((name_len < 4) || (name_len >= 6)) - { - return -RT_EINVAL; - } - if ((name[0] != 'P') || (name[2] != '.')) - { - return -RT_EINVAL; - } - - if ((name[1] >= 'A') && (name[1] <= 'Z')) - { - hw_port_num = (int)(name[1] - 'A'); - } - else - { - return -RT_EINVAL; - } - - for (i = 3; i < name_len; i++) - { - hw_pin_num *= 10; - hw_pin_num += name[i] - '0'; - } - - pin = PIN_NUM(hw_port_num, hw_pin_num); - - return pin; -} - -static void gd32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) -{ - GPIO_TypeDef *gpio_port; - uint16_t gpio_pin; - - if (PIN_PORT(pin) < PIN_GDPORT_MAX) - { - gpio_port = PIN_GDPORT(pin); - gpio_pin = PIN_GDPIN(pin); - - GPIO_WriteBit(gpio_port, gpio_pin, (BitState)value); - } -} - -static int gd32_pin_read(rt_device_t dev, rt_base_t pin) -{ - GPIO_TypeDef *gpio_port; - uint16_t gpio_pin; - int value = PIN_LOW; - - if (PIN_PORT(pin) < PIN_GDPORT_MAX) - { - gpio_port = PIN_GDPORT(pin); - gpio_pin = PIN_GDPIN(pin); - value = GPIO_ReadInputBit(gpio_port, gpio_pin); - } - - return value; -} - -static void gd32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) -{ - GPIO_InitPara GPIO_InitStruct = {0}; - - if (PIN_PORT(pin) >= PIN_GDPORT_MAX) - { - return; - } - - /* Configure GPIO_InitStructure */ - GPIO_InitStruct.GPIO_Pin = PIN_GDPIN(pin); - GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_2MHZ; - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IN_FLOATING; - - switch (mode) - { - case PIN_MODE_OUTPUT: - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_OUT_PP; - break; - case PIN_MODE_INPUT: - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IN_FLOATING; - break; - case PIN_MODE_INPUT_PULLUP: - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IPD; - break; - case PIN_MODE_INPUT_PULLDOWN: - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IPU; - break; - case PIN_MODE_OUTPUT_OD: - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_OUT_OD; - break; - default: - break; - } - - GPIO_Init(PIN_GDPORT(pin), &GPIO_InitStruct); -} - -rt_inline rt_int32_t bit2bitno(rt_uint32_t bit) -{ - int i; - for (i = 0; i < 32; i++) - { - if ((0x01 << i) == bit) - { - return i; - } - } - return -1; -} - -rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit) -{ - rt_int32_t mapindex = bit2bitno(pinbit); - if (mapindex < 0 || mapindex >= ITEM_NUM(pin_irq_map)) - { - return RT_NULL; - } - return &pin_irq_map[mapindex]; -}; - -static rt_err_t gd32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, - rt_uint32_t mode, void (*hdr)(void *args), void *args) -{ - rt_base_t level; - rt_int32_t irqindex = -1; - - if (PIN_PORT(pin) >= PIN_GDPORT_MAX) - { - return -RT_ENOSYS; - } - - irqindex = bit2bitno(PIN_GDPIN(pin)); - if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) - { - return RT_ENOSYS; - } - - level = rt_hw_interrupt_disable(); - if (pin_irq_hdr_tab[irqindex].pin == pin && - pin_irq_hdr_tab[irqindex].hdr == hdr && - pin_irq_hdr_tab[irqindex].mode == mode && - pin_irq_hdr_tab[irqindex].args == args) - { - rt_hw_interrupt_enable(level); - return RT_EOK; - } - if (pin_irq_hdr_tab[irqindex].pin != -1) - { - rt_hw_interrupt_enable(level); - return RT_EBUSY; - } - pin_irq_hdr_tab[irqindex].pin = pin; - pin_irq_hdr_tab[irqindex].hdr = hdr; - pin_irq_hdr_tab[irqindex].mode = mode; - pin_irq_hdr_tab[irqindex].args = args; - rt_hw_interrupt_enable(level); - - return RT_EOK; -} - -static rt_err_t gd32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) -{ - rt_base_t level; - rt_int32_t irqindex = -1; - - if (PIN_PORT(pin) >= PIN_GDPORT_MAX) - { - return -RT_ENOSYS; - } - - irqindex = bit2bitno(PIN_GDPIN(pin)); - if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) - { - return RT_ENOSYS; - } - - level = rt_hw_interrupt_disable(); - if (pin_irq_hdr_tab[irqindex].pin == -1) - { - rt_hw_interrupt_enable(level); - return RT_EOK; - } - pin_irq_hdr_tab[irqindex].pin = -1; - pin_irq_hdr_tab[irqindex].hdr = RT_NULL; - pin_irq_hdr_tab[irqindex].mode = 0; - pin_irq_hdr_tab[irqindex].args = RT_NULL; - rt_hw_interrupt_enable(level); - - return RT_EOK; -} - -static rt_err_t gd32_pin_irq_enable(struct rt_device *device, rt_base_t pin, - rt_uint32_t enabled) -{ - const struct pin_irq_map *irqmap; - rt_base_t level; - rt_int32_t irqindex = -1; - GPIO_InitPara GPIO_InitStruct = {0}; - EXTI_InitPara EXTI_InitParaStruct = {0}; - - if (PIN_PORT(pin) >= PIN_GDPORT_MAX) - { - return -RT_ENOSYS; - } - - GPIO_InitStruct.GPIO_Pin = PIN_GDPIN(pin); - EXTI_InitParaStruct.EXTI_LINE = PIN_GDPIN(pin); - EXTI_InitParaStruct.EXTI_Mode = EXTI_Mode_Interrupt; - if (enabled == PIN_IRQ_ENABLE) - { - irqindex = bit2bitno(PIN_GDPIN(pin)); - if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map)) - { - return RT_ENOSYS; - } - - level = rt_hw_interrupt_disable(); - - if (pin_irq_hdr_tab[irqindex].pin == -1) - { - rt_hw_interrupt_enable(level); - return RT_ENOSYS; - } - - irqmap = &pin_irq_map[irqindex]; - - /* Configure GPIO_InitStructure */ - GPIO_InitStruct.GPIO_Speed = GPIO_SPEED_10MHZ; - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IN_FLOATING; - - EXTI_InitParaStruct.EXTI_LINEEnable = ENABLE; - GPIO_EXTILineConfig(PIN_PORT(pin), PIN_NO(pin)); - switch (pin_irq_hdr_tab[irqindex].mode) - { - case PIN_IRQ_MODE_RISING: - EXTI_InitParaStruct.EXTI_Trigger = EXTI_Trigger_Rising; - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IPD; - EXTI_Init(&EXTI_InitParaStruct); - break; - case PIN_IRQ_MODE_FALLING: - GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IPU; - EXTI_InitParaStruct.EXTI_Trigger = EXTI_Trigger_Falling; - EXTI_Init(&EXTI_InitParaStruct); - break; - case PIN_IRQ_MODE_RISING_FALLING: - EXTI_InitParaStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; - EXTI_Init(&EXTI_InitParaStruct); - break; - default: - break; - } - GPIO_Init(PIN_GDPORT(pin), &GPIO_InitStruct); - - NVIC_SetPriority(irqmap->irqno, 0); - NVIC_EnableIRQ(irqmap->irqno); - pin_irq_enable_mask |= irqmap->pinbit; - - rt_hw_interrupt_enable(level); - } - else if (enabled == PIN_IRQ_DISABLE) - { - irqmap = get_pin_irq_map(PIN_GDPIN(pin)); - if (irqmap == RT_NULL) - { - return RT_ENOSYS; - } - - level = rt_hw_interrupt_disable(); - - EXTI_InitParaStruct.EXTI_LINEEnable = DISABLE; - EXTI_Init(&EXTI_InitParaStruct); - - pin_irq_enable_mask &= ~irqmap->pinbit; - if ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9)) - { - if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9))) - { - NVIC_DisableIRQ(irqmap->irqno); - } - } - else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15)) - { - if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15))) - { - NVIC_DisableIRQ(irqmap->irqno); - } - } - else - { - NVIC_DisableIRQ(irqmap->irqno); - } - rt_hw_interrupt_enable(level); - } - else - { - return -RT_ENOSYS; - } - - return RT_EOK; -} -const static struct rt_pin_ops _gd32_pin_ops = -{ - gd32_pin_mode, - gd32_pin_write, - gd32_pin_read, - gd32_pin_attach_irq, - gd32_pin_dettach_irq, - gd32_pin_irq_enable, - gd32_pin_get, -}; - -rt_inline void pin_irq_hdr(int irqno) -{ - if (pin_irq_hdr_tab[irqno].hdr) - { - pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args); - } -} - -/** - * @brief This function handles EXTI interrupt request. - * @param gpio_pin: Specifies the pins connected EXTI line - * @retval none - */ -void gd32_pin_exti_irqhandler(uint16_t gpio_pin) -{ - if (SET == EXTI_GetIntBitState(gpio_pin)) - { - EXTI_ClearIntBitState(gpio_pin); - pin_irq_hdr(bit2bitno(gpio_pin)); - } -} - -void EXTI0_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_0); - rt_interrupt_leave(); -} - -void EXTI1_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_1); - rt_interrupt_leave(); -} - -void EXTI2_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_2); - rt_interrupt_leave(); -} - -void EXTI3_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_3); - rt_interrupt_leave(); -} - -void EXTI4_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_4); - rt_interrupt_leave(); -} - -void EXTI5_9_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_5); - gd32_pin_exti_irqhandler(GPIO_PIN_6); - gd32_pin_exti_irqhandler(GPIO_PIN_7); - gd32_pin_exti_irqhandler(GPIO_PIN_8); - gd32_pin_exti_irqhandler(GPIO_PIN_9); - rt_interrupt_leave(); -} - -void EXTI10_15_IRQHandler(void) -{ - rt_interrupt_enter(); - gd32_pin_exti_irqhandler(GPIO_PIN_10); - gd32_pin_exti_irqhandler(GPIO_PIN_11); - gd32_pin_exti_irqhandler(GPIO_PIN_12); - gd32_pin_exti_irqhandler(GPIO_PIN_13); - gd32_pin_exti_irqhandler(GPIO_PIN_14); - gd32_pin_exti_irqhandler(GPIO_PIN_15); - rt_interrupt_leave(); -} - -int rt_hw_pin_init(void) -{ -#if defined(GPIOG) - rcu_periph_clock_enable(RCU_GPIOG); -#endif -#if defined(GPIOF) - rcu_periph_clock_enable(RCU_GPIOF); -#endif -#if defined(GPIOE) - rcu_periph_clock_enable(RCU_GPIOE); -#endif -#if defined(GPIOD) - rcu_periph_clock_enable(RCU_GPIOD); -#endif -#if defined(GPIOC) - rcu_periph_clock_enable(RCU_GPIOC); -#endif -#if defined(GPIOB) - rcu_periph_clock_enable(RCU_GPIOB); -#endif -#if defined(GPIOA) - rcu_periph_clock_enable(RCU_GPIOA); -#endif - rcu_periph_clock_enable(RCU_AF); - return rt_device_pin_register("pin", &_gd32_pin_ops, RT_NULL); -} -INIT_BOARD_EXPORT(rt_hw_pin_init); -#endif /* RT_USING_PIN */ - diff --git a/bsp/gd32103c-eval/drivers/drv_gpio.h b/bsp/gd32103c-eval/drivers/drv_gpio.h deleted file mode 100644 index 34d30d63d4..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_gpio.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020-12-27 iysheng first release - */ - -#ifndef __DRV_GPIO_H__ -#define __DRV_GPIO_H__ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define __GD32_PORT(port) GPIO##port##_BASE - -#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__GD32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN) - -#define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu))) -#define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu)) -#define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) - -#define PIN_GDPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin)))) -#define PIN_GDPIN(pin) ((uint16_t)(1u << PIN_NO(pin))) - -struct pin_irq_map -{ - rt_uint16_t pinbit; - IRQn_Type irqno; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* __DRV_GPIO_H__ */ - diff --git a/bsp/gd32103c-eval/drivers/drv_hwtimer.h b/bsp/gd32103c-eval/drivers/drv_hwtimer.h deleted file mode 100644 index 1b1a7e7da9..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_hwtimer.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-15 iysheng first release - */ - -#ifndef __DRV_HWTIMER_H__ -#define __DRV_HWTIMER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef struct { - TIMER_TypeDef *reg_base; - IRQn_Type irqn; - rcu_periph_enum rcu; -} gd32_hwtimer_data; - -typedef struct { - char dev_name[RT_NAME_MAX]; - const gd32_hwtimer_data hw_data; - rt_hwtimer_t hwtimer_dev; - const struct rt_hwtimer_info hwtimer_info; -} gd32_hwtimer_device; - -#ifdef __cplusplus -} -#endif - -#endif /* __DRV_HWTIMER_H__ */ - diff --git a/bsp/gd32103c-eval/drivers/drv_usart.c b/bsp/gd32103c-eval/drivers/drv_usart.c deleted file mode 100644 index c89ce02e0c..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_usart.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-04 iysheng first version - */ - -#include -#include -#include - -#ifdef RT_USING_SERIAL - -#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && \ - !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && \ - !defined(BSP_USING_UART4) - #error "Please define at least one UARTx" - -#endif - -#include - -static void uart_isr(struct rt_serial_device *serial); - -#if defined(BSP_USING_UART0) -struct rt_serial_device serial0; - -void USART0_IRQHandler(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - uart_isr(&serial0); - - /* leave interrupt */ - rt_interrupt_leave(); -} - -#endif /* BSP_USING_UART0 */ - -#if defined(BSP_USING_UART1) -struct rt_serial_device serial1; - -void USART1_IRQHandler(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - uart_isr(&serial1); - - /* leave interrupt */ - rt_interrupt_leave(); -} - -#endif /* BSP_USING_UART1 */ - -#if defined(BSP_USING_UART2) -struct rt_serial_device serial2; - -void USART2_IRQHandler(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - uart_isr(&serial2); - - /* leave interrupt */ - rt_interrupt_leave(); -} - -#endif /* BSP_USING_UART2 */ - -#if defined(BSP_USING_UART3) -struct rt_serial_device serial3; - -void UART3_IRQHandler(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - uart_isr(&serial3); - - /* leave interrupt */ - rt_interrupt_leave(); -} - -#endif /* BSP_USING_UART3 */ - -#if defined(BSP_USING_UART4) -struct rt_serial_device serial4; - -void UART4_IRQHandler(void) -{ - /* enter interrupt */ - rt_interrupt_enter(); - - uart_isr(&serial4); - - /* leave interrupt */ - rt_interrupt_leave(); -} -#endif /* BSP_USING_UART4 */ - -static const struct gd32_uart uarts[] = { -#ifdef BSP_USING_UART0 - { - USART0, /* uart peripheral index */ - USART0_IRQn, /* uart iqrn */ - RCU_USART0, RCU_GPIOA, RCU_GPIOA, /* periph clock, tx gpio clock, rt gpio clock */ - GPIOA, GPIOA, /* tx port, tx alternate, tx pin */ - GPIO_PIN_9, GPIO_PIN_10, /* rx port, rx alternate, rx pin */ - &serial0, - "uart0", - }, -#endif - -#ifdef BSP_USING_UART1 - { - USART1, /* uart peripheral index */ - USART1_IRQn, /* uart iqrn */ - RCU_USART1, RCU_GPIOA, RCU_GPIOA, /* periph clock, tx gpio clock, rt gpio clock */ - GPIOA, GPIOA, /* tx port, tx alternate, tx pin */ - GPIO_PIN_2, GPIO_PIN_3, /* rx port, rx alternate, rx pin */ - &serial1, - "uart1", - }, -#endif - -#ifdef BSP_USING_UART2 - { - USART2, /* uart peripheral index */ - USART2_IRQn, /* uart iqrn */ - RCU_USART2, RCU_GPIOB, RCU_GPIOB, /* periph clock, tx gpio clock, rt gpio clock */ - GPIOB, GPIOB, /* tx port, tx alternate, tx pin */ - GPIO_PIN_10, GPIO_PIN_11, /* rx port, rx alternate, rx pin */ - &serial2, - "uart2", - }, -#endif - -#ifdef BSP_USING_UART3 - { - UART3, /* uart peripheral index */ - UART3_IRQn, /* uart iqrn */ - RCU_UART3, RCU_GPIOC, RCU_GPIOC, /* periph clock, tx gpio clock, rt gpio clock */ - GPIOC, GPIOC, /* tx port, tx alternate, tx pin */ - GPIO_PIN_10, GPIO_PIN_11, /* rx port, rx alternate, rx pin */ - &serial3, - "uart3", - }, -#endif - -#ifdef BSP_USING_UART4 - { - UART4, /* uart peripheral index */ - UART4_IRQn, /* uart iqrn */ - RCU_UART4, RCU_GPIOC, RCU_GPIOD, /* periph clock, tx gpio clock, rt gpio clock */ - GPIOC, GPIOD, /* tx port, tx alternate, tx pin */ - GPIO_PIN_12, GPIO_PIN_2, /* rx port, rx alternate, rx pin */ - &serial4, - "uart4", - }, -#endif -}; - -/** -* @brief UART MSP Initialization -* This function configures the hardware resources used in this example: -* - Peripheral's clock enable -* - Peripheral's GPIO Configuration -* - NVIC configuration for UART interrupt request enable -* @param huart: UART handle pointer -* @retval None -*/ -void gd32_uart_gpio_init(struct gd32_uart *uart) -{ - GPIO_TypeDef *GPIOx; - GPIO_InitPara GPIO_InitStructure = {0}; - /* enable USART clock */ - rcu_periph_clock_enable(uart->tx_gpio_clk); - rcu_periph_clock_enable(uart->rx_gpio_clk); - rcu_periph_clock_enable(uart->per_clk); - - GPIOx = (GPIO_TypeDef *)uart->tx_port; - GPIO_InitStructure.GPIO_Pin = uart->tx_pin; - GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_10MHZ; - GPIO_Init(GPIOx, &GPIO_InitStructure); - /* TODO 初始化 RX */ - GPIOx = (GPIO_TypeDef *)uart->rx_port; - GPIO_InitStructure.GPIO_Pin = uart->rx_pin; - GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN_FLOATING; - GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_10MHZ; - GPIO_Init(GPIOx, &GPIO_InitStructure); - - NVIC_SetPriority(uart->irqn, 0); - NVIC_EnableIRQ(uart->irqn); -} - -static rt_err_t gd32_configure(struct rt_serial_device *serial, struct serial_configure *cfg) -{ - struct gd32_uart *uart; - USART_TypeDef *USARTx; - USART_InitPara USART_InitParaStruct = {0}; - - RT_ASSERT(serial != RT_NULL); - RT_ASSERT(cfg != RT_NULL); - - uart = (struct gd32_uart *)serial->parent.user_data; - gd32_uart_gpio_init(uart); - - USARTx = (USART_TypeDef *)uart->uart_periph; - USART_InitParaStruct.USART_BRR = cfg->baud_rate; - - switch (cfg->data_bits) { - case DATA_BITS_9: - USART_InitParaStruct.USART_WL = USART_WL_9B; - break; - - default: - USART_InitParaStruct.USART_WL = USART_WL_8B; - break; - } - - switch (cfg->stop_bits) { - case STOP_BITS_2: - USART_InitParaStruct.USART_STBits = USART_STBITS_2; - break; - default: - USART_InitParaStruct.USART_STBits = USART_STBITS_1; - break; - } - - switch (cfg->parity) { - case PARITY_ODD: - USART_InitParaStruct.USART_Parity = USART_PARITY_SETODD; - break; - case PARITY_EVEN: - USART_InitParaStruct.USART_Parity = USART_PARITY_SETEVEN; - break; - default: - USART_InitParaStruct.USART_Parity = USART_PARITY_RESET; - break; - } - - USART_InitParaStruct.USART_HardwareFlowControl = USART_HARDWAREFLOWCONTROL_NONE; - USART_InitParaStruct.USART_RxorTx = USART_RXORTX_RX | USART_RXORTX_TX; - USART_Init(USARTx, &USART_InitParaStruct); - USART_Enable(USARTx, ENABLE); - - return RT_EOK; -} - -static rt_err_t gd32_control(struct rt_serial_device *serial, int cmd, void *arg) -{ - struct gd32_uart *uart; - USART_TypeDef *USARTx; - - RT_ASSERT(serial != RT_NULL); - uart = (struct gd32_uart *)serial->parent.user_data; - USARTx = (USART_TypeDef *)uart->uart_periph; - - switch (cmd) { - case RT_DEVICE_CTRL_CLR_INT: - /* disable rx irq */ - NVIC_DisableIRQ(uart->irqn); - /* disable interrupt */ - USART_INT_Set(USARTx, USART_INT_RBNE, DISABLE); - break; - case RT_DEVICE_CTRL_SET_INT: - /* enable rx irq */ - NVIC_EnableIRQ(uart->irqn); - /* enable interrupt */ - USART_INT_Set(USARTx, USART_INT_RBNE, ENABLE); - break; - } - - return RT_EOK; -} - -static int gd32_putc(struct rt_serial_device *serial, char ch) -{ - struct gd32_uart *uart; - - RT_ASSERT(serial != RT_NULL); - uart = (struct gd32_uart *)serial->parent.user_data; - - - USART_DataSend((USART_TypeDef *)uart->uart_periph, ch); - while ((USART_GetBitState(uart->uart_periph, USART_FLAG_TC) == RESET)); - - return 1; -} - -static int gd32_getc(struct rt_serial_device *serial) -{ - int ch; - struct gd32_uart *uart; - - RT_ASSERT(serial != RT_NULL); - uart = (struct gd32_uart *)serial->parent.user_data; - - ch = -1; - if (USART_GetBitState(uart->uart_periph, USART_FLAG_RBNE) != RESET) - ch = USART_DataReceive(uart->uart_periph); - return ch; -} - -/** - * Uart common interrupt process. This need add to uart ISR. - * - * @param serial serial device - */ -static void uart_isr(struct rt_serial_device *serial) -{ - struct gd32_uart *uart = (struct gd32_uart *) serial->parent.user_data; - - RT_ASSERT(uart != RT_NULL); - - if ((USART_GetIntBitState((USART_TypeDef *)uart->uart_periph, USART_INT_RBNE) != RESET) && - (USART_GetBitState((USART_TypeDef *)uart->uart_periph, USART_FLAG_RBNE) != RESET)) { - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); - /* Clear RXNE interrupt flag */ - USART_ClearBitState(uart->uart_periph, USART_FLAG_RBNE); - } -} - -static const struct rt_uart_ops gd32_uart_ops = { - gd32_configure, - gd32_control, - gd32_putc, - gd32_getc, -}; - -int gd32_hw_usart_init(void) -{ - struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; - int i; - - - for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) { - uarts[i].serial->ops = &gd32_uart_ops; - uarts[i].serial->config = config; - - /* register UART device */ - rt_hw_serial_register(uarts[i].serial, - uarts[i].device_name, - RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, - (void *)&uarts[i]); - } - - return 0; -} -INIT_BOARD_EXPORT(gd32_hw_usart_init); -#endif diff --git a/bsp/gd32103c-eval/drivers/drv_usart.h b/bsp/gd32103c-eval/drivers/drv_usart.h deleted file mode 100644 index ad3455db60..0000000000 --- a/bsp/gd32103c-eval/drivers/drv_usart.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-04 iysheng first version - */ - -#ifndef __USART_H__ -#define __USART_H__ - -#include -#include - -/* GD32 uart driver */ -struct gd32_uart { - USART_TypeDef * uart_periph; - IRQn_Type irqn; - rcu_periph_enum per_clk; - rcu_periph_enum tx_gpio_clk; - rcu_periph_enum rx_gpio_clk; - GPIO_TypeDef * tx_port; - GPIO_TypeDef * rx_port; - uint16_t tx_pin; - uint16_t rx_pin; - - struct rt_serial_device *serial; - char *device_name; -}; - -#endif diff --git a/bsp/gd32103c-eval/gd32_rom.ld b/bsp/gd32103c-eval/gd32_rom.ld deleted file mode 100644 index 875d239e58..0000000000 --- a/bsp/gd32103c-eval/gd32_rom.ld +++ /dev/null @@ -1,146 +0,0 @@ -/* - * linker script for GD32F1xx with GNU ld - * - * Change Logs: - * Date Author Notes - * 2009-10-14 bernard.xiong first implementation - * 2021-01-02 iysheng modify to suite gd32f103c - */ - -/* Program Entry, set to mark it as "used" and avoid gc */ -MEMORY -{ - CODE (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* 256KB flash */ - DATA (rw) : ORIGIN = 0x20000000, LENGTH = 48k /* 48KB sram */ -} -ENTRY(Reset_Handler) -_system_stack_size = 0x200; - -SECTIONS -{ - .text : - { - . = ALIGN(4); - _stext = .; - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - *(.text) /* remaining code */ - *(.text.*) /* remaining code */ - *(.rodata) /* read-only data (constants) */ - *(.rodata*) - *(.glue_7) - *(.glue_7t) - *(.gnu.linkonce.t*) - - /* section information for finsh shell */ - . = ALIGN(4); - __fsymtab_start = .; - KEEP(*(FSymTab)) - __fsymtab_end = .; - . = ALIGN(4); - __vsymtab_start = .; - KEEP(*(VSymTab)) - __vsymtab_end = .; - . = ALIGN(4); - - /* section information for initial. */ - . = ALIGN(4); - __rt_init_start = .; - KEEP(*(SORT(.rti_fn*))) - __rt_init_end = .; - . = ALIGN(4); - - . = ALIGN(4); - _etext = .; - } > CODE = 0 - - /* .ARM.exidx is sorted, so has to go in its own output section. */ - __exidx_start = .; - .ARM.exidx : - { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - - /* This is used by the startup in order to initialize the .data secion */ - _sidata = .; - } > CODE - __exidx_end = .; - - /* .data section which is used for initialized data */ - - .data : AT (_sidata) - { - . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ - _sdata = . ; - - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - - . = ALIGN(4); - /* This is used by the startup in order to initialize the .data secion */ - _edata = . ; - } >DATA - - .stack : - { - . = . + _system_stack_size; - . = ALIGN(4); - _estack = .; - } >DATA - - __bss_start = .; - .bss : - { - . = ALIGN(4); - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; - - *(.bss) - *(.bss.*) - *(COMMON) - - . = ALIGN(4); - /* This is used by the startup in order to initialize the .bss secion */ - _ebss = . ; - - *(.bss.init) - } > DATA - __bss_end = .; - - _end = .; - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - * Symbols in the DWARF debugging sections are relative to the beginning - * of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} diff --git a/bsp/gd32103c-eval/rtconfig.h b/bsp/gd32103c-eval/rtconfig.h deleted file mode 100644 index 8f2fc9739e..0000000000 --- a/bsp/gd32103c-eval/rtconfig.h +++ /dev/null @@ -1,208 +0,0 @@ -#ifndef RT_CONFIG_H__ -#define RT_CONFIG_H__ - -/* Automatically generated file; DO NOT EDIT. */ -/* RT-Thread Configuration */ - -/* RT-Thread Kernel */ - -#define RT_NAME_MAX 8 -#define RT_ALIGN_SIZE 4 -#define RT_THREAD_PRIORITY_32 -#define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 -#define RT_USING_OVERFLOW_CHECK -#define RT_USING_HOOK -#define RT_HOOK_USING_FUNC_PTR -#define RT_USING_IDLE_HOOK -#define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 256 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 512 - -/* kservice optimization */ - -#define RT_DEBUG - -/* Inter-Thread communication */ - -#define RT_USING_SEMAPHORE -#define RT_USING_MUTEX -#define RT_USING_EVENT -#define RT_USING_MAILBOX -#define RT_USING_MESSAGEQUEUE - -/* Memory Management */ - -#define RT_USING_MEMPOOL -#define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP -#define RT_USING_HEAP - -/* Kernel Device Object */ - -#define RT_USING_DEVICE -#define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 128 -#define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x40100 - -/* RT-Thread Components */ - -#define RT_USING_COMPONENTS_INIT -#define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 2048 -#define RT_MAIN_THREAD_PRIORITY 10 - -/* C++ features */ - - -/* Command shell */ - -#define RT_USING_FINSH -#define RT_USING_MSH -#define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 -#define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 -#define FINSH_USING_SYMTAB -#define FINSH_CMD_SIZE 80 -#define MSH_USING_BUILT_IN_COMMANDS -#define FINSH_USING_DESCRIPTION -#define FINSH_ARG_MAX 10 - -/* Device virtual file system */ - -#define RT_USING_DFS -#define DFS_USING_POSIX -#define DFS_USING_WORKDIR -#define DFS_FILESYSTEMS_MAX 2 -#define DFS_FILESYSTEM_TYPES_MAX 2 -#define DFS_FD_MAX 16 -#define RT_USING_DFS_DEVFS - -/* Device Drivers */ - -#define RT_USING_DEVICE_IPC -#define RT_USING_SERIAL -#define RT_USING_SERIAL_V1 -#define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_PIN - -/* Using USB */ - - -/* POSIX layer and C standard library */ - -#define RT_LIBC_DEFAULT_TIMEZONE 8 - -/* POSIX (Portable Operating System Interface) layer */ - - -/* Interprocess Communication (IPC) */ - - -/* Socket is in the 'Network' category */ - -/* Network */ - -/* Socket abstraction layer */ - - -/* Network interface device */ - - -/* light weight TCP/IP stack */ - - -/* AT commands */ - - -/* VBUS(Virtual Software BUS) */ - - -/* Utilities */ - - -/* RT-Thread Utestcases */ - - -/* RT-Thread online packages */ - -/* IoT - internet of things */ - - -/* Wi-Fi */ - -/* Marvell WiFi */ - - -/* Wiced WiFi */ - - -/* IoT Cloud */ - - -/* security packages */ - - -/* language packages */ - - -/* multimedia packages */ - -/* LVGL: powerful and easy-to-use embedded GUI library */ - - -/* u8g2: a monochrome graphic library */ - - -/* PainterEngine: A cross-platform graphics application framework written in C language */ - - -/* tools packages */ - - -/* system packages */ - -/* enhanced kernel services */ - - -/* POSIX extension functions */ - - -/* acceleration: Assembly language or algorithmic acceleration packages */ - - -/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */ - - -/* Micrium: Micrium software products porting for RT-Thread */ - - -/* peripheral libraries and drivers */ - - -/* AI packages */ - - -/* miscellaneous packages */ - -/* samples: kernel and components samples */ - - -/* entertainment: terminal games and other interesting software packages */ - -#define SOC_SERIES_GD32F1 -#define SOC_GD32103C - -/* On-chip Peripheral Drivers */ - -#define BSP_USING_UART -#define BSP_USING_UART0 - -#endif diff --git a/bsp/gd32103c-eval/rtconfig.py b/bsp/gd32103c-eval/rtconfig.py deleted file mode 100644 index 7e8934c873..0000000000 --- a/bsp/gd32103c-eval/rtconfig.py +++ /dev/null @@ -1,126 +0,0 @@ -import os - -# toolchains options -ARCH='arm' -CPU='cortex-m3' -CROSS_TOOL='gcc' - -if os.getenv('RTT_CC'): - CROSS_TOOL = os.getenv('RTT_CC') - -# cross_tool provides the cross compiler -# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR -if CROSS_TOOL == 'gcc': - PLATFORM = 'gcc' - EXEC_PATH = r'D:/toolchain/gnu_tools_arm_embedded/5.4_2016q3/bin' -elif CROSS_TOOL == 'keil': - PLATFORM = 'armcc' - EXEC_PATH = r'C:/Keil_v5' -elif CROSS_TOOL == 'iar': - PLATFORM = 'iar' - EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.0' - -if os.getenv('RTT_EXEC_PATH'): - EXEC_PATH = os.getenv('RTT_EXEC_PATH') - -BUILD = 'debug' - -if PLATFORM == 'gcc': - # tool-chains - PREFIX = 'arm-none-eabi-' - CC = PREFIX + 'gcc' - AS = PREFIX + 'gcc' - AR = PREFIX + 'ar' - LINK = PREFIX + 'gcc' - TARGET_EXT = 'elf' - SIZE = PREFIX + 'size' - OBJDUMP = PREFIX + 'objdump' - OBJCPY = PREFIX + 'objcopy' - - DEVICE = ' -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections' - CFLAGS = DEVICE + ' -Dgcc' # -D' + PART_TYPE - AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb ' - LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-gd32.map,-cref,-u,Reset_Handler -T gd32_rom.ld' - - CPATH = '' - LPATH = '' - - if BUILD == 'debug': - CFLAGS += ' -O0 -gdwarf-2 -g' - AFLAGS += ' -gdwarf-2' - else: - CFLAGS += ' -O2' - - POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n' - -elif PLATFORM == 'armcc': - # toolchains - CC = 'armcc' - AS = 'armasm' - AR = 'armar' - LINK = 'armlink' - TARGET_EXT = 'axf' - - DEVICE = ' --cpu Cortex-M4' - CFLAGS = DEVICE + ' --apcs=interwork' - AFLAGS = DEVICE - LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-gd32.map --scatter gd32_rom.sct' - - LFLAGS += ' --keep *.o(.rti_fn.*) --keep *.o(FSymTab) --keep *.o(VSymTab)' - - EXEC_PATH += '/ARM/ARMCC/bin' - print(EXEC_PATH) - - CFLAGS += ' --c99' - - if BUILD == 'debug': - CFLAGS += ' -g -O0' - AFLAGS += ' -g' - else: - CFLAGS += ' -O2' - - POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET' - -elif PLATFORM == 'iar': - # toolchains - CC = 'iccarm' - AS = 'iasmarm' - AR = 'iarchive' - LINK = 'ilinkarm' - TARGET_EXT = 'out' - - DEVICE = ' -D USE_STDPERIPH_DRIVER' + ' -D GD32F30X_HD' - - CFLAGS = DEVICE - CFLAGS += ' --diag_suppress Pa050' - CFLAGS += ' --no_cse' - CFLAGS += ' --no_unroll' - CFLAGS += ' --no_inline' - CFLAGS += ' --no_code_motion' - CFLAGS += ' --no_tbaa' - CFLAGS += ' --no_clustering' - CFLAGS += ' --no_scheduling' - CFLAGS += ' --debug' - CFLAGS += ' --endian=little' - CFLAGS += ' --cpu=Cortex-M4' - CFLAGS += ' -e' - CFLAGS += ' --fpu=None' - CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' - CFLAGS += ' -Ol' - CFLAGS += ' --use_c++_inline' - - AFLAGS = '' - AFLAGS += ' -s+' - AFLAGS += ' -w+' - AFLAGS += ' -r' - AFLAGS += ' --cpu Cortex-M4' - AFLAGS += ' --fpu None' - - LFLAGS = ' --config gd32_rom.icf' - LFLAGS += ' --redirect _Printf=_PrintfTiny' - LFLAGS += ' --redirect _Scanf=_ScanfSmall' - LFLAGS += ' --entry __iar_program_start' - - EXEC_PATH += '/arm/bin/' - POST_ACTION = '' - From c06b57670ff3c51c0deb5fefff8b47dc23ca8e64 Mon Sep 17 00:00:00 2001 From: LeeChunHei Date: Wed, 26 Jan 2022 10:46:57 +0800 Subject: [PATCH 60/65] =?UTF-8?q?=E4=BF=AE=E6=94=B9bsp=E7=9A=84usb=20host?= =?UTF-8?q?=20=E9=A9=85=E5=8B=95=20(#4379)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add arg for rt_usb_host_init call --- bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c | 2 +- bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c | 2 +- bsp/rx/applications/application.c | 2 +- bsp/stm32/libraries/HAL_Drivers/drv_usbh.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c index c82a706c9b..c30bba60c8 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c @@ -880,7 +880,7 @@ int nu_usbh_register(void) RT_ASSERT(res == RT_EOK); /*initialize the usb host function */ - res = rt_usb_host_init(); + res = rt_usb_host_init("usbh"); RT_ASSERT(res == RT_EOK); #if defined(RT_USING_PM) diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c index a5660ba328..85a1af96be 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c @@ -942,7 +942,7 @@ int nu_usbh_register(void) /*initialize the usb host function */ - res = rt_usb_host_init(); + res = rt_usb_host_init("usbh"); RT_ASSERT(res == RT_EOK); #if defined(RT_USING_PM) diff --git a/bsp/rx/applications/application.c b/bsp/rx/applications/application.c index 77bbbfd301..0d8043de91 100644 --- a/bsp/rx/applications/application.c +++ b/bsp/rx/applications/application.c @@ -119,7 +119,7 @@ void rt_init_thread_entry(void* parameter) #endif #ifdef RT_USING_USB_HOST - rt_usb_host_init(); + rt_usb_host_init("usbh"); #endif #ifdef RT_USING_FINSH diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usbh.c b/bsp/stm32/libraries/HAL_Drivers/drv_usbh.c index 9486e1a56d..1f169d2e6b 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usbh.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usbh.c @@ -247,7 +247,7 @@ int stm_usbh_register(void) return -RT_ERROR; } - rt_usb_host_init(); + rt_usb_host_init("usbh"); return RT_EOK; } From 0e30fac0696d8e1df640303fcd2f3d903906a5ee Mon Sep 17 00:00:00 2001 From: iysheng Date: Tue, 25 Jan 2022 22:40:21 +0800 Subject: [PATCH 61/65] [tools] Remove has_key methods to improve compatibility with Scons version --- tools/makefile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/makefile.py b/tools/makefile.py index 97001892c9..78dbd2228a 100644 --- a/tools/makefile.py +++ b/tools/makefile.py @@ -51,11 +51,11 @@ def TargetMakefile(env): if 'CXXFLAGS' in dir(rtconfig): make.write('CXXFLAGS :=%s' % (rtconfig.CXXFLAGS)) make.write('\n') - if env.has_key('LIBS'): + if ('LIBS' in env): make.write('EXTERN_LIB := ') for tlib in env['LIBS']: make.write('-l%s ' % (tlib)) - if env.has_key('LIBPATH'): + if ('LIBPATH' in env): for tlibpath in env['LIBPATH']: make.write('-L%s ' % (tlibpath)) make.write('\n') From 2f6f9da5e3fd581f74ed44e233c0df3fd247b63e Mon Sep 17 00:00:00 2001 From: guozhanxin Date: Wed, 26 Jan 2022 11:00:16 +0800 Subject: [PATCH 62/65] fix usbhost issue by #4378 --- bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c | 2 +- bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c | 2 +- components/drivers/usb/usbhost/core/driver.c | 2 +- components/drivers/usb/usbhost/core/hub.c | 2 +- components/drivers/usb/usbhost/core/usbhost.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c index 964bb7ba05..fe5895dc9d 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c @@ -866,7 +866,7 @@ int nu_usbh_register(void) RT_ASSERT(res == RT_EOK); /*initialize the usb host function */ - res = rt_usb_host_init(); + res = rt_usb_host_init("usbh"); RT_ASSERT(res == RT_EOK); #if defined(RT_USING_PM) diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c index a5660ba328..85a1af96be 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c @@ -942,7 +942,7 @@ int nu_usbh_register(void) /*initialize the usb host function */ - res = rt_usb_host_init(); + res = rt_usb_host_init("usbh"); RT_ASSERT(res == RT_EOK); #if defined(RT_USING_PM) diff --git a/components/drivers/usb/usbhost/core/driver.c b/components/drivers/usb/usbhost/core/driver.c index 102e388154..73360d307a 100644 --- a/components/drivers/usb/usbhost/core/driver.c +++ b/components/drivers/usb/usbhost/core/driver.c @@ -144,4 +144,4 @@ ucd_t rt_usbh_class_driver_find(int class_code, int subclass_code) /* not found */ return RT_NULL; -} \ No newline at end of file +} diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c index bf48bc4c61..eca06f6564 100644 --- a/components/drivers/usb/usbhost/core/hub.c +++ b/components/drivers/usb/usbhost/core/hub.c @@ -718,4 +718,4 @@ void rt_usbh_hub_init(uhcd_t hcd) /* startup usb host thread */ rt_thread_startup(thread); } -} \ No newline at end of file +} diff --git a/components/drivers/usb/usbhost/core/usbhost.c b/components/drivers/usb/usbhost/core/usbhost.c index 84b9640b76..9a4c166acd 100644 --- a/components/drivers/usb/usbhost/core/usbhost.c +++ b/components/drivers/usb/usbhost/core/usbhost.c @@ -65,4 +65,4 @@ rt_err_t rt_usb_host_init(const char *name) rt_device_init(uhc); return RT_EOK; -} \ No newline at end of file +} From 3000140bfdbe27294e54c16968c05d5efbd2dddb Mon Sep 17 00:00:00 2001 From: LeeChunHei Date: Wed, 26 Jan 2022 11:49:22 +0800 Subject: [PATCH 63/65] =?UTF-8?q?=E7=88=B2imxrt=E7=B3=BB=E5=88=97=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0usb=20host=E9=A9=85=E5=8B=95=20(#4377)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * adding fsl_os_abstraction porting * port usbh to imxrt Co-authored-by: guo --- .../MIMXRT1052/drivers/fsl_os_abstraction.h | 812 +++++++ .../drivers/fsl_os_abstraction_config.h | 36 + .../drivers/fsl_os_abstraction_rtthread.c | 917 ++++++++ .../drivers/fsl_os_abstraction_rtthread.h | 130 ++ .../MIMXRT1052/drivers/generic_list.c | 475 ++++ .../MIMXRT1052/drivers/generic_list.h | 203 ++ bsp/imxrt/libraries/MIMXRT1050/SConscript | 4 + bsp/imxrt/libraries/drivers/SConscript | 8 +- bsp/imxrt/libraries/drivers/drv_usbh.c | 730 ++++++ bsp/imxrt/libraries/drivers/drv_usbh.h | 22 + .../libraries/drivers/usb/host/usb_host.h | 141 +- .../drivers/usb/host/usb_host_devices.c | 674 +++--- .../drivers/usb/host/usb_host_devices.h | 41 +- .../drivers/usb/host/usb_host_ehci.c | 2038 +++++++++-------- .../drivers/usb/host/usb_host_ehci.h | 230 +- .../drivers/usb/host/usb_host_framework.c | 261 +++ .../drivers/usb/host/usb_host_framework.h | 131 ++ .../libraries/drivers/usb/host/usb_host_hci.c | 341 +-- .../libraries/drivers/usb/host/usb_host_hci.h | 46 +- bsp/imxrt/libraries/drivers/usb/include/usb.h | 3 +- .../drivers/usb/include/usb_host_config.h | 247 ++ .../libraries/drivers/usb/include/usb_misc.h | 338 +-- 22 files changed, 6069 insertions(+), 1759 deletions(-) create mode 100644 bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction.h create mode 100644 bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_config.h create mode 100644 bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.c create mode 100644 bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.h create mode 100644 bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.c create mode 100644 bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.h create mode 100644 bsp/imxrt/libraries/drivers/drv_usbh.c create mode 100644 bsp/imxrt/libraries/drivers/drv_usbh.h create mode 100644 bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.c create mode 100644 bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.h create mode 100644 bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h diff --git a/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction.h b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction.h new file mode 100644 index 0000000000..1efab708fe --- /dev/null +++ b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction.h @@ -0,0 +1,812 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_OS_ABSTRACTION_H_ +#define _FSL_OS_ABSTRACTION_H_ + +#include "fsl_common.h" +#include "fsl_os_abstraction_config.h" +#include "generic_list.h" + +/*! + * @addtogroup osa_adapter + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief Type for the Task Priority*/ +typedef uint16_t osa_task_priority_t; +/*! @brief Type for a task handler */ +typedef void *osa_task_handle_t; +/*! @brief Type for the parameter to be passed to the task at its creation */ +typedef void *osa_task_param_t; +/*! @brief Type for task pointer. Task prototype declaration */ +typedef void (*osa_task_ptr_t)(osa_task_param_t task_param); +/*! @brief Type for the semaphore handler */ +typedef void *osa_semaphore_handle_t; +/*! @brief Type for the mutex handler */ +typedef void *osa_mutex_handle_t; +/*! @brief Type for the event handler */ +typedef void *osa_event_handle_t; +/*! @brief Type for an event flags group, bit 32 is reserved. */ +typedef uint32_t osa_event_flags_t; +/*! @brief Message definition. */ +typedef void *osa_msg_handle_t; +/*! @brief Type for the message queue handler */ +typedef void *osa_msgq_handle_t; +/*! @brief Type for the Timer handler */ +typedef void *osa_timer_handle_t; +/*! @brief Type for the Timer callback function pointer. */ +typedef void (*osa_timer_fct_ptr_t)(void const *argument); +/*! @brief Thread Definition structure contains startup information of a thread.*/ +typedef struct osa_task_def_tag +{ + osa_task_ptr_t pthread; /*!< start address of thread function*/ + uint32_t tpriority; /*!< initial thread priority*/ + uint32_t instances; /*!< maximum number of instances of that thread function*/ + uint32_t stacksize; /*!< stack size requirements in bytes; 0 is default stack size*/ + uint32_t *tstack; /*!< stack pointer*/ + void *tlink; /*!< link pointer*/ + uint8_t *tname; /*!< name pointer*/ + uint8_t useFloat; /*!< is use float*/ +} osa_task_def_t; +/*! @brief Thread Link Definition structure .*/ +typedef struct osa_thread_link_tag +{ + uint8_t link[12]; /*!< link*/ + osa_task_handle_t osThreadId; /*!< thread id*/ + osa_task_def_t *osThreadDefHandle; /*!< pointer of thread define handle*/ + uint32_t *osThreadStackHandle; /*!< pointer of thread stack handle*/ +} osa_thread_link_t, *osa_thread_link_handle_t; + +/*! @brief Definition structure contains timer parameters.*/ +typedef struct osa_time_def_tag +{ + osa_timer_fct_ptr_t pfCallback; /* < start address of a timer function */ + void *argument; /* < argument of a timer function */ +} osa_time_def_t; + +/*! @brief Type for the timer definition*/ +typedef enum _osa_timer +{ + KOSA_TimerOnce = 0, /*!< one-shot timer*/ + KOSA_TimerPeriodic = 1 /*!< repeating timer*/ +} osa_timer_t; + +/*! @brief Defines the return status of OSA's functions */ +typedef enum _osa_status +{ + KOSA_StatusSuccess = kStatus_Success, /*!< Success */ + KOSA_StatusError = MAKE_STATUS(kStatusGroup_OSA, 1), /*!< Failed */ + KOSA_StatusTimeout = MAKE_STATUS(kStatusGroup_OSA, 2), /*!< Timeout occurs while waiting */ + KOSA_StatusIdle = MAKE_STATUS(kStatusGroup_OSA, 3), /*!< Used for bare metal only, the wait object is not ready + and timeout still not occur */ +} osa_status_t; + +#ifdef USE_RTOS +#undef USE_RTOS +#endif + +#define USE_RTOS (1) +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) +#define OSA_TASK_HANDLE_SIZE (12U) +#else +#define OSA_TASK_HANDLE_SIZE (16U) +#endif +#define OSA_EVENT_HANDLE_SIZE (8U) +#define OSA_SEM_HANDLE_SIZE (4U) +#define OSA_MUTEX_HANDLE_SIZE (4U) +#define OSA_MSGQ_HANDLE_SIZE (4U) +#define OSA_MSG_HANDLE_SIZE (0U) + +/*! @brief Priority setting for OSA. */ +#ifndef OSA_PRIORITY_IDLE +#define OSA_PRIORITY_IDLE (6) +#endif + +#ifndef OSA_PRIORITY_LOW +#define OSA_PRIORITY_LOW (5) +#endif + +#ifndef OSA_PRIORITY_BELOW_NORMAL +#define OSA_PRIORITY_BELOW_NORMAL (4) +#endif + +#ifndef OSA_PRIORITY_NORMAL +#define OSA_PRIORITY_NORMAL (3) +#endif + +#ifndef OSA_PRIORITY_ABOVE_NORMAL +#define OSA_PRIORITY_ABOVE_NORMAL (2) +#endif + +#ifndef OSA_PRIORITY_HIGH +#define OSA_PRIORITY_HIGH (1) +#endif + +#ifndef OSA_PRIORITY_REAL_TIME +#define OSA_PRIORITY_REAL_TIME (0) +#endif + +#ifndef OSA_TASK_PRIORITY_MAX +#define OSA_TASK_PRIORITY_MAX (0) +#endif + +#ifndef OSA_TASK_PRIORITY_MIN +#define OSA_TASK_PRIORITY_MIN (15) +#endif + +#define SIZE_IN_UINT32_UNITS(size) (((size) + sizeof(uint32_t) - 1) / sizeof(uint32_t)) + +/*! @brief Constant to pass as timeout value in order to wait indefinitely. */ +#define osaWaitForever_c ((uint32_t)(-1)) +#define osaEventFlagsAll_c ((osa_event_flags_t)(0x00FFFFFF)) +#define osThreadStackArray(name) osThread_##name##_stack +#define osThreadStackDef(name, stacksize, instances) \ + uint32_t osThreadStackArray(name)[SIZE_IN_UINT32_UNITS(stacksize) * (instances)]; + +/* ==== Thread Management ==== */ + +/* Create a Thread Definition with function, priority, and stack requirements. + * \param name name of the thread function. + * \param priority initial priority of the thread function. + * \param instances number of possible thread instances. + * \param stackSz stack size (in bytes) requirements for the thread function. + * \param useFloat + */ +#if defined(FSL_RTOS_MQX) +#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \ + osa_thread_link_t osThreadLink_##name[instances] = {0}; \ + osThreadStackDef(name, stackSz, instances) osa_task_def_t os_thread_def_##name = { \ + (name), (priority), (instances), (stackSz), osThreadStackArray(name), osThreadLink_##name, \ + (uint8_t *)#name, (useFloat)} +#elif defined(FSL_RTOS_UCOSII) +#if gTaskMultipleInstancesManagement_c +#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \ + osa_thread_link_t osThreadLink_##name[instances] = {0}; \ + osThreadStackDef(name, stackSz, instances) osa_task_def_t os_thread_def_##name = { \ + (name), (priority), (instances), (stackSz), osThreadStackArray(name), osThreadLink_##name, \ + (uint8_t *)#name, (useFloat)} +#else +#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \ + osThreadStackDef(name, stackSz, instances) osa_task_def_t os_thread_def_##name = { \ + (name), (priority), (instances), (stackSz), osThreadStackArray(name), NULL, (uint8_t *)#name, (useFloat)} +#endif +#else +#define OSA_TASK_DEFINE(name, priority, instances, stackSz, useFloat) \ + osa_task_def_t os_thread_def_##name = {(name), (priority), (instances), (stackSz), \ + NULL, NULL, (uint8_t *)#name, (useFloat)} +#endif +/* Access a Thread defintion. + * \param name name of the thread definition object. + */ +#define OSA_TASK(name) &os_thread_def_##name + +#define OSA_TASK_PROTO(name) externosa_task_def_t os_thread_def_##name +/* ==== Timer Management ==== + * Define a Timer object. + * \param name name of the timer object. + * \param function name of the timer call back function. + */ + +#define OSA_TIMER_DEF(name, function) osa_time_def_t os_timer_def_##name = {(function), NULL} + +/* Access a Timer definition. + * \param name name of the timer object. + */ +#define OSA_TIMER(name) &os_timer_def_##name + +/* ==== Buffer Definition ==== */ + +/*! + * @brief Defines the semaphore handle + * + * This macro is used to define a 4 byte aligned semaphore handle. + * Then use "(osa_semaphore_handle_t)name" to get the semaphore handle. + * + * The macro should be global and could be optional. You could also define semaphore handle by yourself. + * + * This is an example, + * @code + * OSA_SEMAPHORE_HANDLE_DEFINE(semaphoreHandle); + * @endcode + * + * @param name The name string of the semaphore handle. + */ +#define OSA_SEMAPHORE_HANDLE_DEFINE(name) \ + uint32_t name[(OSA_SEM_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)] + +/*! + * @brief Defines the mutex handle + * + * This macro is used to define a 4 byte aligned mutex handle. + * Then use "(osa_mutex_handle_t)name" to get the mutex handle. + * + * The macro should be global and could be optional. You could also define mutex handle by yourself. + * + * This is an example, + * @code + * OSA_MUTEX_HANDLE_DEFINE(mutexHandle); + * @endcode + * + * @param name The name string of the mutex handle. + */ +#define OSA_MUTEX_HANDLE_DEFINE(name) uint32_t name[(OSA_MUTEX_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)] + +/*! + * @brief Defines the event handle + * + * This macro is used to define a 4 byte aligned event handle. + * Then use "(osa_event_handle_t)name" to get the event handle. + * + * The macro should be global and could be optional. You could also define event handle by yourself. + * + * This is an example, + * @code + * OSA_EVENT_HANDLE_DEFINE(eventHandle); + * @endcode + * + * @param name The name string of the event handle. + */ +#define OSA_EVENT_HANDLE_DEFINE(name) uint32_t name[(OSA_EVENT_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)] + +/*! + * @brief Defines the message queue handle + * + * This macro is used to define a 4 byte aligned message queue handle. + * Then use "(osa_msgq_handle_t)name" to get the message queue handle. + * + * The macro should be global and could be optional. You could also define message queue handle by yourself. + * + * This is an example, + * @code + * OSA_MSGQ_HANDLE_DEFINE(msgqHandle, 3, sizeof(msgStruct)); + * @endcode + * + * @param name The name string of the message queue handle. + * @param numberOfMsgs Number of messages. + * @param msgSize Message size. + * + */ + +/*< Macro For FREE_RTOS*/ +#define OSA_MSGQ_HANDLE_DEFINE(name, numberOfMsgs, msgSize) \ + uint32_t name[(OSA_MSGQ_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)] + +/*! + * @brief Defines the TASK handle + * + * This macro is used to define a 4 byte aligned TASK handle. + * Then use "(osa_task_handle_t)name" to get the TASK handle. + * + * The macro should be global and could be optional. You could also define TASK handle by yourself. + * + * This is an example, + * @code + * OSA_TASK_HANDLE_DEFINE(taskHandle); + * @endcode + * + * @param name The name string of the TASK handle. + */ +#define OSA_TASK_HANDLE_DEFINE(name) uint32_t name[(OSA_TASK_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)] + +#include "fsl_os_abstraction_rtthread.h" + +extern const uint8_t gUseRtos_c; + +/* + * alloc the temporary memory to store the status + */ +#define OSA_SR_ALLOC() uint32_t osaCurrentSr; +/* + * Enter critical mode + */ +#define OSA_ENTER_CRITICAL() OSA_EnterCritical(&osaCurrentSr) +/* + * Exit critical mode and retore the previous mode + */ +#define OSA_EXIT_CRITICAL() OSA_ExitCritical(osaCurrentSr) + +/******************************************************************************* + * API + ******************************************************************************/ + +/*! + * @brief Reserves the requested amount of memory in bytes. + * + * The function is used to reserve the requested amount of memory in bytes and initializes it to 0. + * + * @param length Amount of bytes to reserve. + * + * @return Pointer to the reserved memory. NULL if memory can't be allocated. + */ +void *OSA_MemoryAllocate(uint32_t length); + +/*! + * @brief Frees the memory previously reserved. + * + * The function is used to free the memory block previously reserved. + * + * @param p Pointer to the start of the memory block previously reserved. + * + */ +void OSA_MemoryFree(void *p); + +/*! + * @brief Enter critical with nesting mode. + * + * @param sr Store current status and return to caller. + */ +void OSA_EnterCritical(uint32_t *sr); + +/*! + * @brief Exit critical with nesting mode. + * + * @param sr Previous status to restore. + */ +void OSA_ExitCritical(uint32_t sr); + +/*! + * @name Task management + * @{ + */ + +/*! + * @brief Creates a task. + * + * This function is used to create task based on the resources defined + * by the macro OSA_TASK_DEFINE. + * + * Example below shows how to use this API to create the task handle. + * @code + * OSA_TASK_HANDLE_DEFINE(taskHandle); + * OSA_TASK_DEFINE( Job1, OSA_PRIORITY_HIGH, 1, 800, 0); + * OSA_TaskCreate((osa_task_handle_t)taskHandle, OSA_TASK(Job1), (osa_task_param_t)NULL); + * @endcode + * + * @param taskHandle Pointer to a memory space of size OSA_TASK_HANDLE_SIZE allocated by the caller, task handle. + * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices. + * You can define the handle in the following two ways: + * #OSA_TASK_HANDLE_DEFINE(taskHandle); + * or + * uint32_t taskHandle[((OSA_TASK_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; + * @param thread_def pointer to theosa_task_def_t structure which defines the task. + * @param task_param Pointer to be passed to the task when it is created. + * @retval KOSA_StatusSuccess The task is successfully created. + * @retval KOSA_StatusError The task can not be created. + */ +#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskCreate(osa_task_handle_t taskHandle, osa_task_def_t *thread_def, osa_task_param_t task_param); +#endif /* FSL_OSA_TASK_ENABLE */ + +/*! + * @brief Gets the handler of active task. + * + * @return Handler to current active task. + */ +#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_task_handle_t OSA_TaskGetCurrentHandle(void); +#endif /* FSL_OSA_TASK_ENABLE */ + +/*! + * @brief Puts the active task to the end of scheduler's queue. + * + * When a task calls this function, it gives up the CPU and puts itself to the + * end of a task ready list. + * + * @retval KOSA_StatusSuccess The function is called successfully. + * @retval KOSA_StatusError Error occurs with this function. + */ +#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskYield(void); +#endif /* FSL_OSA_TASK_ENABLE */ + +/*! + * @brief Gets the priority of a task. + * + * @param taskHandle The handler of the task whose priority is received. + * + * @return Task's priority. + */ +#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_task_priority_t OSA_TaskGetPriority(osa_task_handle_t taskHandle); +#endif /* FSL_OSA_TASK_ENABLE */ + +/*! + * @brief Sets the priority of a task. + * + * @param taskHandle The handler of the task whose priority is set. + * @param taskPriority The priority to set. + * + * @retval KOSA_StatusSuccess Task's priority is set successfully. + * @retval KOSA_StatusError Task's priority can not be set. + */ +#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskSetPriority(osa_task_handle_t taskHandle, osa_task_priority_t taskPriority); +#endif /* FSL_OSA_TASK_ENABLE */ + +/*! + * @brief Destroys a previously created task. + * + * @param taskHandle The handler of the task to destroy. + * + * @retval KOSA_StatusSuccess The task was successfully destroyed. + * @retval KOSA_StatusError Task destruction failed or invalid parameter. + */ +#if ((defined(FSL_OSA_TASK_ENABLE)) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskDestroy(osa_task_handle_t taskHandle); +#endif /* FSL_OSA_TASK_ENABLE */ + +/*! + * @brief Creates a semaphore with a given value. + * + * This function creates a semaphore and sets the value to the parameter + * initValue. + * + * Example below shows how to use this API to create the semaphore handle. + * @code + * OSA_SEMAPHORE_HANDLE_DEFINE(semaphoreHandle); + * OSA_SemaphoreCreate((osa_semaphore_handle_t)semaphoreHandle, 0xff); + * @endcode + * + * @param semaphoreHandle Pointer to a memory space of size OSA_SEM_HANDLE_SIZE allocated by the caller. + * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices. + * You can define the handle in the following two ways: + * #OSA_SEMAPHORE_HANDLE_DEFINE(semaphoreHandle); + * or + * uint32_t semaphoreHandle[((OSA_SEM_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; + * @param initValue Initial value the semaphore will be set to. + * + * @retval KOSA_StatusSuccess the new semaphore if the semaphore is created successfully. + * @retval KOSA_StatusError if the semaphore can not be created. + */ +osa_status_t OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle, uint32_t initValue); + +/*! + * @brief Destroys a previously created semaphore. + * + * @param semaphoreHandle The semaphore handle. + * The macro SEMAPHORE_HANDLE_BUFFER_GET is used to get the semaphore buffer pointer, + * and should not be used before the macro SEMAPHORE_HANDLE_BUFFER_DEFINE is used. + * + * @retval KOSA_StatusSuccess The semaphore is successfully destroyed. + * @retval KOSA_StatusError The semaphore can not be destroyed. + */ +osa_status_t OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle); + +/*! + * @brief Pending a semaphore with timeout. + * + * This function checks the semaphore's counting value. If it is positive, + * decreases it and returns KOSA_StatusSuccess. Otherwise, a timeout is used + * to wait. + * + * @param semaphoreHandle The semaphore handle. + * @param millisec The maximum number of milliseconds to wait if semaphore is not + * positive. Pass osaWaitForever_c to wait indefinitely, pass 0 + * will return KOSA_StatusTimeout immediately. + * + * @retval KOSA_StatusSuccess The semaphore is received. + * @retval KOSA_StatusTimeout The semaphore is not received within the specified 'timeout'. + * @retval KOSA_StatusError An incorrect parameter was passed. + */ +osa_status_t OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle, uint32_t millisec); + +/*! + * @brief Signals for someone waiting on the semaphore to wake up. + * + * Wakes up one task that is waiting on the semaphore. If no task is waiting, increases + * the semaphore's counting value. + * + * @param semaphoreHandle The semaphore handle to signal. + * + * @retval KOSA_StatusSuccess The semaphore is successfully signaled. + * @retval KOSA_StatusError The object can not be signaled or invalid parameter. + * + */ +osa_status_t OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle); + +/*! + * @brief Create an unlocked mutex. + * + * This function creates a non-recursive mutex and sets it to unlocked status. + * + * Example below shows how to use this API to create the mutex handle. + * @code + * OSA_MUTEX_HANDLE_DEFINE(mutexHandle); + * OSA_MutexCreate((osa_mutex_handle_t)mutexHandle); + * @endcode + * + * @param mutexHandle Pointer to a memory space of size OSA_MUTEX_HANDLE_SIZE allocated by the caller. + * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices. + * You can define the handle in the following two ways: + * #OSA_MUTEX_HANDLE_DEFINE(mutexHandle); + * or + * uint32_t mutexHandle[((OSA_MUTEX_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; + * @retval KOSA_StatusSuccess the new mutex if the mutex is created successfully. + * @retval KOSA_StatusError if the mutex can not be created. + */ +osa_status_t OSA_MutexCreate(osa_mutex_handle_t mutexHandle); + +/*! + * @brief Waits for a mutex and locks it. + * + * This function checks the mutex's status. If it is unlocked, locks it and returns the + * KOSA_StatusSuccess. Otherwise, waits for a timeout in milliseconds to lock. + * + * @param mutexHandle The mutex handle. + * @param millisec The maximum number of milliseconds to wait for the mutex. + * If the mutex is locked, Pass the value osaWaitForever_c will + * wait indefinitely, pass 0 will return KOSA_StatusTimeout + * immediately. + * + * @retval KOSA_StatusSuccess The mutex is locked successfully. + * @retval KOSA_StatusTimeout Timeout occurred. + * @retval KOSA_StatusError Incorrect parameter was passed. + * + * @note This is non-recursive mutex, a task can not try to lock the mutex it has locked. + */ +osa_status_t OSA_MutexLock(osa_mutex_handle_t mutexHandle, uint32_t millisec); + +/*! + * @brief Unlocks a previously locked mutex. + * + * @param mutexHandle The mutex handle. + * + * @retval KOSA_StatusSuccess The mutex is successfully unlocked. + * @retval KOSA_StatusError The mutex can not be unlocked or invalid parameter. + */ +osa_status_t OSA_MutexUnlock(osa_mutex_handle_t mutexHandle); + +/*! + * @brief Destroys a previously created mutex. + * + * @param mutexHandle The mutex handle. + * + * @retval KOSA_StatusSuccess The mutex is successfully destroyed. + * @retval KOSA_StatusError The mutex can not be destroyed. + * + */ +osa_status_t OSA_MutexDestroy(osa_mutex_handle_t mutexHandle); + +/*! + * @brief Initializes an event object with all flags cleared. + * + * This function creates an event object and set its clear mode. If autoClear + * is 1, when a task gets the event flags, these flags will be + * cleared automatically. Otherwise these flags must + * be cleared manually. + * + * Example below shows how to use this API to create the event handle. + * @code + * OSA_EVENT_HANDLE_DEFINE(eventHandle); + * OSA_EventCreate((osa_event_handle_t)eventHandle, 0); + * @endcode + * + * @param eventHandle Pointer to a memory space of size OSA_EVENT_HANDLE_SIZE allocated by the caller. + * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices. + * You can define the handle in the following two ways: + * #OSA_EVENT_HANDLE_DEFINE(eventHandle); + * or + * uint32_t eventHandle[((OSA_EVENT_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; + * @param autoClear 1 The event is auto-clear. + * 0 The event manual-clear + * @retval KOSA_StatusSuccess the new event if the event is created successfully. + * @retval KOSA_StatusError if the event can not be created. + */ +osa_status_t OSA_EventCreate(osa_event_handle_t eventHandle, uint8_t autoClear); + +/*! + * @brief Sets one or more event flags. + * + * Sets specified flags of an event object. + * + * @param eventHandle The event handle. + * @param flagsToSet Flags to be set. + * + * @retval KOSA_StatusSuccess The flags were successfully set. + * @retval KOSA_StatusError An incorrect parameter was passed. + */ +osa_status_t OSA_EventSet(osa_event_handle_t eventHandle, osa_event_flags_t flagsToSet); + +/*! + * @brief Clears one or more flags. + * + * Clears specified flags of an event object. + * + * @param eventHandle The event handle. + * @param flagsToClear Flags to be clear. + * + * @retval KOSA_StatusSuccess The flags were successfully cleared. + * @retval KOSA_StatusError An incorrect parameter was passed. + */ +osa_status_t OSA_EventClear(osa_event_handle_t eventHandle, osa_event_flags_t flagsToClear); + +/*! + * @brief Get event's flags. + * + * Get specified flags of an event object. + * + * @param eventHandle The event handle. + * The macro EVENT_HANDLE_BUFFER_GET is used to get the event buffer pointer, + * and should not be used before the macro EVENT_HANDLE_BUFFER_DEFINE is used. + * @param flagsMask The flags user want to get are specified by this parameter. + * @param pFlagsOfEvent The event flags are obtained by this parameter. + * + * @retval KOSA_StatusSuccess The event flags were successfully got. + * @retval KOSA_StatusError An incorrect parameter was passed. + */ +osa_status_t OSA_EventGet(osa_event_handle_t eventHandle, + osa_event_flags_t flagsMask, + osa_event_flags_t *pFlagsOfEvent); + +/*! + * @brief Waits for specified event flags to be set. + * + * This function waits for a combination of flags to be set in an event object. + * Applications can wait for any/all bits to be set. Also this function could + * obtain the flags who wakeup the waiting task. + * + * @param eventHandle The event handle. + * @param flagsToWait Flags that to wait. + * @param waitAll Wait all flags or any flag to be set. + * @param millisec The maximum number of milliseconds to wait for the event. + * If the wait condition is not met, pass osaWaitForever_c will + * wait indefinitely, pass 0 will return KOSA_StatusTimeout + * immediately. + * @param pSetFlags Flags that wakeup the waiting task are obtained by this parameter. + * + * @retval KOSA_StatusSuccess The wait condition met and function returns successfully. + * @retval KOSA_StatusTimeout Has not met wait condition within timeout. + * @retval KOSA_StatusError An incorrect parameter was passed. + * + * @note Please pay attention to the flags bit width, FreeRTOS uses the most + * significant 8 bis as control bits, so do not wait these bits while using + * FreeRTOS. + * + */ +osa_status_t OSA_EventWait(osa_event_handle_t eventHandle, + osa_event_flags_t flagsToWait, + uint8_t waitAll, + uint32_t millisec, + osa_event_flags_t *pSetFlags); + +/*! + * @brief Destroys a previously created event object. + * + * @param eventHandle The event handle. + * + * @retval KOSA_StatusSuccess The event is successfully destroyed. + * @retval KOSA_StatusError Event destruction failed. + */ +osa_status_t OSA_EventDestroy(osa_event_handle_t eventHandle); + +/*! + * @brief Initializes a message queue. + * + * This function allocates memory for and initializes a message queue. Message queue elements are hardcoded as void*. + * + * Example below shows how to use this API to create the massage queue handle. + * @code + * OSA_MSGQ_HANDLE_DEFINE(msgqHandle); + * OSA_MsgQCreate((osa_msgq_handle_t)msgqHandle, 5U, sizeof(msg)); + * @endcode + * + * @param msgqHandle Pointer to a memory space of size #(OSA_MSGQ_HANDLE_SIZE + msgNo*msgSize) on bare-matel + * and #(OSA_MSGQ_HANDLE_SIZE) on FreeRTOS allocated by the caller, message queue handle. + * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices. + * You can define the handle in the following two ways: + * #OSA_MSGQ_HANDLE_DEFINE(msgqHandle); + * or + * For bm: uint32_t msgqHandle[((OSA_MSGQ_HANDLE_SIZE + msgNo*msgSize + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; + * For freertos: uint32_t msgqHandle[((OSA_MSGQ_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; + * @param msgNo :number of messages the message queue should accommodate. + * @param msgSize :size of a single message structure. + * + * @retval KOSA_StatusSuccess Message queue successfully Create. + * @retval KOSA_StatusError Message queue create failure. + */ +osa_status_t OSA_MsgQCreate(osa_msgq_handle_t msgqHandle, uint32_t msgNo, uint32_t msgSize); + +/*! + * @brief Puts a message at the end of the queue. + * + * This function puts a message to the end of the message queue. If the queue + * is full, this function returns the KOSA_StatusError; + * + * @param msgqHandle Message Queue handler. + * @param pMessage Pointer to the message to be put into the queue. + * + * @retval KOSA_StatusSuccess Message successfully put into the queue. + * @retval KOSA_StatusError The queue was full or an invalid parameter was passed. + */ +osa_status_t OSA_MsgQPut(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage); + +/*! + * @brief Reads and remove a message at the head of the queue. + * + * This function gets a message from the head of the message queue. If the + * queue is empty, timeout is used to wait. + * + * @param msgqHandle Message Queue handler. + * @param pMessage Pointer to a memory to save the message. + * @param millisec The number of milliseconds to wait for a message. If the + * queue is empty, pass osaWaitForever_c will wait indefinitely, + * pass 0 will return KOSA_StatusTimeout immediately. + * + * @retval KOSA_StatusSuccess Message successfully obtained from the queue. + * @retval KOSA_StatusTimeout The queue remains empty after timeout. + * @retval KOSA_StatusError Invalid parameter. + */ +osa_status_t OSA_MsgQGet(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage, uint32_t millisec); + +/*! + * @brief Destroys a previously created queue. + * + * @param msgqHandle Message Queue handler. + * + * @retval KOSA_StatusSuccess The queue was successfully destroyed. + * @retval KOSA_StatusError Message queue destruction failed. + */ +osa_status_t OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle); + +/*! + * @brief Enable all interrupts. + */ +void OSA_InterruptEnable(void); + +/*! + * @brief Disable all interrupts. + */ +void OSA_InterruptDisable(void); + +/*! + * @brief Enable all interrupts using PRIMASK. + */ +void OSA_EnableIRQGlobal(void); + +/*! + * @brief Disable all interrupts using PRIMASK. + */ +void OSA_DisableIRQGlobal(void); + +/*! + * @brief Delays execution for a number of milliseconds. + * + * @param millisec The time in milliseconds to wait. + */ +void OSA_TimeDelay(uint32_t millisec); + +/*! + * @brief This function gets current time in milliseconds. + * + * @retval current time in milliseconds + */ +uint32_t OSA_TimeGetMsec(void); + +/*! + * @brief Installs the interrupt handler. + * + * @param IRQNumber IRQ number of the interrupt. + * @param handler The interrupt handler to install. + */ +void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void)); + +/*! @}*/ +#ifdef __cplusplus +} +#endif +/*! @}*/ +#endif \ No newline at end of file diff --git a/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_config.h b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_config.h new file mode 100644 index 0000000000..11eec49e7d --- /dev/null +++ b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_config.h @@ -0,0 +1,36 @@ +/*! + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_OS_ABSTRACTION_CONFIG_H_ +#define _FSL_OS_ABSTRACTION_CONFIG_H_ + +#ifndef gMainThreadStackSize_c +#define gMainThreadStackSize_c 1024 +#endif + +#ifndef gMainThreadPriority_c +#define gMainThreadPriority_c 1 +#endif + +#ifndef gTaskMultipleInstancesManagement_c +#define gTaskMultipleInstancesManagement_c 0 +#endif + +/*! @brief Definition to determine whether enable OSA's TASK module. */ +#ifndef OSA_USED +#ifndef FSL_OSA_TASK_ENABLE +#define FSL_OSA_TASK_ENABLE 0U +#endif +#else +#if defined(FSL_OSA_TASK_ENABLE) +#undef FSL_OSA_TASK_ENABLE +#endif +#define FSL_OSA_TASK_ENABLE 1U +#endif /* OSA_USED */ + +#endif /* _FSL_OS_ABSTRACTION_CONFIG_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.c b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.c new file mode 100644 index 0000000000..4601d5f7bd --- /dev/null +++ b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.c @@ -0,0 +1,917 @@ +/*! ********************************************************************************* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017, 2019 NXP + * All rights reserved. + * + * + * This is the source file for the OS Abstraction layer for freertos. + * + * SPDX-License-Identifier: BSD-3-Clause + ********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ +#include "fsl_common.h" +#include "fsl_os_abstraction.h" +#include "fsl_os_abstraction_rtthread.h" +#include +#include "generic_list.h" + +/*! ********************************************************************************* +************************************************************************************* +* Private macros +************************************************************************************* +********************************************************************************** */ + +/* Weak function. */ +#if defined(__GNUC__) +#define __WEAK_FUNC __attribute__((weak)) +#elif defined(__ICCARM__) +#define __WEAK_FUNC __weak +#elif defined(__CC_ARM) || defined(__ARMCC_VERSION) +#define __WEAK_FUNC __attribute__((weak)) +#endif + +#define millisecToTicks(millisec) (((millisec)*configTICK_RATE_HZ + 999U) / 1000U) + +#ifdef DEBUG_ASSERT +#define OS_ASSERT(condition) \ + if (!(condition)) \ + while (1) \ + ; +#else +#define OS_ASSERT(condition) (void)(condition); +#endif + +/*! @brief Converts milliseconds to ticks*/ +#define MSEC_TO_TICK(msec) \ + (((uint32_t)(msec) + 500uL / (uint32_t)configTICK_RATE_HZ) * (uint32_t)configTICK_RATE_HZ / 1000uL) +#define TICKS_TO_MSEC(tick) ((uint32_t)((uint64_t)(tick)*1000uL / (uint64_t)configTICK_RATE_HZ)) +/************************************************************************************ +************************************************************************************* +* Private type definitions +************************************************************************************* +************************************************************************************/ +typedef struct osa_freertos_task +{ + list_element_t link; + rt_thread_t taskHandle; +} osa_freertos_task_t; + +typedef struct _osa_event_struct +{ + rt_event_t handle; /* The event handle */ + uint8_t autoClear; /*!< Auto clear or manual clear */ +} osa_event_struct_t; + +/*! @brief State structure for bm osa manager. */ +typedef struct _osa_state +{ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) + list_label_t taskList; + OSA_TASK_HANDLE_DEFINE(mainTaskHandle); +#endif + uint32_t basePriority; + int32_t basePriorityNesting; + uint32_t interruptDisableCount; +} osa_state_t; + +/*! ********************************************************************************* +************************************************************************************* +* Private prototypes +************************************************************************************* +********************************************************************************** */ +__WEAK_FUNC void main_task(void const *argument); +__WEAK_FUNC void main_task(void const *argument) +{ +} + +void startup_task(void *argument); + +/*! ********************************************************************************* +************************************************************************************* +* Public memory declarations +************************************************************************************* +********************************************************************************** */ +const uint8_t gUseRtos_c = USE_RTOS; // USE_RTOS = 0 for BareMetal and 1 for OS + +static osa_state_t s_osaState = {0}; +/*! ********************************************************************************* +************************************************************************************* +* Private memory declarations +************************************************************************************* +********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Public functions +************************************************************************************* +********************************************************************************** */ +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MemoryAllocate + * Description : Reserves the requested amount of memory in bytes. + * + *END**************************************************************************/ +void *OSA_MemoryAllocate(uint32_t length) +{ + void *p = rt_malloc(length); + + if (RT_NULL != p) + { + rt_memset(p, 0, length); + } + + return p; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MemoryFree + * Description : Frees the memory previously reserved. + * + *END**************************************************************************/ +void OSA_MemoryFree(void *p) +{ + rt_free(p); +} + +void OSA_EnterCritical(uint32_t *sr) +{ + if (rt_thread_self() != RT_NULL) + rt_enter_critical(); +} + +void OSA_ExitCritical(uint32_t sr) +{ + if (rt_thread_self() != RT_NULL) + rt_exit_critical(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : startup_task + * Description : Wrapper over main_task.. + * + *END**************************************************************************/ +void startup_task(void *argument) +{ + main_task(argument); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetCurrentHandle + * Description : This function is used to get current active task's handler. + * + *END**************************************************************************/ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_task_handle_t OSA_TaskGetCurrentHandle(void) +{ + list_element_handle_t list_element; + osa_freertos_task_t *ptask; + + list_element = LIST_GetHead(&s_osaState.taskList); + while (NULL != list_element) + { + ptask = (osa_freertos_task_t *)(void *)list_element; + if (ptask->taskHandle == xTaskGetCurrentTaskHandle()) + { + return (osa_task_handle_t)ptask; + } + list_element = LIST_GetNext(list_element); + } + return NULL; +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskYield + * Description : When a task calls this function, it will give up CPU and put + * itself to the tail of ready list. + * + *END**************************************************************************/ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskYield(void) +{ + taskYIELD(); + return KOSA_StatusSuccess; +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskGetPriority + * Description : This function returns task's priority by task handler. + * + *END**************************************************************************/ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_task_priority_t OSA_TaskGetPriority(osa_task_handle_t taskHandle) +{ + assert(taskHandle); + osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle; + return (osa_task_priority_t)(PRIORITY_RTOS_TO_OSA(uxTaskPriorityGet(ptask->taskHandle))); +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskSetPriority + * Description : This function sets task's priority by task handler. + * + *END**************************************************************************/ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskSetPriority(osa_task_handle_t taskHandle, osa_task_priority_t taskPriority) +{ + assert(taskHandle); + osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle; + vTaskPrioritySet((task_handler_t)ptask->taskHandle, PRIORITY_OSA_TO_RTOS(taskPriority)); + return KOSA_StatusSuccess; +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskCreate + * Description : This function is used to create a task and make it ready. + * Param[in] : threadDef - Definition of the thread. + * task_param - Parameter to pass to the new thread. + * Return Thread handle of the new thread, or NULL if failed. + * + *END**************************************************************************/ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskCreate(osa_task_handle_t taskHandle, osa_task_def_t *thread_def, osa_task_param_t task_param) +{ + assert(sizeof(osa_freertos_task_t) == OSA_TASK_HANDLE_SIZE); + assert(taskHandle); + TaskHandle_t pxCreatedTask; + osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle; + + if (xTaskCreate((TaskFunction_t)thread_def->pthread, /* pointer to the task */ + (char const *)thread_def->tname, /* task name for kernel awareness debugging */ + (configSTACK_DEPTH_TYPE)thread_def->stacksize / sizeof(portSTACK_TYPE), /* task stack size */ + (task_param_t)task_param, /* optional task startup argument */ + PRIORITY_OSA_TO_RTOS(thread_def->tpriority), /* initial priority */ + &pxCreatedTask /* optional task handle to create */ + ) == pdPASS) + { + ptask->taskHandle = pxCreatedTask; + OSA_InterruptDisable(); + (void)LIST_AddTail(&s_osaState.taskList, (list_element_handle_t) & (ptask->link)); + OSA_InterruptEnable(); + return KOSA_StatusSuccess; + } + return KOSA_StatusError; +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TaskDestroy + * Description : This function destroy a task. + * Param[in] :taskHandle - Thread handle. + * Return KOSA_StatusSuccess if the task is destroied, otherwise return KOSA_StatusError. + * + *END**************************************************************************/ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) +osa_status_t OSA_TaskDestroy(osa_task_handle_t taskHandle) +{ + assert(taskHandle); + osa_freertos_task_t *ptask = (osa_freertos_task_t *)taskHandle; + osa_status_t status; + uint16_t oldPriority; + /*Change priority to avoid context switches*/ + oldPriority = OSA_TaskGetPriority(OSA_TaskGetCurrentHandle()); + (void)OSA_TaskSetPriority(OSA_TaskGetCurrentHandle(), OSA_PRIORITY_REAL_TIME); +#if INCLUDE_vTaskDelete /* vTaskDelete() enabled */ + vTaskDelete((task_handler_t)ptask->taskHandle); + status = KOSA_StatusSuccess; +#else + status = KOSA_StatusError; /* vTaskDelete() not available */ +#endif + (void)OSA_TaskSetPriority(OSA_TaskGetCurrentHandle(), oldPriority); + OSA_InterruptDisable(); + (void)LIST_RemoveElement(taskHandle); + OSA_InterruptEnable(); + return status; +} +#endif + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeDelay + * Description : This function is used to suspend the active thread for the given number of milliseconds. + * + *END**************************************************************************/ +void OSA_TimeDelay(uint32_t millisec) +{ + rt_thread_mdelay(millisec); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_TimeGetMsec + * Description : This function gets current time in milliseconds. + * + *END**************************************************************************/ +uint32_t OSA_TimeGetMsec(void) +{ + return rt_tick_get_millisecond(); +} +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreCreate + * Description : This function is used to create a semaphore. + * Return : Semaphore handle of the new semaphore, or NULL if failed. + * + *END**************************************************************************/ +osa_status_t OSA_SemaphoreCreate(osa_semaphore_handle_t semaphoreHandle, uint32_t initValue) +{ + assert(sizeof(osa_semaphore_handle_t) == OSA_SEM_HANDLE_SIZE); + assert(semaphoreHandle); + + union + { + rt_sem_t sem; + uint32_t semhandle; + } xSemaHandle; + + xSemaHandle.sem = rt_sem_create("osa_sem", initValue, RT_IPC_FLAG_PRIO); + if (NULL != xSemaHandle.sem) + { + *(uint32_t *)semaphoreHandle = xSemaHandle.semhandle; + return KOSA_StatusSuccess; + } + return KOSA_StatusError; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreDestroy + * Description : This function is used to destroy a semaphore. + * Return : KOSA_StatusSuccess if the semaphore is destroyed successfully, otherwise return KOSA_StatusError. + * + *END**************************************************************************/ +osa_status_t OSA_SemaphoreDestroy(osa_semaphore_handle_t semaphoreHandle) +{ + assert(semaphoreHandle); + rt_sem_t sem = (rt_sem_t)(void *)(uint32_t *)(*(uint32_t *)semaphoreHandle); + + rt_sem_delete(sem); + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphoreWait + * Description : This function checks the semaphore's counting value, if it is + * positive, decreases it and returns KOSA_StatusSuccess, otherwise, timeout + * will be used for wait. The parameter timeout indicates how long should wait + * in milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will + * return KOSA_StatusTimeout immediately if semaphore is not positive. + * This function returns KOSA_StatusSuccess if the semaphore is received, returns + * KOSA_StatusTimeout if the semaphore is not received within the specified + * 'timeout', returns KOSA_StatusError if any errors occur during waiting. + * + *END**************************************************************************/ +osa_status_t OSA_SemaphoreWait(osa_semaphore_handle_t semaphoreHandle, uint32_t millisec) +{ + uint32_t timeoutTicks; + assert(semaphoreHandle); + rt_sem_t sem = (rt_sem_t)(void *)(uint32_t *)(*(uint32_t *)semaphoreHandle); + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = RT_WAITING_FOREVER; + } + else + { + timeoutTicks = rt_tick_from_millisecond(millisec); + } + + if (RT_EOK != rt_sem_take(sem, timeoutTicks)) + { + return KOSA_StatusTimeout; /* timeout */ + } + else + { + return KOSA_StatusSuccess; /* semaphore taken */ + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_SemaphorePost + * Description : This function is used to wake up one task that wating on the + * semaphore. If no task is waiting, increase the semaphore. The function returns + * KOSA_StatusSuccess if the semaphre is post successfully, otherwise returns + * KOSA_StatusError. + * + *END**************************************************************************/ +osa_status_t OSA_SemaphorePost(osa_semaphore_handle_t semaphoreHandle) +{ + assert(semaphoreHandle); + rt_sem_t sem = (rt_sem_t)(void *)(uint32_t *)(*(uint32_t *)semaphoreHandle); + rt_sem_release(sem); + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexCreate + * Description : This function is used to create a mutex. + * Return : Mutex handle of the new mutex, or NULL if failed. + * + *END**************************************************************************/ +osa_status_t OSA_MutexCreate(osa_mutex_handle_t mutexHandle) +{ + assert(sizeof(osa_mutex_handle_t) == OSA_MUTEX_HANDLE_SIZE); + assert(mutexHandle); + + union + { + rt_mutex_t mutex; + uint32_t pmutexHandle; + } xMutexHandle; + + xMutexHandle.mutex = rt_mutex_create("osa_mutex", RT_IPC_FLAG_PRIO); + if (RT_NULL != xMutexHandle.mutex) + { + *(uint32_t *)mutexHandle = xMutexHandle.pmutexHandle; + return KOSA_StatusSuccess; + } + return KOSA_StatusError; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexLock + * Description : This function checks the mutex's status, if it is unlocked, + * lock it and returns KOSA_StatusSuccess, otherwise, wait for the mutex. + * This function returns KOSA_StatusSuccess if the mutex is obtained, returns + * KOSA_StatusError if any errors occur during waiting. If the mutex has been + * locked, pass 0 as timeout will return KOSA_StatusTimeout immediately. + * + *END**************************************************************************/ +osa_status_t OSA_MutexLock(osa_mutex_handle_t mutexHandle, uint32_t millisec) +{ + assert(mutexHandle); + uint32_t timeoutTicks; + rt_mutex_t mutex = (rt_mutex_t)(void *)(uint32_t *)(*(uint32_t *)mutexHandle); + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = RT_WAITING_FOREVER; + } + else + { + timeoutTicks = rt_tick_from_millisecond(millisec); + } + + if (RT_EOK != rt_mutex_take(mutex, timeoutTicks)) + { + return KOSA_StatusTimeout; /* timeout */ + } + else + { + return KOSA_StatusSuccess; /* semaphore taken */ + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexUnlock + * Description : This function is used to unlock a mutex. + * + *END**************************************************************************/ +osa_status_t OSA_MutexUnlock(osa_mutex_handle_t mutexHandle) +{ + assert(mutexHandle); + rt_mutex_t mutex = (rt_mutex_t)(void *)(uint32_t *)(*(uint32_t *)mutexHandle); + rt_mutex_release(mutex); + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MutexDestroy + * Description : This function is used to destroy a mutex. + * Return : KOSA_StatusSuccess if the lock object is destroyed successfully, otherwise return KOSA_StatusError. + * + *END**************************************************************************/ +osa_status_t OSA_MutexDestroy(osa_mutex_handle_t mutexHandle) +{ + assert(mutexHandle); + rt_mutex_t mutex = (rt_mutex_t)(void *)(uint32_t *)(*(uint32_t *)mutexHandle); + + rt_mutex_delete(mutex); + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventCreate + * Description : This function is used to create a event object. + * Return : Event handle of the new event, or NULL if failed. + * + *END**************************************************************************/ +osa_status_t OSA_EventCreate(osa_event_handle_t eventHandle, uint8_t autoClear) +{ + assert(eventHandle); + osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle; + + pEventStruct->handle = rt_event_create("osa_event", RT_IPC_FLAG_PRIO); + if (RT_NULL != pEventStruct->handle) + { + pEventStruct->autoClear = autoClear; + } + else + { + return KOSA_StatusError; + } + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventSet + * Description : Set one or more event flags of an event object. + * Return : KOSA_StatusSuccess if set successfully, KOSA_StatusError if failed. + * + *END**************************************************************************/ +osa_status_t OSA_EventSet(osa_event_handle_t eventHandle, osa_event_flags_t flagsToSet) +{ + rt_err_t result; + assert(eventHandle); + osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle; + + if (RT_NULL == pEventStruct->handle) + { + return KOSA_StatusError; + } + + rt_event_send(pEventStruct->handle, (rt_uint32_t)flagsToSet); + + (void)result; + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventClear + * Description : Clear one or more event flags of an event object. + * Return :KOSA_StatusSuccess if clear successfully, KOSA_StatusError if failed. + * + *END**************************************************************************/ +osa_status_t OSA_EventClear(osa_event_handle_t eventHandle, osa_event_flags_t flagsToClear) +{ + assert(eventHandle); + osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle; + + if (RT_NULL == pEventStruct->handle) + { + return KOSA_StatusError; + } + + rt_uint32_t recved; + rt_event_recv(pEventStruct->handle, (rt_uint32_t)flagsToClear, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, &recved); + + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventGet + * Description : This function is used to get event's flags that specified by prameter + * flagsMask, and the flags (user specified) are obatianed by parameter pFlagsOfEvent. So + * you should pass the parameter 0xffffffff to specify you want to check all. + * Return :KOSA_StatusSuccess if event flags were successfully got, KOSA_StatusError if failed. + * + *END**************************************************************************/ +osa_status_t OSA_EventGet(osa_event_handle_t eventHandle, osa_event_flags_t flagsMask, osa_event_flags_t *pFlagsOfEvent) +{ + assert(eventHandle); + osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle; + rt_uint32_t eventFlags; + + if (RT_NULL == pEventStruct->handle) + { + return KOSA_StatusError; + } + + if (RT_NULL == pFlagsOfEvent) + { + return KOSA_StatusError; + } + + if (RT_EOK != rt_event_recv(pEventStruct->handle, (rt_uint32_t)flagsMask, RT_EVENT_FLAG_OR, 0, &eventFlags)) + { + eventFlags = 0; + } + + *pFlagsOfEvent = (osa_event_flags_t)eventFlags & flagsMask; + + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventWait + * Description : This function checks the event's status, if it meets the wait + * condition, return KOSA_StatusSuccess, otherwise, timeout will be used for + * wait. The parameter timeout indicates how long should wait in milliseconds. + * Pass osaWaitForever_c to wait indefinitely, pass 0 will return the value + * KOSA_StatusTimeout immediately if wait condition is not met. The event flags + * will be cleared if the event is auto clear mode. Flags that wakeup waiting + * task could be obtained from the parameter setFlags. + * This function returns KOSA_StatusSuccess if wait condition is met, returns + * KOSA_StatusTimeout if wait condition is not met within the specified + * 'timeout', returns KOSA_StatusError if any errors occur during waiting. + * + *END**************************************************************************/ +osa_status_t OSA_EventWait(osa_event_handle_t eventHandle, + osa_event_flags_t flagsToWait, + uint8_t waitAll, + uint32_t millisec, + osa_event_flags_t *pSetFlags) +{ + assert(eventHandle); + rt_uint8_t option = 0; + rt_uint32_t timeoutTicks; + rt_uint32_t flagsSave; + osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle; + + /* Clean FreeRTOS cotrol flags */ + flagsToWait = flagsToWait & 0x00FFFFFFU; + if (RT_NULL == pEventStruct->handle) + { + return KOSA_StatusError; + } + + /* Convert timeout from millisecond to tick. */ + if (millisec == osaWaitForever_c) + { + timeoutTicks = RT_WAITING_FOREVER; + } + else + { + timeoutTicks = rt_tick_from_millisecond(millisec); + } + + if (pEventStruct->autoClear != 0U) + { + option |= RT_EVENT_FLAG_CLEAR; + } + option |= waitAll ? RT_EVENT_FLAG_AND : RT_EVENT_FLAG_OR; + + rt_err_t status = rt_event_recv(pEventStruct->handle, (rt_uint32_t)flagsToWait, option, timeoutTicks, &flagsSave); + + flagsSave &= (rt_uint32_t)flagsToWait; + if (RT_NULL != pSetFlags) + { + *pSetFlags = (osa_event_flags_t)flagsSave; + } + + if (RT_EOK != status) + { + return KOSA_StatusTimeout; + } + else + { + return KOSA_StatusSuccess; + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EventDestroy + * Description : This function is used to destroy a event object. Return + * KOSA_StatusSuccess if the event object is destroyed successfully, otherwise + * return KOSA_StatusError. + * + *END**************************************************************************/ +osa_status_t OSA_EventDestroy(osa_event_handle_t eventHandle) +{ + assert(eventHandle); + osa_event_struct_t *pEventStruct = (osa_event_struct_t *)eventHandle; + + if (RT_NULL == pEventStruct->handle) + { + return KOSA_StatusError; + } + rt_event_delete(pEventStruct->handle); + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQCreate + * Description : This function is used to create a message queue. + * Return : the handle to the message queue if create successfully, otherwise + * return NULL. + * + *END**************************************************************************/ +osa_status_t OSA_MsgQCreate(osa_msgq_handle_t msgqHandle, uint32_t msgNo, uint32_t msgSize) +{ + assert(sizeof(osa_msgq_handle_t) == OSA_MSGQ_HANDLE_SIZE); + assert(msgqHandle); + + union + { + rt_mq_t msgq; + uint32_t pmsgqHandle; + } xMsgqHandle; + + /* Create the message queue where the number and size is specified by msgNo and msgSize */ + xMsgqHandle.msgq = rt_mq_create("osa_mq", msgSize, msgNo, RT_IPC_FLAG_PRIO); + if (RT_NULL != xMsgqHandle.msgq) + { + *(uint32_t *)msgqHandle = xMsgqHandle.pmsgqHandle; + return KOSA_StatusSuccess; + } + return KOSA_StatusError; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQPut + * Description : This function is used to put a message to a message queue. + * Return : KOSA_StatusSuccess if the message is put successfully, otherwise return KOSA_StatusError. + * + *END**************************************************************************/ +osa_status_t OSA_MsgQPut(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage) +{ + assert(msgqHandle); + rt_mq_t handler = (rt_mq_t)(void *)(uint32_t *)(*(uint32_t *)msgqHandle); + + if (RT_EOK == rt_mq_send(handler, pMessage, handler->msg_size)) + { + return KOSA_StatusSuccess; + } + else + { + return KOSA_StatusError; + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQGet + * Description : This function checks the queue's status, if it is not empty, + * get message from it and return KOSA_StatusSuccess, otherwise, timeout will + * be used for wait. The parameter timeout indicates how long should wait in + * milliseconds. Pass osaWaitForever_c to wait indefinitely, pass 0 will return + * KOSA_StatusTimeout immediately if queue is empty. + * This function returns KOSA_StatusSuccess if message is got successfully, + * returns KOSA_StatusTimeout if message queue is empty within the specified + * 'timeout', returns KOSA_StatusError if any errors occur during waiting. + * + *END**************************************************************************/ +osa_status_t OSA_MsgQGet(osa_msgq_handle_t msgqHandle, osa_msg_handle_t pMessage, uint32_t millisec) +{ + osa_status_t osaStatus; + assert(msgqHandle); + rt_mq_t handler = (rt_mq_t)(void *)(uint32_t *)(*(uint32_t *)msgqHandle); + + uint32_t timeoutTicks; + + if (millisec == osaWaitForever_c) + { + timeoutTicks = RT_WAITING_FOREVER; + } + else + { + timeoutTicks = rt_tick_from_millisecond(millisec); + } + if (RT_EOK != rt_mq_recv(handler, pMessage, handler->msg_size, timeoutTicks)) + { + osaStatus = KOSA_StatusTimeout; /* not able to send it to the queue? */ + } + else + { + osaStatus = KOSA_StatusSuccess; + } + return osaStatus; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_MsgQDestroy + * Description : This function is used to destroy the message queue. + * Return : KOSA_StatusSuccess if the message queue is destroyed successfully, otherwise return KOSA_StatusError. + * + *END**************************************************************************/ +osa_status_t OSA_MsgQDestroy(osa_msgq_handle_t msgqHandle) +{ + assert(msgqHandle); + rt_mq_t handler = (rt_mq_t)(void *)(uint32_t *)(*(uint32_t *)msgqHandle); + + rt_mq_delete(handler); + return KOSA_StatusSuccess; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptEnable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptEnable(void) +{ + rt_exit_critical(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InterruptDisable + * Description : self explanatory. + * + *END**************************************************************************/ +void OSA_InterruptDisable(void) +{ + rt_enter_critical(); +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_EnableIRQGlobal + * Description : enable interrupts using PRIMASK register. + * + *END**************************************************************************/ +void OSA_EnableIRQGlobal(void) +{ + if (s_osaState.interruptDisableCount > 0U) + { + s_osaState.interruptDisableCount--; + + if (0U == s_osaState.interruptDisableCount) + { + __enable_irq(); + } + /* call core API to enable the global interrupt*/ + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_DisableIRQGlobal + * Description : disable interrupts using PRIMASK register. + * + *END**************************************************************************/ +void OSA_DisableIRQGlobal(void) +{ + /* call core API to disable the global interrupt*/ + __disable_irq(); + + /* update counter*/ + s_osaState.interruptDisableCount++; +} + +/*FUNCTION********************************************************************** + * + * Function Name : OSA_InstallIntHandler + * Description : This function is used to install interrupt handler. + * + *END**************************************************************************/ +void OSA_InstallIntHandler(uint32_t IRQNumber, void (*handler)(void)) +{ +#if defined(__IAR_SYSTEMS_ICC__) + _Pragma("diag_suppress = Pm138") +#endif +#if defined(ENABLE_RAM_VECTOR_TABLE) + (void) InstallIRQHandler((IRQn_Type)IRQNumber, (uint32_t) * (uint32_t *)&handler); +#endif /* ENABLE_RAM_VECTOR_TABLE. */ +#if defined(__IAR_SYSTEMS_ICC__) + _Pragma("diag_remark = PM138") +#endif +} + +/*!********************************************************************************* +************************************************************************************* +* Private functions +************************************************************************************* +********************************************************************************** */ +#if (defined(FSL_OSA_TASK_ENABLE) && (FSL_OSA_TASK_ENABLE > 0U)) + +static OSA_TASK_DEFINE(startup_task, gMainThreadPriority_c, 1, gMainThreadStackSize_c, 0); + +int main(void) +{ + extern void BOARD_InitHardware(void); + /* Initialize MCU clock */ + BOARD_InitHardware(); + LIST_Init((&s_osaState.taskList), 0); + + s_osaState.basePriorityNesting = 0; + s_osaState.interruptDisableCount = 0; + (void)OSA_TaskCreate((osa_task_handle_t)s_osaState.mainTaskHandle, OSA_TASK(startup_task), NULL); + + vTaskStartScheduler(); + return 0; +} +#endif /* FSL_OSA_TASK_ENABLE */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.h b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.h new file mode 100644 index 0000000000..0e0423753f --- /dev/null +++ b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/fsl_os_abstraction_rtthread.h @@ -0,0 +1,130 @@ +/*! ********************************************************************************* + * Copyright (c) 2013-2014, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * All rights reserved. + * + * ile + * + * SPDX-License-Identifier: BSD-3-Clause + ********************************************************************************** */ +#if !defined(__FSL_OS_ABSTRACTION_RTTHREAD_H__) +#define __FSL_OS_ABSTRACTION_RTTHREAD_H__ + +#if defined(__IAR_SYSTEMS_ICC__) +/** + * Workaround to disable MISRA C message suppress warnings for IAR compiler. + */ +// http://supp.iar.com/Support/?note=24725 + +#define MISRAC_DISABLE \ + _Pragma( \ + "diag_suppress= \ + Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\ + Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\ + Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\ + Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\ + Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\ + Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\ + Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\ + Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\ + Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\ + Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\ + Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\ + Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\ + Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\ + Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\ + Pm155") + +#define MISRAC_ENABLE \ + _Pragma( \ + "diag_default= \ + Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\ + Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\ + Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\ + Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\ + Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\ + Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\ + Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\ + Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\ + Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\ + Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\ + Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\ + Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\ + Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\ + Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\ + Pm155") +#else +/* Empty MISRA C macros for other toolchains. */ +#define MISRAC_DISABLE +#define MISRAC_ENABLE +#endif + +MISRAC_DISABLE +#include +MISRAC_ENABLE + +/*! + * @addtogroup os_abstraction_free_rtos + * @{ + */ + +/******************************************************************************* + * Declarations + ******************************************************************************/ +/*! @brief Type for a task handler, returned by the OSA_TaskCreate function. */ +typedef rt_thread_t task_handler_t; + +/*! @brief Type for a task stack.*/ +typedef rt_uint32_t task_stack_t; + +/*! @brief Type for task parameter */ +typedef void *task_param_t; + +/*! @brief Type for an event flags object.*/ +typedef rt_uint32_t event_flags_t; + +/*! @brief Constant to pass as timeout value in order to wait indefinitely. */ +#define OSA_WAIT_FOREVER 0xFFFFFFFFU + +/*! @brief OSA's time range in millisecond, OSA time wraps if exceeds this value. */ +#define FSL_OSA_TIME_RANGE 0xFFFFFFFFU + +/*! @brief The default interrupt handler installed in vector table. */ +#define OSA_DEFAULT_INT_HANDLER ((osa_int_handler_t)(&DefaultISR)) + +extern void DefaultISR(void); + +/*! + * @name Thread management + * @{ + */ + +/*! + * @brief To provide unified task piority for upper layer, OSA layer makes conversion. + */ +#define PRIORITY_OSA_TO_RTOS(osa_prio) ((UBaseType_t)configMAX_PRIORITIES - (osa_prio)-2U) +#define PRIORITY_RTOS_TO_OSA(rtos_prio) ((UBaseType_t)configMAX_PRIORITIES - (rtos_prio)-2U) + +/* @}*/ + +/*! + * @name Message queues + * @{ + */ + +/*! + * @brief This macro statically reserves the memory required for the queue. + * + * @param name Identifier for the memory region. + * @param number Number of elements in the queue. + * @param size Size of every elements in words. + */ +#define MSG_QUEUE_DECLARE(name, number, size) msg_queue_t *name = NULL + +/* @}*/ + +/*! @}*/ +/*! @}*/ +/*! @}*/ + +#endif // __FSL_OS_ABSTRACTION_RTTHREAD_H__ \ No newline at end of file diff --git a/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.c b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.c new file mode 100644 index 0000000000..4c0984f503 --- /dev/null +++ b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.c @@ -0,0 +1,475 @@ +/* + * Copyright 2018-2019 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! ********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ +#include "generic_list.h" + +static list_status_t LIST_Error_Check(list_handle_t list, list_element_handle_t newElement) +{ + list_status_t listStatus = kLIST_Ok; + list_element_handle_t element = list->head; + + if ((list->max != 0U) && (list->max == list->size)) + { + listStatus = kLIST_Full; /*List is full*/ + } + else + { + while (element != NULL) /*Scan list*/ + { + /* Determine if element is duplicated */ + if (element == newElement) + { + listStatus = kLIST_DuplicateError; + break; + } + element = element->next; + } + } + + return listStatus; +} + +/*! ********************************************************************************* +************************************************************************************* +* Public functions +************************************************************************************* +********************************************************************************** */ +/*! ********************************************************************************* + * \brief Initialises the list descriptor. + * + * \param[in] list - LIST_ handle to init. + * max - Maximum number of elements in list. 0 for unlimited. + * + * \return void. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +void LIST_Init(list_handle_t list, uint32_t max) +{ + list->head = NULL; + list->tail = NULL; + list->max = (uint16_t)max; + list->size = 0; +} + +/*! ********************************************************************************* + * \brief Gets the list that contains the given element. + * + * \param[in] element - Handle of the element. + * + * \return NULL if element is orphan. + * Handle of the list the element is inserted into. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_handle_t LIST_GetList(list_element_handle_t element) +{ + return element->list; +} + +/*! ********************************************************************************* + * \brief Links element to the tail of the list. + * + * \param[in] list - ID of list to insert into. + * element - element to add + * + * \return kLIST_Full if list is full. + * kLIST_Ok if insertion was successful. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element) +{ + uint32_t regPrimask = DisableGlobalIRQ(); + list_status_t listStatus = kLIST_Ok; + + listStatus = LIST_Error_Check(list, element); + if (listStatus == kLIST_Ok) /* Avoiding list status error */ + { + if (list->size == 0U) + { + list->head = element; + } + else + { + list->tail->next = element; + } +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) +#else + element->prev = list->tail; +#endif + element->list = list; + element->next = NULL; + list->tail = element; + list->size++; + } + + EnableGlobalIRQ(regPrimask); + return listStatus; +} + +/*! ********************************************************************************* + * \brief Links element to the head of the list. + * + * \param[in] list - ID of list to insert into. + * element - element to add + * + * \return kLIST_Full if list is full. + * kLIST_Ok if insertion was successful. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element) +{ + uint32_t regPrimask = DisableGlobalIRQ(); + list_status_t listStatus = kLIST_Ok; + + listStatus = LIST_Error_Check(list, element); + if (listStatus == kLIST_Ok) /* Avoiding list status error */ + { + /* Links element to the head of the list */ + if (list->size == 0U) + { + list->tail = element; + } +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) +#else + else + { + list->head->prev = element; + } + element->prev = NULL; +#endif + element->list = list; + element->next = list->head; + list->head = element; + list->size++; + } + + EnableGlobalIRQ(regPrimask); + return listStatus; +} + +/*! ********************************************************************************* + * \brief Unlinks element from the head of the list. + * + * \param[in] list - ID of list to remove from. + * + * \return NULL if list is empty. + * ID of removed element(pointer) if removal was successful. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_element_handle_t LIST_RemoveHead(list_handle_t list) +{ + list_element_handle_t element; + + uint32_t regPrimask = DisableGlobalIRQ(); + + if ((NULL == list) || (list->size == 0U)) + { + element = NULL; /*LIST_ is empty*/ + } + else + { + element = list->head; + list->size--; + if (list->size == 0U) + { + list->tail = NULL; + } +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) +#else + else + { + element->next->prev = NULL; + } +#endif + element->list = NULL; + list->head = element->next; /*Is NULL if element is head*/ + } + + EnableGlobalIRQ(regPrimask); + return element; +} + +/*! ********************************************************************************* + * \brief Gets head element ID. + * + * \param[in] list - ID of list. + * + * \return NULL if list is empty. + * ID of head element if list is not empty. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_element_handle_t LIST_GetHead(list_handle_t list) +{ + return list->head; +} + +/*! ********************************************************************************* + * \brief Gets next element ID. + * + * \param[in] element - ID of the element. + * + * \return NULL if element is tail. + * ID of next element if exists. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_element_handle_t LIST_GetNext(list_element_handle_t element) +{ + return element->next; +} + +/*! ********************************************************************************* + * \brief Gets previous element ID. + * + * \param[in] element - ID of the element. + * + * \return NULL if element is head. + * ID of previous element if exists. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_element_handle_t LIST_GetPrev(list_element_handle_t element) +{ +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) + return NULL; +#else + return element->prev; +#endif +} + +/*! ********************************************************************************* + * \brief Unlinks an element from its list. + * + * \param[in] element - ID of the element to remove. + * + * \return kLIST_OrphanElement if element is not part of any list. + * kLIST_Ok if removal was successful. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_status_t LIST_RemoveElement(list_element_handle_t element) +{ + list_status_t listStatus = kLIST_Ok; + uint32_t regPrimask = DisableGlobalIRQ(); + + if (element->list == NULL) + { + listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/ + } + else + { +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) + list_element_handle_t element_list = element->list->head; + while (element_list) + { + if (element->list->head == element) + { + element->list->head = element_list->next; + break; + } + if (element_list->next == element) + { + element_list->next = element->next; + break; + } + element_list = element_list->next; + } +#else + if (element->prev == NULL) /*Element is head or solo*/ + { + element->list->head = element->next; /*is null if solo*/ + } + if (element->next == NULL) /*Element is tail or solo*/ + { + element->list->tail = element->prev; /*is null if solo*/ + } + if (element->prev != NULL) /*Element is not head*/ + { + element->prev->next = element->next; + } + if (element->next != NULL) /*Element is not tail*/ + { + element->next->prev = element->prev; + } +#endif + element->list->size--; + element->list = NULL; + } + + EnableGlobalIRQ(regPrimask); + return listStatus; +} + +/*! ********************************************************************************* + * \brief Links an element in the previous position relative to a given member + * of a list. + * + * \param[in] element - ID of a member of a list. + * newElement - new element to insert before the given member. + * + * \return kLIST_OrphanElement if element is not part of any list. + * kLIST_Full if list is full. + * kLIST_Ok if insertion was successful. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement) +{ + list_status_t listStatus = kLIST_Ok; + uint32_t regPrimask = DisableGlobalIRQ(); + + if (element->list == NULL) + { + listStatus = kLIST_OrphanElement; /*Element was previusly removed or never added*/ + } + else + { + listStatus = LIST_Error_Check(element->list, newElement); + if (listStatus == kLIST_Ok) + { +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) + list_element_handle_t element_list = element->list->head; + while (element_list) + { + if ((element_list->next == element) || (element_list == element)) + { + if (element_list == element) + { + element->list->head = newElement; + } + else + { + element_list->next = newElement; + } + newElement->list = element->list; + newElement->next = element; + element->list->size++; + break; + } + element_list = element_list->next; + } + +#else + if (element->prev == NULL) /*Element is list head*/ + { + element->list->head = newElement; + } + else + { + element->prev->next = newElement; + } + newElement->list = element->list; + element->list->size++; + newElement->next = element; + newElement->prev = element->prev; + element->prev = newElement; +#endif + } + } + + EnableGlobalIRQ(regPrimask); + return listStatus; +} + +/*! ********************************************************************************* + * \brief Gets the current size of a list. + * + * \param[in] list - ID of the list. + * + * \return Current size of the list. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +uint32_t LIST_GetSize(list_handle_t list) +{ + return list->size; +} + +/*! ********************************************************************************* + * \brief Gets the number of free places in the list. + * + * \param[in] list - ID of the list. + * + * \return Available size of the list. + * + * \pre + * + * \post + * + * \remarks + * + ********************************************************************************** */ +uint32_t LIST_GetAvailableSize(list_handle_t list) +{ + return ((uint32_t)list->max - (uint32_t)list->size); /*Gets the number of free places in the list*/ +} \ No newline at end of file diff --git a/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.h b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.h new file mode 100644 index 0000000000..0da10d338d --- /dev/null +++ b/bsp/imxrt/libraries/MIMXRT1050/MIMXRT1052/drivers/generic_list.h @@ -0,0 +1,203 @@ +/* + * Copyright 2018-2020 NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _GENERIC_LIST_H_ +#define _GENERIC_LIST_H_ + +#include "fsl_common.h" +/*! + * @addtogroup GenericList + * @{ + */ + +/*!********************************************************************************* +************************************************************************************* +* Include +************************************************************************************* +********************************************************************************** */ + +/*! ********************************************************************************* +************************************************************************************* +* Public macro definitions +************************************************************************************* +********************************************************************************** */ +#ifndef GENERIC_LIST_LIGHT +#define GENERIC_LIST_LIGHT (0) +#endif +/*! ********************************************************************************* +************************************************************************************* +* Public type definitions +************************************************************************************* +********************************************************************************** */ +/*! @brief The list status */ +typedef enum _list_status +{ + kLIST_Ok = kStatus_Success, /*!< Success */ + kLIST_DuplicateError = MAKE_STATUS(kStatusGroup_LIST, 1), /*!< Duplicate Error */ + kLIST_Full = MAKE_STATUS(kStatusGroup_LIST, 2), /*!< FULL */ + kLIST_Empty = MAKE_STATUS(kStatusGroup_LIST, 3), /*!< Empty */ + kLIST_OrphanElement = MAKE_STATUS(kStatusGroup_LIST, 4), /*!< Orphan Element */ + kLIST_NotSupport = MAKE_STATUS(kStatusGroup_LIST, 5), /*!< Not Support */ +} list_status_t; + +/*! @brief The list structure*/ +typedef struct list_label +{ + struct list_element_tag *head; /*!< list head */ + struct list_element_tag *tail; /*!< list tail */ + uint16_t size; /*!< list size */ + uint16_t max; /*!< list max number of elements */ +} list_label_t, *list_handle_t; +#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U)) +/*! @brief The list element*/ +typedef struct list_element_tag +{ + struct list_element_tag *next; /*!< next list element */ + struct list_label *list; /*!< pointer to the list */ +} list_element_t, *list_element_handle_t; +#else +/*! @brief The list element*/ +typedef struct list_element_tag +{ + struct list_element_tag *next; /*!< next list element */ + struct list_element_tag *prev; /*!< previous list element */ + struct list_label *list; /*!< pointer to the list */ +} list_element_t, *list_element_handle_t; +#endif +/*! ********************************************************************************* +************************************************************************************* +* Public prototypes +************************************************************************************* +********************************************************************************** */ +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ +/*! + * @brief Initialize the list. + * + * This function initialize the list. + * + * @param list - List handle to initialize. + * @param max - Maximum number of elements in list. 0 for unlimited. + */ +void LIST_Init(list_handle_t list, uint32_t max); + +/*! + * @brief Gets the list that contains the given element. + * + * + * @param element - Handle of the element. + * @retval NULL if element is orphan, Handle of the list the element is inserted into. + */ +list_handle_t LIST_GetList(list_element_handle_t element); + +/*! + * @brief Links element to the head of the list. + * + * @param list - Handle of the list. + * @param element - Handle of the element. + * @retval kLIST_Full if list is full, kLIST_Ok if insertion was successful. + */ +list_status_t LIST_AddHead(list_handle_t list, list_element_handle_t element); + +/*! + * @brief Links element to the tail of the list. + * + * @param list - Handle of the list. + * @param element - Handle of the element. + * @retval kLIST_Full if list is full, kLIST_Ok if insertion was successful. + */ +list_status_t LIST_AddTail(list_handle_t list, list_element_handle_t element); + +/*! + * @brief Unlinks element from the head of the list. + * + * @param list - Handle of the list. + * + * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful. + */ +list_element_handle_t LIST_RemoveHead(list_handle_t list); + +/*! + * @brief Gets head element handle. + * + * @param list - Handle of the list. + * + * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful. + */ +list_element_handle_t LIST_GetHead(list_handle_t list); + +/*! + * @brief Gets next element handle for given element handle. + * + * @param element - Handle of the element. + * + * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful. + */ +list_element_handle_t LIST_GetNext(list_element_handle_t element); + +/*! + * @brief Gets previous element handle for given element handle. + * + * @param element - Handle of the element. + * + * @retval NULL if list is empty, handle of removed element(pointer) if removal was successful. + */ +list_element_handle_t LIST_GetPrev(list_element_handle_t element); + +/*! + * @brief Unlinks an element from its list. + * + * @param element - Handle of the element. + * + * @retval kLIST_OrphanElement if element is not part of any list. + * @retval kLIST_Ok if removal was successful. + */ +list_status_t LIST_RemoveElement(list_element_handle_t element); + +/*! + * @brief Links an element in the previous position relative to a given member of a list. + * + * @param list - Handle of the list. + * @param element - Handle of the element. + * @param newElement - New element to insert before the given member. + * + * @retval kLIST_OrphanElement if element is not part of any list. + * @retval kLIST_Ok if removal was successful. + */ +list_status_t LIST_AddPrevElement(list_element_handle_t element, list_element_handle_t newElement); + +/*! + * @brief Gets the current size of a list. + * + * @param list - Handle of the list. + * + * @retval Current size of the list. + */ +uint32_t LIST_GetSize(list_handle_t list); + +/*! + * @brief Gets the number of free places in the list. + * + * @param list - Handle of the list. + * + * @retval Available size of the list. + */ +uint32_t LIST_GetAvailableSize(list_handle_t list); + +/* @} */ + +#if defined(__cplusplus) +} +#endif +/*! @}*/ +#endif /*_GENERIC_LIST_H_*/ \ No newline at end of file diff --git a/bsp/imxrt/libraries/MIMXRT1050/SConscript b/bsp/imxrt/libraries/MIMXRT1050/SConscript index c774395330..58a2922fe1 100644 --- a/bsp/imxrt/libraries/MIMXRT1050/SConscript +++ b/bsp/imxrt/libraries/MIMXRT1050/SConscript @@ -83,6 +83,10 @@ if GetDepend(['BSP_USING_PULSE_ENCODER']): src += ['MIMXRT1052/drivers/fsl_xbara.c'] src += ['MIMXRT1052/drivers/fsl_xbarb.c'] +#fsl os abstract files +src += ['MIMXRT1052/drivers/fsl_os_abstraction_rtthread.c'] +src += ['MIMXRT1052/drivers/generic_list.c'] + if rtconfig.CROSS_TOOL == 'gcc': group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, ASFLAGS = '$ASFLAGS -D __STARTUP_CLEAR_BSS') else: diff --git a/bsp/imxrt/libraries/drivers/SConscript b/bsp/imxrt/libraries/drivers/SConscript index eaefd7c5e1..e166989a24 100644 --- a/bsp/imxrt/libraries/drivers/SConscript +++ b/bsp/imxrt/libraries/drivers/SConscript @@ -59,10 +59,14 @@ if GetDepend('BSP_USING_USB_DEVICE'): src += ['drv_usbd.c'] src += Glob('usb/device/*.c') -if GetDepend('BSP_USING_USB_DEVICE'): +if GetDepend('BSP_USING_USB_DEVICE') or GetDepend('RT_USING_USB_HOST'): src += Glob('usb/phy/*.c') - CPPDEFINES += ['ENDIANNESS'] + CPPDEFINES += ['ENDIANNESS','USE_RTOS'] +if GetDepend('RT_USING_USB_HOST'): + src += ['drv_usbh.c'] + src += Glob('usb/host/*.c') + if GetDepend('BSP_USING_PULSE_ENCODER'): src += ['drv_pulse_encoder.c'] diff --git a/bsp/imxrt/libraries/drivers/drv_usbh.c b/bsp/imxrt/libraries/drivers/drv_usbh.c new file mode 100644 index 0000000000..a7e0ad6062 --- /dev/null +++ b/bsp/imxrt/libraries/drivers/drv_usbh.c @@ -0,0 +1,730 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-10-30 ZYH the first version + * 2019-12-19 tyustli port to stm32 series + * 2021-01-19 Leslie Lee port to imxrt series + */ +#include + +#if defined(BSP_USB0_HOST) || defined(BSP_USB1_HOST) +#include "drv_usbh.h" +#include +#include +#include +#include +#include +#include +#include + + +/* USB PHY configuration */ +#ifndef BOARD_USB_PHY_D_CAL +#define BOARD_USB_PHY_D_CAL (0x0CU) +#endif +#ifndef BOARD_USB_PHY_TXCAL45DP +#define BOARD_USB_PHY_TXCAL45DP (0x06U) +#endif +#ifndef BOARD_USB_PHY_TXCAL45DM +#define BOARD_USB_PHY_TXCAL45DM (0x06U) +#endif + +#define USB_HOST_INTERRUPT_PRIORITY 3 + +enum +{ +#ifdef BSP_USB0_HOST + USBH0_INDEX, +#endif +#ifdef BSP_USB1_HOST + USBH1_INDEX, +#endif +}; + +struct imxrt_usb_host_pipe +{ + usb_host_pipe_handle pipe_handle; + struct rt_completion urb_completion; + usb_status_t transfer_status; +}; + +struct imxrt_usb_host +{ + struct uhcd uhcd; + usb_host_handle host_handle; + usb_device_handle device_handle; + struct imxrt_usb_host_pipe pipes[16]; + volatile rt_bool_t connect_status; + char *name; +}; + +static struct imxrt_usb_host imxrt_usb_host_obj[] = +{ +#ifdef BSP_USB0_HOST + { + .connect_status = RT_FALSE, + .name = "usbh0" + }, +#endif +#ifdef BSP_USB1_HOST + { + .connect_status = RT_FALSE, + .name = "usbh1" + }, +#endif +}; + +static void _imxrt_usb_host_send_callback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + struct imxrt_usb_host_pipe *pipe = (struct imxrt_usb_host_pipe *)param; + pipe->transfer_status = status; + rt_completion_done(&pipe->urb_completion); +} + + +/*! + * @brief Initializes USB specific setting that was not set by the Clocks tool. + */ +static void USB_HostClockInit(usb_controller_index_t controller_id) +{ + usb_phy_config_struct_t phyConfig = { + BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM, + }; + uint32_t notUsed = 0; + + if (controller_id == kUSB_ControllerEhci0) + { + CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U); + CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U); + } + else + { + CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U); + CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U); + } + + USB_EhciPhyInit(controller_id, 24000000U, &phyConfig); +} + +/*! + * @brief Enables interrupt service routines for device. + */ +void USB_HostIsrEnable(usb_controller_index_t controller_id) +{ + uint8_t irqNumber; +#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)) + IRQn_Type usbHOSTEhciIrq[] = USBHS_IRQS; + irqNumber = usbHOSTEhciIrq[controller_id - kUSB_ControllerEhci0]; +#endif +/* Install isr, set priority, and enable IRQ. */ +#if defined(__GIC_PRIO_BITS) + GIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY); +#else + NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY); +#endif + EnableIRQ((IRQn_Type)irqNumber); +} + +#ifdef BSP_USB0_HOST +void USB_OTG1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + USB_HostEhciIsrFunction(imxrt_usb_host_obj[USBH0_INDEX].host_handle); + /* leave interrupt */ + rt_interrupt_leave(); +} + +static rt_err_t _ehci0_reset_port(rt_uint8_t port) +{ + // No reset port function available + return RT_EOK; +} + +static uint8_t _ehci0_pipe_buf[64]; +static uint8_t _ehci0_pipe_idx; + +static int _ehci0_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts) +{ + int timeout = timeouts; + + if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status) + { + return -1; + } + usb_host_transfer_t *transfer; + if (imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle == NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error operation on null pipe\n")); + return -1; + } + if (USB_HostMallocTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, &transfer) != kStatus_USB_Success) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error to get transfer\n")); + return -1; + } + transfer->transferBuffer = buffer; + transfer->transferLength = nbytes; + transfer->transferSofar = 0; + transfer->callbackFn = _imxrt_usb_host_send_callback; + transfer->callbackParam = &(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index]); + transfer->direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT; + if (pipe->ep.bmAttributes == USB_ENDPOINT_CONTROL) + { + if (token == USBH_PID_SETUP) + { + struct urequest *setup = (struct urequest *)buffer; + transfer->setupStatus = 0; + transfer->setupPacket->bmRequestType = setup->request_type; + transfer->setupPacket->bRequest = setup->bRequest; + transfer->setupPacket->wIndex = setup->wIndex; + transfer->setupPacket->wLength = setup->wLength; + transfer->setupPacket->wValue = setup->wValue; + transfer->transferBuffer = RT_NULL; + transfer->transferLength = 0; + transfer->next = RT_NULL; + if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN) + { + transfer->direction = USB_IN; + transfer->transferBuffer = _ehci0_pipe_buf; + transfer->transferLength = setup->wLength; + _ehci0_pipe_idx = 0; + } + else + { + transfer->direction = USB_OUT; + } + } + else + { + rt_memcpy(buffer, _ehci0_pipe_buf + _ehci0_pipe_idx, nbytes); + imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].transfer_status = kStatus_USB_Success; + transfer->transferSofar = nbytes; + _ehci0_pipe_idx += nbytes; + if (_ehci0_pipe_idx >= 64) + { + _ehci0_pipe_idx = 0; + } + goto _ehci0_pipe_xfer_finish; + } + + } + rt_completion_init(&(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].urb_completion)); + if (USB_HostEhciWritePipe(((usb_host_instance_t *)imxrt_usb_host_obj[USBH0_INDEX].host_handle)->controllerHandle, imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle, transfer) != kStatus_USB_Success) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb host failed to send\n")); + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer); + return -1; + } + if (-RT_ETIMEOUT == rt_completion_wait(&(imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].urb_completion), RT_WAITING_FOREVER)) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb transfer timeout\n")); + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer); + return -1; + } + _ehci0_pipe_xfer_finish: + switch (imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].transfer_status) + { + case kStatus_USB_Success: + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("ok\n")); + pipe->status = UPIPE_STATUS_OK; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + size_t size = transfer->transferSofar; + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer); + if (pipe->ep.bEndpointAddress & 0x80) + { + return size; + } + else if (pipe->ep.bEndpointAddress & 0x00) + { + return size; + } + return nbytes; + break; + } + case kStatus_USB_TransferStall: + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("stall\n")); + pipe->status = UPIPE_STATUS_STALL; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer); + return -1; + break; + } + case kStatus_USB_TransferFailed: + default: + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error\n")); + pipe->status = UPIPE_STATUS_ERROR; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH0_INDEX].host_handle, transfer); + return -1; + break; + } + } +} + +static rt_uint16_t _ehci0_pipe_index = 0; +static rt_uint8_t _ehci0_get_free_pipe_index(void) +{ + rt_uint8_t idx; + for (idx = 1; idx < 16; idx++) + { + if (!(_ehci0_pipe_index & (0x01 << idx))) + { + _ehci0_pipe_index |= (0x01 << idx); + return idx; + } + } + return 0xff; +} + +static void _ehci0_free_pipe_index(rt_uint8_t index) +{ + _ehci0_pipe_index &= ~(0x01 << index); +} + +static rt_err_t _ehci0_open_pipe(upipe_t pipe) +{ + pipe->pipe_index = _ehci0_get_free_pipe_index(); + if (pipe->pipe_index == 0xFF) + { + return -RT_ERROR; + } + usb_host_pipe_init_t pipe_init = + { + .devInstance = imxrt_usb_host_obj[USBH0_INDEX].device_handle, + .pipeType = pipe->ep.bmAttributes, + .direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT, + .endpointAddress = (pipe->ep.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK), + .interval = pipe->ep.bInterval, + .maxPacketSize = (uint16_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK), + .numberPerUframe = (uint8_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK), + .nakCount = USB_HOST_CONFIG_MAX_NAK, + }; + USB_HostOpenPipe(imxrt_usb_host_obj[USBH0_INDEX].host_handle, &imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle, &pipe_init); + return RT_EOK; +} + +static rt_err_t _ehci0_close_pipe(upipe_t pipe) +{ + (void)USB_HostClosePipe(imxrt_usb_host_obj[USBH0_INDEX].host_handle, imxrt_usb_host_obj[USBH0_INDEX].pipes[pipe->pipe_index].pipe_handle); + _ehci0_free_pipe_index(pipe->pipe_index); + return RT_EOK; +} + +static struct uhcd_ops _ehci0_uhcd_ops = +{ + _ehci0_reset_port, + _ehci0_pipe_xfer, + _ehci0_open_pipe, + _ehci0_close_pipe, +}; + +static usb_status_t usb0_host_callback(usb_device_handle handle, usb_host_configuration_handle config_handle, rt_uint32_t event_code) +{ + usb_status_t status = kStatus_USB_Success; + + switch (event_code) + { + case kUSB_HostEventAttach: + if (!imxrt_usb_host_obj[USBH0_INDEX].connect_status) + { + imxrt_usb_host_obj[USBH0_INDEX].connect_status = RT_TRUE; + imxrt_usb_host_obj[USBH0_INDEX].device_handle = handle; + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb connected\n")); + rt_usbh_root_hub_connect_handler(&(imxrt_usb_host_obj[USBH0_INDEX].uhcd), OTG_PORT, RT_TRUE); + } + break; + + case kUSB_HostEventNotSupported: + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb device not supported\n")); + break; + + case kUSB_HostEventEnumerationDone: + RT_DEBUG_LOG(RT_DEBUG_USB, ("enumeration done\n")); + break; + + case kUSB_HostEventDetach: + if (imxrt_usb_host_obj[USBH0_INDEX].connect_status) + { + imxrt_usb_host_obj[USBH0_INDEX].connect_status = RT_FALSE; + imxrt_usb_host_obj[USBH0_INDEX].device_handle = handle; + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnnect\n")); + rt_usbh_root_hub_disconnect_handler(&(imxrt_usb_host_obj[USBH0_INDEX].uhcd), OTG_PORT); + (void)USB_HostCloseDeviceInterface(handle, NULL); + } + break; + + default: + break; + } + return status; +} + +rt_thread_t usbh0_thread; + +static void _ehci0_usbh_thread(void* param) +{ + while (1) + { + USB_HostEhciTaskFunction(imxrt_usb_host_obj[USBH0_INDEX].host_handle); + } +} + +static rt_err_t _ehci0_usbh_init(rt_device_t device) +{ + USB_HostClockInit(kUSB_ControllerEhci0); + + if (kStatus_USB_Success == USB_HostInit(kUSB_ControllerEhci0, &imxrt_usb_host_obj[USBH0_INDEX].host_handle, usb0_host_callback)) + { + usbh0_thread = rt_thread_create("ehci0", _ehci0_usbh_thread, RT_NULL, 500, 4, 9999999); + rt_thread_startup(usbh0_thread); + USB_HostIsrEnable(kUSB_ControllerEhci0); + } + else + { + rt_kprintf("USB_HostInit ehci0 error\r\n"); + return -RT_ERROR; + } + return RT_EOK; +} +#endif + +#ifdef BSP_USB1_HOST +void USB_OTG2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + USB_HostEhciIsrFunction(imxrt_usb_host_obj[USBH1_INDEX].host_handle); + /* leave interrupt */ + rt_interrupt_leave(); +} + +static rt_err_t _ehci1_reset_port(rt_uint8_t port) +{ + // No reset port function available + return RT_EOK; +} + +static uint8_t _ehci1_pipe_buf[64]; +static uint8_t _ehci1_pipe_idx; + +static int _ehci1_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts) +{ + int timeout = timeouts; + + if (!imxrt_usb_host_obj[USBH1_INDEX].connect_status) + { + return -1; + } + usb_host_transfer_t *transfer; + if (imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle == NULL) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error operation on null pipe\n")); + return -1; + } + if (USB_HostMallocTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, &transfer) != kStatus_USB_Success) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error to get transfer\n")); + return -1; + } + transfer->transferBuffer = buffer; + transfer->transferLength = nbytes; + transfer->transferSofar = 0; + transfer->callbackFn = _imxrt_usb_host_send_callback; + transfer->callbackParam = &(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index]); + transfer->direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT; + if (pipe->ep.bmAttributes == USB_ENDPOINT_CONTROL) + { + if (token == USBH_PID_SETUP) + { + struct urequest *setup = (struct urequest *)buffer; + transfer->setupStatus = 0; + transfer->setupPacket->bmRequestType = setup->request_type; + transfer->setupPacket->bRequest = setup->bRequest; + transfer->setupPacket->wIndex = setup->wIndex; + transfer->setupPacket->wLength = setup->wLength; + transfer->setupPacket->wValue = setup->wValue; + transfer->transferBuffer = RT_NULL; + transfer->transferLength = 0; + transfer->next = RT_NULL; + if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN) + { + transfer->direction = USB_IN; + transfer->transferBuffer = _ehci1_pipe_buf; + transfer->transferLength = setup->wLength; + _ehci1_pipe_idx = 0; + } + else + { + transfer->direction = USB_OUT; + } + } + else + { + rt_memcpy(buffer, _ehci1_pipe_buf + _ehci1_pipe_idx, nbytes); + imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].transfer_status = kStatus_USB_Success; + transfer->transferSofar = nbytes; + _ehci1_pipe_idx += nbytes; + if (_ehci1_pipe_idx >= 64) + { + _ehci1_pipe_idx = 0; + } + goto _ehci1_pipe_xfer_finish; + } + + } + rt_completion_init(&(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].urb_completion)); + if (USB_HostEhciWritePipe(((usb_host_instance_t *)imxrt_usb_host_obj[USBH1_INDEX].host_handle)->controllerHandle, imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle, transfer) != kStatus_USB_Success) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb host failed to send\n")); + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer); + return -1; + } + if (-RT_ETIMEOUT == rt_completion_wait(&(imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].urb_completion), RT_WAITING_FOREVER)) + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb transfer timeout\n")); + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer); + return -1; + } + // rt_thread_mdelay(1); + _ehci1_pipe_xfer_finish: + switch (imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].transfer_status) + { + case kStatus_USB_Success: + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("ok\n")); + pipe->status = UPIPE_STATUS_OK; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + size_t size = transfer->transferSofar; + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer); + if (pipe->ep.bEndpointAddress & 0x80) + { + return size; + } + else if (pipe->ep.bEndpointAddress & 0x00) + { + return size; + } + return nbytes; + break; + } + case kStatus_USB_TransferStall: + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("stall\n")); + pipe->status = UPIPE_STATUS_STALL; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer); + return -1; + break; + } + case kStatus_USB_TransferFailed: + default: + { + RT_DEBUG_LOG(RT_DEBUG_USB, ("error\n")); + pipe->status = UPIPE_STATUS_ERROR; + if (pipe->callback != RT_NULL) + { + pipe->callback(pipe); + } + (void)USB_HostFreeTransfer(imxrt_usb_host_obj[USBH1_INDEX].host_handle, transfer); + return -1; + break; + } + } +} + +static rt_uint16_t _ehci1_pipe_index = 0; +static rt_uint8_t _ehci1_get_free_pipe_index(void) +{ + rt_uint8_t idx; + for (idx = 1; idx < 16; idx++) + { + if (!(_ehci1_pipe_index & (0x01 << idx))) + { + _ehci1_pipe_index |= (0x01 << idx); + return idx; + } + } + return 0xff; +} + +static void _ehci1_free_pipe_index(rt_uint8_t index) +{ + _ehci1_pipe_index &= ~(0x01 << index); +} + +static rt_err_t _ehci1_open_pipe(upipe_t pipe) +{ + pipe->pipe_index = _ehci1_get_free_pipe_index(); + if (pipe->pipe_index == 0xFF) + { + return -RT_ERROR; + } + usb_host_pipe_init_t pipe_init = + { + .devInstance = imxrt_usb_host_obj[USBH1_INDEX].device_handle, + .pipeType = pipe->ep.bmAttributes, + .direction = (pipe->ep.bEndpointAddress & USB_DIR_IN) ? USB_IN : USB_OUT, + .endpointAddress = (pipe->ep.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK), + .interval = pipe->ep.bInterval, + .maxPacketSize = (uint16_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK), + .numberPerUframe = (uint8_t)(pipe->ep.wMaxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK), + .nakCount = USB_HOST_CONFIG_MAX_NAK, + }; + USB_HostOpenPipe(imxrt_usb_host_obj[USBH1_INDEX].host_handle, &imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle, &pipe_init); + return RT_EOK; +} + +static rt_err_t _ehci1_close_pipe(upipe_t pipe) +{ + (void)USB_HostClosePipe(imxrt_usb_host_obj[USBH1_INDEX].host_handle, imxrt_usb_host_obj[USBH1_INDEX].pipes[pipe->pipe_index].pipe_handle); + _ehci1_free_pipe_index(pipe->pipe_index); + return RT_EOK; +} + +static struct uhcd_ops _ehci1_uhcd_ops = +{ + _ehci1_reset_port, + _ehci1_pipe_xfer, + _ehci1_open_pipe, + _ehci1_close_pipe, +}; + +static usb_status_t usb1_host_callback(usb_device_handle handle, usb_host_configuration_handle config_handle, rt_uint32_t event_code) +{ + usb_status_t status = kStatus_USB_Success; + + switch (event_code) + { + case kUSB_HostEventAttach: + if (!imxrt_usb_host_obj[USBH1_INDEX].connect_status) + { + imxrt_usb_host_obj[USBH1_INDEX].connect_status = RT_TRUE; + imxrt_usb_host_obj[USBH1_INDEX].device_handle = handle; + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb connected\n")); + rt_usbh_root_hub_connect_handler(&(imxrt_usb_host_obj[USBH1_INDEX].uhcd), OTG_PORT, RT_TRUE); + } + break; + + case kUSB_HostEventNotSupported: + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb device not supported\n")); + break; + + case kUSB_HostEventEnumerationDone: + RT_DEBUG_LOG(RT_DEBUG_USB, ("enumeration done\n")); + break; + + case kUSB_HostEventDetach: + if (imxrt_usb_host_obj[USBH1_INDEX].connect_status) + { + imxrt_usb_host_obj[USBH1_INDEX].connect_status = RT_FALSE; + imxrt_usb_host_obj[USBH1_INDEX].device_handle = handle; + RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnnect\n")); + rt_usbh_root_hub_disconnect_handler(&(imxrt_usb_host_obj[USBH1_INDEX].uhcd), OTG_PORT); + (void)USB_HostCloseDeviceInterface(handle, NULL); + } + break; + + default: + break; + } + return status; +} + +rt_thread_t usbh1_thread; + +static void _ehci1_usbh_thread(void* param) +{ + while (1) + { + USB_HostEhciTaskFunction(imxrt_usb_host_obj[USBH1_INDEX].host_handle); + } +} + +static rt_err_t _ehci1_usbh_init(rt_device_t device) +{ + USB_HostClockInit(kUSB_ControllerEhci1); + + if (kStatus_USB_Success == USB_HostInit(kUSB_ControllerEhci1, &imxrt_usb_host_obj[USBH1_INDEX].host_handle, usb1_host_callback)) + { + usbh1_thread = rt_thread_create("ehci1", _ehci1_usbh_thread, RT_NULL, 500, 4, 9999999); + rt_thread_startup(usbh1_thread); + USB_HostIsrEnable(kUSB_ControllerEhci1); + } + else + { + rt_kprintf("USB_HostInit ehci1 error\r\n"); + return -RT_ERROR; + } + return RT_EOK; +} +#endif + +int imxrt_usbh_register(void) +{ + rt_err_t res = -RT_ERROR; + struct imxrt_usb_host *usb_host_obj; + +#ifdef BSP_USB0_HOST + usb_host_obj = &(imxrt_usb_host_obj[USBH0_INDEX]); + rt_memset((void *)(&(usb_host_obj->uhcd)), 0, sizeof(struct uhcd)); + usb_host_obj->uhcd.parent.type = RT_Device_Class_USBHost; + usb_host_obj->uhcd.parent.init = _ehci0_usbh_init; + usb_host_obj->uhcd.parent.user_data = usb_host_obj; + usb_host_obj->uhcd.ops = &_ehci0_uhcd_ops; + usb_host_obj->uhcd.num_ports = OTG_PORT; + res = rt_device_register(&(usb_host_obj->uhcd.parent), usb_host_obj->name, RT_DEVICE_FLAG_DEACTIVATE); + if (res != RT_EOK) + { + rt_kprintf("register usb0 host failed res = %d\r\n", res); + return -RT_ERROR; + } + + rt_usb_host_init(usb_host_obj->name); +#endif +#ifdef BSP_USB1_HOST + usb_host_obj = &(imxrt_usb_host_obj[USBH1_INDEX]); + rt_memset((void *)(&(usb_host_obj->uhcd)), 0, sizeof(struct uhcd)); + usb_host_obj->uhcd.parent.type = RT_Device_Class_USBHost; + usb_host_obj->uhcd.parent.init = _ehci1_usbh_init; + usb_host_obj->uhcd.parent.user_data = usb_host_obj; + usb_host_obj->uhcd.ops = &_ehci1_uhcd_ops; + usb_host_obj->uhcd.num_ports = OTG_PORT; + res = rt_device_register(&(usb_host_obj->uhcd.parent), usb_host_obj->name, RT_DEVICE_FLAG_DEACTIVATE); + if (res != RT_EOK) + { + rt_kprintf("register usb0 host failed res = %d\r\n", res); + return -RT_ERROR; + } + + rt_usb_host_init(usb_host_obj->name); +#endif + return RT_EOK; +} +INIT_DEVICE_EXPORT(imxrt_usbh_register); + +#endif \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/drv_usbh.h b/bsp/imxrt/libraries/drivers/drv_usbh.h new file mode 100644 index 0000000000..db1f2074f8 --- /dev/null +++ b/bsp/imxrt/libraries/drivers/drv_usbh.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-12-12 ZYH the first version + * 2019-12-19 tyustli port to stm32 series + * 2021-01-19 Leslie Lee port to imxrt series + */ +#ifndef __DRV_USBH_H__ +#define __DRV_USBH_H__ +#include + +#define OTG_PORT 1 + +int imxrt_usbh_register(void); + +#endif + +/************* end of file ************/ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host.h index 53be402cd3..6d338bb64b 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host.h +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016 - 2019 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _USB_HOST_H_ @@ -68,6 +46,16 @@ typedef enum _usb_host_event kUSB_HostEventDetach, /*!< Device is detached */ kUSB_HostEventEnumerationDone, /*!< Device's enumeration is done and the device is supported */ kUSB_HostEventNotSupported, /*!< Device's enumeration is done and the device is not supported */ + /*! Device's enumeration failed due to errors + * fail reason is put in the high 2 bytes of callback event code. + * kStatus_USB_TransferFailed - the transfer failed. + * kStatus_USB_TransferCancel - transfer is canceled by application. + * kStatus_USB_Error - parsing descriptor failed, the power cannot satisfy device's requirement, + * device addresss allocation failed, transfer is not enough + * or the transfer API failed. + * kStatus_USB_AllocFail - malloc failed. + */ + kUSB_HostEventEnumerationFail, #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) kUSB_HostEventNotSuspended, /*!< Suspend failed */ kUSB_HostEventSuspended, /*!< Suspend successful */ @@ -103,7 +91,60 @@ typedef enum _usb_host_dev_info kUSB_HostGetConfigurationDes, /*!< Device's configuration descriptor pointer */ kUSB_HostGetConfigurationLength, /*!< Device's configuration descriptor pointer */ } usb_host_dev_info_t; +/*! @brief Request type */ +typedef enum _usb_host_request_type +{ + kRequestDevice = 1U, /*!< Control request object is device */ + kRequestInterface, /*!< Control request object is interface */ + kRequestEndpoint, /*!< Control request object is endpoint */ +} usb_host_request_type_t; +/*! @brief For USB_REQUEST_STANDARD_GET_DESCRIPTOR and USB_REQUEST_STANDARD_SET_DESCRIPTOR */ +typedef struct _usb_host_process_descriptor_param +{ + uint8_t descriptorType; /*!< See the usb_spec.h, such as the USB_DESCRIPTOR_TYPE_DEVICE */ + uint8_t descriptorIndex; /*!< The descriptor index is used to select a specific descriptor (only for configuration + and string descriptors) when several descriptors of the same type are implemented in a + device */ + uint8_t languageId; /*!< It specifies the language ID for string descriptors or is reset to zero for other + descriptors */ + uint8_t *descriptorBuffer; /*!< Buffer pointer */ + uint16_t descriptorLength; /*!< Buffer data length */ +} usb_host_process_descriptor_param_t; +/*! @brief For USB_REQUEST_STANDARD_CLEAR_FEATURE and USB_REQUEST_STANDARD_SET_FEATURE */ +typedef struct _usb_host_process_feature_param +{ + uint8_t requestType; /*!< See the #usb_host_request_type_t */ + uint8_t featureSelector; /*!< Set/cleared feature */ + uint8_t interfaceOrEndpoint; /*!< Interface or end pointer */ +} usb_host_process_feature_param_t; +/*! @brief For USB_REQUEST_STANDARD_GET_INTERFACE */ +typedef struct _usb_host_get_interface_param +{ + uint8_t interface; /*!< Interface number */ + uint8_t *alternateInterfaceBuffer; /*!< Save the transfer result */ +} usb_host_get_interface_param_t; +/*! @brief For USB_REQUEST_STANDARD_GET_STATUS */ +typedef struct _usb_host_get_status_param +{ + uint16_t statusSelector; /*!< Interface number, the end pointer number or OTG status selector */ + uint8_t requestType; /*!< See the #usb_host_request_type_t */ + uint8_t *statusBuffer; /*!< Save the transfer result */ +} usb_host_get_status_param_t; + +/*! @brief For USB_REQUEST_STANDARD_SET_INTERFACE */ +typedef struct _usb_host_set_interface_param +{ + uint8_t alternateSetting; /*!< Alternate setting value */ + uint8_t interface; /*!< Interface number */ +} usb_host_set_interface_param_t; + +/*! @brief For USB_REQUEST_STANDARD_SYNCH_FRAME */ +typedef struct _usb_host_synch_frame_param +{ + uint8_t endpoint; /*!< Endpoint number */ + uint8_t *frameNumberBuffer; /*!< Frame number data buffer */ +} usb_host_synch_frame_param_t; /*! * @brief Host callback function typedef. * @@ -243,8 +284,8 @@ typedef struct _usb_host_pipe_init /*! @brief Cancel transfer parameter structure */ typedef struct _usb_host_cancel_param { - usb_host_pipe_handle pipeHandle; /*!< Cancelling pipe handle*/ - usb_host_transfer_t *transfer; /*!< Cancelling transfer*/ + usb_host_pipe_handle pipeHandle; /*!< Canceling pipe handle*/ + usb_host_transfer_t *transfer; /*!< Canceling transfer*/ } usb_host_cancel_param_t; /******************************************************************************* @@ -342,7 +383,7 @@ extern usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handl * @retval kStatus_USB_InvalidParameter The deviceHandle instance don't belong to hostHandle instance. */ extern usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle); - +#if (defined(USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI > 0U)) /*! * @brief KHCI task function. * @@ -353,7 +394,8 @@ extern usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_ * @param[in] hostHandle The host handle. */ extern void USB_HostKhciTaskFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)) /*! * @brief EHCI task function. * @@ -364,7 +406,8 @@ extern void USB_HostKhciTaskFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostEhciTaskFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U)) /*! * @brief OHCI task function. * @@ -375,7 +418,8 @@ extern void USB_HostEhciTaskFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostOhciTaskFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U)) /*! * @brief IP3516HS task function. * @@ -386,7 +430,8 @@ extern void USB_HostOhciTaskFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostIp3516HsTaskFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI > 0U)) /*! * @brief Device KHCI ISR function. * @@ -395,7 +440,8 @@ extern void USB_HostIp3516HsTaskFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostKhciIsrFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)) /*! * @brief Device EHCI ISR function. * @@ -404,7 +450,8 @@ extern void USB_HostKhciIsrFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostEhciIsrFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U)) /*! * @brief Device OHCI ISR function. * @@ -413,7 +460,8 @@ extern void USB_HostEhciIsrFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostOhciIsrFunction(void *hostHandle); - +#endif +#if (defined(USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U)) /*! * @brief Device IP3516HS ISR function. * @@ -422,7 +470,7 @@ extern void USB_HostOhciIsrFunction(void *hostHandle); * @param[in] hostHandle The host handle. */ extern void USB_HostIp3516HsIsrFunction(void *hostHandle); - +#endif /*! @}*/ /*! @@ -566,7 +614,7 @@ extern usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_tr * This function sends the USB standard request packet. * * @param[in] deviceHandle The device handle for control transfer. - * @param[in] usbRequest A USB standard request code. Se the usb_spec.h. + * @param[in] usbRequest A USB standard request code. See the usb_spec.h. * @param[in] transfer The used transfer. * @param[in] param The parameter structure is different for different request, see * usb_host_framework.h. @@ -694,10 +742,10 @@ extern usb_status_t USB_HostL1ResumeDeviceResquest(usb_host_handle hostHandle, /*! * @brief Update the lpm param. * - * The function is used to configuure the lpm token. + * The function is used to configure the lpm token. * * @param[in] hostHandle The host handle. - * @param[in] lpmParam HIRD vaule and whether enable remotewakeup. + * @param[in] lpmParam HIRD value and whether enable remotewakeup. * */ extern usb_status_t USB_HostL1SleepDeviceResquestConfig(usb_host_handle hostHandle, uint8_t *lpmParam); @@ -715,6 +763,19 @@ extern usb_status_t USB_HostUpdateHwTick(usb_host_handle hostHandle, uint64_t ti #endif +#if ((defined(USB_HOST_CONFIG_BATTERY_CHARGER)) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) +/*! + * @brief Set the charger type. It is only supported on RT600 currently. + * + * The set charger type becomes valid in next attach. + * + * @param[in] hostHandle The host handle. + * @param[in] type. + * + */ +extern usb_status_t USB_HostSetChargerType(usb_host_handle hostHandle, uint8_t type); +#endif + /*! @}*/ #ifdef __cplusplus @@ -723,4 +784,4 @@ extern usb_status_t USB_HostUpdateHwTick(usb_host_handle hostHandle, uint64_t ti /*! @}*/ -#endif /* _USB_HOST_H_ */ +#endif /* _USB_HOST_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c index 42b16e071e..1989d6ec76 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.c @@ -1,46 +1,28 @@ /* * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016,2019 NXP * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include +#include #include "usb_host.h" #include "usb_host_hci.h" #include "usb_host_devices.h" - +#include "usb_host_framework.h" #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) #include "usb_host_hub.h" +#include "usb_host_hub_app.h" #endif /* USB_HOST_CONFIG_HUB */ /******************************************************************************* * Definitions ******************************************************************************/ +#ifndef USB_HOST_CONFIG_MAX_CONFIGURATION_DESCRIPTOR_LENGTH +#define USB_HOST_CONFIG_MAX_CONFIGURATION_DESCRIPTOR_LENGTH (5000U) +#endif + /******************************************************************************* * Prototypes ******************************************************************************/ @@ -70,7 +52,7 @@ static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInsta * * @return kStatus_USB_Success or error codes */ -static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance); +static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance, uint32_t dataLength); /*! * @brief notify the application event, the callback is registered when initializing host. @@ -80,7 +62,10 @@ static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceIn * * @return kStatus_USB_Success or error codes */ -static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInstance, uint32_t eventCode); +static usb_status_t USB_HostNotifyDevice(usb_host_handle hostHandle, + usb_host_device_instance_t *deviceInstance, + uint32_t eventCode, + uint32_t eventParameter); /*! * @brief allocate one address. @@ -140,68 +125,57 @@ static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb */ static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType); -extern usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance, - usb_host_transfer_t *transfer, - void *param); -extern usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance, - usb_host_transfer_t *transfer, - void *param); -extern usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance, - usb_host_transfer_t *transfer, - uint8_t *buffer, - uint32_t bufferLen); - #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) -extern usb_status_t USB_HostHubDeviceEvent(usb_host_handle hostHandle, - usb_device_handle deviceHandle, - usb_host_configuration_handle configurationHandle, - uint32_t eventCode); - -extern uint32_t USB_HostHubGetHsHubNumber(usb_host_handle hostHandle, uint8_t parentHubNo); - -extern uint32_t USB_HostHubGetHsHubPort(usb_host_handle hostHandle, uint8_t parentHubNo, uint8_t parentPortNo); - -extern usb_status_t USB_HostHubRemovePort(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber); - #endif /******************************************************************************* * Variables ******************************************************************************/ -extern usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST]; - /*! @brief enumeration step process array */ -static const usb_host_enum_process_entry_t s_EnumEntries[] = \ -{ +static const usb_host_enum_process_entry_t s_EnumEntries[] = { /* kStatus_dev_initial */ { - 0, 0, NULL, + kStatus_DEV_Notinit, + kStatus_DEV_Notinit, + NULL, }, /* kStatus_DEV_GetDes8 */ { - kStatus_DEV_SetAddress, kStatus_DEV_GetDes8, USB_HostProcessCallback, + kStatus_DEV_SetAddress, + kStatus_DEV_GetDes8, + USB_HostProcessCallback, }, /* kStatus_DEV_SetAddress */ { - kStatus_DEV_GetDes, kStatus_DEV_SetAddress, USB_HostProcessCallback, + kStatus_DEV_GetDes, + kStatus_DEV_SetAddress, + USB_HostProcessCallback, }, /* kStatus_DEV_GetDes */ { - kStatus_DEV_GetCfg9, kStatus_DEV_GetDes, NULL, + kStatus_DEV_GetCfg9, + kStatus_DEV_GetDes, + NULL, }, /* kStatus_DEV_GetCfg9 */ { - kStatus_DEV_GetCfg, kStatus_DEV_GetCfg9, USB_HostProcessCallback, + kStatus_DEV_GetCfg, + kStatus_DEV_GetCfg9, + USB_HostProcessCallback, }, /* kStatus_DEV_GetCfg */ { - kStatus_DEV_SetCfg, kStatus_DEV_GetCfg9, USB_HostProcessCallback, + kStatus_DEV_SetCfg, + kStatus_DEV_GetCfg9, + USB_HostProcessCallback, }, /* kStatus_DEV_SetCfg */ { - kStatus_DEV_EnumDone, kStatus_DEV_SetCfg, NULL, + kStatus_DEV_EnumDone, + kStatus_DEV_SetCfg, + NULL, }, }; @@ -211,69 +185,66 @@ static const usb_host_enum_process_entry_t s_EnumEntries[] = \ static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) { - uint8_t nextStep = 0; + /* 0 - retry current transfer, 1 - transfer success process, + * 2 - retry whole process, 3 - fail process + */ + uint8_t nextStep = 0U; usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)param; + usb_status_t failReason = kStatus_USB_Success; + uint32_t dataLength; - USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); /* free transfer */ + dataLength = transfer->transferSofar; + (void)USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); /* free transfer */ if (status == kStatus_USB_Success) { - nextStep = 1; + nextStep = 1U; } else if (status == kStatus_USB_TransferStall) { #if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) - usb_echo("no response from device\r\n"); -#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */ - if (deviceInstance->stallRetries > 0) /* retry same transfer when stall */ + (void)usb_echo("no response from device\r\n"); +#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */ + if (deviceInstance->stallRetries > 0U) /* retry same transfer when stall */ { + nextStep = 0U; deviceInstance->stallRetries--; } - else /* process next state when all retries stall */ + else { - nextStep = 1; + failReason = kStatus_USB_TransferFailed; + nextStep = 2U; } } else if (status == kStatus_USB_TransferCancel) { - return; + failReason = kStatus_USB_TransferCancel; + nextStep = 3U; } else { - if (deviceInstance->enumRetries > 0) /* next whole retry */ - { - deviceInstance->enumRetries--; - deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES; - deviceInstance->configurationValue = 0; - deviceInstance->state = kStatus_DEV_GetDes8; - } - else - { -#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) - usb_echo("Device No Response\r\n"); -#endif - return; - } + failReason = kStatus_USB_TransferFailed; + nextStep = 2U; } - if (nextStep == 1) + if (nextStep == 1U) { deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES; - if (s_EnumEntries[deviceInstance->state - 1].process == NULL) + if (s_EnumEntries[deviceInstance->state - 1U].process == NULL) { - deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].successState; /* next state */ + deviceInstance->state = (uint8_t)s_EnumEntries[deviceInstance->state - 1U].successState; /* next state */ } else { - status = s_EnumEntries[deviceInstance->state - 1].process( - deviceInstance); /* process the previous state result */ + status = s_EnumEntries[deviceInstance->state - 1U].process( + deviceInstance, dataLength); /* process the previous state result */ if (status == kStatus_USB_Success) /* process success */ { - deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].successState; + deviceInstance->state = (uint8_t)s_EnumEntries[deviceInstance->state - 1U].successState; } else if (status == kStatus_USB_Retry) /* need retry */ { - deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].retryState; + deviceInstance->state = (uint8_t)s_EnumEntries[deviceInstance->state - 1U].retryState; } else if (status == kStatus_USB_NotSupported) /* device don't suport by the application */ { @@ -281,30 +252,48 @@ static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t } else /* process error, next retry */ { - if (deviceInstance->enumRetries > 0) /* next whole retry */ - { - deviceInstance->enumRetries--; - deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES; - deviceInstance->configurationValue = 0; - deviceInstance->state = kStatus_DEV_GetDes8; - } - else - { -#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) - usb_echo("Device No Response\r\n"); -#endif - return; /* unrecoverable fail */ - } + /* kStatus_USB_Error or kStatus_USB_AllocFail */ + failReason = status; + nextStep = 2U; } } } - if (USB_HostProcessState(deviceInstance) != kStatus_USB_Success) /* process the new state */ + if (nextStep == 2U) { -#ifdef HOST_ECHO - usb_echo("enumation setup error\r\n"); + if (deviceInstance->enumRetries > 0U) /* next whole retry */ + { + deviceInstance->enumRetries--; + deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES; + deviceInstance->configurationValue = 0U; + deviceInstance->state = (uint8_t)kStatus_DEV_GetDes8; + } + else + { +#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) + usb_echo("Device No Response\r\n"); #endif - return; + nextStep = 3U; + } + } + + /* process the state */ + if (nextStep != 3U) + { + if (USB_HostProcessState(deviceInstance) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("enumation setup error\r\n"); +#endif + failReason = kStatus_USB_Error; + nextStep = 3U; + } + } + + if (nextStep == 3U) + { + (void)USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance, (uint32_t)kUSB_HostEventEnumerationFail, + (uint32_t)failReason); } } @@ -313,9 +302,11 @@ static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInsta usb_status_t status = kStatus_USB_Success; usb_host_process_descriptor_param_t getDescriptorParam; usb_host_transfer_t *transfer; + usb_host_device_enumeration_status_t state; /* malloc transfer */ - if (deviceInstance->state != kStatus_DEV_EnumDone) + state = (usb_host_device_enumeration_status_t)deviceInstance->state; + if (state != kStatus_DEV_EnumDone) { if (USB_HostMallocTransfer(deviceInstance->hostHandle, &transfer) != kStatus_USB_Success) { @@ -324,29 +315,29 @@ static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInsta #endif return kStatus_USB_Error; } - transfer->callbackFn = USB_HostEnumerationTransferCallback; + transfer->callbackFn = USB_HostEnumerationTransferCallback; transfer->callbackParam = deviceInstance; /* reset transfer fields */ - transfer->setupPacket->bmRequestType = 0x00; - transfer->setupPacket->wIndex = 0; - transfer->setupPacket->wLength = 0; - transfer->setupPacket->wValue = 0; + transfer->setupPacket->bmRequestType = 0x00U; + transfer->setupPacket->wIndex = 0U; + transfer->setupPacket->wLength = 0U; + transfer->setupPacket->wValue = 0U; } - switch (deviceInstance->state) + switch (state) { case kStatus_DEV_GetDes8: case kStatus_DEV_GetDes: /* get descriptor state */ getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t); - if (deviceInstance->state == kStatus_DEV_GetDes8) + if (deviceInstance->state == (uint8_t)kStatus_DEV_GetDes8) { - getDescriptorParam.descriptorLength = 8; + getDescriptorParam.descriptorLength = 8U; } getDescriptorParam.descriptorBuffer = (uint8_t *)deviceInstance->deviceDescriptor; - getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE; - getDescriptorParam.descriptorIndex = 0; - getDescriptorParam.languageId = 0; + getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE; + getDescriptorParam.descriptorIndex = 0U; + getDescriptorParam.languageId = 0U; transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; @@ -359,10 +350,10 @@ static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInsta case kStatus_DEV_GetCfg9: /* get 9 bytes configuration state */ getDescriptorParam.descriptorBuffer = deviceInstance->enumBuffer; - getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE; - getDescriptorParam.descriptorIndex = deviceInstance->configurationValue; + getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE; + getDescriptorParam.descriptorIndex = deviceInstance->configurationValue; getDescriptorParam.descriptorLength = 9; - getDescriptorParam.languageId = 0; + getDescriptorParam.languageId = 0; transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; @@ -371,10 +362,10 @@ static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInsta case kStatus_DEV_GetCfg: /* get configuration state */ getDescriptorParam.descriptorBuffer = deviceInstance->configurationDesc; - getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE; - getDescriptorParam.descriptorIndex = deviceInstance->configurationValue; + getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE; + getDescriptorParam.descriptorIndex = deviceInstance->configurationValue; getDescriptorParam.descriptorLength = deviceInstance->configurationLen; - getDescriptorParam.languageId = 0; + getDescriptorParam.languageId = 0; transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; @@ -385,52 +376,71 @@ static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInsta transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(deviceInstance->configuration.configurationDesc->bConfigurationValue); transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_SET_CONFIGURATION; - status = USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); + status = USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); break; case kStatus_DEV_EnumDone: /* enumeration done state */ - status = USB_HostNotifyDevice(deviceInstance, - kUSB_HostEventEnumerationDone); /* notify device enumeration done */ + /* notify device enumeration done */ + status = USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance, + (uint32_t)kUSB_HostEventEnumerationDone, (uint32_t)kStatus_USB_Success); if (status == kStatus_USB_Success) { - deviceInstance->state = kStatus_DEV_AppUsed; + deviceInstance->state = (uint8_t)kStatus_DEV_AppUsed; } break; default: + /*no action*/ break; } return status; } -static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance) +static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance, uint32_t dataLength) { usb_host_pipe_t *pipe = (usb_host_pipe_t *)deviceInstance->controlPipe; - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_descriptor_configuration_t *configureDesc; usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle; + void *temp; + usb_host_device_enumeration_status_t state; - switch (deviceInstance->state) + state = (usb_host_device_enumeration_status_t)deviceInstance->state; + switch (state) { case kStatus_DEV_GetDes8: /* process get 8 bytes descriptor result */ + if (dataLength != 8u) + { + return kStatus_USB_Error; + } pipe->maxPacketSize = deviceInstance->deviceDescriptor->bMaxPacketSize0; - hostInstance->controllerTable->controllerIoctl( + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + (void)hostInstance->controllerTable->controllerIoctl( hostInstance->controllerHandle, kUSB_HostUpdateControlPacketSize, deviceInstance->controlPipe); break; case kStatus_DEV_SetAddress: /* process set address result */ deviceInstance->setAddress = deviceInstance->allocatedAddress; - hostInstance->controllerTable->controllerIoctl( + /* the callbackFn is initialized in USB_HostGetControllerInterface */ + (void)hostInstance->controllerTable->controllerIoctl( hostInstance->controllerHandle, kUSB_HostUpdateControlEndpointAddress, deviceInstance->controlPipe); break; - case kStatus_DEV_GetDes: /* process set address result */ - /* NULL */ + case kStatus_DEV_GetDes: /* process get full device descriptor result */ + if (dataLength != sizeof(usb_descriptor_device_t)) + { + return kStatus_USB_Error; + } break; case kStatus_DEV_GetCfg9: /* process get 9 bytes configuration result */ - configureDesc = (usb_descriptor_configuration_t *)&deviceInstance->enumBuffer[0]; + if (dataLength != 9u) + { + return kStatus_USB_Error; + } + temp = (void *)&deviceInstance->enumBuffer[0]; + configureDesc = (usb_descriptor_configuration_t *)temp; deviceInstance->configurationLen = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(configureDesc->wTotalLength); if (deviceInstance->configurationDesc != NULL) @@ -438,19 +448,25 @@ static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceIn #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) SDK_Free(deviceInstance->configurationDesc); #else - USB_OsaMemoryFree(deviceInstance->configurationDesc); + OSA_MemoryFree(deviceInstance->configurationDesc); #endif deviceInstance->configurationDesc = NULL; } + + /* fix misra 4.14 */ + if (deviceInstance->configurationLen > USB_HOST_CONFIG_MAX_CONFIGURATION_DESCRIPTOR_LENGTH) + { + return kStatus_USB_Error; + } /* for KHCI, the start address and the length should be 4 byte align */ - if ((deviceInstance->configurationLen & 0x03) != 0) + if ((deviceInstance->configurationLen & 0x03U) != 0U) { #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) deviceInstance->configurationDesc = - (uint8_t *)SDK_Malloc((deviceInstance->configurationLen & 0xFFFFFFFCu) + 4, USB_CACHE_LINESIZE); + (uint8_t *)SDK_Malloc((deviceInstance->configurationLen & 0xFFFCu) + 4, USB_CACHE_LINESIZE); #else deviceInstance->configurationDesc = - (uint8_t *)USB_OsaMemoryAllocate((deviceInstance->configurationLen & 0xFFFFFFFCu) + 4); + (uint8_t *)OSA_MemoryAllocate((((uint32_t)deviceInstance->configurationLen) & 0xFFFCU) + 4UL); #endif } else @@ -459,18 +475,22 @@ static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceIn deviceInstance->configurationDesc = (uint8_t *)SDK_Malloc(deviceInstance->configurationLen, USB_CACHE_LINESIZE); #else - deviceInstance->configurationDesc = (uint8_t *)USB_OsaMemoryAllocate(deviceInstance->configurationLen); + deviceInstance->configurationDesc = (uint8_t *)OSA_MemoryAllocate(deviceInstance->configurationLen); #endif } if (deviceInstance->configurationDesc == NULL) { - return kStatus_USB_Error; + return kStatus_USB_AllocFail; } break; - case kStatus_DEV_GetCfg: /* process get cofiguration result */ - if (((usb_descriptor_configuration_t *)deviceInstance->configurationDesc)->bMaxPower > - USB_HOST_CONFIG_MAX_POWER) + case kStatus_DEV_GetCfg: /* process get configuration result */ + if (dataLength != deviceInstance->configurationLen) + { + return kStatus_USB_Error; + } + temp = (void *)deviceInstance->configurationDesc; + if (((usb_descriptor_configuration_t *)temp)->bMaxPower > USB_HOST_CONFIG_MAX_POWER) { return kStatus_USB_Error; } @@ -481,7 +501,8 @@ static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceIn return kStatus_USB_Error; } - status = USB_HostNotifyDevice(deviceInstance, kUSB_HostEventAttach); + status = USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance, (uint32_t)kUSB_HostEventAttach, + (uint32_t)kStatus_USB_Success); if (status != kStatus_USB_Success) { @@ -492,8 +513,9 @@ static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceIn } else { - USB_HostNotifyDevice(deviceInstance, - kUSB_HostEventNotSupported); /* notify application device is not supported */ + /* notify application device is not supported */ + (void)USB_HostNotifyDevice(deviceInstance->hostHandle, deviceInstance, + (uint32_t)kUSB_HostEventNotSupported, (uint32_t)kStatus_USB_Success); return kStatus_USB_NotSupported; } } @@ -504,13 +526,17 @@ static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceIn break; default: + /*no action*/ break; } return status; } -static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInstance, uint32_t eventCode) +static usb_status_t USB_HostNotifyDevice(usb_host_handle hostHandle, + usb_host_device_instance_t *deviceInstance, + uint32_t eventCode, + uint32_t eventParameter) { usb_host_instance_t *hostInstance; usb_status_t status1 = kStatus_USB_Error; @@ -521,34 +547,37 @@ static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInsta uint8_t interfaceIndex; #endif /* USB_HOST_CONFIG_HUB */ + eventCode = (((uint32_t)eventParameter << 16U) | (uint32_t)eventCode); + hostInstance = (usb_host_instance_t *)hostHandle; if (deviceInstance == NULL) { + (void)hostInstance->deviceCallback(NULL, NULL, eventCode); return kStatus_USB_InvalidHandle; } - hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle; #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) - haveHub = 0; - haveNoHub = 0; - for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex) + haveHub = 0U; + haveNoHub = 0U; + for (interfaceIndex = 0U; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex) { if (((usb_descriptor_interface_t *)deviceInstance->configuration.interfaceList[interfaceIndex].interfaceDesc) ->bInterfaceClass == USB_HOST_HUB_CLASS_CODE) { - haveHub = 1; + haveHub = 1U; } else { - haveNoHub = 1; + haveNoHub = 1U; } } - if ((haveNoHub == 1) && (hostInstance->deviceCallback != NULL)) + if ((hostInstance->deviceCallback != NULL) && + ((haveNoHub == 1U) || (deviceInstance->configuration.interfaceCount == 0U))) { - status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, - eventCode); /* notify application event */ + /* call host callback function, function is initialized in USB_HostInit */ + status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, eventCode); } - if (haveHub) + if (0U != haveHub) { status2 = USB_HostHubDeviceEvent(hostInstance, deviceInstance, &deviceInstance->configuration, eventCode); /* notify hub event */ @@ -558,7 +587,7 @@ static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInsta { return kStatus_USB_Success; } - else if (eventCode == kUSB_HostEventAttach) /* attach event */ + else if (eventCode == (uint32_t)kUSB_HostEventAttach) /* attach event */ { status1 = kStatus_USB_NotSupported; } @@ -569,8 +598,8 @@ static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInsta #else if (hostInstance->deviceCallback != NULL) { - status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, - eventCode); /* call host callback function */ + /* call host callback function, function is initialized in USB_HostInit */ + status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration, eventCode); } #endif return status1; @@ -578,24 +607,24 @@ static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInsta static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance) { - uint8_t address = 0; + uint8_t address = 0U; uint8_t addressIndex; uint8_t addressBitIndex; - for (addressIndex = 0; addressIndex < 8; ++addressIndex) /* find the idle address postion byte */ + for (addressIndex = 0U; addressIndex < 8U; ++addressIndex) /* find the idle address position byte */ { - if (hostInstance->addressBitMap[addressIndex] != 0xFF) + if (hostInstance->addressBitMap[addressIndex] != 0xFFU) { break; } } - if (addressIndex < 8) + if (addressIndex < 8U) { - for (addressBitIndex = 0; addressBitIndex < 8; ++addressBitIndex) /* find the idle address position bit */ + for (addressBitIndex = 0U; addressBitIndex < 8U; ++addressBitIndex) /* find the idle address position bit */ { - if (!(hostInstance->addressBitMap[addressIndex] & (0x01u << addressBitIndex))) + if (0U == (hostInstance->addressBitMap[addressIndex] & (0x01U << addressBitIndex))) { - hostInstance->addressBitMap[addressIndex] |= (0x01u << addressBitIndex); /* set the allocated bit */ - address = addressIndex * 8 + addressBitIndex + 1; /* the address minimum is 1 */ + hostInstance->addressBitMap[addressIndex] |= (0x01U << addressBitIndex); /* set the allocated bit */ + address = addressIndex * 8U + addressBitIndex + 1U; /* the address minimum is 1 */ break; } } @@ -605,10 +634,10 @@ static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance) static void USB_HostReleaseDeviceAddress(usb_host_instance_t *hostInstance, uint8_t address) { - USB_HostLock(); - hostInstance->addressBitMap[(uint32_t)(address - 1) >> 3] &= - (~(0x01u << (((uint32_t)address - 1) & 0x07U))); /* reset the allocated bit */ - USB_HostUnlock(); + (void)USB_HostLock(); + hostInstance->addressBitMap[((uint32_t)address - 1U) >> 3U] &= + (~(0x01U << (((uint32_t)address - 1U) & 0x07U))); /* reset the allocated bit */ + (void)USB_HostUnlock(); } static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb_device_handle deviceHandle) @@ -640,7 +669,7 @@ static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb prevInstance->next = currentInstance->next; return kStatus_USB_Success; } - prevInstance = currentInstance; + prevInstance = currentInstance; currentInstance = currentInstance->next; } @@ -660,13 +689,13 @@ static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb } #endif /* release device's address */ - if (deviceInstance->setAddress != 0) + if (deviceInstance->setAddress != 0U) { USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->setAddress); } else { - if (deviceInstance->allocatedAddress != 0) + if (deviceInstance->allocatedAddress != 0U) { USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->allocatedAddress); } @@ -675,7 +704,7 @@ static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb /* close control pipe */ if (deviceInstance->controlPipe != NULL) { - USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL); + (void)USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL); if (USB_HostClosePipe(hostInstance, deviceInstance->controlPipe) != kStatus_USB_Success) { #ifdef HOST_ECHO @@ -691,7 +720,7 @@ static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) SDK_Free(deviceInstance->configurationDesc); #else - USB_OsaMemoryFree(deviceInstance->configurationDesc); + OSA_MemoryFree(deviceInstance->configurationDesc); #endif } @@ -701,20 +730,20 @@ static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) SDK_Free(deviceInstance->deviceDescriptor); #else - USB_OsaMemoryFree(deviceInstance->deviceDescriptor); + OSA_MemoryFree(deviceInstance->deviceDescriptor); #endif /* free device instance buffer */ - USB_OsaMemoryFree(deviceInstance); + OSA_MemoryFree(deviceInstance); #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) /* enable controller attach if root hub */ - if (level == 1) + if (level == 1U) { - USB_HostControlBus(hostInstance, kUSB_HostBusEnableAttach); + (void)USB_HostControlBus(hostInstance, (uint8_t)kUSB_HostBusEnableAttach); } #else /* enable controller attach */ - USB_HostControlBus(hostInstance, kUSB_HostBusEnableAttach); + USB_HostControlBus(hostInstance, (uint8_t)kUSB_HostBusEnableAttach); #endif } @@ -726,35 +755,39 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle usb_host_interface_t *interfaceParse = NULL; usb_host_ep_t *epParse; uint8_t *buffer; + void *temp; if (deviceHandle == NULL) { return kStatus_USB_InvalidParameter; } - buffer = (uint8_t *)&deviceInstance->configuration; + temp = (void *)&deviceInstance->configuration; + buffer = (uint8_t *)temp; /* clear the previous parse result, note: end_pos means buffer index here*/ - for (endPos = 0; endPos < sizeof(usb_host_configuration_t); endPos++) + for (endPos = 0U; endPos < sizeof(usb_host_configuration_t); endPos++) { - buffer[endPos] = 0; + buffer[endPos] = 0U; } - for (endPos = 0; endPos < USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE; ++endPos) + for (endPos = 0U; endPos < USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE; ++endPos) { - deviceInstance->interfaceStatus[endPos] = 0; + deviceInstance->interfaceStatus[endPos] = 0U; } /* parse configuration descriptor */ - unionDes = (usb_descriptor_union_t *)deviceInstance->configurationDesc; - endPos = (uint32_t)(deviceInstance->configurationDesc + deviceInstance->configurationLen); + temp = (void *)deviceInstance->configurationDesc; + unionDes = (usb_descriptor_union_t *)temp; + endPos = (uint32_t)(deviceInstance->configurationDesc + deviceInstance->configurationLen); if ((unionDes->common.bLength == USB_DESCRIPTOR_LENGTH_CONFIGURE) && (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_CONFIGURE)) { /* configuration descriptor */ - deviceInstance->configuration.configurationDesc = (usb_descriptor_configuration_t *)unionDes; + temp = (void *)unionDes; + deviceInstance->configuration.configurationDesc = (usb_descriptor_configuration_t *)temp; deviceInstance->configuration.configurationExtensionLength = 0; - deviceInstance->configuration.configurationExtension = NULL; - deviceInstance->configuration.interfaceCount = 0; + deviceInstance->configuration.configurationExtension = NULL; + deviceInstance->configuration.interfaceCount = 0; unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength); while ((uint32_t)unionDes < endPos) { @@ -764,8 +797,8 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle { deviceInstance->configuration.configurationExtension = (uint8_t *)unionDes; } - if ((unionDes->common.bDescriptorType == 0x00) || - (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */ + if ((unionDes->common.bDescriptorType == 0x00U) || + (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -779,17 +812,17 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle } /* interface descriptor */ - deviceInstance->configuration.interfaceCount = 0; + deviceInstance->configuration.interfaceCount = 0U; while ((uint32_t)unionDes < endPos) { if (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE) { - if (unionDes->interface.bAlternateSetting == 0x00) + if (unionDes->interface.bAlternateSetting == 0x00U) { if (deviceInstance->configuration.interfaceCount >= USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE) { -#ifdef HOST_ECHO - usb_echo( +#if (((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) || defined(HOST_ECHO)) + (void)usb_echo( "Unsupported Device attached\r\n too many interfaces in one configuration, please increase " "the USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE value\n"); #endif @@ -798,13 +831,13 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle interfaceParse = &deviceInstance->configuration.interfaceList[deviceInstance->configuration.interfaceCount]; deviceInstance->configuration.interfaceCount++; - interfaceParse->alternateSettingNumber = 0; - interfaceParse->epCount = 0; - interfaceParse->interfaceDesc = &unionDes->interface; + interfaceParse->alternateSettingNumber = 0; + interfaceParse->epCount = 0; + interfaceParse->interfaceDesc = &unionDes->interface; interfaceParse->interfaceExtensionLength = 0; - interfaceParse->interfaceExtension = NULL; - interfaceParse->interfaceIndex = unionDes->interface.bInterfaceNumber; - if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */ + interfaceParse->interfaceExtension = NULL; + interfaceParse->interfaceIndex = unionDes->interface.bInterfaceNumber; + if (unionDes->common.bLength == 0x00U) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -818,8 +851,8 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle { interfaceParse->interfaceExtension = (uint8_t *)unionDes; } - if ((unionDes->common.bDescriptorType == 0x00) || - (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */ + if ((unionDes->common.bDescriptorType == 0x00U) || + (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -833,7 +866,7 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle } /* endpoint descriptor */ - if (interfaceParse->interfaceDesc->bNumEndpoints != 0) + if (interfaceParse->interfaceDesc->bNumEndpoints != 0U) { if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) || (interfaceParse->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP)) @@ -854,11 +887,13 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle #endif return kStatus_USB_Error; } - epParse = (usb_host_ep_t *)&interfaceParse->epList[interfaceParse->epCount]; - epParse->epDesc = (usb_descriptor_endpoint_t *)unionDes; - epParse->epExtensionLength = 0; - epParse->epExtension = NULL; - if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */ + temp = (void *)&interfaceParse->epList[interfaceParse->epCount]; + epParse = (usb_host_ep_t *)temp; + temp = (void *)unionDes; + epParse->epDesc = (usb_descriptor_endpoint_t *)temp; + epParse->epExtensionLength = 0U; + epParse->epExtension = NULL; + if (unionDes->common.bLength == 0x00U) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -872,8 +907,8 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle { epParse->epExtension = (uint8_t *)unionDes; } - if ((unionDes->common.bDescriptorType == 0x00) || - (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */ + if ((unionDes->common.bDescriptorType == 0x00U) || + (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -900,7 +935,7 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle { interfaceParse->interfaceExtension = (uint8_t *)unionDes; } - if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */ + if (unionDes->common.bLength == 0x00U) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -910,8 +945,8 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle { if (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE) { - if ((unionDes->common.bDescriptorType == 0x00) || - (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */ + if ((unionDes->common.bDescriptorType == 0x00U) || + (unionDes->common.bLength == 0x00U)) /* the descriptor data is wrong */ { return kStatus_USB_Error; } @@ -932,9 +967,9 @@ static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle } } - for (endPos = 0; endPos < deviceInstance->configuration.interfaceCount; ++endPos) + for (endPos = 0U; endPos < deviceInstance->configuration.interfaceCount; ++endPos) { - deviceInstance->interfaceStatus[endPos] = kStatus_interface_Attached; + deviceInstance->interfaceStatus[endPos] = (uint8_t)kStatus_interface_Attached; } return kStatus_USB_Success; @@ -988,28 +1023,29 @@ usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle, #endif /* Allocate new device instance */ - newInstance = (usb_host_device_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_device_instance_t)); + newInstance = (usb_host_device_instance_t *)OSA_MemoryAllocate(sizeof(usb_host_device_instance_t)); if (newInstance == NULL) { #ifdef HOST_ECHO usb_echo("allocate dev instance fail\r\n"); #endif + (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail, + (uint32_t)kStatus_USB_AllocFail); return kStatus_USB_AllocFail; } /* new instance fields init */ - newInstance->hostHandle = hostHandle; - newInstance->speed = speed; - newInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES; - newInstance->enumRetries = USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES; - newInstance->setAddress = 0; - newInstance->deviceAttachState = kStatus_device_Attached; + newInstance->hostHandle = hostHandle; + newInstance->speed = speed; + newInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES; + newInstance->enumRetries = USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES; + newInstance->setAddress = 0; + newInstance->deviceAttachState = (uint8_t)kStatus_device_Attached; #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) newInstance->deviceDescriptor = (usb_descriptor_device_t *)SDK_Malloc(sizeof(usb_descriptor_device_t) + 9, USB_CACHE_LINESIZE); #else - newInstance->deviceDescriptor = - (usb_descriptor_device_t *)USB_OsaMemoryAllocate(sizeof(usb_descriptor_device_t) + 9); + newInstance->deviceDescriptor = (usb_descriptor_device_t *)OSA_MemoryAllocate(sizeof(usb_descriptor_device_t) + 9U); #endif if (newInstance->deviceDescriptor == NULL) { @@ -1019,62 +1055,66 @@ usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle, #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) SDK_Free(newInstance->deviceDescriptor); #else - USB_OsaMemoryFree(newInstance->deviceDescriptor); + OSA_MemoryFree(newInstance->deviceDescriptor); #endif - USB_OsaMemoryFree(newInstance); + OSA_MemoryFree(newInstance); + (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail, + (uint32_t)kStatus_USB_AllocFail); return kStatus_USB_AllocFail; } newInstance->enumBuffer = (uint8_t *)((uint8_t *)newInstance->deviceDescriptor + sizeof(usb_descriptor_device_t)); #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) - newInstance->hubNumber = hubNumber; + newInstance->hubNumber = hubNumber; newInstance->portNumber = portNumber; - newInstance->level = level; + newInstance->level = level; - if ((speed != USB_SPEED_HIGH) && (level > 1)) + if ((speed != USB_SPEED_HIGH) && (level > 1U)) { - newInstance->hsHubNumber = USB_HostHubGetHsHubNumber(hostHandle, hubNumber); - newInstance->hsHubPort = USB_HostHubGetHsHubPort(hostHandle, hubNumber, portNumber); + newInstance->hsHubNumber = (uint8_t)USB_HostHubGetHsHubNumber(hostHandle, hubNumber); + newInstance->hsHubPort = (uint8_t)USB_HostHubGetHsHubPort(hostHandle, hubNumber, portNumber); } else { newInstance->hsHubNumber = hubNumber; - newInstance->hsHubPort = portNumber; + newInstance->hsHubPort = portNumber; } #endif /* USB_HOST_CONFIG_HUB */ - USB_HostLock(); + (void)USB_HostLock(); /* allocate address && insert to the dev list */ address = USB_HostAllocateDeviceAddress(hostInstance); - if (address == 0) + if (address == 0U) { #ifdef HOST_ECHO usb_echo("allocate address fail\r\n"); #endif - USB_HostUnlock(); + (void)USB_HostUnlock(); #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) SDK_Free(newInstance->deviceDescriptor); #else - USB_OsaMemoryFree(newInstance->deviceDescriptor); + OSA_MemoryFree(newInstance->deviceDescriptor); #endif - USB_OsaMemoryFree(newInstance); + OSA_MemoryFree(newInstance); + (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail, + (uint32_t)kStatus_USB_Error); return kStatus_USB_Error; } newInstance->allocatedAddress = address; - newInstance->next = (usb_host_device_instance_t *)hostInstance->deviceList; + newInstance->next = (usb_host_device_instance_t *)hostInstance->deviceList; hostInstance->deviceList = newInstance; - newInstance->state = kStatus_DEV_Initial; - USB_HostUnlock(); + newInstance->state = (uint8_t)kStatus_DEV_Initial; + (void)USB_HostUnlock(); /* open control pipe */ - pipeInit.devInstance = newInstance; - pipeInit.pipeType = USB_ENDPOINT_CONTROL; - pipeInit.direction = 0; + pipeInit.devInstance = newInstance; + pipeInit.pipeType = USB_ENDPOINT_CONTROL; + pipeInit.direction = 0; pipeInit.endpointAddress = 0; - pipeInit.interval = 0; - pipeInit.maxPacketSize = 8; + pipeInit.interval = 0; + pipeInit.maxPacketSize = 8; pipeInit.numberPerUframe = 0; - pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; + pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; if (USB_HostOpenPipe(hostHandle, &newInstance->controlPipe, &pipeInit) != kStatus_USB_Success) { /* don't need release resource, resource is released when detach */ @@ -1082,15 +1122,22 @@ usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle, #if ((defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) SDK_Free(newInstance->deviceDescriptor); #else - USB_OsaMemoryFree(newInstance->deviceDescriptor); + OSA_MemoryFree(newInstance->deviceDescriptor); #endif - USB_OsaMemoryFree(newInstance); + OSA_MemoryFree(newInstance); + (void)USB_HostNotifyDevice(hostInstance, NULL, (uint32_t)kUSB_HostEventEnumerationFail, + (uint32_t)kStatus_USB_Error); return kStatus_USB_Error; } /* start enumeration */ - newInstance->state = kStatus_DEV_GetDes8; - USB_HostProcessState(newInstance); /* process enumeration state machine */ + newInstance->state = (uint8_t)kStatus_DEV_GetDes8; + /* process enumeration state machine */ + if (USB_HostProcessState(newInstance) != kStatus_USB_Success) + { + (void)USB_HostNotifyDevice(hostInstance, newInstance, (uint32_t)kUSB_HostEventEnumerationFail, + (uint32_t)kStatus_USB_Error); + } *deviceHandle = newInstance; return kStatus_USB_Success; @@ -1106,7 +1153,7 @@ usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, return kStatus_USB_InvalidHandle; } - USB_HostLock(); + (void)USB_HostLock(); /* search for device instance handle */ #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList; @@ -1121,7 +1168,7 @@ usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, #else deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList; #endif - USB_HostUnlock(); + (void)USB_HostUnlock(); if (deviceInstance != NULL) { return USB_HostDetachDeviceInternal(hostHandle, deviceInstance); /* device instance detach */ @@ -1132,31 +1179,33 @@ usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle) { usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; - usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; + usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if ((hostHandle == NULL) || (deviceHandle == NULL)) { return kStatus_USB_InvalidHandle; } - deviceInstance->deviceAttachState = kStatus_device_Detached; /* mark the device is detached from host */ + deviceInstance->deviceAttachState = (uint8_t)kStatus_device_Detached; /* mark the device is detached from host */ - if (deviceInstance->state >= kStatus_DEV_Initial) /* device instance is valid */ + if (deviceInstance->state >= (uint8_t)kStatus_DEV_Initial) /* device instance is valid */ { /* detach internally */ - if (deviceInstance->state < kStatus_DEV_AppUsed) /* enumeration is not done */ + if (deviceInstance->state < (uint8_t)kStatus_DEV_AppUsed) /* enumeration is not done */ { if (deviceInstance->controlPipe != NULL) { - USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL); + (void)USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL); } /* remove device instance from host */ - USB_HostRemoveDeviceInstance(hostInstance, deviceInstance); + (void)USB_HostRemoveDeviceInstance(hostInstance, deviceInstance); USB_HostReleaseDeviceResource(hostInstance, deviceInstance); } - else /* enumeration has be done and notifed application */ + else /* enumeration has be done and notified application */ { - USB_HostNotifyDevice(deviceInstance, kUSB_HostEventDetach); /* notify application device detach */ + /* notify application device detach */ + (void)USB_HostNotifyDevice(hostInstance, deviceInstance, (uint32_t)kUSB_HostEventDetach, + (uint32_t)kStatus_USB_Success); } } @@ -1165,7 +1214,7 @@ usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle) { - return deviceHandle ? ((usb_host_device_instance_t *)deviceHandle)->deviceAttachState : 0x0; + return (NULL != deviceHandle) ? ((usb_host_device_instance_t *)deviceHandle)->deviceAttachState : 0x0U; } usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle) @@ -1183,7 +1232,7 @@ usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handl searchDev = searchDev->next; } - if (searchDev) + if (NULL != searchDev) { return kStatus_USB_Success; } @@ -1192,14 +1241,14 @@ usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handl static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if (hostHandle == NULL) { return kStatus_USB_InvalidHandle; } - + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &controlType); @@ -1209,7 +1258,7 @@ static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t contr usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle) { usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; - usb_host_instance_t *hostInstance = NULL; + usb_host_instance_t *hostInstance = NULL; uint8_t interfaceIndex; uint8_t index = 0; @@ -1219,11 +1268,11 @@ usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_hos } hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle; - USB_HostLock(); + (void)USB_HostLock(); /* check host_instance valid? */ for (; index < USB_HOST_CONFIG_MAX_HOST; ++index) { - if ((g_UsbHostInstance[index].occupied == 1) && + if ((g_UsbHostInstance[index].occupied == 1U) && ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance))) { break; @@ -1231,14 +1280,14 @@ usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_hos } if (index >= USB_HOST_CONFIG_MAX_HOST) { - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Error; } /* check deviceHandle valid? */ if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success) { - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Error; } @@ -1247,11 +1296,11 @@ usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_hos { if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle) { - deviceInstance->interfaceStatus[interfaceIndex] = kStatus_interface_Opened; + deviceInstance->interfaceStatus[interfaceIndex] = (uint8_t)kStatus_interface_Opened; break; } } - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Success; } @@ -1259,10 +1308,10 @@ usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_hos usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle) { usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; - usb_host_instance_t *hostInstance = NULL; + usb_host_instance_t *hostInstance = NULL; uint8_t interfaceIndex; uint8_t removeLabel = 1; - uint8_t index = 0; + uint8_t index = 0; if (deviceHandle == NULL) { @@ -1270,11 +1319,11 @@ usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_ho } hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle; - USB_HostLock(); + (void)USB_HostLock(); /* check host_instance valid? */ for (; index < USB_HOST_CONFIG_MAX_HOST; ++index) { - if ((g_UsbHostInstance[index].occupied == 1) && + if ((g_UsbHostInstance[index].occupied == 1U) && ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance))) { break; @@ -1282,14 +1331,14 @@ usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_ho } if (index >= USB_HOST_CONFIG_MAX_HOST) { - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Error; } /* check deviceHandle valid? */ if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success) { - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Error; } @@ -1300,32 +1349,32 @@ usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_ho { if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle) { - deviceInstance->interfaceStatus[interfaceIndex] = kStatus_interface_Detached; + deviceInstance->interfaceStatus[interfaceIndex] = (uint8_t)kStatus_interface_Detached; break; } } } - if (deviceInstance->deviceAttachState == kStatus_device_Detached) /* device is removed from host */ + if (deviceInstance->deviceAttachState == (uint8_t)kStatus_device_Detached) /* device is removed from host */ { removeLabel = 1; /* check all the interfaces of the device are not opened */ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex) { - if (deviceInstance->interfaceStatus[interfaceIndex] == kStatus_interface_Opened) + if (deviceInstance->interfaceStatus[interfaceIndex] == (uint8_t)kStatus_interface_Opened) { - removeLabel = 0; + removeLabel = 0U; break; } } - if (removeLabel == 1) + if (removeLabel == 1U) { /* remove device instance from host */ - USB_HostRemoveDeviceInstance(hostInstance, deviceInstance); + (void)USB_HostRemoveDeviceInstance(hostInstance, deviceInstance); } - USB_HostUnlock(); + (void)USB_HostUnlock(); - if (removeLabel == 1) + if (removeLabel == 1U) { USB_HostReleaseDeviceResource((usb_host_instance_t *)deviceInstance->hostHandle, deviceInstance); /* release device resource */ @@ -1333,7 +1382,7 @@ usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_ho } else { - USB_HostUnlock(); + (void)USB_HostUnlock(); } return kStatus_USB_Success; @@ -1341,9 +1390,9 @@ usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_ho usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle) { - usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; + usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; - uint8_t interfaceIndex = 0; + uint8_t interfaceIndex = 0; #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) uint8_t level = 0; uint8_t devHubNo; @@ -1362,25 +1411,26 @@ usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle if (USB_HostValidateDevice(hostInstance, deviceInstance) == kStatus_USB_Success) /* device is valid */ { #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) - devHubNo = deviceInstance->hubNumber; + devHubNo = deviceInstance->hubNumber; devPortNo = deviceInstance->portNumber; - level = deviceInstance->level; + level = deviceInstance->level; #endif - deviceInstance->deviceAttachState = kStatus_device_Detached; - if (deviceInstance->state >= kStatus_DEV_Initial) /* device is valid */ + deviceInstance->deviceAttachState = (uint8_t)kStatus_device_Detached; + if (deviceInstance->state >= (uint8_t)kStatus_DEV_Initial) /* device is valid */ { - if (deviceInstance->state < kStatus_DEV_AppUsed) /* enumeraion is not done or application don't use */ + if (deviceInstance->state < + (uint8_t)kStatus_DEV_AppUsed) /* enumeration is not done or application don't use */ { /* detach internally */ - USB_HostDetachDeviceInternal(hostHandle, deviceHandle); + (void)USB_HostDetachDeviceInternal(hostHandle, deviceHandle); } else /* application use the device */ { - for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; + for (interfaceIndex = 0U; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex) { - if (deviceInstance->interfaceStatus[interfaceIndex] == kStatus_interface_Opened) + if (deviceInstance->interfaceStatus[interfaceIndex] == (uint8_t)kStatus_interface_Opened) { #ifdef HOST_ECHO usb_echo("error: there is class instance that is not deinited\r\n"); @@ -1389,20 +1439,20 @@ usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle } } /* remove device instance from host */ - USB_HostRemoveDeviceInstance(hostInstance, deviceInstance); + (void)USB_HostRemoveDeviceInstance(hostInstance, deviceInstance); USB_HostReleaseDeviceResource(hostInstance, deviceInstance); /* release resource */ } } #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) - if (level == 1) + if (level == 1U) { - USB_HostControlBus(hostHandle, kUSB_HostBusReset); /* reset controller port */ - USB_HostControlBus(hostHandle, kUSB_HostBusRestart); /* restart controller port */ + (void)USB_HostControlBus(hostHandle, (uint8_t)kUSB_HostBusReset); /* reset controller port */ + (void)USB_HostControlBus(hostHandle, (uint8_t)kUSB_HostBusRestart); /* restart controller port */ } else { - USB_HostHubRemovePort(hostHandle, devHubNo, devPortNo); /* reset hub port */ + (void)USB_HostHubRemovePort(hostHandle, devHubNo, devPortNo); /* reset hub port */ } #else USB_HostControlBus(hostHandle, kUSB_HostBusReset); /* reset controller port */ @@ -1411,4 +1461,4 @@ usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle } return kStatus_USB_Success; -} +} \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.h index 422e876a12..5612603cb0 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.h +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_devices.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _USB_HOST_DEV_MNG_H_ @@ -79,11 +57,11 @@ typedef struct _usb_host_device_instance usb_descriptor_device_t *deviceDescriptor; /*!< Standard device descriptor */ usb_host_pipe_handle controlPipe; /*!< Device's control pipe */ uint8_t *configurationDesc; /*!< Configuration descriptor pointer */ + uint8_t *enumBuffer; /*!< Buffer for enumeration */ uint16_t configurationLen; /*!< Configuration descriptor length */ - uint16_t configurationValue; /*!< Configuration index */ uint8_t interfaceStatus[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interfaces' status, please reference to #usb_host_interface_state_t */ - uint8_t *enumBuffer; /*!< Buffer for enumeration */ + uint8_t configurationValue; /*!< Configuration index */ uint8_t state; /*!< Device state for enumeration */ uint8_t enumRetries; /*!< Re-enumeration when error in control transfer */ uint8_t stallRetries; /*!< Re-transfer when stall */ @@ -104,11 +82,10 @@ typedef struct _usb_host_device_instance typedef struct _usb_host_enum_process_entry { - uint8_t successState; /*!< When the last step is successful, the next state value */ - uint8_t retryState; /*!< When the last step need retry, the next state value */ - usb_status_t (*process)(usb_host_device_instance_t *deviceInstance); /*!< When the last step transfer is done, the - function is used to process the transfer - data */ + usb_host_device_enumeration_status_t successState; /*!< When the last step is successful, the next state value */ + usb_host_device_enumeration_status_t retryState; /*!< When the last step need retry, the next state value */ + /*! When the last step transfer is done, the function is used to process the transfer data */ + usb_status_t (*process)(usb_host_device_instance_t *deviceInstance, uint32_t dataLength); } usb_host_enum_process_entry_t; /******************************************************************************* @@ -175,4 +152,4 @@ extern uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle); extern usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle); /*! @}*/ -#endif /* _USB_HOST_DEV_MNG_H_ */ +#endif /* _USB_HOST_DEV_MNG_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c index 8a31514b3a..9382aad979 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.c @@ -1,41 +1,22 @@ /* * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016,2019 - 2020 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include +#include #if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI > 0U)) #include "usb_host.h" #include "usb_host_hci.h" #include "usb_host_devices.h" +#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) +#include "usb_host_framework.h" +#endif #include "fsl_device_registers.h" #include "usb_host_ehci.h" -#include "usb_phy.h" +#include #if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) #include "usb_host.h" #endif @@ -50,16 +31,16 @@ #endif -#define USB_HOST_EHCI_BANDWIDTH_DELAY (3500U) -#define USB_HOST_EHCI_BANDWIDTH_HUB_LS_SETUP (333U) +#define USB_HOST_EHCI_BANDWIDTH_DELAY (3500U) +#define USB_HOST_EHCI_BANDWIDTH_HUB_LS_SETUP (333U) #define USB_HOST_EHCI_BANDWIDTH_FRAME_TOTOAL_TIME (900U) #if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) -#define USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH (18U) -#define USB_HOST_EHCI_PORTSC_PTC_J_STATE (0x01U) -#define USB_HOST_EHCI_PORTSC_PTC_K_STATE (0x02U) -#define USB_HOST_EHCI_PORTSC_PTC_SE0_NAK (0x03U) -#define USB_HOST_EHCI_PORTSC_PTC_PACKET (0x04U) +#define USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH (18U) +#define USB_HOST_EHCI_PORTSC_PTC_J_STATE (0x01U) +#define USB_HOST_EHCI_PORTSC_PTC_K_STATE (0x02U) +#define USB_HOST_EHCI_PORTSC_PTC_SE0_NAK (0x03U) +#define USB_HOST_EHCI_PORTSC_PTC_PACKET (0x04U) #define USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_HS (0x05U) #define USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_FS (0x06U) #define USB_HOST_EHCI_PORTSC_PTC_FORCE_ENABLE_LS (0x07U) @@ -102,7 +83,7 @@ static void USB_HostBandwidthFslsHostComputeCurrent(usb_host_ehci_instance_t *eh static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t *ehciInstance, uint32_t hubNumber, uint16_t frameIndex, - uint8_t frameBandwidths[8]); + uint16_t frameBandwidths[8]); /*! * @brief compute current allocated HS bandwidth when ehci work as hi-speed host. @@ -113,7 +94,7 @@ static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t * */ static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t *ehciInstance, uint16_t frameIndex, - uint8_t frameBandwidths[8]); + uint16_t frameBandwidths[8]); /*! * @brief allocate HS bandwidth when host work as high-speed host. @@ -175,13 +156,6 @@ static void USB_HostEhciZeroMem(uint32_t *buffer, uint32_t length); */ static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms); -/*! - * @brief host ehci start async schedule. - * - * @param ehciInstance ehci instance pointer. - */ -static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance); - /*! * @brief host ehci stop async schedule. * @@ -189,13 +163,6 @@ static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance); */ static void USB_HostEhciStopAsync(usb_host_ehci_instance_t *ehciInstance); -/*! - * @brief host ehci start periodic schedule. - * - * @param ehciInstance ehci instance pointer. - */ -static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance); - /*! * @brief host ehci stop periodic schedule. * @@ -515,16 +482,6 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc usb_host_ehci_pipe_t *ehciPipePointer, usb_host_transfer_t *transfer); -/*! - * @brief control ehci bus. - * - * @param ehciInstance ehci instance pointer. - * @param bus_control control code. - * - * @return kStatus_USB_Success or error codes. - */ -static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl); - /*! * @brief ehci transaction done process function. * @@ -532,20 +489,7 @@ static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstanc */ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance); -/*! - * @brief ehci port change interrupt process function. - * - * @param ehciInstance ehci instance pointer. - */ -static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance); -/*! - * @brief ehci timer0 interrupt process function. - * cancel control/bulk transfer that time out. - * - * @param ehciInstance ehci instance pointer. - */ -static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance); #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) /*! @@ -586,71 +530,60 @@ extern usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t USB_RAM_ADDRESS_ALIGNMENT(4096) USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList1[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4]; -#define USB_HOST_EHCI_FRAME_LIST_ARRAY \ - { \ - &s_UsbHostEhciFrameList1[0] \ - } +static uint8_t usbHostEhciFramListStatus[1] = {0}; USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData1; -#define USB_HOST_EHCI_DATA_ARRAY \ - { \ - &s_UsbHostEhciData1 \ - } -#elif(USB_HOST_CONFIG_EHCI == 2U) +#elif (USB_HOST_CONFIG_EHCI == 2U) USB_RAM_ADDRESS_ALIGNMENT(4096) USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList1[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4]; USB_RAM_ADDRESS_ALIGNMENT(4096) USB_CONTROLLER_DATA static uint8_t s_UsbHostEhciFrameList2[USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 4]; -#define USB_HOST_EHCI_FRAME_LIST_ARRAY \ - { \ - &s_UsbHostEhciFrameList1[0], &s_UsbHostEhciFrameList2[0] \ - } +static uint8_t usbHostEhciFramListStatus[2] = {0, 0}; USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData1; USB_RAM_ADDRESS_ALIGNMENT(64) USB_CONTROLLER_DATA static usb_host_ehci_data_t s_UsbHostEhciData2; -#define USB_HOST_EHCI_DATA_ARRAY \ - { \ - &s_UsbHostEhciData1, &s_UsbHostEhciData2 \ - } #else #error "Please increase the instance count." #endif +#define USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE (1024U) +#define USB_HOST_EHCI_MAX_MICRFRAME_VALUE ((USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE << 3U) - 1U) -static uint8_t s_SlotMaxBandwidth[8] = {125, 125, 125, 125, 125, 125, 50, 0}; +static uint8_t s_SlotMaxBandwidth[8] = {125, 125, 125, 125, 125, 125, 50, 0}; +static uint8_t s_SlotMaxBandwidthHs[8] = {100, 100, 100, 100, 100, 100, 100, 100}; /******************************************************************************* * Code ******************************************************************************/ /*! -* @brief EHCI NC get USB NC bass address. -* -* This function is used to get USB NC bass address. -* -* @param[in] controllerId EHCI controller ID; See the #usb_controller_index_t. -* -* @retval USB NC bass address. -*/ + * @brief EHCI NC get USB NC bass address. + * + * This function is used to get USB NC bass address. + * + * @param[in] controllerId EHCI controller ID; See the #usb_controller_index_t. + * + * @retval USB NC bass address. + */ #if (defined(USB_HOST_CONFIG_LOW_POWER_MODE) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) #if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U)) -void *USB_EhciNCGetBase(uint8_t controllerId) +static void *USB_EhciNCGetBase(uint8_t controllerId) { void *usbNCBase = NULL; #if ((defined FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U)) uint32_t instance; - uint32_t newinstance = 0; + uint32_t newinstance = 0; uint32_t usbnc_base_temp[] = USBNC_BASE_ADDRS; - uint32_t usbnc_base[] = USBNC_BASE_ADDRS; + uint32_t usbnc_base[] = USBNC_BASE_ADDRS; - if (controllerId < kUSB_ControllerEhci0) + if (controllerId < (uint8_t)kUSB_ControllerEhci0) { return NULL; } - controllerId = controllerId - kUSB_ControllerEhci0; + controllerId = controllerId - (uint8_t)kUSB_ControllerEhci0; for (instance = 0; instance < (sizeof(usbnc_base_temp) / sizeof(usbnc_base_temp[0])); instance++) { - if (usbnc_base_temp[instance]) + if (usbnc_base_temp[instance] != 0U) { usbnc_base[newinstance++] = usbnc_base_temp[instance]; } @@ -660,7 +593,7 @@ void *USB_EhciNCGetBase(uint8_t controllerId) return NULL; } - usbNCBase = (void *)usbnc_base[controllerId]; + usbNCBase = (void *)(uint8_t *)usbnc_base[controllerId]; #endif return usbNCBase; } @@ -729,19 +662,19 @@ static void USB_HostEhciTestSingleStepGetDeviceDesc(usb_host_ehci_instance_t *eh return; } - getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t); - getDescriptorParam.descriptorLength = 18; - getDescriptorParam.descriptorBuffer = (uint8_t *)&deviceInstance->deviceDescriptor; - getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE; - getDescriptorParam.descriptorIndex = 0; - getDescriptorParam.languageId = 0; - transfer->callbackFn = USB_HostEhciTestCallback; - transfer->callbackParam = ehciInstance->hostHandle; + getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t); + getDescriptorParam.descriptorLength = 18; + getDescriptorParam.descriptorBuffer = (uint8_t *)&deviceInstance->deviceDescriptor; + getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE; + getDescriptorParam.descriptorIndex = 0; + getDescriptorParam.languageId = 0; + transfer->callbackFn = USB_HostEhciTestCallback; + transfer->callbackParam = ehciInstance->hostHandle; transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN; - transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; - transfer->setupPacket->wIndex = 0; - transfer->setupPacket->wLength = 0; - transfer->setupPacket->wValue = 0; + transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; + transfer->setupPacket->wIndex = 0; + transfer->setupPacket->wLength = 0; + transfer->setupPacket->wValue = 0; USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam); } @@ -774,8 +707,8 @@ static usb_status_t USB_HostEhciSingleStepQtdListInit(usb_host_ehci_instance_t * { qtdPointer->nextQtdPointer = (uint32_t)ehciInstance->ehciQtdHead; } - qtdPointer = ehciInstance->ehciQtdHead; - ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer; + qtdPointer = ehciInstance->ehciQtdHead; + ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer; qtdPointer->nextQtdPointer = 0; } while (--qtdNumber); } @@ -795,7 +728,7 @@ static usb_status_t USB_HostEhciSingleStepQtdListInit(usb_host_ehci_instance_t * qtdPointer->transferResults[0] = ((0x00000000 << EHCI_HOST_QTD_DT_SHIFT) | (8 << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) | (EHCI_HOST_PID_SETUP << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK)); - dataAddress = (uint32_t)(transfer->setupPacket); + dataAddress = (uint32_t)(transfer->setupPacket); qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */ /* set buffer pointer no matter data length */ for (index = 0; index < 4; ++index) @@ -816,7 +749,7 @@ static usb_status_t USB_HostEhciSingleStepQtdListInit(usb_host_ehci_instance_t * ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (dataLength << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) | (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK)); - dataAddress = (uint32_t)(transfer->transferBuffer); + dataAddress = (uint32_t)(transfer->transferBuffer); qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */ /* set buffer pointer no matter data length */ for (index = 0; index < 4; ++index) @@ -848,24 +781,24 @@ static usb_status_t USB_HostEhciSingleStepQtdListInit(usb_host_ehci_instance_t * transfer->next = NULL; if (vltQhPointer->ehciTransferHead == NULL) { - transfer->next = NULL; + transfer->next = NULL; vltQhPointer->ehciTransferHead = vltQhPointer->ehciTransferTail = transfer; } else { - transfer->next = NULL; + transfer->next = NULL; vltQhPointer->ehciTransferTail->next = transfer; - vltQhPointer->ehciTransferTail = transfer; + vltQhPointer->ehciTransferTail = transfer; } USB_HostEhciLock(); /* link qtd to qh (link to end) */ entryPointer = &(vltQhPointer->nextQtdPointer); - dataAddress = *entryPointer; /* dataAddress variable means entry value here */ + dataAddress = *entryPointer; /* dataAddress variable means entry value here */ while ((dataAddress) && (!(dataAddress & EHCI_HOST_T_INVALID_VALUE))) { entryPointer = (volatile uint32_t *)dataAddress; - dataAddress = *entryPointer; + dataAddress = *entryPointer; } *entryPointer = (uint32_t)qtdPointer; USB_HostEhciUnlock(); @@ -888,11 +821,11 @@ static void USB_HostEhciTestSingleStepGetDeviceDescData(usb_host_ehci_instance_t { return; } - transfer->callbackFn = USB_HostEhciTestCallback; - transfer->callbackParam = ehciInstance->hostHandle; + transfer->callbackFn = USB_HostEhciTestCallback; + transfer->callbackParam = ehciInstance->hostHandle; transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN; - transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; - transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH); + transfer->setupPacket->bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR; + transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH); transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN((uint16_t)((uint16_t)USB_DESCRIPTOR_TYPE_DEVICE << 8)); transfer->setupPacket->wIndex = 0; USB_HostEhciSingleStepQtdListInit(ehciInstance, (usb_host_ehci_pipe_t *)(deviceInstance->controlPipe), transfer, 1); @@ -907,8 +840,8 @@ static void USB_HostEhciTestSingleStepGetDeviceDescData(usb_host_ehci_instance_t { return; } - transfer->callbackFn = USB_HostEhciTestCallback; - transfer->callbackParam = ehciInstance->hostHandle; + transfer->callbackFn = USB_HostEhciTestCallback; + transfer->callbackParam = ehciInstance->hostHandle; transfer->transferBuffer = buffer; transfer->transferLength = USB_HOST_EHCI_TEST_DESCRIPTOR_LENGTH; USB_HostEhciSingleStepQtdListInit(ehciInstance, (usb_host_ehci_pipe_t *)(deviceInstance->controlPipe), transfer, 2); @@ -917,8 +850,8 @@ static void USB_HostEhciTestSingleStepGetDeviceDescData(usb_host_ehci_instance_t { return; } - transfer->callbackFn = USB_HostEhciTestCallback; - transfer->callbackParam = ehciInstance->hostHandle; + transfer->callbackFn = USB_HostEhciTestCallback; + transfer->callbackParam = ehciInstance->hostHandle; transfer->transferBuffer = NULL; transfer->transferLength = 0; USB_HostEhciSingleStepQtdListInit(ehciInstance, (usb_host_ehci_pipe_t *)(deviceInstance->controlPipe), transfer, 3); @@ -934,7 +867,7 @@ static void USB_HostEhciTestSingleStepGetDeviceDescData(usb_host_ehci_instance_t return; } -void USB_HostEhciTestModeInit(usb_device_handle deviceHandle) +static void USB_HostEhciTestModeInit(usb_device_handle deviceHandle) { uint32_t productId; usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; @@ -975,6 +908,7 @@ void USB_HostEhciTestModeInit(usb_device_handle deviceHandle) USB_HostEhciTestSingleStepGetDeviceDescData(ehciInstance, deviceHandle); break; default: + /*no action */ break; } @@ -1014,60 +948,62 @@ static void USB_HostEhciResumeBus(usb_host_ehci_instance_t *ehciInstance) static uint32_t USB_HostBandwidthComputeTime(uint8_t speed, uint8_t pipeType, uint8_t direction, uint32_t dataLength) { - uint32_t result = (3167 + ((1000 * dataLength) * 7U * 8U / 6U)) / 1000; + uint32_t result = (3167U + ((1000U * dataLength) * 7U * 8U / 6U)) / 1000U; if (pipeType == USB_ENDPOINT_ISOCHRONOUS) /* iso */ { if (speed == USB_SPEED_HIGH) { - result = 38 * 8 * 2083 + 2083 * result + USB_HOST_EHCI_BANDWIDTH_DELAY; + result = 38U * 8U * 2083U + 2083U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } else if (speed == USB_SPEED_FULL) { if (direction == USB_IN) { - result = 7268000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY; + result = 7268000U + 83540U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } else { - result = 6265000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY; + result = 6265000U + 83540U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } } else { + /*no action*/ } } else /* interrupt */ { if (speed == USB_SPEED_HIGH) { - result = 55 * 8 * 2083 + 2083 * result + USB_HOST_EHCI_BANDWIDTH_DELAY; + result = 55U * 8U * 2083U + 2083U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } else if (speed == USB_SPEED_FULL) { - result = 9107000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY; + result = 9107000U + 83540U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } else if (speed == USB_SPEED_LOW) { if (direction == USB_IN) { - result = 64060000 + 2000 * USB_HOST_EHCI_BANDWIDTH_HUB_LS_SETUP + 676670 * result + + result = 64060000U + 2000U * USB_HOST_EHCI_BANDWIDTH_HUB_LS_SETUP + 676670U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } else { - result = 6265000 + 83540 * result + USB_HOST_EHCI_BANDWIDTH_DELAY; + result = 6265000U + 83540U * result + USB_HOST_EHCI_BANDWIDTH_DELAY; } } else { + /*no action*/ } } - result /= 1000000; - if (result == 0) + result /= 1000000U; + if (result == 0U) { - result = 1; + result = 1U; } return result; @@ -1078,7 +1014,7 @@ static void USB_HostBandwidthFslsHostComputeCurrent(usb_host_ehci_instance_t *eh uint16_t *frameBandwidth) { usb_host_ehci_pipe_t *ehciPipePointer; - + void *temp; /* clear the bandwidth */ *frameBandwidth = 0; @@ -1091,26 +1027,28 @@ static void USB_HostBandwidthFslsHostComputeCurrent(usb_host_ehci_instance_t *eh { /* does pipe allocate bandwidth in frameIndex frame? note: interval is power of 2. */ if ((frameIndex >= ehciPipePointer->startFrame) && - (!((uint32_t)(frameIndex - ehciPipePointer->startFrame) & - (uint32_t)(ehciPipePointer->pipeCommon.interval - 1)))) + (0U == ((uint32_t)((uint32_t)frameIndex - ehciPipePointer->startFrame) & + ((uint32_t)ehciPipePointer->pipeCommon.interval - 1U)))) { *frameBandwidth += ehciPipePointer->dataTime; } } - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; } } static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t *ehciInstance, uint32_t hubNumber, uint16_t frameIndex, - uint8_t frameBandwidths[8]) + uint16_t frameBandwidths[8]) { usb_host_ehci_pipe_t *ehciPipePointer; uint8_t index; uint32_t deviceInfo; + void *temp; - for (index = 0; index < 8; ++index) + for (index = 0; index < 8U; ++index) { frameBandwidths[index] = 0; } @@ -1124,47 +1062,50 @@ static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t * { /* compute FS/LS bandwidth that blong to same high-speed hub, because FS/LS bandwidth is allocated from * first parent high-speed hub */ - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, - kUSB_HostGetDeviceHSHubNumber, &deviceInfo); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHSHubNumber, &deviceInfo); if (deviceInfo != hubNumber) { - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; continue; } - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &deviceInfo); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &deviceInfo); if (deviceInfo == USB_SPEED_HIGH) { - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; continue; } /* does pipe allocate bandwidth in frameIndex frame? note: interval is power of 2. */ if ((frameIndex >= ehciPipePointer->startFrame) && - (!((uint32_t)(frameIndex - ehciPipePointer->startFrame) & - (uint32_t)(ehciPipePointer->pipeCommon.interval - 1)))) + (0U == ((uint32_t)((uint32_t)frameIndex - ehciPipePointer->startFrame) & + ((uint32_t)ehciPipePointer->pipeCommon.interval - 1U)))) { if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) /* iso bandwidth is allocated once */ { - frameBandwidths[ehciPipePointer->startUframe + 1] += ehciPipePointer->dataTime; + frameBandwidths[ehciPipePointer->startUframe + 1U] += ehciPipePointer->dataTime; } else /* iso bandwidth is allocated three times */ { - frameBandwidths[ehciPipePointer->startUframe + 1] += ehciPipePointer->dataTime; - frameBandwidths[ehciPipePointer->startUframe + 2] += ehciPipePointer->dataTime; - frameBandwidths[ehciPipePointer->startUframe + 3] += ehciPipePointer->dataTime; + frameBandwidths[ehciPipePointer->startUframe + 1U] += ehciPipePointer->dataTime; + frameBandwidths[ehciPipePointer->startUframe + 2U] += ehciPipePointer->dataTime; + frameBandwidths[ehciPipePointer->startUframe + 3U] += ehciPipePointer->dataTime; } } } - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; } - for (index = 0; index < 7; ++index) /* */ + for (index = 0; index < 7U; ++index) /* */ { if (frameBandwidths[index] > s_SlotMaxBandwidth[index]) { - frameBandwidths[index + 1] += (frameBandwidths[index] - s_SlotMaxBandwidth[index]); + frameBandwidths[index + 1U] += (frameBandwidths[index] - s_SlotMaxBandwidth[index]); frameBandwidths[index] = s_SlotMaxBandwidth[index]; } } @@ -1172,14 +1113,14 @@ static void USB_HostBandwidthHsHostComputeCurrentFsls(usb_host_ehci_instance_t * static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t *ehciInstance, uint16_t frameIndex, - uint8_t frameBandwidths[8]) + uint16_t frameBandwidths[8]) { usb_host_ehci_pipe_t *ehciPipePointer; - uint8_t index; + uint16_t index; uint32_t deviceInfo; uint16_t frameInterval; - - for (index = 0; index < 8; ++index) + void *temp; + for (index = 0; index < 8U; ++index) { frameBandwidths[index] = 0; } @@ -1192,26 +1133,26 @@ static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT)) { frameInterval = ehciPipePointer->pipeCommon.interval; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &deviceInfo); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &deviceInfo); if (deviceInfo == USB_SPEED_HIGH) /* high-speed data bandwidth */ { /* frameInterval means micro-frame here */ if (frameIndex >= ehciPipePointer->startFrame) { - if ((frameInterval > 8) && - (frameIndex * 8 - ehciPipePointer->startFrame * 8 >= ehciPipePointer->startUframe)) + if ((frameInterval > 8U) && + (frameIndex * 8U - ehciPipePointer->startFrame * 8U >= ehciPipePointer->startUframe)) { - if (!((uint32_t)(frameIndex * 8 - ehciPipePointer->startFrame * 8 - - ehciPipePointer->startUframe) & - (uint32_t)(frameInterval - 1))) + if (0U == ((((uint32_t)frameIndex) * 8U - ehciPipePointer->startFrame * 8U - + ehciPipePointer->startUframe) & + ((uint32_t)frameInterval - 1U))) { frameBandwidths[ehciPipePointer->startUframe] += ehciPipePointer->dataTime; } } else { - for (index = ehciPipePointer->startUframe; index < 8; index += frameInterval) + for (index = ehciPipePointer->startUframe; index < 8U; index += frameInterval) { frameBandwidths[index] += ehciPipePointer->dataTime; } @@ -1221,17 +1162,18 @@ static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t else /* full-speed split bandwidth */ { if ((frameIndex >= ehciPipePointer->startFrame) && - (!((uint32_t)(frameIndex - ehciPipePointer->startFrame) & (uint32_t)(frameInterval - 1)))) + (0U == ((uint32_t)((uint32_t)frameIndex - ehciPipePointer->startFrame) & + (uint32_t)((uint32_t)frameInterval - 1U)))) { - for (index = 0; index < 8; ++index) + for (index = 0; index < 8U; ++index) { - if ((uint32_t)(ehciPipePointer->uframeSmask) & - (uint32_t)(0x01 << index)) /* start-split micro-frames */ + if (0U != ((uint32_t)(ehciPipePointer->uframeSmask) & + (uint32_t)(0x01UL << index))) /* start-split micro-frames */ { frameBandwidths[index] += ehciPipePointer->startSplitTime; } - if ((uint32_t)(ehciPipePointer->uframeCmask) & - (uint32_t)(0x01 << index)) /* complete-split micro-frames */ + if (0U != ((uint32_t)(ehciPipePointer->uframeCmask) & + (uint32_t)(0x01UL << index))) /* complete-split micro-frames */ { frameBandwidths[index] += ehciPipePointer->completeSplitTime; } @@ -1239,17 +1181,20 @@ static void USB_HostBandwidthHsHostComputeCurrentHsAll(usb_host_ehci_instance_t } } } - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; } +#if 0 for (index = 0; index < 7; ++index) /* */ { - if (frameBandwidths[index] > s_SlotMaxBandwidth[index]) + if (frameBandwidths[index] > s_SlotMaxBandwidthHs[index]) { - frameBandwidths[index + 1] += (frameBandwidths[index] - s_SlotMaxBandwidth[index]); - frameBandwidths[index] = s_SlotMaxBandwidth[index]; + frameBandwidths[index + 1] += (frameBandwidths[index] - s_SlotMaxBandwidthHs[index]); + frameBandwidths[index] = s_SlotMaxBandwidthHs[index]; } } +#endif } /*! @@ -1270,15 +1215,19 @@ static usb_status_t USB_HostBandwidthHsHostAllocateHsCommon(usb_host_ehci_instan uint16_t uframeIntervalIndex; uint16_t uframeIndex; uint16_t frameIndex; - uint8_t frameTimes[8]; + uint16_t frameTimes[8]; frameIndex = 0; + for (uint8_t i = 0; i < 8U; ++i) + { + frameTimes[i] = 0U; + } USB_HostBandwidthHsHostComputeCurrentHsAll( ehciInstance, frameIndex, frameTimes); /* compute the allocated bandwidths in the frameIndex frame */ for (uframeIntervalIndex = 0; (uframeIntervalIndex < uframeInterval); ++uframeIntervalIndex) /* start micro-frame */ { /* for all the micro-frame in interval uframeInterval */ - for (uframeIndex = uframeIntervalIndex; uframeIndex < (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 8); + for (uframeIndex = uframeIntervalIndex; uframeIndex < (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 8U); uframeIndex += uframeInterval) { if (frameIndex != (uframeIndex >> 3)) @@ -1288,13 +1237,13 @@ static usb_status_t USB_HostBandwidthHsHostAllocateHsCommon(usb_host_ehci_instan ehciInstance, frameIndex, frameTimes); /* compute the allocated bandwidths in the new frameIndex frame */ } - if (frameTimes[uframeIndex & 0x0007] + timeData > - s_SlotMaxBandwidth[(uframeIndex & 0x0007)]) /* micro-frame has enough idle bandwidth? */ + if (frameTimes[uframeIndex & 0x0007U] + timeData > + s_SlotMaxBandwidthHs[(uframeIndex & 0x0007U)]) /* micro-frame has enough idle bandwidth? */ { break; /* fail */ } } - if (uframeIndex >= (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 8)) /* success? */ + if (uframeIndex >= (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE * 8U)) /* success? */ { break; } @@ -1318,91 +1267,97 @@ static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t usb_host_ehci_pipe_t *ehciPipePointer) { usb_status_t status; - uint32_t deviceInfo; - uint32_t hubNumber; + uint32_t deviceInfo = 0; + uint32_t hubNumber = 0; uint16_t uframeIntervalIndex = 0; - uint16_t frameIntervalIndex = 0; + uint16_t frameIntervalIndex = 0; uint16_t frameIndex; uint16_t timeCompleteSplit; uint16_t timeStartSplit; uint32_t timeData; uint8_t SsCsNumber = 0; uint16_t frameInterval; - uint8_t frameTimes[8]; + uint16_t frameTimes[8]; uint8_t allocateOk = 1; - uint8_t index; + uint16_t index; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &deviceInfo); + for (uint8_t i = 0; i < 8U; ++i) + { + frameTimes[i] = 0U; + } + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &deviceInfo); timeData = USB_HostBandwidthComputeTime( - deviceInfo, USB_ENDPOINT_ISOCHRONOUS, ehciPipePointer->pipeCommon.direction, - ehciPipePointer->pipeCommon.maxPacketSize * ehciPipePointer->pipeCommon.numberPerUframe); + (uint8_t)deviceInfo, USB_ENDPOINT_ISOCHRONOUS, ehciPipePointer->pipeCommon.direction, + (((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize) * ehciPipePointer->pipeCommon.numberPerUframe)); /* pipe is high-speed */ if (deviceInfo == USB_SPEED_HIGH) { uframeIntervalIndex = 0; - status = USB_HostBandwidthHsHostAllocateHsCommon(ehciInstance, ehciPipePointer->uframeInterval, timeData, - &uframeIntervalIndex); + status = USB_HostBandwidthHsHostAllocateHsCommon(ehciInstance, ehciPipePointer->uframeInterval, + (uint16_t)timeData, &uframeIntervalIndex); if (status == kStatus_USB_Success) { - ehciPipePointer->startFrame = (uframeIntervalIndex / 8); - ehciPipePointer->startUframe = (uframeIntervalIndex & 0x0007); - ehciPipePointer->dataTime = timeData; + ehciPipePointer->startFrame = (uframeIntervalIndex / 8U); + ehciPipePointer->startUframe = (uint8_t)(uframeIntervalIndex & 0x0007U); + ehciPipePointer->dataTime = (uint16_t)timeData; return kStatus_USB_Success; } } else /* pipe is full-speed or low-speed */ { - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetHubThinkTime, - &deviceInfo); /* deviceInfo variable means hub think time */ - timeData += (deviceInfo * 7 / (6 * 12)); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubNumber, - &hubNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetHubThinkTime, + &deviceInfo); /* deviceInfo variable means hub think time */ + timeData += (deviceInfo * 7U / (6U * 12U)); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHSHubNumber, &hubNumber); frameInterval = ehciPipePointer->pipeCommon.interval; /* compute start-split and complete-split bandwidth */ if (ehciPipePointer->pipeCommon.direction == USB_OUT) { - timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_OUT, - ehciPipePointer->pipeCommon.maxPacketSize); + timeStartSplit = (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_OUT, + ehciPipePointer->pipeCommon.maxPacketSize); timeCompleteSplit = 0; } else { - timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_IN, 1); - timeCompleteSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_IN, - ehciPipePointer->pipeCommon.maxPacketSize); + timeStartSplit = + (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_IN, 1); + timeCompleteSplit = (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_ISOCHRONOUS, USB_IN, + ehciPipePointer->pipeCommon.maxPacketSize); } /* note: bandwidth must put in one frame */ - for (uframeIntervalIndex = 0; uframeIntervalIndex <= 5; ++uframeIntervalIndex) /* uframe interval */ + for (uframeIntervalIndex = 0U; uframeIntervalIndex <= 5U; ++uframeIntervalIndex) /* uframe interval */ { - for (frameIntervalIndex = 0; frameIntervalIndex < frameInterval; ++frameIntervalIndex) /* frame interval */ + for (frameIntervalIndex = 0U; frameIntervalIndex < frameInterval; ++frameIntervalIndex) /* frame interval */ { allocateOk = 1; for (frameIndex = frameIntervalIndex; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE; frameIndex += frameInterval) /* check all the frames */ { /* compute start-split and complete-split number */ - SsCsNumber = (ehciPipePointer->pipeCommon.maxPacketSize + 187) / - 188; /* ss number for iso out; cs number for iso in */ + SsCsNumber = (uint8_t)((ehciPipePointer->pipeCommon.maxPacketSize + 187U) / + 188U); /* ss number for iso out; cs number for iso in */ if (ehciPipePointer->pipeCommon.direction == USB_OUT) /* ISO OUT */ { - if (uframeIntervalIndex + SsCsNumber > 8) + if (uframeIntervalIndex + SsCsNumber > 8U) { - allocateOk = 0; + allocateOk = 0U; } } else { - if (uframeIntervalIndex + 2 + SsCsNumber > - 8) /* ISO IN: there are two micro-frame interval between start-split and complete-split */ + if (uframeIntervalIndex + 2U + SsCsNumber > + 8U) /* ISO IN: there are two micro-frame interval between start-split and complete-split */ { - allocateOk = 0; + allocateOk = 0U; } } - if (allocateOk) + if (0U != allocateOk) { /* allocate start-split and complete-split bandwidth */ USB_HostBandwidthHsHostComputeCurrentHsAll(ehciInstance, frameIndex, frameTimes); @@ -1411,9 +1366,9 @@ static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t index = uframeIntervalIndex; for (; index < (uframeIntervalIndex + SsCsNumber); ++index) { - if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidth[index]) + if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidthHs[index]) { - allocateOk = 0; + allocateOk = 0U; break; } } @@ -1421,20 +1376,20 @@ static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t else /* ISO IN */ { index = uframeIntervalIndex; - if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidth[index]) + if (frameTimes[index] + timeStartSplit > s_SlotMaxBandwidthHs[index]) { - allocateOk = 0; + allocateOk = 0U; } - if (allocateOk) + if (0U != allocateOk) { index = uframeIntervalIndex + - 2; /* there are two micro-frames interval between start-split and complete-split */ - for (; index < (uframeIntervalIndex + 2 + SsCsNumber); ++index) + 2U; /* there are two micro-frames interval between start-split and complete-split */ + for (; index < (uframeIntervalIndex + 2U + SsCsNumber); ++index) { - if (frameTimes[index] + timeCompleteSplit > s_SlotMaxBandwidth[index]) + if (frameTimes[index] + timeCompleteSplit > s_SlotMaxBandwidthHs[index]) { - allocateOk = 0; + allocateOk = 0U; break; } } @@ -1443,18 +1398,18 @@ static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t } /* allocate data bandwidth */ - if (allocateOk) + if (0U != allocateOk) { USB_HostBandwidthHsHostComputeCurrentFsls(ehciInstance, hubNumber, frameIndex, frameTimes); - index = uframeIntervalIndex + 1; /* timeData bandwidth start position */ + index = uframeIntervalIndex + 1U; /* timeData bandwidth start position */ /* iso must occupy all the uframe bandwidth */ { deviceInfo = timeData; /* note: deviceInfo variable means bandwidth here */ - while ((index < 8) && (deviceInfo > s_SlotMaxBandwidth[index])) + while ((index < 8U) && (deviceInfo > s_SlotMaxBandwidth[index])) { - if (frameTimes[index] > 0) + if (frameTimes[index] > 0U) { - allocateOk = 0; + allocateOk = 0U; break; } else @@ -1465,16 +1420,16 @@ static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t } } } - if (allocateOk) + if (0U != allocateOk) { /* data bandwidth can be put in the frame? */ - index = uframeIntervalIndex + 1; /* timeData bandwidth start position */ - frameTimes[index] += timeData; - for (; index < 7; ++index) + index = uframeIntervalIndex + 1U; /* timeData bandwidth start position */ + frameTimes[index] += (uint16_t)timeData; + for (; index < 7U; ++index) { if (frameTimes[index] > s_SlotMaxBandwidth[index]) { - frameTimes[index + 1] += (frameTimes[index] - s_SlotMaxBandwidth[index]); + frameTimes[index + 1U] += (frameTimes[index] - s_SlotMaxBandwidth[index]); frameTimes[index] = s_SlotMaxBandwidth[index]; } else @@ -1488,45 +1443,45 @@ static usb_status_t USB_HostBandwidthHsHostAllocateIso(usb_host_ehci_instance_t } } - if (allocateOk) + if (0U != allocateOk) { break; } } - if (allocateOk) + if (0U != allocateOk) { break; } } - if (allocateOk) + if (0U != allocateOk) { break; } } - if (allocateOk) + if (0U != allocateOk) { - ehciPipePointer->startFrame = frameIntervalIndex; - ehciPipePointer->startUframe = uframeIntervalIndex; - ehciPipePointer->dataTime = timeData; - ehciPipePointer->startSplitTime = timeStartSplit; + ehciPipePointer->startFrame = frameIntervalIndex; + ehciPipePointer->startUframe = (uint8_t)uframeIntervalIndex; + ehciPipePointer->dataTime = (uint16_t)timeData; + ehciPipePointer->startSplitTime = timeStartSplit; ehciPipePointer->completeSplitTime = timeCompleteSplit; if (ehciPipePointer->pipeCommon.direction == USB_OUT) { index = uframeIntervalIndex; for (; index < (uframeIntervalIndex + SsCsNumber); ++index) { - ehciPipePointer->uframeSmask = (uint32_t)ehciPipePointer->uframeSmask | (uint32_t)(0x01 << index); + ehciPipePointer->uframeSmask = ehciPipePointer->uframeSmask | (uint8_t)(0x01UL << index); } } else { - index = uframeIntervalIndex; - ehciPipePointer->uframeSmask = (uint32_t)ehciPipePointer->uframeSmask | (uint32_t)(0x01 << index); - index = uframeIntervalIndex + 2; - for (; index < (uframeIntervalIndex + 2 + SsCsNumber); ++index) + index = uframeIntervalIndex; + ehciPipePointer->uframeSmask = ehciPipePointer->uframeSmask | (uint8_t)(0x01UL << index); + index = uframeIntervalIndex + 2U; + for (; index < (uframeIntervalIndex + 2U + SsCsNumber); ++index) { - ehciPipePointer->uframeCmask = (uint32_t)ehciPipePointer->uframeCmask | (uint32_t)(0x01 << index); + ehciPipePointer->uframeCmask = ehciPipePointer->uframeCmask | (uint8_t)(0x01UL << index); } } @@ -1543,92 +1498,100 @@ static usb_status_t USB_HostBandwidthHsHostAllocateInterrupt(usb_host_ehci_insta usb_host_ehci_pipe_t *ehciPipePointer) { usb_status_t status; - uint32_t deviceInfo; - uint32_t hubNumber; + uint32_t deviceInfo = 0; + uint32_t hubNumber = 0; uint16_t uframeIntervalIndex = 0; - uint16_t frameIntervalIndex = 0; + uint16_t frameIntervalIndex = 0; uint16_t frameIndex; uint16_t timeCompleteSplit; uint16_t timeStartSplit; uint32_t timeData; uint8_t SsCsNumber; uint16_t frameInterval; - uint8_t frameTimes[8]; + uint16_t frameTimes[8]; uint8_t allocateOk = 1; uint8_t index; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &deviceInfo); + for (uint8_t i = 0; i < 8U; ++i) + { + frameTimes[i] = 0U; + } + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &deviceInfo); timeData = USB_HostBandwidthComputeTime( - deviceInfo, USB_ENDPOINT_INTERRUPT, ehciPipePointer->pipeCommon.direction, - ehciPipePointer->pipeCommon.maxPacketSize * ehciPipePointer->pipeCommon.numberPerUframe); + (uint8_t)deviceInfo, USB_ENDPOINT_INTERRUPT, ehciPipePointer->pipeCommon.direction, + (uint32_t)ehciPipePointer->pipeCommon.maxPacketSize * ehciPipePointer->pipeCommon.numberPerUframe); /* pipe is high-speed */ if (deviceInfo == USB_SPEED_HIGH) { uframeIntervalIndex = 0; - status = USB_HostBandwidthHsHostAllocateHsCommon(ehciInstance, ehciPipePointer->uframeInterval, timeData, - &uframeIntervalIndex); + status = USB_HostBandwidthHsHostAllocateHsCommon(ehciInstance, ehciPipePointer->uframeInterval, + (uint16_t)timeData, &uframeIntervalIndex); if (status == kStatus_USB_Success) { - ehciPipePointer->startFrame = (uframeIntervalIndex / 8); - ehciPipePointer->startUframe = (uframeIntervalIndex & 0x0007); + ehciPipePointer->startFrame = (uframeIntervalIndex / 8U); + ehciPipePointer->startUframe = (uint8_t)(uframeIntervalIndex & 0x0007U); /* for HS interrupt start transaction position */ - if (ehciPipePointer->uframeInterval >= 8) + if (ehciPipePointer->uframeInterval >= 8U) { - ehciPipePointer->uframeSmask = (0x01 << ehciPipePointer->startUframe); + ehciPipePointer->uframeSmask = (0x01U << ehciPipePointer->startUframe); } else { - ehciPipePointer->uframeSmask = 0x00u; - for (index = ehciPipePointer->startUframe; index < 8; index += ehciPipePointer->uframeInterval) + ehciPipePointer->uframeSmask = 0x00U; + for (index = ehciPipePointer->startUframe; index < 8U; + index += (uint8_t)ehciPipePointer->uframeInterval) { ehciPipePointer->uframeSmask |= (0x01U << index); } } - ehciPipePointer->dataTime = timeData; + ehciPipePointer->dataTime = (uint16_t)timeData; return kStatus_USB_Success; } } else /* pipe is full-speed or low-speed */ { - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetHubThinkTime, - &deviceInfo); - timeData += (deviceInfo * 7 / (6 * 12)); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubNumber, - &hubNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetHubThinkTime, &deviceInfo); + timeData += (deviceInfo * 7U / (6U * 12U)); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHSHubNumber, &hubNumber); frameInterval = ehciPipePointer->pipeCommon.interval; - SsCsNumber = 3; /* complete split number */ + SsCsNumber = 3U; /* complete split number */ /* compute start-split and complete-split bandwidth */ if (ehciPipePointer->pipeCommon.direction == USB_OUT) { - timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, - ehciPipePointer->pipeCommon.maxPacketSize) + - USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, 1); - timeCompleteSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, 0); + timeStartSplit = (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, + ehciPipePointer->pipeCommon.maxPacketSize); + timeStartSplit += + (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, 1U); + timeCompleteSplit = + (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_OUT, 0U); } else { - timeStartSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, 1); - timeCompleteSplit = USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, - ehciPipePointer->pipeCommon.maxPacketSize) + - USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, 0); + timeStartSplit = (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, 1U); + timeCompleteSplit = (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, + ehciPipePointer->pipeCommon.maxPacketSize); + timeCompleteSplit += + (uint16_t)USB_HostBandwidthComputeTime(USB_SPEED_HIGH, USB_ENDPOINT_INTERRUPT, USB_IN, 0U); } /* note: bandwidth must put in one frame */ - for (uframeIntervalIndex = 0; uframeIntervalIndex <= 4; ++uframeIntervalIndex) /* uframe interval */ + for (uframeIntervalIndex = 0U; uframeIntervalIndex <= 4U; ++uframeIntervalIndex) /* uframe interval */ { - for (frameIntervalIndex = 0; frameIntervalIndex < frameInterval; ++frameIntervalIndex) /* frame interval */ + for (frameIntervalIndex = 0U; frameIntervalIndex < frameInterval; ++frameIntervalIndex) /* frame interval */ { - allocateOk = 1; + allocateOk = 1U; for (frameIndex = frameIntervalIndex; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE; frameIndex += frameInterval) /* check all the frames */ { /* allocate data bandwidth */ USB_HostBandwidthHsHostComputeCurrentFsls(ehciInstance, hubNumber, frameIndex, frameTimes); - index = uframeIntervalIndex + 1; - for (; index <= (uframeIntervalIndex + 3); ++index) /* data bandwidth number is 3. + index = (uint8_t)(uframeIntervalIndex + 1U); + for (; index <= (uframeIntervalIndex + 3U); ++index) /* data bandwidth number is 3. uframeIntervalIndex don't exceed 4, so index cannot exceed 7 */ { @@ -1639,60 +1602,61 @@ static usb_status_t USB_HostBandwidthHsHostAllocateInterrupt(usb_host_ehci_insta } } - if (allocateOk) + if (0U != allocateOk) { USB_HostBandwidthHsHostComputeCurrentHsAll(ehciInstance, frameIndex, frameTimes); /* allocate start_split bandwidth */ - if (frameTimes[uframeIntervalIndex] + timeStartSplit > s_SlotMaxBandwidth[uframeIntervalIndex]) + if (frameTimes[uframeIntervalIndex] + timeStartSplit > + s_SlotMaxBandwidthHs[uframeIntervalIndex]) { - allocateOk = 0; + allocateOk = 0U; } - if (allocateOk) + if (0U != allocateOk) { /* allocate complete_split bandwidth */ - index = uframeIntervalIndex + 2; + index = (uint8_t)uframeIntervalIndex + 2U; /* complete-split number is normal 3. When uframeIntervalIndex is 4, complete-split number * is 2. */ - for (; (index <= (uframeIntervalIndex + 1 + SsCsNumber)) && (index < 8); ++index) + for (; (index <= (uframeIntervalIndex + 1U + SsCsNumber)) && (index < 8U); ++index) { - if (frameTimes[index] + timeCompleteSplit > s_SlotMaxBandwidth[index]) + if (frameTimes[index] + timeCompleteSplit > s_SlotMaxBandwidthHs[index]) { - allocateOk = 0; + allocateOk = 0U; break; } } } } - if (!allocateOk) + if (0U == allocateOk) { break; /* allocate fail */ } } - if (allocateOk) + if (0U != allocateOk) { break; } } - if (allocateOk) + if (0U != allocateOk) { break; } } - if (allocateOk) + if (0U != allocateOk) { - ehciPipePointer->startFrame = frameIntervalIndex; - ehciPipePointer->startUframe = uframeIntervalIndex; - ehciPipePointer->uframeSmask = (0x01 << ehciPipePointer->startUframe); - ehciPipePointer->uframeCmask = 0; - index = uframeIntervalIndex + 2; - for (; (index <= (uframeIntervalIndex + 1 + SsCsNumber)) && (index < 8); ++index) + ehciPipePointer->startFrame = frameIntervalIndex; + ehciPipePointer->startUframe = (uint8_t)uframeIntervalIndex; + ehciPipePointer->uframeSmask = (0x01u << ehciPipePointer->startUframe); + ehciPipePointer->uframeCmask = 0u; + index = (uint8_t)uframeIntervalIndex + 2u; + for (; (index <= (uframeIntervalIndex + 1u + SsCsNumber)) && (index < 8u); ++index) { - ehciPipePointer->uframeCmask = (uint32_t)ehciPipePointer->uframeCmask | (uint32_t)(0x01 << index); + ehciPipePointer->uframeCmask = ehciPipePointer->uframeCmask | (0x01U << index); } - ehciPipePointer->dataTime = timeData; - ehciPipePointer->startSplitTime = timeStartSplit; + ehciPipePointer->dataTime = (uint16_t)timeData; + ehciPipePointer->startSplitTime = timeStartSplit; ehciPipePointer->completeSplitTime = timeCompleteSplit; return kStatus_USB_Success; @@ -1706,17 +1670,18 @@ static usb_status_t USB_HostBandwidthFslsHostAllocate(usb_host_ehci_instance_t * usb_host_ehci_pipe_t *ehciPipePointer) { uint32_t FslsTime = 0; - uint32_t speed = 0; + uint32_t speed = 0; uint16_t uframeIntervalIndex; uint16_t frameIndex; uint16_t frameInterval; uint16_t frameTime; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetHubThinkTime, - &FslsTime); - FslsTime += (FslsTime * 7 / (6 * 12)); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, &speed); - FslsTime = FslsTime + USB_HostBandwidthComputeTime(speed, ehciPipePointer->pipeCommon.pipeType, + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetHubThinkTime, &FslsTime); + FslsTime += (FslsTime * 7U / (6U * 12U)); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); + FslsTime = FslsTime + USB_HostBandwidthComputeTime((uint8_t)speed, ehciPipePointer->pipeCommon.pipeType, ehciPipePointer->pipeCommon.direction, ehciPipePointer->pipeCommon.maxPacketSize); @@ -1740,11 +1705,11 @@ static usb_status_t USB_HostBandwidthFslsHostAllocate(usb_host_ehci_instance_t * } if (uframeIntervalIndex < ehciPipePointer->uframeInterval) { - ehciPipePointer->startFrame = (uframeIntervalIndex >> 3); - ehciPipePointer->startUframe = (uframeIntervalIndex & 0x0007); + ehciPipePointer->startFrame = (uframeIntervalIndex >> 3); + ehciPipePointer->startUframe = (uint8_t)(uframeIntervalIndex & 0x0007U); ehciPipePointer->uframeSmask = 0; /* useless */ ehciPipePointer->uframeCmask = 0; - ehciPipePointer->dataTime = FslsTime; + ehciPipePointer->dataTime = (uint16_t)FslsTime; return kStatus_USB_Success; } @@ -1754,46 +1719,46 @@ static usb_status_t USB_HostBandwidthFslsHostAllocate(usb_host_ehci_instance_t * static uint8_t USB_HostEhciGet2PowerValue(uint8_t value) { - if ((value == 0) || (value == 1)) + if ((value == 0U) || (value == 1U)) { return value; } - if (value & 0xf0) + if (0U != (value & 0xf0U)) { - if (value & 0x80) + if (0U != (value & 0x80U)) { - return 128; + return 128U; } - else if (value & 0x40) + else if (0U != (value & 0x40U)) { - return 64; + return 64U; } - else if (value & 0x20) + else if (0U != (value & 0x20U)) { - return 32; + return 32U; } else { - return 16; + return 16U; } } else { - if (value & 0x08) + if (0U != (value & 0x08U)) { - return 8; + return 8U; } - else if (value & 0x04) + else if (0U != (value & 0x04U)) { - return 4; + return 4U; } - else if (value & 0x02) + else if (0U != (value & 0x02U)) { - return 2; + return 2U; } else { - return 1; + return 1U; } } } @@ -1801,8 +1766,9 @@ static uint8_t USB_HostEhciGet2PowerValue(uint8_t value) static void USB_HostEhciZeroMem(uint32_t *buffer, uint32_t length) { /* note: the zero unit is uint32_t */ - while (length--) + while (0U != length) { + length--; *buffer = 0; buffer++; } @@ -1811,24 +1777,24 @@ static void USB_HostEhciZeroMem(uint32_t *buffer, uint32_t length) static void USB_HostEhciDelay(USBHS_Type *ehciIpBase, uint32_t ms) { /* note: the max delay time cannot exceed half of max value (0x4000) */ - int32_t sofStart; - int32_t SofEnd; + uint32_t sofStart; + uint32_t SofEnd; uint32_t distance; - sofStart = (int32_t)(ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); + sofStart = (ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); do { - SofEnd = (int32_t)(ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); - distance = (uint32_t)(SofEnd - sofStart + EHCI_MAX_UFRAME_VALUE + 1); - } while ((distance & EHCI_MAX_UFRAME_VALUE) < (ms * 8)); /* compute the distance between sofStart and SofEnd */ + SofEnd = (ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); + distance = (SofEnd + EHCI_MAX_UFRAME_VALUE + 1U - sofStart); + } while ((distance & EHCI_MAX_UFRAME_VALUE) < (ms * 8U)); /* compute the distance between sofStart and SofEnd */ } -static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance) +void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance) { uint32_t stateSync; - if (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)) + if (0U == (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)) { /* the status must be same when change USBCMD->ASE */ do @@ -1839,7 +1805,7 @@ static void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance) ehciInstance->ehciIpBase->ASYNCLISTADDR = (uint32_t)(ehciInstance->shedFirstQh); ehciInstance->ehciIpBase->USBCMD |= USBHS_USBCMD_ASE_MASK; - while (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)) + while (0U == (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)) { } } @@ -1857,16 +1823,16 @@ static void USB_HostEhciStopAsync(usb_host_ehci_instance_t *ehciInstance) } while ((stateSync == USBHS_USBSTS_AS_MASK) || (stateSync == USBHS_USBCMD_ASE_MASK)); ehciInstance->ehciIpBase->USBCMD &= (uint32_t)(~(uint32_t)USBHS_USBCMD_ASE_MASK); /* disable async schedule */ - while (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK) + while (0U != (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)) { } } -static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance) +void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance) { uint32_t stateSync; - if (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK)) + if (0U == (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK)) { /* the status must be same when change USBCMD->PSE */ do @@ -1875,11 +1841,11 @@ static void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance) (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_PSE_MASK)); } while ((stateSync == USBHS_USBSTS_PS_MASK) || (stateSync == USBHS_USBCMD_PSE_MASK)); ehciInstance->ehciIpBase->PERIODICLISTBASE = (uint32_t)(ehciInstance->ehciFrameList); - if (!(ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_PSE_MASK)) + if (0U == (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_PSE_MASK)) { ehciInstance->ehciIpBase->USBCMD |= USBHS_USBCMD_PSE_MASK; /* start periodic schedule */ } - while (!(ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK)) + while (0U == (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK)) { } } @@ -1898,7 +1864,7 @@ static void USB_HostEhciStopPeriodic(usb_host_ehci_instance_t *ehciInstance) } while ((stateSync == USBHS_USBSTS_PS_MASK) || (stateSync == USBHS_USBCMD_PSE_MASK)); ehciInstance->ehciIpBase->USBCMD &= (~USBHS_USBCMD_PSE_MASK); /* stop periodic schedule */ - while (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK) + while (0U != (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_PS_MASK)) { } } @@ -1908,7 +1874,7 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst usb_host_transfer_t *transfer) { volatile usb_host_ehci_qh_t *vltQhPointer; - usb_host_ehci_qtd_t *qtdPointer = NULL; + usb_host_ehci_qtd_t *qtdPointer = NULL; usb_host_ehci_qtd_t *BaseQtdPointer = NULL; volatile uint32_t *entryPointer; uint32_t qtdNumber; @@ -1921,19 +1887,23 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_CONTROL) { /* assume setup data don't exceed one qtd data size, one qtd can transfer least 16k data */ - if (transfer->transferLength == 0) + if (transfer->transferLength == 0U) { - qtdNumber = 2; + qtdNumber = 2U; } else { - qtdNumber = 3; + qtdNumber = 3U; } } else { - qtdNumber = - (((transfer->transferLength) & 0xFFFFC000U) >> 14) + (((transfer->transferLength) & 0x00003FFF) ? 1 : 0); + qtdNumber = (((transfer->transferLength) & 0xFFFFC000U) >> 14U) + + (0U != ((transfer->transferLength) & 0x00003FFFU) ? 1U : 0U); + if (0U == qtdNumber) + { + qtdNumber = 1U; + } } vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; @@ -1941,20 +1911,21 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst USB_HostEhciLock(); if (qtdNumber <= ehciInstance->ehciQtdNumber) { - ehciInstance->ehciQtdNumber -= qtdNumber; + ehciInstance->ehciQtdNumber -= (uint8_t)qtdNumber; BaseQtdPointer = ehciInstance->ehciQtdHead; - qtdPointer = NULL; + qtdPointer = NULL; do { if (qtdPointer != NULL) { qtdPointer->nextQtdPointer = (uint32_t)ehciInstance->ehciQtdHead; } - qtdPointer = ehciInstance->ehciQtdHead; - ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer; + qtdPointer = ehciInstance->ehciQtdHead; + ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)qtdPointer->nextQtdPointer; qtdPointer->nextQtdPointer = 0; - } while (--qtdNumber); - if (ehciInstance->ehciQtdNumber == 0) + --qtdNumber; + } while (0U != qtdNumber); + if (ehciInstance->ehciQtdNumber == 0U) { ehciInstance->ehciQtdTail = NULL; } @@ -1970,34 +1941,34 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_CONTROL) { /* setup transaction qtd */ - qtdPointer = BaseQtdPointer; + qtdPointer = BaseQtdPointer; qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* dt: need set; ioc: 0; C_Page: 0; PID Code: SETUP; Status: Active */ - qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0; + qtdPointer->transferResults[1] = 0U; qtdPointer->transferResults[0] = - ((0x00000000 << EHCI_HOST_QTD_DT_SHIFT) | (8 << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) | + ((0x00000000UL << EHCI_HOST_QTD_DT_SHIFT) | (8UL << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) | (EHCI_HOST_PID_SETUP << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK)); - dataAddress = ((uint32_t)transfer->setupPacket); + dataAddress = ((uint32_t)transfer->setupPacket); qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */ /* set buffer pointer no matter data length */ - for (index = 0; index < 4; ++index) + for (index = 0; index < 4U; ++index) { - qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000U); + qtdPointer->bufferPointers[index] = ((dataAddress + ((uint32_t)index + 1U) * 4U * 1024U) & 0xFFFFF000U); } /* data transaction qtd */ dataLength = transfer->transferLength; - if (dataLength != 0) + if (dataLength != 0U) { qtdPointer = (usb_host_ehci_qtd_t *)(qtdPointer->nextQtdPointer); qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* dt: need set; ioc: 0; C_Page: 0; PID Code: IN/OUT; Status: Active */ - qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0; + qtdPointer->transferResults[1] = 0U; if (transfer->direction == USB_OUT) { qtdPointer->transferResults[0] = - ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (dataLength << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) | + ((0x00000001UL << EHCI_HOST_QTD_DT_SHIFT) | (dataLength << EHCI_HOST_QTD_TOTAL_BYTES_SHIFT) | (EHCI_HOST_PID_OUT << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK)); } else @@ -2007,24 +1978,24 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK)); } - dataAddress = (uint32_t)transfer->transferBuffer; + dataAddress = (uint32_t)transfer->transferBuffer; qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */ /* set buffer pointer no matter data length */ - for (index = 0; index < 4; ++index) + for (index = 0; index < 4U; ++index) { - qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000U); + qtdPointer->bufferPointers[index] = ((dataAddress + ((uint32_t)index + 1U) * 4U * 1024U) & 0xFFFFF000U); } } /* status transaction qtd */ - qtdPointer = (usb_host_ehci_qtd_t *)(qtdPointer->nextQtdPointer); + qtdPointer = (usb_host_ehci_qtd_t *)(qtdPointer->nextQtdPointer); qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* dt: dont care; ioc: 1; C_Page: 0; PID Code: IN/OUT; Status: Active */ - qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0; - if ((dataLength == 0) || (transfer->direction == USB_OUT)) + qtdPointer->transferResults[1] = 0; + if ((dataLength == 0U) || (transfer->direction == USB_OUT)) { qtdPointer->transferResults[0] = - ((0x00000001U << EHCI_HOST_QTD_DT_SHIFT) | (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | + ((0x00000001UL << EHCI_HOST_QTD_DT_SHIFT) | (EHCI_HOST_PID_IN << EHCI_HOST_QTD_PID_CODE_SHIFT) | (EHCI_HOST_QTD_IOC_MASK) | (EHCI_HOST_QTD_STATUS_ACTIVE_MASK)); } else @@ -2037,12 +2008,11 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst } else { - dataLength = transfer->transferLength; dataAddress = (uint32_t)transfer->transferBuffer; - qtdPointer = BaseQtdPointer; - while (1) + qtdPointer = BaseQtdPointer; + while (1U == 1U) { - endAddress = dataAddress + (16 * 1024); + endAddress = dataAddress + (16U * 1024U); if (endAddress > (uint32_t)(transfer->transferBuffer + transfer->transferLength)) { endAddress = (uint32_t)(transfer->transferBuffer + transfer->transferLength); @@ -2050,7 +2020,7 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst qtdPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* dt: set; ioc: 0; C_Page: 0; PID Code: IN/OUT; Status: Active */ - qtdPointer->transferResults[0] = qtdPointer->transferResults[1] = 0; + qtdPointer->transferResults[1] = 0U; if (transfer->direction == USB_OUT) { qtdPointer->transferResults[0] = @@ -2069,13 +2039,13 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst } qtdPointer->transferResults[1] = dataAddress; /* current offset is set too */ /* set buffer pointer no matter data length */ - for (index = 0; index < 4; ++index) + for (index = 0; index < 4U; ++index) { - qtdPointer->bufferPointers[index] = ((dataAddress + (index + 1) * 4 * 1024) & 0xFFFFF000U); + qtdPointer->bufferPointers[index] = ((dataAddress + ((uint32_t)index + 1U) * 4U * 1024U) & 0xFFFFF000U); } dataAddress = endAddress; /* for next qtd */ - if (qtdPointer->nextQtdPointer == 0) + if (qtdPointer->nextQtdPointer == 0U) { break; } @@ -2093,24 +2063,25 @@ static usb_status_t USB_HostEhciQhQtdListInit(usb_host_ehci_instance_t *ehciInst transfer->next = NULL; if (vltQhPointer->ehciTransferHead == NULL) { - transfer->next = NULL; - vltQhPointer->ehciTransferHead = vltQhPointer->ehciTransferTail = transfer; + transfer->next = NULL; + vltQhPointer->ehciTransferTail = transfer; + vltQhPointer->ehciTransferHead = transfer; } else { - transfer->next = NULL; + transfer->next = NULL; vltQhPointer->ehciTransferTail->next = transfer; - vltQhPointer->ehciTransferTail = transfer; + vltQhPointer->ehciTransferTail = transfer; } USB_HostEhciLock(); /* link qtd to qh (link to end) */ entryPointer = &(vltQhPointer->nextQtdPointer); - dataAddress = *entryPointer; /* dataAddress variable means entry value here */ - while ((dataAddress) && (!(dataAddress & EHCI_HOST_T_INVALID_VALUE))) + dataAddress = *entryPointer; /* dataAddress variable means entry value here */ + while ((0U != dataAddress) && (0U == (dataAddress & EHCI_HOST_T_INVALID_VALUE))) { entryPointer = (volatile uint32_t *)dataAddress; - dataAddress = *entryPointer; + dataAddress = *entryPointer; } *entryPointer = (uint32_t)BaseQtdPointer; USB_HostEhciUnlock(); @@ -2126,7 +2097,7 @@ static uint32_t USB_HostEhciQtdListRelease(usb_host_ehci_instance_t *ehciInstanc uint32_t length = 0; usb_host_ehci_qtd_t *qtdPointer; - ehciQtdEnd->nextQtdPointer = 0; + ehciQtdEnd->nextQtdPointer = 0U; /* compute remaining length */ qtdPointer = ehciQtdStart; @@ -2141,7 +2112,7 @@ static uint32_t USB_HostEhciQtdListRelease(usb_host_ehci_instance_t *ehciInstanc /* put releasing qtd to idle qtd list */ USB_HostEhciLock(); - if (ehciInstance->ehciQtdNumber == 0) + if (ehciInstance->ehciQtdNumber == 0U) { ehciInstance->ehciQtdHead = ehciQtdStart; ehciInstance->ehciQtdTail = ehciQtdEnd; @@ -2149,7 +2120,7 @@ static uint32_t USB_HostEhciQtdListRelease(usb_host_ehci_instance_t *ehciInstanc else { ehciInstance->ehciQtdTail->nextQtdPointer = (uint32_t)ehciQtdStart; - ehciInstance->ehciQtdTail = ehciQtdEnd; + ehciInstance->ehciQtdTail = ehciQtdEnd; } while (ehciQtdStart != ehciQtdEnd) @@ -2169,37 +2140,41 @@ static usb_status_t USB_HostEhciQhQtdListDeinit(usb_host_ehci_instance_t *ehciIn volatile usb_host_ehci_qh_t *vltQhPointer; usb_host_transfer_t *transfer; usb_host_transfer_t *nextTransfer; - uint8_t needStop = 0; + uint32_t currentQtdPointer; + uint8_t needStop = 0U; vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; USB_HostEhciLock(); /* this API is called from APP, the host task may occupy to access the same resource */ /* remove qtd from qh */ - if ((!((uint32_t)vltQhPointer->nextQtdPointer & EHCI_HOST_T_INVALID_VALUE)) || - (!((uint32_t)vltQhPointer->currentQtdPointer & EHCI_HOST_T_INVALID_VALUE))) + /*for misra 13.5*/ + currentQtdPointer = vltQhPointer->currentQtdPointer; + if ((0U == ((uint32_t)vltQhPointer->nextQtdPointer & EHCI_HOST_T_INVALID_VALUE)) || + (0U == ((uint32_t)currentQtdPointer & EHCI_HOST_T_INVALID_VALUE))) { /* need stop async schedule */ - if ((!(vltQhPointer->horizontalLinkPointer & EHCI_HOST_T_INVALID_VALUE)) && + if ((0U == (vltQhPointer->horizontalLinkPointer & EHCI_HOST_T_INVALID_VALUE)) && (ehciPipePointer->pipeCommon.pipeType != USB_ENDPOINT_INTERRUPT)) { - needStop = 1; + needStop = 1U; } - if (needStop) + if (0U != needStop) { USB_HostEhciStopAsync(ehciInstance); } vltQhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* invalid current qtd */ - vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* invalid next qtd */ + vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* invalid next qtd */ vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */ - if (needStop) + if (0U != needStop) { USB_HostEhciStartAsync(ehciInstance); } } /* remove transfer from the QH transfer list */ - transfer = vltQhPointer->ehciTransferHead; - vltQhPointer->ehciTransferHead = vltQhPointer->ehciTransferTail = NULL; + transfer = vltQhPointer->ehciTransferHead; + vltQhPointer->ehciTransferTail = NULL; + vltQhPointer->ehciTransferHead = NULL; USB_HostEhciUnlock(); /* release qtd and transfer callback*/ @@ -2210,8 +2185,9 @@ static usb_status_t USB_HostEhciQhQtdListDeinit(usb_host_ehci_instance_t *ehciIn USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead), (usb_host_ehci_qtd_t *)(transfer->union2.unitTail)); transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ? - 0 : + 0U : (transfer->transferLength - transfer->transferSofar); + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel); transfer = nextTransfer; } @@ -2233,13 +2209,14 @@ static usb_status_t USB_HostEhciTransferQtdListDeinit(usb_host_ehci_instance_t * USB_HostEhciLock(); /* this API is called from APP, the host task may occupy to access the same resource */ /* remove qtd from qh */ - qhNextQtdValue = (uint32_t)vltQhPointer->currentQtdPointer; + qhNextQtdValue = (uint32_t)vltQhPointer->currentQtdPointer; qtdPointerEntry = *((uint32_t *)qhNextQtdValue + 2); /* note: qtdPointerEntry means qtd status */ - if ((qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE) || (!(qtdPointerEntry & EHCI_HOST_QTD_STATUS_ACTIVE_MASK))) + if ((0U != (qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE)) || + (0U == (qtdPointerEntry & EHCI_HOST_QTD_STATUS_ACTIVE_MASK))) { qhNextQtdValue = (uint32_t)vltQhPointer->nextQtdPointer; } - if (!(qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE)) /* there is pending qtd in the qh */ + if (0U == (qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE)) /* there is pending qtd in the qh */ { /* this qh don't schedule temporarily */ if (ehciPipePointer->pipeCommon.pipeType != USB_ENDPOINT_INTERRUPT) @@ -2255,11 +2232,11 @@ static usb_status_t USB_HostEhciTransferQtdListDeinit(usb_host_ehci_instance_t * /* remove qtd from qh one by one */ qtdPointerEntry = transfer->union1.unitHead; - while (1) + while (1U == 1U) { /* search qh's qtd list for qtdPointerEntry */ searchQtdEntryPointer = &qhNextQtdValue; - while (!((*searchQtdEntryPointer) & EHCI_HOST_T_INVALID_VALUE)) + while (0U == ((*searchQtdEntryPointer) & EHCI_HOST_T_INVALID_VALUE)) { if ((*searchQtdEntryPointer) == qtdPointerEntry) { @@ -2306,13 +2283,15 @@ static usb_status_t USB_HostEhciTransferQtdListDeinit(usb_host_ehci_instance_t * transfer->transferSofar = USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead), (usb_host_ehci_qtd_t *)(transfer->union2.unitTail)); - transfer->transferSofar = - (transfer->transferLength < transfer->transferSofar) ? 0 : (transfer->transferLength - transfer->transferSofar); + transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ? + 0U : + (transfer->transferLength - transfer->transferSofar); + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel); /* start this qh schedule */ vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */ - if ((qhNextQtdValue != 0) && (!(qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE))) + if ((qhNextQtdValue != 0U) && (0U == (qhNextQtdValue & EHCI_HOST_T_INVALID_VALUE))) { vltQhPointer->nextQtdPointer = qhNextQtdValue; } @@ -2323,9 +2302,14 @@ static usb_status_t USB_HostEhciTransferQtdListDeinit(usb_host_ehci_instance_t * static usb_status_t USB_HostEhciQhInit(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer) { usb_host_ehci_qh_t *qhPointer = NULL; - uint32_t address, speed, portNumber, hubNumber; - uint32_t controlBits1 = 0; - uint32_t controlBits2 = 0; + uint32_t address = 0; + uint32_t speed = 0; + uint32_t portNumber = 0; + uint32_t hubNumber = 0; + ; + uint32_t controlBits1 = 0U; + uint32_t controlBits2 = 0U; + /* get qh */ USB_HostEhciLock(); if (ehciInstance->ehciQhList != NULL) @@ -2345,26 +2329,27 @@ static usb_status_t USB_HostEhciQhInit(usb_host_ehci_instance_t *ehciInstance, u ehciPipePointer->ehciQh = (void *)qhPointer; /* initialize qh */ - USB_HostEhciZeroMem((uint32_t *)qhPointer, sizeof(usb_host_ehci_qh_t) / 4); - qhPointer->horizontalLinkPointer = EHCI_HOST_T_INVALID_VALUE; - qhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE; - qhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; + USB_HostEhciZeroMem((void *)qhPointer, sizeof(usb_host_ehci_qh_t) / 4U); + qhPointer->horizontalLinkPointer = EHCI_HOST_T_INVALID_VALUE; + qhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE; + qhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; qhPointer->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE; - qhPointer->ehciPipePointer = ehciPipePointer; - qhPointer->timeOutLabel = 0; - qhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, &speed); + qhPointer->ehciPipePointer = ehciPipePointer; + qhPointer->timeOutLabel = 0; + qhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); /* initialize staticEndpointStates[0] */ if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT) { /* Software should set the RL field to zero if the queue head is an interrupt endpoint. */ - controlBits1 |= ((0U << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK); + controlBits1 |= ((0UL << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK); } else { - if (ehciPipePointer->pipeCommon.nakCount >= 16) + if (ehciPipePointer->pipeCommon.nakCount >= 16U) { - controlBits1 |= ((15U << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK); + controlBits1 |= ((15UL << EHCI_HOST_QH_RL_SHIFT) & EHCI_HOST_QH_RL_MASK); } else { @@ -2376,15 +2361,15 @@ static usb_status_t USB_HostEhciQhInit(usb_host_ehci_instance_t *ehciInstance, u { if (speed != USB_SPEED_HIGH) { - controlBits1 |= (1 << EHCI_HOST_QH_C_SHIFT); + controlBits1 |= (1UL << EHCI_HOST_QH_C_SHIFT); } - controlBits1 |= (1 << EHCI_HOST_QH_DTC_SHIFT); + controlBits1 |= (1UL << EHCI_HOST_QH_DTC_SHIFT); } controlBits1 |= ((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize << EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT); controlBits1 |= (speed << EHCI_HOST_QH_EPS_SHIFT); controlBits1 |= ((uint32_t)ehciPipePointer->pipeCommon.endpointAddress << EHCI_HOST_QH_ENDPT_SHIFT); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress, - &address); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceAddress, &address); controlBits1 |= (address << EHCI_HOST_QH_DEVICE_ADDRESS_SHIFT); qhPointer->staticEndpointStates[0] = controlBits1; if (speed == USB_SPEED_HIGH) @@ -2393,22 +2378,22 @@ static usb_status_t USB_HostEhciQhInit(usb_host_ehci_instance_t *ehciInstance, u } else { - controlBits2 |= (0x00000001U << EHCI_HOST_QH_MULT_SHIFT); + controlBits2 |= (0x00000001UL << EHCI_HOST_QH_MULT_SHIFT); } /*initialize staticEndpointStates[1] */ if (speed != USB_SPEED_HIGH) { - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubNumber, - &hubNumber); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHSHubPort, - &portNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHSHubNumber, &hubNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHSHubPort, &portNumber); } else { - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHubNumber, - &hubNumber); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDevicePortNumber, - &portNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHubNumber, &hubNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDevicePortNumber, &portNumber); } controlBits2 |= (portNumber << EHCI_HOST_QH_PORT_NUMBER_SHIFT); controlBits2 |= (hubNumber << EHCI_HOST_QH_HUB_ADDR_SHIFT); @@ -2425,12 +2410,12 @@ static usb_status_t USB_HostEhciQhDeinit(usb_host_ehci_instance_t *ehciInstance, qhPointer = (usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* de-initialize qtd from qh */ - USB_HostEhciQhQtdListDeinit(ehciInstance, ehciPipePointer); + (void)USB_HostEhciQhQtdListDeinit(ehciInstance, ehciPipePointer); /* release QH */ USB_HostEhciLock(); qhPointer->horizontalLinkPointer = (uint32_t)ehciInstance->ehciQhList; - ehciInstance->ehciQhList = qhPointer; + ehciInstance->ehciQhList = qhPointer; USB_HostEhciUnlock(); return kStatus_USB_Success; @@ -2443,17 +2428,19 @@ static void USB_HostEhciAddQhToFrame(usb_host_ehci_instance_t *ehciInstance, { volatile uint32_t *frameEntryPointer; uint32_t frameEntryValue; + void *temp; /* search for the inserting point by interval */ - frameEntryPointer = (volatile uint32_t *)(&((uint32_t *)ehciInstance->ehciFrameList)[framePos]); - while (frameEntryPointer) + temp = (void *)ehciInstance->ehciFrameList; + frameEntryPointer = (volatile uint32_t *)(&((uint32_t *)temp)[framePos]); + while (NULL != frameEntryPointer) { frameEntryValue = *frameEntryPointer; - if (frameEntryValue & EHCI_HOST_T_INVALID_VALUE) + if (0U != (frameEntryValue & EHCI_HOST_T_INVALID_VALUE)) { /* insert into the end */ *((uint32_t *)entryPointerValue) = EHCI_HOST_T_INVALID_VALUE; - *frameEntryPointer = (entryPointerValue | EHCI_HOST_POINTER_TYPE_QH); + *frameEntryPointer = (entryPointerValue | EHCI_HOST_POINTER_TYPE_QH); break; } @@ -2467,7 +2454,7 @@ static void USB_HostEhciAddQhToFrame(usb_host_ehci_instance_t *ehciInstance, { /* insert into this point */ *((uint32_t *)entryPointerValue) = frameEntryValue; - *frameEntryPointer = (entryPointerValue | EHCI_HOST_POINTER_TYPE_QH); + *frameEntryPointer = (entryPointerValue | EHCI_HOST_POINTER_TYPE_QH); return; } else @@ -2483,14 +2470,15 @@ static void USB_HostEhciRemoveFromFrame(usb_host_ehci_instance_t *ehciInstance, { volatile uint32_t *frameEntryPointer; uint32_t frameEntryValue; - + void *temp; /* search for the qh/itd/sitd entry */ - frameEntryPointer = (volatile uint32_t *)(&((uint32_t *)ehciInstance->ehciFrameList)[framePos]); + temp = (void *)ehciInstance->ehciFrameList; + frameEntryPointer = (volatile uint32_t *)(&((uint32_t *)temp)[framePos]); - while (frameEntryPointer) + while (NULL != frameEntryPointer) { frameEntryValue = *frameEntryPointer; - if (frameEntryValue & EHCI_HOST_T_INVALID_VALUE) + if (0U != (frameEntryValue & EHCI_HOST_T_INVALID_VALUE)) { return; } @@ -2517,53 +2505,71 @@ static void USB_HostEhciLinkSitd(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_sitd_t *sitdPointer; uint32_t distance; uint32_t frameInterval; - int32_t shouldLinkFrame; - int32_t currentFrame; + uint32_t shouldLinkFrame; + uint32_t currentFrame; + void *temp; - frameInterval = (ehciPipePointer->uframeInterval >> 3); + frameInterval = ((uint32_t)ehciPipePointer->uframeInterval >> 3U); - if (isoPointer->lastLinkFrame == 0xFFFF) /* first link */ + if (isoPointer->lastLinkFrame == 0xFFFFU) /* first link */ { - currentFrame = ((ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE) >> 3); + currentFrame = ((ehciInstance->ehciIpBase->FRINDEX & USB_HOST_EHCI_MAX_MICRFRAME_VALUE) >> 3U); currentFrame = ((uint32_t)(currentFrame + USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER) & - (EHCI_MAX_UFRAME_VALUE >> 3)); /* add USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER */ + (USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3U)); /* add USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER */ /* frame should align with interval */ - currentFrame -= ehciPipePointer->startFrame; - currentFrame = - ((uint32_t)(currentFrame + frameInterval - 1) & (~(frameInterval - 1))); /* frameInterval is power of 2 */ - currentFrame += ehciPipePointer->startFrame; + if (currentFrame <= ehciPipePointer->startFrame) + { + currentFrame = ehciPipePointer->startFrame; + } + else + { + currentFrame -= ehciPipePointer->startFrame; + currentFrame = ((currentFrame + frameInterval - 1U) & (~(frameInterval - 1U))); + currentFrame += ehciPipePointer->startFrame; + } } else { shouldLinkFrame = isoPointer->lastLinkFrame + frameInterval; /* continuous next should link frame */ - if (shouldLinkFrame > (int32_t)(EHCI_MAX_UFRAME_VALUE >> 3)) + if (shouldLinkFrame > USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3U) { - shouldLinkFrame = shouldLinkFrame - ((EHCI_MAX_UFRAME_VALUE >> 3) + 1); + shouldLinkFrame = shouldLinkFrame - ((USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3U) + 1U); } - currentFrame = ((ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE) >> 3); - distance = ((shouldLinkFrame - currentFrame + (EHCI_MAX_UFRAME_VALUE >> 3) + 1) & - (EHCI_MAX_UFRAME_VALUE >> 3)); /* get the distance from shouldLinkFrame to currentFrame */ + currentFrame = ((ehciInstance->ehciIpBase->FRINDEX & USB_HOST_EHCI_MAX_MICRFRAME_VALUE) >> 3U); + distance = + ((shouldLinkFrame + (USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3U) + 1U - currentFrame) & + (USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3)); /* get the distance from shouldLinkFrame to currentFrame */ /* shouldLinkFrame has add frameInterval, think about the align with interval, so here add (frameInterval * * 2) */ - if ((distance <= (USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER + frameInterval * 2)) && (distance > 0)) + if ((distance <= + (USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER + frameInterval * USB_HOST_EHCI_ISO_MAX_CONTINUOUS_TRANSFER)) && + (distance > 0U)) { currentFrame = shouldLinkFrame; } else /* re-link */ { currentFrame = - ((uint32_t)(currentFrame + USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER) & (EHCI_MAX_UFRAME_VALUE >> 3)); - if (currentFrame > (int32_t)(EHCI_MAX_UFRAME_VALUE >> 3)) + ((currentFrame + USB_HOST_EHCI_ISO_BOUNCE_FRAME_NUMBER) & (USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3)); + + /*if (currentFrame > (USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3)) { - currentFrame = currentFrame - ((EHCI_MAX_UFRAME_VALUE >> 3) + 1); - } + currentFrame = currentFrame - ((USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3) + 1U); + }*/ /* frame should align with interval */ - currentFrame -= ehciPipePointer->startFrame; - currentFrame = ((uint32_t)(currentFrame + frameInterval - 1) & (~(frameInterval - 1))); - currentFrame += ehciPipePointer->startFrame; + if (currentFrame <= ehciPipePointer->startFrame) + { + currentFrame = ehciPipePointer->startFrame; + } + else + { + currentFrame -= ehciPipePointer->startFrame; + currentFrame = ((currentFrame + frameInterval - 1U) & (~(frameInterval - 1U))); + currentFrame += ehciPipePointer->startFrame; + } } } - if (currentFrame >= (int32_t)USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE) /* frame turn around */ + if (currentFrame >= USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE) /* frame turn around */ { shouldLinkFrame = (currentFrame - USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE); /* shouldLinkFrame means inserted frame position */ @@ -2574,14 +2580,14 @@ static void USB_HostEhciLinkSitd(usb_host_ehci_instance_t *ehciInstance, } sitdPointer = (usb_host_ehci_sitd_t *)startEntryPointer; - while (sitdPointer) + while (NULL != sitdPointer) { - sitdPointer->frameEntryIndex = shouldLinkFrame; + sitdPointer->frameEntryIndex = (uint16_t)shouldLinkFrame; /* add to frame list head */ - sitdPointer->nextLinkPointer = ((uint32_t *)ehciInstance->ehciFrameList)[shouldLinkFrame]; - ((uint32_t *)ehciInstance->ehciFrameList)[shouldLinkFrame] = - ((uint32_t)sitdPointer | EHCI_HOST_POINTER_TYPE_SITD); - if (sitdPointer->nextSitdIndex == 0xFF) /* 0xFF is invalid value */ + temp = (void *)ehciInstance->ehciFrameList; + sitdPointer->nextLinkPointer = ((uint32_t *)temp)[shouldLinkFrame]; + ((uint32_t *)temp)[shouldLinkFrame] = ((uint32_t)sitdPointer | EHCI_HOST_POINTER_TYPE_SITD); + if (sitdPointer->nextSitdIndex == 0xFFU) /* 0xFF is invalid value */ { break; } @@ -2589,17 +2595,17 @@ static void USB_HostEhciLinkSitd(usb_host_ehci_instance_t *ehciInstance, shouldLinkFrame += frameInterval; currentFrame += frameInterval; - if (shouldLinkFrame >= (int32_t)USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE) + if (shouldLinkFrame >= USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE) { shouldLinkFrame = (shouldLinkFrame - USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE); } } - if (currentFrame > (int32_t)(EHCI_MAX_UFRAME_VALUE >> 3)) + if (currentFrame > (USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3)) { - currentFrame = currentFrame - ((EHCI_MAX_UFRAME_VALUE >> 3) + 1); + currentFrame = currentFrame - ((USB_HOST_EHCI_MAX_MICRFRAME_VALUE >> 3) + 1U); } - isoPointer->lastLinkFrame = currentFrame; /* save the last link frame value */ + isoPointer->lastLinkFrame = (uint16_t)currentFrame; /* save the last link frame value */ } static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInstance, @@ -2612,33 +2618,35 @@ static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInst uint32_t dataLength = 0; uint32_t sitdLength = 0; uint32_t dataBufferValue; - uint32_t hubNumber; - uint32_t portNumber; - uint32_t address; + uint32_t hubNumber = 0U; + uint32_t portNumber = 0U; + uint32_t address = 0U; uint32_t tmp; - uint8_t index; + uint32_t *temp; + uint32_t index; + int32_t tempIndex; + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceAddress, &address); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress, - &address); - - sitdNumber = ((transfer->transferLength - 1 + (ehciPipePointer->pipeCommon.maxPacketSize)) / + sitdNumber = ((transfer->transferLength - 1U + (ehciPipePointer->pipeCommon.maxPacketSize)) / (ehciPipePointer->pipeCommon.maxPacketSize)); /* get sitd array */ - tmp = ehciPipePointer - ehciInstance->ehciPipeIndexBase; /* pipe index */ /* USB_HostEhciLock(); */ if (ehciInstance->ehciSitdNumber >= sitdNumber) { - sitdPointer = ehciInstance->ehciSitdList; + sitdPointer = ehciInstance->ehciSitdList; transfer->union1.unitHead = (uint32_t)sitdPointer; - for (index = 1; index < sitdNumber; ++index) + for (index = 1U; index < sitdNumber; ++index) { - sitdPointer->nextSitdIndex = - (((usb_host_ehci_sitd_t *)sitdPointer->nextLinkPointer) - ehciInstance->ehciSitdIndexBase); - sitdPointer = (usb_host_ehci_sitd_t *)sitdPointer->nextLinkPointer; + /*misra 10.8*/ + tempIndex = (((usb_host_ehci_sitd_t *)(sitdPointer->nextLinkPointer & 0xFFFFFFFEU)) - + ehciInstance->ehciSitdIndexBase); + sitdPointer->nextSitdIndex = (uint8_t)tempIndex; + sitdPointer = (usb_host_ehci_sitd_t *)(sitdPointer->nextLinkPointer & 0xFFFFFFFEU); } sitdPointer->nextSitdIndex = 0xFF; - ehciInstance->ehciSitdList = (usb_host_ehci_sitd_t *)sitdPointer->nextLinkPointer; - ehciInstance->ehciSitdNumber -= sitdNumber; + ehciInstance->ehciSitdList = (usb_host_ehci_sitd_t *)(sitdPointer->nextLinkPointer & 0xFFFFFFFEU); + ehciInstance->ehciSitdNumber -= (uint8_t)sitdNumber; } else { @@ -2648,15 +2656,16 @@ static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInst /* USB_HostEhciUnlock(); */ transfer->union2.unitTail = (uint32_t)sitdPointer; /* initialize sitd array */ - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceHubNumber, - &hubNumber); - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDevicePortNumber, - &portNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceHubNumber, &hubNumber); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDevicePortNumber, &portNumber); sitdPointer = (usb_host_ehci_sitd_t *)transfer->union1.unitHead; - dataLength = transfer->transferLength; - while (sitdNumber--) + dataLength = transfer->transferLength; + while (0U != sitdNumber) { - USB_HostEhciZeroMem((uint32_t *)sitdPointer, 7); + sitdNumber--; + USB_HostEhciZeroMem((void *)sitdPointer, 7); sitdLength = dataLength; if (sitdLength > ehciPipePointer->pipeCommon.maxPacketSize) { @@ -2665,7 +2674,7 @@ static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInst dataBufferValue = (uint32_t)(transfer->transferBuffer + (transfer->transferLength - dataLength)); dataLength -= sitdLength; /* update left data length */ sitdPointer->transferResults[1] = dataBufferValue; - sitdPointer->transferResults[2] = ((dataBufferValue + 4 * 1024) & 0xFFFFF000U); + sitdPointer->transferResults[2] = ((dataBufferValue + 4U * 1024U) & 0xFFFFF000U); sitdPointer->endpointStates[0] = (((uint32_t)ehciPipePointer->pipeCommon.direction << EHCI_HOST_SITD_DIRECTION_SHIFT) | (portNumber << EHCI_HOST_SITD_PORT_NUMBER_SHIFT) | (hubNumber << EHCI_HOST_SITD_HUB_ADDR_SHIFT) | @@ -2679,14 +2688,14 @@ static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInst sitdPointer->endpointStates[1] = (((uint32_t)ehciPipePointer->uframeCmask << EHCI_HOST_SITD_CMASK_SHIFT) | ((uint32_t)ehciPipePointer->uframeSmask << EHCI_HOST_SITD_SMASK_SHIFT)); - tmp = (sitdLength + 187) / 188; - if (tmp > 1) + tmp = (sitdLength + 187U) / 188U; + if (tmp > 1U) { - sitdPointer->transferResults[2] |= (0x01 << EHCI_HOST_SITD_TP_SHIFT); /* for iso split */ + sitdPointer->transferResults[2] |= (0x01U << EHCI_HOST_SITD_TP_SHIFT); /* for iso split */ } else { - sitdPointer->transferResults[2] |= (0x00 << EHCI_HOST_SITD_TP_SHIFT); /* for iso split */ + sitdPointer->transferResults[2] |= (0x00U << EHCI_HOST_SITD_TP_SHIFT); /* for iso split */ } sitdPointer->transferResults[2] |= (tmp << EHCI_HOST_SITD_TCOUNT_SHIFT); /* for iso split */ } @@ -2696,26 +2705,29 @@ static usb_status_t USB_HostEhciSitdArrayInit(usb_host_ehci_instance_t *ehciInst sitdPointer = (ehciInstance->ehciSitdIndexBase + sitdPointer->nextSitdIndex); } sitdPointer = (usb_host_ehci_sitd_t *)transfer->union2.unitTail; - sitdPointer->transferResults[0] |= (1U << EHCI_HOST_SITD_IOC_SHIFT); /* last set IOC */ + sitdPointer->transferResults[0] |= (1UL << EHCI_HOST_SITD_IOC_SHIFT); /* last set IOC */ /* link transfer to usb_host_ehci_iso_t transfer list */ isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh; USB_HostEhciLock(); if (isoPointer->ehciTransferHead == NULL) { - transfer->next = NULL; - isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = transfer; + transfer->next = NULL; + isoPointer->ehciTransferTail = transfer; + isoPointer->ehciTransferHead = transfer; } else { - transfer->next = NULL; + transfer->next = NULL; isoPointer->ehciTransferTail->next = transfer; - isoPointer->ehciTransferTail = transfer; + isoPointer->ehciTransferTail = transfer; } USB_HostEhciUnlock(); /* link itd to frame list (note: initialize frameEntryIndex)*/ - USB_HostEhciLinkSitd(ehciInstance, ehciPipePointer, (void *)transfer->union1.unitHead); + /*misra 11.6*/ + temp = (uint32_t *)(transfer->union1.unitHead); + USB_HostEhciLinkSitd(ehciInstance, ehciPipePointer, (void *)temp); return kStatus_USB_Success; } @@ -2725,9 +2737,9 @@ static uint32_t USB_HostEhciSitdArrayRelease(usb_host_ehci_instance_t *ehciInsta usb_host_ehci_sitd_t *endSitdPointer) { usb_host_ehci_sitd_t *sitdPointer = startSitdPointer; - uint32_t leftLength = 0; + uint32_t leftLength = 0; /* remove itd from frame list */ - while (1) + while (1U == 1U) { /* record the transfer's result length */ leftLength += @@ -2737,8 +2749,9 @@ static uint32_t USB_HostEhciSitdArrayRelease(usb_host_ehci_instance_t *ehciInsta /* release itd */ /* USB_HostEhciLock(); */ - sitdPointer->nextLinkPointer = (uint32_t)ehciInstance->ehciSitdList; - ehciInstance->ehciSitdList = sitdPointer; + /*set next link pointer to invalid in case hardware access invalid sitd structure in special case*/ + sitdPointer->nextLinkPointer = (((uint32_t)ehciInstance->ehciSitdList) | EHCI_HOST_T_INVALID_VALUE); + ehciInstance->ehciSitdList = sitdPointer; ehciInstance->ehciSitdNumber++; /* USB_HostEhciUnlock(); */ @@ -2762,8 +2775,9 @@ static usb_status_t USB_HostEhciSitdArrayDeinit(usb_host_ehci_instance_t *ehciIn /* firstly remove the transfer (because host task may occupy to access the resource) */ USB_HostEhciLock(); - transfer = isoPointer->ehciTransferHead; - isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = NULL; + transfer = isoPointer->ehciTransferHead; + isoPointer->ehciTransferTail = NULL; + isoPointer->ehciTransferHead = NULL; USB_HostEhciUnlock(); while (transfer != NULL) @@ -2774,7 +2788,7 @@ static usb_status_t USB_HostEhciSitdArrayDeinit(usb_host_ehci_instance_t *ehciIn transfer->transferLength - USB_HostEhciSitdArrayRelease(ehciInstance, (usb_host_ehci_sitd_t *)transfer->union1.unitHead, (usb_host_ehci_sitd_t *)transfer->union2.unitTail); - /* transfer callback */ + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel); /* next transfer */ transfer = nextTransfer; @@ -2790,50 +2804,66 @@ static uint32_t USB_HostEhciGetItdLinkFrame(usb_host_ehci_instance_t *ehciInstan uint16_t startUframe, uint16_t uframeInterval) { - int32_t shouldLinkUframe; - int32_t currentUframe; - int32_t distance; + uint32_t shouldLinkUframe; + uint32_t currentUframe; + uint32_t distance; - if (lastLinkUframe != 0xFFFF) + if (lastLinkUframe != 0xFFFFU) { shouldLinkUframe = lastLinkUframe + uframeInterval; - if (shouldLinkUframe > (int32_t)EHCI_MAX_UFRAME_VALUE) + if (shouldLinkUframe > USB_HOST_EHCI_MAX_MICRFRAME_VALUE) { - shouldLinkUframe = shouldLinkUframe - (EHCI_MAX_UFRAME_VALUE + 1); + shouldLinkUframe = shouldLinkUframe - (USB_HOST_EHCI_MAX_MICRFRAME_VALUE + 1U); } - currentUframe = (ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); - distance = ((shouldLinkUframe - currentUframe + EHCI_MAX_UFRAME_VALUE + 1) & - EHCI_MAX_UFRAME_VALUE); /* get the distance */ + currentUframe = (ehciInstance->ehciIpBase->FRINDEX & USB_HOST_EHCI_MAX_MICRFRAME_VALUE); + distance = ((shouldLinkUframe + USB_HOST_EHCI_MAX_MICRFRAME_VALUE + 1U - currentUframe) & + USB_HOST_EHCI_MAX_MICRFRAME_VALUE); /* get the distance */ /* shouldLinkUframe has add uframeInterval, think about the align with interval, so here add (uframeInterval * * 2) */ - if ((distance <= (int32_t)(USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER + (uframeInterval * 2))) && (distance > 2)) + if ((distance <= ((uint32_t)USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER + + ((uint32_t)uframeInterval * USB_HOST_EHCI_ISO_MAX_CONTINUOUS_TRANSFER))) && + (distance > 2U)) { currentUframe = shouldLinkUframe; } else /* re-link */ { currentUframe = - ((uint32_t)(currentUframe + USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER) & EHCI_MAX_UFRAME_VALUE); - if (currentUframe > (int32_t)EHCI_MAX_UFRAME_VALUE) + ((currentUframe + USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER) & USB_HOST_EHCI_MAX_MICRFRAME_VALUE); + /*if (currentUframe > USB_HOST_EHCI_MAX_MICRFRAME_VALUE) { - currentUframe = currentUframe - (EHCI_MAX_UFRAME_VALUE + 1); - } + currentUframe = currentUframe - (USB_HOST_EHCI_MAX_MICRFRAME_VALUE + 1U); + }*/ /* uframe should align with interval */ - currentUframe -= startUframe; - currentUframe = ((uint32_t)(currentUframe + uframeInterval - 1) & - (~((uint32_t)uframeInterval - 1))); /* uframeInterval is power of 2 */ - currentUframe += startUframe; + if (currentUframe <= startUframe) + { + currentUframe = startUframe; + } + else + { + currentUframe -= startUframe; + currentUframe = ((uint32_t)(currentUframe + uframeInterval) & + (~((uint32_t)uframeInterval - 1U))); /* uframeInterval is power of 2 */ + currentUframe += startUframe; + } } } else { - currentUframe = (ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); - currentUframe = ((uint32_t)(currentUframe + USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER) & EHCI_MAX_UFRAME_VALUE); + currentUframe = (ehciInstance->ehciIpBase->FRINDEX & USB_HOST_EHCI_MAX_MICRFRAME_VALUE); + currentUframe = ((currentUframe + USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER) & USB_HOST_EHCI_MAX_MICRFRAME_VALUE); /* uframe should align with interval */ - currentUframe -= startUframe; - currentUframe = ((uint32_t)(currentUframe + uframeInterval - 1) & - (~((uint32_t)uframeInterval - 1))); /* uframeInterval is power of 2 */ - currentUframe += startUframe; + if (currentUframe <= startUframe) + { + currentUframe = startUframe; + } + else + { + currentUframe -= startUframe; + currentUframe = + ((currentUframe + uframeInterval) & (~(uframeInterval - 1U))); /* uframeInterval is power of 2 */ + currentUframe += startUframe; + } } return currentUframe; @@ -2845,27 +2875,29 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta { usb_host_ehci_iso_t *isoPointer; usb_host_ehci_itd_t *itdPointer = NULL; + usb_host_ehci_itd_t *itdHead = NULL; usb_host_ehci_itd_t *tmpItdPointer; uint32_t dataLength; /* the remaining data for sending */ uint32_t transactionLength; /* the initializing transaction descriptor data length */ uint32_t itdBufferValue; uint32_t itdBufferBaseValue; /* for calculating PG value */ - uint32_t address; + uint32_t address = 0U; uint32_t lastShouldLinkUframe; uint32_t linkUframe; - uint32_t minDataPerItd = ehciPipePointer->pipeCommon.numberPerUframe * ehciPipePointer->pipeCommon.maxPacketSize; + uint32_t minDataPerItd = + (uint32_t)ehciPipePointer->pipeCommon.numberPerUframe * ehciPipePointer->pipeCommon.maxPacketSize; uint8_t maxItdNumber; - uint8_t index = 0; + uint16_t index = 0; isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress, - &address); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceAddress, &address); /* max needed itd number, the actual needed number may be less because micro-frame interval may be less than 8 */ - maxItdNumber = ((transfer->transferLength - 1 + minDataPerItd) / minDataPerItd); - if (ehciPipePointer->uframeInterval < 8) + maxItdNumber = (uint8_t)((transfer->transferLength - 1U + minDataPerItd) / minDataPerItd); + if (ehciPipePointer->uframeInterval < 8U) { - maxItdNumber = ((maxItdNumber * ehciPipePointer->uframeInterval + 7) / 8) + 1; + maxItdNumber = (uint8_t)((maxItdNumber * ehciPipePointer->uframeInterval + 7U) / 8U) + 1U; } if (maxItdNumber > ehciInstance->ehciItdNumber) { @@ -2877,43 +2909,46 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta /* USB_HostEhciLock(); */ if (isoPointer->ehciTransferHead == NULL) { - isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = transfer; + isoPointer->ehciTransferTail = transfer; + isoPointer->ehciTransferHead = transfer; } else { isoPointer->ehciTransferTail->next = transfer; - isoPointer->ehciTransferTail = transfer; + isoPointer->ehciTransferTail = transfer; } /* USB_HostEhciUnlock(); */ - dataLength = transfer->transferLength; - transfer->union1.unitHead = (uint32_t)NULL; + dataLength = transfer->transferLength; + transfer->union1.unitHead = 0U; /* get the link micro-frame */ lastShouldLinkUframe = USB_HostEhciGetItdLinkFrame( ehciInstance, isoPointer->lastLinkFrame, (uint16_t)((ehciPipePointer->startFrame << 3) + ehciPipePointer->startUframe), ehciPipePointer->uframeInterval); - if (lastShouldLinkUframe > EHCI_MAX_UFRAME_VALUE) + if (lastShouldLinkUframe > USB_HOST_EHCI_MAX_MICRFRAME_VALUE) { - linkUframe = lastShouldLinkUframe - (EHCI_MAX_UFRAME_VALUE + 1); + linkUframe = lastShouldLinkUframe - (USB_HOST_EHCI_MAX_MICRFRAME_VALUE + 1U); } else { linkUframe = lastShouldLinkUframe; } - while (dataLength) + itdHead = ehciInstance->ehciItdList; + while (0U != dataLength) { /* get one idle itd */ tmpItdPointer = ehciInstance->ehciItdList; - ehciInstance->ehciItdList = (usb_host_ehci_itd_t *)tmpItdPointer->nextLinkPointer; - ehciInstance->ehciItdNumber -= 1; if (tmpItdPointer == NULL) { return kStatus_USB_Error; /* this should not reach */ } + ehciInstance->ehciItdList = (usb_host_ehci_itd_t *)tmpItdPointer->nextItdPointer; + ehciInstance->ehciItdNumber -= 1U; + tmpItdPointer->nextItdPointer = NULL; /* use the itd */ - if (transfer->union1.unitHead == (uint32_t)NULL) /* first itd */ + if (transfer->union1.unitHead == 0U) /* first itd */ { transfer->union1.unitHead = (uint32_t)tmpItdPointer; } @@ -2924,11 +2959,11 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta itdPointer = tmpItdPointer; /* itd has been set to all zero when releasing */ - itdBufferBaseValue = itdBufferValue = - (uint32_t)(transfer->transferBuffer + (transfer->transferLength - dataLength)); - for (index = 0; index < 7; ++index) + itdBufferValue = (uint32_t)(transfer->transferBuffer + (transfer->transferLength - dataLength)); + itdBufferBaseValue = itdBufferValue; + for (index = 0; index < 7U; ++index) { - itdPointer->bufferPointers[index] = ((itdBufferBaseValue + (index * 4 * 1024)) & 0xFFFFF000U); + itdPointer->bufferPointers[index] = ((itdBufferBaseValue + ((uint32_t)index * 4U * 1024U)) & 0xFFFFF000U); } /* initialize iTD common fields */ itdPointer->bufferPointers[0] |= @@ -2939,7 +2974,7 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta ((uint32_t)ehciPipePointer->pipeCommon.maxPacketSize << EHCI_HOST_ITD_MAX_PACKET_SIZE_SHIFT)); itdPointer->bufferPointers[2] |= (ehciPipePointer->pipeCommon.numberPerUframe); /* initialize transaction descriptors */ - for (index = (linkUframe & 0x0007); index < 8; index += ehciPipePointer->uframeInterval) + for (index = (uint8_t)(linkUframe & 0x0007U); index < 8U; index += ehciPipePointer->uframeInterval) { transactionLength = ((dataLength > minDataPerItd) ? minDataPerItd : dataLength); /* initialize the uframeIndex's transaction descriptor in itd */ @@ -2951,7 +2986,7 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta (itdBufferValue & EHCI_HOST_ITD_TRANSACTION_OFFSET_MASK)); dataLength -= transactionLength; itdBufferValue += transactionLength; - if (dataLength <= 0) + if (dataLength <= 0U) { break; } @@ -2959,17 +2994,25 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta } transfer->union2.unitTail = (uint32_t)itdPointer; - itdPointer->transactions[index] |= (1 << EHCI_HOST_ITD_IOC_SHIFT); /* last set IOC */ + itdPointer->transactions[index] |= (1UL << EHCI_HOST_ITD_IOC_SHIFT); /* last set IOC */ + itdPointer = itdHead; /* link itd to frame list (note: initialize frameEntryIndex)*/ - while (itdPointer) + while (NULL != itdPointer) { - itdPointer->frameEntryIndex = linkUframe; - /* add to frame head */ - itdPointer->nextLinkPointer = ((uint32_t *)ehciInstance->ehciFrameList)[linkUframe >> 3]; - *(uint32_t *)((uint32_t *)ehciInstance->ehciFrameList)[linkUframe >> 3] = - ((uint32_t)itdPointer | EHCI_HOST_POINTER_TYPE_ITD); - itdPointer = itdPointer->nextItdPointer; + void *temp = (void *)ehciInstance->ehciFrameList; + uint32_t *linkPointer = &((uint32_t *)temp)[linkUframe >> 3]; + uint32_t linkValue = *linkPointer; + itdPointer->frameEntryIndex = linkUframe >> 3; + while ((0U == (linkValue & EHCI_HOST_T_INVALID_VALUE)) && + ((linkValue & EHCI_HOST_POINTER_TYPE_MASK) == EHCI_HOST_POINTER_TYPE_ITD)) + { + linkPointer = (uint32_t *)(linkValue & EHCI_HOST_POINTER_ADDRESS_MASK); + linkValue = *linkPointer; + } + itdPointer->nextLinkPointer = *linkPointer; + *linkPointer = ((uint32_t)itdPointer | EHCI_HOST_POINTER_TYPE_ITD); + itdPointer = itdPointer->nextItdPointer; if (itdPointer == NULL) { break; @@ -2983,11 +3026,11 @@ static usb_status_t USB_HostEhciItdArrayInit(usb_host_ehci_instance_t *ehciInsta } } - if (lastShouldLinkUframe > EHCI_MAX_UFRAME_VALUE) + if (lastShouldLinkUframe > USB_HOST_EHCI_MAX_MICRFRAME_VALUE) { - lastShouldLinkUframe = lastShouldLinkUframe - (EHCI_MAX_UFRAME_VALUE + 1); + lastShouldLinkUframe = lastShouldLinkUframe - (USB_HOST_EHCI_MAX_MICRFRAME_VALUE + 1U); } - isoPointer->lastLinkFrame = lastShouldLinkUframe; + isoPointer->lastLinkFrame = (uint16_t)lastShouldLinkUframe; return kStatus_USB_Success; } @@ -3001,23 +3044,24 @@ static uint32_t USB_HostEhciItdArrayRelease(usb_host_ehci_instance_t *ehciInstan uint32_t doneLength = 0; /* remove itd from frame list */ - while (1) + while (1U == 1U) { /* record the transfer's result length */ - for (index = 0; index < 8; ++index) + for (index = 0U; index < 8U; ++index) { doneLength += ((itdPointer->transactions[index] & EHCI_HOST_ITD_TRANSACTION_LEN_MASK) >> EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT); } USB_HostEhciRemoveFromFrame(ehciInstance, (uint32_t)itdPointer, - itdPointer->frameEntryIndex); /* remove from the inserted frame list */ + (uint16_t)itdPointer->frameEntryIndex); /* remove from the inserted frame list */ /* release itd */ /* USB_HostEhciLock(); */ - USB_HostEhciZeroMem((uint32_t *)itdPointer, sizeof(usb_host_ehci_itd_t) >> 2); - itdPointer->nextLinkPointer = (uint32_t)ehciInstance->ehciItdList; - ehciInstance->ehciItdList = itdPointer; + /*set next link pointer to invalid in case hardware access invalid itd structure in special case*/ + itdPointer->nextLinkPointer = EHCI_HOST_T_INVALID_VALUE; + itdPointer->nextItdPointer = (usb_host_ehci_itd_t *)ehciInstance->ehciItdList; + ehciInstance->ehciItdList = itdPointer; ehciInstance->ehciItdNumber++; /* USB_HostEhciUnlock(); */ @@ -3041,14 +3085,15 @@ static usb_status_t USB_HostEhciItdArrayDeinit(usb_host_ehci_instance_t *ehciIns /* firstly remove the transfer (because host task may occupy to access the resource) */ USB_HostEhciLock(); - transfer = isoPointer->ehciTransferHead; - isoPointer->ehciTransferHead = isoPointer->ehciTransferTail = NULL; + transfer = isoPointer->ehciTransferHead; + isoPointer->ehciTransferTail = NULL; + isoPointer->ehciTransferHead = NULL; USB_HostEhciUnlock(); while (transfer != NULL) { nextTransfer = transfer->next; - doneLength = 0; + doneLength = 0; /* remove itd from frame list and release itd */ doneLength = USB_HostEhciItdArrayRelease(ehciInstance, (usb_host_ehci_itd_t *)transfer->union1.unitHead, (usb_host_ehci_itd_t *)transfer->union2.unitTail); @@ -3059,6 +3104,7 @@ static usb_status_t USB_HostEhciItdArrayDeinit(usb_host_ehci_instance_t *ehciIns doneLength = transfer->transferLength; } transfer->transferSofar = doneLength; + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferCancel); /* next transfer */ @@ -3082,7 +3128,7 @@ static usb_status_t USB_HostEhciOpenControlBulk(usb_host_ehci_instance_t *ehciIn qhPointer = (usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* add qh to async */ - qhPointer->horizontalLinkPointer = ehciInstance->shedFirstQh->horizontalLinkPointer; + qhPointer->horizontalLinkPointer = ehciInstance->shedFirstQh->horizontalLinkPointer; ehciInstance->shedFirstQh->horizontalLinkPointer = ((uint32_t)qhPointer | EHCI_HOST_POINTER_TYPE_QH); return kStatus_USB_Success; @@ -3093,10 +3139,11 @@ static usb_status_t USB_HostEhciCloseControlBulk(usb_host_ehci_instance_t *ehciI { volatile usb_host_ehci_qh_t *vltPrevQhPointer; uint32_t horizontalLinkValue; - + uint32_t *temp; /* remove qh from async schedule */ + temp = (uint32_t *)ehciPipePointer->ehciQh; if ((ehciInstance->shedFirstQh->horizontalLinkPointer & EHCI_HOST_POINTER_ADDRESS_MASK) == - (uint32_t)ehciPipePointer->ehciQh) /* the removing qh is the first qh in the async list */ + (uint32_t)temp) /* the removing qh is the first qh in the async list */ { USB_HostEhciStopAsync(ehciInstance); ehciInstance->shedFirstQh->horizontalLinkPointer = @@ -3110,8 +3157,8 @@ static usb_status_t USB_HostEhciCloseControlBulk(usb_host_ehci_instance_t *ehciI while (vltPrevQhPointer != NULL) { horizontalLinkValue = vltPrevQhPointer->horizontalLinkPointer; - if ((horizontalLinkValue & EHCI_HOST_T_INVALID_VALUE) || - ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)ehciPipePointer->ehciQh) || + if ((0U != (horizontalLinkValue & EHCI_HOST_T_INVALID_VALUE)) || + ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)temp) || ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)ehciInstance->shedFirstQh)) { break; @@ -3121,8 +3168,10 @@ static usb_status_t USB_HostEhciCloseControlBulk(usb_host_ehci_instance_t *ehciI } /* remove the qh from async list */ - if ((vltPrevQhPointer != NULL) && (!(horizontalLinkValue & EHCI_HOST_T_INVALID_VALUE)) && - ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)ehciPipePointer->ehciQh)) + /*for misra 11.6*/ + temp = (uint32_t *)ehciPipePointer->ehciQh; + if ((vltPrevQhPointer != NULL) && (0U == (horizontalLinkValue & EHCI_HOST_T_INVALID_VALUE)) && + ((horizontalLinkValue & EHCI_HOST_POINTER_ADDRESS_MASK) == (uint32_t)temp)) { USB_HostEhciStopAsync(ehciInstance); vltPrevQhPointer->horizontalLinkPointer = @@ -3140,6 +3189,7 @@ static usb_status_t USB_HostEhciOpenInterrupt(usb_host_ehci_instance_t *ehciInst { usb_status_t status = kStatus_USB_Success; uint32_t frameIndex; + uint32_t *temp; /* allocate bandwidth */ if (ehciInstance->firstDeviceSpeed == USB_SPEED_HIGH) @@ -3163,10 +3213,10 @@ static usb_status_t USB_HostEhciOpenInterrupt(usb_host_ehci_instance_t *ehciInst /* insert QH to frame list */ for (frameIndex = ehciPipePointer->startFrame; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE; - frameIndex += (ehciPipePointer->uframeInterval / 8)) + frameIndex += (((uint32_t)ehciPipePointer->uframeInterval + 7U) / 8U)) { - USB_HostEhciAddQhToFrame(ehciInstance, (uint32_t)ehciPipePointer->ehciQh, frameIndex, - ehciPipePointer->uframeInterval); + temp = (uint32_t *)ehciPipePointer->ehciQh; + USB_HostEhciAddQhToFrame(ehciInstance, (uint32_t)temp, (uint16_t)frameIndex, ehciPipePointer->uframeInterval); } return kStatus_USB_Success; @@ -3176,12 +3226,13 @@ static usb_status_t USB_HostEhciCloseInterrupt(usb_host_ehci_instance_t *ehciIns usb_host_ehci_pipe_t *ehciPipePointer) { uint32_t frameIndex; - + uint32_t *temp; /* remove from frame list */ for (frameIndex = ehciPipePointer->startFrame; frameIndex < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE; - frameIndex += (ehciPipePointer->uframeInterval / 8)) + frameIndex += (((uint32_t)ehciPipePointer->uframeInterval + 7U) / 8U)) { - USB_HostEhciRemoveFromFrame(ehciInstance, (uint32_t)ehciPipePointer->ehciQh, frameIndex); + temp = (uint32_t *)ehciPipePointer->ehciQh; + USB_HostEhciRemoveFromFrame(ehciInstance, (uint32_t)temp, (uint16_t)frameIndex); } ((usb_host_ehci_qh_t *)ehciPipePointer->ehciQh)->horizontalLinkPointer |= EHCI_HOST_T_INVALID_VALUE; /* invalid next qh link */ @@ -3219,11 +3270,11 @@ static usb_status_t USB_HostEhciOpenIso(usb_host_ehci_instance_t *ehciInstance, return kStatus_USB_Error; } USB_HostEhciLock(); - isoPointer = ehciInstance->ehciIsoList; + isoPointer = ehciInstance->ehciIsoList; ehciInstance->ehciIsoList = ehciInstance->ehciIsoList->next; USB_HostEhciUnlock(); isoPointer->lastLinkFrame = 0xFFFF; - ehciPipePointer->ehciQh = isoPointer; + ehciPipePointer->ehciQh = isoPointer; return status; } @@ -3231,31 +3282,32 @@ static usb_status_t USB_HostEhciOpenIso(usb_host_ehci_instance_t *ehciInstance, static usb_status_t USB_HostEhciCloseIso(usb_host_ehci_instance_t *ehciInstance, usb_host_ehci_pipe_t *ehciPipePointer) { usb_host_ehci_iso_t *isoPointer; - uint32_t speed; + uint32_t speed = 0U; isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh; if (isoPointer->ehciTransferHead != NULL) { - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &speed); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); if (speed == USB_SPEED_HIGH) { #if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) - USB_HostEhciItdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize itd list and free them */ + (void)USB_HostEhciItdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize itd list and free them */ #endif } else { #if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)) - USB_HostEhciSitdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize sitd list and free them */ + (void)USB_HostEhciSitdArrayDeinit(ehciInstance, + ehciPipePointer); /* de-initialize sitd list and free them */ #endif } } /* release usb_host_ehci_iso_t */ USB_HostEhciLock(); - isoPointer->next = ehciInstance->ehciIsoList; + isoPointer->next = ehciInstance->ehciIsoList; ehciInstance->ehciIsoList = isoPointer; USB_HostEhciUnlock(); return kStatus_USB_Success; @@ -3267,17 +3319,17 @@ static usb_status_t USB_HostEhciResetIP(usb_host_ehci_instance_t *ehciInstance) { /* reset controller */ ehciInstance->ehciIpBase->USBCMD = USBHS_USBCMD_RST_MASK; - while (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_RST_MASK) + while (0U != (ehciInstance->ehciIpBase->USBCMD & USBHS_USBCMD_RST_MASK)) { } /* set host mode */ #if (ENDIANNESS == USB_LITTLE_ENDIAN) - ehciInstance->ehciIpBase->USBMODE |= 0x03; + ehciInstance->ehciIpBase->USBMODE |= 0x03U; #else - ehciInstance->ehciIpBase->USBMODE |= (0x03 | (0x01 << USBHS_USBMODE_ES_SHIFT)); + ehciInstance->ehciIpBase->USBMODE |= (0x03U | (0x01U << USBHS_USBMODE_ES_SHIFT)); #endif /* check frame list size */ - if (!(ehciInstance->ehciIpBase->HCCPARAMS & USBHS_HCCPARAMS_PFL_MASK)) + if (0U == (ehciInstance->ehciIpBase->HCCPARAMS & USBHS_HCCPARAMS_PFL_MASK)) { #if ((USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE < 8) || (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE > 1024)) return kStatus_USB_Error; @@ -3293,7 +3345,7 @@ static usb_status_t USB_HostEhciStartIP(usb_host_ehci_instance_t *ehciInstance) { uint32_t tmp = 0; - if (ehciInstance->ehciIpBase->HCSPARAMS & USBHS_HCSPARAMS_PPC_MASK) /* Ports have power port switches */ + if (0U != (ehciInstance->ehciIpBase->HCSPARAMS & USBHS_HCSPARAMS_PPC_MASK)) /* Ports have power port switches */ { /* only has one port */ tmp = ehciInstance->ehciIpBase->PORTSC1; @@ -3302,41 +3354,41 @@ static usb_status_t USB_HostEhciStartIP(usb_host_ehci_instance_t *ehciInstance) } /* set frame list size */ - if (ehciInstance->ehciIpBase->HCCPARAMS & USBHS_HCCPARAMS_PFL_MASK) + if (0U != (ehciInstance->ehciIpBase->HCCPARAMS & USBHS_HCCPARAMS_PFL_MASK)) { #if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE <= 64) ehciInstance->ehciIpBase->USBCMD |= (USBHS_USBCMD_FS2_MASK); #if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 64) - ehciInstance->ehciIpBase->USBCMD |= (0x00 << USBHS_USBCMD_FS_SHIFT); -#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 32) - ehciInstance->ehciIpBase->USBCMD |= (0x01 << USBHS_USBCMD_FS_SHIFT); -#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 16) - ehciInstance->ehciIpBase->USBCMD |= (0x02 << USBHS_USBCMD_FS_SHIFT); -#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 8) - ehciInstance->ehciIpBase->USBCMD |= (0x03 << USBHS_USBCMD_FS_SHIFT); + ehciInstance->ehciIpBase->USBCMD |= (0x00U << USBHS_USBCMD_FS_SHIFT); +#elif (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 32) + ehciInstance->ehciIpBase->USBCMD |= (0x01U << USBHS_USBCMD_FS_SHIFT); +#elif (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 16) + ehciInstance->ehciIpBase->USBCMD |= (0x02U << USBHS_USBCMD_FS_SHIFT); +#elif (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 8) + ehciInstance->ehciIpBase->USBCMD |= (0x03U << USBHS_USBCMD_FS_SHIFT); #endif #else #if (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 1024) - ehciInstance->ehciIpBase->USBCMD |= (0x00 << USBHS_USBCMD_FS_SHIFT); -#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 512) - ehciInstance->ehciIpBase->USBCMD |= (0x01 << USBHS_USBCMD_FS_SHIFT); -#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 256) - ehciInstance->ehciIpBase->USBCMD |= (0x02 << USBHS_USBCMD_FS_SHIFT); -#elif(USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 128) - ehciInstance->ehciIpBase->USBCMD |= (0x03 << USBHS_USBCMD_FS_SHIFT); + ehciInstance->ehciIpBase->USBCMD |= (0x00U << USBHS_USBCMD_FS_SHIFT); +#elif (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 512) + ehciInstance->ehciIpBase->USBCMD |= (0x01U << USBHS_USBCMD_FS_SHIFT); +#elif (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 256) + ehciInstance->ehciIpBase->USBCMD |= (0x02U << USBHS_USBCMD_FS_SHIFT); +#elif (USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE == 128) + ehciInstance->ehciIpBase->USBCMD |= (0x03U << USBHS_USBCMD_FS_SHIFT); #endif #endif } /* start the controller */ - ehciInstance->ehciIpBase->USBCMD = USBHS_USBCMD_RS_MASK; + ehciInstance->ehciIpBase->USBCMD |= USBHS_USBCMD_RS_MASK; /* set timer0 */ - ehciInstance->ehciIpBase->GPTIMER0LD = (300 * 1000 - 1); /* 100ms */ + ehciInstance->ehciIpBase->GPTIMER0LD = (100U * 1000U - 1U); /* 100ms */ /* enable interrupt (USB interrupt enable + USB error interrupt enable + port change detect enable + system error * enable + interrupt on async advance enable) + general purpos Timer 0 Interrupt enable */ - ehciInstance->ehciIpBase->USBINTR |= (0x1000037); + ehciInstance->ehciIpBase->USBINTR |= (0x1000037U); return kStatus_USB_Success; } @@ -3349,7 +3401,7 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc #if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \ ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))) usb_host_ehci_iso_t *isoPointer; - uint32_t speed; + uint32_t speed = 0U; #endif uint8_t cancelPipe = 0; @@ -3368,24 +3420,24 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc if ((qhPointer->ehciTransferHead == transfer) && (qhPointer->ehciTransferHead == qhPointer->ehciTransferTail)) /* only has this one transfer */ { - cancelPipe = 1; + cancelPipe = 1U; } else { - cancelPipe = 0; + cancelPipe = 0U; } } else { - cancelPipe = 1; + cancelPipe = 1U; } - if (cancelPipe == 1) /* cancel all pipe */ + if (cancelPipe == 1U) /* cancel all pipe */ { - USB_HostEhciQhQtdListDeinit(ehciInstance, ehciPipePointer); /* release all the qtd */ + (void)USB_HostEhciQhQtdListDeinit(ehciInstance, ehciPipePointer); /* release all the qtd */ } else /* cancel one transfer */ { - USB_HostEhciTransferQtdListDeinit(ehciInstance, ehciPipePointer, transfer); + (void)USB_HostEhciTransferQtdListDeinit(ehciInstance, ehciPipePointer, transfer); } break; @@ -3398,54 +3450,55 @@ static usb_status_t USB_HostEhciCancelPipe(usb_host_ehci_instance_t *ehciInstanc return kStatus_USB_Success; } /* cancel all pipe, don't implement canceling transfer for iso */ - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &speed); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); if (speed == USB_SPEED_HIGH) { #if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) - USB_HostEhciItdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize itd */ + (void)USB_HostEhciItdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize itd */ #endif } else { #if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)) - USB_HostEhciSitdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize sitd */ + (void)USB_HostEhciSitdArrayDeinit(ehciInstance, ehciPipePointer); /* de-initialize sitd */ #endif } break; #endif default: + /*no action*/ break; } return kStatus_USB_Success; } -static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl) +usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl) { usb_status_t status = kStatus_USB_Success; uint32_t portScRegister; - - switch (busControl) + usb_host_bus_control_t controlCode = (usb_host_bus_control_t)busControl; + switch (controlCode) { case kUSB_HostBusReset: /* reset port */ portScRegister = ehciInstance->ehciIpBase->PORTSC1; portScRegister &= (~EHCI_PORTSC1_W1_BITS); ehciInstance->ehciIpBase->PORTSC1 = (portScRegister | USBHS_PORTSC1_PR_MASK); - while (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PR_MASK) + while (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)) { } break; case kUSB_HostBusRestart: - ehciInstance->deviceAttached = kEHCIDeviceDetached; + ehciInstance->deviceAttached = (uint8_t)kEHCIDeviceDetached; ehciInstance->ehciIpBase->USBINTR |= (USBHS_USBINTR_PCE_MASK); /* enable ehci port change interrupt */ break; case kUSB_HostBusEnableAttach: /* enable device attach */ - if (ehciInstance->deviceAttached == kEHCIDeviceDetached) + if (ehciInstance->deviceAttached == (uint8_t)kEHCIDeviceDetached) { ehciInstance->ehciIpBase->USBINTR |= (USBHS_USBINTR_PCE_MASK); /* enable ehci port change interrupt */ } @@ -3456,7 +3509,7 @@ static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstanc break; #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) case kUSB_HostBusSuspend: - if (ehciInstance->ehciIpBase->PORTSC1 && USBHS_PORTSC1_CCS_MASK) + if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) { /* set timer1 */ ehciInstance->ehciIpBase->GPTIMER1LD = (1 * 1000); /* 1ms */ @@ -3465,9 +3518,9 @@ static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstanc USB_HostEhciStopAsync(ehciInstance); USB_HostEhciStopPeriodic(ehciInstance); - while (ehciInstance->ehciIpBase->USBSTS & (USBHS_USBSTS_PS_MASK | USBHS_USBSTS_AS_MASK)) + while (0U != (ehciInstance->ehciIpBase->USBSTS & (USBHS_USBSTS_PS_MASK | USBHS_USBSTS_AS_MASK))) { - __ASM("nop"); + __NOP(); } ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_WKCN_MASK; ehciInstance->ehciIpBase->PORTSC1 |= USBHS_PORTSC1_WKDS_MASK; @@ -3485,7 +3538,7 @@ static usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstanc case kUSB_HostBusResume: ehciInstance->ehciIpBase->PORTSC1 &= ~(USBHS_PORTSC1_SUSP_MASK); /* Clear Suspend bit */ ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_PHCD_MASK; - if (ehciInstance->deviceAttached != kEHCIDeviceDetached) + if (ehciInstance->deviceAttached != (uint8_t)kEHCIDeviceDetached) { ehciInstance->busSuspendStatus = kBus_EhciStartResume; #if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U)) @@ -3532,6 +3585,9 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) uint32_t dataLength; uint32_t speed; #endif + void *temp; + uint32_t transferResults; + uint32_t transferOverlayResults; ehciPipePointer = ehciInstance->ehciRunningPipeList; /* check all the running pipes */ while (ehciPipePointer != NULL) @@ -3542,43 +3598,45 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) case USB_ENDPOINT_INTERRUPT: case USB_ENDPOINT_CONTROL: vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* pipe's qh */ - transfer = vltQhPointer->ehciTransferHead; /* qh's transfer */ + transfer = vltQhPointer->ehciTransferHead; /* qh's transfer */ while (transfer != NULL) { nextTransfer = transfer->next; /* normal case */ - vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail; - if ((vltQtdPointer->transferResults[0] & (EHCI_HOST_QTD_IOC_MASK)) && - (!(vltQtdPointer->transferResults[0] & - EHCI_HOST_QTD_STATUS_ACTIVE_MASK))) /* transfer is done */ + vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail; + transferResults = vltQtdPointer->transferResults[0]; + transferOverlayResults = vltQhPointer->transferOverlayResults[0]; + if ((0U != (transferResults & (EHCI_HOST_QTD_IOC_MASK))) && + (0U == (transferResults & EHCI_HOST_QTD_STATUS_ACTIVE_MASK))) /* transfer is done */ { - qtdStatus = (vltQtdPointer->transferResults[0] & EHCI_HOST_QTD_STATUS_ERROR_MASK); + qtdStatus = (transferResults & EHCI_HOST_QTD_STATUS_ERROR_MASK); transfer->transferSofar = USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead), (usb_host_ehci_qtd_t *)(transfer->union2.unitTail)); transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ? - 0 : + 0U : (transfer->transferLength - transfer->transferSofar); vltQhPointer->ehciTransferHead = transfer->next; - vltQhPointer->timeOutLabel = 0; - vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; - if (qtdStatus) /* has errors */ + vltQhPointer->timeOutLabel = 0U; + vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; + if (0U != qtdStatus) /* has errors */ { - if (!(vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)) + if (0U == (transferOverlayResults & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)) { vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */ } - if (qtdStatus & EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK) + if (0U != (qtdStatus & EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK)) { + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferFailed); /* transfer fail */ } else { - transfer->callbackFn(transfer->callbackParam, transfer, - kStatus_USB_TransferStall); /* transfer stall */ + /* callback function is different from the current condition */ + transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferStall); } } else @@ -3602,8 +3660,8 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) { break; } - ehciClearPipePointer = - (usb_host_ehci_pipe_t *)ehciClearPipePointer->pipeCommon.next; + temp = (void *)ehciClearPipePointer->pipeCommon.next; + ehciClearPipePointer = (usb_host_ehci_pipe_t *)temp; } if ((ehciClearPipePointer != NULL) && @@ -3614,18 +3672,19 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) ->transferOverlayResults[0] &= (~EHCI_HOST_QTD_DT_MASK); } } + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_Success); /* transfer success */ } } - else if ((!(vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)) && - (vltQhPointer->transferOverlayResults[0] & - EHCI_HOST_QH_STATUS_ERROR_MASK)) /* there is error and transfer is done */ + else if ((0U == (transferOverlayResults & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)) && + (0U != (transferOverlayResults & + EHCI_HOST_QH_STATUS_ERROR_MASK))) /* there is error and transfer is done */ { - qtdStatus = (vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QH_STATUS_ERROR_MASK); + qtdStatus = (vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QH_STATUS_ERROR_MASK); vltQtdPointer = (volatile usb_host_ehci_qtd_t *)(vltQhPointer->currentQtdPointer); - if (((uint32_t)vltQtdPointer & EHCI_HOST_T_INVALID_VALUE) || + if ((0U != ((uint32_t)vltQtdPointer & EHCI_HOST_T_INVALID_VALUE)) || (vltQtdPointer == NULL)) /* the error status is unreasonable */ { vltQhPointer->transferOverlayResults[0] &= @@ -3634,13 +3693,13 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) else { /* remove qtd from qh */ - while ((vltQtdPointer != NULL) && (!(vltQtdPointer->transferResults[0] & - EHCI_HOST_QTD_IOC_MASK))) /* find the IOC qtd */ + while ((vltQtdPointer != NULL) && + (0U == (transferResults & EHCI_HOST_QTD_IOC_MASK))) /* find the IOC qtd */ { vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer; } - vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; + vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; vltQhPointer->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE; vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */ @@ -3653,18 +3712,20 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead), (usb_host_ehci_qtd_t *)(transfer->union2.unitTail)); transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ? - 0 : + 0U : (transfer->transferLength - transfer->transferSofar); vltQhPointer->ehciTransferHead = transfer->next; - vltQhPointer->timeOutLabel = 0; - vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; - if (qtdStatus & EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK) + vltQhPointer->timeOutLabel = 0U; + vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; + if (0U != (qtdStatus & EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK)) { + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferFailed); /* transfer fail */ } else { + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferStall); /* transfer stall */ } @@ -3680,41 +3741,42 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) #if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \ ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))) case USB_ENDPOINT_ISOCHRONOUS: - qtdStatus = 0; /* qtdStatus means break here, because there is only one break in while for misra */ + qtdStatus = 0; /* qtdStatus means break here, because there is only one break in while for misra */ isoPointer = (usb_host_ehci_iso_t *)ehciPipePointer->ehciQh; /* pipe's usb_host_ehci_iso_t */ - transfer = isoPointer->ehciTransferHead; /* usb_host_ehci_iso_t's transfer */ + transfer = isoPointer->ehciTransferHead; /* usb_host_ehci_iso_t's transfer */ while (transfer != NULL) { nextTransfer = transfer->next; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, - kUSB_HostGetDeviceSpeed, &speed); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); if (speed == USB_SPEED_HIGH) { #if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) vltItdPointer = (volatile usb_host_ehci_itd_t *)(transfer->union2.unitTail); /* transfer's last itd */ - for (index = 0; index < 8; ++index) + for (index = 0; index < 8U; ++index) { - if (vltItdPointer->transactions[index] & EHCI_HOST_ITD_STATUS_ACTIVE_MASK) + if (0U != (vltItdPointer->transactions[index] & EHCI_HOST_ITD_STATUS_ACTIVE_MASK)) { break; } } - if (index == 8) /* transfer is done */ + if (index == 8U) /* transfer is done */ { /* remove itd from frame list and release itd */ - dataLength = USB_HostEhciItdArrayRelease(ehciInstance, + dataLength = USB_HostEhciItdArrayRelease(ehciInstance, (usb_host_ehci_itd_t *)transfer->union1.unitHead, (usb_host_ehci_itd_t *)transfer->union2.unitTail); - transfer->transferSofar = dataLength; + transfer->transferSofar = dataLength; isoPointer->ehciTransferHead = transfer->next; + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_Success); /* transfer callback success */ /* TODO: iso callback error */ } else { - qtdStatus = 1; /* break */ + qtdStatus = 1U; /* break */ } #endif } @@ -3723,26 +3785,27 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) #if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)) vltSitdPointer = (volatile usb_host_ehci_sitd_t *)(transfer->union2.unitTail); /* transfer's last sitd */ - if (!(vltSitdPointer->transferResults[0] & - EHCI_HOST_SITD_STATUS_ACTIVE_MASK)) /* transfer is done */ + if (0U == (vltSitdPointer->transferResults[0] & + EHCI_HOST_SITD_STATUS_ACTIVE_MASK)) /* transfer is done */ { /* remove sitd from frame list and release itd */ dataLength = USB_HostEhciSitdArrayRelease( ehciInstance, (usb_host_ehci_sitd_t *)transfer->union1.unitHead, (usb_host_ehci_sitd_t *)transfer->union2.unitTail); - transfer->transferSofar = dataLength; + transfer->transferSofar = transfer->transferLength - dataLength; isoPointer->ehciTransferHead = transfer->next; + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_Success); /* transfer callback success */ /* TODO: iso callback error */ } else { - qtdStatus = 1; /* break */ + qtdStatus = 1U; /* break */ } #endif } - if (qtdStatus == 1) + if (qtdStatus == 1U) { break; } @@ -3752,38 +3815,40 @@ void USB_HostEhciTransactionDone(usb_host_ehci_instance_t *ehciInstance) #endif default: + /*no action*/ break; } - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; } } -static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance) +void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance) { /* note: only has one port */ uint32_t portScRegister = ehciInstance->ehciIpBase->PORTSC1; - int32_t sofStart = 0; - int32_t sofCount = 0; + uint32_t sofStart = 0; + uint32_t sofCount = 0; uint32_t index; - if (portScRegister & USBHS_PORTSC1_CSC_MASK) /* connection status change */ + if (0U != (portScRegister & USBHS_PORTSC1_CSC_MASK)) /* connection status change */ { - sofStart = (int32_t)(ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); + sofStart = (ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); /* process CSC bit */ - while (1) + while (1U == 1U) { portScRegister = ehciInstance->ehciIpBase->PORTSC1; - if (portScRegister & USBHS_PORTSC1_CSC_MASK) + if (0U != (portScRegister & USBHS_PORTSC1_CSC_MASK)) { /* clear csc bit */ portScRegister = ehciInstance->ehciIpBase->PORTSC1; portScRegister &= (~EHCI_PORTSC1_W1_BITS); ehciInstance->ehciIpBase->PORTSC1 = (portScRegister | USBHS_PORTSC1_CSC_MASK); } - sofCount = (int32_t)(ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); - if (((sofCount - sofStart + EHCI_MAX_UFRAME_VALUE + 1) & EHCI_MAX_UFRAME_VALUE) > - (1 * 8)) /* delay 1ms to clear CSC */ + sofCount = (ehciInstance->ehciIpBase->FRINDEX & EHCI_MAX_UFRAME_VALUE); + if (((sofCount + EHCI_MAX_UFRAME_VALUE + 1U - sofStart) & EHCI_MAX_UFRAME_VALUE) > + (1U * 8U)) /* delay 1ms to clear CSC */ { break; } @@ -3792,10 +3857,10 @@ static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance) /* process CCS bit */ portScRegister = ehciInstance->ehciIpBase->PORTSC1; - if (portScRegister & USBHS_PORTSC1_CCS_MASK) /* process attach */ + if (0U != (portScRegister & USBHS_PORTSC1_CCS_MASK)) /* process attach */ { - if ((ehciInstance->deviceAttached == kEHCIDevicePhyAttached) || - (ehciInstance->deviceAttached == kEHCIDeviceAttached)) + if ((ehciInstance->deviceAttached == (uint8_t)kEHCIDevicePhyAttached) || + (ehciInstance->deviceAttached == (uint8_t)kEHCIDeviceAttached)) { return; } @@ -3806,25 +3871,25 @@ static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance) for (index = 0; index < USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY; ++index) { USB_HostEhciDelay(ehciInstance->ehciIpBase, 1); - if (!(ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) + if (0U == (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) { break; } } if (index < USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY) /* CCS is cleared */ { - ehciInstance->deviceAttached = kEHCIDeviceDetached; + ehciInstance->deviceAttached = (uint8_t)kEHCIDeviceDetached; return; } /* reset port */ portScRegister = ehciInstance->ehciIpBase->PORTSC1; portScRegister &= (~EHCI_PORTSC1_W1_BITS); ehciInstance->ehciIpBase->PORTSC1 = (portScRegister | USBHS_PORTSC1_PR_MASK); - while (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PR_MASK) + while (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)) { } ehciInstance->firstDeviceSpeed = - ((ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PSPD_MASK) >> USBHS_PORTSC1_PSPD_SHIFT); + (uint8_t)((ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_PSPD_MASK) >> USBHS_PORTSC1_PSPD_SHIFT); /* enable ehci phy disconnection */ if (ehciInstance->firstDeviceSpeed == USB_SPEED_HIGH) { @@ -3834,16 +3899,16 @@ static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance) /* wait for reset */ USB_HostEhciDelay(ehciInstance->ehciIpBase, USB_HOST_EHCI_PORT_RESET_DELAY); /* process attach */ - USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_DEVICE_ATTACH); + (void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_DEVICE_ATTACH); /* gpt timer start */ ehciInstance->ehciIpBase->GPTIMER0CTL |= (USBHS_GPTIMER0CTL_RUN_MASK | USBHS_GPTIMER0CTL_MODE_MASK | USBHS_GPTIMER0CTL_RST_MASK); - ehciInstance->deviceAttached = kEHCIDevicePhyAttached; + ehciInstance->deviceAttached = (uint8_t)kEHCIDevicePhyAttached; } else { - if ((ehciInstance->deviceAttached == kEHCIDevicePhyAttached) || - (ehciInstance->deviceAttached == kEHCIDeviceAttached)) + if ((ehciInstance->deviceAttached == (uint8_t)kEHCIDevicePhyAttached) || + (ehciInstance->deviceAttached == (uint8_t)kEHCIDeviceAttached)) { #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) ehciInstance->busSuspendStatus = kBus_EhciIdle; @@ -3854,19 +3919,20 @@ static void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance) /* disable async and periodic */ USB_HostEhciStopAsync(ehciInstance); USB_HostEhciStopPeriodic(ehciInstance); - USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_DEVICE_DETACH); + (void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_DEVICE_DETACH); } } } -static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) +void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) { volatile usb_host_ehci_qh_t *vltQhPointer; - volatile usb_host_ehci_qtd_t *vltQtdPointer; + usb_host_ehci_qtd_t *vltQtdPointer; usb_host_transfer_t *transfer; uint32_t backValue; - volatile uint32_t *totalBytesAddress = NULL; + volatile uint32_t *totalBytesAddress = NULL; usb_host_ehci_pipe_t *ehciPipePointer = ehciInstance->ehciRunningPipeList; + void *temp; uint8_t timeoutLabel; while (ehciPipePointer != NULL) @@ -3876,13 +3942,13 @@ static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) case USB_ENDPOINT_BULK: case USB_ENDPOINT_CONTROL: vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* pipe's qh */ - transfer = vltQhPointer->ehciTransferHead; /* qh's transfer */ + transfer = vltQhPointer->ehciTransferHead; /* qh's transfer */ if ((transfer != NULL)) /* there is transfering data */ { - timeoutLabel = 0; - if (ehciInstance->deviceAttached != kEHCIDeviceAttached) + timeoutLabel = 0U; + if (ehciInstance->deviceAttached != (uint8_t)kEHCIDeviceAttached) { - vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail; + vltQtdPointer = (usb_host_ehci_qtd_t *)transfer->union2.unitTail; vltQhPointer->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; /* invalid next qtd */ vltQhPointer->transferOverlayResults[0] &= @@ -3891,15 +3957,15 @@ static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) } else { - if (vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK) + if (0U != (vltQhPointer->transferOverlayResults[0] & EHCI_HOST_QTD_STATUS_ACTIVE_MASK)) { - vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQhPointer->currentQtdPointer; + vltQtdPointer = (usb_host_ehci_qtd_t *)vltQhPointer->currentQtdPointer; totalBytesAddress = &(vltQhPointer->transferOverlayResults[0]); } else { - vltQtdPointer = (volatile usb_host_ehci_qtd_t *)transfer->union2.unitTail; - totalBytesAddress = ((uint32_t *)vltQtdPointer + 2); + vltQtdPointer = (usb_host_ehci_qtd_t *)transfer->union2.unitTail; + totalBytesAddress = &(vltQtdPointer->transferResults[0]); } backValue = @@ -3908,7 +3974,7 @@ static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) if (vltQhPointer->timeOutLabel != backValue) /* use total bytes to reflect the time out */ { vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; - vltQhPointer->timeOutLabel = backValue; + vltQhPointer->timeOutLabel = (uint16_t)backValue; } else { @@ -3916,7 +3982,7 @@ static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) * USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE */ (vltQhPointer->timeOutValue)--; - if (vltQhPointer->timeOutValue == 0) + if (vltQhPointer->timeOutValue == 0U) { /* stop the qh schedule */ USB_HostEhciStopAsync(ehciInstance); @@ -3931,22 +3997,24 @@ static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) vltQhPointer->transferOverlayResults[0] &= (~EHCI_HOST_QTD_STATUS_MASK); /* clear error status */ USB_HostEhciStartAsync(ehciInstance); - timeoutLabel = 1; + timeoutLabel = 1U; } } } } - if (timeoutLabel == 1) + if (timeoutLabel == 1U) { /* remove qtd from qh */ + temp = (void *)vltQhPointer->ehciTransferTail; while ((vltQtdPointer != NULL) && - (!(vltQtdPointer->transferResults[0] & EHCI_HOST_QTD_IOC_MASK)) && - (vltQtdPointer != (usb_host_ehci_qtd_t *)vltQhPointer->ehciTransferTail)) + (0U == (vltQtdPointer->transferResults[0] & EHCI_HOST_QTD_IOC_MASK)) && + (vltQtdPointer != (usb_host_ehci_qtd_t *)temp)) { - vltQtdPointer = (volatile usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer; + vltQtdPointer = (usb_host_ehci_qtd_t *)vltQtdPointer->nextQtdPointer; } - if ((vltQtdPointer != NULL) && (!(vltQtdPointer->nextQtdPointer & EHCI_HOST_T_INVALID_VALUE))) + if ((vltQtdPointer != NULL) && + (0U == (vltQtdPointer->nextQtdPointer & EHCI_HOST_T_INVALID_VALUE))) { vltQhPointer->nextQtdPointer = vltQtdPointer->nextQtdPointer; /* start qh if there are other qtd that don't belong to @@ -3956,38 +4024,41 @@ static void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance) USB_HostEhciQtdListRelease(ehciInstance, (usb_host_ehci_qtd_t *)(transfer->union1.unitHead), (usb_host_ehci_qtd_t *)(transfer->union2.unitTail)); transfer->transferSofar = (transfer->transferLength < transfer->transferSofar) ? - 0 : + 0U : (transfer->transferLength - transfer->transferSofar); vltQhPointer->ehciTransferHead = transfer->next; - vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; + vltQhPointer->timeOutValue = USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE; + /* callback function is different from the current condition */ transfer->callbackFn(transfer->callbackParam, transfer, kStatus_USB_TransferFailed); } } break; default: + /*no action*/ break; } - ehciPipePointer = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = (usb_host_ehci_pipe_t *)temp; } } #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance) { - if (ehciInstance->deviceAttached != kEHCIDeviceDetached) + if (ehciInstance->deviceAttached != (uint8_t)kEHCIDeviceDetached) { if (kBus_EhciStartSuspend == ehciInstance->busSuspendStatus) { usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle; - if (0 == ehciInstance->matchTick) + if (0U == ehciInstance->matchTick) { ehciInstance->matchTick = hostPointer->hwTick; } else { - if ((hostPointer->hwTick - ehciInstance->matchTick) >= 5) + if ((hostPointer->hwTick - ehciInstance->matchTick) >= 5U) { ehciInstance->ehciIpBase->USBCMD &= ~USBHS_USBCMD_RS_MASK; ehciInstance->ehciIpBase->USBSTS |= USBHS_USBSTS_SRI_MASK; @@ -4004,9 +4075,9 @@ static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance) ehciInstance->registerPhyBase->PWD = 0xFFFFFFFFU; - while (ehciInstance->registerPhyBase->CTRL & (USBPHY_CTRL_UTMI_SUSPENDM_MASK)) + while (0U != (ehciInstance->registerPhyBase->CTRL & (USBPHY_CTRL_UTMI_SUSPENDM_MASK))) { - __ASM("nop"); + __NOP(); } #if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U)) @@ -4018,8 +4089,8 @@ static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance) ehciInstance->ehciIpBase->USBGENCTRL = USBHS_USBGENCTRL_WU_IE_MASK; #endif ehciInstance->registerPhyBase->CTRL |= USBPHY_CTRL_CLKGATE_MASK; - hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, - kUSB_HostEventSuspended); /* call host callback function */ + (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventSuspended); /* call host callback function */ ehciInstance->busSuspendStatus = kBus_EhciSuspended; } } @@ -4027,17 +4098,17 @@ static void USB_HostEhciTimer1(usb_host_ehci_instance_t *ehciInstance) else if (kBus_EhciStartResume == ehciInstance->busSuspendStatus) { usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle; - if (!(ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_FPR_MASK)) + if (0U == (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_FPR_MASK)) { ehciInstance->ehciIpBase->PORTSC1 &= ~USBHS_PORTSC1_WKDS_MASK; - if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK) + if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) { USB_HostEhciStartAsync(ehciInstance); USB_HostEhciStartPeriodic(ehciInstance); } - hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, - kUSB_HostEventResumed); /* call host callback function */ - hostPointer->suspendedDevice = NULL; + (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventResumed); /* call host callback function */ + hostPointer->suspendedDevice = NULL; ehciInstance->busSuspendStatus = kBus_EhciIdle; ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK); } @@ -4059,30 +4130,31 @@ usb_status_t USB_HostEhciCreate(uint8_t controllerId, usb_host_controller_handle *controllerHandle) { uint32_t index = 0; - usb_osa_status_t osaStatus; + osa_status_t osaStatus; usb_host_ehci_instance_t *ehciInstance; uint32_t usbhsBaseAddrs[] = USBHS_BASE_ADDRS; - usb_host_ehci_data_t *usbHostEhciData[] = USB_HOST_EHCI_DATA_ARRAY; - uint8_t *usbHostEhciFrameList[] = USB_HOST_EHCI_FRAME_LIST_ARRAY; + usb_host_ehci_data_t *usbHostEhciData[USB_HOST_CONFIG_EHCI]; uint32_t *framePointer; + void *temp; + uint8_t instanceIndex = 0U; - if ((uint32_t)(controllerId - kUSB_ControllerEhci0) >= (sizeof(usbhsBaseAddrs) / sizeof(usbhsBaseAddrs[0]))) + if ((controllerId - (uint8_t)kUSB_ControllerEhci0) >= (sizeof(usbhsBaseAddrs) / sizeof(usbhsBaseAddrs[0]))) { return kStatus_USB_ControllerNotFound; } *controllerHandle = NULL; - ehciInstance = (usb_host_ehci_instance_t *)USB_OsaMemoryAllocate( + ehciInstance = (usb_host_ehci_instance_t *)OSA_MemoryAllocate( sizeof(usb_host_ehci_instance_t)); /* malloc host ehci instance */ if (ehciInstance == NULL) { return kStatus_USB_AllocFail; } - ehciInstance->controllerId = controllerId; - ehciInstance->hostHandle = upperLayerHandle; - ehciInstance->deviceAttached = kEHCIDeviceDetached; - ehciInstance->ehciIpBase = (USBHS_Type *) - usbhsBaseAddrs[controllerId - kUSB_ControllerEhci0]; /* operate ehci ip through the base address */ + ehciInstance->controllerId = controllerId; + ehciInstance->hostHandle = upperLayerHandle; + ehciInstance->deviceAttached = (uint8_t)kEHCIDeviceDetached; + ehciInstance->ehciIpBase = (USBHS_Type *) + usbhsBaseAddrs[controllerId - (uint8_t)kUSB_ControllerEhci0]; /* operate ehci ip through the base address */ #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) ehciInstance->busSuspendStatus = kBus_EhciIdle; @@ -4097,95 +4169,150 @@ usb_status_t USB_HostEhciCreate(uint8_t controllerId, #endif - if (USB_HostEhciResetIP(ehciInstance) != kStatus_USB_Success) /* reset ehci ip */ + if ((USB_HostEhciResetIP(ehciInstance) != kStatus_USB_Success) || + ((ehciInstance->controllerId < (uint8_t)kUSB_ControllerEhci0))) /* reset ehci ip */ { - USB_OsaMemoryFree(ehciInstance); + OSA_MemoryFree(ehciInstance); return kStatus_USB_Error; } - /* initialize ehci frame list */ - ehciInstance->ehciFrameList = usbHostEhciFrameList[ehciInstance->controllerId - kUSB_ControllerEhci0]; +#if (USB_HOST_CONFIG_EHCI == 1U) + if (0U == usbHostEhciFramListStatus[0]) + { + usbHostEhciFramListStatus[0] = 1U; + instanceIndex = 0U; + ehciInstance->ehciFrameList = &s_UsbHostEhciFrameList1[0]; + } +#elif (USB_HOST_CONFIG_EHCI == 2U) + if (0U == usbHostEhciFramListStatus[0]) + { + usbHostEhciFramListStatus[0] = 1U; + instanceIndex = 0U; + ehciInstance->ehciFrameList = &s_UsbHostEhciFrameList1[0]; + } + else if (0U == usbHostEhciFramListStatus[1]) + { + usbHostEhciFramListStatus[1] = 1U; + instanceIndex = 1U; + ehciInstance->ehciFrameList = &s_UsbHostEhciFrameList2[0]; + } + else + { + /*no action*/ + } +#endif + if (ehciInstance->ehciFrameList == NULL) + { + OSA_MemoryFree(ehciInstance); + return kStatus_USB_Error; + } - /* initialize ehci units */ - ehciInstance->ehciUnitBase = (uint32_t *)(usbHostEhciData[ehciInstance->controllerId - kUSB_ControllerEhci0]); +#if (USB_HOST_CONFIG_EHCI == 1U) + usbHostEhciData[0] = &s_UsbHostEhciData1; +#elif (USB_HOST_CONFIG_EHCI == 2U) + usbHostEhciData[0] = &s_UsbHostEhciData1; + usbHostEhciData[1] = &s_UsbHostEhciData2; +#else +#error "Please increase the instance count." +#endif + + temp = (void *)usbHostEhciData[instanceIndex]; + ehciInstance->ehciUnitBase = (uint32_t *)(temp); /* initialize qh/qtd/itd/sitd/iso list */ - ehciInstance->ehciQhList = (usb_host_ehci_qh_t *)((uint32_t)(ehciInstance->ehciUnitBase)); + ehciInstance->ehciQhList = (usb_host_ehci_qh_t *)((uint32_t)(ehciInstance->ehciUnitBase)); ehciInstance->ehciQtdHead = (usb_host_ehci_qtd_t *)((uint32_t)ehciInstance->ehciQhList + (sizeof(usb_host_ehci_qh_t) * USB_HOST_CONFIG_EHCI_MAX_QH)); ehciInstance->ehciItdList = (usb_host_ehci_itd_t *)((uint32_t)ehciInstance->ehciQtdHead + (sizeof(usb_host_ehci_qtd_t) * USB_HOST_CONFIG_EHCI_MAX_QTD)); - ehciInstance->ehciSitdList = ehciInstance->ehciSitdIndexBase = +#if ((defined(USB_HOST_CONFIG_EHCI_MAX_ITD)) && (USB_HOST_CONFIG_EHCI_MAX_ITD > 0U)) + /* If one ITD's first 32 bytes and next 32 bytes are in different 4K region, + * the ITD need move 32 bytes because the ITD cannot cross over 4K boundary. + */ + index = ((((((uint32_t)(ehciInstance->ehciItdList)) + 4095U) & 0xFFFFF000U) - + ((uint32_t)(ehciInstance->ehciItdList))) >> + 5U); + if (((index / 3U) < USB_HOST_CONFIG_EHCI_MAX_ITD) && ((index % 3U) == 1U)) + { + ehciInstance->ehciItdList = (usb_host_ehci_itd_t *)(((uint32_t)(ehciInstance->ehciItdList)) + 32U); + } +#endif + ehciInstance->ehciSitdIndexBase = (usb_host_ehci_sitd_t *)((uint32_t)ehciInstance->ehciItdList + (sizeof(usb_host_ehci_itd_t) * USB_HOST_CONFIG_EHCI_MAX_ITD)); - ehciInstance->ehciIsoList = (usb_host_ehci_iso_t *)((uint32_t)ehciInstance->ehciSitdList + + ehciInstance->ehciSitdList = ehciInstance->ehciSitdIndexBase; + ehciInstance->ehciIsoList = (usb_host_ehci_iso_t *)((uint32_t)ehciInstance->ehciSitdList + (sizeof(usb_host_ehci_sitd_t) * USB_HOST_CONFIG_EHCI_MAX_SITD)); ehciInstance->ehciPipeIndexBase = (usb_host_ehci_pipe_t *)((uint32_t)ehciInstance->ehciIsoList + (sizeof(usb_host_ehci_iso_t) * USB_HOST_EHCI_ISO_NUMBER)); - for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_QH; ++index) + for (index = 1U; index < USB_HOST_CONFIG_EHCI_MAX_QH; ++index) { - ehciInstance->ehciQhList[index - 1].horizontalLinkPointer = (uint32_t)(&ehciInstance->ehciQhList[index]); + ehciInstance->ehciQhList[index - 1U].horizontalLinkPointer = (uint32_t)(&ehciInstance->ehciQhList[index]); } - ehciInstance->ehciQhList[USB_HOST_CONFIG_EHCI_MAX_QH - 1].horizontalLinkPointer = (uint32_t)NULL; + ehciInstance->ehciQhList[USB_HOST_CONFIG_EHCI_MAX_QH - 1U].horizontalLinkPointer = 0U; for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_QTD; ++index) { - ehciInstance->ehciQtdHead[index - 1].nextQtdPointer = (uint32_t)(&ehciInstance->ehciQtdHead[index]); + ehciInstance->ehciQtdHead[index - 1U].nextQtdPointer = (uint32_t)(&ehciInstance->ehciQtdHead[index]); } - ehciInstance->ehciQtdNumber = USB_HOST_CONFIG_EHCI_MAX_QTD; - ehciInstance->ehciQtdHead[USB_HOST_CONFIG_EHCI_MAX_QTD - 1].nextQtdPointer = (uint32_t)NULL; - ehciInstance->ehciQtdTail = &ehciInstance->ehciQtdHead[USB_HOST_CONFIG_EHCI_MAX_QTD - 1]; + ehciInstance->ehciQtdNumber = USB_HOST_CONFIG_EHCI_MAX_QTD; + ehciInstance->ehciQtdHead[USB_HOST_CONFIG_EHCI_MAX_QTD - 1U].nextQtdPointer = 0U; + ehciInstance->ehciQtdTail = &ehciInstance->ehciQtdHead[USB_HOST_CONFIG_EHCI_MAX_QTD - 1U]; #if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_ITD; ++index) { - ehciInstance->ehciItdList[index - 1].nextLinkPointer = (uint32_t)(&ehciInstance->ehciItdList[index]); + ehciInstance->ehciItdList[index - 1U].nextItdPointer = + (usb_host_ehci_itd_t *)(&ehciInstance->ehciItdList[index]); } - ehciInstance->ehciItdNumber = USB_HOST_CONFIG_EHCI_MAX_ITD; - ehciInstance->ehciItdList[USB_HOST_CONFIG_EHCI_MAX_ITD - 1].nextLinkPointer = (uint32_t)NULL; + ehciInstance->ehciItdNumber = USB_HOST_CONFIG_EHCI_MAX_ITD; + ehciInstance->ehciItdList[USB_HOST_CONFIG_EHCI_MAX_ITD - 1U].nextItdPointer = NULL; #endif /* USB_HOST_CONFIG_EHCI_MAX_ITD */ #if ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD)) for (index = 1; index < USB_HOST_CONFIG_EHCI_MAX_SITD; ++index) { - ehciInstance->ehciSitdList[index - 1].nextLinkPointer = (uint32_t)(&ehciInstance->ehciSitdList[index]); + ehciInstance->ehciSitdList[index - 1U].nextLinkPointer = (uint32_t)(&ehciInstance->ehciSitdList[index]); } - ehciInstance->ehciSitdNumber = USB_HOST_CONFIG_EHCI_MAX_SITD; - ehciInstance->ehciSitdList[USB_HOST_CONFIG_EHCI_MAX_SITD - 1].nextLinkPointer = (uint32_t)NULL; + ehciInstance->ehciSitdNumber = USB_HOST_CONFIG_EHCI_MAX_SITD; + ehciInstance->ehciSitdList[USB_HOST_CONFIG_EHCI_MAX_SITD - 1U].nextLinkPointer = 0U; #endif /* USB_HOST_CONFIG_EHCI_MAX_SITD */ #if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) for (index = 1; index < USB_HOST_EHCI_ISO_NUMBER; ++index) { - ehciInstance->ehciIsoList[index - 1].next = &ehciInstance->ehciIsoList[index]; + ehciInstance->ehciIsoList[index - 1U].next = &ehciInstance->ehciIsoList[index]; } - ehciInstance->ehciIsoList[USB_HOST_EHCI_ISO_NUMBER - 1].next = NULL; + ehciInstance->ehciIsoList[USB_HOST_EHCI_ISO_NUMBER - 1U].next = NULL; #endif /* initialize pipes */ ehciInstance->ehciPipeList = ehciInstance->ehciPipeIndexBase; for (index = 1; index < USB_HOST_CONFIG_MAX_PIPES; ++index) { - ehciInstance->ehciPipeList[index - 1].pipeCommon.next = (usb_host_pipe_t *)&ehciInstance->ehciPipeList[index]; + temp = (void *)&ehciInstance->ehciPipeList[index]; + ehciInstance->ehciPipeList[index - 1U].pipeCommon.next = (usb_host_pipe_t *)temp; } /* initialize mutext */ - osaStatus = USB_OsaMutexCreate(&ehciInstance->ehciMutex); - if (osaStatus != kStatus_USB_OSA_Success) + ehciInstance->ehciMutex = (osa_mutex_handle_t)(&ehciInstance->mutexBuffer[0]); + osaStatus = OSA_MutexCreate(ehciInstance->ehciMutex); + if (osaStatus != KOSA_StatusSuccess) { #ifdef HOST_ECHO usb_echo("ehci mutex init fail\r\n"); #endif - USB_OsaMemoryFree(ehciInstance); + OSA_MemoryFree(ehciInstance); return kStatus_USB_Error; } /* initialize task event */ - osaStatus = USB_OsaEventCreate(&ehciInstance->taskEventHandle, 1); - if (osaStatus != kStatus_USB_OSA_Success) + ehciInstance->taskEventHandle = (osa_event_handle_t)&ehciInstance->taskEventHandleBuffer[0]; + osaStatus = OSA_EventCreate(ehciInstance->taskEventHandle, 1); + if (osaStatus != KOSA_StatusSuccess) { #ifdef HOST_ECHO usb_echo("ehci event init fail\r\n"); #endif - USB_OsaMutexDestroy(ehciInstance->ehciMutex); - USB_OsaMemoryFree(ehciInstance); + (void)OSA_MutexDestroy(ehciInstance->ehciMutex); + OSA_MemoryFree(ehciInstance); return kStatus_USB_Error; } @@ -4193,22 +4320,23 @@ usb_status_t USB_HostEhciCreate(uint8_t controllerId, ehciInstance->shedFirstQh = ehciInstance->ehciQhList; ehciInstance->ehciQhList = (usb_host_ehci_qh_t *)(ehciInstance->ehciQhList->horizontalLinkPointer & EHCI_HOST_POINTER_ADDRESS_MASK); - ehciInstance->shedFirstQh->staticEndpointStates[0] |= (1 << EHCI_HOST_QH_H_SHIFT); /* first qh */ - ehciInstance->shedFirstQh->horizontalLinkPointer = EHCI_HOST_T_INVALID_VALUE; - ehciInstance->shedFirstQh->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE; - ehciInstance->shedFirstQh->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; + ehciInstance->shedFirstQh->staticEndpointStates[0] |= (1UL << EHCI_HOST_QH_H_SHIFT); /* first qh */ + ehciInstance->shedFirstQh->horizontalLinkPointer = EHCI_HOST_T_INVALID_VALUE; + ehciInstance->shedFirstQh->currentQtdPointer = EHCI_HOST_T_INVALID_VALUE; + ehciInstance->shedFirstQh->nextQtdPointer = EHCI_HOST_T_INVALID_VALUE; ehciInstance->shedFirstQh->alternateNextQtdPointer = EHCI_HOST_T_INVALID_VALUE; ehciInstance->shedFirstQh->horizontalLinkPointer = (uint32_t)((uint32_t)(ehciInstance->shedFirstQh) | EHCI_HOST_POINTER_TYPE_QH); /* initialize periodic list */ - framePointer = (uint32_t *)ehciInstance->ehciFrameList; + temp = (void *)ehciInstance->ehciFrameList; + framePointer = (uint32_t *)temp; for (index = 0; index < USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE; ++index) { framePointer[index] = EHCI_HOST_T_INVALID_VALUE; } - USB_HostEhciStartIP(ehciInstance); /* start ehci ip */ + (void)USB_HostEhciStartIP(ehciInstance); /* start ehci ip */ *controllerHandle = ehciInstance; @@ -4223,10 +4351,29 @@ usb_status_t USB_HostEhciDestory(usb_host_controller_handle controllerHandle) ehciInstance->ehciIpBase->USBINTR = 0; /* stop the controller */ ehciInstance->ehciIpBase->USBCMD = 0; - /* free memory */ - USB_OsaMutexDestroy(ehciInstance->ehciMutex); - USB_OsaEventDestroy(ehciInstance->taskEventHandle); - USB_OsaMemoryFree(ehciInstance); +/* free memory */ +#if (USB_HOST_CONFIG_EHCI == 1U) + if (ehciInstance->ehciFrameList == &s_UsbHostEhciFrameList1[0]) + { + usbHostEhciFramListStatus[0] = 0; + } +#elif (USB_HOST_CONFIG_EHCI == 2U) + if (ehciInstance->ehciFrameList == &s_UsbHostEhciFrameList1[0]) + { + usbHostEhciFramListStatus[0] = 0; + } + else if (ehciInstance->ehciFrameList == &s_UsbHostEhciFrameList2[0]) + { + usbHostEhciFramListStatus[1] = 0; + } + else + { + /*no action*/ + } +#endif + (void)OSA_MutexDestroy(ehciInstance->ehciMutex); + (void)OSA_EventDestroy(ehciInstance->taskEventHandle); + OSA_MemoryFree(ehciInstance); return kStatus_USB_Success; } @@ -4237,15 +4384,17 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle, { usb_host_ehci_pipe_t *ehciPipePointer = NULL; usb_status_t status; - uint32_t speed; + uint32_t speed = 0; usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle; - + uint32_t val32; + void *temp; /* get one pipe */ USB_HostEhciLock(); if (ehciInstance->ehciPipeList != NULL) { - ehciPipePointer = ehciInstance->ehciPipeList; - ehciInstance->ehciPipeList = (usb_host_ehci_pipe_t *)ehciPipePointer->pipeCommon.next; + ehciPipePointer = ehciInstance->ehciPipeList; + temp = (void *)ehciPipePointer->pipeCommon.next; + ehciInstance->ehciPipeList = (usb_host_ehci_pipe_t *)temp; } USB_HostEhciUnlock(); if (ehciPipePointer == NULL) @@ -4257,43 +4406,53 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle, } /* initialize pipe informations */ - USB_HostEhciZeroMem((uint32_t *)ehciPipePointer, sizeof(usb_host_ehci_pipe_t) / 4); - ehciPipePointer->pipeCommon.deviceHandle = pipeInit->devInstance; + USB_HostEhciZeroMem((void *)ehciPipePointer, sizeof(usb_host_ehci_pipe_t) / 4U); + ehciPipePointer->pipeCommon.deviceHandle = pipeInit->devInstance; ehciPipePointer->pipeCommon.endpointAddress = pipeInit->endpointAddress; - ehciPipePointer->pipeCommon.direction = pipeInit->direction; - ehciPipePointer->pipeCommon.interval = pipeInit->interval; - ehciPipePointer->pipeCommon.maxPacketSize = pipeInit->maxPacketSize; - ehciPipePointer->pipeCommon.pipeType = pipeInit->pipeType; - ehciPipePointer->pipeCommon.numberPerUframe = pipeInit->numberPerUframe; - if (ehciPipePointer->pipeCommon.numberPerUframe == 0) + ehciPipePointer->pipeCommon.direction = pipeInit->direction; + ehciPipePointer->pipeCommon.interval = pipeInit->interval; + ehciPipePointer->pipeCommon.maxPacketSize = pipeInit->maxPacketSize; + ehciPipePointer->pipeCommon.pipeType = pipeInit->pipeType; + ehciPipePointer->pipeCommon.numberPerUframe = pipeInit->numberPerUframe + 1U; + if (ehciPipePointer->pipeCommon.numberPerUframe > 3U) { - ehciPipePointer->pipeCommon.numberPerUframe = 1; + ehciPipePointer->pipeCommon.numberPerUframe = 3U; } - ehciPipePointer->pipeCommon.nakCount = pipeInit->nakCount; - ehciPipePointer->pipeCommon.nextdata01 = 0; - ehciPipePointer->ehciQh = NULL; - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, &speed); - if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) + ehciPipePointer->pipeCommon.nakCount = pipeInit->nakCount; + ehciPipePointer->pipeCommon.nextdata01 = 0U; + ehciPipePointer->ehciQh = NULL; + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); + if ((ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) || + (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT)) { - ehciPipePointer->pipeCommon.interval = - (1 << (ehciPipePointer->pipeCommon.interval - 1)); /* iso interval is the power of 2 */ - } - else if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_INTERRUPT) - { - if (speed == USB_SPEED_HIGH) + if (ehciPipePointer->pipeCommon.pipeType == USB_ENDPOINT_ISOCHRONOUS) { ehciPipePointer->pipeCommon.interval = - (1 << (ehciPipePointer->pipeCommon.interval - 1)); /* HS interrupt interval is the power of 2 */ + (uint16_t)(1UL << (ehciPipePointer->pipeCommon.interval - 1U)); /* iso interval is the power of 2 */ } else { - ehciPipePointer->pipeCommon.interval = USB_HostEhciGet2PowerValue( - ehciPipePointer->pipeCommon - .interval); /* FS/LS interrupt interval should be the power of 2, it is used for ehci bandwidth */ + if (speed == USB_SPEED_HIGH) + { + ehciPipePointer->pipeCommon.interval = (uint16_t)( + 1UL << (ehciPipePointer->pipeCommon.interval - 1U)); /* HS interrupt interval is the power of 2 */ + } + else + { + ehciPipePointer->pipeCommon.interval = USB_HostEhciGet2PowerValue( + (uint8_t)ehciPipePointer->pipeCommon.interval); /* FS/LS interrupt interval should be the power of + 2, it is used for ehci bandwidth */ + } + } + + if ((speed == USB_SPEED_HIGH) && (ehciPipePointer->pipeCommon.interval < 8U)) + { + val32 = ehciInstance->ehciIpBase->USBCMD; + val32 &= (~USBHS_USBCMD_ITC_MASK); + val32 |= USBHS_USBCMD_ITC((ehciPipePointer->pipeCommon.interval)); + ehciInstance->ehciIpBase->USBCMD = val32; } - } - else - { } /* save the micro-frame interval, it is convenient for the interval process */ @@ -4303,7 +4462,7 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle, } else { - ehciPipePointer->uframeInterval = 8 * ehciPipePointer->pipeCommon.interval; + ehciPipePointer->uframeInterval = 8U * ehciPipePointer->pipeCommon.interval; } /* open pipe */ @@ -4334,15 +4493,17 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle, { /* release pipe */ USB_HostEhciLock(); - ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)ehciInstance->ehciPipeList; - ehciInstance->ehciPipeList = ehciPipePointer; + temp = (void *)ehciInstance->ehciPipeList; + ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)temp; + ehciInstance->ehciPipeList = ehciPipePointer; USB_HostEhciUnlock(); return status; } /* add pipe to run pipe list */ USB_HostEhciLock(); - ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)ehciInstance->ehciRunningPipeList; + temp = (void *)ehciInstance->ehciRunningPipeList; + ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)temp; ehciInstance->ehciRunningPipeList = ehciPipePointer; USB_HostEhciUnlock(); @@ -4353,43 +4514,50 @@ usb_status_t USB_HostEhciOpenPipe(usb_host_controller_handle controllerHandle, usb_status_t USB_HostEhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle) { usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle; - usb_host_ehci_pipe_t *ehciPipePointer = (usb_host_ehci_pipe_t *)pipeHandle; - usb_host_pipe_t *prevPointer = NULL; + usb_host_ehci_pipe_t *ehciPipePointer = (usb_host_ehci_pipe_t *)pipeHandle; + usb_host_pipe_t *prevPointer = NULL; + void *temp; + void *tempCurrent; switch (ehciPipePointer->pipeCommon.pipeType) { case USB_ENDPOINT_BULK: case USB_ENDPOINT_CONTROL: - USB_HostEhciCloseControlBulk(ehciInstance, ehciPipePointer); + (void)USB_HostEhciCloseControlBulk(ehciInstance, ehciPipePointer); break; case USB_ENDPOINT_INTERRUPT: - USB_HostEhciCloseInterrupt(ehciInstance, ehciPipePointer); + (void)USB_HostEhciCloseInterrupt(ehciInstance, ehciPipePointer); break; #if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \ ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))) case USB_ENDPOINT_ISOCHRONOUS: - USB_HostEhciCloseIso(ehciInstance, ehciPipePointer); + (void)USB_HostEhciCloseIso(ehciInstance, ehciPipePointer); break; #endif default: + /*no action*/ break; } /* delete pipe from run pipe list */ USB_HostEhciLock(); - prevPointer = (usb_host_pipe_t *)ehciInstance->ehciRunningPipeList; - if (prevPointer == (usb_host_pipe_t *)ehciPipePointer) + temp = (void *)ehciInstance->ehciRunningPipeList; + prevPointer = (usb_host_pipe_t *)temp; + tempCurrent = (void *)ehciPipePointer; + if (prevPointer == (usb_host_pipe_t *)tempCurrent) { - ehciInstance->ehciRunningPipeList = (usb_host_ehci_pipe_t *)(prevPointer->next); + temp = (void *)prevPointer->next; + ehciInstance->ehciRunningPipeList = (usb_host_ehci_pipe_t *)(temp); } else { while (prevPointer != NULL) { - if (prevPointer->next == (usb_host_pipe_t *)ehciPipePointer) + temp = (void *)ehciPipePointer; + if (prevPointer->next == (usb_host_pipe_t *)temp) { prevPointer->next = ehciPipePointer->pipeCommon.next; break; @@ -4404,8 +4572,9 @@ usb_status_t USB_HostEhciClosePipe(usb_host_controller_handle controllerHandle, /* release pipe */ USB_HostEhciLock(); - ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)ehciInstance->ehciPipeList; - ehciInstance->ehciPipeList = ehciPipePointer; + temp = (void *)ehciInstance->ehciPipeList; + ehciPipePointer->pipeCommon.next = (usb_host_pipe_t *)temp; + ehciInstance->ehciPipeList = ehciPipePointer; USB_HostEhciUnlock(); return kStatus_USB_Success; @@ -4416,11 +4585,11 @@ usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerHandle, usb_host_transfer_t *transfer) { usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle; - usb_host_ehci_pipe_t *ehciPipePointer = (usb_host_ehci_pipe_t *)pipeHandle; - usb_status_t status = kStatus_USB_Success; + usb_host_ehci_pipe_t *ehciPipePointer = (usb_host_ehci_pipe_t *)pipeHandle; + usb_status_t status = kStatus_USB_Success; #if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \ ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))) - uint32_t speed; + uint32_t speed = 0U; #endif switch (ehciPipePointer->pipeCommon.pipeType) @@ -4435,8 +4604,8 @@ usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerHandle, #if (((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) || \ ((defined USB_HOST_CONFIG_EHCI_MAX_SITD) && (USB_HOST_CONFIG_EHCI_MAX_SITD))) case USB_ENDPOINT_ISOCHRONOUS: - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceSpeed, - &speed); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceSpeed, &speed); if (speed == USB_SPEED_HIGH) { #if ((defined USB_HOST_CONFIG_EHCI_MAX_ITD) && (USB_HOST_CONFIG_EHCI_MAX_ITD)) @@ -4455,6 +4624,7 @@ usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerHandle, #endif default: + /*no action*/ break; } return status; @@ -4469,22 +4639,22 @@ usb_status_t USB_HostEhciReadpipe(usb_host_controller_handle controllerHandle, usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandle, uint32_t ioctlEvent, void *ioctlParam) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_ehci_instance_t *ehciInstance = (usb_host_ehci_instance_t *)controllerHandle; usb_host_cancel_param_t *param; usb_host_ehci_pipe_t *ehciPipePointer; volatile usb_host_ehci_qh_t *vltQhPointer; - uint32_t deviceAddress; - + uint32_t deviceAddress = 0; + usb_host_controller_control_t controlCode = (usb_host_controller_control_t)ioctlEvent; if (controllerHandle == NULL) { return kStatus_USB_InvalidHandle; } - switch (ioctlEvent) + switch (controlCode) { case kUSB_HostCancelTransfer: /* cancel pipe or one transfer */ - param = (usb_host_cancel_param_t *)ioctlParam; + param = (usb_host_cancel_param_t *)ioctlParam; status = USB_HostEhciCancelPipe(ehciInstance, (usb_host_ehci_pipe_t *)param->pipeHandle, param->transfer); break; @@ -4498,18 +4668,19 @@ usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandle, uint case kUSB_HostUpdateControlEndpointAddress: ehciPipePointer = (usb_host_ehci_pipe_t *)ioctlParam; - vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; + vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; /* update address */ - USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, kUSB_HostGetDeviceAddress, - &deviceAddress); + (void)USB_HostHelperGetPeripheralInformation(ehciPipePointer->pipeCommon.deviceHandle, + (uint32_t)kUSB_HostGetDeviceAddress, &deviceAddress); vltQhPointer->staticEndpointStates[0] |= deviceAddress; + USB_HostEhciDelay(ehciInstance->ehciIpBase, 2U); break; case kUSB_HostUpdateControlPacketSize: ehciPipePointer = (usb_host_ehci_pipe_t *)ioctlParam; - vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; + vltQhPointer = (volatile usb_host_ehci_qh_t *)ehciPipePointer->ehciQh; USB_HostEhciLock(); - if (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK) + if (0U != (ehciInstance->ehciIpBase->USBSTS & USBHS_USBSTS_AS_MASK)) { USB_HostEhciStopAsync(ehciInstance); /* update max packet size */ @@ -4527,8 +4698,13 @@ usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandle, uint } USB_HostEhciUnlock(); break; - +#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) + case kUSB_HostTestModeInit: /* test mode control */ + USB_HostEhciTestModeInit((usb_host_device_instance_t *)ioctlParam); + break; +#endif default: + status = kStatus_USB_NotSupported; break; } return status; @@ -4546,44 +4722,44 @@ void USB_HostEhciTaskFunction(void *hostHandle) } ehciInstance = (usb_host_ehci_instance_t *)((usb_host_instance_t *)hostHandle)->controllerHandle; - if (USB_OsaEventWait(ehciInstance->taskEventHandle, 0xFF, 0, 0, &bitSet) == - kStatus_USB_OSA_Success) /* wait all event */ + if (OSA_EventWait(ehciInstance->taskEventHandle, 0xFF, 0, USB_OSA_WAIT_TIMEOUT, &bitSet) == + KOSA_StatusSuccess) /* wait all event */ { - if (bitSet & EHCI_TASK_EVENT_PORT_CHANGE) /* port change */ + if (0U != (bitSet & EHCI_TASK_EVENT_PORT_CHANGE)) /* port change */ { USB_HostEhciPortChange(ehciInstance); } - if (bitSet & EHCI_TASK_EVENT_TIMER0) /* timer0 */ + if (0U != (bitSet & EHCI_TASK_EVENT_TIMER0)) /* timer0 */ { USB_HostEhciTimer0(ehciInstance); } #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) - if (bitSet & EHCI_TASK_EVENT_TIMER1) /* timer1 */ + if (0U != (bitSet & EHCI_TASK_EVENT_TIMER1)) /* timer1 */ { USB_HostEhciTimer1(ehciInstance); } #endif - if (ehciInstance->deviceAttached == kEHCIDeviceAttached) + if ((ehciInstance->deviceAttached == (uint8_t)kEHCIDeviceAttached)) { - if (bitSet & EHCI_TASK_EVENT_TRANSACTION_DONE) /* transaction done */ + if (0U != (bitSet & EHCI_TASK_EVENT_TRANSACTION_DONE)) /* transaction done */ { USB_HostEhciTransactionDone(ehciInstance); } - if (bitSet & EHCI_TASK_EVENT_DEVICE_DETACH) /* device detach */ + if (0U != (bitSet & EHCI_TASK_EVENT_DEVICE_DETACH)) /* device detach */ { ehciInstance->ehciIpBase->USBINTR &= (~USBHS_USBINTR_PCE_MASK); /* disable attach, enable when the detach process is done */ - ehciInstance->deviceAttached = kEHCIDeviceDetached; - USB_HostDetachDevice(ehciInstance->hostHandle, 0, 0); + ehciInstance->deviceAttached = (uint8_t)kEHCIDeviceDetached; + (void)USB_HostDetachDevice(ehciInstance->hostHandle, 0, 0); } } - else if (ehciInstance->deviceAttached != kEHCIDeviceAttached) + else if (ehciInstance->deviceAttached != (uint8_t)kEHCIDeviceAttached) { - if (bitSet & EHCI_TASK_EVENT_DEVICE_ATTACH) /* device is attached */ + if (0U != (bitSet & EHCI_TASK_EVENT_DEVICE_ATTACH)) /* device is attached */ { USB_HostEhciStartAsync(ehciInstance); USB_HostEhciStartPeriodic(ehciInstance); @@ -4591,12 +4767,13 @@ void USB_HostEhciTaskFunction(void *hostHandle) if (USB_HostAttachDevice(ehciInstance->hostHandle, ehciInstance->firstDeviceSpeed, 0, 0, 1, &deviceHandle) == kStatus_USB_Success) { - ehciInstance->deviceAttached = kEHCIDeviceAttached; + ehciInstance->deviceAttached = (uint8_t)kEHCIDeviceAttached; } } } else { + /*no action*/ } } } @@ -4616,18 +4793,18 @@ void USB_HostEhciIsrFunction(void *hostHandle) #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) #if (defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 0U)) - if (ehciInstance->registerNcBase->USB_OTGn_CTRL & USBNC_USB_OTGn_CTRL_WIE_MASK) + if (0U != (ehciInstance->registerNcBase->USB_OTGn_CTRL & USBNC_USB_OTGn_CTRL_WIE_MASK)) { usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle; ehciInstance->registerNcBase->USB_OTGn_CTRL &= ~USBNC_USB_OTGn_CTRL_WIE_MASK; - hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, - kUSB_HostEventDetectResume); /* call host callback function */ - - while (!(ehciInstance->registerNcBase->USB_OTGn_PHY_CTRL_0 & USBNC_USB_OTGn_PHY_CTRL_0_UTMI_CLK_VLD_MASK)) + (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventDetectResume); /* call host callback function */ +#if (defined(USBNC_USB_OTGn_PHY_CTRL_0_UTMI_CLK_VLD_MASK)) + while (0U == (ehciInstance->registerNcBase->USB_OTGn_PHY_CTRL_0 & USBNC_USB_OTGn_PHY_CTRL_0_UTMI_CLK_VLD_MASK)) { } - - if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK) +#endif + if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) { USB_HostEhciStartAsync(ehciInstance); USB_HostEhciStartPeriodic(ehciInstance); @@ -4640,25 +4817,27 @@ void USB_HostEhciIsrFunction(void *hostHandle) } else { + /*no action*/ } } else { + /*no action*/ } #else - if (ehciInstance->ehciIpBase->USBGENCTRL & USBHS_USBGENCTRL_WU_IE_MASK) + if (0U != (ehciInstance->ehciIpBase->USBGENCTRL & USBHS_USBGENCTRL_WU_IE_MASK)) { usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle; - hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, - kUSB_HostEventDetectResume); /* call host callback function */ + (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventDetectResume); /* call host callback function */ - while (!(USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK)) + while (0U == (USBPHY->PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK_MASK)) { } ehciInstance->ehciIpBase->USBGENCTRL |= USBHS_USBGENCTRL_WU_INT_CLR_MASK; ehciInstance->ehciIpBase->USBGENCTRL &= ~USBHS_USBGENCTRL_WU_IE_MASK; - if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK) + if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) { USB_HostEhciStartAsync(ehciInstance); USB_HostEhciStartPeriodic(ehciInstance); @@ -4671,10 +4850,12 @@ void USB_HostEhciIsrFunction(void *hostHandle) } else { + /*no action*/ } } else { + /*no action*/ } #endif /* FSL_FEATURE_SOC_USBNC_COUNT */ @@ -4682,60 +4863,61 @@ void USB_HostEhciIsrFunction(void *hostHandle) interruptStatus = ehciInstance->ehciIpBase->USBSTS; interruptStatus &= ehciInstance->ehciIpBase->USBINTR; - while (interruptStatus) /* there are usb interrupts */ + while (0U != interruptStatus) /* there are usb interrupts */ { ehciInstance->ehciIpBase->USBSTS = interruptStatus; /* clear interrupt */ - if (interruptStatus & USBHS_USBSTS_SRI_MASK) /* SOF interrupt */ + if (0U != (interruptStatus & USBHS_USBSTS_SRI_MASK)) /* SOF interrupt */ { } - if (interruptStatus & USBHS_USBSTS_SEI_MASK) /* system error interrupt */ + if (0U != (interruptStatus & USBHS_USBSTS_SEI_MASK)) /* system error interrupt */ { } - if ((interruptStatus & USBHS_USBSTS_UI_MASK) || - (interruptStatus & USBHS_USBSTS_UEI_MASK)) /* USB interrupt or USB error interrupt */ + if ((0U != (interruptStatus & USBHS_USBSTS_UI_MASK)) || + (0U != (interruptStatus & USBHS_USBSTS_UEI_MASK))) /* USB interrupt or USB error interrupt */ { - USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TRANSACTION_DONE); + (void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TRANSACTION_DONE); } - if (interruptStatus & USBHS_USBSTS_PCI_MASK) /* port change detect interrupt */ + if (0U != (interruptStatus & USBHS_USBSTS_PCI_MASK)) /* port change detect interrupt */ { #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) usb_host_instance_t *hostPointer = (usb_host_instance_t *)ehciInstance->hostHandle; - if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_FPR_MASK) + if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_FPR_MASK)) { if (kBus_EhciStartSuspend == ehciInstance->busSuspendStatus) { - if (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK) + if (0U != (ehciInstance->ehciIpBase->PORTSC1 & USBHS_PORTSC1_CCS_MASK)) { USB_HostEhciStartAsync(ehciInstance); USB_HostEhciStartPeriodic(ehciInstance); } - hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, - kUSB_HostEventNotSuspended); /* call host callback function */ - hostPointer->suspendedDevice = NULL; + (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL, + kUSB_HostEventNotSuspended); /* call host callback function */ + hostPointer->suspendedDevice = NULL; ehciInstance->busSuspendStatus = kBus_EhciIdle; ehciInstance->ehciIpBase->USBINTR &= ~(USBHS_USBINTR_TIE1_MASK); } else { + /*no action */ } } #endif - USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_PORT_CHANGE); + (void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_PORT_CHANGE); } - if (interruptStatus & USBHS_USBSTS_TI0_MASK) /* timer 0 interrupt */ + if (0U != (interruptStatus & USBHS_USBSTS_TI0_MASK)) /* timer 0 interrupt */ { - USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TIMER0); + (void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TIMER0); } #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) - if (interruptStatus & USBHS_USBSTS_TI1_MASK) /* timer 1 interrupt */ + if (0U != (interruptStatus & USBHS_USBSTS_TI1_MASK)) /* timer 1 interrupt */ { - USB_OsaEventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TIMER1); + (void)OSA_EventSet(ehciInstance->taskEventHandle, EHCI_TASK_EVENT_TIMER1); } #endif @@ -4744,4 +4926,4 @@ void USB_HostEhciIsrFunction(void *hostHandle) } } -#endif /* USB_HOST_CONFIG_EHCI */ +#endif /* USB_HOST_CONFIG_EHCI */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h index 162d6576cd..c67f8baa40 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_ehci.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016,2019 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _USB_HOST_CONTROLLER_EHCI_H_ @@ -39,95 +17,95 @@ * Definitions ******************************************************************************/ /* EHCI host macros */ -#define EHCI_HOST_T_INVALID_VALUE (1U) -#define EHCI_HOST_POINTER_TYPE_ITD (0x00U) -#define EHCI_HOST_POINTER_TYPE_QH (0x00000002U) -#define EHCI_HOST_POINTER_TYPE_SITD (0x00000004U) -#define EHCI_HOST_POINTER_TYPE_FSTN (0x00000006U) -#define EHCI_HOST_POINTER_TYPE_MASK (0x00000006U) +#define EHCI_HOST_T_INVALID_VALUE (1U) +#define EHCI_HOST_POINTER_TYPE_ITD (0x00U) +#define EHCI_HOST_POINTER_TYPE_QH (0x00000002U) +#define EHCI_HOST_POINTER_TYPE_SITD (0x00000004U) +#define EHCI_HOST_POINTER_TYPE_FSTN (0x00000006U) +#define EHCI_HOST_POINTER_TYPE_MASK (0x00000006U) #define EHCI_HOST_POINTER_ADDRESS_MASK (0xFFFFFFE0U) -#define EHCI_HOST_PID_OUT (0U) -#define EHCI_HOST_PID_IN (1U) -#define EHCI_HOST_PID_SETUP (2U) +#define EHCI_HOST_PID_OUT (0UL) +#define EHCI_HOST_PID_IN (1UL) +#define EHCI_HOST_PID_SETUP (2UL) -#define EHCI_HOST_QH_RL_SHIFT (28U) -#define EHCI_HOST_QH_RL_MASK (0xF0000000U) -#define EHCI_HOST_QH_C_SHIFT (27U) -#define EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT (16U) -#define EHCI_HOST_QH_MAX_PACKET_LENGTH_MASK (0x07FF0000U) -#define EHCI_HOST_QH_H_SHIFT (15U) -#define EHCI_HOST_QH_DTC_SHIFT (14U) -#define EHCI_HOST_QH_EPS_SHIFT (12U) -#define EHCI_HOST_QH_ENDPT_SHIFT (8U) -#define EHCI_HOST_QH_I_SHIFT (7U) -#define EHCI_HOST_QH_DEVICE_ADDRESS_SHIFT (0U) -#define EHCI_HOST_QH_MULT_SHIFT (30U) -#define EHCI_HOST_QH_PORT_NUMBER_SHIFT (23U) -#define EHCI_HOST_QH_HUB_ADDR_SHIFT (16U) -#define EHCI_HOST_QH_UFRAME_CMASK_SHIFT (8U) -#define EHCI_HOST_QH_UFRAME_SMASK_SHIFT (0U) -#define EHCI_HOST_QH_STATUS_ERROR_MASK (0x0000007EU) +#define EHCI_HOST_QH_RL_SHIFT (28U) +#define EHCI_HOST_QH_RL_MASK (0xF0000000U) +#define EHCI_HOST_QH_C_SHIFT (27U) +#define EHCI_HOST_QH_MAX_PACKET_LENGTH_SHIFT (16U) +#define EHCI_HOST_QH_MAX_PACKET_LENGTH_MASK (0x07FF0000U) +#define EHCI_HOST_QH_H_SHIFT (15U) +#define EHCI_HOST_QH_DTC_SHIFT (14U) +#define EHCI_HOST_QH_EPS_SHIFT (12U) +#define EHCI_HOST_QH_ENDPT_SHIFT (8U) +#define EHCI_HOST_QH_I_SHIFT (7U) +#define EHCI_HOST_QH_DEVICE_ADDRESS_SHIFT (0U) +#define EHCI_HOST_QH_MULT_SHIFT (30U) +#define EHCI_HOST_QH_PORT_NUMBER_SHIFT (23U) +#define EHCI_HOST_QH_HUB_ADDR_SHIFT (16U) +#define EHCI_HOST_QH_UFRAME_CMASK_SHIFT (8U) +#define EHCI_HOST_QH_UFRAME_SMASK_SHIFT (0U) +#define EHCI_HOST_QH_STATUS_ERROR_MASK (0x0000007EU) #define EHCI_HOST_QH_STATUS_NOSTALL_ERROR_MASK (0x0000003EU) -#define EHCI_HOST_QTD_DT_SHIFT (31U) -#define EHCI_HOST_QTD_DT_MASK (0x80000000U) -#define EHCI_HOST_QTD_TOTAL_BYTES_SHIFT (16U) -#define EHCI_HOST_QTD_TOTAL_BYTES_MASK (0x7FFF0000U) -#define EHCI_HOST_QTD_IOC_MASK (0x00008000U) -#define EHCI_HOST_QTD_C_PAGE_SHIFT (12U) -#define EHCI_HOST_QTD_CERR_SHIFT (10U) -#define EHCI_HOST_QTD_CERR_MAX_VALUE (0x00000003U) -#define EHCI_HOST_QTD_PID_CODE_SHIFT (8U) -#define EHCI_HOST_QTD_STATUS_SHIFT (0U) -#define EHCI_HOST_QTD_CURRENT_OFFSET_MASK (0x00000FFFU) -#define EHCI_HOST_QTD_BUFFER_POINTER_SHIFT (12U) -#define EHCI_HOST_QTD_STATUS_ACTIVE_MASK (0x00000080U) -#define EHCI_HOST_QTD_STATUS_MASK (0x000000ffU) -#define EHCI_HOST_QTD_STATUS_ERROR_MASK (0x0000007EU) +#define EHCI_HOST_QTD_DT_SHIFT (31U) +#define EHCI_HOST_QTD_DT_MASK (0x80000000U) +#define EHCI_HOST_QTD_TOTAL_BYTES_SHIFT (16U) +#define EHCI_HOST_QTD_TOTAL_BYTES_MASK (0x7FFF0000U) +#define EHCI_HOST_QTD_IOC_MASK (0x00008000U) +#define EHCI_HOST_QTD_C_PAGE_SHIFT (12U) +#define EHCI_HOST_QTD_CERR_SHIFT (10U) +#define EHCI_HOST_QTD_CERR_MAX_VALUE (0x00000003UL) +#define EHCI_HOST_QTD_PID_CODE_SHIFT (8U) +#define EHCI_HOST_QTD_STATUS_SHIFT (0U) +#define EHCI_HOST_QTD_CURRENT_OFFSET_MASK (0x00000FFFU) +#define EHCI_HOST_QTD_BUFFER_POINTER_SHIFT (12U) +#define EHCI_HOST_QTD_STATUS_ACTIVE_MASK (0x00000080U) +#define EHCI_HOST_QTD_STATUS_MASK (0x000000ffU) +#define EHCI_HOST_QTD_STATUS_ERROR_MASK (0x0000007EU) #define EHCI_HOST_QTD_STATUS_STALL_ERROR_MASK (0x00000040U) -#define EHCI_HOST_ITD_STATUS_ACTIVE_MASK (0x80000000U) -#define EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT (16U) -#define EHCI_HOST_ITD_TRANSACTION_LEN_MASK (0x0FFF0000U) -#define EHCI_HOST_ITD_IOC_SHIFT (15U) -#define EHCI_HOST_ITD_PG_SHIFT (12U) +#define EHCI_HOST_ITD_STATUS_ACTIVE_MASK (0x80000000U) +#define EHCI_HOST_ITD_TRANSACTION_LEN_SHIFT (16U) +#define EHCI_HOST_ITD_TRANSACTION_LEN_MASK (0x0FFF0000U) +#define EHCI_HOST_ITD_IOC_SHIFT (15U) +#define EHCI_HOST_ITD_PG_SHIFT (12U) #define EHCI_HOST_ITD_TRANSACTION_OFFSET_SHIFT (0U) -#define EHCI_HOST_ITD_TRANSACTION_OFFSET_MASK (0x00000FFFU) -#define EHCI_HOST_ITD_BUFFER_POINTER_SHIFT (12U) -#define EHCI_HOST_ITD_ENDPT_SHIFT (8U) -#define EHCI_HOST_ITD_DEVICE_ADDRESS_SHIFT (0U) -#define EHCI_HOST_ITD_MAX_PACKET_SIZE_SHIFT (0U) -#define EHCI_HOST_ITD_MULT_SHIFT (0U) -#define EHCI_HOST_ITD_DIRECTION_SHIFT (11U) +#define EHCI_HOST_ITD_TRANSACTION_OFFSET_MASK (0x00000FFFU) +#define EHCI_HOST_ITD_BUFFER_POINTER_SHIFT (12U) +#define EHCI_HOST_ITD_ENDPT_SHIFT (8U) +#define EHCI_HOST_ITD_DEVICE_ADDRESS_SHIFT (0U) +#define EHCI_HOST_ITD_MAX_PACKET_SIZE_SHIFT (0U) +#define EHCI_HOST_ITD_MULT_SHIFT (0U) +#define EHCI_HOST_ITD_DIRECTION_SHIFT (11U) -#define EHCI_HOST_SITD_STATUS_ACTIVE_MASK (0x00000080U) -#define EHCI_HOST_SITD_DIRECTION_SHIFT (31U) -#define EHCI_HOST_SITD_PORT_NUMBER_SHIFT (24U) -#define EHCI_HOST_SITD_HUB_ADDR_SHIFT (16U) -#define EHCI_HOST_SITD_ENDPT_SHIFT (8U) +#define EHCI_HOST_SITD_STATUS_ACTIVE_MASK (0x00000080U) +#define EHCI_HOST_SITD_DIRECTION_SHIFT (31U) +#define EHCI_HOST_SITD_PORT_NUMBER_SHIFT (24U) +#define EHCI_HOST_SITD_HUB_ADDR_SHIFT (16U) +#define EHCI_HOST_SITD_ENDPT_SHIFT (8U) #define EHCI_HOST_SITD_DEVICE_ADDRESS_SHIFT (0U) -#define EHCI_HOST_SITD_CMASK_SHIFT (8U) -#define EHCI_HOST_SITD_SMASK_SHIFT (0U) -#define EHCI_HOST_SITD_TOTAL_BYTES_SHIFT (16U) -#define EHCI_HOST_SITD_TOTAL_BYTES_MASK (0x03FF0000U) -#define EHCI_HOST_SITD_TP_SHIFT (3U) -#define EHCI_HOST_SITD_TCOUNT_SHIFT (0U) -#define EHCI_HOST_SITD_IOC_SHIFT (31U) +#define EHCI_HOST_SITD_CMASK_SHIFT (8U) +#define EHCI_HOST_SITD_SMASK_SHIFT (0U) +#define EHCI_HOST_SITD_TOTAL_BYTES_SHIFT (16U) +#define EHCI_HOST_SITD_TOTAL_BYTES_MASK (0x03FF0000U) +#define EHCI_HOST_SITD_TP_SHIFT (3U) +#define EHCI_HOST_SITD_TCOUNT_SHIFT (0U) +#define EHCI_HOST_SITD_IOC_SHIFT (31U) /* register related MACROs */ -#define EHCI_PORTSC1_W1_BITS (0x0000002AU) +#define EHCI_PORTSC1_W1_BITS (0x0000002AU) #define EHCI_MAX_UFRAME_VALUE (0x00003FFFU) /* task event */ -#define EHCI_TASK_EVENT_DEVICE_ATTACH (0x01U) +#define EHCI_TASK_EVENT_DEVICE_ATTACH (0x01U) #define EHCI_TASK_EVENT_TRANSACTION_DONE (0x02U) -#define EHCI_TASK_EVENT_DEVICE_DETACH (0x04U) -#define EHCI_TASK_EVENT_PORT_CHANGE (0x08U) -#define EHCI_TASK_EVENT_TIMER0 (0x10U) -#define EHCI_TASK_EVENT_TIMER1 (0x20U) +#define EHCI_TASK_EVENT_DEVICE_DETACH (0x04U) +#define EHCI_TASK_EVENT_PORT_CHANGE (0x08U) +#define EHCI_TASK_EVENT_TIMER0 (0x10U) +#define EHCI_TASK_EVENT_TIMER1 (0x20U) -#define USB_HostEhciLock() USB_OsaMutexLock(ehciInstance->ehciMutex) -#define USB_HostEhciUnlock() USB_OsaMutexUnlock(ehciInstance->ehciMutex) +#define USB_HostEhciLock() (void)OSA_MutexLock(ehciInstance->ehciMutex, USB_OSA_WAIT_TIMEOUT) +#define USB_HostEhciUnlock() (void)OSA_MutexUnlock(ehciInstance->ehciMutex) /******************************************************************************* * KHCI driver public structures, enumerations, macros, functions @@ -144,6 +122,8 @@ #define USB_HOST_EHCI_PORT_CONNECT_DEBOUNCE_DELAY (101U) /*! @brief Delay for port reset */ #define USB_HOST_EHCI_PORT_RESET_DELAY (11U) +/*! @brief The MAX continuous transfers that application can send. */ +#define USB_HOST_EHCI_ISO_MAX_CONTINUOUS_TRANSFER (8U) /*! @brief The SITD inserts a frame interval for putting more SITD continuously. * There is an interval when an application sends two FS/LS ISO transfers. * When the interval is less than the macro, the two transfers are continuous in the frame list. Otherwise, the two @@ -171,7 +151,7 @@ */ #define USB_HOST_EHCI_ISO_BOUNCE_UFRAME_NUMBER (16U) /*! @brief Control or bulk transaction timeout value (unit: 100 ms) */ -#define USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE (20U) +#define USB_HOST_EHCI_CONTROL_BULK_TIME_OUT_VALUE (50U) #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) typedef enum _bus_ehci_suspend_request_state @@ -323,8 +303,10 @@ typedef struct _usb_host_ehci_instance usb_host_ehci_pipe_t *ehciPipeIndexBase; /*!< Pipe buffer's start pointer*/ usb_host_ehci_pipe_t *ehciPipeList; /*!< Idle pipe list pointer*/ usb_host_ehci_pipe_t *ehciRunningPipeList; /*!< Running pipe list pointer*/ - usb_osa_mutex_handle ehciMutex; /*!< EHCI mutex*/ - usb_osa_event_handle taskEventHandle; /*!< EHCI task event*/ + osa_mutex_handle_t ehciMutex; /*!< EHCI mutex*/ + uint32_t mutexBuffer[(OSA_MUTEX_HANDLE_SIZE + 3) / 4]; /*!< The mutex buffer. */ + osa_event_handle_t taskEventHandle; /*!< EHCI task event*/ + uint32_t taskEventHandleBuffer[(OSA_EVENT_HANDLE_SIZE + 3) / 4]; /*!< EHCI task event handle buffer*/ #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) uint64_t matchTick; USBPHY_Type *registerPhyBase; /*!< The base address of the PHY register */ @@ -355,6 +337,10 @@ typedef struct _usb_host_ehci_data #endif #if ((defined(USB_HOST_CONFIG_EHCI_MAX_ITD)) && (USB_HOST_CONFIG_EHCI_MAX_ITD > 0U)) usb_host_ehci_itd_t ehciItd[USB_HOST_CONFIG_EHCI_MAX_ITD]; /*!< Idle ITD list array*/ + /* add additional 32bytes because the itd cannot cross over 4K boundary, + * If one ITD cross over 4K boundary, the code will move 32 bytes for ITD. + */ + uint32_t reserved[8]; #endif #if ((defined(USB_HOST_CONFIG_EHCI_MAX_SITD)) && (USB_HOST_CONFIG_EHCI_MAX_SITD > 0U)) usb_host_ehci_sitd_t ehciSitd[USB_HOST_CONFIG_EHCI_MAX_SITD]; /*!< Idle SITD list array*/ @@ -463,7 +449,6 @@ extern usb_status_t USB_HostEhciWritePipe(usb_host_controller_handle controllerH * @param[in] controllerHandle The controller handle. * @param[in] pipeHandle The receiving pipe handle. * @param[in] transfer The transfer information. - * @retval kStatus_USB_Success Send successfully. * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI. * @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI. @@ -488,6 +473,45 @@ extern usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandl uint32_t ioctlEvent, void *ioctlParam); +/*! + * @brief control ehci bus. + * + * @param ehciInstance ehci instance pointer. + * @param bus_control control code. + * + * @return kStatus_USB_Success or error codes. + */ +extern usb_status_t USB_HostEhciControlBus(usb_host_ehci_instance_t *ehciInstance, uint8_t busControl); + +/*! + * @brief ehci port change interrupt process function. + * + * @param ehciInstance ehci instance pointer. + */ +extern void USB_HostEhciPortChange(usb_host_ehci_instance_t *ehciInstance); + +/*! + * @brief ehci timer0 interrupt process function. + * cancel control/bulk transfer that time out. + * + * @param ehciInstance ehci instance pointer. + */ +extern void USB_HostEhciTimer0(usb_host_ehci_instance_t *ehciInstance); + +/*! + * @brief host ehci start async schedule. + * + * @param ehciInstance ehci instance pointer. + */ +extern void USB_HostEhciStartAsync(usb_host_ehci_instance_t *ehciInstance); + +/*! + * @brief host ehci start periodic schedule. + * + * @param ehciInstance ehci instance pointer. + */ +extern void USB_HostEhciStartPeriodic(usb_host_ehci_instance_t *ehciInstance); + /*! @}*/ #ifdef __cplusplus @@ -496,4 +520,4 @@ extern usb_status_t USB_HostEhciIoctl(usb_host_controller_handle controllerHandl /*! @}*/ -#endif /* _USB_HOST_CONTROLLER_EHCI_H_ */ +#endif /* _USB_HOST_CONTROLLER_EHCI_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.c new file mode 100644 index 0000000000..d637a6f3cb --- /dev/null +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "usb_host.h" +#include "usb_host_hci.h" +#include "usb_host_devices.h" +#include "usb_host_framework.h" +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "middleware.usb.host.fatfs_usb_stack" +#endif + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + uint8_t *buffer, + uint32_t bufferLen) +{ + /* initialize transfer */ + transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN((uint16_t)bufferLen); + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLen; + + if (USB_HostSendSetup(deviceInstance->hostHandle, deviceInstance->controlPipe, transfer) != + kStatus_USB_Success) /* send setup transfer */ + { +#ifdef HOST_ECHO + usb_echo("failed for USB_HostSendSetup\r\n"); +#endif + (void)USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + return kStatus_USB_Success; +} + +usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_get_status_param_t *statusParam; + uint8_t length; + + /* initialize transfer */ + statusParam = (usb_host_get_status_param_t *)param; + transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_STANDARD; + if (statusParam->requestType == (uint8_t)kRequestDevice) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE; + } + else if (statusParam->requestType == (uint8_t)kRequestInterface) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + } + else + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + } + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(statusParam->statusSelector); + + length = 2; + if (statusParam->statusSelector == USB_REQUEST_STANDARD_GET_STATUS_OTG_STATUS_SELECTOR) + { + length = 1; + } + return USB_HostCh9RequestCommon(deviceInstance, transfer, statusParam->statusBuffer, length); +} + +usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_process_feature_param_t *featureParam; + + /* initialize transfer */ + featureParam = (usb_host_process_feature_param_t *)param; + if (featureParam->requestType == (uint8_t)kRequestDevice) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE; + } + else if (featureParam->requestType == (uint8_t)kRequestInterface) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + } + else + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + } + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->featureSelector); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->interfaceOrEndpoint); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); +} + +usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + uint8_t address; + + /* initialize transfer */ + address = *(uint8_t *)param; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(address); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); +} + +usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_process_descriptor_param_t *descriptorParam; + + /* initialize transfer */ + descriptorParam = (usb_host_process_descriptor_param_t *)param; + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN( + (uint16_t)((uint16_t)descriptorParam->descriptorType << 8) | descriptorParam->descriptorIndex); + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(descriptorParam->languageId); + return USB_HostCh9RequestCommon(deviceInstance, transfer, descriptorParam->descriptorBuffer, + descriptorParam->descriptorLength); +} + +usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_get_interface_param_t *interfaceParam; + + /* initialize transfer */ + interfaceParam = (usb_host_get_interface_param_t *)param; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(interfaceParam->interface); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, interfaceParam->alternateInterfaceBuffer, 1); +} + +usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_set_interface_param_t *setParam; + + /* initialize transfer */ + setParam = (usb_host_set_interface_param_t *)param; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(setParam->interface); + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(setParam->alternateSetting); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0); +} + +usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_synch_frame_param_t *frameParam; + + /* initialize transfer */ + frameParam = (usb_host_synch_frame_param_t *)param; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(frameParam->endpoint); + + return USB_HostCh9RequestCommon(deviceInstance, transfer, frameParam->frameNumberBuffer, 2); +} + +usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle, + uint8_t usbRequest, + usb_host_transfer_t *transfer, + void *param) +{ + usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; + usb_status_t status = kStatus_USB_Error; + + if (deviceHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + /* reset transfer fields */ + transfer->setupPacket->bmRequestType = 0x00; + transfer->setupPacket->bRequest = usbRequest; + transfer->setupPacket->wIndex = 0; + transfer->setupPacket->wLength = 0; + transfer->setupPacket->wValue = 0; + + switch (usbRequest) + { + case USB_REQUEST_STANDARD_GET_STATUS: /* standard get status request */ + status = USB_HostStandardGetStatus(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_CLEAR_FEATURE: /* standard clear status request */ + case USB_REQUEST_STANDARD_SET_FEATURE: /* standard set feature request */ + status = USB_HostStandardSetClearFeature(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_SET_ADDRESS: /* standard set address request */ + status = USB_HostStandardSetAddress(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_GET_DESCRIPTOR: /* standard get descriptor request */ + case USB_REQUEST_STANDARD_SET_DESCRIPTOR: /* standard set descriptor request */ + if (usbRequest == USB_REQUEST_STANDARD_GET_DESCRIPTOR) + { + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + } + status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_GET_CONFIGURATION: /* standard get configuration descriptor request */ + transfer->setupPacket->bmRequestType |= USB_REQUEST_TYPE_DIR_IN; + status = + USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, (uint8_t *)param, 1); + break; + + case USB_REQUEST_STANDARD_SET_CONFIGURATION: /* standard set configuration request */ + transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(*((uint8_t *)param)); + status = USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, NULL, 0); + break; + + case USB_REQUEST_STANDARD_GET_INTERFACE: /* standard get interface request */ + status = USB_HostStandardGetInterface(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_SET_INTERFACE: /* standard set interface request */ + status = USB_HostStandardSetInterface(deviceInstance, transfer, param); + break; + + case USB_REQUEST_STANDARD_SYNCH_FRAME: /* standard synch frame request */ + status = USB_HostStandardSyncFrame(deviceInstance, transfer, param); + break; + + default: + /*no action*/ + break; + } + + return status; +} \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.h new file mode 100644 index 0000000000..b0d8d298e3 --- /dev/null +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_framework.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_CH9_H_ +#define _USB_HOST_CH9_H_ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @addtogroup usb_host_drv + * @{ + */ + +/*! @}*/ + +/******************************************************************************* + * API + ******************************************************************************/ +/*! + * @brief standard control transfer common code. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param buffer data buffer pointer. + * @param bufferLen data length. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + uint8_t *buffer, + uint32_t bufferLen); + +/*! + * @brief standard get status implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set/clear feature implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set address implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set/get descriptor implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard get interface implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard set interface implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); + +/*! + * @brief standard sync frame implementation. + * + * @param deviceInstance device instance handle. + * @param transfer transfer. + * @param param parameter. + * + * @return kStatus_USB_Success or error codes. + */ +usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance, + usb_host_transfer_t *transfer, + void *param); +#endif /* _USB_HOST_CH9_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c b/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c index 927bf8bd9c..a29a4ea08e 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.c @@ -1,34 +1,12 @@ /* * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016 - 2019 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include +#include #include "fsl_common.h" #include "usb_host.h" #include "usb_host_hci.h" @@ -42,16 +20,24 @@ * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "middleware.usb.host_stack" +#endif + +#if defined __CORTEX_M && (__CORTEX_M == 7U) +#if (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE > 0U)) +#warning USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE is not supported. +#endif +#endif + /******************************************************************************* * Prototypes ******************************************************************************/ #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) -extern uint32_t USB_HostHubGetTotalThinkTime(usb_host_handle hostHandle, uint8_t parentHubNo); - -extern usb_status_t USB_HostHubSuspendDevice(usb_host_handle hostHandle); - -extern usb_status_t USB_HostHubResumeDevice(usb_host_handle hostHandle); +#include "usb_host_hub.h" +#include "usb_host_hub_app.h" #endif /*! @@ -77,15 +63,6 @@ static void USB_HostReleaseInstance(usb_host_instance_t *hostInstance); static void USB_HostGetControllerInterface(uint8_t controllerId, const usb_host_controller_interface_t **controllerTable); -#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) -#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) -extern void USB_HostEhciTestModeInit(usb_device_handle devHandle); -#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */ -#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS)) -extern void USB_HostIp3516HsTestModeInit(usb_device_handle devHandle); -#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */ -#endif /* USB_HOST_CONFIG_EHCI */ - /******************************************************************************* * Variables ******************************************************************************/ @@ -94,8 +71,7 @@ usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST]; #if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) #include "usb_host_ehci.h" -static const usb_host_controller_interface_t s_EhciInterface = \ -{ +static const usb_host_controller_interface_t s_EhciInterface = { USB_HostEhciCreate, USB_HostEhciDestory, USB_HostEhciOpenPipe, USB_HostEhciClosePipe, USB_HostEhciWritePipe, USB_HostEhciReadpipe, USB_HostEhciIoctl, }; @@ -103,8 +79,7 @@ static const usb_host_controller_interface_t s_EhciInterface = \ #if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI)) #include "usb_host_khci.h" -static const usb_host_controller_interface_t s_KhciInterface = \ -{ +static const usb_host_controller_interface_t s_KhciInterface = { USB_HostKhciCreate, USB_HostKhciDestory, USB_HostKhciOpenPipe, USB_HostKhciClosePipe, USB_HostKhciWritePipe, USB_HostKhciReadpipe, USB_HostKciIoctl, }; @@ -112,8 +87,7 @@ static const usb_host_controller_interface_t s_KhciInterface = \ #if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U)) #include "usb_host_ohci.h" -static const usb_host_controller_interface_t s_OhciInterface = \ -{ +static const usb_host_controller_interface_t s_OhciInterface = { USB_HostOhciCreate, USB_HostOhciDestory, USB_HostOhciOpenPipe, USB_HostOhciClosePipe, USB_HostOhciWritePipe, USB_HostOhciReadPipe, USB_HostOhciIoctl, }; @@ -121,65 +95,67 @@ static const usb_host_controller_interface_t s_OhciInterface = \ #if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U)) #include "usb_host_ip3516hs.h" -static const usb_host_controller_interface_t s_Ip3516HsInterface = \ -{ +static const usb_host_controller_interface_t s_Ip3516HsInterface = { USB_HostIp3516HsCreate, USB_HostIp3516HsDestory, USB_HostIp3516HsOpenPipe, USB_HostIp3516HsClosePipe, USB_HostIp3516HsWritePipe, USB_HostIp3516HsReadPipe, USB_HostIp3516HsIoctl, }; #endif /* USB_HOST_CONFIG_IP3516HS */ -USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_Setupbuffer[USB_HOST_CONFIG_MAX_HOST][USB_HOST_CONFIG_MAX_TRANSFERS][USB_DATA_ALIGN_SIZE_MULTIPLE(8)]; +USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) +static uint8_t s_Setupbuffer[USB_HOST_CONFIG_MAX_HOST][USB_HOST_CONFIG_MAX_TRANSFERS][USB_DATA_ALIGN_SIZE_MULTIPLE(8)]; /******************************************************************************* -* Code -******************************************************************************/ + * Code + ******************************************************************************/ #if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) /*FUNCTION*---------------------------------------------------------------- -* -* Function Name : usb_test_mode_init -* Returned Value : None -* Comments : -* This function is called by common class to initialize the class driver. It -* is called in response to a select interface call by application -* -*END*--------------------------------------------------------------------*/ + * + * Function Name : usb_test_mode_init + * Returned Value : None + * Comments : + * This function is called by common class to initialize the class driver. It + * is called in response to a select interface call by application + * + *END*--------------------------------------------------------------------*/ usb_status_t USB_HostTestModeInit(usb_device_handle deviceHandle) { #if (((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) || \ ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS))) usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; - usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle; + usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle; #endif uint32_t productId; uint32_t vendorId; - usb_echo("usb host test init\r\n"); - USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &productId); - USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &vendorId); - usb_echo(" vendor id :0x%x product id:0x%x \r\n", vendorId, productId); + (void)usb_echo("usb host test init\r\n"); + (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDevicePID, &productId); + (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceVID, &vendorId); + (void)usb_echo(" vendor id :0x%x product id:0x%x \r\n", vendorId, productId); - if ((productId != 0x0200U) && (productId != 0x0101) && (productId != 0x0102) && (productId != 0x0103) && - (productId != 0x0104) && (productId != 0x0105) && (productId != 0x0106) && (productId != 0x0107) && - (productId != 0x0108)) + if ((productId != 0x0200U) && (productId != 0x0101U) && (productId != 0x0102U) && (productId != 0x0103U) && + (productId != 0x0104U) && (productId != 0x0105U) && (productId != 0x0106U) && (productId != 0x0107U) && + (productId != 0x0108U)) { - usb_echo("Unsupported Device\r\n"); + (void)usb_echo("Unsupported Device\r\n"); } if (productId == 0x0200U) { - usb_echo("PET test device attached\r\n"); + (void)usb_echo("PET test device attached\r\n"); } else { #if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) if (hostInstance->controllerTable == &s_EhciInterface) { - USB_HostEhciTestModeInit(deviceHandle); + (void)hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostTestModeInit, + (void *)deviceHandle); } -#elif((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS)) +#elif ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS)) if (hostInstance->controllerTable == &s_Ip3516HsInterface) { - USB_HostIp3516HsTestModeInit(deviceHandle); + (void)hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostTestModeInit, + (void *)deviceHandle); } #endif } @@ -190,13 +166,14 @@ usb_status_t USB_HostTestModeInit(usb_device_handle deviceHandle) static usb_host_instance_t *USB_HostGetInstance(void) { - uint8_t i = 0; + uint8_t i = 0; uint32_t index = 0; - USB_OSA_SR_ALLOC(); - USB_OSA_ENTER_CRITICAL(); + void *temp; + OSA_SR_ALLOC(); + OSA_ENTER_CRITICAL(); for (; i < USB_HOST_CONFIG_MAX_HOST; i++) { - if (g_UsbHostInstance[i].occupied != 1) + if (g_UsbHostInstance[i].occupied != 1U) { uint8_t *buffer = (uint8_t *)&g_UsbHostInstance[i]; for (uint32_t j = 0U; j < sizeof(usb_host_instance_t); j++) @@ -204,53 +181,53 @@ static usb_host_instance_t *USB_HostGetInstance(void) buffer[j] = 0x00U; } g_UsbHostInstance[i].occupied = 1; - USB_OSA_EXIT_CRITICAL(); + OSA_EXIT_CRITICAL(); for (index = 0; index < USB_HOST_CONFIG_MAX_TRANSFERS; ++index) { - g_UsbHostInstance[i].transferList[index].setupPacket = - (usb_setup_struct_t *)&(s_Setupbuffer[i][index][0]); + temp = (void *)&(s_Setupbuffer[i][index][0]); + g_UsbHostInstance[i].transferList[index].setupPacket = (usb_setup_struct_t *)temp; } return &g_UsbHostInstance[i]; } } - USB_OSA_EXIT_CRITICAL(); + OSA_EXIT_CRITICAL(); return NULL; } static void USB_HostReleaseInstance(usb_host_instance_t *hostInstance) { - USB_OSA_SR_ALLOC(); - USB_OSA_ENTER_CRITICAL(); + OSA_SR_ALLOC(); + OSA_ENTER_CRITICAL(); hostInstance->occupied = 0; - USB_OSA_EXIT_CRITICAL(); + OSA_EXIT_CRITICAL(); } static void USB_HostGetControllerInterface(uint8_t controllerId, const usb_host_controller_interface_t **controllerTable) { #if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI)) - if (controllerId == kUSB_ControllerKhci0) + if (controllerId == (uint8_t)kUSB_ControllerKhci0) { *controllerTable = &s_KhciInterface; } #endif /* USB_HOST_CONFIG_KHCI */ #if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) - if ((controllerId == kUSB_ControllerEhci0) || (controllerId == kUSB_ControllerEhci1)) + if ((controllerId == (uint8_t)kUSB_ControllerEhci0) || (controllerId == (uint8_t)kUSB_ControllerEhci1)) { *controllerTable = &s_EhciInterface; } #endif /* USB_HOST_CONFIG_EHCI */ #if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI > 0U)) - if (controllerId == kUSB_ControllerOhci0) + if (controllerId == (uint8_t)kUSB_ControllerOhci0) { *controllerTable = &s_OhciInterface; } #endif /* USB_HOST_CONFIG_OHCI */ #if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS > 0U)) - if (controllerId == kUSB_ControllerIp3516Hs0) + if (controllerId == (uint8_t)kUSB_ControllerIp3516Hs0) { *controllerTable = &s_Ip3516HsInterface; } @@ -259,10 +236,10 @@ static void USB_HostGetControllerInterface(uint8_t controllerId, usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, host_callback_t callbackFn) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = NULL; usb_host_transfer_t *transferPrev = NULL; - uint8_t i = 0; + uint8_t i = 0; hostInstance = USB_HostGetInstance(); /* get one host instance */ if (hostInstance == NULL) @@ -291,10 +268,11 @@ usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, hos } /* HOST instance init*/ - hostInstance->controllerId = controllerId; + hostInstance->controllerId = controllerId; hostInstance->deviceCallback = callbackFn; - hostInstance->deviceList = NULL; - if (kStatus_USB_OSA_Success != USB_OsaMutexCreate(&hostInstance->hostMutex)) + hostInstance->deviceList = NULL; + hostInstance->hostMutex = (osa_mutex_handle_t)(&hostInstance->mutexBuffer[0]); + if (KOSA_StatusSuccess != OSA_MutexCreate(hostInstance->hostMutex)) { USB_HostReleaseInstance(hostInstance); #ifdef HOST_ECHO @@ -306,19 +284,19 @@ usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, hos /* initialize transfer list */ hostInstance->transferHead = &hostInstance->transferList[0]; - transferPrev = hostInstance->transferHead; + transferPrev = hostInstance->transferHead; for (i = 1; i < USB_HOST_CONFIG_MAX_TRANSFERS; ++i) { transferPrev->next = &hostInstance->transferList[i]; - transferPrev = transferPrev->next; + transferPrev = transferPrev->next; } - /* controller create */ + /* controller create, the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerCreate(controllerId, hostInstance, &(hostInstance->controllerHandle)); if ((status != kStatus_USB_Success) || (hostInstance->controllerHandle == NULL)) { - USB_OsaMutexDestroy(hostInstance->hostMutex); + (void)OSA_MutexDestroy(hostInstance->hostMutex); USB_HostReleaseInstance(hostInstance); #ifdef HOST_ECHO usb_echo("host init: controller init fail\r\n"); @@ -332,8 +310,8 @@ usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, hos usb_status_t USB_HostDeinit(usb_host_handle hostHandle) { - usb_status_t status = kStatus_USB_Success; - usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; + usb_status_t status = kStatus_USB_Success; + usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; usb_host_device_instance_t *deviceInstance = NULL; if (hostHandle == NULL) @@ -346,23 +324,23 @@ usb_status_t USB_HostDeinit(usb_host_handle hostHandle) while (deviceInstance != NULL) { deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList; - USB_HostDetachDeviceInternal(hostHandle, deviceInstance); + (void)USB_HostDetachDeviceInternal(hostHandle, deviceInstance); } - /* controller instance destory */ - status = hostInstance->controllerTable->controllerDestory(hostInstance->controllerHandle); + /* controller instance destroy, the callbackFn is initialized in USB_HostGetControllerInterface */ + status = hostInstance->controllerTable->controllerDestory(hostInstance->controllerHandle); hostInstance->controllerHandle = NULL; if (status != kStatus_USB_Success) { #ifdef HOST_ECHO - usb_echo("host controller destory fail\r\n"); + usb_echo("host controller destroy fail\r\n"); #endif } /* resource release */ - if (hostInstance->hostMutex) + if (NULL != hostInstance->hostMutex) { - USB_OsaMutexDestroy(hostInstance->hostMutex); + (void)OSA_MutexDestroy(hostInstance->hostMutex); hostInstance->hostMutex = NULL; } USB_HostReleaseInstance(hostInstance); @@ -374,7 +352,7 @@ usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle, usb_host_pipe_handle *pipeHandle, usb_host_pipe_init_t *pipeInit) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if ((hostHandle == NULL) || (pipeInit == NULL)) @@ -382,7 +360,7 @@ usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle, return kStatus_USB_InvalidHandle; } - /* call controller open pipe interface */ + /* call controller open pipe interface, the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerOpenPipe(hostInstance->controllerHandle, pipeHandle, pipeInit); return status; @@ -390,7 +368,7 @@ usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle, usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if ((hostHandle == NULL) || (pipeHandle == NULL)) @@ -398,7 +376,7 @@ usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle return kStatus_USB_InvalidHandle; } - /* call controller close pipe interface */ + /* call controller close pipe interface, the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerClosePipe(hostInstance->controllerHandle, pipeHandle); return status; @@ -406,7 +384,7 @@ usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle usb_status_t USB_HostSend(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL)) @@ -416,9 +394,9 @@ usb_status_t USB_HostSend(usb_host_handle hostHandle, usb_host_pipe_handle pipeH /* initialize transfer */ transfer->transferSofar = 0; - transfer->direction = USB_OUT; + transfer->direction = USB_OUT; - USB_HostLock(); /* This api can be called by host task and app task */ + (void)USB_HostLock(); /* This api can be called by host task and app task */ /* keep this code: in normal situation application will guarantee the device is attached when call send/receive function */ #if 0 @@ -435,9 +413,10 @@ usb_status_t USB_HostSend(usb_host_handle hostHandle, usb_host_pipe_handle pipeH DCACHE_CleanByRange((uint32_t)transfer->transferBuffer, transfer->transferLength); } #endif + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerWritePipe(hostInstance->controllerHandle, pipeHandle, transfer); - USB_HostUnlock(); + (void)USB_HostUnlock(); return status; } @@ -445,7 +424,7 @@ usb_status_t USB_HostSendSetup(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL)) @@ -455,8 +434,8 @@ usb_status_t USB_HostSendSetup(usb_host_handle hostHandle, /* initialize transfer */ transfer->transferSofar = 0; - transfer->next = NULL; - transfer->setupStatus = 0; + transfer->next = NULL; + transfer->setupStatus = 0; if ((transfer->setupPacket->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN) { transfer->direction = USB_IN; @@ -466,7 +445,7 @@ usb_status_t USB_HostSendSetup(usb_host_handle hostHandle, transfer->direction = USB_OUT; } - USB_HostLock(); /* This API can be called by host task and application task */ + (void)USB_HostLock(); /* This API can be called by host task and application task */ /* keep this code: in normal situation application will guarantee the device is attached when call send/receive function */ #if 0 @@ -484,15 +463,16 @@ usb_status_t USB_HostSendSetup(usb_host_handle hostHandle, DCACHE_CleanInvalidateByRange((uint32_t)transfer->transferBuffer, transfer->transferLength); } #endif + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerWritePipe(hostInstance->controllerHandle, pipeHandle, transfer); - USB_HostUnlock(); + (void)USB_HostUnlock(); return status; } usb_status_t USB_HostRecv(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL)) @@ -502,9 +482,9 @@ usb_status_t USB_HostRecv(usb_host_handle hostHandle, usb_host_pipe_handle pipeH /* initialize transfer */ transfer->transferSofar = 0; - transfer->direction = USB_IN; + transfer->direction = USB_IN; - USB_HostLock(); /* This API can be called by host task and application task */ + (void)USB_HostLock(); /* This API can be called by host task and application task */ /* keep this code: in normal situation application will guarantee the device is attached when call send/receive function */ #if 0 @@ -521,9 +501,10 @@ usb_status_t USB_HostRecv(usb_host_handle hostHandle, usb_host_pipe_handle pipeH DCACHE_CleanInvalidateByRange((uint32_t)transfer->transferBuffer, transfer->transferLength); } #endif + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerReadPipe(hostInstance->controllerHandle, pipeHandle, transfer); - USB_HostUnlock(); + (void)USB_HostUnlock(); return status; } @@ -531,7 +512,7 @@ usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer) { - usb_status_t status = kStatus_USB_Success; + usb_status_t status = kStatus_USB_Success; usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle; usb_host_cancel_param_t cancelParam; @@ -542,9 +523,10 @@ usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle, /* initialize cancel parameter */ cancelParam.pipeHandle = pipeHandle; - cancelParam.transfer = transfer; + cancelParam.transfer = transfer; /* USB_HostLock(); This api can be called by host task and app task */ + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostCancelTransfer, &cancelParam); /* USB_HostUnlock(); */ @@ -562,18 +544,18 @@ usb_status_t USB_HostMallocTransfer(usb_host_handle hostHandle, usb_host_transfe } /* get one from the transfer_head */ - USB_HostLock(); + (void)USB_HostLock(); if (hostInstance->transferHead != NULL) { - *transfer = hostInstance->transferHead; + *transfer = hostInstance->transferHead; hostInstance->transferHead = hostInstance->transferHead->next; - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Success; } else { *transfer = NULL; - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Error; } } @@ -592,10 +574,10 @@ usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_transfer_ } /* release one to the transfer_head */ - USB_HostLock(); - transfer->next = hostInstance->transferHead; + (void)USB_HostLock(); + transfer->next = hostInstance->transferHead; hostInstance->transferHead = transfer; - USB_HostUnlock(); + (void)USB_HostUnlock(); return kStatus_USB_Success; } @@ -604,23 +586,28 @@ usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHand uint32_t *infoValue) { usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle; + uint32_t *temp; + usb_host_dev_info_t devInfo; if ((deviceHandle == NULL) || (infoValue == NULL)) { return kStatus_USB_InvalidParameter; } - - switch (infoCode) + devInfo = (usb_host_dev_info_t)infoCode; + switch (devInfo) { case kUSB_HostGetDeviceAddress: /* device address */ + *infoValue = (uint32_t)deviceInstance->setAddress; break; case kUSB_HostGetDeviceControlPipe: /* device control pipe */ - *infoValue = (uint32_t)deviceInstance->controlPipe; + temp = (uint32_t *)deviceInstance->controlPipe; + *infoValue = (uint32_t)temp; break; case kUSB_HostGetHostHandle: /* device host handle */ - *infoValue = (uint32_t)deviceInstance->hostHandle; + temp = (uint32_t *)deviceInstance->hostHandle; + *infoValue = (uint32_t)temp; break; #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) @@ -685,7 +672,8 @@ usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHand break; default: - return kStatus_USB_Error; + /*no action*/ + break; } return kStatus_USB_Success; @@ -698,26 +686,27 @@ usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle inter uint32_t endPosition; usb_descriptor_union_t *unionDes; usb_host_ep_t *epParse; - + void *temp; if (interfaceHandle == NULL) { return kStatus_USB_InvalidHandle; } - if (alternateSetting == 0) + if (alternateSetting == 0U) { return kStatus_USB_InvalidParameter; } /* parse configuration descriptor */ - unionDes = (usb_descriptor_union_t *)((usb_host_interface_t *)interfaceHandle) - ->interfaceDesc; /* interface extend descriptor start */ + temp = (void *)((usb_host_interface_t *)interfaceHandle)->interfaceDesc; + ; + unionDes = (usb_descriptor_union_t *)temp; /* interface extend descriptor start */ endPosition = (uint32_t)unionDes + ((usb_host_interface_t *)interfaceHandle)->interfaceExtensionLength; /* interface extend descriptor end */ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength); - /* search for the alternate setting interface descritpor */ + /* search for the alternate setting interface descriptor */ while ((uint32_t)unionDes < endPosition) { if (unionDes->interface.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE) @@ -742,12 +731,12 @@ usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle inter } /* initialize interface handle structure instance */ - interface->interfaceDesc = &unionDes->interface; - interface->alternateSettingNumber = 0; - interface->epCount = 0; - interface->interfaceExtension = NULL; - interface->interfaceExtensionLength = 0; - interface->interfaceIndex = unionDes->interface.bInterfaceNumber; + interface->interfaceDesc = &unionDes->interface; + interface->alternateSettingNumber = 0U; + interface->epCount = 0U; + interface->interfaceExtension = NULL; + interface->interfaceExtensionLength = 0U; + interface->interfaceIndex = unionDes->interface.bInterfaceNumber; /* search for endpoint descriptor start position */ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength); @@ -770,7 +759,7 @@ usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle inter } /* parse endpoint descriptor */ - if (interface->interfaceDesc->bNumEndpoints != 0) + if (interface->interfaceDesc->bNumEndpoints != 0U) { if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) || (interface->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP)) @@ -790,11 +779,12 @@ usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle inter #endif return kStatus_USB_Error; } - epParse = (usb_host_ep_t *)&interface->epList[interface->epCount]; - epParse->epDesc = (usb_descriptor_endpoint_t *)unionDes; + epParse = (usb_host_ep_t *)&interface->epList[interface->epCount]; + temp = (void *)unionDes; + epParse->epDesc = (usb_descriptor_endpoint_t *)temp; epParse->epExtensionLength = 0; - epParse->epExtension = NULL; - unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength); + epParse->epExtension = NULL; + unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength); while ((uint32_t)unionDes < endPosition) { if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) && @@ -820,7 +810,7 @@ usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle inter void USB_HostGetVersion(uint32_t *version) { - if (version) + if (NULL != version) { *version = (uint32_t)USB_MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX); @@ -828,12 +818,12 @@ void USB_HostGetVersion(uint32_t *version) } #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) -/* Send BUS or specific device suepend request */ +/* Send BUS or specific device suspend request */ usb_status_t USB_HostSuspendDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle) { usb_host_instance_t *hostInstance; usb_host_device_instance_t *deviceInstance; - usb_status_t status = kStatus_USB_Error; + usb_status_t status = kStatus_USB_Error; usb_host_bus_control_t type = kUSB_HostBusSuspend; if (hostHandle == NULL) @@ -849,6 +839,7 @@ usb_status_t USB_HostSuspendDeviceResquest(usb_host_handle hostHandle, usb_devic #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) status = USB_HostHubSuspendDevice(hostInstance); #else + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); #endif @@ -857,11 +848,12 @@ usb_status_t USB_HostSuspendDeviceResquest(usb_host_handle hostHandle, usb_devic { #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) deviceInstance = (usb_host_device_instance_t *)deviceHandle; - if (0 == deviceInstance->hubNumber) + if (0U == deviceInstance->hubNumber) { #endif if (hostInstance->deviceList == deviceHandle) { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); } @@ -888,7 +880,7 @@ usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device { usb_host_instance_t *hostInstance; usb_host_device_instance_t *deviceInstance; - usb_status_t status = kStatus_USB_Error; + usb_status_t status = kStatus_USB_Error; usb_host_bus_control_t type = kUSB_HostBusResume; if (hostHandle == NULL) @@ -905,6 +897,7 @@ usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device if (NULL == deviceHandle) { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); } @@ -912,11 +905,12 @@ usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device { #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) deviceInstance = (usb_host_device_instance_t *)deviceHandle; - if (0 == deviceInstance->hubNumber) + if (0U == deviceInstance->hubNumber) { #endif if (hostInstance->deviceList == deviceHandle) { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); } @@ -935,13 +929,13 @@ usb_status_t USB_HostResumeDeviceResquest(usb_host_handle hostHandle, usb_device return status; } #if ((defined(USB_HOST_CONFIG_LPM_L1)) && (USB_HOST_CONFIG_LPM_L1 > 0U)) -/* Send BUS or specific device suepend request */ +/* Send BUS or specific device suspend request */ usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle, usb_device_handle deviceHandle, uint8_t sleepType) { usb_host_instance_t *hostInstance; - usb_status_t status = kStatus_USB_Error; + usb_status_t status = kStatus_USB_Error; usb_host_bus_control_t type = kUSB_HostBusL1Sleep; if (hostHandle == NULL) @@ -955,8 +949,9 @@ usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle, if (1U == sleepType) { /*#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))*/ - /*To do, implete hub L1 suspend device*/ + /*To do, incomplete hub L1 suspend device*/ /*#else*/ + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); /*#endif*/ @@ -968,6 +963,7 @@ usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle, #endif if (hostInstance->deviceList == deviceHandle) { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); } @@ -978,7 +974,7 @@ usb_status_t USB_HostL1SleepDeviceResquest(usb_host_handle hostHandle, } return status; } -/* Send BUS or specific device suepend request */ +/* Send BUS or specific device suspend request */ usb_status_t USB_HostL1SleepDeviceResquestConfig(usb_host_handle hostHandle, uint8_t *lpmParam) { usb_host_instance_t *hostInstance; @@ -989,7 +985,7 @@ usb_status_t USB_HostL1SleepDeviceResquestConfig(usb_host_handle hostHandle, uin return kStatus_USB_InvalidHandle; } hostInstance = (usb_host_instance_t *)hostHandle; - + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostL1Config, lpmParam); @@ -1003,7 +999,7 @@ usb_status_t USB_HostL1ResumeDeviceResquest(usb_host_handle hostHandle, { usb_host_instance_t *hostInstance; - usb_status_t status = kStatus_USB_Error; + usb_status_t status = kStatus_USB_Error; usb_host_bus_control_t type = kUSB_HostBusL1Resume; if (hostHandle == NULL) @@ -1014,17 +1010,19 @@ usb_status_t USB_HostL1ResumeDeviceResquest(usb_host_handle hostHandle, if (1U == sleepType) { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); } else { #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB)) -/*To do, if device hub number is 0, need suspend the bus ,else suspend the corresponding device*/ + /*To do, if device hub number is 0, need suspend the bus ,else suspend the corresponding device*/ #endif if (hostInstance->deviceList == deviceHandle) { + /* the callbackFn is initialized in USB_HostGetControllerInterface */ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type); } @@ -1050,3 +1048,18 @@ usb_status_t USB_HostUpdateHwTick(usb_host_handle hostHandle, uint64_t tick) return status; } #endif + +#if ((defined(USB_HOST_CONFIG_BATTERY_CHARGER)) && (USB_HOST_CONFIG_BATTERY_CHARGER > 0U)) +usb_status_t USB_HostSetChargerType(usb_host_handle hostHandle, uint8_t type) +{ + usb_host_instance_t *hostInstance; + + if (hostHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + hostInstance = (usb_host_instance_t *)hostHandle; + return hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostSetChargerType, + &type); +} +#endif \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.h b/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.h index 26b6d4a9c5..f9ac8b6a7f 100644 --- a/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.h +++ b/bsp/imxrt/libraries/drivers/usb/host/usb_host_hci.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016 - 2019 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _USB_HOST_HCI_H_ @@ -36,9 +14,9 @@ ******************************************************************************/ /*! @brief USB host lock */ -#define USB_HostLock() USB_OsaMutexLock(hostInstance->hostMutex) +#define USB_HostLock() OSA_MutexLock(hostInstance->hostMutex, USB_OSA_WAIT_TIMEOUT) /*! @brief USB host unlock */ -#define USB_HostUnlock() USB_OsaMutexUnlock(hostInstance->hostMutex) +#define USB_HostUnlock() OSA_MutexUnlock(hostInstance->hostMutex) /*! * @addtogroup usb_host_controller_driver @@ -56,6 +34,10 @@ typedef enum _usb_host_controller_control kUSB_HostPortAttachDisable, /*!< Disable the port attach event */ kUSB_HostPortAttachEnable, /*!< Enable the port attach event */ kUSB_HostL1Config, /*!< L1 suspend Bus control code */ + kUSB_HostSetChargerType, /*!< set charger type */ +#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) + kUSB_HostTestModeInit, /*!< intialize charger type */ +#endif } usb_host_controller_control_t; /*! @brief USB host controller bus control code */ @@ -97,7 +79,9 @@ typedef struct _usb_host_controller_interface uint32_t ioctlEvent, void *ioctlParam); /*!< Control a controller function prototype*/ } usb_host_controller_interface_t; - +#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST)) +usb_status_t USB_HostTestModeInit(usb_device_handle deviceHandle); +#endif /*! @}*/ /*! @@ -110,7 +94,8 @@ typedef struct _usb_host_instance { void *controllerHandle; /*!< The low level controller handle*/ host_callback_t deviceCallback; /*!< Device attach/detach callback*/ - usb_osa_mutex_handle hostMutex; /*!< Host layer mutex*/ + osa_mutex_handle_t hostMutex; /*!< Host layer mutex*/ + uint32_t mutexBuffer[(OSA_MUTEX_HANDLE_SIZE + 3) / 4]; /*!< Host layer mutex*/ usb_host_transfer_t transferList[USB_HOST_CONFIG_MAX_TRANSFERS]; /*!< Transfer resource*/ usb_host_transfer_t *transferHead; /*!< Idle transfer head*/ const usb_host_controller_interface_t *controllerTable; /*!< KHCI/EHCI interface*/ @@ -126,6 +111,7 @@ typedef struct _usb_host_instance uint8_t controllerId; /*!< The controller ID*/ } usb_host_instance_t; +extern usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST]; /*! @}*/ -#endif /* _USB_HOST_HCI_H_ */ +#endif /* _USB_HOST_HCI_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/include/usb.h b/bsp/imxrt/libraries/drivers/usb/include/usb.h index 256896b472..a5d0550ce0 100644 --- a/bsp/imxrt/libraries/drivers/usb/include/usb.h +++ b/bsp/imxrt/libraries/drivers/usb/include/usb.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "usb_misc.h" #include "usb_spec.h" @@ -137,4 +138,4 @@ typedef struct _usb_version /*! @} */ -#endif /* __USB_H__ */ +#endif /* __USB_H__ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h b/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h new file mode 100644 index 0000000000..73bc46a8e6 --- /dev/null +++ b/bsp/imxrt/libraries/drivers/usb/include/usb_host_config.h @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_HOST_CONFIG_H_ +#define _USB_HOST_CONFIG_H_ + +/* Host Controller Enable */ +/*! + * @brief host khci instance count, meantime it indicates khci enable or disable. + * - if 0, host khci driver is disable. + * - if greater than 0, host khci driver is enable. + */ +#define USB_HOST_CONFIG_KHCI (0U) + +/*! + * @brief host ehci instance count, meantime it indicates ehci enable or disable. + * - if 0, host ehci driver is disable. + * - if greater than 0, host ehci driver is enable. + */ +#define USB_HOST_CONFIG_EHCI (2U) + +/*! + * @brief host ohci instance count, meantime it indicates ohci enable or disable. + * - if 0, host ohci driver is disable. + * - if greater than 0, host ohci driver is enable. + */ +#define USB_HOST_CONFIG_OHCI (0U) + +/*! + * @brief host ip3516hs instance count, meantime it indicates ohci enable or disable. + * - if 0, host ip3516hs driver is disable. + * - if greater than 0, host ip3516hs driver is enable. + */ +#define USB_HOST_CONFIG_IP3516HS (0U) + +/* Common configuration macros for all controllers */ + +/*! + * @brief host driver instance max count. + * for example: 2 - one for khci, one for ehci. + */ +#define USB_HOST_CONFIG_MAX_HOST \ + (USB_HOST_CONFIG_KHCI + USB_HOST_CONFIG_EHCI + USB_HOST_CONFIG_OHCI + USB_HOST_CONFIG_IP3516HS) + +/*! + * @brief host pipe max count. + * pipe is the host driver resource for device endpoint, one endpoint need one pipe. + */ +#define USB_HOST_CONFIG_MAX_PIPES (16U) + +/*! + * @brief host transfer max count. + * transfer is the host driver resource for data transmission mission, one transmission mission need one transfer. + */ +#define USB_HOST_CONFIG_MAX_TRANSFERS (16U) + +/*! + * @brief the max endpoint for one interface. + * the max endpoint descriptor number that one interface descriptor contain. + */ +#define USB_HOST_CONFIG_INTERFACE_MAX_EP (4U) + +/*! + * @brief the max interface for one configuration. + * the max interface descriptor number that one configuration descriptor can contain. + */ +#define USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE (5U) + +/*! + * @brief the max power for one device. + * the max power the host can provide for one device. + */ +#define USB_HOST_CONFIG_MAX_POWER (250U) + +/*! + * @brief the max retries for enumeration. + * retry time when enumeration fail. + */ +#define USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES (3U) + +/*! + * @brief the max retries for enumeration setup stall. + * the max times for one transfer can stall. + */ +#define USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES (1U) + +/*! + * @brief the max NAK count for one transaction. + * when nak count reach to the value, the transaction fail. + */ +#define USB_HOST_CONFIG_MAX_NAK (3000U) + +/*! @brief Whether the transfer buffer is cache-enabled or not. */ +#ifndef USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE +#define USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE (0U) +#endif +/*! @brief if 1, enable usb compliance test codes; if 0, disable usb compliance test codes. */ +#define USB_HOST_CONFIG_COMPLIANCE_TEST (0U) + +/*! @brief if 1, class driver clear stall automatically; if 0, class driver don't clear stall. */ +#define USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL (0U) + +/* KHCI configuration */ +#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI)) + +/*! + * @brief khci dma align fix buffer size. + */ +#define USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER (64U) + +#endif + +/* EHCI configuration */ +#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI)) + +/*! + * @brief ehci periodic frame list size. + * the value can be 1024, 512, 256, 128, 64, 32, 16 or 8. + */ +#define USB_HOST_CONFIG_EHCI_FRAME_LIST_SIZE (1024U) + +/*! + * @brief ehci QH max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_QH (8U) + +/*! + * @brief ehci QTD max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_QTD (8U) + +/*! + * @brief ehci ITD max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_ITD (0U) + +/*! + * @brief ehci SITD max count. + */ +#define USB_HOST_CONFIG_EHCI_MAX_SITD (0U) + +#endif + +/* OHCI configuration */ +#if ((defined USB_HOST_CONFIG_OHCI) && (USB_HOST_CONFIG_OHCI)) + +/*! + * @brief ohci ED max count. + */ +#define USB_HOST_CONFIG_OHCI_MAX_ED (8U) + +/*! + * @brief ohci GTD max count. + */ +#define USB_HOST_CONFIG_OHCI_MAX_GTD (8U) + +/*! + * @brief ohci ITD max count. + */ +#define USB_HOST_CONFIG_OHCI_MAX_ITD (8U) + +#endif + +/* OHCI configuration */ +#if ((defined USB_HOST_CONFIG_IP3516HS) && (USB_HOST_CONFIG_IP3516HS)) + +#define USB_HOST_CONFIG_IP3516HS_MAX_PIPE (32U) + +/*! + * @brief ohci ED max count. + */ +#define USB_HOST_CONFIG_IP3516HS_MAX_ATL (32U) + +/*! + * @brief ohci GTD max count. + */ +#define USB_HOST_CONFIG_IP3516HS_MAX_INT (32U) + +/*! + * @brief ohci ITD max count. + */ +#define USB_HOST_CONFIG_IP3516HS_MAX_ISO (0U) + +#endif + +/*! + * @brief host HUB class instance count, meantime it indicates HUB class enable or disable. + * - if 0, host HUB class driver is disable. + * - if greater than 0, host HUB class driver is enable. + */ +#define USB_HOST_CONFIG_HUB (0U) + +/*! + * @brief host HID class instance count, meantime it indicates HID class enable or disable. + * - if 0, host HID class driver is disable. + * - if greater than 0, host HID class driver is enable. + */ +#define USB_HOST_CONFIG_HID (0U) + +/*! + * @brief host MSD class instance count, meantime it indicates MSD class enable or disable. + * - if 0, host MSD class driver is disable. + * - if greater than 0, host MSD class driver is enable. + */ +#define USB_HOST_CONFIG_MSD (0U) + +/*! + * @brief host CDC class instance count, meantime it indicates CDC class enable or disable. + * - if 0, host CDC class driver is disable. + * - if greater than 0, host CDC class driver is enable. + */ +#define USB_HOST_CONFIG_CDC (0U) + +/*! + * @brief host AUDIO class instance count, meantime it indicates AUDIO class enable or disable. + * - if 0, host AUDIO class driver is disable. + * - if greater than 0, host AUDIO class driver is enable. + */ +#define USB_HOST_CONFIG_AUDIO (0U) + +/*! + * @brief host PHDC class instance count, meantime it indicates PHDC class enable or disable. + * - if 0, host PHDC class driver is disable. + * - if greater than 0, host PHDC class driver is enable. + */ +#define USB_HOST_CONFIG_PHDC (0U) + +/*! + * @brief host printer class instance count, meantime it indicates printer class enable or disable. + * - if 0, host printer class driver is disable. + * - if greater than 0, host printer class driver is enable. + */ +#define USB_HOST_CONFIG_PRINTER (0U) + +/*! + * @brief host charger detect enable or disable. It is only supported on RT600 currently. + * - if 0, host charger detect is disable. + * - if greater than 0, host charger detect is enable. + */ +#define USB_HOST_CONFIG_BATTERY_CHARGER (0U) + +#endif /* _USB_HOST_CONFIG_H_ */ \ No newline at end of file diff --git a/bsp/imxrt/libraries/drivers/usb/include/usb_misc.h b/bsp/imxrt/libraries/drivers/usb/include/usb_misc.h index 4e65cfa94b..382c5d3619 100644 --- a/bsp/imxrt/libraries/drivers/usb/include/usb_misc.h +++ b/bsp/imxrt/libraries/drivers/usb/include/usb_misc.h @@ -1,46 +1,34 @@ /* * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. - * Copyright 2016 NXP + * Copyright 2016, 2019 NXP + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef __USB_MISC_H__ #define __USB_MISC_H__ -#ifndef ENDIANNESS - -#error ENDIANNESS should be defined, and then rebulid the project. - -#endif - /******************************************************************************* * Definitions ******************************************************************************/ +/*! @brief Define big endian */ +#define USB_BIG_ENDIAN (0U) +/*! @brief Define little endian */ +#define USB_LITTLE_ENDIAN (1U) + +/*! @brief Define current endian */ +#ifndef ENDIANNESS +#define ENDIANNESS USB_LITTLE_ENDIAN +#endif +/*! @brief Define default timeout value */ +#if (defined(USE_RTOS) && (USE_RTOS > 0)) +#define USB_OSA_WAIT_TIMEOUT (osaWaitForever_c) +#else +#define USB_OSA_WAIT_TIMEOUT (0U) +#endif /* (defined(USE_RTOS) && (USE_RTOS > 0)) */ + /*! @brief Define USB printf */ #if defined(__cplusplus) extern "C" { @@ -52,10 +40,14 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); } #endif /* __cplusplus */ +#ifndef __DSC__ #if defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE < 1) #define usb_echo printf #else -#define usb_echo DbgConsole_Printf +#define usb_echo rt_kprintf +#endif +#else +#define usb_echo #endif #if defined(__ICCARM__) @@ -78,7 +70,7 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); #define STRUCT_UNPACKED __attribute__((__packed__)) #endif -#elif defined(__CC_ARM) +#elif defined(__CC_ARM) || (defined(__ARMCC_VERSION)) #ifndef STRUCT_PACKED #define STRUCT_PACKED _Pragma("pack(1U)") @@ -112,7 +104,7 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); #define USB_ASSIGN_VALUE_ADDRESS_LONG_BY_BYTE(n, m) \ { \ - *((uint8_t *)&(n)) = *((uint8_t *)&(m)); \ + *((uint8_t *)&(n)) = *((uint8_t *)&(m)); \ *((uint8_t *)&(n) + 1) = *((uint8_t *)&(m) + 1); \ *((uint8_t *)&(n) + 2) = *((uint8_t *)&(m) + 2); \ *((uint8_t *)&(n) + 3) = *((uint8_t *)&(m) + 3); \ @@ -120,13 +112,13 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); #define USB_ASSIGN_VALUE_ADDRESS_SHORT_BY_BYTE(n, m) \ { \ - *((uint8_t *)&(n)) = *((uint8_t *)&(m)); \ + *((uint8_t *)&(n)) = *((uint8_t *)&(m)); \ *((uint8_t *)&(n) + 1) = *((uint8_t *)&(m) + 1); \ } #define USB_ASSIGN_MACRO_VALUE_ADDRESS_LONG_BY_BYTE(n, m) \ { \ - *((uint8_t *)&(n)) = (uint8_t)m; \ + *((uint8_t *)&(n)) = (uint8_t)m; \ *((uint8_t *)&(n) + 1) = (uint8_t)(m >> 8); \ *((uint8_t *)&(n) + 2) = (uint8_t)(m >> 16); \ *((uint8_t *)&(n) + 3) = (uint8_t)(m >> 24); \ @@ -134,7 +126,7 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); #define USB_ASSIGN_MACRO_VALUE_ADDRESS_SHORT_BY_BYTE(n, m) \ { \ - *((uint8_t *)&(n)) = (uint8_t)m; \ + *((uint8_t *)&(n)) = (uint8_t)m; \ *((uint8_t *)&(n) + 1) = (uint8_t)(m >> 8); \ } @@ -150,65 +142,66 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); #define USB_SHORT_FROM_BIG_ENDIAN(n) (n) #define USB_LONG_FROM_BIG_ENDIAN(n) (n) -#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ - { \ - m[3] = ((n >> 24U) & 0xFFU); \ - m[2] = ((n >> 16U) & 0xFFU); \ - m[1] = ((n >> 8U) & 0xFFU); \ - m[0] = (n & 0xFFU); \ +#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ + { \ + m[3] = (uint8_t)((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[2] = (uint8_t)((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[1] = (uint8_t)((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (uint8_t)(((uint32_t)(n)) & 0xFFU); \ } -#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n) \ - ((uint32_t)((((uint8_t)n[3]) << 24U) | (((uint8_t)n[2]) << 16U) | (((uint8_t)n[1]) << 8U) | \ - (((uint8_t)n[0]) << 0U))) +#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n) \ + ((uint32_t)((((uint32_t)n[3]) << 24U) | (((uint32_t)n[2]) << 16U) | (((uint32_t)n[1]) << 8U) | \ + (((uint32_t)n[0]) << 0U))) -#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \ - { \ - m[0] = ((n >> 24U) & 0xFFU); \ - m[1] = ((n >> 16U) & 0xFFU); \ - m[2] = ((n >> 8U) & 0xFFU); \ - m[3] = (n & 0xFFU); \ +#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \ + { \ + m[0] = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[1] = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[2] = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[3] = (((uint32_t)(n)) & 0xFFU); \ } -#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n) \ - ((uint32_t)((((uint8_t)n[0]) << 24U) | (((uint8_t)n[1]) << 16U) | (((uint8_t)n[2]) << 8U) | \ - (((uint8_t)n[3]) << 0U))) +#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n) \ + ((uint32_t)((((uint32_t)n[0]) << 24U) | (((uint32_t)n[1]) << 16U) | (((uint32_t)n[2]) << 8U) | \ + (((uint32_t)n[3]) << 0U))) -#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ - { \ - m[1] = ((n >> 8U) & 0xFFU); \ - m[0] = (n & 0xFFU); \ +#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ + { \ + m[1] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (((uint16_t)(n)) & 0xFFU); \ } -#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[1]) << 8U) | (((uint8_t)n[0]) << 0U))) +#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint16_t)((((uint16_t)n[1]) << 8U) | (((uint16_t)n[0]) << 0U))) -#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \ - { \ - m[0] = ((n >> 8U) & 0xFFU); \ - m[1] = (n & 0xFFU); \ +#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \ + { \ + m[0] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[1] = (((uint16_t)(n)) & 0xFFU); \ } -#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[0]) << 8U) | (((uint8_t)n[1]) << 0U))) +#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint16_t)((((uint16_t)n[0]) << 8U) | (((uint16_t)n[1]) << 0U))) -#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m) \ - { \ - *((uint8_t *)&(m) + 3) = ((n >> 24U) & 0xFFU); \ - *((uint8_t *)&(m) + 2) = ((n >> 16U) & 0xFFU); \ - *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \ - *((uint8_t *)&(m) + 0) = (n & 0xFFU); \ +#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m) \ + { \ + *((uint8_t *)&(m) + 3) = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + *((uint8_t *)&(m) + 2) = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + *((uint8_t *)&(m) + 1) = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m) + 0) = (((uint32_t)(n)) & 0xFFU); \ } -#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n) \ - ((uint32_t)(((*((uint8_t *)&(n) + 3)) << 24U) | ((*((uint8_t *)&(n) + 2)) << 16U) | \ - ((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))) << 0U))) +#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n) \ + ((uint32_t)(((uint32_t)(*((uint8_t *)&(n) + 3)) << 24U) | ((uint32_t)(*((uint8_t *)&(n) + 2)) << 16U) | \ + ((uint32_t)(*((uint8_t *)&(n) + 1)) << 8U) | ((uint32_t)(*((uint8_t *)&(n))) << 0U))) -#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m) \ - { \ - *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \ - *((uint8_t *)&(m)) = ((n)&0xFFU); \ +#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m) \ + { \ + *((uint8_t *)&(m) + 1) = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m)) = ((((uint16_t)(n))) & 0xFFU); \ } -#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) ((uint32_t)(((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n)))))) +#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) \ + ((uint16_t)((uint16_t)(*((uint8_t *)&(n) + 1)) << 8U) | ((uint16_t)(*((uint8_t *)&(n))))) #else @@ -222,75 +215,76 @@ extern int DbgConsole_Printf(const char *fmt_s, ...); #define USB_SHORT_FROM_BIG_ENDIAN(n) SWAP2BYTE_CONST(n) #define USB_LONG_FROM_BIG_ENDIAN(n) SWAP4BYTE_CONST(n) -#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ - { \ - m[3] = ((n >> 24U) & 0xFFU); \ - m[2] = ((n >> 16U) & 0xFFU); \ - m[1] = ((n >> 8U) & 0xFFU); \ - m[0] = (n & 0xFFU); \ +#define USB_LONG_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ + { \ + m[3] = (uint8_t)((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[2] = (uint8_t)((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[1] = (uint8_t)((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (uint8_t)(((uint32_t)(n)) & 0xFFU); \ } -#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n) \ - ((uint32_t)((((uint8_t)n[3]) << 24U) | (((uint8_t)n[2]) << 16U) | (((uint8_t)n[1]) << 8U) | \ - (((uint8_t)n[0]) << 0U))) +#define USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(n) \ + ((uint32_t)((((uint32_t)n[3]) << 24U) | (((uint32_t)n[2]) << 16U) | (((uint32_t)n[1]) << 8U) | \ + (((uint32_t)n[0]) << 0U))) -#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \ - { \ - m[0] = ((n >> 24U) & 0xFFU); \ - m[1] = ((n >> 16U) & 0xFFU); \ - m[2] = ((n >> 8U) & 0xFFU); \ - m[3] = (n & 0xFFU); \ +#define USB_LONG_TO_BIG_ENDIAN_ADDRESS(n, m) \ + { \ + m[0] = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + m[1] = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + m[2] = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + m[3] = (((uint32_t)(n)) & 0xFFU); \ } -#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n) \ - ((uint32_t)((((uint8_t)n[0]) << 24U) | (((uint8_t)n[1]) << 16U) | (((uint8_t)n[2]) << 8U) | \ - (((uint8_t)n[3]) << 0U))) +#define USB_LONG_FROM_BIG_ENDIAN_ADDRESS(n) \ + ((uint32_t)((((uint32_t)n[0]) << 24U) | (((uint32_t)n[1]) << 16U) | (((uint32_t)n[2]) << 8U) | \ + (((uint32_t)n[3]) << 0U))) -#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ - { \ - m[1] = ((n >> 8U) & 0xFFU); \ - m[0] = (n & 0xFFU); \ +#define USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(n, m) \ + { \ + m[1] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[0] = (((uint16_t)(n)) & 0xFFU); \ } -#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[1]) << 8U) | (((uint8_t)n[0]) << 0U))) +#define USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(n) ((uint16_t)((((uint16_t)n[1]) << 8U) | (((uint16_t)n[0]) << 0U))) -#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \ - { \ - m[0] = ((n >> 8U) & 0xFFU); \ - m[1] = (n & 0xFFU); \ +#define USB_SHORT_TO_BIG_ENDIAN_ADDRESS(n, m) \ + { \ + m[0] = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + m[1] = (((uint16_t)(n)) & 0xFFU); \ } -#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint32_t)((((uint8_t)n[0]) << 8U) | (((uint8_t)n[1]) << 0U))) +#define USB_SHORT_FROM_BIG_ENDIAN_ADDRESS(n) ((uint16_t)((((uint16_t)n[0]) << 8U) | (((uint16_t)n[1]) << 0U))) -#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m) \ - { \ - *((uint8_t *)&(m) + 3) = ((n >> 24U) & 0xFFU); \ - *((uint8_t *)&(m) + 2) = ((n >> 16U) & 0xFFU); \ - *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \ - *((uint8_t *)&(m) + 0) = (n & 0xFFU); \ +#define USB_LONG_TO_LITTLE_ENDIAN_DATA(n, m) \ + { \ + *((uint8_t *)&(m) + 3) = ((((uint32_t)(n)) >> 24U) & 0xFFU); \ + *((uint8_t *)&(m) + 2) = ((((uint32_t)(n)) >> 16U) & 0xFFU); \ + *((uint8_t *)&(m) + 1) = ((((uint32_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m) + 0) = (((uint32_t)(n)) & 0xFFU); \ } -#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n) \ - ((uint32_t)(((*((uint8_t *)&(n) + 3)) << 24U) | ((*((uint8_t *)&(n) + 2)) << 16U) | \ - ((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n))) << 0U))) +#define USB_LONG_FROM_LITTLE_ENDIAN_DATA(n) \ + ((uint32_t)(((uint32_t)(*((uint8_t *)&(n) + 3)) << 24U) | ((uint32_t)(*((uint8_t *)&(n) + 2)) << 16U) | \ + ((uint32_t)(*((uint8_t *)&(n) + 1)) << 8U) | ((uint32_t)(*((uint8_t *)&(n))) << 0U))) -#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m) \ - { \ - *((uint8_t *)&(m) + 1) = ((n >> 8U) & 0xFFU); \ - *((uint8_t *)&(m)) = ((n)&0xFFU); \ +#define USB_SHORT_TO_LITTLE_ENDIAN_DATA(n, m) \ + { \ + *((uint8_t *)&(m) + 1) = ((((uint16_t)(n)) >> 8U) & 0xFFU); \ + *((uint8_t *)&(m)) = ((((uint16_t)(n))) & 0xFFU); \ } -#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) ((uint32_t)(((*((uint8_t *)&(n) + 1)) << 8U) | ((*((uint8_t *)&(n)))))) +#define USB_SHORT_FROM_LITTLE_ENDIAN_DATA(n) \ + ((uint16_t)(((uint16_t)(*(((uint8_t *)&(n)) + 1)) << 8U) | ((uint16_t)(*((uint8_t *)&(n)))))) #endif /* * The following MACROs (USB_GLOBAL, USB_BDT, USB_RAM_ADDRESS_ALIGNMENT, etc) are only used for USB device stack. - * The USB device global variables are put into the section m_usb_global and m_usb_bdt or the section - * .bss.m_usb_global and .bss.m_usb_bdt by using the MACRO USB_GLOBAL and USB_BDT. In this way, the USB device + * The USB device global variables are put into the section m_usb_global and m_usb_bdt + * by using the MACRO USB_GLOBAL and USB_BDT. In this way, the USB device * global variables can be linked into USB dedicated RAM by USB_STACK_USE_DEDICATED_RAM. * The MACRO USB_STACK_USE_DEDICATED_RAM is used to decide the USB stack uses dedicated RAM or not. The value of - * the marco can be set as 0, USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL, or USB_STACK_DEDICATED_RAM_TYPE_BDT. + * the macro can be set as 0, USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL, or USB_STACK_DEDICATED_RAM_TYPE_BDT. * The MACRO USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL means USB device global variables, including USB_BDT and * USB_GLOBAL, are put into the USB dedicated RAM. This feature can only be enabled when the USB dedicated RAM * is not less than 2K Bytes. @@ -313,40 +307,63 @@ _Pragma("diag_suppress=Pm120") #define USB_RAM_ADDRESS_ALIGNMENT(n) USB_ALIGN_PRAGMA(data_alignment = n) _Pragma("diag_suppress=Pm120") #define USB_LINK_SECTION_PART(str) _Pragma(#str) -#define USB_LINK_SECTION_SUB(sec) USB_LINK_SECTION_PART(location = #sec) +#define USB_LINK_DMA_INIT_DATA(sec) USB_LINK_SECTION_PART(location = #sec) #define USB_LINK_USB_GLOBAL _Pragma("location = \"m_usb_global\"") #define USB_LINK_USB_BDT _Pragma("location = \"m_usb_bdt\"") -#define USB_LINK_USB_GLOBAL_BSS _Pragma("location = \".bss.m_usb_global\"") -#define USB_LINK_USB_BDT_BSS _Pragma("location = \".bss.m_usb_bdt\"") +#define USB_LINK_USB_GLOBAL_BSS +#define USB_LINK_USB_BDT_BSS _Pragma("diag_default=Pm120") #define USB_LINK_DMA_NONINIT_DATA _Pragma("location = \"m_usb_dma_noninit_data\"") #define USB_LINK_NONCACHE_NONINIT_DATA _Pragma("location = \"NonCacheable\"") -#elif defined(__CC_ARM) +#elif defined(__CC_ARM) || (defined(__ARMCC_VERSION)) #define USB_WEAK_VAR __attribute__((weak)) -#define USB_WEAK_FUN __weak +#define USB_WEAK_FUN __attribute__((weak)) #define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n))) -#define USB_LINK_SECTION_SUB(sec) __attribute__((section(#sec))) +#define USB_LINK_DMA_INIT_DATA(sec) __attribute__((section(#sec))) +#if defined(__CC_ARM) #define USB_LINK_USB_GLOBAL __attribute__((section("m_usb_global"))) __attribute__((zero_init)) +#else +#define USB_LINK_USB_GLOBAL __attribute__((section(".bss.m_usb_global"))) +#endif +#if defined(__CC_ARM) #define USB_LINK_USB_BDT __attribute__((section("m_usb_bdt"))) __attribute__((zero_init)) -#define USB_LINK_USB_GLOBAL_BSS __attribute__((section(".bss.m_usb_global"))) __attribute__((zero_init)) -#define USB_LINK_USB_BDT_BSS __attribute__((section(".bss.m_usb_bdt"))) __attribute__((zero_init)) +#else +#define USB_LINK_USB_BDT __attribute__((section(".bss.m_usb_bdt"))) +#endif +#define USB_LINK_USB_GLOBAL_BSS +#define USB_LINK_USB_BDT_BSS +#if defined(__CC_ARM) #define USB_LINK_DMA_NONINIT_DATA __attribute__((section("m_usb_dma_noninit_data"))) __attribute__((zero_init)) +#else +#define USB_LINK_DMA_NONINIT_DATA __attribute__((section(".bss.m_usb_dma_noninit_data"))) +#endif +#if defined(__CC_ARM) #define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section("NonCacheable"))) __attribute__((zero_init)) +#else +#define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section(".bss.NonCacheable"))) +#endif #elif defined(__GNUC__) #define USB_WEAK_VAR __attribute__((weak)) #define USB_WEAK_FUN __attribute__((weak)) #define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n))) -#define USB_LINK_SECTION_SUB(sec) __attribute__((section(#sec))) +#define USB_LINK_DMA_INIT_DATA(sec) __attribute__((section(#sec))) #define USB_LINK_USB_GLOBAL __attribute__((section("m_usb_global, \"aw\", %nobits @"))) #define USB_LINK_USB_BDT __attribute__((section("m_usb_bdt, \"aw\", %nobits @"))) -#define USB_LINK_USB_GLOBAL_BSS __attribute__((section(".bss.m_usb_global, \"aw\", %nobits @"))) -#define USB_LINK_USB_BDT_BSS __attribute__((section(".bss.m_usb_bdt, \"aw\", %nobits @"))) +#define USB_LINK_USB_GLOBAL_BSS +#define USB_LINK_USB_BDT_BSS #define USB_LINK_DMA_NONINIT_DATA __attribute__((section("m_usb_dma_noninit_data, \"aw\", %nobits @"))) #define USB_LINK_NONCACHE_NONINIT_DATA __attribute__((section("NonCacheable, \"aw\", %nobits @"))) +#elif (defined(__DSC__) && defined(__CW__)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define USB_WEAK_VAR __attribute__((weak)) +#define USB_WEAK_FUN __attribute__((weak)) +#define USB_RAM_ADDRESS_ALIGNMENT(n) __attribute__((aligned(n))) +#define USB_LINK_USB_BDT_BSS +#define USB_LINK_USB_GLOBAL_BSS #else #error The tool-chain is not supported. #endif @@ -356,28 +373,32 @@ _Pragma("diag_suppress=Pm120") #if ((defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)) && (defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE))) #define USB_CACHE_LINESIZE MAX(FSL_FEATURE_L2CACHE_LINESIZE_BYTE, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) -#elif(defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)) +#elif (defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)) #define USB_CACHE_LINESIZE MAX(FSL_FEATURE_L2CACHE_LINESIZE_BYTE, 0) -#elif(defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)) +#elif (defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)) #define USB_CACHE_LINESIZE MAX(0, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) #else -#define USB_CACHE_LINESIZE 4 +#define USB_CACHE_LINESIZE 4U #endif #else -#define USB_CACHE_LINESIZE 4 +#define USB_CACHE_LINESIZE 4U #endif #if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \ ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))) -#define USB_DATA_ALIGN 64 +#define USB_DATA_ALIGN 64U #else -#define USB_DATA_ALIGN 4 +#define USB_DATA_ALIGN 4U #endif -#define USB_DATA_ALIGN_SIZE MAX(USB_CACHE_LINESIZE, USB_DATA_ALIGN) +#if (USB_CACHE_LINESIZE > USB_DATA_ALIGN) +#define USB_DATA_ALIGN_SIZE USB_CACHE_LINESIZE +#else +#define USB_DATA_ALIGN_SIZE USB_DATA_ALIGN +#endif -#define USB_DATA_ALIGN_SIZE_MULTIPLE(n) ((n + USB_DATA_ALIGN_SIZE - 1) & (~(USB_DATA_ALIGN_SIZE - 1))) +#define USB_DATA_ALIGN_SIZE_MULTIPLE(n) (((n) + USB_DATA_ALIGN_SIZE - 1U) & (~(USB_DATA_ALIGN_SIZE - 1U))) #if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL) @@ -387,13 +408,19 @@ _Pragma("diag_suppress=Pm120") #if (defined(USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE)) || \ (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) #define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA -#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data) +#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(m_usb_dma_init_data) +#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA +#else +#if (defined(DATA_SECTION_IS_CACHEABLE) && (DATA_SECTION_IS_CACHEABLE)) +#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA +#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(NonCacheable.init) #define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA #else #define USB_DMA_DATA_NONINIT_SUB #define USB_DMA_DATA_INIT_SUB #define USB_CONTROLLER_DATA USB_LINK_USB_GLOBAL #endif +#endif #elif defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT) @@ -403,7 +430,13 @@ _Pragma("diag_suppress=Pm120") (defined(USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE)) #define USB_GLOBAL USB_LINK_DMA_NONINIT_DATA #define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA -#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data) +#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(m_usb_dma_init_data) +#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA +#else +#if (defined(DATA_SECTION_IS_CACHEABLE) && (DATA_SECTION_IS_CACHEABLE)) +#define USB_GLOBAL USB_LINK_NONCACHE_NONINIT_DATA +#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA +#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(NonCacheable.init) #define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA #else #define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS @@ -411,6 +444,7 @@ _Pragma("diag_suppress=Pm120") #define USB_DMA_DATA_INIT_SUB #define USB_CONTROLLER_DATA #endif +#endif #else @@ -420,9 +454,17 @@ _Pragma("diag_suppress=Pm120") #define USB_GLOBAL USB_LINK_DMA_NONINIT_DATA #define USB_BDT USB_LINK_NONCACHE_NONINIT_DATA #define USB_DMA_DATA_NONINIT_SUB USB_LINK_DMA_NONINIT_DATA -#define USB_DMA_DATA_INIT_SUB USB_LINK_SECTION_SUB(m_usb_dma_init_data) +#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(m_usb_dma_init_data) #define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA +#else + +#if (defined(DATA_SECTION_IS_CACHEABLE) && (DATA_SECTION_IS_CACHEABLE)) +#define USB_GLOBAL USB_LINK_NONCACHE_NONINIT_DATA +#define USB_BDT USB_LINK_NONCACHE_NONINIT_DATA +#define USB_DMA_DATA_NONINIT_SUB USB_LINK_NONCACHE_NONINIT_DATA +#define USB_DMA_DATA_INIT_SUB USB_LINK_DMA_INIT_DATA(NonCacheable.init) +#define USB_CONTROLLER_DATA USB_LINK_NONCACHE_NONINIT_DATA #else #define USB_GLOBAL USB_LINK_USB_GLOBAL_BSS #define USB_BDT USB_LINK_USB_BDT_BSS @@ -433,6 +475,8 @@ _Pragma("diag_suppress=Pm120") #endif +#endif + #define USB_DMA_NONINIT_DATA_ALIGN(n) USB_RAM_ADDRESS_ALIGNMENT(n) USB_DMA_DATA_NONINIT_SUB #define USB_DMA_INIT_DATA_ALIGN(n) USB_RAM_ADDRESS_ALIGNMENT(n) USB_DMA_DATA_INIT_SUB @@ -449,4 +493,4 @@ _Pragma("diag_suppress=Pm120") /* #define USB_RAM_ADDRESS_NONCACHEREG_ALIGNMENT(n, var) AT_NONCACHEABLE_SECTION_ALIGN(var, n) */ /* #define USB_RAM_ADDRESS_NONCACHEREG(var) AT_NONCACHEABLE_SECTION(var) */ -#endif /* __USB_MISC_H__ */ +#endif /* __USB_MISC_H__ */ \ No newline at end of file From 77b8db800ce99a931ed92c24015f91287575642b Mon Sep 17 00:00:00 2001 From: Meco Man <920369182@qq.com> Date: Tue, 25 Jan 2022 23:24:09 -0500 Subject: [PATCH 64/65] [imxrt] format codes --- bsp/imxrt/libraries/drivers/drv_can.c | 4 +- bsp/imxrt/libraries/drivers/drv_can.h | 4 +- bsp/imxrt/libraries/drivers/drv_eth.c | 10 +- bsp/imxrt/libraries/drivers/drv_gpio.c | 4 +- bsp/imxrt/libraries/drivers/drv_gpio.h | 8 +- bsp/imxrt/libraries/drivers/drv_i2c.c | 114 +++++++-------- bsp/imxrt/libraries/drivers/drv_mdio.c | 3 +- bsp/imxrt/libraries/drivers/drv_mdio.h | 3 +- .../libraries/drivers/drv_pulse_encoder.c | 6 +- bsp/imxrt/libraries/drivers/drv_sai.c | 4 +- bsp/imxrt/libraries/drivers/drv_sai.h | 8 +- bsp/imxrt/libraries/drivers/drv_sdram.c | 20 +-- bsp/imxrt/libraries/drivers/drv_sdram.h | 4 +- bsp/imxrt/libraries/drivers/drv_spi.c | 136 +++++++++--------- bsp/imxrt/libraries/drivers/drv_spi.h | 4 +- bsp/imxrt/libraries/drivers/drv_uart.c | 4 +- .../libraries/drivers/usb/device/usb_device.h | 6 +- 17 files changed, 170 insertions(+), 172 deletions(-) diff --git a/bsp/imxrt/libraries/drivers/drv_can.c b/bsp/imxrt/libraries/drivers/drv_can.c index 829060e2d7..377e36bcc7 100644 --- a/bsp/imxrt/libraries/drivers/drv_can.c +++ b/bsp/imxrt/libraries/drivers/drv_can.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -375,7 +375,7 @@ static int can_send(struct rt_can_device *can_dev, const void *buf, rt_uint32_t ret = RT_EBUSY; break; } - + return ret; } diff --git a/bsp/imxrt/libraries/drivers/drv_can.h b/bsp/imxrt/libraries/drivers/drv_can.h index d5d2b13f2e..1ea524e98c 100644 --- a/bsp/imxrt/libraries/drivers/drv_can.h +++ b/bsp/imxrt/libraries/drivers/drv_can.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,7 +7,7 @@ * Date Author Notes * 2019-06-28 misonyo the first version. */ - + #ifndef DRV_CAN_H__ #define DRV_CAN_H__ diff --git a/bsp/imxrt/libraries/drivers/drv_eth.c b/bsp/imxrt/libraries/drivers/drv_eth.c index ecff2bb6ab..35de385658 100644 --- a/bsp/imxrt/libraries/drivers/drv_eth.c +++ b/bsp/imxrt/libraries/drivers/drv_eth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2019, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -329,7 +329,7 @@ static status_t _ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, const ui #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ pbuf_copy_partial((const struct pbuf *)data, (void *)address, length, 0); - + /* Set data length. */ curBuffDescrip->length = length; #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE @@ -434,7 +434,7 @@ static status_t _ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, const ui address = (uint32_t)curBuffDescrip->buffer; #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ DCACHE_CleanByRange(address, handle->txBuffSizeAlign[0]); -#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ +#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ /* Active the transmit buffer descriptor. */ _ENET_ActiveSend(base, 0); @@ -454,8 +454,8 @@ static status_t _ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, const ui /* transmit packet. */ rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p) { - rt_err_t result = RT_EOK; - enet_handle_t * enet_handle = &imxrt_eth_device.enet_handle; + rt_err_t result = RT_EOK; + enet_handle_t * enet_handle = &imxrt_eth_device.enet_handle; RT_ASSERT(p != NULL); RT_ASSERT(enet_handle != RT_NULL); diff --git a/bsp/imxrt/libraries/drivers/drv_gpio.c b/bsp/imxrt/libraries/drivers/drv_gpio.c index a2e9dda3d7..3e27a1e9c3 100644 --- a/bsp/imxrt/libraries/drivers/drv_gpio.c +++ b/bsp/imxrt/libraries/drivers/drv_gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -70,7 +70,7 @@ const struct pin_mask mask_tab[5] = #endif }; -const rt_int8_t reg_offset[] = +const rt_int8_t reg_offset[] = { #if defined(SOC_IMXRT1015_SERIES) 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 64, 65, 66, 67, 68, 69, diff --git a/bsp/imxrt/libraries/drivers/drv_gpio.h b/bsp/imxrt/libraries/drivers/drv_gpio.h index cf1a80ffbb..c2de77d933 100644 --- a/bsp/imxrt/libraries/drivers/drv_gpio.h +++ b/bsp/imxrt/libraries/drivers/drv_gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,12 +7,12 @@ * Date Author Notes * 2018-4-30 misonyo the first version. */ - + #ifndef DRV_GPIO_H__ #define DRV_GPIO_H__ -#include -#include +#include +#include #define GET_PIN(PORTx, PIN) (32 * (PORTx - 1) + (PIN & 31)) /* PORTx:1,2,3,4,5 */ diff --git a/bsp/imxrt/libraries/drivers/drv_i2c.c b/bsp/imxrt/libraries/drivers/drv_i2c.c index 0ccbb48996..c2a8ec321b 100644 --- a/bsp/imxrt/libraries/drivers/drv_i2c.c +++ b/bsp/imxrt/libraries/drivers/drv_i2c.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -35,9 +35,9 @@ struct imxrt_i2c_bus volatile rt_uint32_t msg_ptr; volatile rt_uint32_t dptr; char *device_name; -#ifdef SOC_IMXRT1170_SERIES - clock_root_t clock_root; -#endif +#ifdef SOC_IMXRT1170_SERIES + clock_root_t clock_root; +#endif }; #if defined (BSP_USING_I2C1) @@ -70,7 +70,7 @@ struct imxrt_i2c_bus /* Select USB1 PLL (360 MHz) as master lpi2c clock source */ #define LPI2C_CLOCK_SOURCE_SELECT (1U) -#ifdef SOC_IMXRT1170_SERIES +#ifdef SOC_IMXRT1170_SERIES /* Clock divider for master lpi2c clock source */ #define LPI2C_CLOCK_SOURCE_DIVIDER (12U) #else @@ -157,19 +157,19 @@ static rt_err_t imxrt_lpi2c_configure(struct imxrt_i2c_bus *bus, lpi2c_master_co RT_ASSERT(cfg != RT_NULL); bus->parent.ops = &imxrt_i2c_ops; -#ifdef SOC_IMXRT1170_SERIES - clock_root_config_t rootCfg = {0}; - rootCfg.mux = LPI2C_CLOCK_SOURCE_SELECT; - rootCfg.div = LPI2C_CLOCK_SOURCE_DIVIDER + 1; - CLOCK_SetRootClock(bus->clock_root, &rootCfg); - volatile uint32_t freq = CLOCK_GetRootClockFreq(bus->clock_root); - LPI2C_MasterInit(bus->I2C, cfg, freq); +#ifdef SOC_IMXRT1170_SERIES + clock_root_config_t rootCfg = {0}; + rootCfg.mux = LPI2C_CLOCK_SOURCE_SELECT; + rootCfg.div = LPI2C_CLOCK_SOURCE_DIVIDER + 1; + CLOCK_SetRootClock(bus->clock_root, &rootCfg); + volatile uint32_t freq = CLOCK_GetRootClockFreq(bus->clock_root); + LPI2C_MasterInit(bus->I2C, cfg, freq); #else - CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT); - CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER); + CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT); + CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER); LPI2C_MasterInit(bus->I2C, cfg, LPI2C_CLOCK_FREQUENCY); -#endif - +#endif + return RT_EOK; } @@ -267,36 +267,36 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, { if (imxrt_i2c->msg[i].flags & RT_I2C_RD) { - if ((imxrt_i2c->msg[i].flags & RT_I2C_NO_START) != RT_I2C_NO_START) - { - if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success) - { - i = 0; - break; - } + if ((imxrt_i2c->msg[i].flags & RT_I2C_NO_START) != RT_I2C_NO_START) + { + if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Write) != kStatus_Success) + { + i = 0; + break; + } - while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) - { - } - - if (LPI2C_MasterRepeatedStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) - { - i = 0; - break; - } - } - else - { - if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) - { - i = 0; - break; - } - - while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) - { - } - } + while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + { + } + + if (LPI2C_MasterRepeatedStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) + { + i = 0; + break; + } + } + else + { + if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) + { + i = 0; + break; + } + + while (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + { + } + } if (LPI2C_MasterStart(imxrt_i2c->I2C, imxrt_i2c->msg[i].addr, kLPI2C_Read) != kStatus_Success) { @@ -321,16 +321,16 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, i = 0; break; } - + if(LPI2C_MasterWaitForTxFifoAllEmpty(imxrt_i2c->I2C) != kStatus_Success) { i = 0; break; } - - if (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) + + if (LPI2C_MasterGetStatusFlags(imxrt_i2c->I2C) & kLPI2C_MasterNackDetectFlag) { - i = 0; + i = 0; break; } @@ -346,12 +346,12 @@ static rt_size_t imxrt_i2c_mst_xfer(struct rt_i2c_bus_device *bus, break; } } - - if (LPI2C_MasterStop(imxrt_i2c->I2C) != kStatus_Success) - { - i = 0; - } - + + if (LPI2C_MasterStop(imxrt_i2c->I2C) != kStatus_Success) + { + i = 0; + } + } imxrt_i2c->msg = RT_NULL; @@ -434,7 +434,7 @@ int rt_hw_i2c_init(void) #elif defined(HW_I2C5_BADURATE_100kHZ) masterConfig.baudRate_Hz = 100000U; #endif /* HW_I2C5_BADURATE_400kHZ */ - lpi2c5.clock_root = kCLOCK_Root_Lpi2c5; + lpi2c5.clock_root = kCLOCK_Root_Lpi2c5; imxrt_lpi2c_configure(&lpi2c5, &masterConfig); rt_i2c_bus_device_register(&lpi2c5.parent, lpi2c5.device_name); #endif /* BSP_USING_I2C5 */ @@ -446,7 +446,7 @@ int rt_hw_i2c_init(void) #elif defined(HW_I2C6_BADURATE_100kHZ) masterConfig.baudRate_Hz = 100000U; #endif /* HW_I2C6_BADURATE_400kHZ */ - lpi2c6.clock_root = kCLOCK_Root_Lpi2c6; + lpi2c6.clock_root = kCLOCK_Root_Lpi2c6; imxrt_lpi2c_configure(&lpi2c6, &masterConfig); rt_i2c_bus_device_register(&lpi2c6.parent, lpi2c6.device_name); #endif /* BSP_USING_I2C6 */ diff --git a/bsp/imxrt/libraries/drivers/drv_mdio.c b/bsp/imxrt/libraries/drivers/drv_mdio.c index 3e98d57f29..2738877335 100644 --- a/bsp/imxrt/libraries/drivers/drv_mdio.c +++ b/bsp/imxrt/libraries/drivers/drv_mdio.c @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/imxrt/libraries/drivers/drv_mdio.h b/bsp/imxrt/libraries/drivers/drv_mdio.h index a1623cfc2c..69d8290a32 100644 --- a/bsp/imxrt/libraries/drivers/drv_mdio.h +++ b/bsp/imxrt/libraries/drivers/drv_mdio.h @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2006-2020, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * diff --git a/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c b/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c index c0e5ce27f8..517664b73d 100644 --- a/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c +++ b/bsp/imxrt/libraries/drivers/drv_pulse_encoder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -22,7 +22,7 @@ #if !defined(BSP_USING_PULSE_ENCODER1) && !defined(BSP_USING_PULSE_ENCODER2) && !defined(BSP_USING_PULSE_ENCODER3) \ && !defined(BSP_USING_PULSE_ENCODER4) #error "Please define at least one BSP_USING_PULSE_ENCODERx" - /* this driver can be disabled at menuconfig → RT-Thread Components → Device Drivers */ + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ #elif (defined(BSP_USING_PULSE_ENCODER2) || defined(BSP_USING_PULSE_ENCODER3) || defined(BSP_USING_PULSE_ENCODER4)) || defined(SOC_IMXRT1015_SERIES) #error "IMXRT1015 had only one quadrature decoder module" #elif (defined(BSP_USING_PULSE_ENCODER3) || defined(BSP_USING_PULSE_ENCODER4)) || defined(SOC_IMXRT1020_SERIES) @@ -157,4 +157,4 @@ int rt_hw_pulse_encoder_init(void) } INIT_BOARD_EXPORT(rt_hw_pulse_encoder_init); -#endif \ No newline at end of file +#endif diff --git a/bsp/imxrt/libraries/drivers/drv_sai.c b/bsp/imxrt/libraries/drivers/drv_sai.c index 63c2eadb32..7a682dfb34 100644 --- a/bsp/imxrt/libraries/drivers/drv_sai.c +++ b/bsp/imxrt/libraries/drivers/drv_sai.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,7 +7,7 @@ * Date Author Notes * 2018-4-30 misonyo the first version. */ - + #include #include #include diff --git a/bsp/imxrt/libraries/drivers/drv_sai.h b/bsp/imxrt/libraries/drivers/drv_sai.h index 80e4c5d5dc..1affd91101 100644 --- a/bsp/imxrt/libraries/drivers/drv_sai.h +++ b/bsp/imxrt/libraries/drivers/drv_sai.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -30,9 +30,9 @@ /* Clock divider for sai1 clock source */ #define DEMO_SAI1_CLOCK_SOURCE_DIVIDER (63U) /* Get frequency of sai1 clock */ -#define AUD_BLOCK_CNT 2 -#define AUD_BLOCK_SIZE 1024 -#define AUD_FIFO_SIZE (AUD_BLOCK_SIZE * AUD_BLOCK_CNT) +#define AUD_BLOCK_CNT 2 +#define AUD_BLOCK_SIZE 1024 +#define AUD_FIFO_SIZE (AUD_BLOCK_SIZE * AUD_BLOCK_CNT) #define DEMO_SAI_CLK_FREQ \ (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI1_CLOCK_SOURCE_DIVIDER + 1U) / \ (DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER + 1U)) diff --git a/bsp/imxrt/libraries/drivers/drv_sdram.c b/bsp/imxrt/libraries/drivers/drv_sdram.c index a0dbe7afe2..0b7b7907b8 100644 --- a/bsp/imxrt/libraries/drivers/drv_sdram.c +++ b/bsp/imxrt/libraries/drivers/drv_sdram.c @@ -31,7 +31,7 @@ int rt_hw_sdram_Init(void) /* Initializes the MAC configure structure to zero. */ memset(&config, 0, sizeof(semc_config_t)); memset(&sdramconfig, 0, sizeof(semc_sdram_config_t)); - + /* Initialize SEMC. */ SEMC_GetDefaultConfig(&config); config.dqsMode = kSEMC_Loopbackdqspad; /* For more accurate timing. */ @@ -68,18 +68,18 @@ int rt_hw_sdram_Init(void) { LOG_D("sdram init success, mapped at 0x%X, size is %d Kbytes.", SDRAM_BANK_ADDR, SDRAM_SIZE); #ifdef RT_USING_MEMHEAP_AS_HEAP - /* - * If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap. - * The heap start address is (base + half size), and the size is (half size - 2M). - * The reasons are: - * 1. Reserve the half space for SDRAM link case - * 2. Reserve the 2M for non-cache space - */ + /* + * If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap. + * The heap start address is (base + half size), and the size is (half size - 2M). + * The reasons are: + * 1. Reserve the half space for SDRAM link case + * 2. Reserve the 2M for non-cache space + */ rt_memheap_init(&system_heap, "sdram", (void *)(SDRAM_BANK_ADDR + (SDRAM_SIZE * 1024)/2), - (SDRAM_SIZE * 1024)/2 - (2 * 1024 * 1024)); + (SDRAM_SIZE * 1024)/2 - (2 * 1024 * 1024)); #endif } - + return result; } INIT_BOARD_EXPORT(rt_hw_sdram_Init); diff --git a/bsp/imxrt/libraries/drivers/drv_sdram.h b/bsp/imxrt/libraries/drivers/drv_sdram.h index f7956c6944..9eda46bcd5 100644 --- a/bsp/imxrt/libraries/drivers/drv_sdram.h +++ b/bsp/imxrt/libraries/drivers/drv_sdram.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,7 +7,7 @@ * Date Author Notes * 2018-03-27 Liuguang the first version. */ - + #ifndef DRV_SDRAM_H__ #define DRV_SDRAM_H__ diff --git a/bsp/imxrt/libraries/drivers/drv_spi.c b/bsp/imxrt/libraries/drivers/drv_spi.c index 04c9e94020..c32d66b934 100644 --- a/bsp/imxrt/libraries/drivers/drv_spi.c +++ b/bsp/imxrt/libraries/drivers/drv_spi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -11,10 +11,10 @@ #include #ifdef BSP_USING_SPI -#include "drv_spi.h" -#include "fsl_common.h" -#include "fsl_iomuxc.h" -#include "fsl_lpspi.h" +#include "drv_spi.h" +#include "fsl_common.h" +#include "fsl_iomuxc.h" +#include "fsl_lpspi.h" #include "fsl_lpspi_edma.h" #include "fsl_dmamux.h" @@ -177,21 +177,21 @@ void edma_xfer_callback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, st rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin) { - rt_err_t ret = RT_EOK; - - struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); - RT_ASSERT(spi_device != RT_NULL); - - struct imxrt_sw_spi_cs *cs_pin = (struct imxrt_sw_spi_cs *)rt_malloc(sizeof(struct imxrt_sw_spi_cs)); + rt_err_t ret = RT_EOK; + + struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + + struct imxrt_sw_spi_cs *cs_pin = (struct imxrt_sw_spi_cs *)rt_malloc(sizeof(struct imxrt_sw_spi_cs)); RT_ASSERT(cs_pin != RT_NULL); - + cs_pin->pin = pin; - rt_pin_mode(pin, PIN_MODE_OUTPUT); - rt_pin_write(pin, PIN_HIGH); - - ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); - - return ret; + rt_pin_mode(pin, PIN_MODE_OUTPUT); + rt_pin_write(pin, PIN_HIGH); + + ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + + return ret; } static uint32_t imxrt_get_lpspi_freq(void) @@ -199,31 +199,31 @@ static uint32_t imxrt_get_lpspi_freq(void) uint32_t freq = 0; /* CLOCK_GetMux(kCLOCK_LpspiMux): - 00b: derive clock from PLL3 PFD1 720M - 01b: derive clock from PLL3 PFD0 720M - 10b: derive clock from PLL2 528M - 11b: derive clock from PLL2 PFD2 396M + 00b: derive clock from PLL3 PFD1 720M + 01b: derive clock from PLL3 PFD0 720M + 10b: derive clock from PLL2 528M + 11b: derive clock from PLL2 PFD2 396M */ switch(CLOCK_GetMux(kCLOCK_LpspiMux)) { case 0: - freq = CLOCK_GetFreq(kCLOCK_Usb1PllPfd1Clk); - break; - + freq = CLOCK_GetFreq(kCLOCK_Usb1PllPfd1Clk); + break; + case 1: - freq = CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk); - break; - + freq = CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk); + break; + case 2: - freq = CLOCK_GetFreq(kCLOCK_SysPllClk); - break; - + freq = CLOCK_GetFreq(kCLOCK_SysPllClk); + break; + case 3: - freq = CLOCK_GetFreq(kCLOCK_SysPllPfd2Clk); - break; + freq = CLOCK_GetFreq(kCLOCK_SysPllPfd2Clk); + break; } - - freq /= (CLOCK_GetDiv(kCLOCK_LpspiDiv) + 1U); + + freq /= (CLOCK_GetDiv(kCLOCK_LpspiDiv) + 1U); return freq; } @@ -250,7 +250,7 @@ static void lpspi_dma_config(struct imxrt_spi *spi) DMAMUX_SetSource(DMAMUX, spi->dma->tx_channel, spi->dma->tx_request); DMAMUX_EnableChannel(DMAMUX, spi->dma->tx_channel); EDMA_CreateHandle(&spi->dma->tx_edma, DMA0, spi->dma->tx_channel); - + LPSPI_MasterTransferCreateHandleEDMA(spi->base, &spi->dma->spi_edma, edma_xfer_callback, @@ -263,8 +263,8 @@ static void lpspi_dma_config(struct imxrt_spi *spi) static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) { - lpspi_master_config_t masterConfig; - struct imxrt_spi *spi = RT_NULL; + lpspi_master_config_t masterConfig; + struct imxrt_spi *spi = RT_NULL; RT_ASSERT(cfg != RT_NULL); RT_ASSERT(device != RT_NULL); @@ -274,76 +274,76 @@ static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_config if(cfg->data_width != 8 && cfg->data_width != 16 && cfg->data_width != 32) { - return RT_EINVAL; + return RT_EINVAL; } - LPSPI_MasterGetDefaultConfig(&masterConfig); - + LPSPI_MasterGetDefaultConfig(&masterConfig); + if(cfg->max_hz > 40*1000*1000) { cfg->max_hz = 40*1000*1000; } - masterConfig.baudRate = cfg->max_hz; - masterConfig.bitsPerFrame = cfg->data_width; - + masterConfig.baudRate = cfg->max_hz; + masterConfig.bitsPerFrame = cfg->data_width; + if(cfg->mode & RT_SPI_MSB) { - masterConfig.direction = kLPSPI_MsbFirst; + masterConfig.direction = kLPSPI_MsbFirst; } else { - masterConfig.direction = kLPSPI_LsbFirst; + masterConfig.direction = kLPSPI_LsbFirst; } - + if(cfg->mode & RT_SPI_CPHA) { - masterConfig.cpha = kLPSPI_ClockPhaseSecondEdge; + masterConfig.cpha = kLPSPI_ClockPhaseSecondEdge; } else { - masterConfig.cpha = kLPSPI_ClockPhaseFirstEdge; + masterConfig.cpha = kLPSPI_ClockPhaseFirstEdge; } - + if(cfg->mode & RT_SPI_CPOL) { - masterConfig.cpol = kLPSPI_ClockPolarityActiveLow; + masterConfig.cpol = kLPSPI_ClockPolarityActiveLow; } else { - masterConfig.cpol = kLPSPI_ClockPolarityActiveHigh; + masterConfig.cpol = kLPSPI_ClockPolarityActiveHigh; } - masterConfig.pinCfg = kLPSPI_SdiInSdoOut; + masterConfig.pinCfg = kLPSPI_SdiInSdoOut; masterConfig.dataOutConfig = kLpspiDataOutTristate; - masterConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.baudRate; - masterConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.baudRate; - masterConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.baudRate; + masterConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.baudRate; + masterConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.baudRate; + masterConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.baudRate; - LPSPI_MasterInit(spi->base, &masterConfig, imxrt_get_lpspi_freq()); - spi->base->CFGR1 |= LPSPI_CFGR1_PCSCFG_MASK; + LPSPI_MasterInit(spi->base, &masterConfig, imxrt_get_lpspi_freq()); + spi->base->CFGR1 |= LPSPI_CFGR1_PCSCFG_MASK; return RT_EOK; } static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) { - lpspi_transfer_t transfer; + lpspi_transfer_t transfer; status_t status; RT_ASSERT(device != RT_NULL); RT_ASSERT(device->bus != RT_NULL); RT_ASSERT(device->bus->parent.user_data != RT_NULL); - struct imxrt_spi *spi = (struct imxrt_spi *)(device->bus->parent.user_data); - struct imxrt_sw_spi_cs *cs = device->parent.user_data; + struct imxrt_spi *spi = (struct imxrt_spi *)(device->bus->parent.user_data); + struct imxrt_sw_spi_cs *cs = device->parent.user_data; if(message->cs_take) { rt_pin_write(cs->pin, PIN_LOW); } - transfer.dataSize = message->length; - transfer.rxData = (uint8_t *)(message->recv_buf); - transfer.txData = (uint8_t *)(message->send_buf); + transfer.dataSize = message->length; + transfer.rxData = (uint8_t *)(message->recv_buf); + transfer.txData = (uint8_t *)(message->send_buf); if(RT_FALSE == spi->dma_flag) { @@ -370,10 +370,10 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message * message->length = 0; } - return message->length; + return message->length; } -static struct rt_spi_ops imxrt_spi_ops = +static struct rt_spi_ops imxrt_spi_ops = { .configure = spi_configure, .xfer = spixfer @@ -405,8 +405,8 @@ int rt_hw_spi_bus_init(void) lpspis[i].xfer_sem = rt_sem_create(sem_name, 0, RT_IPC_FLAG_PRIO); } - return ret; + return ret; } -INIT_BOARD_EXPORT(rt_hw_spi_bus_init); +INIT_BOARD_EXPORT(rt_hw_spi_bus_init); #endif /* BSP_USING_SPI */ diff --git a/bsp/imxrt/libraries/drivers/drv_spi.h b/bsp/imxrt/libraries/drivers/drv_spi.h index 54f1744be0..4cd4c1a2bb 100644 --- a/bsp/imxrt/libraries/drivers/drv_spi.h +++ b/bsp/imxrt/libraries/drivers/drv_spi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -7,7 +7,7 @@ * Date Author Notes * 2018-03-27 Liuguang the first version. */ - + #ifndef DRV_SPI_H__ #define DRV_SPI_H__ diff --git a/bsp/imxrt/libraries/drivers/drv_uart.c b/bsp/imxrt/libraries/drivers/drv_uart.c index fd5bfd1719..0265ee215a 100644 --- a/bsp/imxrt/libraries/drivers/drv_uart.c +++ b/bsp/imxrt/libraries/drivers/drv_uart.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -461,7 +461,7 @@ void edma_rx_callback(struct _edma_handle *handle, void *userData, bool transfer recv_len = uart->serial.config.bufsz - uart->dma_rx->last_index; uart->dma_rx->last_index = 0; } - else + else { /* clear half interrupt */ EDMA_ClearChannelStatusFlags(DMA0, uart->dma_rx->channel,kEDMA_InterruptFlag); diff --git a/bsp/imxrt/libraries/drivers/usb/device/usb_device.h b/bsp/imxrt/libraries/drivers/usb/device/usb_device.h index 99e8a879f8..dc12f0249a 100644 --- a/bsp/imxrt/libraries/drivers/usb/device/usb_device.h +++ b/bsp/imxrt/libraries/drivers/usb/device/usb_device.h @@ -253,7 +253,7 @@ extern "C" { * @retval kStatus_USB_Busy Cannot allocate a device handle. * @retval kStatus_USB_ControllerNotFound Cannot find the controller according to the controller id. * @retval kStatus_USB_InvalidControllerInterface The controller driver interfaces is invalid. There is an empty - * interface entity. + * interface entity. * @retval kStatus_USB_Error The macro USB_DEVICE_CONFIG_ENDPOINTS is more than the IP's endpoint number. * Or, the device has been initialized. * Or, the mutex or message queue is created failed. @@ -501,8 +501,8 @@ extern usb_status_t USB_DeviceDcdInitModule(usb_device_handle handle, void *time * * @param[in] handle The device handle got from #USB_DeviceInit. * - * @retval kStatus_USB_Success The device is stopped successfully. - * @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer or the controller handle is invalid. + * @retval kStatus_USB_Success The device is stopped successfully. + * @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer or the controller handle is invalid. */ extern usb_status_t USB_DeviceDcdDeinitModule(usb_device_handle handle); #endif From 8803bf4018560a2c21fd66676adc240b69d0dd57 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 26 Jan 2022 15:09:29 +0800 Subject: [PATCH 65/65] Update RT_USING_DFS options and sync new USB host API. --- bsp/nuvoton/libraries/m2354/rtt_port/Kconfig | 1 + .../libraries/m2354/rtt_port/drv_sdh.c | 47 ++++++++++--------- .../libraries/m2354/rtt_port/drv_usbhost.c | 2 +- bsp/nuvoton/libraries/m480/rtt_port/Kconfig | 1 + bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c | 23 +++------ .../libraries/m480/rtt_port/drv_usbhost.c | 2 +- bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig | 1 + .../libraries/n9h30/rtt_port/drv_sdh.c | 24 +++------- .../libraries/n9h30/rtt_port/drv_usbhost.c | 8 ++-- bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig | 1 + .../libraries/nuc980/rtt_port/drv_sdh.c | 24 +++------- .../libraries/nuc980/rtt_port/drv_usbhost.c | 8 ++-- bsp/nuvoton/nk-980iot/applications/mnt.c | 14 +++--- bsp/nuvoton/nk-n9h30/applications/mnt.c | 14 +++--- bsp/nuvoton/nk-rtu980/applications/mnt.c | 14 +++--- .../numaker-iot-m487/applications/mnt.c | 14 +++--- bsp/nuvoton/numaker-m032ki/applications/mnt.c | 14 +++--- .../numaker-pfm-m487/applications/mnt.c | 14 +++--- 18 files changed, 92 insertions(+), 134 deletions(-) diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/Kconfig b/bsp/nuvoton/libraries/m2354/rtt_port/Kconfig index bf7d2da98d..5d06999d6b 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/m2354/rtt_port/Kconfig @@ -470,6 +470,7 @@ config SOC_SERIES_M2354 menuconfig BSP_USING_SDH bool "Enable Secure Digital Host Controller(SDH)" select RT_USING_DFS + select DFS_USING_POSIX if BSP_USING_SDH config BSP_USING_SDH0 diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c index 1ab43b4989..e71677a917 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_sdh.c @@ -19,14 +19,12 @@ #include #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include /* Private define ---------------------------------------------------------------*/ @@ -236,11 +234,13 @@ static rt_size_t nu_sdh_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_siz { rt_uint32_t ret = 0; nu_sdh_t sdh = (nu_sdh_t)dev; + rt_err_t result; RT_ASSERT(dev != RT_NULL); RT_ASSERT(buffer != RT_NULL); - rt_sem_take(&sdh->lock, RT_WAITING_FOREVER); + result = rt_sem_take(&sdh->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); /* Check alignment. */ if (((uint32_t)buffer & 0x03) != 0) @@ -281,7 +281,8 @@ exit_nu_sdh_read: sdh->pbuf = RT_NULL; } - rt_sem_release(&sdh->lock); + result = rt_sem_release(&sdh->lock); + RT_ASSERT(result == RT_EOK); if (ret == Successful) return blk_nb; @@ -295,11 +296,13 @@ static rt_size_t nu_sdh_write(rt_device_t dev, rt_off_t pos, const void *buffer, { rt_uint32_t ret = 0; nu_sdh_t sdh = (nu_sdh_t)dev; + rt_err_t result; RT_ASSERT(dev != RT_NULL); RT_ASSERT(buffer != RT_NULL); - rt_sem_take(&sdh->lock, RT_WAITING_FOREVER); + result = rt_sem_take(&sdh->lock, RT_WAITING_FOREVER); + RT_ASSERT(result == RT_EOK); /* Check alignment. */ if (((uint32_t)buffer & 0x03) != 0) @@ -338,7 +341,8 @@ exit_nu_sdh_write: sdh->pbuf = RT_NULL; } - rt_sem_release(&sdh->lock); + result = rt_sem_release(&sdh->lock); + RT_ASSERT(result == RT_EOK); if (ret == Successful) return blk_nb; @@ -393,7 +397,8 @@ static int rt_hw_sdh_init(void) /* Private */ nu_sdh_arr[i].dev.user_data = (void *)&nu_sdh_arr[i]; - rt_sem_init(&nu_sdh_arr[i].lock, "sdhlock", 1, RT_IPC_FLAG_FIFO); + ret = rt_sem_init(&nu_sdh_arr[i].lock, "sdhlock", 1, RT_IPC_FLAG_FIFO); + RT_ASSERT(ret == RT_EOK); SDH_Open(nu_sdh_arr[i].base, CardDetect_From_GPIO); @@ -402,6 +407,7 @@ static int rt_hw_sdh_init(void) NVIC_EnableIRQ(SDH0_IRQn); nu_sdh_arr[i].pbuf = RT_NULL; + ret = rt_device_register(&nu_sdh_arr[i].dev, nu_sdh_arr[i].name, flags); RT_ASSERT(ret == RT_EOK); } @@ -415,8 +421,6 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) { rt_bool_t ret = RT_FALSE; -#if defined(RT_USING_DFS) - struct dfs_filesystem *psFS = dfs_filesystem_lookup(mounting_path); if (psFS == RT_NULL) { @@ -431,8 +435,6 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) ret = RT_FALSE; } -#endif - exit_nu_sdh_hotplug_is_mounted: return ret; @@ -442,8 +444,6 @@ static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) rt_err_t ret = RT_ERROR; DIR *t; -#if defined(RT_USING_DFS) - if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_TRUE) { ret = RT_EOK; @@ -491,7 +491,6 @@ static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) exit_nu_sdh_hotplug_mount: -#endif return -(ret); } @@ -499,7 +498,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) { rt_err_t ret = RT_ERROR; -#if defined(RT_USING_DFS) if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_FALSE) { ret = RT_EOK; @@ -516,7 +514,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) rt_kprintf("Succeed to unmount %s.\n", sdh->mounted_point); ret = RT_EOK; } -#endif exit_nu_sdh_hotplug_unmount: @@ -585,7 +582,11 @@ static void sdh_hotplugger(void *param) int mnt_init_sdcard_hotplug(void) { - rt_thread_init(&sdh_tid, "hotplug", sdh_hotplugger, NULL, sdh_stack, sizeof(sdh_stack), RT_THREAD_PRIORITY_MAX - 2, 10); + rt_err_t result; + + result = rt_thread_init(&sdh_tid, "hotplug", sdh_hotplugger, NULL, sdh_stack, sizeof(sdh_stack), RT_THREAD_PRIORITY_MAX - 2, 10); + RT_ASSERT(result == RT_EOK); + rt_thread_startup(&sdh_tid); return 0; diff --git a/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c index fe5895dc9d..e54580d671 100644 --- a/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/m2354/rtt_port/drv_usbhost.c @@ -469,7 +469,7 @@ static void int_xfer_done_cb(UTR_T *psUTR) msg.type = USB_MSG_CALLBACK; msg.content.cb.function = pipe->callback; msg.content.cb.context = pipe; - rt_usbh_event_signal(&msg); + rt_usbh_event_signal(&s_sUSBHDev.uhcd, &msg); } exit_int_xfer_done_cb: diff --git a/bsp/nuvoton/libraries/m480/rtt_port/Kconfig b/bsp/nuvoton/libraries/m480/rtt_port/Kconfig index 22523e90b4..0d529462a3 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/m480/rtt_port/Kconfig @@ -447,6 +447,7 @@ config SOC_SERIES_M480 menuconfig BSP_USING_SDH bool "Enable Secure Digital Host Controller(SDH)" select RT_USING_DFS + select DFS_USING_POSIX if BSP_USING_SDH config BSP_USING_SDH0 diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c index 7fdd2c8876..a4f49958c4 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_sdh.c @@ -19,14 +19,12 @@ #include #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include /* Private define ---------------------------------------------------------------*/ @@ -457,8 +455,6 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) { rt_bool_t ret = RT_FALSE; -#if defined(RT_USING_DFS) - struct dfs_filesystem *psFS = dfs_filesystem_lookup(mounting_path); if (psFS == RT_NULL) { @@ -473,8 +469,6 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) ret = RT_FALSE; } -#endif - exit_nu_sdh_hotplug_is_mounted: return ret; @@ -484,8 +478,6 @@ static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) rt_err_t ret = RT_ERROR; DIR *t; -#if defined(RT_USING_DFS) - if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_TRUE) { ret = RT_EOK; @@ -533,7 +525,6 @@ static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) exit_nu_sdh_hotplug_mount: -#endif return -(ret); } @@ -541,7 +532,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) { rt_err_t ret = RT_ERROR; -#if defined(RT_USING_DFS) if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_FALSE) { ret = RT_EOK; @@ -558,7 +548,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) rt_kprintf("Succeed to unmount %s.\n", sdh->mounted_point); ret = RT_EOK; } -#endif exit_nu_sdh_hotplug_unmount: diff --git a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c index c30bba60c8..0df76a63ad 100644 --- a/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/m480/rtt_port/drv_usbhost.c @@ -472,7 +472,7 @@ static void int_xfer_done_cb(UTR_T *psUTR) msg.type = USB_MSG_CALLBACK; msg.content.cb.function = pipe->callback; msg.content.cb.context = pipe; - rt_usbh_event_signal(&msg); + rt_usbh_event_signal(&s_sUSBHDev.uhcd, &msg); } exit_int_xfer_done_cb: diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig index 4d863f6126..8d480dacf1 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig @@ -273,6 +273,7 @@ config SOC_SERIES_N9H30 menuconfig BSP_USING_SDH bool "Enable Secure Digital Host Controller(SDH)" select RT_USING_DFS + select DFS_USING_POSIX if BSP_USING_SDH diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c index 26c3a3a90e..2ead28d452 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_sdh.c @@ -19,14 +19,12 @@ #include "NuMicro.h" #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include /* Private define ---------------------------------------------------------------*/ @@ -602,8 +600,6 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) { rt_bool_t ret = RT_FALSE; -#if defined(RT_USING_DFS) - struct dfs_filesystem *psFS = dfs_filesystem_lookup(mounting_path); if (psFS == RT_NULL) { @@ -620,15 +616,11 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) exit_nu_sdh_hotplug_is_mounted: -#endif - return ret; } static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) { rt_err_t ret = RT_ERROR; - -#if defined(RT_USING_DFS) DIR *t; if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_TRUE) @@ -678,7 +670,6 @@ static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) exit_nu_sdh_hotplug_mount: -#endif return -(ret); } @@ -686,7 +677,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) { rt_err_t ret = RT_ERROR; -#if defined(RT_USING_DFS) if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_FALSE) { ret = RT_EOK; @@ -706,8 +696,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) exit_nu_sdh_hotplug_unmount: -#endif - return -(ret); } diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c index 85a1af96be..64e9dbf3ae 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_usbhost.c @@ -425,7 +425,7 @@ static int nu_bulk_xfer( UTR_T *psUTR, int timeouts) { - #define TIMEOUT_RETRY 3 +#define TIMEOUT_RETRY 3 int retry = TIMEOUT_RETRY; int ret = usbh_bulk_xfer(psUTR); @@ -435,9 +435,9 @@ static int nu_bulk_xfer( return ret; } - while ( retry > 0 ) + while (retry > 0) { - if ( rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0 ) + if (rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0) { rt_uint32_t level; @@ -513,7 +513,7 @@ static void int_xfer_done_cb(UTR_T *psUTR) msg.type = USB_MSG_CALLBACK; msg.content.cb.function = pipe->callback; msg.content.cb.context = pipe; - rt_usbh_event_signal(&msg); + rt_usbh_event_signal(&s_sUSBHDev.uhcd, &msg); } exit_int_xfer_done_cb: diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig index ffa3e55cc4..697685116c 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/Kconfig @@ -353,6 +353,7 @@ config SOC_SERIES_NUC980 menuconfig BSP_USING_SDH bool "Enable Secure Digital Host Controller(SDH)" select RT_USING_DFS + select DFS_USING_POSIX if BSP_USING_SDH config BSP_USING_SDH0 diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c index 6832db912b..bc3b23fd0d 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_sdh.c @@ -20,14 +20,12 @@ #include #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include /* Private define ---------------------------------------------------------------*/ @@ -458,8 +456,6 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) { rt_bool_t ret = RT_FALSE; -#if defined(RT_USING_DFS) - struct dfs_filesystem *psFS = dfs_filesystem_lookup(mounting_path); if (psFS == RT_NULL) { @@ -476,15 +472,11 @@ static rt_bool_t nu_sdh_hotplug_is_mounted(const char *mounting_path) exit_nu_sdh_hotplug_is_mounted: -#endif - return ret; } static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) { rt_err_t ret = RT_ERROR; - -#if defined(RT_USING_DFS) DIR *t; if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_TRUE) @@ -534,7 +526,6 @@ static rt_err_t nu_sdh_hotplug_mount(nu_sdh_t sdh) exit_nu_sdh_hotplug_mount: -#endif return -(ret); } @@ -542,7 +533,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) { rt_err_t ret = RT_ERROR; -#if defined(RT_USING_DFS) if (nu_sdh_hotplug_is_mounted(sdh->mounted_point) == RT_FALSE) { ret = RT_EOK; @@ -562,8 +552,6 @@ static rt_err_t nu_sdh_hotplug_unmount(nu_sdh_t sdh) exit_nu_sdh_hotplug_unmount: -#endif - return -(ret); } diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c index 85a1af96be..64e9dbf3ae 100644 --- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c +++ b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_usbhost.c @@ -425,7 +425,7 @@ static int nu_bulk_xfer( UTR_T *psUTR, int timeouts) { - #define TIMEOUT_RETRY 3 +#define TIMEOUT_RETRY 3 int retry = TIMEOUT_RETRY; int ret = usbh_bulk_xfer(psUTR); @@ -435,9 +435,9 @@ static int nu_bulk_xfer( return ret; } - while ( retry > 0 ) + while (retry > 0) { - if ( rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0 ) + if (rt_completion_wait(&(psPortDev->utr_completion), timeouts) != 0) { rt_uint32_t level; @@ -513,7 +513,7 @@ static void int_xfer_done_cb(UTR_T *psUTR) msg.type = USB_MSG_CALLBACK; msg.content.cb.function = pipe->callback; msg.content.cb.context = pipe; - rt_usbh_event_signal(&msg); + rt_usbh_event_signal(&s_sUSBHDev.uhcd, &msg); } exit_int_xfer_done_cb: diff --git a/bsp/nuvoton/nk-980iot/applications/mnt.c b/bsp/nuvoton/nk-980iot/applications/mnt.c index fc440ab8e4..07905a6b13 100644 --- a/bsp/nuvoton/nk-980iot/applications/mnt.c +++ b/bsp/nuvoton/nk-980iot/applications/mnt.c @@ -21,14 +21,12 @@ #define DBG_COLOR #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include #if defined(PKG_USING_FAL) #include diff --git a/bsp/nuvoton/nk-n9h30/applications/mnt.c b/bsp/nuvoton/nk-n9h30/applications/mnt.c index 05b29c2a24..9fdf7ec3a1 100644 --- a/bsp/nuvoton/nk-n9h30/applications/mnt.c +++ b/bsp/nuvoton/nk-n9h30/applications/mnt.c @@ -21,14 +21,12 @@ #define DBG_COLOR #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include #if defined(PKG_USING_FAL) #include diff --git a/bsp/nuvoton/nk-rtu980/applications/mnt.c b/bsp/nuvoton/nk-rtu980/applications/mnt.c index 266ea0ede0..1c834fcb3e 100644 --- a/bsp/nuvoton/nk-rtu980/applications/mnt.c +++ b/bsp/nuvoton/nk-rtu980/applications/mnt.c @@ -21,14 +21,12 @@ #define DBG_COLOR #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include #if defined(PKG_USING_FAL) #include diff --git a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c index 3bafda9b75..9abcd5de26 100644 --- a/bsp/nuvoton/numaker-iot-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-iot-m487/applications/mnt.c @@ -12,14 +12,12 @@ #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include #if defined(PKG_USING_FAL) #include diff --git a/bsp/nuvoton/numaker-m032ki/applications/mnt.c b/bsp/nuvoton/numaker-m032ki/applications/mnt.c index 62c470570c..7ac94f7f0f 100644 --- a/bsp/nuvoton/numaker-m032ki/applications/mnt.c +++ b/bsp/nuvoton/numaker-m032ki/applications/mnt.c @@ -12,14 +12,12 @@ #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include #if defined(PKG_USING_FAL) #include diff --git a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c index 398f292c43..0b4ed458b1 100644 --- a/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c +++ b/bsp/nuvoton/numaker-pfm-m487/applications/mnt.c @@ -12,14 +12,12 @@ #include -#if defined(RT_USING_DFS) - #include - #include - #include - #include - #include - #include -#endif +#include +#include +#include +#include +#include +#include #if defined(PKG_USING_FAL) #include

#Usnl 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

9>i*u@uoe7?}Vp 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

tw_EWIB&C= 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