Browse Source

Merge pull request #409 from grissiom/lpc43xx

Lpc43xx
Bernard Xiong 10 years ago
parent
commit
56ab0995c1
49 changed files with 4087 additions and 1163 deletions
  1. 9 9
      bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/ARM/startup_LPC43xx_M0.s
  2. 46 20
      bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx.s
  3. 94 111
      bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s
  4. 5 3
      bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c
  5. 10 6
      bsp/lpc43xx/M0/SConscript
  6. 19 1
      bsp/lpc43xx/M0/SConstruct
  7. 0 0
      bsp/lpc43xx/M0/applications/SConscript
  8. 121 0
      bsp/lpc43xx/M0/applications/application.c
  9. 67 0
      bsp/lpc43xx/M0/applications/board.c
  10. 59 0
      bsp/lpc43xx/M0/applications/board.h
  11. 0 0
      bsp/lpc43xx/M0/applications/startup.c
  12. 13 0
      bsp/lpc43xx/M0/applications/vbus_conf.h
  13. 86 0
      bsp/lpc43xx/M0/applications/vbus_drv.c
  14. 53 0
      bsp/lpc43xx/M0/applications/vbus_hw.h
  15. 5 2
      bsp/lpc43xx/M0/rtconfig.h
  16. 11 14
      bsp/lpc43xx/M0/rtconfig.py
  17. 139 0
      bsp/lpc43xx/M0/rtthread-lpc43xx.ld
  18. 18 0
      bsp/lpc43xx/M0/rtthread_lpc43xx.sct
  19. 20 402
      bsp/lpc43xx/M0/template.uvproj
  20. 8 0
      bsp/lpc43xx/M0/vbus_local_conf.h
  21. 10 6
      bsp/lpc43xx/M4/SConscript
  22. 27 2
      bsp/lpc43xx/M4/SConstruct
  23. 13 0
      bsp/lpc43xx/M4/applications/SConscript
  24. 156 0
      bsp/lpc43xx/M4/applications/application.c
  25. 3 4
      bsp/lpc43xx/M4/applications/board.c
  26. 1 2
      bsp/lpc43xx/M4/applications/board.h
  27. 74 0
      bsp/lpc43xx/M4/applications/startup.c
  28. 13 0
      bsp/lpc43xx/M4/applications/vbus_conf.h
  29. 86 0
      bsp/lpc43xx/M4/applications/vbus_drv.c
  30. 53 0
      bsp/lpc43xx/M4/applications/vbus_hw.h
  31. 4 2
      bsp/lpc43xx/M4/rtconfig.h
  32. 7 6
      bsp/lpc43xx/M4/rtconfig.py
  33. 147 0
      bsp/lpc43xx/M4/rtthread-lpc43xx.ld
  34. 23 0
      bsp/lpc43xx/M4/rtthread_lpc43xx.sct
  35. 7 390
      bsp/lpc43xx/M4/template.uvproj
  36. 8 0
      bsp/lpc43xx/M4/vbus_local_conf.h
  37. 0 84
      bsp/lpc43xx/applications/application.c
  38. 14 0
      bsp/lpc43xx/bin2C.py
  39. 122 99
      bsp/lpc43xx/drivers/drv_uart.c
  40. 4 0
      bsp/lpc43xx/readme.txt
  41. 29 0
      components/vbus/SConscript
  42. 276 0
      components/vbus/prio_queue.c
  43. 73 0
      components/vbus/prio_queue.h
  44. 71 0
      components/vbus/rt_watermark_queue.c
  45. 149 0
      components/vbus/rt_watermark_queue.h
  46. 79 0
      components/vbus/share_hdr/vbus_api.h
  47. 1371 0
      components/vbus/vbus.c
  48. 197 0
      components/vbus/vbus.h
  49. 287 0
      components/vbus/vbus_chnx.c

+ 9 - 9
bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/ARM/startup_LPC43xx_M0.s

@@ -96,10 +96,10 @@ __Vectors       DCD     __initial_sp                      ; 0 Top of Stack
                 DCD     ADC1_IRQHandler                ; 37 ADC1
                 DCD     SSP0_OR_SSP1_IRQHandler        ; 38 SSP0 or SSP1
                 DCD     EVENTROUTER_IRQHandler         ; 39 Event router
-                DCD     USART0_IRQHandler              ; 40 USART0
+                DCD     UART0_IRQHandler               ; 40 USART0
                 DCD     UART1_IRQHandler               ; 41 UART1/Modem
-                DCD     USART2_OR_C_CAN1_IRQHandler    ; 42 USART2 or C CAN1
-                DCD     USART3_IRQHandler              ; 43 USART3
+                DCD     UART2_OR_C_CAN1_IRQHandler     ; 42 USART2 or C CAN1
+                DCD     UART3_IRQHandler               ; 43 USART3
                 DCD     I2S0_OR_I2S1_OR_QEI_IRQHandler ; 44 I2S0 or I2S1 or QEI
                 DCD     C_CAN0_IRQHandler              ; 45 C CAN0
                 DCD     0                                 ; 46 Reserved
@@ -175,10 +175,10 @@ Default_Handler PROC
                 EXPORT   ADC1_IRQHandler                 [WEAK]
                 EXPORT   SSP0_OR_SSP1_IRQHandler         [WEAK]
                 EXPORT   EVENTROUTER_IRQHandler          [WEAK]
-                EXPORT   USART0_IRQHandler               [WEAK]
+                EXPORT   UART0_IRQHandler                [WEAK]
                 EXPORT   UART1_IRQHandler                [WEAK]
-                EXPORT   USART2_OR_C_CAN1_IRQHandler     [WEAK]
-                EXPORT   USART3_IRQHandler               [WEAK]
+                EXPORT   UART2_OR_C_CAN1_IRQHandler      [WEAK]
+                EXPORT   UART3_IRQHandler                [WEAK]
                 EXPORT   I2S0_OR_I2S1_OR_QEI_IRQHandler  [WEAK]
                 EXPORT   C_CAN0_IRQHandler               [WEAK]
 
@@ -206,10 +206,10 @@ SPI_OR_DAC_IRQHandler
 ADC1_IRQHandler
 SSP0_OR_SSP1_IRQHandler
 EVENTROUTER_IRQHandler
-USART0_IRQHandler
+UART0_IRQHandler
 UART1_IRQHandler
-USART2_OR_C_CAN1_IRQHandler
-USART3_IRQHandler
+UART2_OR_C_CAN1_IRQHandler
+UART3_IRQHandler
 I2S0_OR_I2S1_OR_QEI_IRQHandler
 C_CAN0_IRQHandler
 

+ 46 - 20
bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx.s

@@ -109,30 +109,56 @@ __interrupt_vector:
 	.type  Reset_Handler, %function
 Reset_Handler:
     .fnstart
-.ifdef RAM_MODE
-/* Clear .bss section (Zero init) */
-	mov     R0, #0
-	ldr     R1, =__bss_start__
-	ldr    R2, =__bss_end__
-	cmp     R1,R2
-	beq     BSSIsEmpty
-LoopZI:
-    cmp     R1, R2
-    bhs     BSSIsEmpty
-    str     R0, [R1]
-    add     R1, #4
-    blo     LoopZI
-BSSIsEmpty:
-    ldr     R0, =SystemInit
-    blx     R0
-    ldr     R0,=main
-    bx      R0
-.else
+/*  Single section scheme.
+ *
+ *  The ranges of copy from/to are specified by following symbols
+ *    _sidata: LMA of start of the section to copy from. Usually end of text
+ *    _sdata: VMA of start of the section to copy to
+ *    _edata: VMA of end of the section to copy to
+ *
+ *  All addresses must be aligned to 4 bytes boundary.
+ */
+	ldr	r1, =_sidata
+	ldr	r2, =_sdata
+	ldr	r3, =_edata
+
+	subs	r3, r2
+	ble	.L_loop1_done
+
+.L_loop1:
+	subs	r3, #4
+	ldr	r0, [r1,r3]
+	str	r0, [r2,r3]
+	bgt	.L_loop1
+
+.L_loop1_done:
+
+/*  Single BSS section scheme.
+ *
+ *  The BSS section is specified by following symbols
+ *    __bss_start: start of the BSS section.
+ *    __bss_end: end of the BSS section.
+ *
+ *  Both addresses must be aligned to 4 bytes boundary.
+ */
+	ldr	r1, =__bss_start
+	ldr	r2, =__bss_end
+
+	movs	r0, 0
+
+	subs	r2, r1
+	ble	.L_loop3_done
+
+.L_loop3:
+	subs	r2, #4
+	str	r0, [r1, r2]
+	bgt	.L_loop3
+.L_loop3_done:
+
     ldr     R0, =SystemInit
     blx     R0
     ldr     R0,=main
     bx      R0
-.endif
 
     .pool
     .cantunwind

+ 94 - 111
bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s

@@ -6,9 +6,9 @@
 
 	.syntax unified
 	.cpu cortex-m0
-	.fpu softvfp
+	.arch armv6-m
 	.thumb
-	
+
 	.word  _sidata
 	.word  _sdata
 	.word  _edata
@@ -43,59 +43,38 @@ __interrupt_vector:
     .long   SysTick_Handler             /* SysTick Handler              */
 
 /* External Interrupts */
-    .long   DAC_IRQHandler              /* 16 D/A Converter             */
-    .long   M4CORE_IRQHandler           /* 17 M0 Core                   */
-    .long   DMA_IRQHandler              /* 18 General Purpose DMA       */
-    .long   EZH_IRQHandler              /* 19 EZH/EDM                   */
-    .long   FLASH_EEPROM_IRQHandler     /* 20 Reserved for Typhoon      */
-    .long   ETH_IRQHandler              /* 21 Ethernet                  */
-    .long   SDIO_IRQHandler             /* 22 SD/MMC                    */
-    .long   LCD_IRQHandler              /* 23 LCD                       */
-    .long   USB0_IRQHandler             /* 24 USB0                      */
-    .long   USB1_IRQHandler             /* 25 USB1                      */
-    .long   SCT_IRQHandler              /* 26 State Configurable Timer  */
-    .long   RIT_IRQHandler              /* 27 Repetitive Interrupt Timer*/
-    .long   TIMER0_IRQHandler           /* 28 Timer0                    */
-    .long   TIMER1_IRQHandler           /* 29 Timer1                    */
-    .long   TIMER2_IRQHandler           /* 30 Timer2                    */
-    .long   TIMER3_IRQHandler           /* 31 Timer3                    */
-    .long   MCPWM_IRQHandler            /* 32 Motor Control PWM         */
-    .long   ADC0_IRQHandler             /* 33 A/D Converter 0           */
-    .long   I2C0_IRQHandler             /* 34 I2C0                      */
-    .long   I2C1_IRQHandler             /* 35 I2C1                      */
-    .long   SPI_IRQHandler              /* 36 SPI                       */
-    .long   ADC1_IRQHandler             /* 37 A/D Converter 1           */
-    .long   SSP0_IRQHandler             /* 38 SSP0                      */
-    .long   SSP1_IRQHandler             /* 39 SSP1                      */
-    .long   UART0_IRQHandler            /* 40 UART0                     */
-    .long   UART1_IRQHandler            /* 41 UART1                     */
-    .long   UART2_IRQHandler            /* 42 UART2                     */
-    .long   UART3_IRQHandler            /* 43 UART3                     */
-    .long   I2S0_IRQHandler             /* 44 I2S0                      */
-    .long   I2S1_IRQHandler             /* 45 I2S1                      */
-    .long   SPIFI_IRQHandler            /* 46 SPI Flash Interface       */
-    .long   SGPIO_IRQHandler            /* 47 SGPIO                     */
-    .long   GPIO0_IRQHandler            /* 48 GPIO0                     */
-    .long   GPIO1_IRQHandler            /* 49 GPIO1                     */
-    .long   GPIO2_IRQHandler            /* 50 GPIO2                     */
-    .long   GPIO3_IRQHandler            /* 51 GPIO3                     */
-    .long   GPIO4_IRQHandler            /* 52 GPIO4                     */
-    .long   GPIO5_IRQHandler            /* 53 GPIO5                     */
-    .long   GPIO6_IRQHandler            /* 54 GPIO6                     */
-    .long   GPIO7_IRQHandler            /* 55 GPIO7                     */
-    .long   GINT0_IRQHandler            /* 56 GINT0                     */
-    .long   GINT1_IRQHandler            /* 57 GINT1                     */
-    .long   EVRT_IRQHandler             /* 58 Event Router              */
-    .long   CAN1_IRQHandler             /* 59 C_CAN1                    */
-    .long   0                           /* 60 Reserved                  */
-    .long   VADC_IRQHandler             /* 61 VADC                      */
-    .long   ATIMER_IRQHandler           /* 62 ATIMER                    */
-    .long   RTC_IRQHandler              /* 63 RTC                       */
-    .long   0                           /* 64 Reserved                  */
-    .long   WDT_IRQHandler              /* 65 WDT                       */
-    .long   M0s_IRQHandler              /* 66 M0s                       */
-    .long   CAN0_IRQHandler             /* 67 C_CAN0                    */
-    .long   QEI_IRQHandler              /* 68 QEI                       */
+    .long   RTC_IRQHandler                 /* 16 D/A Converter             */
+    .long   M4CORE_IRQHandler              /* 17 M0 Core                   */
+    .long   DMA_IRQHandler                 /* 18 General Purpose DMA       */
+    .long   0                              /* 19 EZH/EDM                   */
+    .long   FLASHEEPROMAT_IRQHandler       /* 20 Reserved for Typhoon      */
+    .long   ETH_IRQHandler                 /* 21 Ethernet                  */
+    .long   SDIO_IRQHandler                /* 22 SD/MMC                    */
+    .long   LCD_IRQHandler                 /* 23 LCD                       */
+    .long   USB0_IRQHandler                /* 24 USB0                      */
+    .long   USB1_IRQHandler                /* 25 USB1                      */
+    .long   SCT_IRQHandler                 /* 26 State Configurable Timer  */
+    .long   RIT_OR_WWDT_IRQHandler         /* 27 Repetitive Interrupt Timer*/
+    .long   TIMER0_IRQHandler              /* 28 Timer0                    */
+    .long   GINT1_IRQHandler               /* 29 Timer1                    */
+    .long   PIN_INT4_IRQHandler            /* 30 Timer2                    */
+    .long   TIMER3_IRQHandler              /* 31 Timer3                    */
+    .long   MCPWM_IRQHandler               /* 32 Motor Control PWM         */
+    .long   ADC0_IRQHandler                /* 33 A/D Converter 0           */
+    .long   I2C0_OR_I2C1_IRQHandler        /* 34 I2C0                      */
+    .long   SGPIO_IRQHandler               /* 35 I2C1                      */
+    .long   SPI_OR_DAC_IRQHandler          /* 36 SPI                       */
+    .long   ADC1_IRQHandler                /* 37 A/D Converter 1           */
+    .long   SSP0_OR_SSP1_IRQHandler        /* 38 SSP0                      */
+    .long   EVENTROUTER_IRQHandler         /* 39 SSP1                      */
+    .long   UART0_IRQHandler               /* 40 UART0                     */
+    .long   UART1_IRQHandler               /* 41 UART1                     */
+    .long   UART2_OR_C_CAN1_IRQHandler     /* 42 UART2                     */
+    .long   UART3_IRQHandler               /* 43 UART3                     */
+    .long   I2S0_OR_I2S1_OR_QEI_IRQHandler /* 44 I2S0                      */
+    .long   C_CAN0_IRQHandler              /* 45 I2S1                      */
+    .long   0                              /* 46 SPI Flash Interface       */
+    .long   0                              /* 47 SGPIO                     */
 
     .size   __interrupt_vector, . - __interrupt_vector
 
@@ -109,30 +88,56 @@ __interrupt_vector:
 	.type  Reset_Handler, %function
 Reset_Handler:
     .fnstart
-.ifdef RAM_MODE
-/* Clear .bss section (Zero init) */
-	mov     R0, #0
-	ldr     R1, =__bss_start__
-	ldr    R2, =__bss_end__
-	cmp     R1,R2
-	beq     BSSIsEmpty
-LoopZI:
-    cmp     R1, R2
-    bhs     BSSIsEmpty
-    str     R0, [R1]
-    add     R1, #4
-    blo     LoopZI
-BSSIsEmpty:
-    ldr     R0, =SystemInit
-    blx     R0
-    ldr     R0,=main
-    bx      R0
-.else
+/*  Single section scheme.
+ *
+ *  The ranges of copy from/to are specified by following symbols
+ *    _sidata: LMA of start of the section to copy from. Usually end of text
+ *    _sdata: VMA of start of the section to copy to
+ *    _edata: VMA of end of the section to copy to
+ *
+ *  All addresses must be aligned to 4 bytes boundary.
+ */
+	ldr	r1, =_sidata
+	ldr	r2, =_sdata
+	ldr	r3, =_edata
+
+	subs	r3, r2
+	ble	.L_loop1_done
+
+.L_loop1:
+	subs	r3, #4
+	ldr	r0, [r1,r3]
+	str	r0, [r2,r3]
+	bgt	.L_loop1
+
+.L_loop1_done:
+
+/*  Single BSS section scheme.
+ *
+ *  The BSS section is specified by following symbols
+ *    __bss_start: start of the BSS section.
+ *    __bss_end: end of the BSS section.
+ *
+ *  Both addresses must be aligned to 4 bytes boundary.
+ */
+	ldr	r1, =__bss_start
+	ldr	r2, =__bss_end
+
+	movs	r0, 0
+
+	subs	r2, r1
+	ble	.L_loop3_done
+
+.L_loop3:
+	subs	r2, #4
+	str	r0, [r1, r2]
+	bgt	.L_loop3
+.L_loop3_done:
+
     ldr     R0, =SystemInit
     blx     R0
     ldr     R0,=main
     bx      R0
-.endif
 
     .pool
     .cantunwind
@@ -211,56 +216,34 @@ Default_Handler:
     .set    \handler, Default_Handler
     .endm
 
-    IRQ    DAC_IRQHandler
-    IRQ    M0CORE_IRQHandler
+    IRQ    RTC_IRQHandler
+    IRQ    M4CORE_IRQHandler
     IRQ    DMA_IRQHandler
-    IRQ    EZH_IRQHandler
-    IRQ    FLASH_EEPROM_IRQHandler
+    IRQ    FLASHEEPROMAT_IRQHandler
     IRQ    ETH_IRQHandler
     IRQ    SDIO_IRQHandler
     IRQ    LCD_IRQHandler
     IRQ    USB0_IRQHandler
     IRQ    USB1_IRQHandler
     IRQ    SCT_IRQHandler
-    IRQ    RIT_IRQHandler
+    IRQ    RIT_OR_WWDT_IRQHandler
     IRQ    TIMER0_IRQHandler
-    IRQ    TIMER1_IRQHandler
-    IRQ    TIMER2_IRQHandler
+    IRQ    GINT1_IRQHandler
+    IRQ    PIN_INT4_IRQHandler
     IRQ    TIMER3_IRQHandler
     IRQ    MCPWM_IRQHandler
     IRQ    ADC0_IRQHandler
-    IRQ    I2C0_IRQHandler
-    IRQ    I2C1_IRQHandler
-    IRQ    SPI_IRQHandler
+    IRQ    I2C0_OR_I2C1_IRQHandler
+    IRQ    SGPIO_IRQHandler
+    IRQ    SPI_OR_DAC_IRQHandler
     IRQ    ADC1_IRQHandler
-    IRQ    SSP0_IRQHandler
-    IRQ    SSP1_IRQHandler
+    IRQ    SSP0_OR_SSP1_IRQHandler
+    IRQ    EVENTROUTER_IRQHandler
     IRQ    UART0_IRQHandler
     IRQ    UART1_IRQHandler
-    IRQ    UART2_IRQHandler
+    IRQ    UART2_OR_C_CAN1_IRQHandler
     IRQ    UART3_IRQHandler
-    IRQ    I2S0_IRQHandler
-    IRQ    I2S1_IRQHandler
-    IRQ    SPIFI_IRQHandler
-    IRQ    SGPIO_IRQHandler
-    IRQ    GPIO0_IRQHandler
-    IRQ    GPIO1_IRQHandler
-    IRQ    GPIO2_IRQHandler
-    IRQ    GPIO3_IRQHandler
-    IRQ    GPIO4_IRQHandler
-    IRQ    GPIO5_IRQHandler
-    IRQ    GPIO6_IRQHandler
-    IRQ    GPIO7_IRQHandler
-    IRQ    GINT0_IRQHandler
-    IRQ    GINT1_IRQHandler
-    IRQ    EVRT_IRQHandler
-    IRQ    CAN1_IRQHandler
-    IRQ    VADC_IRQHandler
-    IRQ    ATIMER_IRQHandler
-    IRQ    RTC_IRQHandler
-    IRQ    WDT_IRQHandler
-    IRQ    M0s_IRQHandler
-    IRQ    CAN0_IRQHandler
-    IRQ    QEI_IRQHandler
+    IRQ    I2S0_OR_I2S1_OR_QEI_IRQHandler
+    IRQ    C_CAN0_IRQHandler
 
     .end

+ 5 - 3
bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c

