From a447b5f3cfdf5b575fcc49c5b05c29864d6024da Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sun, 4 Jan 2015 19:54:53 +0800 Subject: [PATCH 01/24] lpc43xx: refactor uart drivers --- .../Source/Templates/ARM/startup_LPC43xx_M0.s | 18 +- bsp/lpc43xx/drivers/drv_uart.c | 165 +++++++----------- 2 files changed, 69 insertions(+), 114 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/drivers/drv_uart.c b/bsp/lpc43xx/drivers/drv_uart.c index 9c1f0ada8c..29f509ec21 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,6 +83,44 @@ static const struct rt_uart_ops lpc_uart_ops = lpc_getc, }; +static void _do_uart_isr(struct rt_serial_device *sdev) +{ + struct lpc_uart *uart; + volatile uint32_t intsrc, temp; + + 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 */ + /* read the line status */ + intsrc = uart->USART->LSR; + /* Receive an error data */ + if (intsrc & UART_LSR_PE) + { + temp = uart->USART->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(sdev, RT_SERIAL_EVENT_RX_IND); + } + break; + + default: + break; + } +} + #if defined(RT_USING_UART0) /* UART0 device driver structure */ struct lpc_uart uart0 = @@ -106,49 +132,13 @@ struct rt_serial_device serial0; void UART0_IRQHandler(void) { - struct lpc_uart *uart; - volatile uint32_t intsrc, temp; - - uart = &uart0; - - /* enter interrupt */ rt_interrupt_enter(); - - /* 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; - } - - /* leave interrupt */ + _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,12 @@ struct rt_serial_device serial2; void UART2_IRQHandler(void) { - struct lpc_uart *uart; - uint32_t intsrc, temp; - - uart = &uart2; - - /* enter interrupt */ rt_interrupt_enter(); - - /* 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; - } - - /* leave interrupt */ + _do_uart_isr(&serial2); rt_interrupt_leave(); } #endif + void rt_hw_uart_init(void) { struct lpc_uart *uart; @@ -212,7 +167,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,22 +176,22 @@ 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 */ @@ -250,7 +205,7 @@ void rt_hw_uart_init(void) /* 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 +218,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,22 +227,22 @@ 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_APB0_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 */ @@ -295,14 +250,14 @@ void rt_hw_uart_init(void) LPC_USART2->DLM = 0x00; LPC_USART2->FDR = 0xC1; LPC_USART2->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); From f609a63564625478f1d533bee283fad7f09059ac Mon Sep 17 00:00:00 2001 From: Grissiom Date: Sun, 4 Jan 2015 20:43:32 +0800 Subject: [PATCH 02/24] lpc43xx: add uart3 support --- bsp/lpc43xx/drivers/drv_uart.c | 90 +++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 11 deletions(-) diff --git a/bsp/lpc43xx/drivers/drv_uart.c b/bsp/lpc43xx/drivers/drv_uart.c index 29f509ec21..46edf3ab04 100644 --- a/bsp/lpc43xx/drivers/drv_uart.c +++ b/bsp/lpc43xx/drivers/drv_uart.c @@ -154,6 +154,22 @@ void UART2_IRQHandler(void) } #endif +#if defined(RT_USING_UART3) +struct lpc_uart uart3 = +{ + LPC_USART3, + USART3_IRQn, +}; +struct rt_serial_device serial3; + +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; @@ -194,11 +210,11 @@ void rt_hw_uart_init(void) (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)); @@ -228,7 +244,7 @@ void rt_hw_uart_init(void) while (!(LPC_CCU1->CLK_M4_GPIO_STAT & 0x01)); /* Enable USART2 peripheral clock */ - LPC_CCU2->CLK_APB0_USART2_CFG |= 0x01; + LPC_CCU2->CLK_APB2_USART2_CFG |= 0x01; while (!(LPC_CCU2->CLK_APB2_USART2_STAT & 0x01)); /* Enable USART2 register interface clock */ @@ -245,11 +261,11 @@ void rt_hw_uart_init(void) (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)); @@ -262,4 +278,56 @@ void rt_hw_uart_init(void) 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 } From 5542af8b7c1ec7359616d2e2521a5654547554b2 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 5 Jan 2015 11:15:54 +0800 Subject: [PATCH 03/24] lpc43xx/driver: fix the VTOR setting --- bsp/lpc43xx/drivers/board.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bsp/lpc43xx/drivers/board.c b/bsp/lpc43xx/drivers/board.c index 421298c19e..b7d3ead87e 100644 --- a/bsp/lpc43xx/drivers/board.c +++ b/bsp/lpc43xx/drivers/board.c @@ -43,13 +43,12 @@ 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 */ From 959f6c695fdea80d6bbd9146770eda95e0a2dfa9 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 5 Jan 2015 11:19:42 +0800 Subject: [PATCH 04/24] lpc43xx: move the application code into its own space --- bsp/lpc43xx/M0/SConscript | 16 ++- bsp/lpc43xx/{ => M0}/applications/SConscript | 0 .../{ => M0}/applications/application.c | 5 +- bsp/lpc43xx/M0/applications/board.h | 59 +++++++++ bsp/lpc43xx/{ => M0}/applications/startup.c | 0 bsp/lpc43xx/M0/rtconfig.h | 4 +- bsp/lpc43xx/M4/SConscript | 16 ++- bsp/lpc43xx/M4/applications/SConscript | 13 ++ bsp/lpc43xx/M4/applications/application.c | 113 ++++++++++++++++++ .../{drivers => M4/applications}/board.h | 1 - bsp/lpc43xx/M4/applications/startup.c | 74 ++++++++++++ bsp/lpc43xx/M4/rtconfig.h | 3 +- 12 files changed, 287 insertions(+), 17 deletions(-) rename bsp/lpc43xx/{ => M0}/applications/SConscript (100%) rename bsp/lpc43xx/{ => M0}/applications/application.c (95%) create mode 100644 bsp/lpc43xx/M0/applications/board.h rename bsp/lpc43xx/{ => M0}/applications/startup.c (100%) create mode 100644 bsp/lpc43xx/M4/applications/SConscript create mode 100644 bsp/lpc43xx/M4/applications/application.c rename bsp/lpc43xx/{drivers => M4/applications}/board.h (98%) create mode 100644 bsp/lpc43xx/M4/applications/startup.c diff --git a/bsp/lpc43xx/M0/SConscript b/bsp/lpc43xx/M0/SConscript index e2c31c0755..285e5c295f 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(cwd, '..', d, 'SConscript') + if os.path.isfile(path): + objs = objs + SConscript(path) + +for d in os.listdir(cwd): + p = os.path.join(cwd, d, 'SConscript'); + if os.path.isfile(p): + objs = objs + SConscript(p) Return('objs') diff --git a/bsp/lpc43xx/applications/SConscript b/bsp/lpc43xx/M0/applications/SConscript similarity index 100% rename from bsp/lpc43xx/applications/SConscript rename to bsp/lpc43xx/M0/applications/SConscript diff --git a/bsp/lpc43xx/applications/application.c b/bsp/lpc43xx/M0/applications/application.c similarity index 95% rename from bsp/lpc43xx/applications/application.c rename to bsp/lpc43xx/M0/applications/application.c index e40ad02e48..e49f1dd767 100644 --- a/bsp/lpc43xx/applications/application.c +++ b/bsp/lpc43xx/M0/applications/application.c @@ -49,12 +49,12 @@ static void led_thread_entry(void *parameter) { /* led0 on */ led_value = 1; - led_dev->write(led_dev, 0, &led_value, 1); + led_dev->write(led_dev, 1, &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); + led_dev->write(led_dev, 1, &led_value, 1); rt_thread_delay(RT_TICK_PER_SECOND / 2); } } @@ -82,3 +82,4 @@ int rt_application_init(void) } return 0; } + diff --git a/bsp/lpc43xx/M0/applications/board.h b/bsp/lpc43xx/M0/applications/board.h new file mode 100644 index 0000000000..c19d0dc4ba --- /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 + +/* disable SDRAM in default */ +#ifndef LPC_EXT_SDRAM +#define LPC_EXT_SDRAM 0 +#endif + +// + +// +#define LPC_EXT_SDRAM_BEGIN 0xA0000000 +// +#define LPC_EXT_SDRAM_END 0xA2000000 + +// +// +//#define RT_USING_UART1 +// +//#define RT_USING_UART2 + +// + +#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); + + +#endif diff --git a/bsp/lpc43xx/applications/startup.c b/bsp/lpc43xx/M0/applications/startup.c similarity index 100% rename from bsp/lpc43xx/applications/startup.c rename to bsp/lpc43xx/M0/applications/startup.c diff --git a/bsp/lpc43xx/M0/rtconfig.h b/bsp/lpc43xx/M0/rtconfig.h index 84fc28028c..a1ac5509ab 100644 --- a/bsp/lpc43xx/M0/rtconfig.h +++ b/bsp/lpc43xx/M0/rtconfig.h @@ -24,6 +24,7 @@ #define RT_DEBUG // #define RT_DEBUG_INIT 0 +//#define RT_DEBUG_SCHEDULER 1 // // #define RT_THREAD_DEBUG // @@ -33,7 +34,7 @@ // #define RT_USING_HOOK //
-#define RT_USING_TIMER_SOFT +//#define RT_USING_TIMER_SOFT // #define RT_TIMER_THREAD_PRIO 4 // @@ -96,6 +97,7 @@ #define RT_CONSOLEBUF_SIZE 128 // #define RT_CONSOLE_DEVICE_NAME "uart0" +#define RT_USING_UART0 //
// diff --git a/bsp/lpc43xx/M4/SConscript b/bsp/lpc43xx/M4/SConscript index e2c31c0755..285e5c295f 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(cwd, '..', d, 'SConscript') + if os.path.isfile(path): + objs = objs + SConscript(path) + +for d in os.listdir(cwd): + p = os.path.join(cwd, d, 'SConscript'); + if os.path.isfile(p): + objs = objs + SConscript(p) Return('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..72e0234d85 --- /dev/null +++ b/bsp/lpc43xx/M4/applications/application.c @@ -0,0 +1,113 @@ +/* + * 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 +#include +#include +#include "drv_led.h" + +#ifdef RT_USING_FINSH +#include +#include +#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) +{ +#ifdef RT_USING_FINSH + /* initialize finsh */ + finsh_system_init(); + finsh_set_device(RT_CONSOLE_DEVICE_NAME); +#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 = 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/drivers/board.h b/bsp/lpc43xx/M4/applications/board.h similarity index 98% rename from bsp/lpc43xx/drivers/board.h rename to bsp/lpc43xx/M4/applications/board.h index 393dc30c91..465ccef2cc 100644 --- a/bsp/lpc43xx/drivers/board.h +++ b/bsp/lpc43xx/M4/applications/board.h @@ -33,7 +33,6 @@ #define LPC_EXT_SDRAM_END 0xA2000000 // -#define RT_USING_UART0 // //#define RT_USING_UART1 // 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 +#include + +#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/rtconfig.h b/bsp/lpc43xx/M4/rtconfig.h index 84fc28028c..fb65f5bf3d 100644 --- a/bsp/lpc43xx/M4/rtconfig.h +++ b/bsp/lpc43xx/M4/rtconfig.h @@ -95,7 +95,8 @@ // #define RT_CONSOLEBUF_SIZE 128 // -#define RT_CONSOLE_DEVICE_NAME "uart0" +#define RT_CONSOLE_DEVICE_NAME "uart3" +#define RT_USING_UART3 // // From d2e4050a706b2fdd9f5f59f1671cad6a2ac6aeef Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 5 Jan 2015 20:31:02 +0800 Subject: [PATCH 05/24] lpc43xx: update template.uvproj and add sct files --- bsp/lpc43xx/M0/rtthread_lpc43xx.sct | 15 + bsp/lpc43xx/M0/template.uvproj | 407 +--------------------------- bsp/lpc43xx/M4/rtthread_lpc43xx.sct | 20 ++ bsp/lpc43xx/M4/template.uvproj | 397 +-------------------------- bsp/lpc43xx/bin2C.py | 13 + 5 files changed, 67 insertions(+), 785 deletions(-) create mode 100644 bsp/lpc43xx/M0/rtthread_lpc43xx.sct create mode 100644 bsp/lpc43xx/M4/rtthread_lpc43xx.sct create mode 100644 bsp/lpc43xx/bin2C.py diff --git a/bsp/lpc43xx/M0/rtthread_lpc43xx.sct b/bsp/lpc43xx/M0/rtthread_lpc43xx.sct new file mode 100644 index 0000000000..2232a4aa9b --- /dev/null +++ b/bsp/lpc43xx/M0/rtthread_lpc43xx.sct @@ -0,0 +1,15 @@ +; ************************************************************* +; *** 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) + } +} + diff --git a/bsp/lpc43xx/M0/template.uvproj b/bsp/lpc43xx/M0/template.uvproj index 95f6c36a2b..a955307372 100644 --- a/bsp/lpc43xx/M0/template.uvproj +++ b/bsp/lpc43xx/M0/template.uvproj @@ -73,10 +73,10 @@ 0 - 0 - 0 - - + 1 + 1 + fromelf --bin !L --output rtthread.bin + C:\Python27\python.exe ..\bin2C.py rtthread.bin ..\M4\applications\M0_CODE.h 0 0 @@ -208,10 +208,10 @@ 1 0 0 - 1 + 2 1 1 - 1 + 16 1 0 0 @@ -224,11 +224,11 @@ 0 0 0 - 1 + 0 0 0 0 - 0 + 1 0 0 0 @@ -338,7 +338,7 @@ 1 0 0 - 0 + 1 0 0 0 @@ -371,7 +371,7 @@ - 1 + 0 0 0 0 @@ -379,390 +379,8 @@ 0 0x14000000 0x10000000 - - - - - - - - - - - - LPC43xx RAM - 0x4 - ARM-ADS - - - LPC4357 - NXP (founded by Philips) - IRAM(0x10000000-0x10007FFF) IRAM2(0x20000000-0x2000FFFF) IROM(0x1A000000-0x1A07FFFF) IROM2(0x1B000000-0x1B07FFFF) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 - - "STARTUP\NXP\LPC43xx\startup_LPC43xx.s" ("NXP LPC43xx Startup Code") - UL2CM3(-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000) - 6414 - LPC43xx.H - - - - - - - - - - SFD\NXP\LPC43xx\LPC43xx.SFR - 0 - - - - NXP\LPC43xx\ - NXP\LPC43xx\ - - 0 - 0 - 0 - 0 - 1 - - .\build\ - rtthread_lpc43xx - 1 - 0 - 0 - 1 - 1 - .\build\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARMCM3.DLL - -MPU - DCM.DLL - -pCM4 - SARMCM3.DLL - -MPU - TCM.DLL - -pCM4 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - - 0 - 1 - - - - - - - - - - - - - .\Dbg_RAM.ini - BIN\UL2CM3.DLL - - - - - 1 - 1 - 0 - 1 - 1 - 4096 - - 1 - BIN\UL2CM3.DLL - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 8 - 1 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x10000000 - 0x8000 - - - 1 - 0x1a000000 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x1a000000 - 0x80000 - - - 1 - 0x1b000000 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x10000000 - 0x8000 - - - 0 - 0x20000000 - 0x10000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - NO_CRP - - - - - - 1 - 0 - 0 - 0 - 1 - 0 - 0x10000000 - 0x20000000 - + + .\rtthread_lpc43xx.sct @@ -773,5 +391,4 @@ - diff --git a/bsp/lpc43xx/M4/rtthread_lpc43xx.sct b/bsp/lpc43xx/M4/rtthread_lpc43xx.sct new file mode 100644 index 0000000000..c483ea87d2 --- /dev/null +++ b/bsp/lpc43xx/M4/rtthread_lpc43xx.sct @@ -0,0 +1,20 @@ +; ************************************************************* +; *** 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) + } +} + +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 @@ 2 1 1 - 1 + 8 1 0 0 @@ -224,10 +224,10 @@ 0 0 0 - 1 + 0 0 0 - 0 + 1 0 0 0 @@ -338,7 +338,7 @@ 1 0 0 - 0 + 1 0 0 0 @@ -371,7 +371,7 @@ - 1 + 0 0 0 0 @@ -379,390 +379,8 @@ 0 0x14000000 0x10000000 - - - - - - - - - - - - LPC43xx RAM - 0x4 - ARM-ADS - - - LPC4357 - NXP (founded by Philips) - IRAM(0x10000000-0x10007FFF) IRAM2(0x20000000-0x2000FFFF) IROM(0x1A000000-0x1A07FFFF) IROM2(0x1B000000-0x1B07FFFF) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 - - "STARTUP\NXP\LPC43xx\startup_LPC43xx.s" ("NXP LPC43xx Startup Code") - UL2CM3(-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000) - 6414 - LPC43xx.H - - - - - - - - - - SFD\NXP\LPC43xx\LPC43xx.SFR - 0 - - - - NXP\LPC43xx\ - NXP\LPC43xx\ - - 0 - 0 - 0 - 0 - 1 - - .\build\ - rtthread_lpc43xx - 1 - 0 - 0 - 1 - 1 - .\build\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - 0 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - - - SARMCM3.DLL - -MPU - DCM.DLL - -pCM4 - SARMCM3.DLL - -MPU - TCM.DLL - -pCM4 - - - - 1 - 0 - 0 - 0 - 16 - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - - - 1 - 0 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - - 0 - 1 - - - - - - - - - - - - - .\Dbg_RAM.ini - BIN\UL2CM3.DLL - - - - - 1 - 1 - 0 - 1 - 1 - 4096 - - 1 - BIN\UL2CM3.DLL - "" () - - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 1 - 1 - 8 - 1 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x10000000 - 0x8000 - - - 1 - 0x1a000000 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x1a000000 - 0x80000 - - - 1 - 0x1b000000 - 0x80000 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x10000000 - 0x8000 - - - 0 - 0x20000000 - 0x10000 - - - - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - NO_CRP - - - - - - 1 - 0 - 0 - 0 - 1 - 0 - 0x10000000 - 0x20000000 - + + .\rtthread_lpc43xx.sct @@ -773,5 +391,4 @@ - diff --git a/bsp/lpc43xx/bin2C.py b/bsp/lpc43xx/bin2C.py new file mode 100644 index 0000000000..bc76419b06 --- /dev/null +++ b/bsp/lpc43xx/bin2C.py @@ -0,0 +1,13 @@ +#!/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') From 773a884a4b38ce18ba1c8908f0bf04931a377158 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 5 Jan 2015 20:59:11 +0800 Subject: [PATCH 06/24] lpc43xx: move board.c into M0/M4 --- bsp/lpc43xx/M0/applications/board.c | 49 +++++++++++++++++++ .../{drivers => M4/applications}/board.c | 0 2 files changed, 49 insertions(+) create mode 100644 bsp/lpc43xx/M0/applications/board.c rename bsp/lpc43xx/{drivers => M4/applications}/board.c (100%) diff --git a/bsp/lpc43xx/M0/applications/board.c b/bsp/lpc43xx/M0/applications/board.c new file mode 100644 index 0000000000..116c433040 --- /dev/null +++ b/bsp/lpc43xx/M0/applications/board.c @@ -0,0 +1,49 @@ +/* + * 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 +#include + +#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(); + + rt_tick_increase(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function will initial LPC43xx board. + */ +void rt_hw_board_init() +{ + /* 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/drivers/board.c b/bsp/lpc43xx/M4/applications/board.c similarity index 100% rename from bsp/lpc43xx/drivers/board.c rename to bsp/lpc43xx/M4/applications/board.c From 21ef733251473f1d7f43cab03d998210a000b844 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 5 Jan 2015 21:30:42 +0800 Subject: [PATCH 07/24] lpc43xx: use the RIT timer as SysTick in M0 core --- bsp/lpc43xx/M0/applications/board.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/bsp/lpc43xx/M0/applications/board.c b/bsp/lpc43xx/M0/applications/board.c index 116c433040..c3377aac2a 100644 --- a/bsp/lpc43xx/M0/applications/board.c +++ b/bsp/lpc43xx/M0/applications/board.c @@ -26,17 +26,34 @@ void RIT_OR_WWDT_IRQHandler(void) /* enter interrupt */ rt_interrupt_enter(); - rt_tick_increase(); + 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->COMPVAL = SystemCoreClock / RT_TICK_PER_SECOND - 1; + /* 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); From 090adcf4c070083e98fce673dcb23c5a97c5bd00 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Mon, 5 Jan 2015 21:32:21 +0800 Subject: [PATCH 08/24] lpc43xx: don't set the Clock again in M0 core M0 core is always booted by the M4 core. It means that if we are running in M0, the clock is always configured. --- .../Device/NXP/LPC43xx/Source/Templates/system_LPC43xx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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(); } From ff3ab9c0abe31725894922802916ff54635b4097 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 10:42:09 +0800 Subject: [PATCH 09/24] lpc43xx: add readme --- bsp/lpc43xx/readme.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 bsp/lpc43xx/readme.txt 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. From 833339e1c64c5021195137db339012edecb44a39 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 11:03:01 +0800 Subject: [PATCH 10/24] lpc43xx: output a newline in the header file Some compiler is brain-damaged that it will yeild a warning for headers not ended with a newline. Yes, I mean you, Keil. --- bsp/lpc43xx/bin2C.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bsp/lpc43xx/bin2C.py b/bsp/lpc43xx/bin2C.py index bc76419b06..ea7bf2959d 100644 --- a/bsp/lpc43xx/bin2C.py +++ b/bsp/lpc43xx/bin2C.py @@ -11,3 +11,4 @@ for i in fi.read(): fo.write('0x%02x, ' % ord(i)) if idx % 16 == 0: fo.write('\n') +fo.write('\n') From fca84daa9dff8ad17e6b3669a652fdbb98acdc75 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 12:42:12 +0800 Subject: [PATCH 11/24] lpc43xx: fix the startup code for GCC --- .../Source/Templates/GCC/startup_LPC43xx.s | 66 ++++-- .../Source/Templates/GCC/startup_LPC43xx_M0.s | 203 ++++++++---------- 2 files changed, 139 insertions(+), 130 deletions(-) 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: +/* 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 -.else - 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..38e1869243 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 @@ -8,7 +8,7 @@ .cpu cortex-m0 .fpu softvfp .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: +/* 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 -.else - 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 From bcbe180886e7beab7585a03b5067fb60eae4af2d Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 13:39:54 +0800 Subject: [PATCH 12/24] lpc43xx: fix the default RTT_ROOT in SConstruct --- bsp/lpc43xx/M0/SConstruct | 2 +- bsp/lpc43xx/M4/SConstruct | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/bsp/lpc43xx/M0/SConstruct b/bsp/lpc43xx/M0/SConstruct index f6f21f4ec4..62cebd454f 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 * diff --git a/bsp/lpc43xx/M4/SConstruct b/bsp/lpc43xx/M4/SConstruct index f6f21f4ec4..17f5eaf11c 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,22 @@ 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'): + 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) + else: + # assume Windows. + ocwd = os.getcwdu() + os.chdir('..\M0') + os.system('scons.bat') + os.chdir(ocwd) + # do building DoBuilding(TARGET, objs) From 0ca281c1622e6df2442501e340e6ff5c468dc8ba Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 13:40:46 +0800 Subject: [PATCH 13/24] lpc43xx: add flash linker script for GCC --- bsp/lpc43xx/M0/rtconfig.py | 25 +++--- bsp/lpc43xx/M0/rtthread-lpc43xx.ld | 133 +++++++++++++++++++++++++++ bsp/lpc43xx/M4/rtconfig.py | 11 +-- bsp/lpc43xx/M4/rtthread-lpc43xx.ld | 140 +++++++++++++++++++++++++++++ 4 files changed, 290 insertions(+), 19 deletions(-) create mode 100644 bsp/lpc43xx/M0/rtthread-lpc43xx.ld create mode 100644 bsp/lpc43xx/M4/rtthread-lpc43xx.ld diff --git a/bsp/lpc43xx/M0/rtconfig.py b/bsp/lpc43xx/M0/rtconfig.py index 5eef1d3ab8..f6e58476e5 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' + 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..3419e6f235 --- /dev/null +++ b/bsp/lpc43xx/M0/rtthread-lpc43xx.ld @@ -0,0 +1,133 @@ +/* + * 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 +} +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 = .; + + _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/rtconfig.py b/bsp/lpc43xx/M4/rtconfig.py index b19c390160..f73811f23d 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,7 +44,7 @@ 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' @@ -53,14 +53,15 @@ if PLATFORM == 'gcc': 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..81d1655b52 --- /dev/null +++ b/bsp/lpc43xx/M4/rtthread-lpc43xx.ld @@ -0,0 +1,140 @@ +/* + * 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 +} +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 = .; + + .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) } +} From df317441783adf6b49987622da1cf663fdda162e Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 21:33:32 +0800 Subject: [PATCH 14/24] lpc43xx: fix the M0 project template --- bsp/lpc43xx/M0/template.uvproj | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/bsp/lpc43xx/M0/template.uvproj b/bsp/lpc43xx/M0/template.uvproj index a955307372..fc50dbac3e 100644 --- a/bsp/lpc43xx/M0/template.uvproj +++ b/bsp/lpc43xx/M0/template.uvproj @@ -12,13 +12,13 @@ ARM-ADS - LPC4357 - NXP (founded by Philips) - IRAM(0x10000000-0x10007FFF) IRAM2(0x20000000-0x2000FFFF) IROM(0x1A000000-0x1A07FFFF) IROM2(0x1B000000-0x1B07FFFF) CLOCK(12000000) CPUTYPE("Cortex-M4") FPU2 + LPC4357 CM0 + NXP + CLOCK(12000000) CPUTYPE("Cortex-M0") - "STARTUP\NXP\LPC43xx\startup_LPC43xx.s" ("NXP LPC43xx Startup Code") - UL2CM3(-O975 -S0 -C0 -FO7 -FD10000000 -FC800 -FN2 -FF0LPC18xx43xx_512_BA -FS01A000000 -FL080000 -FF1LPC18xx43xx_512_BB -FS11B000000 -FL180000) - 6414 + "STARTUP\NXP\LPC43xx\startup_LPC43xx_M0.s" ("NXP LPC43xx CM0 Startup Code") + UL2CM3(-O910 -S8 -C1 -FO7 -FD10000000 -FC800 -FN0) + 6917 LPC43xx.H @@ -26,10 +26,11 @@ - + -DCORE_M0 SFD\NXP\LPC43xx\LPC43xx.SFR + 0 0 From 7965708050acba01c253b757c8be54a3200e166e Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 21:34:46 +0800 Subject: [PATCH 15/24] lpc43xx: add -Wall --- bsp/lpc43xx/M0/rtconfig.py | 2 +- bsp/lpc43xx/M4/rtconfig.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/lpc43xx/M0/rtconfig.py b/bsp/lpc43xx/M0/rtconfig.py index f6e58476e5..e998c27fe1 100644 --- a/bsp/lpc43xx/M0/rtconfig.py +++ b/bsp/lpc43xx/M0/rtconfig.py @@ -44,7 +44,7 @@ if PLATFORM == 'gcc': SIZE = PREFIX + 'size' OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mthumb -mcpu=cortex-m0 -ffunction-sections -fdata-sections' + 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.ld' diff --git a/bsp/lpc43xx/M4/rtconfig.py b/bsp/lpc43xx/M4/rtconfig.py index f73811f23d..1cbaacf650 100644 --- a/bsp/lpc43xx/M4/rtconfig.py +++ b/bsp/lpc43xx/M4/rtconfig.py @@ -48,7 +48,7 @@ if PLATFORM == 'gcc': 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 From 03a2847f12bb262e5ccd7c64a93da3786d0c8cb4 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 21:39:18 +0800 Subject: [PATCH 16/24] lpc43xx: fix some compile warnings --- bsp/lpc43xx/M0/applications/application.c | 9 +++++++++ bsp/lpc43xx/M0/applications/board.h | 2 +- bsp/lpc43xx/M4/applications/application.c | 8 ++++++++ bsp/lpc43xx/M4/applications/board.h | 2 +- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/bsp/lpc43xx/M0/applications/application.c b/bsp/lpc43xx/M0/applications/application.c index e49f1dd767..209b7071b1 100644 --- a/bsp/lpc43xx/M0/applications/application.c +++ b/bsp/lpc43xx/M0/applications/application.c @@ -16,11 +16,20 @@ #include #include #include "drv_led.h" + #ifdef RT_USING_FINSH #include #include #endif +#ifdef RT_USING_LOGTRACE +#include +#endif + +#ifdef RT_USING_VBUS +#include +#endif + /* thread phase init */ void rt_init_thread_entry(void *parameter) { diff --git a/bsp/lpc43xx/M0/applications/board.h b/bsp/lpc43xx/M0/applications/board.h index c19d0dc4ba..ee300eb739 100644 --- a/bsp/lpc43xx/M0/applications/board.h +++ b/bsp/lpc43xx/M0/applications/board.h @@ -54,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/application.c b/bsp/lpc43xx/M4/applications/application.c index 72e0234d85..8ca6f823f1 100644 --- a/bsp/lpc43xx/M4/applications/application.c +++ b/bsp/lpc43xx/M4/applications/application.c @@ -22,6 +22,14 @@ #include #endif +#ifdef RT_USING_LOGTRACE +#include +#endif + +#ifdef RT_USING_VBUS +#include +#endif + static const unsigned char _M0_CODE[] SECTION("M0_CODE") = { #include "M0_CODE.h" }; diff --git a/bsp/lpc43xx/M4/applications/board.h b/bsp/lpc43xx/M4/applications/board.h index 465ccef2cc..299404a368 100644 --- a/bsp/lpc43xx/M4/applications/board.h +++ b/bsp/lpc43xx/M4/applications/board.h @@ -54,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 From fcff552626079f87889ef4d03cbc25a909b6c71b Mon Sep 17 00:00:00 2001 From: Grissiom Date: Wed, 7 Jan 2015 10:20:50 +0800 Subject: [PATCH 17/24] lpc43xx: fix the SConscripts --- bsp/lpc43xx/M0/SConscript | 10 +++++----- bsp/lpc43xx/M4/SConscript | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bsp/lpc43xx/M0/SConscript b/bsp/lpc43xx/M0/SConscript index 285e5c295f..8333973c01 100644 --- a/bsp/lpc43xx/M0/SConscript +++ b/bsp/lpc43xx/M0/SConscript @@ -5,13 +5,13 @@ objs = [] for d in os.listdir(os.path.join(cwd, '..')): if d not in ('M0', 'M4'): - path = os.path.join(cwd, '..', d, 'SConscript') - if os.path.isfile(path): - objs = objs + SConscript(path) + 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(cwd, d, 'SConscript'); - if os.path.isfile(p): + 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/SConscript b/bsp/lpc43xx/M4/SConscript index 285e5c295f..8333973c01 100644 --- a/bsp/lpc43xx/M4/SConscript +++ b/bsp/lpc43xx/M4/SConscript @@ -5,13 +5,13 @@ objs = [] for d in os.listdir(os.path.join(cwd, '..')): if d not in ('M0', 'M4'): - path = os.path.join(cwd, '..', d, 'SConscript') - if os.path.isfile(path): - objs = objs + SConscript(path) + 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(cwd, d, 'SConscript'); - if os.path.isfile(p): + p = os.path.join(d, 'SConscript'); + if os.path.isfile(os.path.join(cwd, p)): objs = objs + SConscript(p) Return('objs') From f7415e595e613e37c5f7c4cebbc9a67a8eb68592 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Tue, 6 Jan 2015 18:50:22 +0800 Subject: [PATCH 18/24] VBus: added Currently only lpc43xx is supported. --- bsp/lpc43xx/M0/applications/application.c | 69 +- bsp/lpc43xx/M0/applications/board.c | 2 + bsp/lpc43xx/M0/applications/vbus_conf.h | 13 + bsp/lpc43xx/M0/applications/vbus_drv.c | 57 + bsp/lpc43xx/M0/applications/vbus_hw.h | 53 + bsp/lpc43xx/M0/rtconfig.h | 3 +- bsp/lpc43xx/M0/rtthread-lpc43xx.ld | 6 + bsp/lpc43xx/M0/rtthread_lpc43xx.sct | 3 + bsp/lpc43xx/M0/vbus_local_conf.h | 8 + bsp/lpc43xx/M4/applications/application.c | 75 +- bsp/lpc43xx/M4/applications/board.c | 1 + bsp/lpc43xx/M4/applications/vbus_conf.h | 13 + bsp/lpc43xx/M4/applications/vbus_drv.c | 57 + bsp/lpc43xx/M4/applications/vbus_hw.h | 53 + bsp/lpc43xx/M4/rtconfig.h | 3 +- bsp/lpc43xx/M4/rtthread-lpc43xx.ld | 7 + bsp/lpc43xx/M4/rtthread_lpc43xx.sct | 3 + bsp/lpc43xx/M4/vbus_local_conf.h | 8 + components/vbus/SConscript | 29 + components/vbus/prio_queue.c | 275 +++++ components/vbus/prio_queue.h | 44 + components/vbus/rt_watermark_queue.c | 70 ++ components/vbus/rt_watermark_queue.h | 148 +++ components/vbus/share_hdr/vbus_api.h | 79 ++ components/vbus/vbus.c | 1370 +++++++++++++++++++++ components/vbus/vbus.h | 195 +++ components/vbus/vbus_chnx.c | 286 +++++ 27 files changed, 2887 insertions(+), 43 deletions(-) create mode 100644 bsp/lpc43xx/M0/applications/vbus_conf.h create mode 100644 bsp/lpc43xx/M0/applications/vbus_drv.c create mode 100644 bsp/lpc43xx/M0/applications/vbus_hw.h create mode 100644 bsp/lpc43xx/M0/vbus_local_conf.h create mode 100644 bsp/lpc43xx/M4/applications/vbus_conf.h create mode 100644 bsp/lpc43xx/M4/applications/vbus_drv.c create mode 100644 bsp/lpc43xx/M4/applications/vbus_hw.h create mode 100644 bsp/lpc43xx/M4/vbus_local_conf.h create mode 100644 components/vbus/SConscript create mode 100644 components/vbus/prio_queue.c create mode 100644 components/vbus/prio_queue.h create mode 100644 components/vbus/rt_watermark_queue.c create mode 100644 components/vbus/rt_watermark_queue.h create mode 100644 components/vbus/share_hdr/vbus_api.h create mode 100644 components/vbus/vbus.c create mode 100644 components/vbus/vbus.h create mode 100644 components/vbus/vbus_chnx.c diff --git a/bsp/lpc43xx/M0/applications/application.c b/bsp/lpc43xx/M0/applications/application.c index 209b7071b1..8e861873c8 100644 --- a/bsp/lpc43xx/M0/applications/application.c +++ b/bsp/lpc43xx/M0/applications/application.c @@ -33,38 +33,67 @@ /* 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[ 512 ]; +static rt_uint8_t led_stack[1024]; 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_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"); + 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) { - /* led0 on */ - led_value = 1; - led_dev->write(led_dev, 1, &led_value, 1); - rt_thread_delay(RT_TICK_PER_SECOND / 2); /* sleep 0.5 second and switch to other thread */ + rt_uint8_t led_value; + int len; - /* led0 off */ - led_value = 0; - led_dev->write(led_dev, 1, &led_value, 1); - rt_thread_delay(RT_TICK_PER_SECOND / 2); + 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)); } } @@ -74,17 +103,15 @@ int rt_application_init(void) 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); + 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); + 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); diff --git a/bsp/lpc43xx/M0/applications/board.c b/bsp/lpc43xx/M0/applications/board.c index c3377aac2a..324e1bc7ae 100644 --- a/bsp/lpc43xx/M0/applications/board.c +++ b/bsp/lpc43xx/M0/applications/board.c @@ -62,5 +62,7 @@ void rt_hw_board_init() /* setup the console device */ rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + + rt_kprintf("timer compval: %d\n", LPC_RITIMER->COMPVAL); } 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..ad9c8f9210 --- /dev/null +++ b/bsp/lpc43xx/M0/applications/vbus_drv.c @@ -0,0 +1,57 @@ +#include + +#ifdef RT_USING_VBUS +#include +#include +#include + +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..758d2e9e5c --- /dev/null +++ b/bsp/lpc43xx/M0/applications/vbus_hw.h @@ -0,0 +1,53 @@ +/* + * VMM Bus + * + * COPYRIGHT (C) 2014, 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 + * 2014-04-15 Grissiom init commit + */ + +#include +#include + +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 a1ac5509ab..77846191fc 100644 --- a/bsp/lpc43xx/M0/rtconfig.h +++ b/bsp/lpc43xx/M0/rtconfig.h @@ -224,7 +224,8 @@ #define RT_LWIP_MSKADDR3 0 // - +#define RT_USING_VBUS +#define RT_USING_LOGTRACE // diff --git a/bsp/lpc43xx/M0/rtthread-lpc43xx.ld b/bsp/lpc43xx/M0/rtthread-lpc43xx.ld index 3419e6f235..e8ef2fe490 100644 --- a/bsp/lpc43xx/M0/rtthread-lpc43xx.ld +++ b/bsp/lpc43xx/M0/rtthread-lpc43xx.ld @@ -8,6 +8,7 @@ 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; @@ -95,6 +96,11 @@ SECTIONS } > DATA __bss_end = .; + .vbus_ring (NOLOAD) : + { + *(vbus_ring) + } > AHBRAM + _end = .; /* Stabs debugging sections. */ diff --git a/bsp/lpc43xx/M0/rtthread_lpc43xx.sct b/bsp/lpc43xx/M0/rtthread_lpc43xx.sct index 2232a4aa9b..d0fd443a85 100644 --- a/bsp/lpc43xx/M0/rtthread_lpc43xx.sct +++ b/bsp/lpc43xx/M0/rtthread_lpc43xx.sct @@ -11,5 +11,8 @@ LR_IROM2 0x1B000000 0x00080000 { ; load region size_region RW_IRAM2 0x10080000 0x00008000 { ; RW data .ANY (+RW +ZI) } + RW_AHBRAM 0x20000000 0x00010000 { ; RW data + * (vbus_ring) + } } 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/applications/application.c b/bsp/lpc43xx/M4/applications/application.c index 8ca6f823f1..6575991895 100644 --- a/bsp/lpc43xx/M4/applications/application.c +++ b/bsp/lpc43xx/M4/applications/application.c @@ -58,12 +58,26 @@ static void _boot_M0(void) /* 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(); } @@ -73,26 +87,49 @@ 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_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"); + 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) { - /* 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 */ + int len; - /* led0 off */ - led_value = 0; - led_dev->write(led_dev, 0, &led_value, 1); - rt_thread_delay(RT_TICK_PER_SECOND / 2); + 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); } } @@ -102,17 +139,15 @@ int rt_application_init(void) 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); + 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); + 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); diff --git a/bsp/lpc43xx/M4/applications/board.c b/bsp/lpc43xx/M4/applications/board.c index b7d3ead87e..3358e52c96 100644 --- a/bsp/lpc43xx/M4/applications/board.c +++ b/bsp/lpc43xx/M4/applications/board.c @@ -65,6 +65,7 @@ void rt_hw_board_init() /* setup the console device */ rt_console_set_device(RT_CONSOLE_DEVICE_NAME); + rt_kprintf("timer compval: %d\n", SystemCoreClock / RT_TICK_PER_SECOND - 1); #if LPC_EXT_SDRAM == 1 lpc_sdram_hw_init(); 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..6d85a2e11e --- /dev/null +++ b/bsp/lpc43xx/M4/applications/vbus_drv.c @@ -0,0 +1,57 @@ +#include + +#ifdef RT_USING_VBUS +#include +#include +#include + +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..758d2e9e5c --- /dev/null +++ b/bsp/lpc43xx/M4/applications/vbus_hw.h @@ -0,0 +1,53 @@ +/* + * VMM Bus + * + * COPYRIGHT (C) 2014, 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 + * 2014-04-15 Grissiom init commit + */ + +#include +#include + +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 fb65f5bf3d..31854ca2fc 100644 --- a/bsp/lpc43xx/M4/rtconfig.h +++ b/bsp/lpc43xx/M4/rtconfig.h @@ -223,7 +223,8 @@ #define RT_LWIP_MSKADDR3 0 // - +#define RT_USING_VBUS +#define RT_USING_LOGTRACE // diff --git a/bsp/lpc43xx/M4/rtthread-lpc43xx.ld b/bsp/lpc43xx/M4/rtthread-lpc43xx.ld index 81d1655b52..63057abc40 100644 --- a/bsp/lpc43xx/M4/rtthread-lpc43xx.ld +++ b/bsp/lpc43xx/M4/rtthread-lpc43xx.ld @@ -9,6 +9,7 @@ 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; @@ -97,6 +98,12 @@ SECTIONS } > DATA __bss_end = .; + .vbus_ring (NOLOAD) : + { + *(vbus_ring) + } > AHBRAM + + .text.M0CODE : { *(M0_CODE) diff --git a/bsp/lpc43xx/M4/rtthread_lpc43xx.sct b/bsp/lpc43xx/M4/rtthread_lpc43xx.sct index c483ea87d2..238ca28c6e 100644 --- a/bsp/lpc43xx/M4/rtthread_lpc43xx.sct +++ b/bsp/lpc43xx/M4/rtthread_lpc43xx.sct @@ -11,6 +11,9 @@ LR_IROM1 0x1A000000 0x00080000 { ; load region size_region RW_IRAM1 0x10000000 0x00008000 { ; RW data .ANY (+RW +ZI) } + RW_AHBRAM 0x20000000 0x00010000 { ; RW data + * (vbus_ring) + } } LR_IROM2 0x1B000000 0x00080000 { 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/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..e0f57d1e05 --- /dev/null +++ b/components/vbus/prio_queue.c @@ -0,0 +1,275 @@ +/* + * Priority Queue + * + * COPYRIGHT (C) 2013, 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 + * 2013-11-04 Grissiom add comment + */ + +#include +#include + +#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..09bc3c7e63 --- /dev/null +++ b/components/vbus/prio_queue.h @@ -0,0 +1,44 @@ +#ifndef __PRIO_QUEUE_H__ +#define __PRIO_QUEUE_H__ + +#include + +#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..9c551fa525 --- /dev/null +++ b/components/vbus/rt_watermark_queue.c @@ -0,0 +1,70 @@ +/* + * Water Gauge + * + * COPYRIGHT (C) 2014, 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 + * 2014-04-16 Grissiom first version + */ + +#include +#include + +#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..c29c65bda0 --- /dev/null +++ b/components/vbus/rt_watermark_queue.h @@ -0,0 +1,148 @@ +/* + * Thread queue with water mark + * + * COPYRIGHT (C) 2014, 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 + * 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 /* 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..4ce618ee86 --- /dev/null +++ b/components/vbus/vbus.c @@ -0,0 +1,1370 @@ +/* + * VMM Bus + * + * COPYRIGHT (C) 2013-2014, 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 + * 2013-11-04 Grissiom add comment + */ + +#include +#include +#include + +#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 + +#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 +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, ¬use); +} + +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_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..83f0bb295e --- /dev/null +++ b/components/vbus/vbus.h @@ -0,0 +1,195 @@ +#ifndef __VBUS_H__ +#define __VBUS_H__ +/* + * VBus + * + * COPYRIGHT (C) 2013-2014, 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 + * 2014-06-09 Grissiom version 2.0.2; add comment + */ + +#include "vbus_local_conf.h" +#include + +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..fab6b20c2d --- /dev/null +++ b/components/vbus/vbus_chnx.c @@ -0,0 +1,286 @@ +/* + * Channel on VMM Bus + * + * COPYRIGHT (C) 2013, 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 + * 2013-11-04 Grissiom add comment + */ + +#include +#include +#include + +#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; +} From 22938a93ef781f3775ee1936b69c4a465b4dfc43 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Wed, 7 Jan 2015 11:13:13 +0800 Subject: [PATCH 19/24] lpc43xx: fix some compile warnings --- bsp/lpc43xx/drivers/drv_uart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp/lpc43xx/drivers/drv_uart.c b/bsp/lpc43xx/drivers/drv_uart.c index 46edf3ab04..70f4a880e1 100644 --- a/bsp/lpc43xx/drivers/drv_uart.c +++ b/bsp/lpc43xx/drivers/drv_uart.c @@ -86,7 +86,7 @@ static const struct rt_uart_ops lpc_uart_ops = static void _do_uart_isr(struct rt_serial_device *sdev) { struct lpc_uart *uart; - volatile uint32_t intsrc, temp; + uint32_t intsrc; uart = sdev->parent.user_data; @@ -102,7 +102,7 @@ static void _do_uart_isr(struct rt_serial_device *sdev) /* Receive an error data */ if (intsrc & UART_LSR_PE) { - temp = uart->USART->RBR; + uart->USART->RBR; } break; case UART_IIR_INTID_RDA: From 17a75eaa028d0c4f462c0cc64649b661bdf7d5d0 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Wed, 7 Jan 2015 12:47:33 +0800 Subject: [PATCH 20/24] lpc43xx: remove the fpu settings in startup_LPC43xx_M0 --- .../NXP/LPC43xx/Source/Templates/GCC/startup_LPC43xx_M0.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 38e1869243..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,7 +6,7 @@ .syntax unified .cpu cortex-m0 - .fpu softvfp + .arch armv6-m .thumb .word _sidata From 11026d05791d7208036b18c043d6e968ef366f00 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Wed, 7 Jan 2015 12:50:43 +0800 Subject: [PATCH 21/24] lpc43xx: clean the .o before building M0 and M4 SCons will omit the file in parent dir of SConstruct somehow and build the object files in that dir instead of in variant dir. This cause problem because we cannot mix the object files between M0 and M4 which SCons failed to rebuild. So we have to manually remove the files before building. --- bsp/lpc43xx/M0/SConstruct | 18 ++++++++++++++++++ bsp/lpc43xx/M4/SConstruct | 10 +++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/bsp/lpc43xx/M0/SConstruct b/bsp/lpc43xx/M0/SConstruct index 62cebd454f..c7967d02f6 100644 --- a/bsp/lpc43xx/M0/SConstruct +++ b/bsp/lpc43xx/M0/SConstruct @@ -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/M4/SConstruct b/bsp/lpc43xx/M4/SConstruct index 17f5eaf11c..7b02b732d4 100644 --- a/bsp/lpc43xx/M4/SConstruct +++ b/bsp/lpc43xx/M4/SConstruct @@ -28,6 +28,7 @@ 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') @@ -35,12 +36,19 @@ if rtconfig.CROSS_TOOL == 'gcc': 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. + # 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) From 05a01884e6b4bf0024397fa06c5bbe87d213609e Mon Sep 17 00:00:00 2001 From: Grissiom Date: Wed, 7 Jan 2015 17:07:32 +0800 Subject: [PATCH 22/24] lpc43xx: fix clock configure --- bsp/lpc43xx/M0/applications/board.c | 5 ++--- bsp/lpc43xx/M4/applications/board.c | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bsp/lpc43xx/M0/applications/board.c b/bsp/lpc43xx/M0/applications/board.c index 324e1bc7ae..000bd52f40 100644 --- a/bsp/lpc43xx/M0/applications/board.c +++ b/bsp/lpc43xx/M0/applications/board.c @@ -46,7 +46,8 @@ void rt_hw_board_init() SystemCoreClockUpdate(); /* Setup RIT timer. */ - LPC_RITIMER->COMPVAL = SystemCoreClock / RT_TICK_PER_SECOND - 1; + 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. */ @@ -62,7 +63,5 @@ void rt_hw_board_init() /* setup the console device */ rt_console_set_device(RT_CONSOLE_DEVICE_NAME); - - rt_kprintf("timer compval: %d\n", LPC_RITIMER->COMPVAL); } diff --git a/bsp/lpc43xx/M4/applications/board.c b/bsp/lpc43xx/M4/applications/board.c index 3358e52c96..dc0859f666 100644 --- a/bsp/lpc43xx/M4/applications/board.c +++ b/bsp/lpc43xx/M4/applications/board.c @@ -55,7 +55,7 @@ void rt_hw_board_init() 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); @@ -65,7 +65,6 @@ void rt_hw_board_init() /* setup the console device */ rt_console_set_device(RT_CONSOLE_DEVICE_NAME); - rt_kprintf("timer compval: %d\n", SystemCoreClock / RT_TICK_PER_SECOND - 1); #if LPC_EXT_SDRAM == 1 lpc_sdram_hw_init(); From 17aa3b19756945b809330384c9478b398f825ac7 Mon Sep 17 00:00:00 2001 From: Grissiom Date: Thu, 8 Jan 2015 17:05:56 +0800 Subject: [PATCH 23/24] vbus: update copy-right information --- components/vbus/prio_queue.c | 3 ++- components/vbus/prio_queue.h | 29 ++++++++++++++++++++++++++++ components/vbus/rt_watermark_queue.c | 3 ++- components/vbus/rt_watermark_queue.h | 3 ++- components/vbus/vbus.c | 7 ++++--- components/vbus/vbus.h | 4 +++- components/vbus/vbus_chnx.c | 3 ++- 7 files changed, 44 insertions(+), 8 deletions(-) diff --git a/components/vbus/prio_queue.c b/components/vbus/prio_queue.c index e0f57d1e05..b402e0376a 100644 --- a/components/vbus/prio_queue.c +++ b/components/vbus/prio_queue.c @@ -1,7 +1,8 @@ /* * Priority Queue * - * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd + * 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) * diff --git a/components/vbus/prio_queue.h b/components/vbus/prio_queue.h index 09bc3c7e63..8a29cbb715 100644 --- a/components/vbus/prio_queue.h +++ b/components/vbus/prio_queue.h @@ -1,3 +1,32 @@ +/* + * 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__ diff --git a/components/vbus/rt_watermark_queue.c b/components/vbus/rt_watermark_queue.c index 9c551fa525..329e9f331c 100644 --- a/components/vbus/rt_watermark_queue.c +++ b/components/vbus/rt_watermark_queue.c @@ -1,7 +1,8 @@ /* * Water Gauge * - * COPYRIGHT (C) 2014, Shanghai Real-Thread Technology Co., Ltd + * 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) * diff --git a/components/vbus/rt_watermark_queue.h b/components/vbus/rt_watermark_queue.h index c29c65bda0..1fd51e07c2 100644 --- a/components/vbus/rt_watermark_queue.h +++ b/components/vbus/rt_watermark_queue.h @@ -1,7 +1,8 @@ /* * Thread queue with water mark * - * COPYRIGHT (C) 2014, Shanghai Real-Thread Technology Co., Ltd + * 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) * diff --git a/components/vbus/vbus.c b/components/vbus/vbus.c index 4ce618ee86..7005e52513 100644 --- a/components/vbus/vbus.c +++ b/components/vbus/vbus.c @@ -1,7 +1,8 @@ /* * VMM Bus * - * COPYRIGHT (C) 2013-2014, Shanghai Real-Thread Technology Co., Ltd + * 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) * @@ -59,7 +60,7 @@ const static struct log_trace_session _lgs = { #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__) +#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"}, @@ -68,7 +69,7 @@ static struct log_trace_session _lgs = { #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__) +#define vbus_error(fmt, ...) log_session(&_lgs, LOG_TRACE_ERROR""fmt, ##__VA_ARGS__) #endif #endif // RT_USING_LOGTRACE diff --git a/components/vbus/vbus.h b/components/vbus/vbus.h index 83f0bb295e..2187773a47 100644 --- a/components/vbus/vbus.h +++ b/components/vbus/vbus.h @@ -3,7 +3,8 @@ /* * VBus * - * COPYRIGHT (C) 2013-2014, Shanghai Real-Thread Technology Co., Ltd + * 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) * @@ -26,6 +27,7 @@ * 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" diff --git a/components/vbus/vbus_chnx.c b/components/vbus/vbus_chnx.c index fab6b20c2d..bd54c9dbbd 100644 --- a/components/vbus/vbus_chnx.c +++ b/components/vbus/vbus_chnx.c @@ -1,7 +1,8 @@ /* * Channel on VMM Bus * - * COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., Ltd + * 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) * From 81b37fb1f90fc57eb28f97ecd32d98642db96b2a Mon Sep 17 00:00:00 2001 From: Grissiom Date: Thu, 8 Jan 2015 17:16:26 +0800 Subject: [PATCH 24/24] lpc43xx: add copy-right info in vbus drivers --- bsp/lpc43xx/M0/applications/vbus_drv.c | 29 ++++++++++++++++++++++++++ bsp/lpc43xx/M0/applications/vbus_hw.h | 4 ++-- bsp/lpc43xx/M4/applications/vbus_drv.c | 29 ++++++++++++++++++++++++++ bsp/lpc43xx/M4/applications/vbus_hw.h | 4 ++-- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/bsp/lpc43xx/M0/applications/vbus_drv.c b/bsp/lpc43xx/M0/applications/vbus_drv.c index ad9c8f9210..24d7f19b58 100644 --- a/bsp/lpc43xx/M0/applications/vbus_drv.c +++ b/bsp/lpc43xx/M0/applications/vbus_drv.c @@ -1,3 +1,32 @@ +/* + * 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 #ifdef RT_USING_VBUS diff --git a/bsp/lpc43xx/M0/applications/vbus_hw.h b/bsp/lpc43xx/M0/applications/vbus_hw.h index 758d2e9e5c..b88586a112 100644 --- a/bsp/lpc43xx/M0/applications/vbus_hw.h +++ b/bsp/lpc43xx/M0/applications/vbus_hw.h @@ -1,7 +1,7 @@ /* * VMM Bus * - * COPYRIGHT (C) 2014, Shanghai Real-Thread Technology Co., Ltd + * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd * * This file is part of RT-Thread (http://www.rt-thread.org) * @@ -23,7 +23,7 @@ * * Change Logs: * Date Author Notes - * 2014-04-15 Grissiom init commit + * 2015-01-07 Grissiom init commit */ #include diff --git a/bsp/lpc43xx/M4/applications/vbus_drv.c b/bsp/lpc43xx/M4/applications/vbus_drv.c index 6d85a2e11e..872de86504 100644 --- a/bsp/lpc43xx/M4/applications/vbus_drv.c +++ b/bsp/lpc43xx/M4/applications/vbus_drv.c @@ -1,3 +1,32 @@ +/* + * 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 #ifdef RT_USING_VBUS diff --git a/bsp/lpc43xx/M4/applications/vbus_hw.h b/bsp/lpc43xx/M4/applications/vbus_hw.h index 758d2e9e5c..b88586a112 100644 --- a/bsp/lpc43xx/M4/applications/vbus_hw.h +++ b/bsp/lpc43xx/M4/applications/vbus_hw.h @@ -1,7 +1,7 @@ /* * VMM Bus * - * COPYRIGHT (C) 2014, Shanghai Real-Thread Technology Co., Ltd + * COPYRIGHT (C) 2015, Shanghai Real-Thread Technology Co., Ltd * * This file is part of RT-Thread (http://www.rt-thread.org) * @@ -23,7 +23,7 @@ * * Change Logs: * Date Author Notes - * 2014-04-15 Grissiom init commit + * 2015-01-07 Grissiom init commit */ #include