summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/ARM/startup_LPC43xx_M0.s18
-rw-r--r--bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx.s66
-rw-r--r--bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s205
-rw-r--r--bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c8
-rw-r--r--bsp/lpc43xx/M0/SConscript16
-rw-r--r--bsp/lpc43xx/M0/SConstruct20
-rw-r--r--bsp/lpc43xx/M0/applications/SConscript (renamed from bsp/lpc43xx/applications/SConscript)0
-rw-r--r--bsp/lpc43xx/M0/applications/application.c121
-rw-r--r--bsp/lpc43xx/M0/applications/board.c67
-rw-r--r--bsp/lpc43xx/M0/applications/board.h59
-rw-r--r--bsp/lpc43xx/M0/applications/startup.c (renamed from bsp/lpc43xx/applications/startup.c)0
-rw-r--r--bsp/lpc43xx/M0/applications/vbus_conf.h13
-rw-r--r--bsp/lpc43xx/M0/applications/vbus_drv.c86
-rw-r--r--bsp/lpc43xx/M0/applications/vbus_hw.h53
-rw-r--r--bsp/lpc43xx/M0/rtconfig.h7
-rw-r--r--bsp/lpc43xx/M0/rtconfig.py25
-rw-r--r--bsp/lpc43xx/M0/rtthread-lpc43xx.ld139
-rw-r--r--bsp/lpc43xx/M0/rtthread_lpc43xx.sct18
-rw-r--r--bsp/lpc43xx/M0/template.uvproj422
-rw-r--r--bsp/lpc43xx/M0/vbus_local_conf.h8
-rw-r--r--bsp/lpc43xx/M4/SConscript16
-rw-r--r--bsp/lpc43xx/M4/SConstruct29
-rw-r--r--bsp/lpc43xx/M4/applications/SConscript13
-rw-r--r--bsp/lpc43xx/M4/applications/application.c156
-rw-r--r--bsp/lpc43xx/M4/applications/board.c (renamed from bsp/lpc43xx/drivers/board.c)7
-rw-r--r--bsp/lpc43xx/M4/applications/board.h (renamed from bsp/lpc43xx/drivers/board.h)3
-rw-r--r--bsp/lpc43xx/M4/applications/startup.c74
-rw-r--r--bsp/lpc43xx/M4/applications/vbus_conf.h13
-rw-r--r--bsp/lpc43xx/M4/applications/vbus_drv.c86
-rw-r--r--bsp/lpc43xx/M4/applications/vbus_hw.h53
-rw-r--r--bsp/lpc43xx/M4/rtconfig.h6
-rw-r--r--bsp/lpc43xx/M4/rtconfig.py13
-rw-r--r--bsp/lpc43xx/M4/rtthread-lpc43xx.ld147
-rw-r--r--bsp/lpc43xx/M4/rtthread_lpc43xx.sct23
-rw-r--r--bsp/lpc43xx/M4/template.uvproj397
-rw-r--r--bsp/lpc43xx/M4/vbus_local_conf.h8
-rw-r--r--bsp/lpc43xx/applications/application.c84
-rw-r--r--bsp/lpc43xx/bin2C.py14
-rw-r--r--bsp/lpc43xx/drivers/drv_uart.c221
-rw-r--r--bsp/lpc43xx/readme.txt4
-rw-r--r--components/vbus/SConscript29
-rw-r--r--components/vbus/prio_queue.c276
-rw-r--r--components/vbus/prio_queue.h73
-rw-r--r--components/vbus/rt_watermark_queue.c71
-rw-r--r--components/vbus/rt_watermark_queue.h149
-rw-r--r--components/vbus/share_hdr/vbus_api.h79
-rw-r--r--components/vbus/vbus.c1371
-rw-r--r--components/vbus/vbus.h197
-rw-r--r--components/vbus/vbus_chnx.c287
49 files changed, 4087 insertions, 1163 deletions
diff --git a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/ARM/startup_LPC43xx_M0.s b/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/ARM/startup_LPC43xx_M0.s
index c5a5dbefd9..efda7f9c2b 100644
--- a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/ARM/startup_LPC43xx_M0.s
+++ b/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
diff --git a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx.s b/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx.s
index 879e33872d..9d8b409c2c 100644
--- a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx.s
+++ b/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
diff --git a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s b/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s
index 5a7b26405d..39baf24094 100644
--- a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s
+++ b/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
diff --git a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c b/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c
index c51bd1c67e..3309f50aaf 100644
--- a/bsp/lpc43xx/Libraries/Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c
+++ b/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();
}
diff --git a/bsp/lpc43xx/M0/SConscript b/bsp/lpc43xx/M0/SConscript
index e2c31c0755..8333973c01 100644
--- a/bsp/lpc43xx/M0/SConscript
+++ b/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')
diff --git a/bsp/lpc43xx/M0/SConstruct b/bsp/lpc43xx/M0/SConstruct
index f6f21f4ec4..c7967d02f6 100644
--- a/bsp/lpc43xx/M0/SConstruct
+++ b/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)
diff --git a/bsp/lpc43xx/applications/SConscript b/bsp/lpc43xx/M0/applications/SConscript
index 01eb940dfb..01eb940dfb 100644
--- a/bsp/lpc43xx/applications/SConscript
+++ b/bsp/lpc43xx/M0/applications/SConscript
diff --git a/bsp/lpc43xx/M0/applications/application.c b/bsp/lpc43xx/M0/applications/application.c
new file mode 100644
index 0000000000..8e861873c8
--- /dev/null
+++ b/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;
+}
+
diff --git a/bsp/lpc43xx/M0/applications/board.c b/bsp/lpc43xx/M0/applications/board.c
new file mode 100644
index 0000000000..000bd52f40
--- /dev/null
+++ b/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);
+}
+
diff --git a/bsp/lpc43xx/M0/applications/board.h b/bsp/lpc43xx/M0/applications/board.h
new file mode 100644
index 0000000000..ee300eb739
--- /dev/null
+++ b/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
diff --git a/bsp/lpc43xx/applications/startup.c b/bsp/lpc43xx/M0/applications/startup.c
index f6cf534b03..f6cf534b03 100644
--- a/bsp/lpc43xx/applications/startup.c
+++ b/bsp/lpc43xx/M0/applications/startup.c
diff --git a/bsp/lpc43xx/M0/applications/vbus_conf.h b/bsp/lpc43xx/M0/applications/vbus_conf.h
new file mode 100644
index 0000000000..62bec83227
--- /dev/null
+++ b/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__ */
+
diff --git a/bsp/lpc43xx/M0/applications/vbus_drv.c b/bsp/lpc43xx/M0/applications/vbus_drv.c
new file mode 100644
index 0000000000..24d7f19b58
--- /dev/null
+++ b/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 */
+
diff --git a/bsp/lpc43xx/M0/applications/vbus_hw.h b/bsp/lpc43xx/M0/applications/vbus_hw.h
new file mode 100644
index 0000000000..b88586a112
--- /dev/null
+++ b/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();
+}
diff --git a/bsp/lpc43xx/M0/rtconfig.h b/bsp/lpc43xx/M0/rtconfig.h
index 84fc28028c..77846191fc 100644
--- a/bsp/lpc43xx/M0/rtconfig.h
+++ b/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>
diff --git a/bsp/lpc43xx/M0/rtconfig.py b/bsp/lpc43xx/M0/rtconfig.py
index 5eef1d3ab8..e998c27fe1 100644
--- a/bsp/lpc43xx/M0/rtconfig.py
+++ b/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
diff --git a/bsp/lpc43xx/M0/rtthread-lpc43xx.ld b/bsp/lpc43xx/M0/rtthread-lpc43xx.ld
new file mode 100644
index 0000000000..e8ef2fe490
--- /dev/null
+++ b/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) }
+}
diff --git a/bsp/lpc43xx/M0/rtthread_lpc43xx.sct b/bsp/lpc43xx/M0/rtthread_lpc43xx.sct
new file mode 100644
index 0000000000..d0fd443a85
--- /dev/null
+++ b/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)
+ }
+}
+
diff --git a/bsp/lpc43xx/M0/template.uvproj b/bsp/lpc43xx/M0/template.uvproj
index 95f6c36a2b..fc50dbac3e 100644
--- a/bsp/lpc43xx/M0/template.uvproj
+++ b/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>
diff --git a/bsp/lpc43xx/M0/vbus_local_conf.h b/bsp/lpc43xx/M0/vbus_local_conf.h
new file mode 100644
index 0000000000..571c51e612
--- /dev/null
+++ b/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__ */
diff --git a/bsp/lpc43xx/M4/SConscript b/bsp/lpc43xx/M4/SConscript
index e2c31c0755..8333973c01 100644
--- a/bsp/lpc43xx/M4/SConscript
+++ b/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')
diff --git a/bsp/lpc43xx/M4/SConstruct b/bsp/lpc43xx/M4/SConstruct
index f6f21f4ec4..7b02b732d4 100644
--- a/bsp/lpc43xx/M4/SConstruct
+++ b/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)
diff --git a/bsp/lpc43xx/M4/applications/SConscript b/bsp/lpc43xx/M4/applications/SConscript
new file mode 100644
index 0000000000..773b8d0422
--- /dev/null
+++ b/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')
diff --git a/bsp/lpc43xx/M4/applications/application.c b/bsp/lpc43xx/M4/applications/application.c
new file mode 100644
index 0000000000..6575991895
--- /dev/null
+++ b/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;
+}
diff --git a/bsp/lpc43xx/drivers/board.c b/bsp/lpc43xx/M4/applications/board.c
index 421298c19e..dc0859f666 100644
--- a/bsp/lpc43xx/drivers/board.c
+++ b/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);
diff --git a/bsp/lpc43xx/drivers/board.h b/bsp/lpc43xx/M4/applications/board.h
index 393dc30c91..299404a368 100644
--- a/bsp/lpc43xx/drivers/board.h
+++ b/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
diff --git a/bsp/lpc43xx/M4/applications/startup.c b/bsp/lpc43xx/M4/applications/startup.c
new file mode 100644
index 0000000000..f6cf534b03
--- /dev/null
+++ b/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;
+}
diff --git a/bsp/lpc43xx/M4/applications/vbus_conf.h b/bsp/lpc43xx/M4/applications/vbus_conf.h
new file mode 100644
index 0000000000..62bec83227
--- /dev/null
+++ b/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__ */
+
diff --git a/bsp/lpc43xx/M4/applications/vbus_drv.c b/bsp/lpc43xx/M4/applications/vbus_drv.c
new file mode 100644
index 0000000000..872de86504
--- /dev/null
+++ b/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 */
+
diff --git a/bsp/lpc43xx/M4/applications/vbus_hw.h b/bsp/lpc43xx/M4/applications/vbus_hw.h
new file mode 100644
index 0000000000..b88586a112
--- /dev/null
+++ b/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();
+}
diff --git a/bsp/lpc43xx/M4/rtconfig.h b/bsp/lpc43xx/M4/rtconfig.h
index 84fc28028c..31854ca2fc 100644
--- a/bsp/lpc43xx/M4/rtconfig.h
+++ b/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>
diff --git a/bsp/lpc43xx/M4/rtconfig.py b/bsp/lpc43xx/M4/rtconfig.py
index b19c390160..1cbaacf650 100644
--- a/bsp/lpc43xx/M4/rtconfig.py
+++ b/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'
diff --git a/bsp/lpc43xx/M4/rtthread-lpc43xx.ld b/bsp/lpc43xx/M4/rtthread-lpc43xx.ld
new file mode 100644
index 0000000000..63057abc40
--- /dev/null
+++ b/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) }
+}
diff --git a/bsp/lpc43xx/M4/rtthread_lpc43xx.sct b/bsp/lpc43xx/M4/rtthread_lpc43xx.sct
new file mode 100644
index 0000000000..238ca28c6e
--- /dev/null
+++ b/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)
+ }
+}
diff --git a/bsp/lpc43xx/M4/template.uvproj b/bsp/lpc43xx/M4/template.uvproj
index f93cbd2c11..f8bc0558a2 100644
--- a/bsp/lpc43xx/M4/template.uvproj
+++ b/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>
diff --git a/bsp/lpc43xx/M4/vbus_local_conf.h b/bsp/lpc43xx/M4/vbus_local_conf.h
new file mode 100644
index 0000000000..571c51e612
--- /dev/null
+++ b/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__ */
diff --git a/bsp/lpc43xx/applications/application.c b/bsp/lpc43xx/applications/application.c
deleted file mode 100644
index e40ad02e48..0000000000
--- a/bsp/lpc43xx/applications/application.c
+++ /dev/null
@@ -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;
-}
diff --git a/bsp/lpc43xx/bin2C.py b/bsp/lpc43xx/bin2C.py
new file mode 100644
index 0000000000..ea7bf2959d
--- /dev/null
+++ b/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')
diff --git a/bsp/lpc43xx/drivers/drv_uart.c b/bsp/lpc43xx/drivers/drv_uart.c
index 9c1f0ada8c..70f4a880e1 100644
--- a/bsp/lpc43xx/drivers/drv_uart.c
+++ b/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
}
diff --git a/bsp/lpc43xx/readme.txt b/bsp/lpc43xx/readme.txt
new file mode 100644
index 0000000000..0226599032
--- /dev/null
+++ b/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.
diff --git a/components/vbus/SConscript b/components/vbus/SConscript
new file mode 100644
index 0000000000..e9097d19ff
--- /dev/null
+++ b/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')
diff --git a/components/vbus/prio_queue.c b/components/vbus/prio_queue.c
new file mode 100644
index 0000000000..b402e0376a
--- /dev/null
+++ b/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");
+ }
+}
+
diff --git a/components/vbus/prio_queue.h b/components/vbus/prio_queue.h
new file mode 100644
index 0000000000..8a29cbb715
--- /dev/null
+++ b/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__ */
diff --git a/components/vbus/rt_watermark_queue.c b/components/vbus/rt_watermark_queue.c
new file mode 100644
index 0000000000..329e9f331c
--- /dev/null
+++ b/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");
+}
diff --git a/components/vbus/rt_watermark_queue.h b/components/vbus/rt_watermark_queue.h
new file mode 100644
index 0000000000..1fd51e07c2
--- /dev/null
+++ b/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();
+}
diff --git a/components/vbus/share_hdr/vbus_api.h b/components/vbus/share_hdr/vbus_api.h
new file mode 100644
index 0000000000..fb15fa24b0
--- /dev/null
+++ b/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__ */
+
diff --git a/components/vbus/vbus.c b/components/vbus/vbus.c
new file mode 100644
index 0000000000..7005e52513
--- /dev/null
+++ b/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
+
diff --git a/components/vbus/vbus.h b/components/vbus/vbus.h
new file mode 100644
index 0000000000..2187773a47
--- /dev/null
+++ b/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__ */
diff --git a/components/vbus/vbus_chnx.c b/components/vbus/vbus_chnx.c
new file mode 100644
index 0000000000..bd54c9dbbd
--- /dev/null
+++ b/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;
+}