@@ -869,6 +869,7 @@ void SystemCoreClockUpdate (void) {
  *----------------------------------------------------------------------------*/
 void SystemInit (void) {
 
+#ifdef BOOT_PROCESSOR
   #if (__FPU_USED == 1)
     SCB->CPACR |= ((3UL << 10*2) |                 /* set CP10 Full Access */
                    (3UL << 11*2)  );               /* set CP11 Full Access */
@@ -880,9 +881,10 @@ void SystemInit (void) {
   /* Configure PLL0 and PLL1, connect CPU clock to selected clock source */
   SetClock();
 
-  /* Update SystemCoreClock variable */
-  SystemCoreClockUpdate();
-
   /* Configure External Memory Controller */
   SystemInit_ExtMemCtl ();
+#endif
+
+  /* Update SystemCoreClock variable */
+  SystemCoreClockUpdate();
 }

+ 10 - 6
bsp/lpc43xx/M0/SConscript

@@ -2,12 +2,16 @@ from building import *
 
 cwd  = GetCurrentDir()
 objs = []
-list = os.listdir(os.path.join(cwd, '..'))
 
-for d in list:
-    if (d != 'M4' and d != 'M0'):
-        path = os.path.join(cwd, '..', d)
-        if os.path.isfile(os.path.join(path, 'SConscript')):
-            objs = objs + SConscript(os.path.join(path, 'SConscript'))
+for d in os.listdir(os.path.join(cwd, '..')):
+    if d not in ('M0', 'M4'):
+        path = os.path.join('..', d, 'SConscript')
+        if os.path.isfile(os.path.join(cwd, path)):
+            objs = objs + SConscript(os.path.join(cwd, path))
+
+for d in os.listdir(cwd):
+    p = os.path.join(d, 'SConscript');
+    if os.path.isfile(os.path.join(cwd, p)):
+        objs = objs + SConscript(p)
 
 Return('objs')

+ 19 - 1
bsp/lpc43xx/M0/SConstruct

@@ -5,7 +5,7 @@ import rtconfig
 if os.getenv('RTT_ROOT'):
     RTT_ROOT = os.getenv('RTT_ROOT')
 else:
-    RTT_ROOT = os.path.join(Dir('#').get_abspath(), '..', '..', 'rt-thread')
+    RTT_ROOT = os.path.join(Dir('#').get_abspath(), '..', '..', '..')
 
 sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
 from building import *
@@ -25,5 +25,23 @@ Export('rtconfig')
 # prepare building environment
 objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
 
+if rtconfig.CROSS_TOOL == 'gcc':
+    import glob
+    # Remove the .o for M0 left on the drivers dir.
+    for i in glob.glob(GetCurrentDir() + '/../drivers/*.o'):
+        print 'RM %s' % i
+        os.unlink(i)
+
+    if sys.platform.startswith('linux'):
+        import glob
+        ocwd = os.getcwdu()
+        res = os.system('cd ../Libraries/; find -name \*.o -exec rm {} \;')
+        os.chdir(ocwd)
+    else:
+        # Assume Windows.
+        ocwd = os.getcwdu()
+        print 'TODO: remove the object files in ../Libraries'
+        os.chdir(ocwd)
+
 # do building 
 DoBuilding(TARGET, objs)

+ 0 - 0
bsp/lpc43xx/applications/SConscript → bsp/lpc43xx/M0/applications/SConscript


+ 121 - 0
bsp/lpc43xx/M0/applications/application.c

@@ -0,0 +1,121 @@
+/*
+ * File      : application.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2014, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2014-07-13     xiaonong     port for lpc43xx
+ */
+
+#include <rtthread.h>
+#include <board.h>
+#include <rtdevice.h>
+#include "drv_led.h"
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+#include <shell.h>
+#endif
+
+#ifdef RT_USING_LOGTRACE
+#include <log_trace.h>
+#endif
+
+#ifdef RT_USING_VBUS
+#include <vbus.h>
+#endif
+
+/* thread phase init */
+void rt_init_thread_entry(void *parameter)
+{
+#ifdef RT_USING_LOGTRACE
+    log_trace_init();
+    log_trace_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+#ifdef RT_USING_FINSH
+    /* initialize finsh */
+    finsh_system_init();
+    finsh_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+#ifdef RT_USING_VBUS
+    rt_vbus_do_init();
+#endif
+}
+
+/*the led thread*/
+ALIGN(RT_ALIGN_SIZE)
+static rt_uint8_t led_stack[1024];
+static struct rt_thread led_thread;
+static void led_thread_entry(void *parameter)
+{
+    rt_device_t led_dev;
+    rt_device_t vbus_dev;
+    rt_err_t err;
+
+    rt_led_hw_init();
+
+    led_dev = rt_device_find("led");
+    if (led_dev == RT_NULL)
+    {
+        rt_kprintf("can not find the led device\n");
+        return;
+    }
+
+    vbus_dev = rt_device_find("vecho");
+    if (vbus_dev == RT_NULL)
+    {
+        rt_kprintf("can not find the vbus device\n");
+        return;
+    }
+
+    err = rt_device_open(vbus_dev, RT_DEVICE_OFLAG_RDWR);
+    if (err != RT_EOK)
+    {
+        rt_kprintf("open vbus failed: %d\n", err);
+        return;
+    }
+
+    while (1)
+    {
+        rt_uint8_t led_value;
+        int len;
+
+        len = rt_device_read(vbus_dev, 0, &led_value, sizeof(led_value));
+        if (len <= 0)
+        {
+            rt_kprintf("vbus read err: %d, %d\n", len, rt_get_errno());
+        }
+
+        led_dev->write(led_dev, 1, &led_value, sizeof(led_value));
+    }
+}
+
+int rt_application_init(void)
+{
+    rt_thread_t tid;
+    rt_err_t result;
+    tid = rt_thread_create("init",
+                           rt_init_thread_entry, RT_NULL,
+                           2048, 3, 20);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid);
+
+    /* init led thread */
+    result = rt_thread_init(&led_thread, "led",
+                            led_thread_entry, RT_NULL,
+                            (rt_uint8_t *)&led_stack[0], sizeof(led_stack),
+                            20, 5);
+    if (result == RT_EOK)
+    {
+        rt_thread_startup(&led_thread);
+    }
+    return 0;
+}
+

+ 67 - 0
bsp/lpc43xx/M0/applications/board.c

@@ -0,0 +1,67 @@
+/*
+ * File      : board.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2014 RT-Thread Develop Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2009-01-05     Bernard      first implementation
+ * 2014-06-20     xiaonong     ported to LPC43xx
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "board.h"
+#include "drv_uart.h"
+
+
+/** M0 does not have SysTick so we have to use RIT timer for it... */
+void RIT_OR_WWDT_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    if (LPC_RITIMER->CTRL & 0x01)
+    {
+        rt_tick_increase();
+        LPC_RITIMER->CTRL |= 0x01;
+    }
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+extern void SystemCoreClockUpdate(void);
+
+/**
+ * This function will initial LPC43xx board.
+ */
+void rt_hw_board_init()
+{
+    SystemCoreClockUpdate();
+
+    /* Setup RIT timer. */
+    LPC_RITIMER->MASK     = 0;
+    LPC_RITIMER->COMPVAL  = SystemCoreClock / RT_TICK_PER_SECOND;
+    /* Enable auto-clear. */
+    LPC_RITIMER->CTRL    |= 1 << 1;
+    /* Reset the counter as the counter is enabled after reset. */
+    LPC_RITIMER->COUNTER  = 0;
+    NVIC_SetPriority(M0_RITIMER_OR_WWDT_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+    NVIC_EnableIRQ(M0_RITIMER_OR_WWDT_IRQn);
+
+    /* set pend exception priority */
+    NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+
+    /* init uart device */
+    rt_hw_uart_init();
+
+    /* setup the console device */
+    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+}
+

+ 59 - 0
bsp/lpc43xx/M0/applications/board.h

@@ -0,0 +1,59 @@
+/*
+ * File      : board.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2009, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2009-09-22     Bernard      add board.h to this bsp
+ * 2010-02-04     Magicoe      add board.h to LPC176x bsp
+ * 2013-12-18     Bernard      porting to LPC4088 bsp
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include "LPC43xx.h"
+#include <rtthread.h>
+
+/* disable SDRAM in default */
+#ifndef LPC_EXT_SDRAM
+#define LPC_EXT_SDRAM       0
+#endif
+
+// <RDTConfigurator URL="http://www.rt-thread.com/eclipse">
+
+// <integer name="LPC_EXT_SDRAM" description="Begin Address of External SDRAM" default="0xA0000000" />
+#define LPC_EXT_SDRAM_BEGIN    0xA0000000
+// <integer name="LPC_EXT_SDRAM_END" description="End Address of External SDRAM" default="0xA2000000" />
+#define LPC_EXT_SDRAM_END      0xA2000000
+
+// <bool name="RT_USING_UART0" description="Using UART0" default="true" />
+// <bool name="RT_USING_UART1" description="Using UART1" default="true" />
+//#define RT_USING_UART1
+// <bool name="RT_USING_UART2" description="Using UART2" default="true" />
+//#define RT_USING_UART2
+
+// </RDTConfigurator>
+
+#ifdef __CC_ARM
+extern int Image$$RW_IRAM2$$ZI$$Limit;
+#define HEAP_BEGIN  ((void *)&Image$$RW_IRAM2$$ZI$$Limit)
+#elif __ICCARM__
+#pragma section="HEAP"
+#define HEAP_BEGIN  (__segment_end("HEAP"))
+#else
+extern int __bss_end;
+#define HEAP_BEGIN  ((void *)&__bss_end)
+#endif
+#define HEAP_END    (void*)(0x10080000 + 0x8000)
+
+void rt_hw_board_init(void);
+int  rt_hw_board_heap_init(void);
+int rt_vbus_do_init(void);
+
+#endif

+ 0 - 0
bsp/lpc43xx/applications/startup.c → bsp/lpc43xx/M0/applications/startup.c


+ 13 - 0
bsp/lpc43xx/M0/applications/vbus_conf.h

@@ -0,0 +1,13 @@
+#ifndef __VBUS_CONF_H__
+#define __VBUS_CONF_H__
+
+/* Number of blocks in VBus. The total size of VBus is
+ * RT_VMM_RB_BLK_NR * 64byte * 2. */
+#define RT_VMM_RB_BLK_NR     20
+
+/* We don't use the IRQ number to trigger IRQ in this BSP. */
+#define RT_VBUS_GUEST_VIRQ    0
+#define RT_VBUS_HOST_VIRQ     0
+
+#endif /* end of include guard: __VBUS_CONF_H__ */
+

+ 86 - 0
bsp/lpc43xx/M0/applications/vbus_drv.c

@@ -0,0 +1,86 @@
+/*
+ * VMM Bus Driver
+ *
+ * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2015-01-07     Grissiom     add comment
+ */
+
+#include <rtthread.h>
+
+#ifdef RT_USING_VBUS
+#include <rtdevice.h>
+#include <vbus.h>
+#include <board.h>
+
+struct rt_vbus_ring rt_vbus_rings[2] SECTION("vbus_ring");
+
+int rt_vbus_do_init(void)
+{
+    return rt_vbus_init(&rt_vbus_rings[1], &rt_vbus_rings[0]);
+}
+INIT_COMPONENT_EXPORT(rt_vbus_do_init);
+
+int rt_vbus_hw_init(void)
+{
+    NVIC_ClearPendingIRQ(M0_M4CORE_IRQn);
+    NVIC_EnableIRQ(M0_M4CORE_IRQn);
+    return 0;
+}
+
+void M4CORE_IRQHandler(void)
+{
+    LPC_CREG->M4TXEVENT = 0;
+    rt_vbus_isr(M0_M4CORE_IRQn, RT_NULL);
+}
+
+int rt_vbus_hw_eoi(int irqnr, void *param)
+{
+    /* Nothing to do here as we cleared the interrupt in IRQHandler. */
+    return 0;
+}
+
+struct rt_vbus_dev rt_vbus_chn_devx[] = {
+    {
+        .req =
+        {
+            .prio = 30,
+            .name = "vecho",
+            .is_server = 0,
+            .recv_wm.low = RT_VMM_RB_BLK_NR / 3,
+            .recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
+            .post_wm.low = RT_VMM_RB_BLK_NR / 3,
+            .post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
+        }
+    },
+    {
+        .req =
+        {
+            .name = RT_NULL,
+        }
+    },
+};
+
+#endif /* RT_USING_VBUS */
+

+ 53 - 0
bsp/lpc43xx/M0/applications/vbus_hw.h

@@ -0,0 +1,53 @@
+/*
+ * VMM Bus
+ *
+ * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2015-01-07     Grissiom     init commit
+ */
+
+#include <rtthread.h>
+#include <board.h>
+
+rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr)
+{
+    __SEV();
+}
+
+/* Read memory barrier. */
+rt_inline void rt_vbus_smp_rmb(void)
+{
+    __DMB();
+}
+
+/* Write memory barrier. */
+rt_inline void rt_vbus_smp_wmb(void)
+{
+    __DSB();
+}
+
+/* General memory barrier. */
+rt_inline void rt_vbus_smp_mb(void)
+{
+    __DSB();
+}

+ 5 - 2
bsp/lpc43xx/M0/rtconfig.h

@@ -24,6 +24,7 @@
 #define RT_DEBUG
 // <bool name="RT_DEBUG_INIT" description="debug init enable" default=0 />
 #define RT_DEBUG_INIT   0
+//#define RT_DEBUG_SCHEDULER             1
 // <bool name="RT_THREAD_DEBUG" description="Thread debug enable" default="false" />
 // #define RT_THREAD_DEBUG
 // <bool name="RT_USING_OVERFLOW_CHECK" description="Thread stack over flow detect" default="true" />
@@ -33,7 +34,7 @@
 // <bool name="RT_USING_HOOK" description="Using hook functions" default="true" />
 #define RT_USING_HOOK
 // <section name="RT_USING_TIMER_SOFT" description="Using software timer which will start a thread to handle soft-timer" default="true" >
-#define RT_USING_TIMER_SOFT
+//#define RT_USING_TIMER_SOFT
 // <integer name="RT_TIMER_THREAD_PRIO" description="The priority level of timer thread" default="4" />
 #define RT_TIMER_THREAD_PRIO    4
 // <integer name="RT_TIMER_THREAD_STACK_SIZE" description="The stack size of timer thread" default="512" />
@@ -96,6 +97,7 @@
 #define RT_CONSOLEBUF_SIZE  128
 // <string name="RT_CONSOLE_DEVICE_NAME" description="The device name for console" default="uart" />
 #define RT_CONSOLE_DEVICE_NAME  "uart0"
+#define RT_USING_UART0
 // </section>
 
 // <bool name="RT_USING_COMPONENTS_INIT" description="Using RT-Thread components initialization" default="true" />
@@ -222,7 +224,8 @@
 #define RT_LWIP_MSKADDR3 0
 // </section>
 
-
+#define RT_USING_VBUS
+#define RT_USING_LOGTRACE
 
 // </RDTConfigurator>
 

+ 11 - 14
bsp/lpc43xx/M0/rtconfig.py

@@ -2,15 +2,11 @@ import os
 
 # core to be use
 USE_CORE = 'CORE_M0'
-#USE_CORE = 'CORE_M4'
 
 # toolchains options
 ARCH='arm'
 
-if USE_CORE == 'CORE_M4':
-    CPU = 'cortex-m4'
-else:
-    CPU = 'cortex-m0'
+CPU = 'cortex-m0'
 
 CROSS_TOOL='keil'
 
@@ -35,7 +31,7 @@ if os.getenv('RTT_EXEC_PATH'):
         EXEC_PATH = os.getenv('RTT_EXEC_PATH')
 
 #
-BUILD = 'release'
+BUILD = 'debug'
 
 if PLATFORM == 'gcc':
     # toolchains
@@ -48,23 +44,24 @@ if PLATFORM == 'gcc':
     SIZE = PREFIX + 'size'
     OBJDUMP = PREFIX + 'objdump'
     OBJCPY = PREFIX + 'objcopy'
-    DEVICE = ' -mcpu=' + CPU + ' -mthumb -ffunction-sections -fdata-sections'
-    if USE_CORE == 'CORE_M4':
-        DEVICE += ' -mfpu=fpv4-sp-d16 -mfloat-abi=softfp'
-    CFLAGS = DEVICE 
+    DEVICE = ' -mthumb -mcpu=cortex-m0 -ffunction-sections -fdata-sections -Wall'
+    CFLAGS = DEVICE
     AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb '
-    LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-lpc43xx.map,-cref,-u,Reset_Handler -T rtthread-lpc43xx_spifi.ld'
+    LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-lpc43xx.map,-cref,-u,Reset_Handler -T rtthread-lpc43xx.ld'
 
     CPATH = ''
     LPATH = ''
 
+    CFLAGS += ' -gdwarf-2'
+    AFLAGS += ' -gdwarf-2'
     if BUILD == 'debug':
-        CFLAGS += ' -O0 -gdwarf-2'
-        AFLAGS += ' -gdwarf-2'
+        CFLAGS += ' -O0'
     else:
         CFLAGS += ' -O2'
 
-    POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
+    POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\
+                  SIZE + ' $TARGET \n' +\
+                  '../bin2C.py rtthread.bin ../M4/applications/M0_CODE.h'
 
 elif PLATFORM == 'armcc':
     # toolchains

+ 139 - 0
bsp/lpc43xx/M0/rtthread-lpc43xx.ld

@@ -0,0 +1,139 @@
+/*
+ * linker script for LPC43xx SPIFI (4Mb NorFlash, 32kB SRAM ) with GNU ld
+ * yiyue.fang 2012-04-14
+ */
+
+/* Program Entry, set to mark it as "used" and avoid gc */
+MEMORY
+{
+    CODE (rx) : ORIGIN = 0x1B000000, LENGTH = 0x00080000
+    DATA (rw) : ORIGIN = 0x10080000, LENGTH = 0x00008000
+    AHBRAM (rw) : ORIGIN = 0x20000000, LENGTH = 0x00010000
+}
+ENTRY(Reset_Handler)
+_system_stack_size = 0x200;
+
+SECTIONS
+{
+    .text :
+    {
+        . = ALIGN(4);
+        KEEP(*(.interrupt_vector))      /* Startup code */
+        . = ALIGN(4);
+        *(.text)                        /* remaining code */
+        *(.text.*)                      /* remaining code */
+        *(.rodata)                      /* read-only data (constants) */
+        *(.rodata*)
+        *(.glue_7)
+        *(.glue_7t)
+        *(.gnu.linkonce.t*)
+
+        /* section information for finsh shell */
+        . = ALIGN(4);
+        __fsymtab_start = .;
+        KEEP(*(FSymTab))
+        __fsymtab_end = .;
+        . = ALIGN(4);
+        __vsymtab_start = .;
+        KEEP(*(VSymTab))
+        __vsymtab_end = .;
+        . = ALIGN(4);
+
+        . = ALIGN(4);
+        _etext = .;
+    } > CODE = 0
+
+    /* .ARM.exidx is sorted, so has to go in its own output section.  */
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+
+        /* This is used by the startup in order to initialize the .data secion */
+        _sidata = .;
+    } > CODE
+    __exidx_end = .;
+
+    /* .data section which is used for initialized data */
+
+    .data : AT (_sidata)
+    {
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .data secion */
+        _sdata = . ;
+
+        *(.data)
+        *(.data.*)
+        *(.gnu.linkonce.d*)
+
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .data secion */
+        _edata = . ;
+    } >DATA
+
+    .stack :
+    {
+        . = . + _system_stack_size;
+        . = ALIGN(4);
+        _estack = .;
+    } >DATA
+
+    __bss_start = .;
+    .bss :
+    {
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .bss secion */
+        _sbss = .;
+
+        *(.bss)
+        *(.bss.*)
+        *(COMMON)
+
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .bss secion */
+        _ebss = . ;
+        *(.bss.init)
+    } > DATA
+    __bss_end = .;
+
+    .vbus_ring (NOLOAD) :
+    {
+        *(vbus_ring)
+    } > AHBRAM
+
+    _end = .;
+
+    /* Stabs debugging sections.  */
+    .stab          0 : { *(.stab) }
+    .stabstr       0 : { *(.stabstr) }
+    .stab.excl     0 : { *(.stab.excl) }
+    .stab.exclstr  0 : { *(.stab.exclstr) }
+    .stab.index    0 : { *(.stab.index) }
+    .stab.indexstr 0 : { *(.stab.indexstr) }
+    .comment       0 : { *(.comment) }
+    /* DWARF debug sections.
+     * Symbols in the DWARF debugging sections are relative to the beginning
+     * of the section so we begin them at 0.  */
+    /* DWARF 1 */
+    .debug          0 : { *(.debug) }
+    .line           0 : { *(.line) }
+    /* GNU DWARF 1 extensions */
+    .debug_srcinfo  0 : { *(.debug_srcinfo) }
+    .debug_sfnames  0 : { *(.debug_sfnames) }
+    /* DWARF 1.1 and DWARF 2 */
+    .debug_aranges  0 : { *(.debug_aranges) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+    /* DWARF 2 */
+    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+    .debug_abbrev   0 : { *(.debug_abbrev) }
+    .debug_line     0 : { *(.debug_line) }
+    .debug_frame    0 : { *(.debug_frame) }
+    .debug_str      0 : { *(.debug_str) }
+    .debug_loc      0 : { *(.debug_loc) }
+    .debug_macinfo  0 : { *(.debug_macinfo) }
+    /* SGI/MIPS DWARF 2 extensions */
+    .debug_weaknames 0 : { *(.debug_weaknames) }
+    .debug_funcnames 0 : { *(.debug_funcnames) }
+    .debug_typenames 0 : { *(.debug_typenames) }
+    .debug_varnames  0 : { *(.debug_varnames) }
+}

+ 18 - 0
bsp/lpc43xx/M0/rtthread_lpc43xx.sct

@@ -0,0 +1,18 @@
+; *************************************************************
+; *** Scatter-Loading Description File generated by uVision ***
+; *************************************************************
+
+LR_IROM2 0x1B000000 0x00080000  {    ; load region size_region
+  ER_IROM2 0x1B000000 0x00080000  {  ; load address = execution address
+   *.o (RESET, +First)
+   *(InRoot$$Sections)
+   .ANY (+RO)
+  }
+  RW_IRAM2 0x10080000 0x00008000  {  ; RW data
+   .ANY (+RW +ZI)
+  }
+  RW_AHBRAM 0x20000000 0x00010000  {  ; RW data
+   * (vbus_ring)
+  }
+}
+

+ 20 - 402
bsp/lpc43xx/M0/template.uvproj

@@ -12,13 +12,13 @@
       <ToolsetName>ARM-ADS</ToolsetName>
       <TargetOption>
         <TargetCommonOption>
-          <Device>LPC4357</Device>
-          <Vendor>NXP (founded by Philips)</Vendor>
-          <Cpu>IRAM(0x10000000-0x10007FFF) IRAM2(0x20000000-0x2000FFFF) IROM(0x1A000000-0x1A07FFFF) IROM2(0x1B000000-0x1B07FFFF) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2</Cpu>
+          <Device>LPC4357 CM0</Device>
+          <Vendor>NXP</Vendor>
+          <Cpu>CLOCK(12000000) CPUTYPE("Cortex-M0")</Cpu>
           <FlashUtilSpec></FlashUtilSpec>
-          <StartupFile>"STARTUP\NXP\LPC43xx\startup_LPC43xx.s" ("NXP LPC43xx Startup Code")</StartupFile>
-          <FlashDriverDll>UL2CM3(-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000)</FlashDriverDll>
-          <DeviceId>6414</DeviceId>
+          <StartupFile>"STARTUP\NXP\LPC43xx\startup_LPC43xx_M0.s" ("NXP LPC43xx CM0 Startup Code")</StartupFile>
+          <FlashDriverDll>UL2CM3(-O910 -S8 -C1 -FO7 -FD10000000 -FC800 -FN0)</FlashDriverDll>
+          <DeviceId>6917</DeviceId>
           <RegisterFile>LPC43xx.H</RegisterFile>
           <MemoryEnv></MemoryEnv>
           <Cmp></Cmp>
@@ -26,10 +26,11 @@
           <Linker></Linker>
           <OHString></OHString>
           <InfinionOptionDll></InfinionOptionDll>
-          <SLE66CMisc></SLE66CMisc>
+          <SLE66CMisc>-DCORE_M0</SLE66CMisc>
           <SLE66AMisc></SLE66AMisc>
           <SLE66LinkerMisc></SLE66LinkerMisc>
           <SFDFile>SFD\NXP\LPC43xx\LPC43xx.SFR</SFDFile>
+          <bCustSvd>0</bCustSvd>
           <UseEnv>0</UseEnv>
           <BinPath></BinPath>
           <IncludePath></IncludePath>
@@ -73,10 +74,10 @@
             <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
           </BeforeMake>
           <AfterMake>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
+            <RunUserProg1>1</RunUserProg1>
+            <RunUserProg2>1</RunUserProg2>
+            <UserProg1Name>fromelf --bin !L --output rtthread.bin</UserProg1Name>
+            <UserProg2Name>C:\Python27\python.exe ..\bin2C.py rtthread.bin ..\M4\applications\M0_CODE.h</UserProg2Name>
             <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
             <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
           </AfterMake>
@@ -208,10 +209,10 @@
             <hadIRAM>1</hadIRAM>
             <hadXRAM>0</hadXRAM>
             <uocXRam>0</uocXRam>
-            <RvdsVP>1</RvdsVP>
+            <RvdsVP>2</RvdsVP>
             <hadIRAM2>1</hadIRAM2>
             <hadIROM2>1</hadIROM2>
-            <StupSel>1</StupSel>
+            <StupSel>16</StupSel>
             <useUlib>1</useUlib>
             <EndSel>0</EndSel>
             <uLtcg>0</uLtcg>
@@ -224,11 +225,11 @@
             <NoZi3>0</NoZi3>
             <NoZi4>0</NoZi4>
             <NoZi5>0</NoZi5>
-            <Ro1Chk>1</Ro1Chk>
+            <Ro1Chk>0</Ro1Chk>
             <Ro2Chk>0</Ro2Chk>
             <Ro3Chk>0</Ro3Chk>
             <Ir1Chk>0</Ir1Chk>
-            <Ir2Chk>0</Ir2Chk>
+            <Ir2Chk>1</Ir2Chk>
             <Ra1Chk>0</Ra1Chk>
             <Ra2Chk>0</Ra2Chk>
             <Ra3Chk>0</Ra3Chk>
@@ -338,7 +339,7 @@
             <Optim>1</Optim>
             <oTime>0</oTime>
             <SplitLS>0</SplitLS>
-            <OneElfS>0</OneElfS>
+            <OneElfS>1</OneElfS>
             <Strict>0</Strict>
             <EnumInt>0</EnumInt>
             <PlainCh>0</PlainCh>
@@ -371,7 +372,7 @@
             </VariousControls>
           </Aads>
           <LDads>
-            <umfTarg>1</umfTarg>
+            <umfTarg>0</umfTarg>
             <Ropi>0</Ropi>
             <Rwpi>0</Rwpi>
             <noStLib>0</noStLib>
@@ -379,390 +380,8 @@
             <useFile>0</useFile>
             <TextAddressRange>0x14000000</TextAddressRange>
             <DataAddressRange>0x10000000</DataAddressRange>
-            <ScatterFile></ScatterFile>
-            <IncludeLibs></IncludeLibs>
-            <IncludeLibsPath></IncludeLibsPath>
-            <Misc></Misc>
-            <LinkerInputFile></LinkerInputFile>
-            <DisabledWarnings></DisabledWarnings>
-          </LDads>
-        </TargetArmAds>
-      </TargetOption>
-    </Target>
-    <Target>
-      <TargetName>LPC43xx RAM</TargetName>
-      <ToolsetNumber>0x4</ToolsetNumber>
-      <ToolsetName>ARM-ADS</ToolsetName>
-      <TargetOption>
-        <TargetCommonOption>
-          <Device>LPC4357</Device>
-          <Vendor>NXP (founded by Philips)</Vendor>
-          <Cpu>IRAM(0x10000000-0x10007FFF) IRAM2(0x20000000-0x2000FFFF) IROM(0x1A000000-0x1A07FFFF) IROM2(0x1B000000-0x1B07FFFF) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2</Cpu>
-          <FlashUtilSpec></FlashUtilSpec>
-          <StartupFile>"STARTUP\NXP\LPC43xx\startup_LPC43xx.s" ("NXP LPC43xx Startup Code")</StartupFile>
-          <FlashDriverDll>UL2CM3(-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000)</FlashDriverDll>
-          <DeviceId>6414</DeviceId>
-          <RegisterFile>LPC43xx.H</RegisterFile>
-          <MemoryEnv></MemoryEnv>
-          <Cmp></Cmp>
-          <Asm></Asm>
-          <Linker></Linker>
-          <OHString></OHString>
-          <InfinionOptionDll></InfinionOptionDll>
-          <SLE66CMisc></SLE66CMisc>
-          <SLE66AMisc></SLE66AMisc>
-          <SLE66LinkerMisc></SLE66LinkerMisc>
-          <SFDFile>SFD\NXP\LPC43xx\LPC43xx.SFR</SFDFile>
-          <UseEnv>0</UseEnv>
-          <BinPath></BinPath>
-          <IncludePath></IncludePath>
-          <LibPath></LibPath>
-          <RegisterFilePath>NXP\LPC43xx\</RegisterFilePath>
-          <DBRegisterFilePath>NXP\LPC43xx\</DBRegisterFilePath>
-          <TargetStatus>
-            <Error>0</Error>
-            <ExitCodeStop>0</ExitCodeStop>
-            <ButtonStop>0</ButtonStop>
-            <NotGenerated>0</NotGenerated>
-            <InvalidFlash>1</InvalidFlash>
-          </TargetStatus>
-          <OutputDirectory>.\build\</OutputDirectory>
-          <OutputName>rtthread_lpc43xx</OutputName>
-          <CreateExecutable>1</CreateExecutable>
-          <CreateLib>0</CreateLib>
-          <CreateHexFile>0</CreateHexFile>
-          <DebugInformation>1</DebugInformation>
-          <BrowseInformation>1</BrowseInformation>
-          <ListingPath>.\build\</ListingPath>
-          <HexFormatSelection>1</HexFormatSelection>
-          <Merge32K>0</Merge32K>
-          <CreateBatchFile>0</CreateBatchFile>
-          <BeforeCompile>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-            <nStopU1X>0</nStopU1X>
-            <nStopU2X>0</nStopU2X>
-          </BeforeCompile>
-          <BeforeMake>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-          </BeforeMake>
-          <AfterMake>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-          </AfterMake>
-          <SelectedForBatchBuild>0</SelectedForBatchBuild>
-          <SVCSIdString></SVCSIdString>
-        </TargetCommonOption>
-        <CommonProperty>
-          <UseCPPCompiler>0</UseCPPCompiler>
-          <RVCTCodeConst>0</RVCTCodeConst>
-          <RVCTZI>0</RVCTZI>
-          <RVCTOtherData>0</RVCTOtherData>
-          <ModuleSelection>0</ModuleSelection>
-          <IncludeInBuild>1</IncludeInBuild>
-          <AlwaysBuild>0</AlwaysBuild>
-          <GenerateAssemblyFile>0</GenerateAssemblyFile>
-          <AssembleAssemblyFile>0</AssembleAssemblyFile>
-          <PublicsOnly>0</PublicsOnly>
-          <StopOnExitCode>3</StopOnExitCode>
-          <CustomArgument></CustomArgument>
-          <IncludeLibraryModules></IncludeLibraryModules>
-        </CommonProperty>
-        <DllOption>
-          <SimDllName>SARMCM3.DLL</SimDllName>
-          <SimDllArguments>-MPU</SimDllArguments>
-          <SimDlgDll>DCM.DLL</SimDlgDll>
-          <SimDlgDllArguments>-pCM4</SimDlgDllArguments>
-          <TargetDllName>SARMCM3.DLL</TargetDllName>
-          <TargetDllArguments>-MPU</TargetDllArguments>
-          <TargetDlgDll>TCM.DLL</TargetDlgDll>
-          <TargetDlgDllArguments>-pCM4</TargetDlgDllArguments>
-        </DllOption>
-        <DebugOption>
-          <OPTHX>
-            <HexSelection>1</HexSelection>
-            <HexRangeLowAddress>0</HexRangeLowAddress>
-            <HexRangeHighAddress>0</HexRangeHighAddress>
-            <HexOffset>0</HexOffset>
-            <Oh166RecLen>16</Oh166RecLen>
-          </OPTHX>
-          <Simulator>
-            <UseSimulator>0</UseSimulator>
-            <LoadApplicationAtStartup>1</LoadApplicationAtStartup>
-            <RunToMain>1</RunToMain>
-            <RestoreBreakpoints>1</RestoreBreakpoints>
-            <RestoreWatchpoints>1</RestoreWatchpoints>
-            <RestoreMemoryDisplay>1</RestoreMemoryDisplay>
-            <RestoreFunctions>1</RestoreFunctions>
-            <RestoreToolbox>1</RestoreToolbox>
-            <LimitSpeedToRealTime>0</LimitSpeedToRealTime>
-          </Simulator>
-          <Target>
-            <UseTarget>1</UseTarget>
-            <LoadApplicationAtStartup>0</LoadApplicationAtStartup>
-            <RunToMain>0</RunToMain>
-            <RestoreBreakpoints>1</RestoreBreakpoints>
-            <RestoreWatchpoints>1</RestoreWatchpoints>
-            <RestoreMemoryDisplay>0</RestoreMemoryDisplay>
-            <RestoreFunctions>0</RestoreFunctions>
-            <RestoreToolbox>1</RestoreToolbox>
-            <RestoreTracepoints>0</RestoreTracepoints>
-          </Target>
-          <RunDebugAfterBuild>0</RunDebugAfterBuild>
-          <TargetSelection>1</TargetSelection>
-          <SimDlls>
-            <CpuDll></CpuDll>
-            <CpuDllArguments></CpuDllArguments>
-            <PeripheralDll></PeripheralDll>
-            <PeripheralDllArguments></PeripheralDllArguments>
-            <InitializationFile></InitializationFile>
-          </SimDlls>
-          <TargetDlls>
-            <CpuDll></CpuDll>
-            <CpuDllArguments></CpuDllArguments>
-            <PeripheralDll></PeripheralDll>
-            <PeripheralDllArguments></PeripheralDllArguments>
-            <InitializationFile>.\Dbg_RAM.ini</InitializationFile>
-            <Driver>BIN\UL2CM3.DLL</Driver>
-          </TargetDlls>
-        </DebugOption>
-        <Utilities>
-          <Flash1>
-            <UseTargetDll>1</UseTargetDll>
-            <UseExternalTool>1</UseExternalTool>
-            <RunIndependent>0</RunIndependent>
-            <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
-            <Capability>1</Capability>
-            <DriverSelection>4096</DriverSelection>
-          </Flash1>
-          <bUseTDR>1</bUseTDR>
-          <Flash2>BIN\UL2CM3.DLL</Flash2>
-          <Flash3>"" ()</Flash3>
-          <Flash4></Flash4>
-        </Utilities>
-        <TargetArmAds>
-          <ArmAdsMisc>
-            <GenerateListings>0</GenerateListings>
-            <asHll>1</asHll>
-            <asAsm>1</asAsm>
-            <asMacX>1</asMacX>
-            <asSyms>1</asSyms>
-            <asFals>1</asFals>
-            <asDbgD>1</asDbgD>
-            <asForm>1</asForm>
-            <ldLst>0</ldLst>
-            <ldmm>1</ldmm>
-            <ldXref>1</ldXref>
-            <BigEnd>0</BigEnd>
-            <AdsALst>1</AdsALst>
-            <AdsACrf>1</AdsACrf>
-            <AdsANop>0</AdsANop>
-            <AdsANot>0</AdsANot>
-            <AdsLLst>1</AdsLLst>
-            <AdsLmap>1</AdsLmap>
-            <AdsLcgr>1</AdsLcgr>
-            <AdsLsym>1</AdsLsym>
-            <AdsLszi>1</AdsLszi>
-            <AdsLtoi>1</AdsLtoi>
-            <AdsLsun>1</AdsLsun>
-            <AdsLven>1</AdsLven>
-            <AdsLsxf>1</AdsLsxf>
-            <RvctClst>0</RvctClst>
-            <GenPPlst>0</GenPPlst>
-            <AdsCpuType>"Cortex-M4"</AdsCpuType>
-            <RvctDeviceName></RvctDeviceName>
-            <mOS>0</mOS>
-            <uocRom>0</uocRom>
-            <uocRam>0</uocRam>
-            <hadIROM>1</hadIROM>
-            <hadIRAM>1</hadIRAM>
-            <hadXRAM>0</hadXRAM>
-            <uocXRam>0</uocXRam>
-            <RvdsVP>1</RvdsVP>
-            <hadIRAM2>1</hadIRAM2>
-            <hadIROM2>1</hadIROM2>
-            <StupSel>8</StupSel>
-            <useUlib>1</useUlib>
-            <EndSel>0</EndSel>
-            <uLtcg>0</uLtcg>
-            <RoSelD>3</RoSelD>
-            <RwSelD>3</RwSelD>
-            <CodeSel>0</CodeSel>
-            <OptFeed>0</OptFeed>
-            <NoZi1>0</NoZi1>
-            <NoZi2>0</NoZi2>
-            <NoZi3>0</NoZi3>
-            <NoZi4>0</NoZi4>
-            <NoZi5>0</NoZi5>
-            <Ro1Chk>0</Ro1Chk>
-            <Ro2Chk>0</Ro2Chk>
-            <Ro3Chk>0</Ro3Chk>
-            <Ir1Chk>1</Ir1Chk>
-            <Ir2Chk>0</Ir2Chk>
-            <Ra1Chk>0</Ra1Chk>
-            <Ra2Chk>0</Ra2Chk>
-            <Ra3Chk>0</Ra3Chk>
-            <Im1Chk>0</Im1Chk>
-            <Im2Chk>1</Im2Chk>
-            <OnChipMemories>
-              <Ocm1>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm1>
-              <Ocm2>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm2>
-              <Ocm3>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm3>
-              <Ocm4>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm4>
-              <Ocm5>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm5>
-              <Ocm6>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm6>
-              <IRAM>
-                <Type>0</Type>
-                <StartAddress>0x10000000</StartAddress>
-                <Size>0x8000</Size>
-              </IRAM>
-              <IROM>
-                <Type>1</Type>
-                <StartAddress>0x1a000000</StartAddress>
-                <Size>0x80000</Size>
-              </IROM>
-              <XRAM>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </XRAM>
-              <OCR_RVCT1>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT1>
-              <OCR_RVCT2>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT2>
-              <OCR_RVCT3>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT3>
-              <OCR_RVCT4>
-                <Type>1</Type>
-                <StartAddress>0x1a000000</StartAddress>
-                <Size>0x80000</Size>
-              </OCR_RVCT4>
-              <OCR_RVCT5>
-                <Type>1</Type>
-                <StartAddress>0x1b000000</StartAddress>
-                <Size>0x80000</Size>
-              </OCR_RVCT5>
-              <OCR_RVCT6>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT6>
-              <OCR_RVCT7>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT7>
-              <OCR_RVCT8>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT8>
-              <OCR_RVCT9>
-                <Type>0</Type>
-                <StartAddress>0x10000000</StartAddress>
-                <Size>0x8000</Size>
-              </OCR_RVCT9>
-              <OCR_RVCT10>
-                <Type>0</Type>
-                <StartAddress>0x20000000</StartAddress>
-                <Size>0x10000</Size>
-              </OCR_RVCT10>
-            </OnChipMemories>
-            <RvctStartVector></RvctStartVector>
-          </ArmAdsMisc>
-          <Cads>
-            <interw>1</interw>
-            <Optim>1</Optim>
-            <oTime>0</oTime>
-            <SplitLS>0</SplitLS>
-            <OneElfS>0</OneElfS>
-            <Strict>0</Strict>
-            <EnumInt>0</EnumInt>
-            <PlainCh>0</PlainCh>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <wLevel>0</wLevel>
-            <uThumb>0</uThumb>
-            <uSurpInc>0</uSurpInc>
-            <VariousControls>
-              <MiscControls></MiscControls>
-              <Define></Define>
-              <Undefine></Undefine>
-              <IncludePath></IncludePath>
-            </VariousControls>
-          </Cads>
-          <Aads>
-            <interw>1</interw>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <thumb>0</thumb>
-            <SplitLS>0</SplitLS>
-            <SwStkChk>0</SwStkChk>
-            <NoWarn>0</NoWarn>
-            <uSurpInc>0</uSurpInc>
-            <VariousControls>
-              <MiscControls></MiscControls>
-              <Define>NO_CRP</Define>
-              <Undefine></Undefine>
-              <IncludePath></IncludePath>
-            </VariousControls>
-          </Aads>
-          <LDads>
-            <umfTarg>1</umfTarg>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <noStLib>0</noStLib>
-            <RepFail>1</RepFail>
-            <useFile>0</useFile>
-            <TextAddressRange>0x10000000</TextAddressRange>
-            <DataAddressRange>0x20000000</DataAddressRange>
-            <ScatterFile></ScatterFile>
+            <pXoBase></pXoBase>
+            <ScatterFile>.\rtthread_lpc43xx.sct</ScatterFile>
             <IncludeLibs></IncludeLibs>
             <IncludeLibsPath></IncludeLibsPath>
             <Misc></Misc>
@@ -773,5 +392,4 @@
       </TargetOption>
     </Target>
   </Targets>
-
 </Project>

+ 8 - 0
bsp/lpc43xx/M0/vbus_local_conf.h

@@ -0,0 +1,8 @@
+#ifndef __VBUS_LOCAL_CONF_H__
+#define __VBUS_LOCAL_CONF_H__
+
+#define RT_VBUS_USING_FLOW_CONTROL
+
+#define RT_VBUS_USING_TESTS
+
+#endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */

+ 10 - 6
bsp/lpc43xx/M4/SConscript

@@ -2,12 +2,16 @@ from building import *
 
 cwd  = GetCurrentDir()
 objs = []
-list = os.listdir(os.path.join(cwd, '..'))
 
-for d in list:
-    if (d != 'M4' and d != 'M0'):
-        path = os.path.join(cwd, '..', d)
-        if os.path.isfile(os.path.join(path, 'SConscript')):
-            objs = objs + SConscript(os.path.join(path, 'SConscript'))
+for d in os.listdir(os.path.join(cwd, '..')):
+    if d not in ('M0', 'M4'):
+        path = os.path.join('..', d, 'SConscript')
+        if os.path.isfile(os.path.join(cwd, path)):
+            objs = objs + SConscript(os.path.join(cwd, path))
+
+for d in os.listdir(cwd):
+    p = os.path.join(d, 'SConscript');
+    if os.path.isfile(os.path.join(cwd, p)):
+        objs = objs + SConscript(p)
 
 Return('objs')

+ 27 - 2
bsp/lpc43xx/M4/SConstruct

@@ -5,12 +5,12 @@ import rtconfig
 if os.getenv('RTT_ROOT'):
     RTT_ROOT = os.getenv('RTT_ROOT')
 else:
-    RTT_ROOT = os.path.join(Dir('#').get_abspath(), '..', '..', 'rt-thread')
+    RTT_ROOT = os.path.join(Dir('#').get_abspath(), '..', '..', '..')
 
 sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
 from building import *
 
-TARGET = 'rtthread-lpc40xx.' + rtconfig.TARGET_EXT
+TARGET = 'build/rtthread_lpc43xx.' + rtconfig.TARGET_EXT
 
 env = Environment(tools = ['mingw'],
     AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
@@ -25,5 +25,30 @@ Export('rtconfig')
 # prepare building environment
 objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
 
+if rtconfig.CROSS_TOOL == 'gcc':
+    print 'build M0 code first'
+    if sys.platform.startswith('linux'):
+        import glob
+        ocwd = os.getcwdu()
+        os.chdir('../M0')
+        res = os.system('scons')
+        if res:
+            print 'build M0 exit with code %d\n' % res
+            sys.exit(res)
+        os.chdir(ocwd)
+        res = os.system('cd ../Libraries/; find -name \*.o -exec rm {} \;')
+        os.chdir(ocwd)
+    else:
+        # Assume Windows.
+        ocwd = os.getcwdu()
+        os.chdir('..\M0')
+        os.system('scons.bat')
+        os.chdir(ocwd)
+
+    # Remove the .o for M0 left on the drivers dir.
+    for i in glob.glob(GetCurrentDir() + '/../drivers/*.o'):
+        print 'RM %s' % i
+        os.unlink(i)
+
 # do building 
 DoBuilding(TARGET, objs)

+ 13 - 0
bsp/lpc43xx/M4/applications/SConscript

@@ -0,0 +1,13 @@
+Import('RTT_ROOT')
+Import('rtconfig')
+from building import *
+
+cwd     = os.path.join(str(Dir('#')), 'applications')
+src	= Glob('*.c')
+CPPPATH = [cwd, str(Dir('#'))]
+
+group = DefineGroup('Applications', src,
+        depend = [''], CPPPATH = CPPPATH,
+        CPPDEFINES = ['BOOT_PROCESSOR'])
+
+Return('group')

+ 156 - 0
bsp/lpc43xx/M4/applications/application.c

@@ -0,0 +1,156 @@
+/*
+ * File      : application.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2014, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2014-07-13     xiaonong     port for lpc43xx
+ */
+
+#include <rtthread.h>
+#include <board.h>
+#include <rtdevice.h>
+#include "drv_led.h"
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+#include <shell.h>
+#endif
+
+#ifdef RT_USING_LOGTRACE
+#include <log_trace.h>
+#endif
+
+#ifdef RT_USING_VBUS
+#include <vbus.h>
+#endif
+
+static const unsigned char _M0_CODE[] SECTION("M0_CODE") = {
+#include "M0_CODE.h"
+};
+
+static void _boot_M0(void)
+{
+    volatile uint32_t u32REG,  u32Val;
+
+    LPC_CREG->M0APPMEMMAP = (uint32_t)&_M0_CODE[0];
+
+    // Release Slave from reset,  first read status 
+    u32REG = LPC_RGU->RESET_ACTIVE_STATUS1;
+
+    // If the M0 is being held in reset,  release it... 
+    // 1 = no reset,  0 = reset
+    while(!(u32REG & (1u << 24)))
+    {
+        u32Val = (~(u32REG) & (~(1 << 24)));
+        LPC_RGU->RESET_CTRL1 = u32Val;
+        u32REG = LPC_RGU->RESET_ACTIVE_STATUS1;
+    }
+
+    rt_kprintf("M0 boot to %p\n", &_M0_CODE[0]);
+}
+
+/* thread phase init */
+void rt_init_thread_entry(void *parameter)
+{
+    /*
+     *register unsigned int _msp __asm("msp");
+     *register unsigned int _psp __asm("psp");
+     *rt_kprintf("msp@ %p, psp@ %p\n", _msp, _psp);
+     */
+#ifdef RT_USING_LOGTRACE
+    log_trace_init();
+    log_trace_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+#ifdef RT_USING_FINSH
+    /* initialize finsh */
+    finsh_system_init();
+    finsh_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+#ifdef RT_USING_VBUS
+    rt_vbus_do_init();
+#endif
+
+    _boot_M0();
+}
+
+/*the led thread*/
+ALIGN(RT_ALIGN_SIZE)
+static rt_uint8_t led_stack[ 512 ];
+static struct rt_thread led_thread;
+static void led_thread_entry(void *parameter)
+{
+    rt_uint8_t led_value;
+    rt_device_t led_dev;
+    rt_device_t vbus_dev;
+    rt_err_t err;
+
+    rt_led_hw_init();
+
+    led_dev = rt_device_find("led");
+    if (led_dev == RT_NULL)
+    {
+        rt_kprintf("can not find the led device\n");
+        return;
+    }
+
+    vbus_dev = rt_device_find("vecho");
+    if (vbus_dev == RT_NULL)
+    {
+        rt_kprintf("can not find the vbus device\n");
+        return;
+    }
+
+    err = rt_device_open(vbus_dev, RT_DEVICE_OFLAG_RDWR);
+    if (err != RT_EOK)
+    {
+        rt_kprintf("open vbus failed: %d\n", err);
+        return;
+    }
+
+    led_value = 0;
+    while (1)
+    {
+        int len;
+
+        led_dev->write(led_dev, 0, &led_value, sizeof(led_value));
+
+        led_value = !led_value;
+        len = rt_device_write(vbus_dev, 0, &led_value, sizeof(led_value));
+        if (len <= 0)
+        {
+            rt_kprintf("vbus write err: %d, %d\n", len, rt_get_errno());
+        }
+
+        rt_thread_delay(1000);
+    }
+}
+
+int rt_application_init(void)
+{
+    rt_thread_t tid;
+    rt_err_t result;
+    tid = rt_thread_create("init",
+                           rt_init_thread_entry, RT_NULL,
+                           2048, 3, 20);
+    if (tid != RT_NULL)
+        rt_thread_startup(tid);
+
+    /* init led thread */
+    result = rt_thread_init(&led_thread, "led",
+                            led_thread_entry, RT_NULL,
+                            (rt_uint8_t *)&led_stack[0], sizeof(led_stack),
+                            20, 5);
+    if (result == RT_EOK)
+    {
+        rt_thread_startup(&led_thread);
+    }
+    return 0;
+}

+ 3 - 4
bsp/lpc43xx/drivers/board.c → bsp/lpc43xx/M4/applications/board.c

@@ -43,20 +43,19 @@ void rt_hw_board_init()
 {
 #ifdef CORE_M4
     /* NVIC Configuration */
-#define NVIC_VTOR_MASK              0x3FFFFF80
 #ifdef  VECT_TAB_RAM
     /* Set the Vector Table base location at 0x10000000 */
-    SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
+    SCB->VTOR  = 0x10000000;
 #else  /* VECT_TAB_FLASH  */
     /* Set the Vector Table base location at 0x00000000 */
-    SCB->VTOR  = (0x00000000 & NVIC_VTOR_MASK);
+    SCB->VTOR  = 0x1A000000;
 #endif
 #endif
     /* update the core clock */
     SystemCoreClockUpdate();
 
     /* init systick */
-    SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND - 1);
+    SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
 
     /* set pend exception priority */
     NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);

+ 1 - 2
bsp/lpc43xx/drivers/board.h → bsp/lpc43xx/M4/applications/board.h

@@ -33,7 +33,6 @@
 #define LPC_EXT_SDRAM_END      0xA2000000
 
 // <bool name="RT_USING_UART0" description="Using UART0" default="true" />
-#define RT_USING_UART0
 // <bool name="RT_USING_UART1" description="Using UART1" default="true" />
 //#define RT_USING_UART1
 // <bool name="RT_USING_UART2" description="Using UART2" default="true" />
@@ -55,6 +54,6 @@ extern int __bss_end;
 
 void rt_hw_board_init(void);
 int  rt_hw_board_heap_init(void);
-
+int rt_vbus_do_init(void);
 
 #endif

+ 74 - 0
bsp/lpc43xx/M4/applications/startup.c

@@ -0,0 +1,74 @@
+/*
+ * File      : startup.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2009, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2009-01-05     Bernard      first implementation
+ * 2014-07-13     xiaonong      for LPC43xx
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "board.h"
+
+extern int rt_application_init(void);
+
+/**
+ * This function will startup RT-Thread RTOS.
+ */
+void rtthread_startup(void)
+{
+    /* initialize board */
+    rt_hw_board_init();
+
+    /* show version */
+    rt_show_version();
+
+#ifdef RT_USING_HEAP
+#if LPC_EXT_SDRAM
+    rt_system_heap_init((void *)LPC_EXT_SDRAM_BEGIN, (void *)LPC_EXT_SDRAM_END);
+    sram_init();
+#else
+    rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
+#endif
+#endif
+
+    /* initialize scheduler system */
+    rt_system_scheduler_init();
+
+    /* initialize system timer*/
+    rt_system_timer_init();
+
+    /* initialize application */
+    rt_application_init();
+
+    /* initialize timer thread */
+    rt_system_timer_thread_init();
+
+    /* initialize idle thread */
+    rt_thread_idle_init();
+
+    /* start scheduler */
+    rt_system_scheduler_start();
+
+    /* never reach here */
+    return ;
+}
+
+int main(void)
+{
+    /* disable interrupt first */
+    rt_hw_interrupt_disable();
+
+    /* startup RT-Thread RTOS */
+    rtthread_startup();
+
+    return 0;
+}

+ 13 - 0
bsp/lpc43xx/M4/applications/vbus_conf.h

@@ -0,0 +1,13 @@
+#ifndef __VBUS_CONF_H__
+#define __VBUS_CONF_H__
+
+/* Number of blocks in VBus. The total size of VBus is
+ * RT_VMM_RB_BLK_NR * 64byte * 2. */
+#define RT_VMM_RB_BLK_NR     20
+
+/* We don't use the IRQ number to trigger IRQ in this BSP. */
+#define RT_VBUS_GUEST_VIRQ    0
+#define RT_VBUS_HOST_VIRQ     0
+
+#endif /* end of include guard: __VBUS_CONF_H__ */
+

+ 86 - 0
bsp/lpc43xx/M4/applications/vbus_drv.c

@@ -0,0 +1,86 @@
+/*
+ * VMM Bus Driver
+ *
+ * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2015-01-07     Grissiom     add comment
+ */
+
+#include <rtthread.h>
+
+#ifdef RT_USING_VBUS
+#include <rtdevice.h>
+#include <vbus.h>
+#include <board.h>
+
+struct rt_vbus_ring rt_vbus_rings[2] SECTION("vbus_ring");
+
+int rt_vbus_do_init(void)
+{
+    return rt_vbus_init(&rt_vbus_rings[0], &rt_vbus_rings[1]);
+}
+INIT_COMPONENT_EXPORT(rt_vbus_do_init);
+
+int rt_vbus_hw_init(void)
+{
+    NVIC_ClearPendingIRQ(M0CORE_IRQn);
+    NVIC_EnableIRQ(M0CORE_IRQn);
+    return 0;
+}
+
+void M0CORE_IRQHandler(void)
+{
+    LPC_CREG->M0TXEVENT = 0;
+    rt_vbus_isr(M0CORE_IRQn, RT_NULL);
+}
+
+int rt_vbus_hw_eoi(int irqnr, void *param)
+{
+    /* Nothing to do here as we cleared the interrupt in IRQHandler. */
+    return 0;
+}
+
+struct rt_vbus_dev rt_vbus_chn_devx[] = {
+    {
+        .req =
+        {
+            .prio = 30,
+            .name = "vecho",
+            .is_server = 1,
+            .recv_wm.low = RT_VMM_RB_BLK_NR / 3,
+            .recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
+            .post_wm.low = RT_VMM_RB_BLK_NR / 3,
+            .post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
+        }
+    },
+    {
+        .req =
+        {
+            .name = RT_NULL,
+        }
+    },
+};
+
+#endif /* RT_USING_VBUS */
+

+ 53 - 0
bsp/lpc43xx/M4/applications/vbus_hw.h

@@ -0,0 +1,53 @@
+/*
+ * VMM Bus
+ *
+ * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2015-01-07     Grissiom     init commit
+ */
+
+#include <rtthread.h>
+#include <board.h>
+
+rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr)
+{
+    __SEV();
+}
+
+/* Read memory barrier. */
+rt_inline void rt_vbus_smp_rmb(void)
+{
+    __DMB();
+}
+
+/* Write memory barrier. */
+rt_inline void rt_vbus_smp_wmb(void)
+{
+    __DSB();
+}
+
+/* General memory barrier. */
+rt_inline void rt_vbus_smp_mb(void)
+{
+    __DSB();
+}

