diff --git a/doxygen/configuration.txt b/doxygen/configuration.txt
index 5816826d..da30786e 100644
--- a/doxygen/configuration.txt
+++ b/doxygen/configuration.txt
@@ -10,13 +10,13 @@
#define CFG_TUSB_RHPORT0_MODE
/** USB controller in MCU often has limited access to specific RAM section. The Stack will use this macro to place internal variables
- into the USB RAM section as follows. if your mcu's usb controller has no such limit, define CFG_TUSB_ATTR_USBRAM as empty macro.
+ into the USB RAM section as follows. if your mcu's usb controller has no such limit, define CFG_TUSB_MEM_SECTION as empty macro.
@code
- CFG_TUSB_ATTR_USBRAM uint8_t usb_xfer_buffer[10];
+ CFG_TUSB_MEM_SECTION uint8_t usb_xfer_buffer[10];
@endcode
*/
-#define CFG_TUSB_ATTR_USBRAM
+#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MCU ///< Select one of the supported MCU, the value must be from \ref group_mcu
#define CFG_TUSB_OS ///< Select one of the supported RTOS, the value must be from \ref group_supported_os.
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4300_Startup.s b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4300_Startup.s
new file mode 100644
index 00000000..3df2ad96
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4300_Startup.s
@@ -0,0 +1,126 @@
+/*****************************************************************************
+ * SEGGER Microcontroller GmbH & Co. KG *
+ * Solutions for real time microcontroller applications *
+ *****************************************************************************
+ * *
+ * (c) 2017 SEGGER Microcontroller GmbH & Co. KG *
+ * *
+ * Internet: www.segger.com Support: support@segger.com *
+ * *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preprocessor Definitions *
+ * ------------------------ *
+ * NO_FPU_ENABLE *
+ * *
+ * If defined, FPU will not be enabled. *
+ * *
+ * NO_STACK_INIT *
+ * *
+ * If defined, the stack pointer will not be initialised. *
+ * *
+ * NO_SYSTEM_INIT *
+ * *
+ * If defined, the SystemInit() function will not be called. By default *
+ * SystemInit() is called after reset to enable the clocks and memories to *
+ * be initialised prior to any C startup initialisation. *
+ * *
+ * NO_VTOR_CONFIG *
+ * *
+ * If defined, the vector table offset register will not be configured. *
+ * *
+ * MEMORY_INIT *
+ * *
+ * If defined, the MemoryInit() function will be called. By default *
+ * MemoryInit() is called after SystemInit() to enable an external memory *
+ * controller. *
+ * *
+ * STACK_INIT_VAL *
+ * *
+ * If defined, specifies the initial stack pointer value. If undefined, *
+ * the stack pointer will be initialised to point to the end of the *
+ * RAM segment. *
+ * *
+ * VECTORS_IN_RAM *
+ * *
+ * If defined, the exception vectors will be copied from Flash to RAM. *
+ * *
+ *****************************************************************************/
+
+ .syntax unified
+
+ .global Reset_Handler
+ .extern _vectors
+
+ .section .init, "ax"
+ .thumb_func
+
+ .equ VTOR_REG, 0xE000ED08
+ .equ FPU_CPACR_REG, 0xE000ED88
+
+#ifndef STACK_INIT_VAL
+#define STACK_INIT_VAL __RAM_segment_end__
+#endif
+
+Reset_Handler:
+#ifndef NO_STACK_INIT
+ /* Initialise main stack */
+ ldr r0, =STACK_INIT_VAL
+ ldr r1, =0x7
+ bics r0, r1
+ mov sp, r0
+#endif
+
+#ifndef NO_SYSTEM_INIT
+ /* Initialise system */
+ ldr r0, =SystemInit
+ blx r0
+#endif
+
+#ifdef MEMORY_INIT
+ ldr r0, =MemoryInit
+ blx r0
+#endif
+
+#ifdef VECTORS_IN_RAM
+ /* Copy exception vectors into RAM */
+ ldr r0, =__vectors_start__
+ ldr r1, =__vectors_end__
+ ldr r2, =__vectors_ram_start__
+1:
+ cmp r0, r1
+ beq 2f
+ ldr r3, [r0]
+ str r3, [r2]
+ adds r0, r0, #4
+ adds r2, r2, #4
+ b 1b
+2:
+#endif
+
+#ifndef NO_VTOR_CONFIG
+ /* Configure vector table offset register */
+ ldr r0, =VTOR_REG
+#ifdef VECTORS_IN_RAM
+ ldr r1, =_vectors_ram
+#else
+ ldr r1, =_vectors
+#endif
+ str r1, [r0]
+#endif
+
+#if (defined(__ARM_ARCH_FPV4_SP_D16__) || defined(__ARM_ARCH_FPV5_D16__)) && !defined(NO_FPU_ENABLE)
+ /* Enable FPU */
+ ldr r0, =FPU_CPACR_REG
+ ldr r1, [r0]
+ orr r1, r1, #(0xF << 20)
+ str r1, [r0]
+ dsb
+ isb
+#endif
+
+ /* Jump to program start */
+ b _start
+
+
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4300_Target.js b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4300_Target.js
new file mode 100644
index 00000000..20560af4
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4300_Target.js
@@ -0,0 +1,19 @@
+/*****************************************************************************
+ * SEGGER Microcontroller GmbH & Co. KG *
+ * Solutions for real time microcontroller applications *
+ *****************************************************************************
+ * *
+ * (c) 2017 SEGGER Microcontroller GmbH & Co. KG *
+ * *
+ * Internet: www.segger.com Support: support@segger.com *
+ * *
+ *****************************************************************************/
+
+function Reset() {
+ TargetInterface.resetAndStop();
+}
+
+function EnableTrace(traceInterfaceType) {
+ // TODO: Enable trace
+}
+
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4357 Cortex-M4_MemoryMap.xml b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4357 Cortex-M4_MemoryMap.xml
new file mode 100644
index 00000000..eb42b7bf
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC4357 Cortex-M4_MemoryMap.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/LPC43xx_Registers.xml b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC43xx_Registers.xml
new file mode 100644
index 00000000..9c094646
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC43xx_Registers.xml
@@ -0,0 +1,33526 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/LPC43xx_Vectors.s b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC43xx_Vectors.s
new file mode 100644
index 00000000..ab223b8a
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/LPC43xx_Vectors.s
@@ -0,0 +1,540 @@
+/*****************************************************************************
+ * SEGGER Microcontroller GmbH & Co. KG *
+ * Solutions for real time microcontroller applications *
+ *****************************************************************************
+ * *
+ * (c) 2017 SEGGER Microcontroller GmbH & Co. KG *
+ * *
+ * Internet: www.segger.com Support: support@segger.com *
+ * *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preprocessor Definitions *
+ * ------------------------ *
+ * VECTORS_IN_RAM *
+ * *
+ * If defined, an area of RAM will large enough to store the vector table *
+ * will be reserved. *
+ * *
+ *****************************************************************************/
+
+ .syntax unified
+ .code 16
+
+ .section .init, "ax"
+ .align 0
+
+/*****************************************************************************
+ * Default Exception Handlers *
+ *****************************************************************************/
+
+ .thumb_func
+ .weak NMI_Handler
+NMI_Handler:
+ b .
+
+ .thumb_func
+ .weak HardFault_Handler
+HardFault_Handler:
+ b .
+
+ .thumb_func
+ .weak SVC_Handler
+SVC_Handler:
+ b .
+
+ .thumb_func
+ .weak PendSV_Handler
+PendSV_Handler:
+ b .
+
+ .thumb_func
+ .weak SysTick_Handler
+SysTick_Handler:
+ b .
+
+ .thumb_func
+Dummy_Handler:
+ b .
+
+#if defined(__OPTIMIZATION_SMALL)
+
+ .weak DAC_IRQHandler
+ .thumb_set DAC_IRQHandler,Dummy_Handler
+
+ .weak DMA_IRQHandler
+ .thumb_set DMA_IRQHandler,Dummy_Handler
+
+ .weak FLASH_IRQHandler
+ .thumb_set FLASH_IRQHandler,Dummy_Handler
+
+ .weak ETHERNET_IRQHandler
+ .thumb_set ETHERNET_IRQHandler,Dummy_Handler
+
+ .weak SDIO_IRQHandler
+ .thumb_set SDIO_IRQHandler,Dummy_Handler
+
+ .weak LCD_IRQHandler
+ .thumb_set LCD_IRQHandler,Dummy_Handler
+
+ .weak USB0_IRQHandler
+ .thumb_set USB0_IRQHandler,Dummy_Handler
+
+ .weak USB1_IRQHandler
+ .thumb_set USB1_IRQHandler,Dummy_Handler
+
+ .weak SCT_IRQHandler
+ .thumb_set SCT_IRQHandler,Dummy_Handler
+
+ .weak RITIMER_IRQHandler
+ .thumb_set RITIMER_IRQHandler,Dummy_Handler
+
+ .weak TIMER0_IRQHandler
+ .thumb_set TIMER0_IRQHandler,Dummy_Handler
+
+ .weak TIMER1_IRQHandler
+ .thumb_set TIMER1_IRQHandler,Dummy_Handler
+
+ .weak TIMER2_IRQHandler
+ .thumb_set TIMER2_IRQHandler,Dummy_Handler
+
+ .weak TIMER3_IRQHandler
+ .thumb_set TIMER3_IRQHandler,Dummy_Handler
+
+ .weak MCPWM_IRQHandler
+ .thumb_set MCPWM_IRQHandler,Dummy_Handler
+
+ .weak ADC0_IRQHandler
+ .thumb_set ADC0_IRQHandler,Dummy_Handler
+
+ .weak I2C0_IRQHandler
+ .thumb_set I2C0_IRQHandler,Dummy_Handler
+
+ .weak I2C1_IRQHandler
+ .thumb_set I2C1_IRQHandler,Dummy_Handler
+
+ .weak SPI_INT_IRQHandler
+ .thumb_set SPI_INT_IRQHandler,Dummy_Handler
+
+ .weak ADC1_IRQHandler
+ .thumb_set ADC1_IRQHandler,Dummy_Handler
+
+ .weak SSP0_IRQHandler
+ .thumb_set SSP0_IRQHandler,Dummy_Handler
+
+ .weak SSP1_IRQHandler
+ .thumb_set SSP1_IRQHandler,Dummy_Handler
+
+ .weak USART0_IRQHandler
+ .thumb_set USART0_IRQHandler,Dummy_Handler
+
+ .weak UART1_IRQHandler
+ .thumb_set UART1_IRQHandler,Dummy_Handler
+
+ .weak USART2_IRQHandler
+ .thumb_set USART2_IRQHandler,Dummy_Handler
+
+ .weak USART3_IRQHandler
+ .thumb_set USART3_IRQHandler,Dummy_Handler
+
+ .weak I2S0_IRQHandler
+ .thumb_set I2S0_IRQHandler,Dummy_Handler
+
+ .weak I2S1_IRQHandler
+ .thumb_set I2S1_IRQHandler,Dummy_Handler
+
+ .weak SPIFI_IRQHandler
+ .thumb_set SPIFI_IRQHandler,Dummy_Handler
+
+ .weak SGPIO_IINT_IRQHandler
+ .thumb_set SGPIO_IINT_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT0_IRQHandler
+ .thumb_set PIN_INT0_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT1_IRQHandler
+ .thumb_set PIN_INT1_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT2_IRQHandler
+ .thumb_set PIN_INT2_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT3_IRQHandler
+ .thumb_set PIN_INT3_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT4_IRQHandler
+ .thumb_set PIN_INT4_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT5_IRQHandler
+ .thumb_set PIN_INT5_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT6_IRQHandler
+ .thumb_set PIN_INT6_IRQHandler,Dummy_Handler
+
+ .weak PIN_INT7_IRQHandler
+ .thumb_set PIN_INT7_IRQHandler,Dummy_Handler
+
+ .weak GINT0_IRQHandler
+ .thumb_set GINT0_IRQHandler,Dummy_Handler
+
+ .weak GINT1_IRQHandler
+ .thumb_set GINT1_IRQHandler,Dummy_Handler
+
+ .weak EVENTROUTER_IRQHandler
+ .thumb_set EVENTROUTER_IRQHandler,Dummy_Handler
+
+ .weak C_CAN1_IRQHandler
+ .thumb_set C_CAN1_IRQHandler,Dummy_Handler
+
+ .weak ADCHS_IRQHandler
+ .thumb_set ADCHS_IRQHandler,Dummy_Handler
+
+ .weak ATIMER_IRQHandler
+ .thumb_set ATIMER_IRQHandler,Dummy_Handler
+
+ .weak RTC_IRQHandler
+ .thumb_set RTC_IRQHandler,Dummy_Handler
+
+ .weak WWDT_IRQHandler
+ .thumb_set WWDT_IRQHandler,Dummy_Handler
+
+ .weak C_CAN0_IRQHandler
+ .thumb_set C_CAN0_IRQHandler,Dummy_Handler
+
+ .weak QEI_IRQHandler
+ .thumb_set QEI_IRQHandler,Dummy_Handler
+
+#else
+
+ .thumb_func
+ .weak DAC_IRQHandler
+DAC_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak DMA_IRQHandler
+DMA_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak FLASH_IRQHandler
+FLASH_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak ETHERNET_IRQHandler
+ETHERNET_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SDIO_IRQHandler
+SDIO_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak LCD_IRQHandler
+LCD_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak USB0_IRQHandler
+USB0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak USB1_IRQHandler
+USB1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SCT_IRQHandler
+SCT_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak RITIMER_IRQHandler
+RITIMER_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak TIMER0_IRQHandler
+TIMER0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak TIMER1_IRQHandler
+TIMER1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak TIMER2_IRQHandler
+TIMER2_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak TIMER3_IRQHandler
+TIMER3_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak MCPWM_IRQHandler
+MCPWM_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak ADC0_IRQHandler
+ADC0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak I2C0_IRQHandler
+I2C0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak I2C1_IRQHandler
+I2C1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SPI_INT_IRQHandler
+SPI_INT_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak ADC1_IRQHandler
+ADC1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SSP0_IRQHandler
+SSP0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SSP1_IRQHandler
+SSP1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak USART0_IRQHandler
+USART0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak UART1_IRQHandler
+UART1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak USART2_IRQHandler
+USART2_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak USART3_IRQHandler
+USART3_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak I2S0_IRQHandler
+I2S0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak I2S1_IRQHandler
+I2S1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SPIFI_IRQHandler
+SPIFI_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak SGPIO_IINT_IRQHandler
+SGPIO_IINT_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT0_IRQHandler
+PIN_INT0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT1_IRQHandler
+PIN_INT1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT2_IRQHandler
+PIN_INT2_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT3_IRQHandler
+PIN_INT3_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT4_IRQHandler
+PIN_INT4_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT5_IRQHandler
+PIN_INT5_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT6_IRQHandler
+PIN_INT6_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak PIN_INT7_IRQHandler
+PIN_INT7_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak GINT0_IRQHandler
+GINT0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak GINT1_IRQHandler
+GINT1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak EVENTROUTER_IRQHandler
+EVENTROUTER_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak C_CAN1_IRQHandler
+C_CAN1_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak ADCHS_IRQHandler
+ADCHS_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak ATIMER_IRQHandler
+ATIMER_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak RTC_IRQHandler
+RTC_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak WWDT_IRQHandler
+WWDT_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak C_CAN0_IRQHandler
+C_CAN0_IRQHandler:
+ b .
+
+ .thumb_func
+ .weak QEI_IRQHandler
+QEI_IRQHandler:
+ b .
+
+#endif
+
+/*****************************************************************************
+ * Vector Table *
+ *****************************************************************************/
+
+ .section .vectors, "ax"
+ .align 0
+ .global _vectors
+ .extern __stack_end__
+ .extern Reset_Handler
+
+_vectors:
+ .word __stack_end__
+ .word Reset_Handler
+ .word NMI_Handler
+ .word HardFault_Handler
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word SVC_Handler
+ .word 0 /* Reserved */
+ .word 0 /* Reserved */
+ .word PendSV_Handler
+ .word SysTick_Handler
+ .word DAC_IRQHandler
+ .word Dummy_Handler /* Reserved */
+ .word DMA_IRQHandler
+ .word Dummy_Handler /* Reserved */
+ .word FLASH_IRQHandler
+ .word ETHERNET_IRQHandler
+ .word SDIO_IRQHandler
+ .word LCD_IRQHandler
+ .word USB0_IRQHandler
+ .word USB1_IRQHandler
+ .word SCT_IRQHandler
+ .word RITIMER_IRQHandler
+ .word TIMER0_IRQHandler
+ .word TIMER1_IRQHandler
+ .word TIMER2_IRQHandler
+ .word TIMER3_IRQHandler
+ .word MCPWM_IRQHandler
+ .word ADC0_IRQHandler
+ .word I2C0_IRQHandler
+ .word I2C1_IRQHandler
+ .word SPI_INT_IRQHandler
+ .word ADC1_IRQHandler
+ .word SSP0_IRQHandler
+ .word SSP1_IRQHandler
+ .word USART0_IRQHandler
+ .word UART1_IRQHandler
+ .word USART2_IRQHandler
+ .word USART3_IRQHandler
+ .word I2S0_IRQHandler
+ .word I2S1_IRQHandler
+ .word SPIFI_IRQHandler
+ .word SGPIO_IINT_IRQHandler
+ .word PIN_INT0_IRQHandler
+ .word PIN_INT1_IRQHandler
+ .word PIN_INT2_IRQHandler
+ .word PIN_INT3_IRQHandler
+ .word PIN_INT4_IRQHandler
+ .word PIN_INT5_IRQHandler
+ .word PIN_INT6_IRQHandler
+ .word PIN_INT7_IRQHandler
+ .word GINT0_IRQHandler
+ .word GINT1_IRQHandler
+ .word EVENTROUTER_IRQHandler
+ .word C_CAN1_IRQHandler
+ .word Dummy_Handler /* Reserved */
+ .word ADCHS_IRQHandler
+ .word ATIMER_IRQHandler
+ .word RTC_IRQHandler
+ .word Dummy_Handler /* Reserved */
+ .word WWDT_IRQHandler
+ .word Dummy_Handler /* Reserved */
+ .word C_CAN0_IRQHandler
+ .word QEI_IRQHandler
+_vectors_end:
+
+#ifdef VECTORS_IN_RAM
+ .section .vectors_ram, "ax"
+ .align 0
+ .global _vectors_ram
+
+_vectors_ram:
+ .space _vectors_end - _vectors, 0
+#endif
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/flash_placement.xml b/examples/device/cdc_msc_hid/ses/lpc43xx/flash_placement.xml
new file mode 100644
index 00000000..79bedc53
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/flash_placement.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject b/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject
new file mode 100644
index 00000000..363fae3e
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/lpc43xx.emProject
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/device/cdc_msc_hid/ses/lpc43xx/thumb_crt0.s b/examples/device/cdc_msc_hid/ses/lpc43xx/thumb_crt0.s
new file mode 100644
index 00000000..17f88e0c
--- /dev/null
+++ b/examples/device/cdc_msc_hid/ses/lpc43xx/thumb_crt0.s
@@ -0,0 +1,415 @@
+// **********************************************************************
+// * SEGGER Microcontroller GmbH *
+// * The Embedded Experts *
+// **********************************************************************
+// * *
+// * (c) 2014 - 2018 SEGGER Microcontroller GmbH *
+// * (c) 2001 - 2018 Rowley Associates Limited *
+// * *
+// * www.segger.com Support: support@segger.com *
+// * *
+// **********************************************************************
+// * *
+// * 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. *
+// * *
+// * - Neither the name of SEGGER Microcontroller GmbH *
+// * 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 SEGGER Microcontroller GmbH 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. *
+// * *
+// **********************************************************************
+//
+//
+// Preprocessor Definitions
+// ------------------------
+// APP_ENTRY_POINT
+//
+// Defines the application entry point function, if undefined this setting
+// defaults to "main".
+//
+// INITIALIZE_STACK
+//
+// If defined, the contents of the stack will be initialized to a the
+// value 0xCC.
+//
+// INITIALIZE_SECONDARY_SECTIONS
+//
+// If defined, the .data2, .text2, .rodata2 and .bss2 sections will be initialized.
+//
+// INITIALIZE_TCM_SECTIONS
+//
+// If defined, the .data_tcm, .text_tcm, .rodata_tcm and .bss_tcm sections
+// will be initialized.
+//
+// INITIALIZE_USER_SECTIONS
+//
+// If defined, the function InitializeUserMemorySections will be called prior
+// to entering main in order to allow the user to initialize any user defined
+// memory sections.
+//
+// FULL_LIBRARY
+//
+// If defined then
+// - argc, argv are setup by the debug_getargs.
+// - the exit symbol is defined and executes on return from main.
+// - the exit symbol calls destructors, atexit functions and then debug_exit.
+//
+// If not defined then
+// - argc and argv are zero.
+// - the exit symbol is defined, executes on return from main and loops
+//
+
+#ifndef APP_ENTRY_POINT
+#define APP_ENTRY_POINT main
+#endif
+
+#ifndef ARGSSPACE
+#define ARGSSPACE 128
+#endif
+ .syntax unified
+
+ .global _start
+ .extern APP_ENTRY_POINT
+ .global exit
+ .weak exit
+
+#ifdef INITIALIZE_USER_SECTIONS
+ .extern InitializeUserMemorySections
+#endif
+
+ .section .init, "ax"
+ .code 16
+ .balign 2
+ .thumb_func
+
+_start:
+ /* Set up main stack if size > 0 */
+ ldr r1, =__stack_end__
+ ldr r0, =__stack_start__
+ subs r2, r1, r0
+ beq 1f
+#ifdef __ARM_EABI__
+ movs r2, #0x7
+ bics r1, r2
+#endif
+ mov sp, r1
+#ifdef INITIALIZE_STACK
+ movs r2, #0xCC
+ ldr r0, =__stack_start__
+ bl memory_set
+#endif
+1:
+
+ /* Set up process stack if size > 0 */
+ ldr r1, =__stack_process_end__
+ ldr r0, =__stack_process_start__
+ subs r2, r1, r0
+ beq 1f
+#ifdef __ARM_EABI__
+ movs r2, #0x7
+ bics r1, r2
+#endif
+ msr psp, r1
+ movs r2, #2
+ msr control, r2
+#ifdef INITIALIZE_STACK
+ movs r2, #0xCC
+ bl memory_set
+#endif
+1:
+
+ /* Copy initialized memory sections into RAM (if necessary). */
+ ldr r0, =__data_load_start__
+ ldr r1, =__data_start__
+ ldr r2, =__data_end__
+ bl memory_copy
+ ldr r0, =__text_load_start__
+ ldr r1, =__text_start__
+ ldr r2, =__text_end__
+ bl memory_copy
+ ldr r0, =__fast_load_start__
+ ldr r1, =__fast_start__
+ ldr r2, =__fast_end__
+ bl memory_copy
+ ldr r0, =__ctors_load_start__
+ ldr r1, =__ctors_start__
+ ldr r2, =__ctors_end__
+ bl memory_copy
+ ldr r0, =__dtors_load_start__
+ ldr r1, =__dtors_start__
+ ldr r2, =__dtors_end__
+ bl memory_copy
+ ldr r0, =__rodata_load_start__
+ ldr r1, =__rodata_start__
+ ldr r2, =__rodata_end__
+ bl memory_copy
+ ldr r0, =__tdata_load_start__
+ ldr r1, =__tdata_start__
+ ldr r2, =__tdata_end__
+ bl memory_copy
+#ifdef INITIALIZE_SECONDARY_SECTIONS
+ ldr r0, =__data2_load_start__
+ ldr r1, =__data2_start__
+ ldr r2, =__data2_end__
+ bl memory_copy
+ ldr r0, =__text2_load_start__
+ ldr r1, =__text2_start__
+ ldr r2, =__text2_end__
+ bl memory_copy
+ ldr r0, =__rodata2_load_start__
+ ldr r1, =__rodata2_start__
+ ldr r2, =__rodata2_end__
+ bl memory_copy
+#endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */
+#ifdef INITIALIZE_TCM_SECTIONS
+ ldr r0, =__data_tcm_load_start__
+ ldr r1, =__data_tcm_start__
+ ldr r2, =__data_tcm_end__
+ bl memory_copy
+ ldr r0, =__text_tcm_load_start__
+ ldr r1, =__text_tcm_start__
+ ldr r2, =__text_tcm_end__
+ bl memory_copy
+ ldr r0, =__rodata_tcm_load_start__
+ ldr r1, =__rodata_tcm_start__
+ ldr r2, =__rodata_tcm_end__
+ bl memory_copy
+#endif /* #ifdef INITIALIZE_TCM_SECTIONS */
+
+ /* Zero the bss. */
+ ldr r0, =__bss_start__
+ ldr r1, =__bss_end__
+ movs r2, #0
+ bl memory_set
+ ldr r0, =__tbss_start__
+ ldr r1, =__tbss_end__
+ movs r2, #0
+ bl memory_set
+#ifdef INITIALIZE_SECONDARY_SECTIONS
+ ldr r0, =__bss2_start__
+ ldr r1, =__bss2_end__
+ mov r2, #0
+ bl memory_set
+#endif /* #ifdef INITIALIZE_SECONDARY_SECTIONS */
+#ifdef INITIALIZE_TCM_SECTIONS
+ ldr r0, =__bss_tcm_start__
+ ldr r1, =__bss_tcm_end__
+ mov r2, #0
+ bl memory_set
+#endif /* #ifdef INITIALIZE_TCM_SECTIONS */
+
+ /* Initialize the heap */
+ ldr r0, = __heap_start__
+ ldr r1, = __heap_end__
+ subs r1, r1, r0
+ cmp r1, #8
+ blt 1f
+ movs r2, #0
+ str r2, [r0]
+ adds r0, r0, #4
+ str r1, [r0]
+1:
+
+#ifdef INITIALIZE_USER_SECTIONS
+ ldr r2, =InitializeUserMemorySections
+ blx r2
+#endif
+
+ /* Call constructors */
+ ldr r0, =__ctors_start__
+ ldr r1, =__ctors_end__
+ctor_loop:
+ cmp r0, r1
+ beq ctor_end
+ ldr r2, [r0]
+ adds r0, #4
+ push {r0-r1}
+ blx r2
+ pop {r0-r1}
+ b ctor_loop
+ctor_end:
+
+ /* Setup initial call frame */
+ movs r0, #0
+ mov lr, r0
+ mov r12, sp
+
+ .type start, function
+start:
+ /* Jump to application entry point */
+#ifdef FULL_LIBRARY
+ movs r0, #ARGSSPACE
+ ldr r1, =args
+ ldr r2, =debug_getargs
+ blx r2
+ ldr r1, =args
+#else
+ movs r0, #0
+ movs r1, #0
+#endif
+ ldr r2, =APP_ENTRY_POINT
+ blx r2
+
+ .thumb_func
+exit:
+#ifdef FULL_LIBRARY
+ mov r5, r0 // save the exit parameter/return result
+
+ /* Call destructors */
+ ldr r0, =__dtors_start__
+ ldr r1, =__dtors_end__
+dtor_loop:
+ cmp r0, r1
+ beq dtor_end
+ ldr r2, [r0]
+ add r0, #4
+ push {r0-r1}
+ blx r2
+ pop {r0-r1}
+ b dtor_loop
+dtor_end:
+
+ /* Call atexit functions */
+ ldr r2, =_execute_at_exit_fns
+ blx r2
+
+ /* Call debug_exit with return result/exit parameter */
+ mov r0, r5
+ ldr r2, =debug_exit
+ blx r2
+#endif
+
+ /* Returned from application entry point, loop forever. */
+exit_loop:
+ b exit_loop
+
+ .thumb_func
+memory_copy:
+ cmp r0, r1
+ beq 2f
+ subs r2, r2, r1
+ beq 2f
+1:
+ ldrb r3, [r0]
+ adds r0, r0, #1
+ strb r3, [r1]
+ adds r1, r1, #1
+ subs r2, r2, #1
+ bne 1b
+2:
+ bx lr
+
+ .thumb_func
+memory_set:
+ cmp r0, r1
+ beq 1f
+ strb r2, [r0]
+ adds r0, r0, #1
+ b memory_set
+1:
+ bx lr
+
+ // default C/C++ library helpers
+
+.macro HELPER helper_name
+ .section .text.\helper_name, "ax", %progbits
+ .balign 2
+ .global \helper_name
+ .weak \helper_name
+\helper_name:
+ .thumb_func
+.endm
+
+.macro JUMPTO name
+#if defined(__thumb__) && !defined(__thumb2__)
+ mov r12, r0
+ ldr r0, =\name
+ push {r0}
+ mov r0, r12
+ pop {pc}
+#else
+ b \name
+#endif
+.endm
+
+HELPER __aeabi_read_tp
+ ldr r0, =__tbss_start__-8
+ bx lr
+HELPER abort
+ b .
+HELPER __assert
+ b .
+HELPER __aeabi_assert
+ b .
+HELPER __sync_synchronize
+ bx lr
+HELPER __getchar
+ JUMPTO debug_getchar
+HELPER __putchar
+ JUMPTO debug_putchar
+HELPER __open
+ JUMPTO debug_fopen
+HELPER __close
+ JUMPTO debug_fclose
+HELPER __write
+ mov r3, r0
+ mov r0, r1
+ movs r1, #1
+ JUMPTO debug_fwrite
+HELPER __read
+ mov r3, r0
+ mov r0, r1
+ movs r1, #1
+ JUMPTO debug_fread
+HELPER __seek
+ push {r4, lr}
+ mov r4, r0
+ bl debug_fseek
+ cmp r0, #0
+ bne 1f
+ mov r0, r4
+ bl debug_ftell
+ pop {r4, pc}
+1:
+ ldr r0, =-1
+ pop {r4, pc}
+ // char __user_locale_name_buffer[];
+ .section .bss.__user_locale_name_buffer, "aw", %nobits
+ .global __user_locale_name_buffer
+ .weak __user_locale_name_buffer
+ __user_locale_name_buffer:
+ .word 0x0
+
+#ifdef FULL_LIBRARY
+ .bss
+args:
+ .space ARGSSPACE
+#endif
+
+ /* Setup attibutes of stack and heap sections so they don't take up room in the elf file */
+ .section .stack, "wa", %nobits
+ .section .stack_process, "wa", %nobits
+ .section .heap, "wa", %nobits
+
diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h
index 29ed8a8e..9bc97ecf 100644
--- a/examples/device/cdc_msc_hid/src/tusb_config.h
+++ b/examples/device/cdc_msc_hid/src/tusb_config.h
@@ -58,10 +58,24 @@
#define CFG_TUSB_DEBUG 2
#define CFG_TUSB_OS OPT_OS_NONE
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_SECTION
+#endif
+
+#ifndef CFG_TUSB_MEM_ALIGN
+#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
+#endif
+
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------
-
#define CFG_TUD_ENDOINT0_SIZE 64
/*------------- Descriptors -------------*/
@@ -132,12 +146,6 @@
*/
#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1
-//--------------------------------------------------------------------
-// USB RAM PLACEMENT
-//--------------------------------------------------------------------
-#define CFG_TUSB_ATTR_USBRAM
-#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
-
#ifdef __cplusplus
}
diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h
index a8068033..777930ba 100644
--- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h
+++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h
@@ -140,7 +140,7 @@
//--------------------------------------------------------------------
// USB RAM PLACEMENT
//--------------------------------------------------------------------
-#define CFG_TUSB_ATTR_USBRAM
+#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
diff --git a/examples/device/device_virtual_com/src/tusb_config.h b/examples/device/device_virtual_com/src/tusb_config.h
index f7cde784..fd3f41b0 100644
--- a/examples/device/device_virtual_com/src/tusb_config.h
+++ b/examples/device/device_virtual_com/src/tusb_config.h
@@ -93,36 +93,36 @@
#ifdef __CODE_RED // compiled with lpcxpresso
#if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM2) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM2) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
#elif CFG_TUSB_MCU == OPT_MCU_LPC175X_6X
- #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all
+ #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM3)
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM3)
#endif
#elif defined __CC_ARM // Compiled with Keil armcc, USBRAM_SECTION is defined in scatter files
#if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(USBRAM_SECTION) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(USBRAM_SECTION) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
#elif (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
- #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all address
+ #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM // Use keil tool configure to have AHB SRAM as default memory
+ #define CFG_TUSB_MEM_SECTION // Use keil tool configure to have AHB SRAM as default memory
#endif
#elif defined __ICCARM__ // compiled with IAR
#if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
- #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\"USB_PACKET_MEMORY\"") ATTR_ALIGNED(64)
+ #define CFG_TUSB_MEM_SECTION _Pragma("location=\"USB_PACKET_MEMORY\"") ATTR_ALIGNED(64)
#elif (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
- #define CFG_TUSB_ATTR_USBRAM
+ #define CFG_TUSB_MEM_SECTION
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\".ahb_sram1\"")
+ #define CFG_TUSB_MEM_SECTION _Pragma("location=\".ahb_sram1\"")
#endif
#elif defined __SES_ARM
-#define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.bss2)
+#define CFG_TUSB_MEM_SECTION ATTR_SECTION(.bss2)
#else
diff --git a/examples/device/device_virtual_com/xpresso/.cproject b/examples/device/device_virtual_com/xpresso/.cproject
index a9c1f03f..1e76a688 100644
--- a/examples/device/device_virtual_com/xpresso/.cproject
+++ b/examples/device/device_virtual_com/xpresso/.cproject
@@ -80,6 +80,9 @@
+
+
+
@@ -87,15 +90,6 @@
-
-
-
-
-
-
-
-
-
@@ -114,7 +108,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<TargetConfig>
-<Properties property_0="None" property_2="LPC18x7_43x7_2x512_BootA.cfx" property_3="NXP" property_4="LPC4357" property_count="5" version="70200"/>
+<Properties property_0="None" property_2="LPC18x7_43x7_2x512_BootA.cfx" property_3="NXP" property_4="LPC4357" property_count="5" version="100200"/>
<infoList vendor="NXP"><info chip="LPC4357" flash_driver="LPC18x7_43x7_2x512_BootA.cfx" match_id="0x0" name="LPC4357" resetscript="LPC18LPC43InternalFLASHBootResetscript.scp" stub="crt_emu_lpc18_43_nxp"><chip><name>LPC4357</name>
<family>LPC43xx</family>
<vendor>NXP (formerly Philips)</vendor>
diff --git a/examples/obsolete/device/src/keyboard_device_app.c b/examples/obsolete/device/src/keyboard_device_app.c
index 4bb25b9c..5e14c56c 100644
--- a/examples/obsolete/device/src/keyboard_device_app.c
+++ b/examples/obsolete/device/src/keyboard_device_app.c
@@ -51,7 +51,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM hid_keyboard_report_t keyboard_report;
+CFG_TUSB_MEM_SECTION hid_keyboard_report_t keyboard_report;
//--------------------------------------------------------------------+
// tinyusb callbacks
@@ -66,13 +66,13 @@ void keyboard_app_umount(uint8_t rhport)
}
-void tud_hid_keyboard_cb(uint8_t rhport, tusb_event_t event, uint32_t xferred_bytes)
+void tud_hid_keyboard_cb(uint8_t rhport, xfer_result_t event, uint32_t xferred_bytes)
{
switch(event)
{
- case TUSB_EVENT_XFER_COMPLETE:
- case TUSB_EVENT_XFER_ERROR:
- case TUSB_EVENT_XFER_STALLED:
+ case XFER_RESULT_SUCCESS:
+ case XFER_RESULT_FAILED:
+ case XFER_RESULT_STALLED:
default: break;
}
}
diff --git a/examples/obsolete/device/src/mouse_device_app.c b/examples/obsolete/device/src/mouse_device_app.c
index 077cecc7..6869f1a0 100644
--- a/examples/obsolete/device/src/mouse_device_app.c
+++ b/examples/obsolete/device/src/mouse_device_app.c
@@ -51,7 +51,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM hid_mouse_report_t mouse_report;
+CFG_TUSB_MEM_SECTION hid_mouse_report_t mouse_report;
//--------------------------------------------------------------------+
// tinyusb callbacks
@@ -66,13 +66,13 @@ void mouse_app_umount(uint8_t rhport)
}
-void tud_hid_mouse_cb(uint8_t rhport, tusb_event_t event, uint32_t xferred_bytes)
+void tud_hid_mouse_cb(uint8_t rhport, xfer_result_t event, uint32_t xferred_bytes)
{
switch(event)
{
- case TUSB_EVENT_XFER_COMPLETE:
- case TUSB_EVENT_XFER_ERROR:
- case TUSB_EVENT_XFER_STALLED:
+ case XFER_RESULT_SUCCESS:
+ case XFER_RESULT_FAILED:
+ case XFER_RESULT_STALLED:
default: break;
}
}
diff --git a/examples/obsolete/device/src/msc_device_ramdisk.c b/examples/obsolete/device/src/msc_device_ramdisk.c
index 6dc48e29..f28690b7 100644
--- a/examples/obsolete/device/src/msc_device_ramdisk.c
+++ b/examples/obsolete/device/src/msc_device_ramdisk.c
@@ -47,7 +47,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM
+CFG_TUSB_MEM_SECTION
uint8_t msc_device_ramdisk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
{
//------------- Boot Sector -------------//
diff --git a/examples/obsolete/device/src/tusb_config.h b/examples/obsolete/device/src/tusb_config.h
index 7b7c8229..c5739038 100644
--- a/examples/obsolete/device/src/tusb_config.h
+++ b/examples/obsolete/device/src/tusb_config.h
@@ -97,31 +97,31 @@
#ifdef __CODE_RED // compiled with lpcxpresso
#if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM2) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM2) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
#elif CFG_TUSB_MCU == OPT_MCU_LPC175X_6X
- #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all
+ #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM3)
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM3)
#endif
#elif defined __CC_ARM // Compiled with Keil armcc, USBRAM_SECTION is defined in scatter files
#if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(USBRAM_SECTION) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(USBRAM_SECTION) ATTR_ALIGNED(64) // lp11u & lp13u requires data to be 64 byte aligned
#elif (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
- #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all address
+ #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM // Use keil tool configure to have AHB SRAM as default memory
+ #define CFG_TUSB_MEM_SECTION // Use keil tool configure to have AHB SRAM as default memory
#endif
#elif defined __ICCARM__ // compiled with IAR
#if (CFG_TUSB_MCU == OPT_MCU_LPC11UXX) || (CFG_TUSB_MCU == OPT_MCU_LPC13UXX)
- #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\"USB_PACKET_MEMORY\"") ATTR_ALIGNED(64)
+ #define CFG_TUSB_MEM_SECTION _Pragma("location=\"USB_PACKET_MEMORY\"") ATTR_ALIGNED(64)
#elif (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
- #define CFG_TUSB_ATTR_USBRAM
+ #define CFG_TUSB_MEM_SECTION
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\".ahb_sram1\"")
+ #define CFG_TUSB_MEM_SECTION _Pragma("location=\".ahb_sram1\"")
#endif
#else
diff --git a/examples/obsolete/host/src/cdc_serial_host_app.c b/examples/obsolete/host/src/cdc_serial_host_app.c
index 30ed6698..85604dcd 100644
--- a/examples/obsolete/host/src/cdc_serial_host_app.c
+++ b/examples/obsolete/host/src/cdc_serial_host_app.c
@@ -49,8 +49,8 @@
static osal_semaphore_t sem_hdl;
enum { SERIAL_BUFFER_SIZE = 64 };
-CFG_TUSB_ATTR_USBRAM static uint8_t serial_in_buffer[SERIAL_BUFFER_SIZE];
-CFG_TUSB_ATTR_USBRAM static uint8_t serial_out_buffer[SERIAL_BUFFER_SIZE];
+CFG_TUSB_MEM_SECTION static uint8_t serial_in_buffer[SERIAL_BUFFER_SIZE];
+CFG_TUSB_MEM_SECTION static uint8_t serial_out_buffer[SERIAL_BUFFER_SIZE];
static uint8_t received_bytes; // set by transfer complete callback
@@ -75,7 +75,7 @@ void tuh_cdc_unmounted_cb(uint8_t dev_addr)
}
// invoked ISR context
-void tuh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
+void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
{
(void) dev_addr; // compiler warnings
@@ -84,17 +84,17 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id
case CDC_PIPE_DATA_IN:
switch(event)
{
- case TUSB_EVENT_XFER_COMPLETE:
+ case XFER_RESULT_SUCCESS:
received_bytes = xferred_bytes;
osal_semaphore_post(sem_hdl); // notify main task
break;
- case TUSB_EVENT_XFER_ERROR:
+ case XFER_RESULT_FAILED:
received_bytes = 0; // ignore
tuh_cdc_receive(dev_addr, serial_in_buffer, SERIAL_BUFFER_SIZE, true); // waiting for next data
break;
- case TUSB_EVENT_XFER_STALLED:
+ case XFER_RESULT_STALLED:
default :
break;
}
diff --git a/examples/obsolete/host/src/keyboard_host_app.c b/examples/obsolete/host/src/keyboard_host_app.c
index 21ace3bb..fd51548c 100644
--- a/examples/obsolete/host/src/keyboard_host_app.c
+++ b/examples/obsolete/host/src/keyboard_host_app.c
@@ -53,7 +53,7 @@
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
static osal_queue_t queue_kbd_hdl;
-CFG_TUSB_ATTR_USBRAM static hid_keyboard_report_t usb_keyboard_report;
+CFG_TUSB_MEM_SECTION static hid_keyboard_report_t usb_keyboard_report;
static inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) ATTR_CONST ATTR_ALWAYS_INLINE;
static inline void process_kbd_report(hid_keyboard_report_t const * report);
@@ -77,16 +77,16 @@ void tuh_hid_keyboard_unmounted_cb(uint8_t dev_addr)
}
// invoked ISR context
-void tuh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event)
+void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event)
{
switch(event)
{
- case TUSB_EVENT_XFER_COMPLETE:
+ case XFER_RESULT_SUCCESS:
osal_queue_send(queue_kbd_hdl, &usb_keyboard_report);
tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report);
break;
- case TUSB_EVENT_XFER_ERROR:
+ case XFER_RESULT_FAILED:
tuh_hid_keyboard_get_report(dev_addr, (uint8_t*) &usb_keyboard_report); // ignore & continue
break;
diff --git a/examples/obsolete/host/src/mouse_host_app.c b/examples/obsolete/host/src/mouse_host_app.c
index e242c7ca..819c2b29 100644
--- a/examples/obsolete/host/src/mouse_host_app.c
+++ b/examples/obsolete/host/src/mouse_host_app.c
@@ -53,7 +53,7 @@
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
static osal_queue_t queue_mouse_hdl;
-CFG_TUSB_ATTR_USBRAM static hid_mouse_report_t usb_mouse_report;
+CFG_TUSB_MEM_SECTION static hid_mouse_report_t usb_mouse_report;
static inline void process_mouse_report(hid_mouse_report_t const * p_report);
@@ -76,16 +76,16 @@ void tuh_hid_mouse_unmounted_cb(uint8_t dev_addr)
}
// invoked ISR context
-void tuh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event)
+void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event)
{
switch(event)
{
- case TUSB_EVENT_XFER_COMPLETE:
+ case XFER_RESULT_SUCCESS:
osal_queue_send(queue_mouse_hdl, &usb_mouse_report);
(void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report);
break;
- case TUSB_EVENT_XFER_ERROR:
+ case XFER_RESULT_FAILED:
(void) tuh_hid_mouse_get_report(dev_addr, (uint8_t*) &usb_mouse_report); // ignore & continue
break;
diff --git a/examples/obsolete/host/src/msc_cli.c b/examples/obsolete/host/src/msc_cli.c
index 1f7b1f5e..75dbb1c0 100644
--- a/examples/obsolete/host/src/msc_cli.c
+++ b/examples/obsolete/host/src/msc_cli.c
@@ -141,7 +141,7 @@ static cli_cmdfunc_t cli_command_tbl[] =
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM uint8_t fileread_buffer[CLI_FILE_READ_BUFFER];
+CFG_TUSB_MEM_SECTION uint8_t fileread_buffer[CLI_FILE_READ_BUFFER];
static char cli_buffer[CLI_MAX_BUFFER];
static char volume_label[20];
diff --git a/examples/obsolete/host/src/msc_host_app.c b/examples/obsolete/host/src/msc_host_app.c
index 957db2fa..1cfe9ec6 100644
--- a/examples/obsolete/host/src/msc_host_app.c
+++ b/examples/obsolete/host/src/msc_host_app.c
@@ -55,7 +55,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX];
+CFG_TUSB_MEM_SECTION static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX];
//--------------------------------------------------------------------+
// tinyusb callbacks
@@ -129,7 +129,7 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr)
}
// invoked ISR context
-void tuh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes)
+void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes)
{
(void) dev_addr;
(void) event;
diff --git a/examples/obsolete/host/src/tusb_config.h b/examples/obsolete/host/src/tusb_config.h
index 547fd364..f39fa26b 100644
--- a/examples/obsolete/host/src/tusb_config.h
+++ b/examples/obsolete/host/src/tusb_config.h
@@ -77,26 +77,26 @@
#ifdef __CODE_RED // make use of code red's support for ram region macros
#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X
- #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all address
+ #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM ATTR_SECTION(.data.$RAM3)
+ #define CFG_TUSB_MEM_SECTION ATTR_SECTION(.data.$RAM3)
#endif
#elif defined __CC_ARM // Compiled with Keil armcc
#if (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
- #define CFG_TUSB_ATTR_USBRAM // LPC17xx USB DMA can access all address
+ #define CFG_TUSB_MEM_SECTION // LPC17xx USB DMA can access all address
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM // Use keil tool configure to have AHB SRAM as default memory
+ #define CFG_TUSB_MEM_SECTION // Use keil tool configure to have AHB SRAM as default memory
#endif
#elif defined __ICCARM__ // compiled with IAR
#if (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X)
// LP175x_6x can access all but CMSIS-RTX causes overflow in 32KB SRAM --> move to AHB ram
- #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\".sram\"")
+ #define CFG_TUSB_MEM_SECTION _Pragma("location=\".sram\"")
#elif (CFG_TUSB_MCU == OPT_MCU_LPC43XX)
- #define CFG_TUSB_ATTR_USBRAM _Pragma("location=\".ahb_sram1\"")
+ #define CFG_TUSB_MEM_SECTION _Pragma("location=\".ahb_sram1\"")
#endif
#else
diff --git a/hw/bsp/ea4357/board_ea4357.c b/hw/bsp/ea4357/board_ea4357.c
index e4b9a0dc..ebe0d02e 100644
--- a/hw/bsp/ea4357/board_ea4357.c
+++ b/hw/bsp/ea4357/board_ea4357.c
@@ -36,7 +36,8 @@
*/
/**************************************************************************/
-#include "../board.h"
+#include "bsp/board.h"
+#include "tusb.h"
#ifdef BOARD_EA4357
@@ -119,6 +120,7 @@ void board_init(void)
GPIO_SetDir(buttons[i].gpio_port, BIT_(buttons[i].gpio_pin), 0);
}
+#if 0
//------------- UART -------------//
scu_pinmux(BOARD_UART_PIN_PORT, BOARD_UART_PIN_TX, MD_PDN, FUNC1);
scu_pinmux(BOARD_UART_PIN_PORT, BOARD_UART_PIN_RX, MD_PLN | MD_EZI | MD_ZI, FUNC1);
@@ -130,6 +132,7 @@ void board_init(void)
UART_Init(BOARD_UART_PORT, &UARTConfigStruct);
UART_TxCmd(BOARD_UART_PORT, ENABLE); // Enable UART Transmit
+#endif
//------------- NAND Flash (K9FXX) Size = 128M, Page Size = 2K, Block Size = 128K, Number of Block = 1024 -------------//
// nand_init();
@@ -167,11 +170,11 @@ uint32_t board_buttons(void)
//--------------------------------------------------------------------+
uint8_t board_uart_getchar(void)
{
- return UART_ReceiveByte(BOARD_UART_PORT);
+ //return UART_ReceiveByte(BOARD_UART_PORT);
}
void board_uart_putchar(uint8_t c)
{
- UART_Send(BOARD_UART_PORT, &c, 1, BLOCKING);
+ //UART_Send(BOARD_UART_PORT, &c, 1, BLOCKING);
}
#endif
diff --git a/hw/bsp/ea4357/board_ea4357.h b/hw/bsp/ea4357/board_ea4357.h
index 518b37ab..6fe8ca87 100644
--- a/hw/bsp/ea4357/board_ea4357.h
+++ b/hw/bsp/ea4357/board_ea4357.h
@@ -54,6 +54,7 @@
#include "oem_base_board/pca9532.h" // LEDs
#define BOARD_LED_NUM 1
+#define BOARD_LED0 0
//#define CFG_PRINTF_TARGET PRINTF_TARGET_SWO
diff --git a/hw/bsp/ea4357/oem_base_board/pca9532.c b/hw/bsp/ea4357/oem_base_board/pca9532.c
index 05e73cc2..7b526f67 100644
--- a/hw/bsp/ea4357/oem_base_board/pca9532.c
+++ b/hw/bsp/ea4357/oem_base_board/pca9532.c
@@ -24,9 +24,9 @@
/******************************************************************************
* Includes
*****************************************************************************/
-#include "../../board.h"
+#include "bsp/board.h"
-#if BOARD == BOARD_EA4357
+#ifdef BOARD_EA4357
#include "lpc43xx_i2c.h"
#include "lpc43xx_cgu.h"
diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h
index afac8379..d07c6242 100644
--- a/src/class/cdc/cdc.h
+++ b/src/class/cdc/cdc.h
@@ -50,10 +50,6 @@
extern "C" {
#endif
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpacked"
-#pragma GCC diagnostic ignored "-Wattributes"
-
/** \defgroup ClassDriver_CDC_Common Common Definitions
* @{ */
@@ -406,8 +402,6 @@ typedef struct ATTR_PACKED
TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct");
-#pragma GCC diagnostic pop
-
/** @} */
#ifdef __cplusplus
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index d8ade9c7..b68a6a7f 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -87,7 +87,7 @@ typedef struct
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
//--------------------------------------------------------------------+
// APPLICATION API
@@ -358,7 +358,7 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request
return true;
}
-tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes)
+tusb_error_t cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
{
// TODO Support multiple interfaces
uint8_t const itf = 0;
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h
index 749351a5..ad1100e9 100644
--- a/src/class/cdc/cdc_device.h
+++ b/src/class/cdc/cdc_device.h
@@ -116,7 +116,7 @@ void cdcd_init (void);
tusb_error_t cdcd_open (uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length);
bool cdcd_control_request (uint8_t rhport, tusb_control_request_t const * p_request);
bool cdcd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request);
-tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes);
+tusb_error_t cdcd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes);
void cdcd_reset (uint8_t rhport);
#endif
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index af2e2c44..0a366187 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -221,7 +221,7 @@ tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_
OSAL_SUBTASK_END
}
-void cdch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+void cdch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes)
{
tuh_cdc_xfer_isr( pipe_hdl.dev_addr, event, get_app_pipeid(pipe_hdl), xferred_bytes );
}
diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h
index 77f1e5a7..0b863bb6 100644
--- a/src/class/cdc/cdc_host.h
+++ b/src/class/cdc/cdc_host.h
@@ -77,27 +77,27 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid) ATTR_PURE ATTR_WARN
/** \brief Perform USB OUT transfer to device
* \param[in] dev_addr device address
- * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[in] p_data Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] length Number of bytes to be transferred via USB bus
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
- * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_ATTR_USBRAM.
+ * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
*/
tusb_error_t tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool is_notify);
/** \brief Perform USB IN transfer to get data from device
* \param[in] dev_addr device address
- * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[in] p_buffer Buffer containing received data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] length Number of bytes to be transferred via USB bus
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
* \retval TUSB_ERROR_INVALID_PARA if input parameters are not correct
* \note This function is non-blocking and returns immediately. The result of USB transfer will be reported by the
- * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_ATTR_USBRAM.
+ * interface's callback function. \a p_data must be declared with \ref CFG_TUSB_MEM_SECTION.
*/
tusb_error_t tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify);
@@ -118,16 +118,16 @@ void tuh_cdc_unmounted_cb(uint8_t dev_addr);
/** \brief Callback function that is invoked when an transferring event occurred
* \param[in] dev_addr Address of device
- * \param[in] event an value from \ref tusb_event_t
+ * \param[in] event an value from \ref xfer_result_t
* \param[in] pipe_id value from \ref cdc_pipeid_t indicate the pipe
* \param[in] xferred_bytes Number of bytes transferred via USB bus
* \note event can be one of following
- * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
- * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error.
- * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
+ * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
+ * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
* \note
*/
-void tuh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
+void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
/// @} // group CDC_Serial_Host
/// @}
@@ -151,7 +151,7 @@ extern cdch_data_t cdch_data[CFG_TUSB_HOST_DEVICE_MAX]; // TODO consider to move
void cdch_init(void);
tusb_error_t cdch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void cdch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void cdch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes);
void cdch_close(uint8_t dev_addr);
#endif
diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c
index 9b7684f7..89ea3b32 100644
--- a/src/class/cdc/cdc_rndis_host.c
+++ b/src/class/cdc/cdc_rndis_host.c
@@ -54,8 +54,8 @@
//--------------------------------------------------------------------+
#define RNDIS_MSG_PAYLOAD_MAX (1024*4)
-CFG_TUSB_ATTR_USBRAM static uint8_t msg_notification[CFG_TUSB_HOST_DEVICE_MAX][8];
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX];
+CFG_TUSB_MEM_SECTION static uint8_t msg_notification[CFG_TUSB_HOST_DEVICE_MAX][8];
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4) static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX];
STATIC_VAR rndish_data_t rndish_data[CFG_TUSB_HOST_DEVICE_MAX];
@@ -224,7 +224,7 @@ tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc)
OSAL_SUBTASK_END
}
-void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes)
{
if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) )
{
diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h
index c4597daa..3b92d3f2 100644
--- a/src/class/cdc/cdc_rndis_host.h
+++ b/src/class/cdc/cdc_rndis_host.h
@@ -65,7 +65,7 @@ typedef struct {
void rndish_init(void);
tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) ATTR_WARN_UNUSED_RESULT;
-void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes);
void rndish_close(uint8_t dev_addr);
#endif
diff --git a/src/class/custom/custom_device.c b/src/class/custom/custom_device.c
index cc440fc7..194963c1 100644
--- a/src/class/custom/custom_device.c
+++ b/src/class/custom/custom_device.c
@@ -94,7 +94,7 @@ bool cusd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque
return false;
}
-tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes)
+tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes)
{
return TUSB_ERROR_NONE;
}
diff --git a/src/class/custom/custom_device.h b/src/class/custom/custom_device.h
index 704c4127..0a8f05e7 100644
--- a/src/class/custom/custom_device.h
+++ b/src/class/custom/custom_device.h
@@ -66,7 +66,7 @@ void cusd_init(void);
tusb_error_t cusd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length);
bool cusd_control_request_st(uint8_t rhport, tusb_control_request_t const * p_request);
bool cusd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request);
-tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes);
+tusb_error_t cusd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes);
void cusd_reset(uint8_t rhport);
#endif
diff --git a/src/class/custom/custom_host.c b/src/class/custom/custom_host.c
index 329012fd..9f0b70af 100644
--- a/src/class/custom/custom_host.c
+++ b/src/class/custom/custom_host.c
@@ -131,7 +131,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_
return TUSB_ERROR_NONE;
}
-void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event)
+void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event)
{
}
diff --git a/src/class/custom/custom_host.h b/src/class/custom/custom_host.h
index 2bf3a8d3..5f9c25dd 100644
--- a/src/class/custom/custom_host.h
+++ b/src/class/custom/custom_host.h
@@ -73,7 +73,7 @@ tusb_error_t tusbh_custom_write(uint8_t dev_addr, uint16_t vendor_id, uint16_t p
void cush_init(void);
tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void cush_isr(pipe_handle_t pipe_hdl, tusb_event_t event);
+void cush_isr(pipe_handle_t pipe_hdl, xfer_result_t event);
void cush_close(uint8_t dev_addr);
#endif
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index 0008e47f..8bfede2d 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -49,10 +49,6 @@
extern "C" {
#endif
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpacked"
-#pragma GCC diagnostic ignored "-Wattributes"
-
//--------------------------------------------------------------------+
// Common Definitions
//--------------------------------------------------------------------+
@@ -613,8 +609,6 @@ enum
HID_USAGE_CONSUMER_AC_PAN = 0x0238,
};
-#pragma GCC diagnostic pop
-
#ifdef __cplusplus
}
#endif
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index b5586a48..f1ecec3c 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -91,7 +91,7 @@ typedef struct
hidd_interface_t* itf;
} hidd_report_t ;
-CFG_TUSB_ATTR_USBRAM static hidd_interface_t _hidd_itf[ITF_COUNT];
+CFG_TUSB_MEM_SECTION static hidd_interface_t _hidd_itf[ITF_COUNT];
#if CFG_TUD_HID_KEYBOARD
@@ -510,7 +510,7 @@ bool hidd_control_request_complete(uint8_t rhport, tusb_control_request_t const
return true;
}
-tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes)
+tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes)
{
// nothing to do
return TUSB_ERROR_NONE;
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index 7f8cd0fa..7aff7f34 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -110,7 +110,7 @@ extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128];
/** Callback invoked when USB host request \ref HID_REQ_CONTROL_GET_REPORT.
* \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests
- * \param[out] buffer data that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[out] buffer data that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] reqlen number of bytes that host requested
* \retval non-zero Actual number of bytes in the response's buffer.
* \retval zero indicates the current request is not supported. Tinyusb device stack will reject the request by
@@ -173,7 +173,7 @@ static inline bool tud_hid_mouse_button_release(void)
/**
* Callback function that is invoked when USB host request \ref HID_REQ_CONTROL_GET_REPORT.
* \param[in] report_type specify which report (INPUT, OUTPUT, FEATURE) that host requests
- * \param[out] buffer buffer that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[out] buffer buffer that application need to update, value must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] reqlen number of bytes that host requested
* \retval non-zero Actual number of bytes in the response's buffer.
* \retval zero indicates the current request is not supported. Tinyusb device stack will reject the request by
@@ -380,7 +380,7 @@ void hidd_init(void);
tusb_error_t hidd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length);
bool hidd_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
bool hidd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request);
-tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes);
+tusb_error_t hidd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes);
void hidd_reset(uint8_t rhport);
#endif
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index 518297ee..6aa0748d 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -177,7 +177,7 @@ void hidh_init(void)
}
#if 0
-CFG_TUSB_ATTR_USBRAM uint8_t report_descriptor[256];
+CFG_TUSB_MEM_SECTION uint8_t report_descriptor[256];
#endif
tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length)
@@ -251,7 +251,7 @@ tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_
OSAL_SUBTASK_END
}
-void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes)
{
(void) xferred_bytes; // TODO may need to use this para later
diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h
index b93bcdcc..cb0230e8 100644
--- a/src/class/hid/hid_host.h
+++ b/src/class/hid/hid_host.h
@@ -80,7 +80,7 @@ bool tuh_hid_keyboard_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNU
/** \brief Perform a get report from Keyboard interface
* \param[in] dev_addr device address
- * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION)
* \returns \ref tusb_error_t type to indicate success or error condition.
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
@@ -93,14 +93,14 @@ tusb_error_t tuh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report) /*A
//------------- Application Callback -------------//
/** \brief Callback function that is invoked when an transferring event occurred
* \param[in] dev_addr Address of device
- * \param[in] event an value from \ref tusb_event_t
+ * \param[in] event an value from \ref xfer_result_t
* \note event can be one of following
- * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
- * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error.
- * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
+ * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
+ * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
* \note Application should schedule the next report by calling \ref tuh_hid_keyboard_get_report within this callback
*/
-void tuh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event);
+void tuh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event);
/** \brief Callback function that will be invoked when a device with Keyboard interface is mounted
* \param[in] dev_addr Address of newly mounted device
@@ -145,7 +145,7 @@ bool tuh_hid_mouse_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED
/** \brief Perform a get report from Mouse interface
* \param[in] dev_addr device address
- * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref CFG_TUSB_MEM_SECTION)
* \returns \ref tusb_error_t type to indicate success or error condition.
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
@@ -158,14 +158,14 @@ tusb_error_t tuh_hid_mouse_get_report(uint8_t dev_addr, void* p_report) /*ATTR_
//------------- Application Callback -------------//
/** \brief Callback function that is invoked when an transferring event occurred
* \param[in] dev_addr Address of device
- * \param[in] event an value from \ref tusb_event_t
+ * \param[in] event an value from \ref xfer_result_t
* \note event can be one of following
- * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
- * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error.
- * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
+ * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
+ * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
* \note Application should schedule the next report by calling \ref tuh_hid_mouse_get_report within this callback
*/
-void tuh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event);
+void tuh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event);
/** \brief Callback function that will be invoked when a device with Mouse interface is mounted
* \param[in] dev_addr Address of newly mounted device
@@ -199,7 +199,7 @@ tusb_interface_status_t tuh_hid_generic_get_status(uint8_t dev_addr) ATTR_WARN_U
tusb_interface_status_t tuh_hid_generic_set_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
//------------- Application Callback -------------//
-void tuh_hid_generic_isr(uint8_t dev_addr, tusb_event_t event);
+void tuh_hid_generic_isr(uint8_t dev_addr, xfer_result_t event);
/** @} */ // Generic_Host
/** @} */ // ClassDriver_HID_Generic
@@ -217,7 +217,7 @@ typedef struct {
void hidh_init(void);
tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void hidh_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes);
void hidh_close(uint8_t dev_addr);
#endif
diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h
index e7c32b30..10a73bb1 100644
--- a/src/class/msc/msc.h
+++ b/src/class/msc/msc.h
@@ -46,16 +46,12 @@
#ifndef _TUSB_MSC_H_
#define _TUSB_MSC_H_
-#include
+#include "common/tusb_common.h"
#ifdef __cplusplus
extern "C" {
#endif
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpacked"
-#pragma GCC diagnostic ignored "-Wattributes"
-
//--------------------------------------------------------------------+
// Mass Storage Class Constant
//--------------------------------------------------------------------+
@@ -396,8 +392,6 @@ typedef struct ATTR_PACKED
TU_VERIFY_STATIC(sizeof(scsi_read10_t) == 10, "size is not correct");
TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct");
-#pragma GCC diagnostic pop
-
#ifdef __cplusplus
}
#endif
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index bfe708f4..88f8da6d 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -83,8 +83,8 @@ typedef struct {
uint8_t add_sense_qualifier;
}mscd_interface_t;
-CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf;
-CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static mscd_interface_t _mscd_itf;
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _mscd_buf[CFG_TUD_MSC_BUFSIZE];
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
@@ -324,7 +324,7 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf
return ret;
}
-tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes)
+tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
{
mscd_interface_t* p_msc = &_mscd_itf;
msc_cbw_t const * p_cbw = &p_msc->cbw;
@@ -337,7 +337,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
// Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it
if(ep_addr != p_msc->ep_out) return TUSB_ERROR_NONE;
- TU_ASSERT( event == DCD_XFER_SUCCESS &&
+ TU_ASSERT( event == XFER_RESULT_SUCCESS &&
xferred_bytes == sizeof(msc_cbw_t) && p_cbw->signature == MSC_CBW_SIGNATURE, TUSB_ERROR_INVALID_PARA );
p_csw->signature = MSC_CSW_SIGNATURE;
@@ -467,7 +467,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
}
// simulate an transfer complete with adjusted parameters --> this driver callback will fired again
- dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, DCD_XFER_SUCCESS, false);
+ dcd_event_xfer_complete(rhport, p_msc->ep_out, xferred_bytes-nbytes, XFER_RESULT_SUCCESS, false);
return TUSB_ERROR_NONE; // skip the rest
}
@@ -516,7 +516,7 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
if ( dcd_edpt_stalled(rhport, p_msc->ep_in) || dcd_edpt_stalled(rhport, p_msc->ep_out) )
{
// simulate an transfer complete with adjusted parameters --> this driver callback will fired again
- dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, DCD_XFER_SUCCESS, false);
+ dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, XFER_RESULT_SUCCESS, false);
}
else
{
@@ -578,7 +578,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc)
else if ( nbytes == 0 )
{
// zero means not ready -> simulate an transfer complete so that this driver callback will fired again
- dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, DCD_XFER_SUCCESS, false);
+ dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false);
}
else
{
diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h
index c1c51255..c4476f56 100644
--- a/src/class/msc/msc_device.h
+++ b/src/class/msc/msc_device.h
@@ -180,7 +180,7 @@ void mscd_init(void);
tusb_error_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length);
bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
bool mscd_control_request_complete (uint8_t rhport, tusb_control_request_t const * p_request);
-tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, tusb_event_t event, uint32_t xferred_bytes);
+tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t event, uint32_t xferred_bytes);
void mscd_reset(uint8_t rhport);
#endif
diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c
index 9250b8df..baef7ff4 100644
--- a/src/class/msc/msc_host.c
+++ b/src/class/msc/msc_host.c
@@ -51,13 +51,13 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM STATIC_VAR msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX];
+CFG_TUSB_MEM_SECTION STATIC_VAR msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX];
//------------- Initalization Data -------------//
static osal_semaphore_t msch_sem_hdl;
// buffer used to read scsi information when mounted, largest response data currently is inquiry
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)];
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)];
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
@@ -397,7 +397,7 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_
OSAL_SUBTASK_END
}
-void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+void msch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes)
{
if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) )
{
diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h
index dce275fc..a408bbea 100644
--- a/src/class/msc/msc_host.h
+++ b/src/class/msc/msc_host.h
@@ -104,7 +104,7 @@ tusb_error_t tuh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32
/** \brief Perform SCSI READ 10 command to read data from MassStorage device
* \param[in] dev_addr device address
* \param[in] lun Targeted Logical Unit
- * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[out] p_buffer Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] lba Starting Logical Block Address to be read
* \param[in] block_count Number of Block to be read
* \retval TUSB_ERROR_NONE on success
@@ -118,7 +118,7 @@ tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uin
/** \brief Perform SCSI WRITE 10 command to write data to MassStorage device
* \param[in] dev_addr device address
* \param[in] lun Targeted Logical Unit
- * \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[in] p_buffer Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \param[in] lba Starting Logical Block Address to be written
* \param[in] block_count Number of Block to be written
* \retval TUSB_ERROR_NONE on success
@@ -132,7 +132,7 @@ tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffe
/** \brief Perform SCSI REQUEST SENSE command, used to retrieve sense data from MassStorage device
* \param[in] dev_addr device address
* \param[in] lun Targeted Logical Unit
- * \param[in] p_data Buffer to store response's data from device. Must be accessible by USB controller (see \ref CFG_TUSB_ATTR_USBRAM)
+ * \param[in] p_data Buffer to store response's data from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
* \retval TUSB_ERROR_NONE on success
* \retval TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
* \retval TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
@@ -171,15 +171,15 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr);
/** \brief Callback function that is invoked when an transferring event occurred
* \param[in] dev_addr Address of device
- * \param[in] event an value from \ref tusb_event_t
+ * \param[in] event an value from \ref xfer_result_t
* \param[in] xferred_bytes Number of bytes transferred via USB bus
* \note event can be one of following
- * - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
- * - TUSB_EVENT_XFER_ERROR : previously scheduled transfer encountered a transaction error.
- * - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * - XFER_RESULT_SUCCESS : previously scheduled transfer completes successfully.
+ * - XFER_RESULT_FAILED : previously scheduled transfer encountered a transaction error.
+ * - XFER_RESULT_STALLED : previously scheduled transfer is stalled by device.
* \note
*/
-void tuh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes);
+void tuh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes);
//--------------------------------------------------------------------+
@@ -205,7 +205,7 @@ typedef struct {
void msch_init(void);
tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void msch_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes);
void msch_close(uint8_t dev_addr);
#endif
diff --git a/src/common/compiler/tusb_compiler_gcc.h b/src/common/compiler/tusb_compiler_gcc.h
index c9f716d4..e40ad9c4 100644
--- a/src/common/compiler/tusb_compiler_gcc.h
+++ b/src/common/compiler/tusb_compiler_gcc.h
@@ -66,10 +66,8 @@
/// The packed attribute specifies that a variable or structure field should have the smallest possible alignment—one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute
#define ATTR_PACKED __attribute__ ((packed))
-
#define ATTR_PREPACKED
-#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed))
/** @} */
/** \defgroup Group_FuncAttr Function Attributes
diff --git a/src/common/compiler/tusb_compiler_iar.h b/src/common/compiler/tusb_compiler_iar.h
index 1703ea45..1f893685 100644
--- a/src/common/compiler/tusb_compiler_iar.h
+++ b/src/common/compiler/tusb_compiler_iar.h
@@ -53,8 +53,6 @@
#endif
#define ALIGN_OF(x) __ALIGNOF__(x)
-
-#define ATTR_PACKED_STRUCT(x) __packed x
#define ATTR_PREPACKED __packed
#define ATTR_PACKED
//#define ATTR_SECTION(section) _Pragma((#section))
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index 32632cd9..b11481b1 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -51,10 +51,6 @@
extern "C" {
#endif
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpacked"
-#pragma GCC diagnostic ignored "-Wattributes"
-
/*------------------------------------------------------------------*/
/* CONSTANTS
*------------------------------------------------------------------*/
@@ -197,11 +193,10 @@ typedef enum
typedef enum
{
- TUSB_EVENT_NONE = 0,
- TUSB_EVENT_XFER_COMPLETE,
- TUSB_EVENT_XFER_ERROR,
- TUSB_EVENT_XFER_STALLED,
-}tusb_event_t;
+ XFER_RESULT_SUCCESS,
+ XFER_RESULT_FAILED,
+ XFER_RESULT_STALLED,
+}xfer_result_t;
enum
{
@@ -428,8 +423,6 @@ static inline uint8_t descriptor_len(uint8_t const p_desc[])
// Convert comma-separated string to descriptor unicode format
#define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { TUD_DESC_STR_HEADER(VA_ARGS_NUM_(__VA_ARGS__)), __VA_ARGS__ }
-#pragma GCC diagnostic pop
-
#ifdef __cplusplus
}
#endif
diff --git a/src/device/dcd.h b/src/device/dcd.h
index f07bda2d..db84df83 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -49,13 +49,6 @@
extern "C" {
#endif
-enum
-{
- DCD_XFER_SUCCESS = 0,
- DCD_XFER_FAILED,
- DCD_XFER_STALLED
-};
-
typedef enum
{
DCD_EVENT_BUS_RESET = 1,
diff --git a/src/device/usbd.c b/src/device/usbd.c
index f3960598..8c7e588e 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -92,7 +92,7 @@ typedef struct {
tusb_error_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t* p_length);
bool (* control_request ) (uint8_t rhport, tusb_control_request_t const * request);
bool (* control_request_complete ) (uint8_t rhport, tusb_control_request_t const * request);
- tusb_error_t (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, tusb_event_t, uint32_t);
+ tusb_error_t (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t, uint32_t);
void (* sof ) (uint8_t rhport);
void (* reset ) (uint8_t);
} usbd_class_driver_t;
@@ -174,7 +174,7 @@ static bool process_set_config(uint8_t rhport, uint8_t config_number);
static void const* get_descriptor(tusb_control_request_t const * p_request, uint16_t* desc_len);
void usbd_control_reset (uint8_t rhport);
-bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes);
+bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void usbd_control_set_complete_callback( bool (*fp) (uint8_t, tusb_control_request_t const * ) );
//--------------------------------------------------------------------+
@@ -581,7 +581,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
if ( 0 == edpt_number(event->xfer_complete.ep_addr) && event->xfer_complete.len == 0) break;
osal_queue_send(_usbd_q, event, in_isr);
- TU_ASSERT(event->xfer_complete.result == DCD_XFER_SUCCESS,);
+ TU_ASSERT(event->xfer_complete.result == XFER_RESULT_SUCCESS,);
break;
default: break;
diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c
index 8564d1ae..31d74edf 100644
--- a/src/device/usbd_control.c
+++ b/src/device/usbd_control.c
@@ -64,7 +64,7 @@ typedef struct
static usbd_control_xfer_t _control_state;
-CFG_TUSB_ATTR_USBRAM CFG_TUSB_MEM_ALIGN uint8_t _usbd_ctrl_buf[CFG_TUD_ENDOINT0_SIZE];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t _usbd_ctrl_buf[CFG_TUD_ENDOINT0_SIZE];
void usbd_control_reset (uint8_t rhport)
{
@@ -126,7 +126,7 @@ bool usbd_control_xfer(uint8_t rhport, tusb_control_request_t const * request, v
}
// callback when a transaction complete on DATA stage of control endpoint
-bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, tusb_event_t event, uint32_t xferred_bytes)
+bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
{
if ( _control_state.request.bmRequestType_bit.direction == TUSB_DIR_OUT )
{
diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c
index c7ff70d7..27808d59 100644
--- a/src/host/ehci/ehci.c
+++ b/src/host/ehci/ehci.c
@@ -56,12 +56,12 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data;
+CFG_TUSB_MEM_SECTION STATIC_VAR ehci_data_t ehci_data;
#if EHCI_PERIODIC_LIST
#if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST)
- CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE];
+ CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE];
#ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
TU_VERIFY_STATIC( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation
@@ -69,7 +69,7 @@ CFG_TUSB_ATTR_USBRAM STATIC_VAR ehci_data_t ehci_data;
#endif
#if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST)
- CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE];
+ CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE];
#ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
TU_VERIFY_STATIC( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation
@@ -570,7 +570,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
if (is_ioc) // end of request
{ // call USBH callback
usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
- p_qhd->class_code, TUSB_EVENT_XFER_COMPLETE,
+ p_qhd->class_code, XFER_RESULT_SUCCESS,
p_qhd->total_xferred_bytes - (xfer_type == TUSB_XFER_CONTROL ? 8 : 0) ); // subtract setup packet size if control,
p_qhd->total_xferred_bytes = 0;
}
@@ -638,15 +638,15 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
qhd_has_xact_error(p_qhd) )
{ // current qhd has error in transaction
tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
- tusb_event_t error_event;
+ xfer_result_t error_event;
// no error bits are set, endpoint is halted due to STALL
- error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED;
+ error_event = qhd_has_xact_error(p_qhd) ? XFER_RESULT_FAILED : XFER_RESULT_STALLED;
p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
-// if ( TUSB_EVENT_XFER_ERROR == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device
+// if ( XFER_RESULT_FAILED == error_event ) TU_BREAKPOINT(); // TODO skip unplugged device
p_qhd->p_qtd_list_head->used = 0; // free QTD
qtd_remove_1st_from_qhd(p_qhd);
diff --git a/src/host/hub.c b/src/host/hub.c
index 624e4356..55c8597a 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -58,8 +58,8 @@ typedef struct {
uint8_t status_change; // data from status change interrupt endpoint
}usbh_hub_t;
-CFG_TUSB_ATTR_USBRAM STATIC_VAR usbh_hub_t hub_data[CFG_TUSB_HOST_DEVICE_MAX];
-ATTR_ALIGNED(4) CFG_TUSB_ATTR_USBRAM STATIC_VAR uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)];
+CFG_TUSB_MEM_SECTION STATIC_VAR usbh_hub_t hub_data[CFG_TUSB_HOST_DEVICE_MAX];
+ATTR_ALIGNED(4) CFG_TUSB_MEM_SECTION STATIC_VAR uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)];
//OSAL_SEM_DEF(hub_enum_semaphore);
//static osal_semaphore_handle_t hub_enum_sem_hdl;
@@ -209,13 +209,13 @@ tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_i
}
// is the response of interrupt endpoint polling
-void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+void hub_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes)
{
(void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
usbh_hub_t * p_hub = &hub_data[pipe_hdl.dev_addr-1];
- if ( event == TUSB_EVENT_XFER_COMPLETE )
+ if ( event == XFER_RESULT_SUCCESS )
{
for (uint8_t port=1; port <= p_hub->port_number; port++)
{ // TODO HUB ignore bit0 hub_status_change
diff --git a/src/host/hub.h b/src/host/hub.h
index 67c02f2e..9376a269 100644
--- a/src/host/hub.h
+++ b/src/host/hub.h
@@ -196,7 +196,7 @@ tusb_error_t hub_status_pipe_queue(uint8_t dev_addr);
void hub_init(void);
tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void hub_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void hub_isr(pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes);
void hub_close(uint8_t dev_addr);
#endif
diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c
index b9183a02..91d9b624 100644
--- a/src/host/ohci/ohci.c
+++ b/src/host/ohci/ohci.c
@@ -142,7 +142,7 @@ enum {
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(256) STATIC_VAR ohci_data_t ohci_data;
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(256) STATIC_VAR ohci_data_t ohci_data;
static ohci_ed_t * const p_ed_head[] =
{
@@ -617,11 +617,11 @@ static void done_queue_isr(uint8_t hostid)
// TODO check if td_head is iso td
//------------- Non ISO transfer -------------//
ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head;
- tusb_event_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? TUSB_EVENT_XFER_COMPLETE :
- (p_qtd->condition_code == OHCI_CCODE_STALL) ? TUSB_EVENT_XFER_STALLED : TUSB_EVENT_XFER_ERROR;
+ xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS :
+ (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED;
p_qtd->used = 0; // free TD
- if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != TUSB_EVENT_XFER_COMPLETE) )
+ if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) )
{
ohci_ed_t * const p_ed = gtd_get_ed(p_qtd);
@@ -634,11 +634,11 @@ static void done_queue_isr(uint8_t hostid)
// --> HC will not process Control list (due to service ratio when Bulk list not empty)
// To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt
// the TailP must be set back to NULL for processing remaining TDs
- if ((event != TUSB_EVENT_XFER_COMPLETE))
+ if ((event != XFER_RESULT_SUCCESS))
{
p_ed->td_tail.address &= 0x0Ful;
p_ed->td_tail.address |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue
- if ( event == TUSB_EVENT_XFER_STALLED ) p_ed->is_stalled = 1;
+ if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1;
}
pipe_handle_t pipe_hdl =
diff --git a/src/host/usbh.c b/src/host/usbh.c
index f996d7a7..a0aab3b9 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -109,13 +109,13 @@ enum { USBH_CLASS_DRIVER_COUNT = sizeof(usbh_class_drivers) / sizeof(host_class_
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address
+CFG_TUSB_MEM_SECTION usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address
//------------- Enumeration Task Data -------------/
enum { ENUM_QUEUE_DEPTH = 16 };
STATIC_VAR osal_queue_t enum_queue_hdl;
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t enum_data_buffer[CFG_TUSB_HOST_ENUM_BUFFER_SIZE];
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4) STATIC_VAR uint8_t enum_data_buffer[CFG_TUSB_HOST_ENUM_BUFFER_SIZE];
//------------- Reporter Task Data -------------//
@@ -199,7 +199,7 @@ tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType,
#ifndef _TEST_
usbh_devices[dev_addr].control.pipe_status = 0;
#else
- usbh_devices[dev_addr].control.pipe_status = TUSB_EVENT_XFER_COMPLETE; // in Test project, mark as complete immediately
+ usbh_devices[dev_addr].control.pipe_status = XFER_RESULT_SUCCESS; // in Test project, mark as complete immediately
#endif
error = hcd_pipe_control_xfer(dev_addr, &usbh_devices[dev_addr].control.request, data);
@@ -207,11 +207,11 @@ tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, uint8_t bmRequestType,
osal_mutex_release(usbh_devices[dev_addr].control.mutex_hdl);
STASK_ASSERT_ERR(error);
- if (TUSB_EVENT_XFER_STALLED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_STALLED);
- if (TUSB_EVENT_XFER_ERROR == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_FAILED);
+ if (XFER_RESULT_STALLED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_STALLED);
+ if (XFER_RESULT_FAILED == usbh_devices[dev_addr].control.pipe_status) STASK_RETURN(TUSB_ERROR_USBH_XFER_FAILED);
// STASK_ASSERT_HDLR(TUSB_ERROR_NONE == error &&
-// TUSB_EVENT_XFER_COMPLETE == usbh_devices[dev_addr].control.pipe_status,
+// XFER_RESULT_SUCCESS == usbh_devices[dev_addr].control.pipe_status,
// tuh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL) );
OSAL_SUBTASK_END
@@ -256,7 +256,7 @@ static inline uint8_t std_class_code_to_index(uint8_t std_class_code)
// USBH-HCD ISR/Callback API
//--------------------------------------------------------------------+
// interrupt caused by a TD (with IOC=1) in pipe of class class_code
-void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t event, uint32_t xferred_bytes)
+void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, xfer_result_t event, uint32_t xferred_bytes)
{
uint8_t class_index = std_class_code_to_index(class_code);
if (TUSB_XFER_CONTROL == pipe_hdl.xfer_type)
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 5aaeb418..22fdef16 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -66,7 +66,7 @@ typedef enum tusb_interface_status_{
typedef struct {
void (* const init) (void);
tusb_error_t (* const open_subtask)(uint8_t, tusb_desc_interface_t const *, uint16_t*);
- void (* const isr) (pipe_handle_t, tusb_event_t, uint32_t);
+ void (* const isr) (pipe_handle_t, xfer_result_t, uint32_t);
void (* const close) (uint8_t);
} host_class_driver_t;
//--------------------------------------------------------------------+
diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h
index 1c2c4ad0..f6b72273 100644
--- a/src/host/usbh_hcd.h
+++ b/src/host/usbh_hcd.h
@@ -101,7 +101,7 @@ extern usbh_device_info_t usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including
//--------------------------------------------------------------------+
// callback from HCD ISR
//--------------------------------------------------------------------+
-void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, tusb_event_t event, uint32_t xferred_bytes);
+void usbh_xfer_isr(pipe_handle_t pipe_hdl, uint8_t class_code, xfer_result_t event, uint32_t xferred_bytes);
void usbh_hcd_rhport_plugged_isr(uint8_t hostid);
void usbh_hcd_rhport_unplugged_isr(uint8_t hostid);
diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h
index 46930aed..b21c3332 100644
--- a/src/osal/osal_none.h
+++ b/src/osal/osal_none.h
@@ -156,10 +156,12 @@ static inline void osal_queue_reset(osal_queue_t const queue_hdl)
static inline bool osal_queue_receive(osal_queue_t const queue_hdl, void* data)
{
// osal none return immediately without blocking
+ // extern void tusb_hal_int_disable(uint8_t rhport);
+ // extern void tusb_hal_int_enable(uint8_t rhport);
- // tusb_hal_int_disable_all();
+// tusb_hal_int_disable(0);
bool rc = tu_fifo_read(queue_hdl, data);
- // tusb_hal_int_enable_all();
+// tusb_hal_int_enable(0);
return rc;
}
diff --git a/src/portable/microchip/samd21/dcd_samd21.c b/src/portable/microchip/samd21/dcd_samd21.c
index b31db547..c6101f31 100644
--- a/src/portable/microchip/samd21/dcd_samd21.c
+++ b/src/portable/microchip/samd21/dcd_samd21.c
@@ -275,7 +275,7 @@ void maybe_transfer_complete(void) {
total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT;
uint8_t ep_addr = epnum | TUSB_DIR_IN_MASK;
- dcd_event_xfer_complete(0, ep_addr, total_transfer_size, DCD_XFER_SUCCESS, true);
+ dcd_event_xfer_complete(0, ep_addr, total_transfer_size, XFER_RESULT_SUCCESS, true);
}
// Handle OUT completions
@@ -286,7 +286,7 @@ void maybe_transfer_complete(void) {
total_transfer_size = bank->PCKSIZE.bit.BYTE_COUNT;
uint8_t ep_addr = epnum;
- dcd_event_xfer_complete(0, ep_addr, total_transfer_size, DCD_XFER_SUCCESS, true);
+ dcd_event_xfer_complete(0, ep_addr, total_transfer_size, XFER_RESULT_SUCCESS, true);
}
// just finished status stage (total size = 0), prepare for next setup packet
diff --git a/src/portable/microchip/samd51/dcd_samd51.c b/src/portable/microchip/samd51/dcd_samd51.c
index 6fff12ba..6e8053e5 100644
--- a/src/portable/microchip/samd51/dcd_samd51.c
+++ b/src/portable/microchip/samd51/dcd_samd51.c
@@ -304,7 +304,7 @@ void transfer_complete(uint8_t direction) {
if (direction == TUSB_DIR_IN) {
ep_addr |= TUSB_DIR_IN_MASK;
}
- dcd_event_xfer_complete(0, ep_addr, total_transfer_size, DCD_XFER_SUCCESS, true);
+ dcd_event_xfer_complete(0, ep_addr, total_transfer_size, XFER_RESULT_SUCCESS, true);
// just finished status stage (total size = 0), prepare for next setup packet
if (epnum == 0 && total_transfer_size == 0) {
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index 816ff62a..4fb88689 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -261,7 +261,7 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
edpt_dma_end();
// The nRF doesn't interrupt on status transmit so we queue up a success response.
- dcd_event_xfer_complete(0, ep_addr, 0, DCD_XFER_SUCCESS, false);
+ dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false);
}
else if ( dir == TUSB_DIR_OUT )
{
@@ -459,7 +459,7 @@ void USBD_IRQHandler(void)
xfer->total_len = xfer->actual_len;
// BULK/INT OUT complete
- dcd_event_xfer_complete(0, epnum, xfer->actual_len, DCD_XFER_SUCCESS, true);
+ dcd_event_xfer_complete(0, epnum, xfer->actual_len, XFER_RESULT_SUCCESS, true);
}
}
@@ -494,7 +494,7 @@ void USBD_IRQHandler(void)
} else
{
// Bulk/Int IN complete
- dcd_event_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, DCD_XFER_SUCCESS, true);
+ dcd_event_xfer_complete(0, epnum | TUSB_DIR_IN_MASK, xfer->actual_len, XFER_RESULT_SUCCESS, true);
}
}
}
diff --git a/src/portable/nordic/nrf5x/hal_nrf5x.c b/src/portable/nordic/nrf5x/hal_nrf5x.c
index 4ce51274..f40e904d 100644
--- a/src/portable/nordic/nrf5x/hal_nrf5x.c
+++ b/src/portable/nordic/nrf5x/hal_nrf5x.c
@@ -61,6 +61,7 @@ enum {
#endif
#include "tusb_hal.h"
+#include "device/dcd.h"
/*------------------------------------------------------------------*/
/* MACRO TYPEDEF CONSTANT ENUM
@@ -291,6 +292,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
nrf_usbd_disable();
hfclk_disable();
+
+ dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
}
break;
diff --git a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c
index 5c64cbb6..4e514d6e 100644
--- a/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c
+++ b/src/portable/nxp/lpc11xx_lpc13xx/dcd_lpc_11uxx_13uxx.c
@@ -141,11 +141,11 @@ typedef struct {
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-// CFG_TUSB_ATTR_USBRAM must have ATTR_ALIGNED(64) for lpc11u & lpc13u
+// CFG_TUSB_MEM_SECTION must have ATTR_ALIGNED(64) for lpc11u & lpc13u
#ifdef __ICCARM__
-ATTR_ALIGNED(256) CFG_TUSB_ATTR_USBRAM // for IAR the first ATTR_ALIGNED takes effect
+ATTR_ALIGNED(256) CFG_TUSB_MEM_SECTION // for IAR the first ATTR_ALIGNED takes effect
#else
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(256) // GCC & Keil the last ATTR_ALIGNED takes effect
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(256) // GCC & Keil the last ATTR_ALIGNED takes effect
#endif
STATIC_VAR dcd_11u_13u_data_t dcd_data;
diff --git a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c
index 850e257c..ce836254 100644
--- a/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c
+++ b/src/portable/nxp/lpc17xx/dcd_lpc175x_6x.c
@@ -68,7 +68,7 @@ typedef struct {
}dcd_data_t;
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(128) STATIC_VAR dcd_data_t dcd_data;
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(128) STATIC_VAR dcd_data_t dcd_data;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c
index 8d53759e..2f83f420 100644
--- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c
+++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.c
@@ -66,19 +66,30 @@ typedef struct {
dcd_qtd_t qtd[DCD_QTD_MAX] ATTR_ALIGNED(32);
}dcd_data_t;
-extern ATTR_WEAK dcd_data_t dcd_data0;
-extern ATTR_WEAK dcd_data_t dcd_data1;
-
#if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE)
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(2048) STATIC_VAR dcd_data_t dcd_data0;
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(2048) static dcd_data_t dcd_data0;
#endif
#if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(2048) STATIC_VAR dcd_data_t dcd_data1;
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(2048) static dcd_data_t dcd_data1;
#endif
static LPC_USB0_Type * const LPC_USB[2] = { LPC_USB0, ((LPC_USB0_Type*) LPC_USB1_BASE) };
-static dcd_data_t* const dcd_data_ptr[2] = { &dcd_data0, &dcd_data1 };
+
+static dcd_data_t* const dcd_data_ptr[2] =
+{
+#if (CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE)
+ &dcd_data0,
+#else
+ NULL,
+#endif
+
+#if (CFG_TUSB_RHPORT1_MODE & OPT_MODE_DEVICE)
+ &dcd_data1
+#else
+ NULL
+#endif
+};
//--------------------------------------------------------------------+
// CONTROLLER API
@@ -104,12 +115,11 @@ static void bus_reset(uint8_t rhport)
LPC_USB0_Type* const lpc_usb = LPC_USB[rhport];
// The reset value for all endpoint types is the control endpoint. If one endpoint
- //direction is enabled and the paired endpoint of opposite direction is disabled, then the
- //endpoint type of the unused direction must bechanged from the control type to any other
- //type (e.g. bulk). Leaving an unconfigured endpoint control will cause undefined behavior
- //for the data PID tracking on the active endpoint.
- lpc_usb->ENDPTCTRL1 = lpc_usb->ENDPTCTRL2 = lpc_usb->ENDPTCTRL3 =
- (TUSB_XFER_BULK << 2) | (TUSB_XFER_BULK << 18);
+ // direction is enabled and the paired endpoint of opposite direction is disabled, then the
+ // endpoint type of the unused direction must bechanged from the control type to any other
+ // type (e.g. bulk). Leaving an unconfigured endpoint control will cause undefined behavior
+ // for the data PID tracking on the active endpoint.
+ lpc_usb->ENDPTCTRL1 = lpc_usb->ENDPTCTRL2 = lpc_usb->ENDPTCTRL3 = (TUSB_XFER_BULK << 2) | (TUSB_XFER_BULK << 18);
// USB1 only has 3 non-control endpoints
if ( rhport == 0)
@@ -165,41 +175,18 @@ bool dcd_init(uint8_t rhport)
}
//--------------------------------------------------------------------+
-// PIPE HELPER
+// HELPER
//--------------------------------------------------------------------+
-#if 0
-static inline uint8_t edpt_pos2phy(uint8_t pos)
-{ // 0-5 --> OUT, 16-21 IN
- return (pos < DCD_QHD_MAX/2) ? (2*pos) : (2*(pos-16)+1);
-}
-#endif
-
-static inline uint8_t edpt_phy2pos(uint8_t physical_endpoint)
+// index to bit position in register
+static inline uint8_t ep_idx2bit(uint8_t ep_idx)
{
- return physical_endpoint/2 + ( (physical_endpoint%2) ? 16 : 0);
-}
-
-static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr)
-{
- return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_IN_MASK) ? 1 : 0);
-}
-
-static inline uint8_t edpt_phy2addr(uint8_t ep_idx)
-{
- return (ep_idx/2) | ( ep_idx & 0x01 ? TUSB_DIR_IN_MASK : 0 );
-}
-
-static inline uint8_t edpt_phy2log(uint8_t physical_endpoint)
-{
- return physical_endpoint/2;
+ return ep_idx/2 + ( (ep_idx%2) ? 16 : 0);
}
static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
{
tu_memclr(p_qtd, sizeof(dcd_qtd_t));
- p_qtd->used = 1;
-
p_qtd->next = QTD_NEXT_INVALID;
p_qtd->active = 1;
p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
@@ -214,81 +201,49 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
}
}
-// retval 0: invalid
-static inline uint8_t qtd_find_free(uint8_t rhport)
+static inline volatile uint32_t * get_endpt_ctrl_reg(uint8_t rhport, uint8_t ep_idx)
{
- // QTD0 is reserved for control transfer
- for(uint8_t i=1; iqtd[i].used == 0) return i;
- }
-
- return 0;
+ return &(LPC_USB[rhport]->ENDPTCTRL0) + ep_idx/2;
}
//--------------------------------------------------------------------+
-// CONTROL PIPE API
+// DCD Endpoint Port
//--------------------------------------------------------------------+
-
-// control transfer does not need to use qtd find function
-// follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism
-bool dcd_control_xfer(uint8_t rhport, uint8_t dir, uint8_t * p_buffer, uint16_t length)
-{
- LPC_USB0_Type* const lpc_usb = LPC_USB[rhport];
- dcd_data_t* const p_dcd = dcd_data_ptr[rhport];
-
- uint8_t const ep_phy = (dir == TUSB_DIR_IN) ? 1 : 0;
-
- dcd_qhd_t* qhd = &p_dcd->qhd[ep_phy];
-
- // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out
- while(lpc_usb->ENDPTSETUPSTAT & BIT_(0)) {}
-
- TU_VERIFY( !qhd->qtd_overlay.active );
-
- dcd_qtd_t* qtd = &p_dcd->qtd[0];
- qtd_init(qtd, p_buffer, length);
-
- // skip xfer complete for Status
- qtd->int_on_complete = (length > 0 ? 1 : 0);
-
- qhd->qtd_overlay.next = (uint32_t) qtd;
-
- lpc_usb->ENDPTPRIME = BIT_(edpt_phy2pos(ep_phy));
-
- return true;
-}
-
-//--------------------------------------------------------------------+
-// BULK/INTERRUPT/ISOCHRONOUS PIPE API
-//--------------------------------------------------------------------+
-static inline volatile uint32_t * get_reg_control_addr(uint8_t rhport, uint8_t physical_endpoint)
-{
- return &(LPC_USB[rhport]->ENDPTCTRL0) + edpt_phy2log(physical_endpoint);
-}
-
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
{
- uint8_t ep_idx = edpt_addr2phy(ep_addr);
- volatile uint32_t * reg_control = get_reg_control_addr(rhport, ep_idx);
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
+ uint8_t const ep_idx = 2*epnum + dir;
- if ( ep_addr == 0)
+ volatile uint32_t * endpt_ctrl = get_endpt_ctrl_reg(rhport, ep_idx);
+
+ if ( epnum == 0)
{
// Stall both Control IN and OUT
- (*reg_control) |= ( (ENDPTCTRL_MASK_STALL << 16) || (ENDPTCTRL_MASK_STALL << 0) );
+ (*endpt_ctrl) |= ( (ENDPTCTRL_MASK_STALL << 16) || (ENDPTCTRL_MASK_STALL << 0) );
}else
{
- (*reg_control) |= ENDPTCTRL_MASK_STALL << (ep_idx & 0x01 ? 16 : 0);
+ (*endpt_ctrl) |= ENDPTCTRL_MASK_STALL << (ep_idx & 0x01 ? 16 : 0);
}
}
+// TOOD implement later
+bool dcd_edpt_stalled (uint8_t rhport, uint8_t ep_addr)
+{
+ return false;
+}
+
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
{
- volatile uint32_t * reg_control = get_reg_control_addr(rhport, edpt_addr2phy(ep_addr));
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
+ uint8_t const ep_idx = 2*epnum + dir;
+
+ volatile uint32_t * endpt_ctrl = get_endpt_ctrl_reg(rhport, ep_idx);
// data toggle also need to be reset
- (*reg_control) |= ENDPTCTRL_MASK_TOGGLE_RESET << ((ep_addr & TUSB_DIR_IN_MASK) ? 16 : 0);
- (*reg_control) &= ~(ENDPTCTRL_MASK_STALL << ((ep_addr & TUSB_DIR_IN_MASK) ? 16 : 0));
+ (*endpt_ctrl) |= ENDPTCTRL_MASK_TOGGLE_RESET << ((ep_addr & TUSB_DIR_IN_MASK) ? 16 : 0);
+ (*endpt_ctrl) &= ~(ENDPTCTRL_MASK_STALL << ((ep_addr & TUSB_DIR_IN_MASK) ? 16 : 0));
}
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
@@ -297,12 +252,12 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
// TODO not support ISO yet
TU_VERIFY ( p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
- tusb_dir_t dir = (p_endpoint_desc->bEndpointAddress & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
+ uint8_t const epnum = edpt_number(p_endpoint_desc->bEndpointAddress);
+ uint8_t const dir = edpt_dir(p_endpoint_desc->bEndpointAddress);
+ uint8_t const ep_idx = 2*epnum + dir;
//------------- Prepare Queue Head -------------//
- uint8_t ep_idx = edpt_addr2phy(p_endpoint_desc->bEndpointAddress);
dcd_qhd_t * p_qhd = &dcd_data_ptr[rhport]->qhd[ep_idx];
-
tu_memclr(p_qhd, sizeof(dcd_qhd_t));
p_qhd->zero_length_termination = 1;
@@ -310,105 +265,61 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
p_qhd->qtd_overlay.next = QTD_NEXT_INVALID;
//------------- Endpoint Control Register -------------//
- volatile uint32_t * reg_control = get_reg_control_addr(rhport, ep_idx);
+ volatile uint32_t * endpt_ctrl = get_endpt_ctrl_reg(rhport, ep_idx);
// endpoint must not be already enabled
- TU_VERIFY( !( (*reg_control) & (ENDPTCTRL_MASK_ENABLE << (dir ? 16 : 0)) ) );
+ TU_VERIFY( !( (*endpt_ctrl) & (ENDPTCTRL_MASK_ENABLE << (dir ? 16 : 0)) ) );
- (*reg_control) |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_MASK_ENABLE | ENDPTCTRL_MASK_TOGGLE_RESET) << (dir ? 16 : 0);
+ (*endpt_ctrl) |= ((p_endpoint_desc->bmAttributes.xfer << 2) | ENDPTCTRL_MASK_ENABLE | ENDPTCTRL_MASK_TOGGLE_RESET) << (dir ? 16 : 0);
return true;
}
bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
{
- uint8_t ep_idx = edpt_addr2phy(ep_addr);
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
+ uint8_t const ep_idx = 2*epnum + dir;
+
dcd_qhd_t const * p_qhd = &dcd_data_ptr[rhport]->qhd[ep_idx];
+ dcd_qtd_t * p_qtd = &dcd_data_ptr[rhport]->qtd[ep_idx];
- return p_qhd->list_qtd_idx[0] != 0; // qtd list is not empty
+ return p_qtd->active;
// return !p_qhd->qtd_overlay.halted && p_qhd->qtd_overlay.active;
}
-// add only, controller virtually cannot know
-// TODO remove and merge to dcd_edpt_xfer
-static bool pipe_add_xfer(uint8_t rhport, uint8_t ed_idx, void * buffer, uint16_t total_bytes, bool int_on_complete)
-{
- uint8_t qtd_idx = qtd_find_free(rhport);
- TU_ASSERT(qtd_idx != 0);
-
- dcd_data_t* p_dcd = dcd_data_ptr[rhport];
- dcd_qhd_t * p_qhd = &p_dcd->qhd[ed_idx];
- dcd_qtd_t * p_qtd = &p_dcd->qtd[qtd_idx];
-
- //------------- Find free slot in qhd's array list -------------//
- uint8_t free_slot;
- for(free_slot=0; free_slot < DCD_QTD_PER_QHD_MAX; free_slot++)
- {
- if ( p_qhd->list_qtd_idx[free_slot] == 0 ) break; // found free slot
- }
- TU_ASSERT(free_slot < DCD_QTD_PER_QHD_MAX);
-
- p_qhd->list_qtd_idx[free_slot] = qtd_idx; // add new qtd to qhd's array list
-
- //------------- Prepare qtd -------------//
- qtd_init(p_qtd, buffer, total_bytes);
- p_qtd->int_on_complete = int_on_complete;
-
- if ( free_slot > 0 ) p_dcd->qtd[ p_qhd->list_qtd_idx[free_slot-1] ].next = (uint32_t) p_qtd;
-
- return true;
-}
-
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
{
- uint8_t ep_idx = edpt_addr2phy(ep_addr);
+ uint8_t const epnum = edpt_number(ep_addr);
+ uint8_t const dir = edpt_dir(ep_addr);
+ uint8_t const ep_idx = 2*epnum + dir;
- TU_VERIFY ( pipe_add_xfer(rhport, ep_idx, buffer, total_bytes, true) );
-
- dcd_qhd_t* p_qhd = &dcd_data_ptr[rhport]->qhd[ ep_idx ];
- dcd_qtd_t* p_qtd = &dcd_data_ptr[rhport]->qtd[ p_qhd->list_qtd_idx[0] ];
-
- p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // attach head QTD to QHD start transferring
-
- LPC_USB[rhport]->ENDPTPRIME = BIT_( edpt_phy2pos(ep_idx) ) ;
-
- return true;
-}
-
-//------------- Device Controller Driver's Interrupt Handler -------------//
-void xfer_complete_isr(uint8_t rhport, uint32_t reg_complete)
-{
- for(uint8_t ep_idx = 2; ep_idx < DCD_QHD_MAX; ep_idx++)
+ if ( epnum == 0 )
{
- if ( BIT_TEST_(reg_complete, edpt_phy2pos(ep_idx)) )
- { // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
- dcd_qhd_t * p_qhd = &dcd_data_ptr[rhport]->qhd[ep_idx];
-
- // retire all QTDs in array list, up to 1st still-active QTD
- while( p_qhd->list_qtd_idx[0] != 0 )
- {
- dcd_qtd_t * p_qtd = &dcd_data_ptr[rhport]->qtd[ p_qhd->list_qtd_idx[0] ];
-
- if (p_qtd->active) break; // stop immediately if found still-active QTD and shift array list
-
- //------------- Free QTD and shift array list -------------//
- p_qtd->used = 0; // free QTD
- memmove( (void*) p_qhd->list_qtd_idx, (void*) (p_qhd->list_qtd_idx+1), DCD_QTD_PER_QHD_MAX-1);
- p_qhd->list_qtd_idx[DCD_QTD_PER_QHD_MAX-1]=0;
-
- if (p_qtd->int_on_complete)
- {
- uint8_t result = p_qtd->halted ? DCD_XFER_STALLED :
- ( p_qtd->xact_err ||p_qtd->buffer_err ) ? DCD_XFER_FAILED : DCD_XFER_SUCCESS;
-
- uint8_t ep_addr = edpt_phy2addr(ep_idx);
- dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd
- }
- }
- }
+ // follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism
+ // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out
+ while(LPC_USB[rhport]->ENDPTSETUPSTAT & BIT_(0)) {}
}
+
+ dcd_data_t* p_dcd = dcd_data_ptr[rhport];
+ dcd_qhd_t * p_qhd = &p_dcd->qhd[ep_idx];
+ dcd_qtd_t * p_qtd = &p_dcd->qtd[ep_idx];
+
+ //------------- Prepare qtd -------------//
+ qtd_init(p_qtd, buffer, total_bytes);
+ p_qtd->int_on_complete = true;
+ p_qhd->qtd_overlay.next = (uint32_t) p_qtd; // link qtd to qhd
+
+ // start transfer
+ LPC_USB[rhport]->ENDPTPRIME = BIT_( ep_idx2bit(ep_idx) ) ;
+
+ return true;
}
+
+//--------------------------------------------------------------------+
+// ISR
+//--------------------------------------------------------------------+
void hal_dcd_isr(uint8_t rhport)
{
LPC_USB0_Type* const lpc_usb = LPC_USB[rhport];
@@ -457,9 +368,9 @@ void hal_dcd_isr(uint8_t rhport)
dcd_data_t* const p_dcd = dcd_data_ptr[rhport];
- //------------- Set up Received -------------//
if (lpc_usb->ENDPTSETUPSTAT)
{
+ //------------- Set up Received -------------//
// 23.10.10.2 Operational model for setup transfers
lpc_usb->ENDPTSETUPSTAT = lpc_usb->ENDPTSETUPSTAT;// acknowledge
@@ -469,29 +380,24 @@ void hal_dcd_isr(uint8_t rhport)
dcd_event_handler(&event, true);
}
- //------------- Control Request Completed -------------//
- else if ( edpt_complete & ( BIT_(0) | BIT_(16)) )
+ if ( edpt_complete )
{
- // determine Control OUT or IN
- uint8_t ep_idx = BIT_TEST_(edpt_complete, 0) ? 0 : 1;
-
- // TODO use the actual QTD instead of the qhd's overlay to get expected bytes for actual byte xferred
- dcd_qtd_t* const p_qtd = (dcd_qtd_t*) p_dcd->qhd[ep_idx].qtd_addr;
-
- if ( p_qtd->int_on_complete )
+ for(uint8_t ep_idx = 0; ep_idx < DCD_QHD_MAX; ep_idx++)
{
- uint8_t result = p_qtd->halted ? DCD_XFER_STALLED :
- ( p_qtd->xact_err ||p_qtd->buffer_err ) ? DCD_XFER_FAILED : DCD_XFER_SUCCESS;
+ if ( BIT_TEST_(edpt_complete, ep_idx2bit(ep_idx)) )
+ {
+ // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
+ dcd_qhd_t * p_qhd = &dcd_data_ptr[rhport]->qhd[ep_idx];
+ dcd_qtd_t * p_qtd = &dcd_data_ptr[rhport]->qtd[ep_idx];
- dcd_event_xfer_complete(rhport, 0, p_qtd->expected_bytes - p_qtd->total_bytes, result, true);
+ uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
+ ( p_qtd->xact_err ||p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
+
+ uint8_t ep_addr = (ep_idx/2) | ( (ep_idx & 0x01) ? TUSB_DIR_IN_MASK : 0 );
+ dcd_event_xfer_complete(rhport, ep_addr, p_qtd->expected_bytes - p_qtd->total_bytes, result, true); // only number of bytes in the IOC qtd
+ }
}
}
-
- //------------- Transfer Complete -------------//
- if ( edpt_complete & ~(BIT_(0) | BIT_(16)) )
- {
- xfer_complete_isr(rhport, edpt_complete);
- }
}
if (int_status & INT_MASK_SOF)
@@ -504,7 +410,4 @@ void hal_dcd_isr(uint8_t rhport)
if (int_status & INT_MASK_ERROR) TU_ASSERT(false, );
}
-//--------------------------------------------------------------------+
-// HELPER
-//--------------------------------------------------------------------+
#endif
diff --git a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h
index 1476c0d3..85334a34 100644
--- a/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h
+++ b/src/portable/nxp/lpc43xx_lpc18xx/dcd_lpc43xx.h
@@ -54,7 +54,6 @@
//--------------------------------------------------------------------+
#define DCD_QHD_MAX 12
#define DCD_QTD_MAX 12
-#define DCD_QTD_PER_QHD_MAX 2 // maximum number of qtd that are linked into one queue head at a time
#define QTD_NEXT_INVALID 0x01
@@ -91,7 +90,6 @@ enum {
PORTSC_CURRENT_CONNECT_STATUS_MASK = BIT_(0),
PORTSC_FORCE_PORT_RESUME_MASK = BIT_(6),
PORTSC_SUSPEND_MASK = BIT_(7)
-
};
typedef struct
@@ -118,8 +116,7 @@ typedef struct
//------------- DCD Area -------------//
uint16_t expected_bytes;
- uint8_t used;
- uint8_t reserved;
+ uint8_t reserved[2];
} dcd_qtd_t;
TU_VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct");
@@ -148,9 +145,7 @@ typedef struct
/// Due to the fact QHD is 64 bytes aligned but occupies only 48 bytes
/// thus there are 16 bytes padding free that we can make use of.
//--------------------------------------------------------------------+
- volatile uint8_t list_qtd_idx[DCD_QTD_PER_QHD_MAX];
-
- uint8_t reserved[16-DCD_QTD_PER_QHD_MAX];
+ uint8_t reserved[16];
} dcd_qhd_t;
TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct");
diff --git a/src/tusb_option.h b/src/tusb_option.h
index f19ff407..18e1e245 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -131,8 +131,9 @@
#warning CFG_TUSB_DEBUG is not defined, default value is 0
#endif
-#ifndef CFG_TUSB_ATTR_USBRAM
- #error CFG_TUSB_ATTR_USBRAM is not defined, please help me know how to place data in accessible RAM for usb controller
+// place data in accessible RAM for usb controller
+#ifndef CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_SECTION
#endif
#ifndef CFG_TUSB_OS
diff --git a/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h b/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h
index b1aea64b..1eb608b9 100644
--- a/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h
+++ b/tests/lpc18xx_43xx/test/host/cdc/cdc_callback.h
@@ -55,7 +55,7 @@
void tusbh_cdc_mounted_cb(uint8_t dev_addr);
void tusbh_cdc_unmounted_cb(uint8_t dev_addr);
-void tusbh_cdc_xfer_isr(uint8_t dev_addr, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
+void tusbh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes);
void tusbh_cdc_rndis_mounted_cb(uint8_t dev_addr);
void tusbh_cdc_rndis_unmounted_isr(uint8_t dev_addr);
diff --git a/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c b/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c
index f71ab453..02c4c8f9 100644
--- a/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c
+++ b/tests/lpc18xx_43xx/test/host/cdc/descriptor_cdc.c
@@ -42,7 +42,7 @@
//--------------------------------------------------------------------+
// CDC Serials
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM
+CFG_TUSB_MEM_SECTION
const cdc_configuration_desc_t cdc_config_descriptor =
{
.configuration =
@@ -168,7 +168,7 @@ const cdc_configuration_desc_t cdc_config_descriptor =
// CDC RNSID
//--------------------------------------------------------------------+
-CFG_TUSB_ATTR_USBRAM
+CFG_TUSB_MEM_SECTION
const cdc_configuration_desc_t rndis_config_descriptor =
{
.configuration =
diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c
index 5077eea9..12dce052 100644
--- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c
+++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_host.c
@@ -251,10 +251,10 @@ void test_cdc_xfer_notification_pipe(void)
cdch_data[dev_addr-1].pipe_out = pipe_out;
cdch_data[dev_addr-1].pipe_in = pipe_in;
- tusbh_cdc_xfer_isr_Expect(dev_addr, TUSB_EVENT_XFER_COMPLETE, CDC_PIPE_NOTIFICATION, 10);
+ tusbh_cdc_xfer_isr_Expect(dev_addr, XFER_RESULT_SUCCESS, CDC_PIPE_NOTIFICATION, 10);
//------------- CUT -------------//
- cdch_isr(pipe_notification, TUSB_EVENT_XFER_COMPLETE, 10);
+ cdch_isr(pipe_notification, XFER_RESULT_SUCCESS, 10);
}
void test_cdc_xfer_pipe_out(void)
@@ -267,10 +267,10 @@ void test_cdc_xfer_pipe_out(void)
cdch_data[dev_addr-1].pipe_out = pipe_out;
cdch_data[dev_addr-1].pipe_in = pipe_in;
- tusbh_cdc_xfer_isr_Expect(dev_addr, TUSB_EVENT_XFER_ERROR, CDC_PIPE_DATA_OUT, 20);
+ tusbh_cdc_xfer_isr_Expect(dev_addr, XFER_RESULT_FAILED, CDC_PIPE_DATA_OUT, 20);
//------------- CUT -------------//
- cdch_isr(pipe_out, TUSB_EVENT_XFER_ERROR, 20);
+ cdch_isr(pipe_out, XFER_RESULT_FAILED, 20);
}
void test_cdc_xfer_pipe_in(void)
@@ -283,8 +283,8 @@ void test_cdc_xfer_pipe_in(void)
cdch_data[dev_addr-1].pipe_out = pipe_out;
cdch_data[dev_addr-1].pipe_in = pipe_in;
- tusbh_cdc_xfer_isr_Expect(dev_addr, TUSB_EVENT_XFER_STALLED, CDC_PIPE_DATA_IN, 0);
+ tusbh_cdc_xfer_isr_Expect(dev_addr, XFER_RESULT_STALLED, CDC_PIPE_DATA_IN, 0);
//------------- CUT -------------//
- cdch_isr(pipe_in, TUSB_EVENT_XFER_STALLED, 0);
+ cdch_isr(pipe_in, XFER_RESULT_STALLED, 0);
}
diff --git a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c
index a493c3b7..86d6c289 100644
--- a/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c
+++ b/tests/lpc18xx_43xx/test/host/cdc/test_cdc_rndis_host.c
@@ -188,7 +188,7 @@ static tusb_error_t stub_pipe_notification_xfer(pipe_handle_t pipe_hdl, uint8_t
buffer[0] = 1; // response available
- cdch_isr(pipe_hdl, TUSB_EVENT_XFER_COMPLETE, 8);
+ cdch_isr(pipe_hdl, XFER_RESULT_SUCCESS, 8);
return TUSB_ERROR_NONE;
}
diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c
index 2e9e29fd..c4037c59 100644
--- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c
+++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_bulk_xfer.c
@@ -208,7 +208,7 @@ void test_bulk_xfer_complete_isr(void)
ehci_qtd_t* p_head = p_qhd_bulk->p_qtd_list_head;
ehci_qtd_t* p_tail = p_qhd_bulk->p_qtd_list_tail;
- usbh_xfer_isr_Expect(pipe_hdl_bulk, TUSB_CLASS_MSC, TUSB_EVENT_XFER_COMPLETE, sizeof(data2)+sizeof(xfer_data));
+ usbh_xfer_isr_Expect(pipe_hdl_bulk, TUSB_CLASS_MSC, XFER_RESULT_SUCCESS, sizeof(data2)+sizeof(xfer_data));
//------------- Code Under Test -------------//
ehci_controller_run(hostid);
diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c
index ffd7ffb6..4f8cdb4c 100644
--- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c
+++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_control_xfer.c
@@ -228,7 +228,7 @@ void test_control_xfer_complete_isr(void)
{
TEST_ASSERT_STATUS( hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data) );
- usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, TUSB_EVENT_XFER_COMPLETE, 18);
+ usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, XFER_RESULT_SUCCESS, 18);
//------------- Code Under TEST -------------//
ehci_controller_run(hostid);
@@ -247,7 +247,7 @@ void test_control_xfer_error_isr(void)
{
TEST_ASSERT_STATUS( hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data) );
- usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, TUSB_EVENT_XFER_ERROR, 0);
+ usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, XFER_RESULT_FAILED, 0);
//------------- Code Under TEST -------------//
ehci_controller_run_error(hostid);
@@ -266,7 +266,7 @@ void test_control_xfer_error_stall(void)
{
TEST_ASSERT_STATUS( hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data) );
- usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, TUSB_EVENT_XFER_STALLED, 0);
+ usbh_xfer_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, XFER_RESULT_STALLED, 0);
//------------- Code Under TEST -------------//
ehci_controller_run_stall(hostid);
diff --git a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c
index 827db289..bf7ad352 100644
--- a/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c
+++ b/tests/lpc18xx_43xx/test/host/ehci/test_pipe_interrupt_xfer.c
@@ -201,7 +201,7 @@ void test_interrupt_xfer_complete_isr_interval_less_than_1ms(void)
TEST_ASSERT_STATUS( hcd_pipe_xfer(pipe_hdl_interrupt, data2, sizeof(data2), true) );
- usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, TUSB_EVENT_XFER_COMPLETE, sizeof(xfer_data)+sizeof(data2));
+ usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, XFER_RESULT_SUCCESS, sizeof(xfer_data)+sizeof(data2));
ehci_qtd_t* p_head = p_qhd_interrupt->p_qtd_list_head;
ehci_qtd_t* p_tail = p_qhd_interrupt->p_qtd_list_tail;
@@ -242,7 +242,7 @@ void test_interrupt_xfer_error_isr(void)
{
TEST_ASSERT_STATUS( hcd_pipe_xfer(pipe_hdl_interrupt, xfer_data, sizeof(xfer_data), true) );
- usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, TUSB_EVENT_XFER_ERROR, 0);
+ usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, XFER_RESULT_FAILED, 0);
//------------- Code Under TEST -------------//
ehci_controller_run_error(hostid);
@@ -254,7 +254,7 @@ void test_interrupt_xfer_error_stall(void)
{
TEST_ASSERT_STATUS( hcd_pipe_xfer(pipe_hdl_interrupt, xfer_data, sizeof(xfer_data), true) );
- usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, TUSB_EVENT_XFER_STALLED, 0);
+ usbh_xfer_isr_Expect(pipe_hdl_interrupt, TUSB_CLASS_HID, XFER_RESULT_STALLED, 0);
//------------- Code Under TEST -------------//
ehci_controller_run_stall(hostid);
diff --git a/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h b/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h
index 4b76bd3c..b0945c1d 100644
--- a/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h
+++ b/tests/lpc18xx_43xx/test/host/hid/hidh_callback.h
@@ -59,11 +59,11 @@
#include "common/common.h"
//------------- hidh -------------//
-void tusbh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event);
+void tusbh_hid_keyboard_isr(uint8_t dev_addr, xfer_result_t event);
void tusbh_hid_keyboard_mounted_cb(uint8_t dev_addr);
void tusbh_hid_keyboard_unmounted_cb(uint8_t dev_addr);
-void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event);
+void tusbh_hid_mouse_isr(uint8_t dev_addr, xfer_result_t event);
void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr);
void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr);
diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c
index b3b49c17..de358142 100644
--- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c
+++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_keyboard.c
@@ -216,10 +216,10 @@ void test_keyboard_get_ok()
void test_keyboard_isr_event_complete(void)
{
- tusbh_hid_keyboard_isr_Expect(dev_addr, TUSB_EVENT_XFER_COMPLETE);
+ tusbh_hid_keyboard_isr_Expect(dev_addr, XFER_RESULT_SUCCESS);
//------------- Code Under TEST -------------//
- hidh_isr(p_hidh_kbd->pipe_hdl, TUSB_EVENT_XFER_COMPLETE, 8);
+ hidh_isr(p_hidh_kbd->pipe_hdl, XFER_RESULT_SUCCESS, 8);
// tusbh_device_get_state_IgnoreAndReturn(TUSB_DEVICE_STATE_CONFIGURED);
// TEST_ASSERT_EQUAL(TUSB_INTERFACE_STATUS_COMPLETE, tusbh_hid_keyboard_status(dev_addr));
diff --git a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c
index b1a3558e..541c2cae 100644
--- a/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c
+++ b/tests/lpc18xx_43xx/test/host/hid/test_hidh_mouse.c
@@ -189,10 +189,10 @@ void test_mouse_get_ok()
void test_mouse_isr_event_xfer_complete(void)
{
- tusbh_hid_mouse_isr_Expect(dev_addr, TUSB_EVENT_XFER_COMPLETE);
+ tusbh_hid_mouse_isr_Expect(dev_addr, XFER_RESULT_SUCCESS);
//------------- Code Under TEST -------------//
- hidh_isr(p_hidh_mouse->pipe_hdl, TUSB_EVENT_XFER_COMPLETE, 8);
+ hidh_isr(p_hidh_mouse->pipe_hdl, XFER_RESULT_SUCCESS, 8);
tusbh_device_get_state_IgnoreAndReturn(TUSB_DEVICE_STATE_CONFIGURED);
// TEST_ASSERT_EQUAL(TUSB_INTERFACE_STATUS_COMPLETE, tusbh_hid_mouse_status(dev_addr));
@@ -200,10 +200,10 @@ void test_mouse_isr_event_xfer_complete(void)
void test_mouse_isr_event_xfer_error(void)
{
- tusbh_hid_mouse_isr_Expect(dev_addr, TUSB_EVENT_XFER_ERROR);
+ tusbh_hid_mouse_isr_Expect(dev_addr, XFER_RESULT_FAILED);
//------------- Code Under TEST -------------//
- hidh_isr(p_hidh_mouse->pipe_hdl, TUSB_EVENT_XFER_ERROR, 0);
+ hidh_isr(p_hidh_mouse->pipe_hdl, XFER_RESULT_FAILED, 0);
tusbh_device_get_state_IgnoreAndReturn(TUSB_DEVICE_STATE_CONFIGURED);
// TEST_ASSERT_EQUAL(TUSB_INTERFACE_STATUS_ERROR, tusbh_hid_mouse_status(dev_addr));
diff --git a/tests/lpc18xx_43xx/test/host/msc/msch_callback.h b/tests/lpc18xx_43xx/test/host/msc/msch_callback.h
index 26b301a0..275245be 100644
--- a/tests/lpc18xx_43xx/test/host/msc/msch_callback.h
+++ b/tests/lpc18xx_43xx/test/host/msc/msch_callback.h
@@ -54,7 +54,7 @@
void tusbh_msc_mounted_cb(uint8_t dev_addr);
void tusbh_msc_unmounted_cb(uint8_t dev_addr);
-void tusbh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes);
+void tusbh_msc_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes);
#ifdef __cplusplus
diff --git a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c
index a85c3c48..eba3fbcc 100644
--- a/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c
+++ b/tests/lpc18xx_43xx/test/host/usbh/test_enum_task.c
@@ -181,7 +181,7 @@ tusb_error_t control_xfer_stub(uint8_t dev_addr, const tusb_control_request_t *
usbh_xfer_isr(
(pipe_handle_t) { .dev_addr = (num_call > 1 ? 1 : 0), .xfer_type = TUSB_XFER_CONTROL },
- 0, TUSB_EVENT_XFER_COMPLETE, 0);
+ 0, XFER_RESULT_SUCCESS, 0);
return TUSB_ERROR_NONE;
}
diff --git a/tests/support/descriptor_test.c b/tests/support/descriptor_test.c
index 0998db8b..ced24674 100644
--- a/tests/support/descriptor_test.c
+++ b/tests/support/descriptor_test.c
@@ -39,7 +39,7 @@
#include "tusb_option.h"
#include "descriptor_test.h"
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4)
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4)
const uint8_t keyboard_report_descriptor[] = {
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ),
HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ),
@@ -81,7 +81,7 @@ const uint8_t keyboard_report_descriptor[] = {
HID_COLLECTION_END
};
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4)
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4)
const uint8_t mouse_report_descriptor[] = {
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ),
HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ),
@@ -118,7 +118,7 @@ const uint8_t mouse_report_descriptor[] = {
};
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4)
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4)
tusb_desc_device_t const desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
@@ -142,7 +142,7 @@ tusb_desc_device_t const desc_device =
} ;
-CFG_TUSB_ATTR_USBRAM ATTR_ALIGNED(4)
+CFG_TUSB_MEM_SECTION ATTR_ALIGNED(4)
const app_configuration_desc_t desc_configuration =
{
.configuration =
diff --git a/tests/support/tusb_config.h b/tests/support/tusb_config.h
index e46d6f04..bf627784 100644
--- a/tests/support/tusb_config.h
+++ b/tests/support/tusb_config.h
@@ -86,7 +86,7 @@
#define CFG_TUSB_DEBUG 3
#define CFG_TUSB_OS OPT_OS_NONE
-#define CFG_TUSB_ATTR_USBRAM
+#define CFG_TUSB_MEM_SECTION
#ifdef __cplusplus
}