+ 4 - 2
bsp/lpc43xx/M4/rtconfig.h

@@ -95,7 +95,8 @@
 // <integer name="RT_CONSOLEBUF_SIZE" description="The buffer size for console output" default="128" />
 #define RT_CONSOLEBUF_SIZE  128
 // <string name="RT_CONSOLE_DEVICE_NAME" description="The device name for console" default="uart" />
-#define RT_CONSOLE_DEVICE_NAME  "uart0"
+#define RT_CONSOLE_DEVICE_NAME  "uart3"
+#define RT_USING_UART3
 // </section>
 
 // <bool name="RT_USING_COMPONENTS_INIT" description="Using RT-Thread components initialization" default="true" />
@@ -222,7 +223,8 @@
 #define RT_LWIP_MSKADDR3 0
 // </section>
 
-
+#define RT_USING_VBUS
+#define RT_USING_LOGTRACE
 
 // </RDTConfigurator>
 

+ 7 - 6
bsp/lpc43xx/M4/rtconfig.py

@@ -35,7 +35,7 @@ if os.getenv('RTT_EXEC_PATH'):
         EXEC_PATH = os.getenv('RTT_EXEC_PATH')
 
 #
-BUILD = 'release'
+BUILD = 'debug'
 
 if PLATFORM == 'gcc':
     # toolchains
@@ -44,23 +44,24 @@ if PLATFORM == 'gcc':
     AS = PREFIX + 'gcc'
     AR = PREFIX + 'ar'
     LINK = PREFIX + 'gcc'
-    TARGET_EXT = 'elf'
+    TARGET_EXT = 'axf'
     SIZE = PREFIX + 'size'
     OBJDUMP = PREFIX + 'objdump'
     OBJCPY = PREFIX + 'objcopy'
-    DEVICE = ' -mcpu=' + CPU + ' -mthumb -ffunction-sections -fdata-sections'
+    DEVICE = ' -mcpu=' + CPU + ' -mthumb -ffunction-sections -fdata-sections -Wall'
     if USE_CORE == 'CORE_M4':
         DEVICE += ' -mfpu=fpv4-sp-d16 -mfloat-abi=softfp'
     CFLAGS = DEVICE 
     AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -Wa,-mimplicit-it=thumb '
-    LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-lpc43xx.map,-cref,-u,Reset_Handler -T rtthread-lpc43xx_spifi.ld'
+    LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-lpc43xx.map,-cref,-u,Reset_Handler -T rtthread-lpc43xx.ld'
 
     CPATH = ''
     LPATH = ''
 
+    CFLAGS += ' -gdwarf-2'
+    AFLAGS += ' -gdwarf-2'
     if BUILD == 'debug':
-        CFLAGS += ' -O0 -gdwarf-2'
-        AFLAGS += ' -gdwarf-2'
+        CFLAGS += ' -O0'
     else:
         CFLAGS += ' -O2'
 

+ 147 - 0
bsp/lpc43xx/M4/rtthread-lpc43xx.ld

@@ -0,0 +1,147 @@
+/*
+ * linker script for LPC43xx SPIFI (4Mb NorFlash, 32kB SRAM ) with GNU ld
+ * yiyue.fang 2012-04-14
+ */
+
+/* Program Entry, set to mark it as "used" and avoid gc */
+MEMORY
+{
+    CODE (rx) : ORIGIN = 0x1A000000, LENGTH = 0x00080000
+    M0CODE (rx) : ORIGIN = 0x1B000000, LENGTH = 0x00080000
+    DATA (rw) : ORIGIN = 0x10000000, LENGTH = 0x00008000
+    AHBRAM (rw) : ORIGIN = 0x20000000, LENGTH = 0x00010000
+}
+ENTRY(Reset_Handler)
+_system_stack_size = 0x200;
+
+SECTIONS
+{
+    .text :
+    {
+        . = ALIGN(4);
+        KEEP(*(.interrupt_vector))      /* Startup code */
+        . = ALIGN(4);
+        *(.text)                        /* remaining code */
+        *(.text.*)                      /* remaining code */
+        *(.rodata)                      /* read-only data (constants) */
+        *(.rodata*)
+        *(.glue_7)
+        *(.glue_7t)
+        *(.gnu.linkonce.t*)
+
+        /* section information for finsh shell */
+        . = ALIGN(4);
+        __fsymtab_start = .;
+        KEEP(*(FSymTab))
+        __fsymtab_end = .;
+        . = ALIGN(4);
+        __vsymtab_start = .;
+        KEEP(*(VSymTab))
+        __vsymtab_end = .;
+        . = ALIGN(4);
+
+        . = ALIGN(4);
+        _etext = .;
+    } > CODE = 0
+
+    /* .ARM.exidx is sorted, so has to go in its own output section.  */
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+
+        /* This is used by the startup in order to initialize the .data secion */
+        _sidata = .;
+    } > CODE
+    __exidx_end = .;
+
+    /* .data section which is used for initialized data */
+
+    .data : AT (_sidata)
+    {
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .data secion */
+        _sdata = . ;
+
+        *(.data)
+        *(.data.*)
+        *(.gnu.linkonce.d*)
+
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .data secion */
+        _edata = . ;
+    } >DATA
+
+    . = _edata  ;
+    .stack :
+    {
+        . = . + _system_stack_size;
+        . = ALIGN(4);
+        _estack = .;
+    } >DATA
+
+    __bss_start = .;
+    .bss :
+    {
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .bss secion */
+        _sbss = .;
+
+        *(.bss)
+        *(.bss.*)
+        *(COMMON)
+
+        . = ALIGN(4);
+        /* This is used by the startup in order to initialize the .bss secion */
+        _ebss = . ;        
+        *(.bss.init)
+    } > DATA
+    __bss_end = .;
+
+    .vbus_ring (NOLOAD) :
+    {
+        *(vbus_ring)
+    } > AHBRAM
+
+
+    .text.M0CODE :
+    {
+        *(M0_CODE)
+    } > M0CODE = 0
+
+    _end = .;
+
+    /* Stabs debugging sections.  */
+    .stab          0 : { *(.stab) }
+    .stabstr       0 : { *(.stabstr) }
+    .stab.excl     0 : { *(.stab.excl) }
+    .stab.exclstr  0 : { *(.stab.exclstr) }
+    .stab.index    0 : { *(.stab.index) }
+    .stab.indexstr 0 : { *(.stab.indexstr) }
+    .comment       0 : { *(.comment) }
+    /* DWARF debug sections.
+     * Symbols in the DWARF debugging sections are relative to the beginning
+     * of the section so we begin them at 0.  */
+    /* DWARF 1 */
+    .debug          0 : { *(.debug) }
+    .line           0 : { *(.line) }
+    /* GNU DWARF 1 extensions */
+    .debug_srcinfo  0 : { *(.debug_srcinfo) }
+    .debug_sfnames  0 : { *(.debug_sfnames) }
+    /* DWARF 1.1 and DWARF 2 */
+    .debug_aranges  0 : { *(.debug_aranges) }
+    .debug_pubnames 0 : { *(.debug_pubnames) }
+    /* DWARF 2 */
+    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+    .debug_abbrev   0 : { *(.debug_abbrev) }
+    .debug_line     0 : { *(.debug_line) }
+    .debug_frame    0 : { *(.debug_frame) }
+    .debug_str      0 : { *(.debug_str) }
+    .debug_loc      0 : { *(.debug_loc) }
+    .debug_macinfo  0 : { *(.debug_macinfo) }
+    /* SGI/MIPS DWARF 2 extensions */
+    .debug_weaknames 0 : { *(.debug_weaknames) }
+    .debug_funcnames 0 : { *(.debug_funcnames) }
+    .debug_typenames 0 : { *(.debug_typenames) }
+    .debug_varnames  0 : { *(.debug_varnames) }
+}

+ 23 - 0
bsp/lpc43xx/M4/rtthread_lpc43xx.sct

@@ -0,0 +1,23 @@
+; *************************************************************
+; *** Scatter-Loading Description File generated by uVision ***
+; *************************************************************
+
+LR_IROM1 0x1A000000 0x00080000  {    ; load region size_region
+  ER_IROM1 0x1A000000 0x00080000  {  ; load address = execution address
+   *.o (RESET, +First)
+   *(InRoot$$Sections)
+   .ANY (+RO)
+  }
+  RW_IRAM1 0x10000000 0x00008000  {  ; RW data
+   .ANY (+RW +ZI)
+  }
+  RW_AHBRAM 0x20000000 0x00010000  {  ; RW data
+   * (vbus_ring)
+  }
+}
+
+LR_IROM2 0x1B000000 0x00080000  {
+  ER_IROM2 0x1B000000 0x00080000  {  ; load address = execution address
+   * (M0_CODE)
+  }
+}

+ 7 - 390
bsp/lpc43xx/M4/template.uvproj

@@ -211,7 +211,7 @@
             <RvdsVP>2</RvdsVP>
             <hadIRAM2>1</hadIRAM2>
             <hadIROM2>1</hadIROM2>
-            <StupSel>1</StupSel>
+            <StupSel>8</StupSel>
             <useUlib>1</useUlib>
             <EndSel>0</EndSel>
             <uLtcg>0</uLtcg>
@@ -224,10 +224,10 @@
             <NoZi3>0</NoZi3>
             <NoZi4>0</NoZi4>
             <NoZi5>0</NoZi5>
-            <Ro1Chk>1</Ro1Chk>
+            <Ro1Chk>0</Ro1Chk>
             <Ro2Chk>0</Ro2Chk>
             <Ro3Chk>0</Ro3Chk>
-            <Ir1Chk>0</Ir1Chk>
+            <Ir1Chk>1</Ir1Chk>
             <Ir2Chk>0</Ir2Chk>
             <Ra1Chk>0</Ra1Chk>
             <Ra2Chk>0</Ra2Chk>
@@ -338,7 +338,7 @@
             <Optim>1</Optim>
             <oTime>0</oTime>
             <SplitLS>0</SplitLS>
-            <OneElfS>0</OneElfS>
+            <OneElfS>1</OneElfS>
             <Strict>0</Strict>
             <EnumInt>0</EnumInt>
             <PlainCh>0</PlainCh>
@@ -371,7 +371,7 @@
             </VariousControls>
           </Aads>
           <LDads>
-            <umfTarg>1</umfTarg>
+            <umfTarg>0</umfTarg>
             <Ropi>0</Ropi>
             <Rwpi>0</Rwpi>
             <noStLib>0</noStLib>
@@ -379,390 +379,8 @@
             <useFile>0</useFile>
             <TextAddressRange>0x14000000</TextAddressRange>
             <DataAddressRange>0x10000000</DataAddressRange>
-            <ScatterFile></ScatterFile>
-            <IncludeLibs></IncludeLibs>
-            <IncludeLibsPath></IncludeLibsPath>
-            <Misc></Misc>
-            <LinkerInputFile></LinkerInputFile>
-            <DisabledWarnings></DisabledWarnings>
-          </LDads>
-        </TargetArmAds>
-      </TargetOption>
-    </Target>
-    <Target>
-      <TargetName>LPC43xx RAM</TargetName>
-      <ToolsetNumber>0x4</ToolsetNumber>
-      <ToolsetName>ARM-ADS</ToolsetName>
-      <TargetOption>
-        <TargetCommonOption>
-          <Device>LPC4357</Device>
-          <Vendor>NXP (founded by Philips)</Vendor>
-          <Cpu>IRAM(0x10000000-0x10007FFF) IRAM2(0x20000000-0x2000FFFF) IROM(0x1A000000-0x1A07FFFF) IROM2(0x1B000000-0x1B07FFFF) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2</Cpu>
-          <FlashUtilSpec></FlashUtilSpec>
-          <StartupFile>"STARTUP\NXP\LPC43xx\startup_LPC43xx.s" ("NXP LPC43xx Startup Code")</StartupFile>
-          <FlashDriverDll>UL2CM3(-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000)</FlashDriverDll>
-          <DeviceId>6414</DeviceId>
-          <RegisterFile>LPC43xx.H</RegisterFile>
-          <MemoryEnv></MemoryEnv>
-          <Cmp></Cmp>
-          <Asm></Asm>
-          <Linker></Linker>
-          <OHString></OHString>
-          <InfinionOptionDll></InfinionOptionDll>
-          <SLE66CMisc></SLE66CMisc>
-          <SLE66AMisc></SLE66AMisc>
-          <SLE66LinkerMisc></SLE66LinkerMisc>
-          <SFDFile>SFD\NXP\LPC43xx\LPC43xx.SFR</SFDFile>
-          <UseEnv>0</UseEnv>
-          <BinPath></BinPath>
-          <IncludePath></IncludePath>
-          <LibPath></LibPath>
-          <RegisterFilePath>NXP\LPC43xx\</RegisterFilePath>
-          <DBRegisterFilePath>NXP\LPC43xx\</DBRegisterFilePath>
-          <TargetStatus>
-            <Error>0</Error>
-            <ExitCodeStop>0</ExitCodeStop>
-            <ButtonStop>0</ButtonStop>
-            <NotGenerated>0</NotGenerated>
-            <InvalidFlash>1</InvalidFlash>
-          </TargetStatus>
-          <OutputDirectory>.\build\</OutputDirectory>
-          <OutputName>rtthread_lpc43xx</OutputName>
-          <CreateExecutable>1</CreateExecutable>
-          <CreateLib>0</CreateLib>
-          <CreateHexFile>0</CreateHexFile>
-          <DebugInformation>1</DebugInformation>
-          <BrowseInformation>1</BrowseInformation>
-          <ListingPath>.\build\</ListingPath>
-          <HexFormatSelection>1</HexFormatSelection>
-          <Merge32K>0</Merge32K>
-          <CreateBatchFile>0</CreateBatchFile>
-          <BeforeCompile>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-            <nStopU1X>0</nStopU1X>
-            <nStopU2X>0</nStopU2X>
-          </BeforeCompile>
-          <BeforeMake>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-          </BeforeMake>
-          <AfterMake>
-            <RunUserProg1>0</RunUserProg1>
-            <RunUserProg2>0</RunUserProg2>
-            <UserProg1Name></UserProg1Name>
-            <UserProg2Name></UserProg2Name>
-            <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
-            <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
-          </AfterMake>
-          <SelectedForBatchBuild>0</SelectedForBatchBuild>
-          <SVCSIdString></SVCSIdString>
-        </TargetCommonOption>
-        <CommonProperty>
-          <UseCPPCompiler>0</UseCPPCompiler>
-          <RVCTCodeConst>0</RVCTCodeConst>
-          <RVCTZI>0</RVCTZI>
-          <RVCTOtherData>0</RVCTOtherData>
-          <ModuleSelection>0</ModuleSelection>
-          <IncludeInBuild>1</IncludeInBuild>
-          <AlwaysBuild>0</AlwaysBuild>
-          <GenerateAssemblyFile>0</GenerateAssemblyFile>
-          <AssembleAssemblyFile>0</AssembleAssemblyFile>
-          <PublicsOnly>0</PublicsOnly>
-          <StopOnExitCode>3</StopOnExitCode>
-          <CustomArgument></CustomArgument>
-          <IncludeLibraryModules></IncludeLibraryModules>
-        </CommonProperty>
-        <DllOption>
-          <SimDllName>SARMCM3.DLL</SimDllName>
-          <SimDllArguments>-MPU</SimDllArguments>
-          <SimDlgDll>DCM.DLL</SimDlgDll>
-          <SimDlgDllArguments>-pCM4</SimDlgDllArguments>
-          <TargetDllName>SARMCM3.DLL</TargetDllName>
-          <TargetDllArguments>-MPU</TargetDllArguments>
-          <TargetDlgDll>TCM.DLL</TargetDlgDll>
-          <TargetDlgDllArguments>-pCM4</TargetDlgDllArguments>
-        </DllOption>
-        <DebugOption>
-          <OPTHX>
-            <HexSelection>1</HexSelection>
-            <HexRangeLowAddress>0</HexRangeLowAddress>
-            <HexRangeHighAddress>0</HexRangeHighAddress>
-            <HexOffset>0</HexOffset>
-            <Oh166RecLen>16</Oh166RecLen>
-          </OPTHX>
-          <Simulator>
-            <UseSimulator>0</UseSimulator>
-            <LoadApplicationAtStartup>1</LoadApplicationAtStartup>
-            <RunToMain>1</RunToMain>
-            <RestoreBreakpoints>1</RestoreBreakpoints>
-            <RestoreWatchpoints>1</RestoreWatchpoints>
-            <RestoreMemoryDisplay>1</RestoreMemoryDisplay>
-            <RestoreFunctions>1</RestoreFunctions>
-            <RestoreToolbox>1</RestoreToolbox>
-            <LimitSpeedToRealTime>0</LimitSpeedToRealTime>
-          </Simulator>
-          <Target>
-            <UseTarget>1</UseTarget>
-            <LoadApplicationAtStartup>0</LoadApplicationAtStartup>
-            <RunToMain>0</RunToMain>
-            <RestoreBreakpoints>1</RestoreBreakpoints>
-            <RestoreWatchpoints>1</RestoreWatchpoints>
-            <RestoreMemoryDisplay>0</RestoreMemoryDisplay>
-            <RestoreFunctions>0</RestoreFunctions>
-            <RestoreToolbox>1</RestoreToolbox>
-            <RestoreTracepoints>0</RestoreTracepoints>
-          </Target>
-          <RunDebugAfterBuild>0</RunDebugAfterBuild>
-          <TargetSelection>1</TargetSelection>
-          <SimDlls>
-            <CpuDll></CpuDll>
-            <CpuDllArguments></CpuDllArguments>
-            <PeripheralDll></PeripheralDll>
-            <PeripheralDllArguments></PeripheralDllArguments>
-            <InitializationFile></InitializationFile>
-          </SimDlls>
-          <TargetDlls>
-            <CpuDll></CpuDll>
-            <CpuDllArguments></CpuDllArguments>
-            <PeripheralDll></PeripheralDll>
-            <PeripheralDllArguments></PeripheralDllArguments>
-            <InitializationFile>.\Dbg_RAM.ini</InitializationFile>
-            <Driver>BIN\UL2CM3.DLL</Driver>
-          </TargetDlls>
-        </DebugOption>
-        <Utilities>
-          <Flash1>
-            <UseTargetDll>1</UseTargetDll>
-            <UseExternalTool>1</UseExternalTool>
-            <RunIndependent>0</RunIndependent>
-            <UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
-            <Capability>1</Capability>
-            <DriverSelection>4096</DriverSelection>
-          </Flash1>
-          <bUseTDR>1</bUseTDR>
-          <Flash2>BIN\UL2CM3.DLL</Flash2>
-          <Flash3>"" ()</Flash3>
-          <Flash4></Flash4>
-        </Utilities>
-        <TargetArmAds>
-          <ArmAdsMisc>
-            <GenerateListings>0</GenerateListings>
-            <asHll>1</asHll>
-            <asAsm>1</asAsm>
-            <asMacX>1</asMacX>
-            <asSyms>1</asSyms>
-            <asFals>1</asFals>
-            <asDbgD>1</asDbgD>
-            <asForm>1</asForm>
-            <ldLst>0</ldLst>
-            <ldmm>1</ldmm>
-            <ldXref>1</ldXref>
-            <BigEnd>0</BigEnd>
-            <AdsALst>1</AdsALst>
-            <AdsACrf>1</AdsACrf>
-            <AdsANop>0</AdsANop>
-            <AdsANot>0</AdsANot>
-            <AdsLLst>1</AdsLLst>
-            <AdsLmap>1</AdsLmap>
-            <AdsLcgr>1</AdsLcgr>
-            <AdsLsym>1</AdsLsym>
-            <AdsLszi>1</AdsLszi>
-            <AdsLtoi>1</AdsLtoi>
-            <AdsLsun>1</AdsLsun>
-            <AdsLven>1</AdsLven>
-            <AdsLsxf>1</AdsLsxf>
-            <RvctClst>0</RvctClst>
-            <GenPPlst>0</GenPPlst>
-            <AdsCpuType>"Cortex-M4"</AdsCpuType>
-            <RvctDeviceName></RvctDeviceName>
-            <mOS>0</mOS>
-            <uocRom>0</uocRom>
-            <uocRam>0</uocRam>
-            <hadIROM>1</hadIROM>
-            <hadIRAM>1</hadIRAM>
-            <hadXRAM>0</hadXRAM>
-            <uocXRam>0</uocXRam>
-            <RvdsVP>2</RvdsVP>
-            <hadIRAM2>1</hadIRAM2>
-            <hadIROM2>1</hadIROM2>
-            <StupSel>8</StupSel>
-            <useUlib>1</useUlib>
-            <EndSel>0</EndSel>
-            <uLtcg>0</uLtcg>
-            <RoSelD>3</RoSelD>
-            <RwSelD>3</RwSelD>
-            <CodeSel>0</CodeSel>
-            <OptFeed>0</OptFeed>
-            <NoZi1>0</NoZi1>
-            <NoZi2>0</NoZi2>
-            <NoZi3>0</NoZi3>
-            <NoZi4>0</NoZi4>
-            <NoZi5>0</NoZi5>
-            <Ro1Chk>0</Ro1Chk>
-            <Ro2Chk>0</Ro2Chk>
-            <Ro3Chk>0</Ro3Chk>
-            <Ir1Chk>1</Ir1Chk>
-            <Ir2Chk>0</Ir2Chk>
-            <Ra1Chk>0</Ra1Chk>
-            <Ra2Chk>0</Ra2Chk>
-            <Ra3Chk>0</Ra3Chk>
-            <Im1Chk>0</Im1Chk>
-            <Im2Chk>1</Im2Chk>
-            <OnChipMemories>
-              <Ocm1>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm1>
-              <Ocm2>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm2>
-              <Ocm3>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm3>
-              <Ocm4>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm4>
-              <Ocm5>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm5>
-              <Ocm6>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </Ocm6>
-              <IRAM>
-                <Type>0</Type>
-                <StartAddress>0x10000000</StartAddress>
-                <Size>0x8000</Size>
-              </IRAM>
-              <IROM>
-                <Type>1</Type>
-                <StartAddress>0x1a000000</StartAddress>
-                <Size>0x80000</Size>
-              </IROM>
-              <XRAM>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </XRAM>
-              <OCR_RVCT1>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT1>
-              <OCR_RVCT2>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT2>
-              <OCR_RVCT3>
-                <Type>1</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT3>
-              <OCR_RVCT4>
-                <Type>1</Type>
-                <StartAddress>0x1a000000</StartAddress>
-                <Size>0x80000</Size>
-              </OCR_RVCT4>
-              <OCR_RVCT5>
-                <Type>1</Type>
-                <StartAddress>0x1b000000</StartAddress>
-                <Size>0x80000</Size>
-              </OCR_RVCT5>
-              <OCR_RVCT6>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT6>
-              <OCR_RVCT7>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT7>
-              <OCR_RVCT8>
-                <Type>0</Type>
-                <StartAddress>0x0</StartAddress>
-                <Size>0x0</Size>
-              </OCR_RVCT8>
-              <OCR_RVCT9>
-                <Type>0</Type>
-                <StartAddress>0x10000000</StartAddress>
-                <Size>0x8000</Size>
-              </OCR_RVCT9>
-              <OCR_RVCT10>
-                <Type>0</Type>
-                <StartAddress>0x20000000</StartAddress>
-                <Size>0x10000</Size>
-              </OCR_RVCT10>
-            </OnChipMemories>
-            <RvctStartVector></RvctStartVector>
-          </ArmAdsMisc>
-          <Cads>
-            <interw>1</interw>
-            <Optim>1</Optim>
-            <oTime>0</oTime>
-            <SplitLS>0</SplitLS>
-            <OneElfS>0</OneElfS>
-            <Strict>0</Strict>
-            <EnumInt>0</EnumInt>
-            <PlainCh>0</PlainCh>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <wLevel>0</wLevel>
-            <uThumb>0</uThumb>
-            <uSurpInc>0</uSurpInc>
-            <VariousControls>
-              <MiscControls></MiscControls>
-              <Define></Define>
-              <Undefine></Undefine>
-              <IncludePath></IncludePath>
-            </VariousControls>
-          </Cads>
-          <Aads>
-            <interw>1</interw>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <thumb>0</thumb>
-            <SplitLS>0</SplitLS>
-            <SwStkChk>0</SwStkChk>
-            <NoWarn>0</NoWarn>
-            <uSurpInc>0</uSurpInc>
-            <VariousControls>
-              <MiscControls></MiscControls>
-              <Define>NO_CRP</Define>
-              <Undefine></Undefine>
-              <IncludePath></IncludePath>
-            </VariousControls>
-          </Aads>
-          <LDads>
-            <umfTarg>1</umfTarg>
-            <Ropi>0</Ropi>
-            <Rwpi>0</Rwpi>
-            <noStLib>0</noStLib>
-            <RepFail>1</RepFail>
-            <useFile>0</useFile>
-            <TextAddressRange>0x10000000</TextAddressRange>
-            <DataAddressRange>0x20000000</DataAddressRange>
-            <ScatterFile></ScatterFile>
+            <pXoBase></pXoBase>
+            <ScatterFile>.\rtthread_lpc43xx.sct</ScatterFile>
             <IncludeLibs></IncludeLibs>
             <IncludeLibsPath></IncludeLibsPath>
             <Misc></Misc>
@@ -773,5 +391,4 @@
       </TargetOption>
     </Target>
   </Targets>
-
 </Project>

+ 8 - 0
bsp/lpc43xx/M4/vbus_local_conf.h

@@ -0,0 +1,8 @@
+#ifndef __VBUS_LOCAL_CONF_H__
+#define __VBUS_LOCAL_CONF_H__
+
+#define RT_VBUS_USING_FLOW_CONTROL
+
+#define RT_VBUS_USING_TESTS
+
+#endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */

+ 0 - 84
bsp/lpc43xx/applications/application.c

@@ -1,84 +0,0 @@
-/*
- * File      : application.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2014, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date           Author       Notes
- * 2014-07-13     xiaonong     port for lpc43xx
- */
-
-#include <rtthread.h>
-#include <board.h>
-#include <rtdevice.h>
-#include "drv_led.h"
-#ifdef RT_USING_FINSH
-#include <finsh.h>
-#include <shell.h>
-#endif
-
-/* thread phase init */
-void rt_init_thread_entry(void *parameter)
-{
-#ifdef RT_USING_FINSH
-    /* initialize finsh */
-    finsh_system_init();
-    finsh_set_device(RT_CONSOLE_DEVICE_NAME);
-#endif
-}
-/*the led thread*/
-ALIGN(RT_ALIGN_SIZE)
-static rt_uint8_t led_stack[ 512 ];
-static struct rt_thread led_thread;
-static void led_thread_entry(void *parameter)
-{
-    rt_uint8_t led_value = 0;
-    rt_device_t led_dev;
-    rt_led_hw_init();
-    led_dev = rt_device_find("led");
-    if (led_dev == RT_NULL)
-    {
-        rt_kprintf("can not find the led device!\n");
-        return;
-    }
-    while (1)
-    {
-        /* led0 on */
-        led_value = 1;
-        led_dev->write(led_dev, 0, &led_value, 1);
-        rt_thread_delay(RT_TICK_PER_SECOND / 2); /* sleep 0.5 second and switch to other thread */
-
-        /* led0 off */
-        led_value = 0;
-        led_dev->write(led_dev, 0, &led_value, 1);
-        rt_thread_delay(RT_TICK_PER_SECOND / 2);
-    }
-}
-
-int rt_application_init(void)
-{
-    rt_thread_t tid;
-    rt_err_t result;
-    tid = rt_thread_create("init",
-                           rt_init_thread_entry, RT_NULL,
-                           2048, RT_THREAD_PRIORITY_MAX / 3, 20);
-    if (tid != RT_NULL) rt_thread_startup(tid);
-    /* init led thread */
-    result = rt_thread_init(&led_thread,
-                            "led",
-                            led_thread_entry,
-                            RT_NULL,
-                            (rt_uint8_t *)&led_stack[0],
-                            sizeof(led_stack),
-                            20,
-                            5);
-    if (result == RT_EOK)
-    {
-        rt_thread_startup(&led_thread);
-    }
-    return 0;
-}

+ 14 - 0
bsp/lpc43xx/bin2C.py

@@ -0,0 +1,14 @@
+#!/bin/env python
+
+import sys
+
+fi = open(sys.argv[1], 'rb')
+fo = open(sys.argv[2], 'wb')
+
+idx = 0
+for i in fi.read():
+    idx += 1
+    fo.write('0x%02x, ' % ord(i))
+    if idx % 16 == 0:
+        fo.write('\n')
+fo.write('\n')

+ 122 - 99
bsp/lpc43xx/drivers/drv_uart.c

@@ -26,19 +26,7 @@ struct lpc_uart
 
 static rt_err_t lpc_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
 {
-//    struct lpc_uart *uart;
-
-
     RT_ASSERT(serial != RT_NULL);
-    //  uart = (struct lpc_uart *)serial->parent.user_data;
-
-
-
-    // Initialize FIFO for UART0 peripheral
-//    UART_FIFOConfig(uart->USART, &UARTFIFOConfigStruct);
-
-//    UART_TxCmd(uart->USART, ENABLE);
-
     return RT_EOK;
 }
 
@@ -95,60 +83,62 @@ static const struct rt_uart_ops lpc_uart_ops =
     lpc_getc,
 };
 
-#if defined(RT_USING_UART0)
-/* UART0 device driver structure */
-struct lpc_uart uart0 =
-{
-    LPC_USART0,
-    USART0_IRQn,
-};
-struct rt_serial_device serial0;
-
-void UART0_IRQHandler(void)
+static void _do_uart_isr(struct rt_serial_device *sdev)
 {
     struct lpc_uart *uart;
-    volatile uint32_t intsrc, temp;
+    uint32_t intsrc;
 
-    uart = &uart0;
-
-    /* enter interrupt */
-    rt_interrupt_enter();
+    uart = sdev->parent.user_data;
 
     /* Determine the interrupt source */
     intsrc = uart->USART->IIR & UART_IIR_INTID_MASK;
 
     switch (intsrc)
     {
-
-    case UART_IIR_INTID_RLS:                                            /* Receive Line Status interrupt*/
+    case UART_IIR_INTID_RLS:
+        /* Receive Line Status interrupt */
         /* read the line status */
         intsrc = uart->USART->LSR;
         /* Receive an error data */
         if (intsrc & UART_LSR_PE)
         {
-            temp = LPC_USART0->RBR;
+            uart->USART->RBR;
         }
         break;
-
-    case UART_IIR_INTID_RDA:                                            /*  Receive data               */
-    case UART_IIR_INTID_CTI:                                            /*  Receive data timeout       */
+    case UART_IIR_INTID_RDA:
+        /* Receive data */
+    case UART_IIR_INTID_CTI:
+        /* Receive data timeout */
         /* read the data to buffer  */
         while (uart->USART->LSR & UART_LSR_RDR)
         {
-            rt_hw_serial_isr(&serial0, RT_SERIAL_EVENT_RX_IND);
+            rt_hw_serial_isr(sdev, RT_SERIAL_EVENT_RX_IND);
         }
         break;
 
     default:
         break;
     }
+}
 
-    /* leave interrupt */
+#if defined(RT_USING_UART0)
+/* UART0 device driver structure */
+struct lpc_uart uart0 =
+{
+    LPC_USART0,
+    USART0_IRQn,
+};
+struct rt_serial_device serial0;
+
+void UART0_IRQHandler(void)
+{
+    rt_interrupt_enter();
+    _do_uart_isr(&serial0);
     rt_interrupt_leave();
 }
 #endif
+
 #if defined(RT_USING_UART2)
-/* UART2 device driver structure */
 struct lpc_uart uart2 =
 {
     LPC_USART2,
@@ -158,47 +148,28 @@ struct rt_serial_device serial2;
 
 void UART2_IRQHandler(void)
 {
-    struct lpc_uart *uart;
-    uint32_t intsrc, temp;
-
-    uart = &uart2;
-
-    /* enter interrupt */
     rt_interrupt_enter();
+    _do_uart_isr(&serial2);
+    rt_interrupt_leave();
+}
+#endif
 
-    /* Determine the interrupt source */
-    intsrc = uart->USART->IIR & UART_IIR_INTID_MASK;
-
-    switch (intsrc)
-    {
-
-    case UART_IIR_INTID_RLS:                                            /* Receive Line Status interrupt*/
-        /* read the line status */
-        intsrc = uart->USART->LSR;
-        /* Receive an error data */
-        if (intsrc & UART_LSR_PE)
-        {
-            temp = LPC_USART0->RBR;
-        }
-        break;
-
-    case UART_IIR_INTID_RDA:                                            /*  Receive data               */
-    case UART_IIR_INTID_CTI:                                            /*  Receive data timeout       */
-        /* read the data to buffer  */
-        while (uart->USART->LSR & UART_LSR_RDR)
-        {
-            rt_hw_serial_isr(&serial0, RT_SERIAL_EVENT_RX_IND);
-        }
-        break;
-
-    default:
-        break;
-    }
+#if defined(RT_USING_UART3)
+struct lpc_uart uart3 =
+{
+    LPC_USART3,
+    USART3_IRQn,
+};
+struct rt_serial_device serial3;
 
-    /* leave interrupt */
+void UART3_IRQHandler(void)
+{
+    rt_interrupt_enter();
+    _do_uart_isr(&serial3);
     rt_interrupt_leave();
 }
 #endif
+
 void rt_hw_uart_init(void)
 {
     struct lpc_uart *uart;
@@ -212,7 +183,7 @@ void rt_hw_uart_init(void)
     config.parity    = PARITY_NONE;
     config.stop_bits = STOP_BITS_1;
     config.invert    = NRZ_NORMAL;
-	config.bufsz	 = RT_SERIAL_RB_BUFSZ;
+    config.bufsz	 = RT_SERIAL_RB_BUFSZ;
 
     serial0.ops    = &lpc_uart_ops;
     serial0.config = config;
@@ -221,36 +192,36 @@ void rt_hw_uart_init(void)
     LPC_CCU1->CLK_M4_GPIO_CFG     |= 0x01;
     while (!(LPC_CCU1->CLK_M4_GPIO_STAT  & 0x01));
 
-    /* Enable USART1 peripheral clock                                           */
+    /* Enable USART0 peripheral clock                                           */
     LPC_CCU2->CLK_APB0_USART0_CFG |= 0x01;
     while (!(LPC_CCU2->CLK_APB0_USART0_STAT & 0x01));
 
-    /* Enable USART1 register interface clock                                   */
+    /* Enable USART0 register interface clock                                   */
     LPC_CCU1->CLK_M4_USART0_CFG   |= 0x01;
     while (!(LPC_CCU1->CLK_M4_USART0_STAT & 0x01));
 
     /* Init GPIO pins                                                           */
     LPC_SCU->SFSP2_0 = (1 << 6) |         /* Input buffer enabled               */
-                       (1 << 4) |        /* Pull-up disabled                   */
-                       (1 << 0) ;        /* Pin P2_0 used as U0_TXD            */
+        (1 << 4) |        /* Pull-up disabled                   */
+        (1 << 0) ;        /* Pin P2_0 used as U0_TXD            */
 
     LPC_SCU->SFSP2_1 = (1 << 6) |         /* Input buffer enabled               */
-                       (1 << 4) |        /* Pull-up disabled                   */
-                       (1 << 0) ;        /* Pin P2_1 used as U0_RXD            */
+        (1 << 4) |        /* Pull-up disabled                   */
+        (1 << 0) ;        /* Pin P2_1 used as U0_RXD            */
 
     /* Init USART0                                                              */
-    LPC_USART0->LCR    = 0x83;            /* 8 bits, no Parity, 1 Stop bit      */
-    LPC_USART0->DLL    = 0x06;            /* 115200 Baudrate @ 12 MHz IRC       */
-    LPC_USART0->DLM    = 0x00;
-    LPC_USART0->FDR    = 0xC1;
-    LPC_USART0->LCR    = 0x03;            /* DLAB = 0                           */
+    uart->USART->LCR    = 0x83;            /* 8 bits, no Parity, 1 Stop bit      */
+    uart->USART->DLL    = 0x06;            /* 115200 Baudrate @ 12 MHz IRC       */
+    uart->USART->DLM    = 0x00;
+    uart->USART->FDR    = 0xC1;
+    uart->USART->LCR    = 0x03;            /* DLAB = 0                           */
     /* preemption = 1, sub-priority = 1 */
     NVIC_SetPriority(uart->USART_IRQn, ((0x01 << 3) | 0x01));
 
     /* Enable Interrupt for UART channel */
     NVIC_EnableIRQ(uart->USART_IRQn);
 
-    /* register UART1 device */
+    /* register UART0 device */
     rt_hw_serial_register(&serial0, "uart0",
                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                           uart);
@@ -263,7 +234,7 @@ void rt_hw_uart_init(void)
     config.parity    = PARITY_NONE;
     config.stop_bits = STOP_BITS_1;
     config.invert    = NRZ_NORMAL;
-	config.bufsz	 = RT_SERIAL_RB_BUFSZ;
+    config.bufsz	 = RT_SERIAL_RB_BUFSZ;
 
     serial2.ops    = &lpc_uart_ops;
     serial2.config = config;
@@ -272,39 +243,91 @@ void rt_hw_uart_init(void)
     LPC_CCU1->CLK_M4_GPIO_CFG     |= 0x01;
     while (!(LPC_CCU1->CLK_M4_GPIO_STAT  & 0x01));
 
-    /* Enable USART1 peripheral clock                                           */
-    LPC_CCU2->CLK_APB0_USART0_CFG |= 0x01;
+    /* Enable USART2 peripheral clock                                           */
+    LPC_CCU2->CLK_APB2_USART2_CFG |= 0x01;
     while (!(LPC_CCU2->CLK_APB2_USART2_STAT & 0x01));
 
     /* Enable USART2 register interface clock                                   */
-    LPC_CCU1->CLK_M4_USART0_CFG   |= 0x01;
+    LPC_CCU1->CLK_M4_USART2_CFG   |= 0x01;
     while (!(LPC_CCU1->CLK_M4_USART2_STAT & 0x01));
 
     /* Init GPIO pins                                                           */
     LPC_SCU->SFSP1_15 = (1 << 6) |         /* Input buffer enabled               */
-                        (1 << 4) |        /* Pull-up disabled                   */
-                        (1 << 0) ;        /* Pin P1_15 used as U2_TXD            */
+        (1 << 4) |        /* Pull-up disabled                   */
+        (1 << 0) ;        /* Pin P1_15 used as U2_TXD            */
 
     LPC_SCU->SFSP1_16 = (1 << 6) |         /* Input buffer enabled               */
-                        (1 << 4) |        /* Pull-up disabled                   */
-                        (1 << 0) ;        /* Pin P1_16 used as U2_RXD            */
+        (1 << 4) |        /* Pull-up disabled                   */
+        (1 << 0) ;        /* Pin P1_16 used as U2_RXD            */
 
     /* Init USART2                                                              */
-    LPC_USART2->LCR    = 0x83;            /* 8 bits, no Parity, 1 Stop bit      */
-    LPC_USART2->DLL    = 0x06;            /* 115200 Baudrate @ 12 MHz IRC       */
-    LPC_USART2->DLM    = 0x00;
-    LPC_USART2->FDR    = 0xC1;
-    LPC_USART2->LCR    = 0x03;            /* DLAB = 0                           */
-	
+    uart->USART->LCR    = 0x83;            /* 8 bits, no Parity, 1 Stop bit      */
+    uart->USART->DLL    = 0x06;            /* 115200 Baudrate @ 12 MHz IRC       */
+    uart->USART->DLM    = 0x00;
+    uart->USART->FDR    = 0xC1;
+    uart->USART->LCR    = 0x03;            /* DLAB = 0                           */
+
     /* preemption = 1, sub-priority = 1 */
     NVIC_SetPriority(uart->USART_IRQn, ((0x01 << 3) | 0x01));
 
     /* Enable Interrupt for UART channel */
     NVIC_EnableIRQ(uart->USART_IRQn);
 
-    /* register UART1 device */
+    /* register UART2 device */
     rt_hw_serial_register(&serial2, "uart2",
                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                           uart);
 #endif
+#ifdef RT_USING_UART3
+    uart = &uart3;
+    config.baud_rate = BAUD_RATE_115200;
+    config.bit_order = BIT_ORDER_LSB;
+    config.data_bits = DATA_BITS_8;
+    config.parity    = PARITY_NONE;
+    config.stop_bits = STOP_BITS_1;
+    config.invert    = NRZ_NORMAL;
+    config.bufsz	 = RT_SERIAL_RB_BUFSZ;
+
+    serial3.ops    = &lpc_uart_ops;
+    serial3.config = config;
+
+    /* Enable GPIO register interface clock                                     */
+    LPC_CCU1->CLK_M4_GPIO_CFG     |= 0x01;
+    while (!(LPC_CCU1->CLK_M4_GPIO_STAT  & 0x01));
+
+    /* Enable USART3 peripheral clock                                           */
+    LPC_CCU2->CLK_APB2_USART3_CFG |= 0x01;
+    while (!(LPC_CCU2->CLK_APB2_USART3_STAT & 0x01));
+
+    /* Enable USART3 register interface clock                                   */
+    LPC_CCU1->CLK_M4_USART3_CFG   |= 0x01;
+    while (!(LPC_CCU1->CLK_M4_USART3_STAT & 0x01));
+
+    /* Init GPIO pins                                                           */
+    LPC_SCU->SFSP2_3 = (1 << 6) |         /* Input buffer enabled               */
+        (1 << 4) |        /* Pull-up disabled                   */
+        (2 << 0) ;        /* Pin P1_15 used as U2_TXD            */
+
+    LPC_SCU->SFSP2_4 = (1 << 6) |         /* Input buffer enabled               */
+        (1 << 4) |        /* Pull-up disabled                   */
+        (2 << 0) ;        /* Pin P1_16 used as U2_RXD            */
+
+    /* Init USART3                                                              */
+    uart->USART->LCR    = 0x83;            /* 8 bits, no Parity, 1 Stop bit      */
+    uart->USART->DLL    = 0x06;            /* 115200 Baudrate @ 12 MHz IRC       */
+    uart->USART->DLM    = 0x00;
+    uart->USART->FDR    = 0xC1;
+    uart->USART->LCR    = 0x03;            /* DLAB = 0                           */
+
+    /* preemption = 1, sub-priority = 1 */
+    NVIC_SetPriority(uart->USART_IRQn, ((0x01 << 3) | 0x01));
+
+    /* Enable Interrupt for UART channel */
+    NVIC_EnableIRQ(uart->USART_IRQn);
+
+    /* register UART2 device */
+    rt_hw_serial_register(&serial3, "uart3",
+                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+                          uart);
+#endif
 }

+ 4 - 0
bsp/lpc43xx/readme.txt

@@ -0,0 +1,4 @@
+1. M4 run on flash bank A. M0 run on flash bank B and the binary code of M0 is
+   embedded into the code of M4.
+3. Compile the project in M0/ first and then compile the project in M4/. Then
+   flash it into the chip with JLink.

+ 29 - 0
components/vbus/SConscript

@@ -0,0 +1,29 @@
+# RT-Thread building script for component
+
+import SCons, os
+from building import *
+
+group = []
+if not GetDepend(['RT_USING_VBUS']):
+    Return('group')
+
+cwd = GetCurrentDir()
+src = Glob('*.c')
+
+for c, f in [['RT_USING_VBUS_RFS', 'utilities/rfs.c'],
+             ['RT_USING_VBUS_RSHELL', 'utilities/rshell.c'],
+             ]:
+    if GetDepend(c):
+        src += Glob(f)
+
+with open(os.path.join(Dir('#').get_abspath(), 'vbus_local_conf.h'), 'r') as f:
+    cpp = SCons.cpp.PreProcessor()
+    cpp.process_contents(f.read())
+    if 'RT_VBUS_USING_TESTS' in cpp.cpp_namespace:
+        src += Glob('tests/*.c')
+
+CPPPATH = [cwd, os.path.join(cwd, 'share_hdr')]
+
+group = DefineGroup('VBus', src, depend = ['RT_USING_VBUS'], CPPPATH = CPPPATH)
+
+Return('group')

+ 276 - 0
components/vbus/prio_queue.c

@@ -0,0 +1,276 @@
+/*
+ * Priority Queue
+ *
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-11-04     Grissiom     add comment
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "prio_queue.h"
+
+struct rt_prio_queue_item {
+    struct rt_prio_queue_item *next;
+    /* data follows */
+};
+
+static void _do_push(struct rt_prio_queue *que,
+                     rt_uint8_t prio,
+                     struct rt_prio_queue_item *item)
+{
+    if (que->head[prio] == RT_NULL)
+    {
+        que->head[prio] = item;
+        que->bitmap |= 1 << prio;
+    }
+    else
+    {
+        RT_ASSERT(que->tail[prio]);
+        que->tail[prio]->next = item;
+    }
+    que->tail[prio] = item;
+}
+
+static struct rt_prio_queue_item* _do_pop(struct rt_prio_queue *que)
+{
+    int ffs;
+    struct rt_prio_queue_item *item;
+
+    ffs = __rt_ffs(que->bitmap);
+    if (ffs == 0)
+        return RT_NULL;
+    ffs--;
+
+    item = que->head[ffs];
+    RT_ASSERT(item);
+
+    que->head[ffs] = item->next;
+    if (que->head[ffs] == RT_NULL)
+    {
+        que->bitmap &= ~(1 << ffs);
+    }
+
+    return item;
+}
+
+rt_err_t rt_prio_queue_init(struct rt_prio_queue *que,
+                            const char *name,
+                            void *buf,
+                            rt_size_t bufsz,
+                            rt_size_t itemsz)
+{
+    RT_ASSERT(que);
+
+    rt_memset(que, 0, sizeof(*que));
+
+    rt_list_init(&(que->suspended_pop_list));
+
+    rt_mp_init(&que->pool, name, buf, bufsz,
+               sizeof(struct rt_prio_queue_item) + itemsz);
+
+    que->item_sz = itemsz;
+
+    return RT_EOK;
+}
+
+void rt_prio_queue_detach(struct rt_prio_queue *que)
+{
+    /* wake up all suspended pop threads, push thread is suspended on mempool.
+     */
+    while (!rt_list_isempty(&(que->suspended_pop_list)))
+    {
+        rt_thread_t thread;
+
+        /* disable interrupt */
+        rt_ubase_t temp = rt_hw_interrupt_disable();
+
+        /* get next suspend thread */
+        thread = rt_list_entry(que->suspended_pop_list.next, struct rt_thread, tlist);
+        /* set error code to RT_ERROR */
+        thread->error = -RT_ERROR;
+
+        rt_thread_resume(thread);
+
+        /* enable interrupt */
+        rt_hw_interrupt_enable(temp);
+    }
+    rt_mp_detach(&que->pool);
+}
+
+#ifdef RT_USING_HEAP
+struct rt_prio_queue* rt_prio_queue_create(const char *name,
+                                           rt_size_t item_nr,
+                                           rt_size_t item_sz)
+{
+    struct rt_prio_queue *que;
+    rt_size_t bufsz;
+
+    bufsz = item_nr * (sizeof(struct rt_prio_queue_item)
+                       + item_sz
+                       + sizeof(void*));
+
+    RT_ASSERT(item_nr);
+
+    que = rt_malloc(sizeof(*que) + bufsz);
+    if (!que)
+        return RT_NULL;
+
+    rt_prio_queue_init(que, name, que+1, bufsz, item_sz);
+
+    return que;
+}
+
+void rt_prio_queue_delete(struct rt_prio_queue *que)
+{
+    rt_prio_queue_detach(que);
+    rt_free(que);
+}
+#endif
+
+rt_err_t rt_prio_queue_push(struct rt_prio_queue *que,
+                            rt_uint8_t prio,
+                            void *data,
+                            rt_int32_t timeout)
+{
+    rt_ubase_t level;
+    struct rt_prio_queue_item *item;
+
+    RT_ASSERT(que);
+
+    if (prio >= RT_PRIO_QUEUE_PRIO_MAX)
+        return -RT_ERROR;
+
+    item = rt_mp_alloc(&que->pool, timeout);
+    if (item == RT_NULL)
+        return -RT_ENOMEM;
+
+    rt_memcpy(item+1, data, que->item_sz);
+    item->next = RT_NULL;
+
+    level = rt_hw_interrupt_disable();
+
+    _do_push(que, prio, item);
+
+    if (!rt_list_isempty(&(que->suspended_pop_list)))
+    {
+        rt_thread_t thread;
+
+        /* get thread entry */
+        thread = rt_list_entry(que->suspended_pop_list.next,
+                               struct rt_thread,
+                               tlist);
+        /* resume it */
+        rt_thread_resume(thread);
+        rt_hw_interrupt_enable(level);
+
+        /* perform a schedule */
+        rt_schedule();
+
+        return RT_EOK;
+    }
+
+    rt_hw_interrupt_enable(level);
+
+    return RT_EOK;
+}
+
+rt_err_t rt_prio_queue_pop(struct rt_prio_queue *que,
+                           void *data,
+                           rt_int32_t timeout)
+{
+    rt_ubase_t level;
+    struct rt_prio_queue_item *item;
+
+    RT_ASSERT(que);
+    RT_ASSERT(data);
+
+    level = rt_hw_interrupt_disable();
+    for (item = _do_pop(que);
+         item == RT_NULL;
+         item = _do_pop(que))
+    {
+        rt_thread_t thread;
+
+        if (timeout == 0)
+        {
+            rt_hw_interrupt_enable(level);
+            return -RT_ETIMEOUT;
+        }
+
+        RT_DEBUG_NOT_IN_INTERRUPT;
+
+        thread = rt_thread_self();
+        thread->error = RT_EOK;
+        rt_thread_suspend(thread);
+
+        rt_list_insert_before(&(que->suspended_pop_list), &(thread->tlist));
+
+        if (timeout > 0)
+        {
+            rt_timer_control(&(thread->thread_timer),
+                             RT_TIMER_CTRL_SET_TIME,
+                             &timeout);
+            rt_timer_start(&(thread->thread_timer));
+        }
+
+        rt_hw_interrupt_enable(level);
+
+        rt_schedule();
+
+        /* thread is waked up */
+        if (thread->error != RT_EOK)
+            return thread->error;
+        level = rt_hw_interrupt_disable();
+    }
+
+    rt_hw_interrupt_enable(level);
+
+    rt_memcpy(data, item+1, que->item_sz);
+    rt_mp_free(item);
+
+    return RT_EOK;
+}
+
+void rt_prio_queue_dump(struct rt_prio_queue *que)
+{
+    int level = 0;
+
+    rt_kprintf("bitmap: %08x\n", que->bitmap);
+    for (level = 0; level < RT_PRIO_QUEUE_PRIO_MAX; level++)
+    {
+        struct rt_prio_queue_item *item;
+
+        rt_kprintf("%2d: ", level);
+        for (item = que->head[level];
+             item;
+             item = item->next)
+        {
+            rt_kprintf("%p, ", item);
+        }
+        rt_kprintf("\n");
+    }
+}
+

+ 73 - 0
components/vbus/prio_queue.h

@@ -0,0 +1,73 @@
+/*
+ * Priority Queue
+ *
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-11-04     Grissiom     add comment
+ */
+
+#ifndef __PRIO_QUEUE_H__
+#define __PRIO_QUEUE_H__
+
+#include <rtthread.h>
+
+#define RT_PRIO_QUEUE_PRIO_MAX  32
+
+struct rt_prio_queue_item;
+
+struct rt_prio_queue {
+    rt_uint32_t bitmap;
+    struct rt_prio_queue_item *head[RT_PRIO_QUEUE_PRIO_MAX];
+    struct rt_prio_queue_item *tail[RT_PRIO_QUEUE_PRIO_MAX];
+    /* push thread suspend on the mempool, not queue */
+    rt_list_t suspended_pop_list;
+    rt_size_t item_sz;
+
+    struct rt_mempool pool;
+};
+
+rt_err_t rt_prio_queue_init(struct rt_prio_queue *que,
+                            const char *name,
+                            void *buf,
+                            rt_size_t bufsz,
+                            rt_size_t itemsz);
+void rt_prio_queue_detach(struct rt_prio_queue *que);
+
+rt_err_t rt_prio_queue_push(struct rt_prio_queue *que,
+                            rt_uint8_t prio,
+                            void *data,
+                            rt_int32_t timeout);
+rt_err_t rt_prio_queue_pop(struct rt_prio_queue *que,
+                           void *data,
+                           rt_int32_t timeout);
+#ifdef RT_USING_HEAP
+struct rt_prio_queue* rt_prio_queue_create(const char *name,
+                                           rt_size_t item_nr,
+                                           rt_size_t item_sz);
+void rt_prio_queue_delete(struct rt_prio_queue *que);
+#endif
+
+void rt_prio_queue_dump(struct rt_prio_queue *que);
+
+#endif /* end of include guard: __PRIO_QUEUE_H__ */

+ 71 - 0
components/vbus/rt_watermark_queue.c

@@ -0,0 +1,71 @@
+/*
+ * Water Gauge
+ *
+ * COPYRIGHT (C) 2014-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2014-04-16     Grissiom     first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "rt_watermark_queue.h"
+
+void rt_wm_que_set_mark(struct rt_watermark_queue *wg,
+                             unsigned int low, unsigned int high)
+{
+    RT_ASSERT(low <= high);
+
+    wg->high_mark = high;
+    wg->low_mark = low;
+}
+
+void rt_wm_que_init(struct rt_watermark_queue *wg,
+                         unsigned int low, unsigned int high)
+{
+    rt_wm_que_set_mark(wg, low, high);
+    rt_list_init(&wg->suspended_threads);
+    wg->level = 0;
+}
+
+void rt_wm_que_dump(struct rt_watermark_queue *wg)
+{
+    struct rt_list_node *node;
+
+    rt_kprintf("wg %p: low: %d, high: %d, cur: %d\n",
+               wg, wg->low_mark, wg->high_mark, wg->level);
+    rt_kprintf("thread suspend:");
+    for (node = wg->suspended_threads.next;
+         node != &wg->suspended_threads;
+         node = node->next)
+    {
+        rt_thread_t thread;
+
+        thread = rt_list_entry(wg->suspended_threads.next,
+                               struct rt_thread,
+                               tlist);
+        rt_kprintf(" %.*s", RT_NAME_MAX, thread->name);
+    }
+    rt_kprintf("\n");
+}

+ 149 - 0
components/vbus/rt_watermark_queue.h

@@ -0,0 +1,149 @@
+/*
+ * Thread queue with water mark
+ *
+ * COPYRIGHT (C) 2014-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2014-04-16     Grissiom     first version
+ */
+
+struct rt_watermark_queue
+{
+    /* Current water level. */
+    unsigned int level;
+    unsigned int high_mark;
+    unsigned int low_mark;
+    rt_list_t suspended_threads;
+};
+
+/** Init the struct rt_watermark_queue.
+ */
+void rt_wm_que_init(struct rt_watermark_queue *wg,
+                    unsigned int low, unsigned int high);
+void rt_wm_que_set_mark(struct rt_watermark_queue *wg,
+                        unsigned int low, unsigned int high);
+void rt_wm_que_dump(struct rt_watermark_queue *wg);
+
+/* Water marks are often used in performance critical places. Benchmark shows
+ * inlining functions will have 10% performance gain in some situation(for
+ * example, VBus). So keep the inc/dec compact and inline. */
+
+/** Increase the water level.
+ *
+ * It should be called in the thread that want to raise the water level. If the
+ * current level is above the high mark, the thread will be suspended up to
+ * @timeout ticks.
+ *
+ * @return RT_EOK if water level increased successfully. -RT_EFULL on @timeout
+ * is zero and the level is above water mark. -RT_ETIMEOUT if timeout occurred.
+ */
+rt_inline rt_err_t rt_wm_que_inc(struct rt_watermark_queue *wg,
+                                 int timeout)
+{
+    rt_base_t ilvl;
+
+    /* Assert as early as possible. */
+    if (timeout != 0)
+    {
+        RT_DEBUG_IN_THREAD_CONTEXT;
+    }
+
+    ilvl = rt_hw_interrupt_disable();
+
+    while (wg->level > wg->high_mark)
+    {
+        rt_thread_t thread;
+
+        if (timeout == 0)
+        {
+            rt_hw_interrupt_enable(ilvl);
+            return -RT_EFULL;
+        }
+
+        thread = rt_thread_self();
+        thread->error = RT_EOK;
+        rt_thread_suspend(thread);
+        rt_list_insert_after(&wg->suspended_threads, &thread->tlist);
+        if (timeout > 0)
+        {
+            rt_timer_control(&(thread->thread_timer),
+                             RT_TIMER_CTRL_SET_TIME,
+                             &timeout);
+            rt_timer_start(&(thread->thread_timer));
+        }
+        rt_hw_interrupt_enable(ilvl);
+        rt_schedule();
+        if (thread->error != RT_EOK)
+            return thread->error;
+
+        ilvl = rt_hw_interrupt_disable();
+    }
+
+    wg->level++;
+
+    if (wg->level == 0)
+    {
+        wg->level = ~0;
+    }
+
+    rt_hw_interrupt_enable(ilvl);
+
+    return RT_EOK;
+}
+
+/** Decrease the water level.
+ *
+ * It should be called by the consumer that drain the water out. If the water
+ * level reached low mark, all the thread suspended in this queue will be waken
+ * up. It's safe to call this function in interrupt context.
+ */
+rt_inline void rt_wm_que_dec(struct rt_watermark_queue *wg)
+{
+    int need_sched = 0;
+    rt_base_t ilvl;
+
+    if (wg->level == 0)
+        return;
+
+    ilvl = rt_hw_interrupt_disable();
+    wg->level--;
+    if (wg->level == wg->low_mark)
+    {
+        /* There should be spaces between the low mark and high mark, so it's
+         * safe to resume all the threads. */
+        while (!rt_list_isempty(&wg->suspended_threads))
+        {
+            rt_thread_t thread;
+
+            thread = rt_list_entry(wg->suspended_threads.next,
+                                   struct rt_thread,
+                                   tlist);
+            rt_thread_resume(thread);
+            need_sched = 1;
+        }
+    }
+    rt_hw_interrupt_enable(ilvl);
+
+    if (need_sched)
+        rt_schedule();
+}

+ 79 - 0
components/vbus/share_hdr/vbus_api.h

@@ -0,0 +1,79 @@
+#ifndef __VBUS_API_H__
+#define __VBUS_API_H__
+
+#include "vbus_conf.h"
+
+#define RT_VBUS_CHANNEL_NR   32
+
+#define RT_VBUS_BLK_HEAD_SZ  4
+#define RT_VBUS_MAX_PKT_SZ   (256 - RT_VBUS_BLK_HEAD_SZ)
+
+#ifndef __ASSEMBLY__
+#include <stddef.h> /* For size_t */
+
+struct rt_vbus_blk
+{
+    unsigned char id;
+    unsigned char qos;
+    unsigned char len;
+    unsigned char reserved;
+    unsigned char data[60];
+} __attribute__((packed));
+
+struct rt_vbus_ring
+{
+    volatile size_t put_idx;
+    volatile size_t get_idx;
+    /* whether the writer is blocked on this ring. For RTT, it means the
+     * central writer thread is waiting. For Linux, it means there are some
+     * threads waiting for space to write.
+     *
+     * Note that we don't record whether there are reading thread blocked. When
+     * there is new data, the other side will always be waked up. */
+    volatile unsigned int blocked;
+    struct rt_vbus_blk blks[RT_VMM_RB_BLK_NR];
+};
+
+enum
+{
+    RT_VBUS_CHN0_CMD_ENABLE,
+    RT_VBUS_CHN0_CMD_DISABLE,
+    RT_VBUS_CHN0_CMD_SET,
+    RT_VBUS_CHN0_CMD_ACK,
+    RT_VBUS_CHN0_CMD_NAK,
+    /* If the recieving side reached high water mark. It has the right to
+     * suspend the channel. All the server/client should know about this
+     * command but the one that does not implement flow control could ignore
+     * this command. */
+    RT_VBUS_CHN0_CMD_SUSPEND,
+    RT_VBUS_CHN0_CMD_RESUME,
+    RT_VBUS_CHN0_CMD_MAX,
+};
+
+enum rt_vbus_chn_status
+{
+    /* initial state, available for reuse */
+    RT_VBUS_CHN_ST_AVAILABLE,
+    /* ACK DISABLE send(CS) or received(CS), but not ready for reuse.(the
+     * channel is not closed by this end) */
+    RT_VBUS_CHN_ST_CLOSED,
+    /* ENABLE send(client) or received(server) */
+    RT_VBUS_CHN_ST_ESTABLISHING,
+    /* ACK SET send(C) or received(S) */
+    RT_VBUS_CHN_ST_ESTABLISHED,
+    /* Channel suspended by flow control. */
+    RT_VBUS_CHN_ST_SUSPEND,
+    /* DISABLE received(CS) */
+    RT_VBUS_CHN_ST_CLOSING,
+};
+#endif
+
+#undef BUILD_ASSERT
+/* borrowed from http://lxr.linux.no/linux+v2.6.26.5/include/linux/kernel.h#L494 */
+#define BUILD_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)]))
+
+/* max length of a channel name, including the \0 */
+#define RT_VBUS_CHN_NAME_MAX   16
+
+#endif /* end of include guard: __VBUS_API_H__ */
+

+ 1371 - 0
components/vbus/vbus.c

@@ -0,0 +1,1371 @@
+/*
+ * VMM Bus
+ *
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-11-04     Grissiom     add comment
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "vbus.h"
+#include "prio_queue.h"
+#include "vbus_hw.h"
+
+//#define RT_VBUS_STATISTICS
+
+#define RT_VBUS_RB_LOW_TICK   (RT_VMM_RB_BLK_NR * 2 / 3)
+#define RT_VBUS_RB_TICK_STEP  (100)
+
+#ifndef RT_USING_LOGTRACE
+/* console could be run on vbus. If we log on it, there will be oops. */
+#define vbus_debug(...)
+#define vbus_verbose(...)
+#define vbus_info(...)
+#define vbus_error(...)
+#else // have RT_USING_LOGTRACE
+#include <log_trace.h>
+
+#if defined(log_session_lvl)
+/* Define log_trace_session as const so the compiler could optimize some log
+ * out. */
+const static struct log_trace_session _lgs = {
+    .id  = {.name = "vbus"},
+    .lvl = LOG_TRACE_LEVEL_VERBOSE,
+};
+
+#define vbus_debug(fmt, ...)   log_session_lvl(&_lgs, LOG_TRACE_LEVEL_DEBUG,   fmt, ##__VA_ARGS__)
+#define vbus_verbose(fmt, ...) log_session_lvl(&_lgs, LOG_TRACE_LEVEL_VERBOSE, fmt, ##__VA_ARGS__)
+#define vbus_info(fmt, ...)    log_session_lvl(&_lgs, LOG_TRACE_LEVEL_INFO,    fmt, ##__VA_ARGS__)
+#define vbus_error(fmt, ...)   log_session_lvl(&_lgs, LOG_TRACE_LEVEL_ERROR,    fmt, ##__VA_ARGS__)
+#else
+static struct log_trace_session _lgs = {
+    .id  = {.name = "vbus"},
+    .lvl = LOG_TRACE_LEVEL_VERBOSE,
+};
+#define vbus_debug(fmt, ...)   log_session(&_lgs, LOG_TRACE_DEBUG""fmt, ##__VA_ARGS__)
+#define vbus_verbose(fmt, ...) log_session(&_lgs, LOG_TRACE_VERBOSE""fmt, ##__VA_ARGS__)
+#define vbus_info(fmt, ...)    log_session(&_lgs, LOG_TRACE_INFO""fmt, ##__VA_ARGS__)
+#define vbus_error(fmt, ...)   log_session(&_lgs, LOG_TRACE_ERROR""fmt, ##__VA_ARGS__)
+#endif
+#endif // RT_USING_LOGTRACE
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(ar)     (sizeof(ar)/sizeof(ar[0]))
+#endif
+
+struct rt_vbus_ring *RT_VBUS_OUT_RING;
+struct rt_vbus_ring *RT_VBUS_IN_RING;
+
+const char *rt_vbus_chn_st2str[] = {
+    "available",
+    "closed",
+    "establishing",
+    "established",
+    "suspended",
+    "closing",
+};
+
+const char *rt_vbus_sess_st2str[] = {
+    "available",
+    "listening",
+    "establishing",
+};
+
+const char *rt_vbus_cmd2str[] = {
+    "ENABLE",
+    "DISABLE",
+    "SET",
+    "ACK",
+    "NAK",
+    "SUSPEND",
+    "RESUME",
+};
+
+static char* dump_cmd_pkt(unsigned char *dp, size_t dsize);
+
+/* 4 bytes for the head */
+#define LEN2BNR(len)    ((len + RT_VBUS_BLK_HEAD_SZ \
+                          + sizeof(struct rt_vbus_blk) - 1) \
+                         / sizeof(struct rt_vbus_blk))
+
+rt_inline void _ring_add_get_bnr(struct rt_vbus_ring *ring,
+                                 rt_size_t bnr)
+{
+    int nidx = ring->get_idx + bnr;
+
+    if (nidx >= RT_VMM_RB_BLK_NR)
+    {
+        nidx -= RT_VMM_RB_BLK_NR;
+    }
+    rt_vbus_smp_wmb();
+    ring->get_idx = nidx;
+}
+
+rt_inline int _bus_ring_space_nr(struct rt_vbus_ring *rg)
+{
+    int delta;
+
+    rt_vbus_smp_rmb();
+    delta = rg->get_idx - rg->put_idx;
+
+    if (delta > 0)
+    {
+        /* Put is behind the get. */
+        return delta - 1;
+    }
+    else
+    {
+        /* delta is negative. */
+        return RT_VMM_RB_BLK_NR + delta - 1;
+    }
+}
+
+struct rt_vbus_pkg {
+    rt_uint8_t id;
+    rt_uint8_t prio;
+    rt_uint8_t finished;
+    rt_uint8_t len;
+    const void *data;
+};
+
+/* chn0 is always connected */
+static enum rt_vbus_chn_status _chn_status[RT_VBUS_CHANNEL_NR];
+
+rt_inline int _chn_connected(unsigned char chnr)
+{
+    return _chn_status[chnr] == RT_VBUS_CHN_ST_ESTABLISHED ||
+           _chn_status[chnr] == RT_VBUS_CHN_ST_SUSPEND;
+}
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+#include <rt_watermark_queue.h>
+struct rt_watermark_queue _chn_wm_que[RT_VBUS_CHANNEL_NR];
+void rt_vbus_set_post_wm(unsigned char chnr, unsigned int low, unsigned int high)
+{
+    RT_ASSERT((0 < chnr) && (chnr < ARRAY_SIZE(_chn_wm_que)));
+    rt_wm_que_set_mark(&_chn_wm_que[chnr], low, high);
+}
+
+/* Threads suspended by the flow control of other side. */
+rt_list_t _chn_suspended_threads[RT_VBUS_CHANNEL_NR];
+
+struct
+{
+    unsigned int level;
+    unsigned int high_mark;
+    unsigned int low_mark;
+    /* The suspend command does not have ACK. So if the other side still
+     * sending pkg after SUSPEND, warn it again. Also use it as a flag that
+     * tell me whether are we dropping from the high mark or not when reaching
+     * the low mark. */
+    unsigned int last_warn;
+} _chn_recv_wm[RT_VBUS_CHANNEL_NR];
+
+void rt_vbus_set_recv_wm(unsigned char chnr, unsigned int low, unsigned int high)
+{
+    RT_ASSERT((0 < chnr) && (chnr < ARRAY_SIZE(_chn_recv_wm)));
+    _chn_recv_wm[chnr].low_mark = low;
+    _chn_recv_wm[chnr].high_mark = high;
+}
+#else
+void rt_vbus_set_recv_wm(unsigned char chnr, unsigned int low, unsigned int high)
+{}
+void rt_vbus_set_post_wm(unsigned char chnr, unsigned int low, unsigned int high)
+{}
+#endif
+
+struct {
+    rt_vbus_event_listener indicate;
+    void *ctx;
+} _vbus_rx_indi[RT_VBUS_EVENT_ID_MAX][RT_VBUS_CHANNEL_NR];
+
+void rt_vbus_register_listener(unsigned char chnr,
+                               enum rt_vbus_event_id eve,
+                               rt_vbus_event_listener indi,
+                               void *ctx)
+{
+    RT_ASSERT(chnr != 0 && chnr < RT_VBUS_CHANNEL_NR);
+    RT_ASSERT(eve < sizeof(_vbus_rx_indi)/sizeof(_vbus_rx_indi[0]));
+
+    _vbus_rx_indi[eve][chnr].indicate = indi;
+    _vbus_rx_indi[eve][chnr].ctx = ctx;
+}
+
+static void _vbus_indicate(enum rt_vbus_event_id eve, unsigned char chnr)
+{
+    RT_ASSERT(eve < sizeof(_vbus_rx_indi)/sizeof(_vbus_rx_indi[0]));
+
+    if (_vbus_rx_indi[eve][chnr].indicate)
+        _vbus_rx_indi[eve][chnr].indicate(_vbus_rx_indi[eve][chnr].ctx);
+}
+
+#define _BUS_OUT_THRD_STACK_SZ  2048
+#define _BUS_OUT_THRD_PRIO      8
+#define _BUS_OUT_PKG_NR         RT_VMM_RB_BLK_NR
+
+static struct rt_thread _bus_out_thread;
+static rt_uint8_t _bus_out_thread_stack[_BUS_OUT_THRD_STACK_SZ];
+struct rt_prio_queue *_bus_out_que;
+
+static void _bus_out_entry(void *param)
+{
+    struct rt_vbus_pkg dpkg;
+
+    _bus_out_que = rt_prio_queue_create("vbus",
+                                        _BUS_OUT_PKG_NR,
+                                        sizeof(struct rt_vbus_pkg));
+
+    if (!_bus_out_que)
+    {
+        rt_kprintf("could not create vmm bus queue\n");
+        return;
+    }
+
+    while (rt_prio_queue_pop(_bus_out_que, &dpkg,
+                             RT_WAITING_FOREVER) == RT_EOK)
+    {
+        int sp;
+        rt_uint32_t nxtidx;
+        const int dnr = LEN2BNR(dpkg.len);
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+        rt_wm_que_dec(&_chn_wm_que[dpkg.id]);
+#endif
+
+        if (!_chn_connected(dpkg.id))
+            continue;
+
+        sp = _bus_ring_space_nr(RT_VBUS_OUT_RING);
+
+        vbus_debug("vmm bus out"
+                   "(data: %p, len: %d, prio: %d, id: %d)\n",
+                   dpkg.data, dpkg.len, dpkg.prio, dpkg.id);
+
+        /* wait for enough space */
+        while (sp < dnr)
+        {
+            rt_ubase_t lvl = rt_hw_interrupt_disable();
+
+            RT_VBUS_OUT_RING->blocked = 1;
+            rt_vbus_smp_wmb();
+
+            /* kick the guest, hoping this could force it do the work */
+            rt_vbus_tick(0, RT_VBUS_GUEST_VIRQ);
+
+            rt_thread_suspend(rt_thread_self());
+            rt_schedule();
+
+            RT_VBUS_OUT_RING->blocked = 0;
+
+            rt_hw_interrupt_enable(lvl);
+
+            sp = _bus_ring_space_nr(RT_VBUS_OUT_RING);
+        }
+
+        nxtidx = RT_VBUS_OUT_RING->put_idx + dnr;
+
+        RT_VBUS_OUT_RING->blks[RT_VBUS_OUT_RING->put_idx].id  = dpkg.id;
+        RT_VBUS_OUT_RING->blks[RT_VBUS_OUT_RING->put_idx].qos = dpkg.prio;
+        RT_VBUS_OUT_RING->blks[RT_VBUS_OUT_RING->put_idx].len = dpkg.len;
+
+        if (nxtidx >= RT_VMM_RB_BLK_NR)
+        {
+            unsigned int tailsz;
+
+            tailsz = (RT_VMM_RB_BLK_NR - RT_VBUS_OUT_RING->put_idx)
+                * sizeof(RT_VBUS_OUT_RING->blks[0]) - RT_VBUS_BLK_HEAD_SZ;
+
+            /* the remaining block is sufficient for the data */
+            if (tailsz > dpkg.len)
+                tailsz = dpkg.len;
+
+            rt_memcpy(&RT_VBUS_OUT_RING->blks[RT_VBUS_OUT_RING->put_idx].data,
+                      dpkg.data, tailsz);
+            rt_memcpy(&RT_VBUS_OUT_RING->blks[0],
+                      ((char*)dpkg.data)+tailsz,
+                      dpkg.len - tailsz);
+
+            rt_vbus_smp_wmb();
+            RT_VBUS_OUT_RING->put_idx = nxtidx - RT_VMM_RB_BLK_NR;
+        }
+        else
+        {
+            rt_memcpy(&RT_VBUS_OUT_RING->blks[RT_VBUS_OUT_RING->put_idx].data,
+                      dpkg.data, dpkg.len);
+
+            rt_vbus_smp_wmb();
+            RT_VBUS_OUT_RING->put_idx = nxtidx;
+        }
+
+        rt_vbus_smp_wmb();
+        rt_vbus_tick(0, RT_VBUS_GUEST_VIRQ);
+
+        if (dpkg.finished)
+        {
+            _vbus_indicate(RT_VBUS_EVENT_ID_TX, dpkg.id);
+        }
+    }
+    RT_ASSERT(0);
+}
+
+void rt_vbus_resume_out_thread(void)
+{
+    rt_thread_resume(&_bus_out_thread);
+    rt_schedule();
+}
+
+rt_err_t rt_vbus_post(rt_uint8_t id,
+                      rt_uint8_t prio,
+                      const void *data,
+                      rt_size_t size,
+                      rt_int32_t timeout)
+{
+    rt_err_t err = RT_EOK;
+    struct rt_vbus_pkg pkg;
+    unsigned int putsz;
+    const unsigned char *dp;
+
+    if (!_bus_out_que)
+    {
+        rt_kprintf("post (data: %p, size: %d, timeout: %d) "
+                   "to bus before initialition\n",
+                   data, size, timeout);
+        return -RT_ERROR;
+    }
+
+    if (id >= RT_VBUS_CHANNEL_NR)
+        return -RT_ERROR;
+
+    if (timeout != 0)
+    {
+        RT_DEBUG_IN_THREAD_CONTEXT;
+    }
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+    while (_chn_status[id] == RT_VBUS_CHN_ST_SUSPEND)
+    {
+        rt_thread_t thread;
+
+        if (timeout == 0)
+        {
+            return -RT_EFULL;
+        }
+
+        thread = rt_thread_self();
+        thread->error = RT_EOK;
+        /* We only touch the _chn_suspended_threads in thread, so lock the
+         * scheduler is enough. */
+        rt_enter_critical();
+        rt_thread_suspend(thread);
+
+        rt_list_insert_after(&_chn_suspended_threads[id], &thread->tlist);
+        if (timeout > 0)
+        {
+            rt_timer_control(&(thread->thread_timer),
+                             RT_TIMER_CTRL_SET_TIME,
+                             &timeout);
+            rt_timer_start(&(thread->thread_timer));
+        }
+        /* rt_exit_critical will do schedule on need. */
+        rt_exit_critical();
+
+        if (thread->error != RT_EOK)
+            return thread->error;
+    }
+#endif
+
+    if (_chn_status[id] != RT_VBUS_CHN_ST_ESTABLISHED)
+        return -RT_ERROR;
+
+    dp       = data;
+    pkg.id   = id;
+    pkg.prio = prio;
+    for (putsz = 0; size; size -= putsz)
+    {
+        pkg.data = dp;
+
+        if (size > RT_VBUS_MAX_PKT_SZ)
+        {
+            putsz = RT_VBUS_MAX_PKT_SZ;
+            pkg.finished = 0;
+        }
+        else
+        {
+            putsz = size;
+            pkg.finished = 1;
+        }
+
+        pkg.len = putsz;
+        dp += putsz;
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+        err = rt_wm_que_inc(&_chn_wm_que[id], timeout);
+        if (err != RT_EOK)
+            break;
+#endif
+
+        vbus_debug("post (data: %p(%d), size: %d, finshed: %d, timeout: %d)\n",
+                   pkg.data, ((unsigned char*)pkg.data)[0],
+                   pkg.len, pkg.finished, timeout);
+
+        err = rt_prio_queue_push(_bus_out_que, prio, &pkg, timeout);
+        if (err != RT_EOK)
+            break;
+    }
+
+    return err;
+}
+
+struct rt_completion _chn0_post_cmp;
+
+void _chn0_tx_listener(void *p)
+{
+    rt_completion_done(&_chn0_post_cmp);
+}
+
+/* Posts in channel0 should be sync. */
+static rt_err_t _chn0_post(const void *data,
+                               rt_size_t size,
+                               int timeout)
+{
+    rt_err_t err;
+
+    rt_completion_init(&_chn0_post_cmp);
+    err = rt_vbus_post(0, 0, data, size, timeout);
+    if (err != RT_EOK)
+        return err;
+    return rt_completion_wait(&_chn0_post_cmp, timeout);
+}
+
+#define _BUS_IN_THRD_STACK_SZ  1024
+#define _BUS_IN_THRD_PRIO      (_BUS_OUT_THRD_PRIO+1)
+#if (_BUS_IN_THRD_PRIO == RT_THREAD_PRIORITY_MAX)
+#error "_BUS_OUT_THRD_PRIO too low"
+#endif
+
+static struct rt_thread _bus_in_thread;
+static rt_uint8_t _bus_in_thread_stack[_BUS_OUT_THRD_STACK_SZ];
+static struct rt_semaphore _bus_in_sem;
+static struct rt_event     _bus_in_event;
+/* {head, tail} */
+#define _IN_ACT_HEAD 0
+#define _IN_ACT_TAIL 1
+static struct rt_vbus_data *_bus_in_action[RT_VBUS_CHANNEL_NR][2];
+#ifdef RT_VBUS_STATISTICS
+static unsigned int _bus_in_action_nr[RT_VBUS_CHANNEL_NR];
+#endif
+
+static void rt_vbus_notify_chn(unsigned char chnr, rt_err_t err)
+{
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+    /* TODO: get rid of this */
+    /* Protect the list. */
+    rt_enter_critical();
+    while (!rt_list_isempty(&_chn_suspended_threads[chnr]))
+    {
+        rt_thread_t thread;
+
+        thread = rt_list_entry(_chn_suspended_threads[chnr].next,
+                               struct rt_thread,
+                               tlist);
+        thread->error = err;
+        rt_thread_resume(thread);
+    }
+    rt_exit_critical();
+#endif
+    rt_event_send(&_bus_in_event, 1 << chnr);
+}
+
+static void rt_vbus_notify_set(rt_uint32_t set)
+{
+    rt_event_send(&_bus_in_event, set);
+}
+
+rt_err_t rt_vbus_listen_on(rt_uint8_t chnr,
+                           rt_int32_t timeout)
+{
+    rt_uint32_t notuse;
+
+    if (chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR || !_chn_connected(chnr))
+        return -RT_EIO;
+
+    return rt_event_recv(&_bus_in_event, 1 << chnr,
+                         RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                         timeout, &notuse);
+}
+
+void rt_vbus_data_push(unsigned int id, struct rt_vbus_data *act)
+{
+    rt_ubase_t lvl;
+
+    RT_ASSERT(0 < id && id < RT_VBUS_CHANNEL_NR);
+
+    lvl = rt_hw_interrupt_disable();
+
+    if (_bus_in_action[id][_IN_ACT_HEAD] == RT_NULL)
+    {
+        _bus_in_action[id][_IN_ACT_HEAD] = act;
+        _bus_in_action[id][_IN_ACT_TAIL] = act;
+    }
+    else
+    {
+        _bus_in_action[id][_IN_ACT_TAIL]->next = act;
+        _bus_in_action[id][_IN_ACT_TAIL] = act;
+    }
+
+#ifdef RT_VBUS_STATISTICS
+    _bus_in_action_nr[id]++;
+#endif
+
+    rt_hw_interrupt_enable(lvl);
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+    _chn_recv_wm[id].level++;
+    if (_chn_recv_wm[id].level == 0)
+        _chn_recv_wm[id].level = ~0;
+    if (_chn_recv_wm[id].level > _chn_recv_wm[id].high_mark &&
+        _chn_recv_wm[id].level > _chn_recv_wm[id].last_warn)
+    {
+        unsigned char buf[2];
+
+        buf[0] = RT_VBUS_CHN0_CMD_SUSPEND;
+        buf[1] = id;
+        vbus_debug("%s --> remote\n", dump_cmd_pkt(buf, sizeof(buf)));
+        _chn0_post(buf, sizeof(buf), RT_WAITING_FOREVER);
+        /* Warn the other side in 100 more pkgs. */
+        _chn_recv_wm[id].last_warn = _chn_recv_wm[id].level + 100;
+    }
+#endif
+}
+
+struct rt_vbus_data* rt_vbus_data_pop(unsigned int id)
+{
+    struct rt_vbus_data *act;
+    rt_ubase_t lvl;
+
+    RT_ASSERT(0 < id && id < RT_VBUS_CHANNEL_NR);
+
+    lvl = rt_hw_interrupt_disable();
+
+    act = _bus_in_action[id][_IN_ACT_HEAD];
+    if (act)
+    {
+        _bus_in_action[id][_IN_ACT_HEAD] = act->next;
+    }
+
+    rt_hw_interrupt_enable(lvl);
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+    if (_chn_recv_wm[id].level != 0)
+    {
+        _chn_recv_wm[id].level--;
+        if (_chn_recv_wm[id].level <= _chn_recv_wm[id].low_mark &&
+            _chn_recv_wm[id].last_warn > _chn_recv_wm[id].low_mark)
+        {
+            unsigned char buf[2];
+
+            buf[0] = RT_VBUS_CHN0_CMD_RESUME;
+            buf[1] = id;
+            vbus_debug("%s --> remote\n", dump_cmd_pkt(buf, sizeof(buf)));
+            _chn0_post(buf, sizeof(buf), RT_WAITING_FOREVER);
+            _chn_recv_wm[id].last_warn = 0;
+        }
+    }
+#endif
+    return act;
+}
+
+/* dump cmd that is not start with ACK/NAK */
+static size_t __dump_naked_cmd(char *dst, size_t lsize,
+                               unsigned char *dp, size_t dsize)
+{
+    size_t len;
+    if (dp[0] == RT_VBUS_CHN0_CMD_DISABLE ||
+        dp[0] == RT_VBUS_CHN0_CMD_SUSPEND ||
+        dp[0] == RT_VBUS_CHN0_CMD_RESUME)
+    {
+        len = rt_snprintf(dst, lsize, "%s %d",
+                          rt_vbus_cmd2str[dp[0]], dp[1]);
+    }
+    else if (dp[0] == RT_VBUS_CHN0_CMD_ENABLE)
+    {
+        len = rt_snprintf(dst, lsize, "%s %s",
+                          rt_vbus_cmd2str[dp[0]], dp+1);
+    }
+    else if (dp[0] < RT_VBUS_CHN0_CMD_MAX)
+    {
+        len = rt_snprintf(dst, lsize, "%s %s %d",
+                          rt_vbus_cmd2str[dp[0]],
+                          dp+1, dp[2+rt_strlen((char*)dp+1)]);
+    }
+    else
+    {
+        len = rt_snprintf(dst, lsize, "(invalid)%d %d",
+                          dp[0], dp[1]);
+    }
+    return len;
+}
+
+static char _cmd_dump_buf[64];
+static char* dump_cmd_pkt(unsigned char *dp, size_t dsize)
+{
+    size_t len;
+
+    if (dp[0] == RT_VBUS_CHN0_CMD_ACK || dp[0] == RT_VBUS_CHN0_CMD_NAK )
+    {
+        len = rt_snprintf(_cmd_dump_buf, sizeof(_cmd_dump_buf),
+                          "%s ", rt_vbus_cmd2str[dp[0]]);
+        len += __dump_naked_cmd(_cmd_dump_buf+len, sizeof(_cmd_dump_buf)-len,
+                                dp+1, dsize-1);
+    }
+    else
+    {
+        len = __dump_naked_cmd(_cmd_dump_buf, sizeof(_cmd_dump_buf),
+                               dp, dsize);
+    }
+
+    if (len > sizeof(_cmd_dump_buf) - 1)
+        len = sizeof(_cmd_dump_buf) - 1;
+
+    _cmd_dump_buf[len] = '\0';
+    return _cmd_dump_buf;
+}
+
+static rt_err_t _chn0_echo_with(rt_uint8_t prefix,
+                                rt_uint32_t dsize,
+                                unsigned char *dp)
+{
+    rt_err_t err;
+    unsigned char *resp;
+
+    resp = rt_malloc(dsize+1);
+    if (!resp)
+        return -RT_ENOMEM;
+    *resp = prefix;
+    rt_memcpy(resp+1, dp, dsize);
+    vbus_verbose("%s --> remote\n", dump_cmd_pkt(resp, dsize+1));
+
+    err = _chn0_post(resp, dsize+1, RT_WAITING_FOREVER);
+
+    rt_free(resp);
+
+    return err;
+}
+
+static rt_err_t _chn0_nak(rt_uint32_t dsize, unsigned char *dp)
+{
+    return _chn0_echo_with(RT_VBUS_CHN0_CMD_NAK, dsize, dp);
+}
+
+static rt_err_t _chn0_ack(rt_uint32_t dsize, unsigned char *dp)
+{
+    return _chn0_echo_with(RT_VBUS_CHN0_CMD_ACK, dsize, dp);
+}
+
+enum _vbus_session_st
+{
+    SESSIOM_AVAILABLE,
+    SESSIOM_LISTENING,
+    SESSIOM_ESTABLISHING,
+};
+
+struct rt_vbus_conn_session
+{
+    /* negative value means error */
+    int chnr;
+    enum _vbus_session_st st;
+    struct rt_completion cmp;
+    struct rt_vbus_request *req;
+};
+
+static struct rt_vbus_conn_session _sess[RT_VBUS_CHANNEL_NR/2];
+
+static int _sess_find(const unsigned char *name,
+                      enum _vbus_session_st st)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(_sess); i++)
+    {
+        if (_sess[i].st == st && _sess[i].req->name &&
+            rt_strcmp(_sess[i].req->name, (char*)name) == 0)
+            break;
+    }
+    return i;
+}
+
+static int _chn0_actor(unsigned char *dp, size_t dsize)
+{
+    if (*dp != RT_VBUS_CHN0_CMD_SUSPEND && *dp != RT_VBUS_CHN0_CMD_RESUME)
+        vbus_verbose("local <-- %s\n", dump_cmd_pkt(dp, dsize));
+
+    switch (*dp)
+    {
+    case RT_VBUS_CHN0_CMD_ENABLE:
+        {
+            int i, chnr;
+            rt_err_t err;
+            unsigned char *resp;
+
+            i = _sess_find(dp+1, SESSIOM_LISTENING);
+            if (i == ARRAY_SIZE(_sess))
+            {
+                _chn0_nak(dsize, dp);
+                break;
+            }
+
+            for (chnr = 0; chnr < ARRAY_SIZE(_chn_status); chnr++)
+            {
+                if (_chn_status[chnr] == RT_VBUS_CHN_ST_AVAILABLE)
+                    break;
+            }
+            if (chnr == ARRAY_SIZE(_chn_status))
+            {
+                _chn0_nak(dsize, dp);
+                break;
+            }
+
+            resp = rt_malloc(dsize + 1);
+            if (!resp)
+                break;
+
+            *resp = RT_VBUS_CHN0_CMD_SET;
+            rt_memcpy(resp+1, dp+1, dsize-1);
+            resp[dsize] = chnr;
+
+            rt_vbus_set_recv_wm(chnr, _sess[i].req->recv_wm.low, _sess[i].req->recv_wm.high);
+            rt_vbus_set_post_wm(chnr, _sess[i].req->post_wm.low, _sess[i].req->post_wm.high);
+
+            vbus_verbose("%s --> remote\n", dump_cmd_pkt(resp, dsize+1));
+            err = _chn0_post(resp, dsize+1, RT_WAITING_FOREVER);
+
+            if (err == RT_EOK)
+            {
+                _sess[i].st   = SESSIOM_ESTABLISHING;
+                vbus_debug("set sess %d st: %s\n", i,
+                           rt_vbus_sess_st2str[_sess[i].st]);
+                _sess[i].chnr = chnr;
+                _chn_status[chnr] = RT_VBUS_CHN_ST_ESTABLISHING;
+            }
+            rt_free(resp);
+        }
+        break;
+    case RT_VBUS_CHN0_CMD_SET:
+        {
+            int i, chnr;
+
+            i = _sess_find(dp+1, SESSIOM_ESTABLISHING);
+            if (i == ARRAY_SIZE(_sess))
+            {
+                vbus_verbose("drop spurious packet\n");
+                break;
+            }
+
+            chnr = dp[1+rt_strlen((const char*)dp+1)+1];
+
+            if (chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR)
+            {
+                vbus_verbose("SET wrong chnr %d\n", chnr);
+                break;
+            }
+            if (_chn_status[chnr] != RT_VBUS_CHN_ST_AVAILABLE)
+            {
+                _chn0_nak(dsize, dp);
+                vbus_verbose("SET wrong chnr status %d, %s\n",
+                             chnr, rt_vbus_chn_st2str[_chn_status[chnr]]);
+                break;
+            }
+
+            rt_vbus_set_recv_wm(chnr, _sess[i].req->recv_wm.low, _sess[i].req->recv_wm.high);
+            rt_vbus_set_post_wm(chnr, _sess[i].req->post_wm.low, _sess[i].req->post_wm.high);
+
+            if (_chn0_ack(dsize, dp) >= 0)
+            {
+                _sess[i].chnr = chnr;
+                _chn_status[chnr] = RT_VBUS_CHN_ST_ESTABLISHED;
+                vbus_debug("chn %d %s\n", chnr,
+                           rt_vbus_chn_st2str[_chn_status[chnr]]);
+                rt_completion_done(&_sess[i].cmp);
+            }
+        }
+        break;
+    case RT_VBUS_CHN0_CMD_ACK:
+        if (dp[1] == RT_VBUS_CHN0_CMD_SET)
+        {
+            int i, chnr;
+
+            i = _sess_find(dp+2, SESSIOM_ESTABLISHING);
+            if (i == ARRAY_SIZE(_sess))
+                /* drop that spurious packet */
+                break;
+
+            chnr = dp[1+rt_strlen((const char*)dp+2)+2];
+
+            _sess[i].chnr = chnr;
+            _chn_status[chnr] = RT_VBUS_CHN_ST_ESTABLISHED;
+            vbus_debug("chn %d %s\n", chnr,
+                       rt_vbus_chn_st2str[_chn_status[chnr]]);
+            rt_completion_done(&_sess[i].cmp);
+        }
+        else if (dp[1] == RT_VBUS_CHN0_CMD_DISABLE)
+        {
+            unsigned char chnr = dp[2];
+
+            if (chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR)
+                break;
+
+            /* We could only get here by sending DISABLE command, which is
+             * initiated by the rt_vbus_close_chn. */
+            _chn_status[chnr] = RT_VBUS_CHN_ST_AVAILABLE;
+
+            _vbus_indicate(RT_VBUS_EVENT_ID_DISCONN, chnr);
+            /* notify the thread that the channel has been closed */
+            rt_vbus_notify_chn(chnr, -RT_ERROR);
+        }
+        else
+        {
+            vbus_info("invalid ACK for %d\n", dp[1]);
+        }
+        break;
+    case RT_VBUS_CHN0_CMD_DISABLE:
+        {
+            unsigned char chnr = dp[1];
+
+            if (chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR)
+                break;
+
+            _chn_status[chnr] = RT_VBUS_CHN_ST_CLOSING;
+
+            _chn0_ack(dsize, dp);
+
+            _vbus_indicate(RT_VBUS_EVENT_ID_DISCONN, chnr);
+            /* notify the thread that the channel has been closed */
+            rt_vbus_notify_chn(chnr, -RT_ERROR);
+        }
+        break;
+    case RT_VBUS_CHN0_CMD_SUSPEND:
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+        {
+            unsigned char chnr = dp[1];
+
+            if (chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR)
+                break;
+
+            if (_chn_status[chnr] != RT_VBUS_CHN_ST_ESTABLISHED)
+                break;
+
+            _chn_status[chnr] = RT_VBUS_CHN_ST_SUSPEND;
+        }
+#endif
+        break;
+    case RT_VBUS_CHN0_CMD_RESUME:
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+        {
+            unsigned char chnr = dp[1];
+
+            if (chnr == 0 || chnr >= RT_VBUS_CHANNEL_NR)
+                break;
+
+            if (_chn_status[chnr] != RT_VBUS_CHN_ST_SUSPEND)
+                break;
+
+            _chn_status[chnr] = RT_VBUS_CHN_ST_ESTABLISHED;
+
+            /* Protect the list. */
+            rt_enter_critical();
+            while (!rt_list_isempty(&_chn_suspended_threads[chnr]))
+            {
+                rt_thread_t thread;
+
+                thread = rt_list_entry(_chn_suspended_threads[chnr].next,
+                                       struct rt_thread,
+                                       tlist);
+                rt_thread_resume(thread);
+            }
+            rt_exit_critical();
+        }
+#endif
+        break;
+    case RT_VBUS_CHN0_CMD_NAK:
+        if (dp[1] == RT_VBUS_CHN0_CMD_ENABLE)
+        {
+            int i;
+
+            i = _sess_find(dp+2, SESSIOM_ESTABLISHING);
+            if (i == ARRAY_SIZE(_sess))
+                /* drop that spurious packet */
+                break;
+
+            _sess[i].chnr = -RT_EIO;
+            rt_completion_done(&_sess[i].cmp);
+        }
+        else if (dp[1] == RT_VBUS_CHN0_CMD_SET)
+        {
+            vbus_info("NAK for %d not implemented\n", dp[1]);
+        }
+        else
+        {
+            vbus_info("invalid NAK for %d\n", dp[1]);
+        }
+        break;
+    default:
+        /* just ignore the invalid cmd */
+        vbus_info("drop unknown cmd %d on chn0\n", *dp);
+        break;
+    };
+
+    return RT_EOK;
+}
+
+int rt_vbus_request_chn(struct rt_vbus_request *req,
+                        int timeout)
+{
+    int i, chnr, err;
+	size_t plen = rt_strlen(req->name) + 2;
+	unsigned char *pbuf;
+    rt_ubase_t lvl;
+
+    lvl = rt_hw_interrupt_disable();
+    for (i = 0; i < ARRAY_SIZE(_sess); i++)
+    {
+        if (_sess[i].st == SESSIOM_AVAILABLE)
+            break;
+    }
+    if (i == ARRAY_SIZE(_sess))
+    {
+        rt_hw_interrupt_enable(lvl);
+        return -RT_ERROR;
+    }
+
+    rt_completion_init(&_sess[i].cmp);
+    _sess[i].req = req;
+
+    if (req->is_server)
+    {
+        _sess[i].st = SESSIOM_LISTENING;
+        rt_hw_interrupt_enable(lvl);
+
+        vbus_debug("request listening %s on %d\n", req->name, i);
+
+        /* always wait on the condition */
+        err = RT_EOK;
+        goto _waitforcmp;
+    }
+
+	pbuf = rt_malloc(plen);
+	if (!pbuf)
+    {
+        rt_hw_interrupt_enable(lvl);
+        return -RT_ENOMEM;
+    }
+
+    _sess[i].st = SESSIOM_ESTABLISHING;
+    rt_hw_interrupt_enable(lvl);
+
+    pbuf[0] = RT_VBUS_CHN0_CMD_ENABLE;
+    rt_memcpy(pbuf+1, req->name, plen-1);
+    vbus_verbose("%s --> remote\n", dump_cmd_pkt(pbuf, plen));
+
+	err = _chn0_post(pbuf, plen, RT_WAITING_FOREVER);
+    rt_free(pbuf);
+
+_waitforcmp:
+    if (err == RT_EOK)
+        err = rt_completion_wait(&_sess[i].cmp, timeout);
+
+    vbus_debug("request wait cmp done %d, chnr %d\n", err, _sess[i].chnr);
+
+    if (err)
+    {
+        /* cleanup the mass when the wait is time out but we have done some job
+         */
+        if (_sess[i].st == SESSIOM_ESTABLISHING)
+            _chn_status[_sess[i].chnr] = RT_VBUS_CHN_ST_AVAILABLE;
+        chnr = err;
+        goto Out;
+    }
+
+    RT_ASSERT(_sess[i].chnr != 0);
+
+    chnr = _sess[i].chnr;
+
+Out:
+    /* detach the sess as we finished the job */
+    _sess[i].st = SESSIOM_AVAILABLE;
+    _sess[i].req = RT_NULL;
+
+    return chnr;
+}
+
+void rt_vbus_close_chn(unsigned char chnr)
+{
+    void *p;
+    rt_err_t err;
+    unsigned char buf[2];
+
+    buf[0] = RT_VBUS_CHN0_CMD_DISABLE;
+    buf[1] = chnr;
+
+    RT_ASSERT(0 < chnr && chnr < RT_VBUS_CHANNEL_NR);
+
+    if (_chn_status[chnr] == RT_VBUS_CHN_ST_CLOSED ||
+        _chn_status[chnr] == RT_VBUS_CHN_ST_CLOSING)
+    {
+        _chn_status[chnr] = RT_VBUS_CHN_ST_AVAILABLE;
+        return;
+    }
+
+    if (!_chn_connected(chnr))
+        return;
+
+    _chn_status[chnr] = RT_VBUS_CHN_ST_CLOSING;
+    vbus_info("%s --> remote\n", dump_cmd_pkt(buf, sizeof(buf)));
+    err = _chn0_post(&buf, sizeof(buf), RT_WAITING_FOREVER);
+    if (err == RT_EOK)
+        /* wait for the ack */
+        rt_vbus_listen_on(chnr, 10 * RT_TICK_PER_SECOND);
+
+    /* cleanup the remaining data */
+    for (p = rt_vbus_data_pop(chnr); p; p = rt_vbus_data_pop(chnr))
+        rt_free(p);
+    /* FIXME: there is a chance that there are some data left on the send
+     * buffer. So if we connect other channel with the same number immediately,
+     * the new channel will receive some garbage data. However, this is highly
+     * un-probable. */
+}
+
+#ifdef RT_VBUS_STATISTICS
+static unsigned int _total_data_sz;
+#endif
+
+static void _bus_in_entry(void *param)
+{
+    rt_sem_init(&_bus_in_sem, "vbus", 0, RT_IPC_FLAG_FIFO);
+    rt_event_init(&_bus_in_event, "vbus", RT_IPC_FLAG_FIFO);
+    rt_memset(_bus_in_action, 0, sizeof(_bus_in_action));
+
+    while (rt_sem_take(&_bus_in_sem,
+                       RT_WAITING_FOREVER) == RT_EOK)
+    {
+        rt_uint32_t event_set = 0;
+
+        /* while(not empty) */
+        while (RT_VBUS_IN_RING->get_idx != RT_VBUS_IN_RING->put_idx)
+        {
+            unsigned int id, nxtidx;
+            rt_size_t size;
+            struct rt_vbus_data *act;
+
+            rt_vbus_smp_rmb();
+            size = RT_VBUS_IN_RING->blks[RT_VBUS_IN_RING->get_idx].len;
+            id = RT_VBUS_IN_RING->blks[RT_VBUS_IN_RING->get_idx].id;
+
+            vbus_debug("vmm bus in: chnr %d, size %d\n", id, size);
+
+            /* Suspended channel can still recv data. */
+            if (id > RT_VBUS_CHANNEL_NR || !_chn_connected(id))
+            {
+                vbus_error("drop on invalid chn %d\n", id);
+                /* drop the invalid packet */
+                _ring_add_get_bnr(RT_VBUS_IN_RING, LEN2BNR(size));
+                continue;
+            }
+
+            if (id == 0)
+            {
+                if (size > 60)
+                    vbus_error("too big(%d) packet on chn0\n", size);
+                else
+                    _chn0_actor(RT_VBUS_IN_RING->blks[RT_VBUS_IN_RING->get_idx].data, size);
+                _ring_add_get_bnr(RT_VBUS_IN_RING, LEN2BNR(size));
+                continue;
+            }
+
+#ifdef RT_VBUS_STATISTICS
+            _total_data_sz += size;
+#endif
+
+            act = rt_malloc(sizeof(*act) + size);
+            if (act == RT_NULL)
+            {
+                //vbus_error("drop on OOM (%d, %d)\n", id, size);
+                /* drop the packet on malloc fall */
+                _ring_add_get_bnr(RT_VBUS_IN_RING, LEN2BNR(size));
+                continue;
+            }
+
+            act->size = size;
+            act->next = RT_NULL;
+
+            nxtidx = RT_VBUS_IN_RING->get_idx + LEN2BNR(size);
+            if (nxtidx >= RT_VMM_RB_BLK_NR)
+            {
+                unsigned int tailsz;
+
+                tailsz = (RT_VMM_RB_BLK_NR - RT_VBUS_IN_RING->get_idx)
+                          * sizeof(RT_VBUS_IN_RING->blks[0]) - RT_VBUS_BLK_HEAD_SZ;
+
+                /* the remaining block is sufficient for the data */
+                if (tailsz > size)
+                    tailsz = size;
+
+                rt_memcpy(act+1, &RT_VBUS_IN_RING->blks[RT_VBUS_IN_RING->get_idx].data, tailsz);
+                rt_memcpy((char*)(act+1) + tailsz, &RT_VBUS_IN_RING->blks[0], size - tailsz);
+
+                /* It shall make sure the CPU has finished reading the item
+                 * before it writes the new tail pointer, which will erase the
+                 * item. */
+                rt_vbus_smp_wmb();
+                RT_VBUS_IN_RING->get_idx = nxtidx - RT_VMM_RB_BLK_NR;
+            }
+            else
+            {
+                rt_memcpy(act+1, &RT_VBUS_IN_RING->blks[RT_VBUS_IN_RING->get_idx].data, size);
+
+                rt_vbus_smp_wmb();
+                RT_VBUS_IN_RING->get_idx = nxtidx;
+            }
+
+            rt_vbus_data_push(id, act);
+            _vbus_indicate(RT_VBUS_EVENT_ID_RX, id);
+            event_set |= 1 << id;
+
+            if (RT_VBUS_IN_RING->blocked)
+                rt_vbus_tick(0, RT_VBUS_GUEST_VIRQ);
+        }
+
+        if (event_set != 0)
+            rt_vbus_notify_set(event_set);
+    }
+    RT_ASSERT(0);
+}
+
+void rt_vbus_isr(int irqnr, void *param)
+{
+    if (RT_VBUS_OUT_RING->blocked)
+        rt_vbus_resume_out_thread();
+
+    rt_sem_release(&_bus_in_sem);
+    rt_vbus_hw_eoi(irqnr, param);
+}
+
+int rt_vbus_init(void *outr, void *inr)
+{
+    int i;
+
+#ifdef RT_USING_LOGTRACE
+    log_trace_register_session(&_lgs);
+#endif
+
+    if (outr > inr)
+    {
+        RT_ASSERT((char*)outr - (char*)inr >= sizeof(struct rt_vbus_ring));
+    }
+    else
+    {
+        RT_ASSERT((char*)inr - (char*)outr >= sizeof(struct rt_vbus_ring));
+    }
+
+    RT_VBUS_OUT_RING = outr;
+    RT_VBUS_IN_RING  = inr;
+
+    rt_memset(RT_VBUS_OUT_RING, 0, sizeof(*RT_VBUS_OUT_RING));
+    rt_memset(RT_VBUS_IN_RING,  0, sizeof(*RT_VBUS_IN_RING));
+    _chn_status[0] = RT_VBUS_CHN_ST_ESTABLISHED;
+    for (i = 1; i < ARRAY_SIZE(_chn_status); i++)
+    {
+        _chn_status[i] = RT_VBUS_CHN_ST_AVAILABLE;
+    }
+    for (i = 0; i < ARRAY_SIZE(_sess); i++)
+    {
+        _sess[i].req = RT_NULL;
+        _sess[i].st  = SESSIOM_AVAILABLE;
+    }
+    _vbus_rx_indi[RT_VBUS_EVENT_ID_TX][0].indicate = _chn0_tx_listener;
+    _vbus_rx_indi[RT_VBUS_EVENT_ID_TX][0].ctx = RT_NULL;
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+    for (i = 0; i < ARRAY_SIZE(_chn_wm_que); i++)
+    {
+        rt_wm_que_init(&_chn_wm_que[i],
+                       RT_VMM_RB_BLK_NR / 3,
+                       RT_VMM_RB_BLK_NR * 2 / 3);
+    }
+    /* Channel 0 has the full channel. */
+    rt_wm_que_set_mark(&_chn_wm_que[0], 0, ~0);
+
+    for (i = 0; i < ARRAY_SIZE(_chn_suspended_threads); i++)
+    {
+        rt_list_init(&_chn_suspended_threads[i]);
+    }
+
+    for (i = 1; i < ARRAY_SIZE(_chn_recv_wm); i++)
+    {
+        rt_vbus_set_recv_wm(i,
+                            RT_VMM_RB_BLK_NR / 3,
+                            RT_VMM_RB_BLK_NR * 2 / 3);
+        _chn_recv_wm[i].level = 0;
+        _chn_recv_wm[i].last_warn = 0;
+    }
+    /* Channel 0 has the full channel. Don't suspend it. */
+    _chn_recv_wm[0].low_mark = 0;
+    _chn_recv_wm[0].high_mark = ~0;
+    _chn_recv_wm[0].level = 0;
+    _chn_recv_wm[0].last_warn = 0;
+#endif
+
+    rt_thread_init(&_bus_out_thread, "vbusout",
+                   _bus_out_entry, RT_NULL,
+                   _bus_out_thread_stack, sizeof(_bus_out_thread_stack),
+                   _BUS_OUT_THRD_PRIO, 20);
+    rt_thread_startup(&_bus_out_thread);
+
+    rt_thread_init(&_bus_in_thread, "vbusin",
+                   _bus_in_entry, RT_NULL,
+                   _bus_in_thread_stack, sizeof(_bus_in_thread_stack),
+                   _BUS_IN_THRD_PRIO, 20);
+
+
+    rt_thread_startup(&_bus_in_thread);
+
+    rt_vbus_hw_init();
+
+    rt_kprintf("VBus loaded: %d out blocks, %d in blocks\n",
+               RT_VMM_RB_BLK_NR, RT_VMM_RB_BLK_NR);
+
+    rt_vbus_chnx_init();
+
+    return 0;
+}
+
+void rt_vbus_rb_dump(void)
+{
+    rt_kprintf("OUT ring:(%s blocked)\n", RT_VBUS_OUT_RING->blocked ? "is" : "not");
+    rt_kprintf("put idx: %8x, get idx: %8x\n",
+               RT_VBUS_OUT_RING->put_idx, RT_VBUS_OUT_RING->get_idx);
+    rt_kprintf("space: %d\n", _bus_ring_space_nr(RT_VBUS_OUT_RING));
+
+
+    rt_kprintf("IN ring:(%s blocked)\n", RT_VBUS_IN_RING->blocked ? "is" : "not");
+    rt_kprintf("put idx: %8x, get idx: %8x\n",
+               RT_VBUS_IN_RING->put_idx, RT_VBUS_IN_RING->get_idx);
+    rt_kprintf("space: %d\n", _bus_ring_space_nr(RT_VBUS_IN_RING));
+}
+
+void rt_vbus_chn_dump(void)
+{
+    int i;
+    rt_kprintf("vbus channel status:\n");
+    for (i = 0; i < ARRAY_SIZE(_chn_status); i++)
+    {
+        rt_kprintf("%2d:%s\n", i, rt_vbus_chn_st2str[_chn_status[i]]);
+    }
+}
+
+void rt_vbus_sess_dump(void)
+{
+    int i;
+
+    rt_kprintf("vbus conn session:\n");
+    for (i = 0; i < ARRAY_SIZE(_sess); i++)
+    {
+        rt_kprintf("%2d(%s):%s\n", i, _sess[i].req ? _sess[i].req->name : "",
+                   rt_vbus_sess_st2str[_sess[i].st]);
+    }
+}
+
+void rt_vbus_que_dump(void)
+{
+    rt_kprintf("out que:\n");
+    rt_prio_queue_dump(_bus_out_que);
+}
+
+unsigned int rt_vbus_total_data_sz(void)
+{
+#ifdef RT_VBUS_STATISTICS
+    return _total_data_sz;
+#else
+    return (unsigned int)-1;
+#endif
+}
+
+void rt_vbus_data_pkt_dump(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(_bus_in_action); i++)
+    {
+        struct rt_vbus_data *dp;
+
+#ifdef RT_VBUS_STATISTICS
+        rt_kprintf("%2d %4d: ", i, _bus_in_action_nr[i]);
+#else
+        rt_kprintf("%2d: ", i);
+#endif
+        for (dp = _bus_in_action[i][_IN_ACT_HEAD];
+             dp;
+             dp = dp->next)
+        {
+            rt_kprintf("%p(%d) -> ", dp, dp->size);
+        }
+        rt_kprintf(" nil\n");
+    }
+}
+
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+void rt_vbus_chm_wm_dump(void)
+{
+    int i;
+
+    rt_kprintf("post wm:\n");
+    for (i = 0; i < ARRAY_SIZE(_chn_wm_que); i++)
+        rt_wm_que_dump(&_chn_wm_que[i]);
+
+    rt_kprintf("recv wm:\n");
+    rt_kprintf("     low,     high,      cur,  last warn\n");
+    for (i = 0; i < ARRAY_SIZE(_chn_recv_wm); i++)
+    {
+        rt_kprintf("%8x, %8x, %8x, %8x\n",
+                   _chn_recv_wm[i].low_mark, _chn_recv_wm[i].high_mark,
+                   _chn_recv_wm[i].level, _chn_recv_wm[i].last_warn);
+    }
+}
+#endif
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_rb_dump,    vbrb, dump vbus ringbuffer status);
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_chn_dump,  vbchn, dump vbus channel status);
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_sess_dump, vbses, dump vbus session status);
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_que_dump,  vbque, dump vbus out queue status);
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_total_data_sz,  vbtsz, total in data);
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_data_pkt_dump,  vbdq, dump the data queue);
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+FINSH_FUNCTION_EXPORT_ALIAS(rt_vbus_chm_wm_dump, vbwm, dump vbus water mark status);
+#endif
+#endif
+

+ 197 - 0
components/vbus/vbus.h

@@ -0,0 +1,197 @@
+#ifndef __VBUS_H__
+#define __VBUS_H__
+/*
+ * VBus
+ *
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2014-06-09     Grissiom     version 2.0.2; add comment
+ * 2015-01-06     Grissiom     version 2.0.3; API change, no functional changes
+ */
+
+#include "vbus_local_conf.h"
+#include <vbus_api.h>
+
+int rt_vbus_init(void *outr, void *inr);
+
+void rt_vbus_resume_out_thread(void);
+
+/** Post data on channel.
+ *
+ * @param chnr the channel number
+ * @param prio the priority of the data
+ * @param datap pointer to the actual data
+ * @param size number of byte of the data
+ * @param timeout the value used in the blocking API
+ *
+ * Note: rt_vbus_post is an asynchronous function that when it returns, the
+ * @datap and @size is recorded in the post queue at least but there is no
+ * guarantee that the data is copied into the ring buffer. To avoid data
+ * corruption, you need to wait on the RT_VBUS_EVENT_ID_TX event.
+ *
+ * However, if you just post static data such as static string, there is no
+ * need to wait.
+ *
+ * @sa rt_vbus_register_listener .
+ */
+rt_err_t rt_vbus_post(rt_uint8_t chnr,
+                      rt_uint8_t prio,
+                      const void *datap,
+                      rt_size_t size,
+                      rt_int32_t timeout);
+
+struct rt_vbus_data {
+    /* Number of bytes in current data package. */
+    unsigned char size;
+    /* Used internally in VBus. Don't modify this field as it may corrupt the
+     * receive queue. */
+    struct rt_vbus_data *next;
+    /* Data follows the struct */
+};
+
+struct rt_vbus_wm_cfg {
+	unsigned int low, high;
+};
+
+struct rt_vbus_request {
+	unsigned char prio;
+	const char *name;
+	int is_server;
+	struct rt_vbus_wm_cfg recv_wm, post_wm;
+};
+
+/** Request a channel.
+ *
+ * @return channel number. Negative if error happened.
+ */
+int rt_vbus_request_chn(struct rt_vbus_request *req, int timeout);
+
+/** Close channel @chnr */
+void rt_vbus_close_chn(unsigned char chnr);
+
+/** Set the water mark level for posting into the channel @chnr. */
+void rt_vbus_set_post_wm(unsigned char chnr, unsigned int low, unsigned int high);
+/** Set the water mark level for receiving from the channel @chnr. */
+void rt_vbus_set_recv_wm(unsigned char chnr, unsigned int low, unsigned int high);
+
+typedef void (*rt_vbus_event_listener)(void *ctx);
+
+enum rt_vbus_event_id {
+    /* On a packet received in channel. */
+    RT_VBUS_EVENT_ID_RX,
+    /* On the data of rt_vbus_post has been written to the ring buffer. */
+    RT_VBUS_EVENT_ID_TX,
+    /* On the channel has been closed. */
+    RT_VBUS_EVENT_ID_DISCONN,
+    RT_VBUS_EVENT_ID_MAX,
+};
+
+/** Register callback @indi on the event @eve on the @chnr.
+ *
+ * @ctx will passed to @indi on calling the @indi.
+ */
+void rt_vbus_register_listener(unsigned char chnr,
+                               enum rt_vbus_event_id eve,
+                               rt_vbus_event_listener indi,
+                               void *ctx);
+
+/** Listen on any events happen on the @chnr for @timeout ticks.
+ *
+ * This function blocks until events occur or timeout happened.
+ */
+rt_err_t rt_vbus_listen_on(rt_uint8_t chnr,
+                           rt_int32_t timeout);
+
+/** Push a data package into the receive queue of the channel @chnr. */
+void rt_vbus_data_push(unsigned int chnr,
+                       struct rt_vbus_data *data);
+/** Pop a data package from the receive queue of the channel @chnr.
+ *
+ * The actual data is following the struct rt_vbus_data. After using it, it
+ * should be freed by rt_free.
+ */
+struct rt_vbus_data* rt_vbus_data_pop(unsigned int chnr);
+
+struct rt_vbus_dev
+{
+    /* Runtime infomations. */
+    rt_uint8_t chnr;
+    struct rt_vbus_data *act;
+    rt_size_t pos;
+
+    /* There will be a request for each channel. So no need to seperate them so
+     * clearly. */
+    struct rt_vbus_request req;
+};
+
+rt_err_t rt_vbus_chnx_init(void);
+/** Get the corresponding channel number from the VBus device @dev. */
+rt_uint8_t rt_vbus_get_chnnr(rt_device_t dev);
+/** Register a call back on the other side disconnect the channel.
+ *
+ * @sa rt_vbus_register_listener .
+ */
+void rt_vbus_chnx_register_disconn(rt_device_t dev,
+                                   rt_vbus_event_listener indi,
+                                   void *ctx);
+
+/* Commands for the device control interface. */
+#define VBUS_IOCRECV_WM      0xD1
+#define VBUS_IOCPOST_WM      0xD2
+/** Configure event listener */
+#define VBUS_IOC_LISCFG      0xD3
+
+struct rt_vbus_dev_liscfg
+{
+    enum rt_vbus_event_id event;
+    rt_vbus_event_listener listener;
+    void *ctx;
+};
+
+int rt_vbus_shell_start(void);
+#ifdef RT_USING_VBUS_RFS
+int dfs_rfs_init(void);
+#endif
+
+/** VBus hardware init function.
+ *
+ * BSP should implement this function to initialize the interrupts etc.
+ */
+int rt_vbus_hw_init(void);
+
+/** VBus ISR function.
+ *
+ * BSP should call this function when the interrupt from other core is
+ * triggered. @param is not used by VBus and will pass to rt_vbus_hw_eoi.
+ */
+void rt_vbus_isr(int irqnr, void *param);
+
+/** VBus End Of Interrupt function.
+ *
+ * This function will be called when VBus finished the ISR handling. BSP should
+ * define this function to clear the interrupt flag etc.
+ */
+int rt_vbus_hw_eoi(int irqnr, void *param);
+
+#endif /* end of include guard: __VBUS_H__ */

+ 287 - 0
components/vbus/vbus_chnx.c

@@ -0,0 +1,287 @@
+/*
+ * Channel on VMM Bus
+ *
+ * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd
+ *      http://www.rt-thread.com
+ *
+ *  This file is part of RT-Thread (http://www.rt-thread.org)
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-11-04     Grissiom     add comment
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "vbus.h"
+
+static void _rx_indicate(void *ctx)
+{
+    rt_device_t dev = ctx;
+
+    if (dev->rx_indicate)
+        dev->rx_indicate(dev, 0);
+}
+
+static void _tx_complete(void *ctx)
+{
+    rt_device_t dev = ctx;
+
+    if (dev->tx_complete)
+        dev->tx_complete(dev, 0);
+}
+
+static rt_err_t _open(rt_device_t dev, rt_uint16_t oflag)
+{
+    int chnr;
+    struct rt_vbus_dev *vdev = dev->user_data;
+
+    if (vdev->chnr)
+        return RT_EOK;
+
+    /* FIXME: request the same name for twice will crash */
+    chnr = rt_vbus_request_chn(&vdev->req, RT_WAITING_FOREVER);
+    if (chnr < 0)
+        return chnr;
+
+    vdev->chnr = chnr;
+    rt_vbus_register_listener(chnr, RT_VBUS_EVENT_ID_RX, _rx_indicate, dev);
+    rt_vbus_register_listener(chnr, RT_VBUS_EVENT_ID_TX, _tx_complete, dev);
+
+    return RT_EOK;
+}
+
+static rt_err_t _close(rt_device_t dev)
+{
+    struct rt_vbus_dev *vdev = dev->user_data;
+
+    RT_ASSERT(vdev->chnr != 0);
+
+    rt_vbus_close_chn(vdev->chnr);
+    vdev->chnr = 0;
+
+    return RT_EOK;
+}
+
+static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
+{
+    rt_size_t outsz = 0;
+    struct rt_vbus_dev *vdev = dev->user_data;
+
+    RT_ASSERT(vdev->chnr != 0);
+
+    if (vdev->act == RT_NULL)
+    {
+        vdev->act = rt_vbus_data_pop(vdev->chnr);
+        vdev->pos = 0;
+    }
+
+    while (1)
+    {
+        rt_err_t err;
+
+        while (vdev->act)
+        {
+            rt_size_t cpysz;
+
+            if (size - outsz > vdev->act->size - vdev->pos)
+                cpysz = vdev->act->size - vdev->pos;
+            else
+                cpysz = size - outsz;
+
+            rt_memcpy((char*)buffer + outsz, ((char*)(vdev->act+1)) + vdev->pos, cpysz);
+            vdev->pos += cpysz;
+
+            outsz += cpysz;
+            if (outsz == size)
+            {
+                return outsz;
+            }
+            else if (outsz > size)
+                RT_ASSERT(0);
+
+            /* free old and get new */
+            rt_free(vdev->act);
+            vdev->act = rt_vbus_data_pop(vdev->chnr);
+            vdev->pos = 0;
+        }
+
+        /* TODO: We don't want to touch the rx_indicate here. But this lead to
+         * some duplication. Maybe we should find a better way to handle this.
+         */
+        if (rt_interrupt_get_nest() == 0)
+        {
+            err = rt_vbus_listen_on(vdev->chnr, RT_WAITING_FOREVER);
+        }
+        else
+        {
+            err = rt_vbus_listen_on(vdev->chnr, 0);
+        }
+        if (err != RT_EOK)
+        {
+            rt_set_errno(err);
+            return outsz;
+        }
+        vdev->act = rt_vbus_data_pop(vdev->chnr);
+        vdev->pos = 0;
+    }
+}
+
+static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    rt_err_t err;
+    struct rt_vbus_dev *vdev = dev->user_data;
+
+    RT_ASSERT(vdev->chnr != 0);
+
+    if (rt_interrupt_get_nest() == 0)
+    {
+        /* Thread context. */
+        err = rt_vbus_post(vdev->chnr, vdev->req.prio,
+                           buffer, size, RT_WAITING_FOREVER);
+    }
+    else
+    {
+        /* Interrupt context. */
+        err = rt_vbus_post(vdev->chnr, vdev->req.prio,
+                           buffer, size, 0);
+    }
+
+    if (err)
+    {
+        rt_set_errno(err);
+        return 0;
+    }
+
+    return size;
+}
+
+rt_err_t  _control(rt_device_t dev, rt_uint8_t cmd, void *args)
+{
+    RT_ASSERT(dev);
+
+    switch (cmd) {
+    case VBUS_IOC_LISCFG: {
+        struct rt_vbus_dev *vdev = dev->user_data;
+        struct rt_vbus_dev_liscfg *liscfg = args;
+
+        RT_ASSERT(vdev->chnr != 0);
+        if (!liscfg)
+            return -RT_ERROR;
+
+        rt_vbus_register_listener(vdev->chnr, liscfg->event,
+                                  liscfg->listener, liscfg->ctx);
+        return RT_EOK;
+    }
+        break;
+#ifdef RT_VBUS_USING_FLOW_CONTROL
+    case VBUS_IOCRECV_WM: {
+        struct rt_vbus_dev *vdev = dev->user_data;
+        struct rt_vbus_wm_cfg *cfg;
+
+        RT_ASSERT(vdev->chnr != 0);
+
+        if (!args)
+            return -RT_ERROR;
+
+        cfg = (struct rt_vbus_wm_cfg*)args;
+        if (cfg->low > cfg->high)
+            return -RT_ERROR;
+
+        rt_vbus_set_recv_wm(vdev->chnr, cfg->low, cfg->high);
+        return RT_EOK;
+    }
+        break;
+    case VBUS_IOCPOST_WM: {
+        struct rt_vbus_dev *vdev = dev->user_data;
+        struct rt_vbus_wm_cfg *cfg;
+
+        RT_ASSERT(vdev->chnr != 0);
+
+        if (!args)
+            return -RT_ERROR;
+
+        cfg = (struct rt_vbus_wm_cfg*)args;
+        if (cfg->low > cfg->high)
+            return -RT_ERROR;
+
+        rt_vbus_set_post_wm(vdev->chnr, cfg->low, cfg->high);
+        return RT_EOK;
+    }
+        break;
+#endif
+    default:
+        break;
+    };
+
+    return -RT_ENOSYS;
+}
+
+rt_uint8_t rt_vbus_get_chnnr(rt_device_t dev)
+{
+    struct rt_vbus_dev *vdev;
+
+    RT_ASSERT(dev);
+
+    vdev = dev->user_data;
+
+    return vdev->chnr;
+}
+
+void rt_vbus_chnx_register_disconn(rt_device_t dev,
+                                   rt_vbus_event_listener indi,
+                                   void *ctx)
+{
+    struct rt_vbus_dev *vdev = dev->user_data;
+
+    RT_ASSERT(vdev->chnr != 0);
+
+    if (vdev)
+        rt_vbus_register_listener(vdev->chnr, RT_VBUS_EVENT_ID_DISCONN,
+                                  indi, ctx);
+}
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+extern struct rt_vbus_dev rt_vbus_chn_devx[];
+static struct rt_device _devx[32];
+
+rt_err_t rt_vbus_chnx_init(void)
+{
+    int i;
+    struct rt_vbus_dev *p;
+
+    for (i = 0,                   p = rt_vbus_chn_devx;
+         i < ARRAY_SIZE(_devx) && p->req.name;
+         i++,                     p++)
+    {
+        _devx[i].type      = RT_Device_Class_Char;
+        _devx[i].open      = _open;
+        _devx[i].close     = _close;
+        _devx[i].read      = _read;
+        _devx[i].write     = _write;
+        _devx[i].control   = _control;
+        _devx[i].user_data = p;
+        rt_device_register(&_devx[i], p->req.name, RT_DEVICE_FLAG_RDWR);
+    }
+
+    return RT_EOK;
+}