From ca486b4cfc62b51c2f63576136911e3d8b813b10 Mon Sep 17 00:00:00 2001 From: James Snyder Date: Thu, 26 Feb 2015 20:10:25 -0600 Subject: [PATCH 01/26] update link for mailing list --- README.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index ca0d1df6..43085a5a 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -91,4 +91,4 @@ Dado Sutter: dadosutter -at- eluaproject -dot- net James Snyder: jbsnyder -at- eluaproject -dot- net You are also welcomed to share your questions and suggestions on our -link:http://www.eluaproject.net/en_comunity.html#lists[Mail Discussion List] \ No newline at end of file +link:http://www.eluaproject.net/get-involved/community-resources[Mail Discussion List] \ No newline at end of file From 377567feab4e7901cb14ca033625fe8dd262990f Mon Sep 17 00:00:00 2001 From: denis Date: Thu, 12 Mar 2015 12:25:19 +0300 Subject: [PATCH 02/26] better handling of CR/LF --- src/common.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/common.c b/src/common.c index ede14361..42dfafc6 100644 --- a/src/common.c +++ b/src/common.c @@ -24,6 +24,8 @@ extern const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ]; #define CON_BUF_SIZE 0 #endif // #ifndef CON_BUF_SIZE +static unsigned int skip_0A = 0; + // **************************************************************************** // XMODEM support code @@ -55,10 +57,23 @@ static void term_out( u8 data ) static int term_in( int mode ) { - if( mode == TERM_INPUT_DONT_WAIT ) - return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, 0 ); - else - return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, PLATFORM_TIMER_INF_TIMEOUT ); + int c; + do{ + if( mode == TERM_INPUT_DONT_WAIT ) + c = platform_uart_recv( CON_UART_ID, CON_TIMER_ID, 0 ); + else + c = platform_uart_recv( CON_UART_ID, CON_TIMER_ID, PLATFORM_TIMER_INF_TIMEOUT ); + // CR/LF sequence, skip the second char (LF) if applicable + if( skip_0A > 0 ) + { + skip_0A=0; + if( c == 0x0A ) + continue; + } + + break; + }while( TRUE ); + return c; } static int term_translate( int data ) @@ -107,8 +122,11 @@ static int term_translate( int data ) } else if( data == 0x0D ) { - // CR/LF sequence, read the second char (LF) if applicable - platform_uart_recv( CON_UART_ID, CON_TIMER_ID, TERM_TIMEOUT ); + skip_0A=1; + return KC_ENTER; + } + else if( data == 0x0A ) + { return KC_ENTER; } else From d2b4c4a9e49aae9b17460950d0b400a38af54300 Mon Sep 17 00:00:00 2001 From: James Snyder Date: Fri, 17 Apr 2015 10:26:07 -0500 Subject: [PATCH 03/26] add initial support for nucleo-stm32f411re --- boards/known/nucleo-f411re.lua | 31 +++++++++++++++ build_data.lua | 2 +- src/platform/stm32f4/cpu_stm32f411re.h | 52 ++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 boards/known/nucleo-f411re.lua create mode 100644 src/platform/stm32f4/cpu_stm32f411re.h diff --git a/boards/known/nucleo-f411re.lua b/boards/known/nucleo-f411re.lua new file mode 100644 index 00000000..ff06e99d --- /dev/null +++ b/boards/known/nucleo-f411re.lua @@ -0,0 +1,31 @@ +-- STM32F4-NUCLEO build configuration + +return { + cpu = 'stm32f411re', + components = { + sercon = { uart = "1", speed = 115200 }, + romfs = true, + cdc = false, + advanced_shell = true, + term = { lines = 25, cols = 80 }, + linenoise = { shell_lines = 10, lua_lines = 50 }, + stm32f4_enc = true, + rpc = { uart = "0", speed = 115200 }, + adc = { buf_size = 2 }, + xmodem = true, + cints = true, + luaints = true + }, + config = { + egc = { mode = "alloc" }, + vtmr = { num = 4, freq = 10 }, + ram = { internal_rams = 1 }, + clocks = { internal = 16000000, cpu = 100000000 }, + stm32f4_uart_pins = { con_rx_port = 0, con_rx_pin = 3, con_tx_port = 0, con_tx_pin = 2 } + }, + modules = { + generic = { 'all', "-i2c", "-net", "-can" }, + platform = 'all', + }, +} + diff --git a/build_data.lua b/build_data.lua index 2353ba48..e45a32e5 100644 --- a/build_data.lua +++ b/build_data.lua @@ -111,7 +111,7 @@ local platform_list = str7 = { cpus = { 'STR711FR2' }, arch = 'arm' }, stm32f2 = { cpus = { 'STM32F205RF' }, arch = 'cortexm' }, stm32 = { cpus = { 'STM32F103ZE', 'STM32F103RE' }, arch = 'cortexm' }, - stm32f4 = { cpus = { 'STM32F401RE', 'STM32F407VG', 'STM32F407ZG' }, arch = 'cortexm' }, + stm32f4 = { cpus = { 'STM32F411RE', 'STM32F401RE', 'STM32F407VG', 'STM32F407ZG' }, arch = 'cortexm' }, avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, arch = 'avr32' }, lpc24xx = { cpus = { 'LPC2468' }, arch = 'arm' }, lpc17xx = { cpus = { 'LPC1768' }, arch = 'cortexm' } diff --git a/src/platform/stm32f4/cpu_stm32f411re.h b/src/platform/stm32f4/cpu_stm32f411re.h new file mode 100644 index 00000000..f3e5d83c --- /dev/null +++ b/src/platform/stm32f4/cpu_stm32f411re.h @@ -0,0 +1,52 @@ +// CPU definition file for STM32F401RE + +#ifndef __CPU_STM32F401RE_H__ +#define __CPU_STM32F401RE_H__ + +#include "type.h" +#include "stacks.h" +#include "platform_ints.h" + +// Number of resources (0 if not available/not implemented) +#define NUM_PIO 5 +#define NUM_SPI 3 +#define NUM_UART 3 +#define NUM_TIMER 12 +#define NUM_PHYS_TIMER 12 +#define NUM_PWM 4 +#define NUM_ADC 18 +#define NUM_CAN 0 + +#define ADC_BIT_RESOLUTION 12 + +u32 platform_s_cpu_get_frequency(); +#define CPU_FREQUENCY platform_s_cpu_get_frequency() + +// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...) +#define PIO_PREFIX 'A' +// Pins per port configuration: +// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or +// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array +// Use #define PIO_PINS_PER_PORT 0 if this isn't needed +#define PIO_PINS_PER_PORT 16 + +// Internal memory data +#define INTERNAL_SRAM_BASE 0x20000000 +#define INTERNAL_SRAM_SIZE ( 128 * 1024 ) +#define INTERNAL_RAM1_FIRST_FREE end +#define INTERNAL_RAM1_LAST_FREE ( INTERNAL_SRAM_BASE + INTERNAL_SRAM_SIZE - STACK_SIZE_TOTAL -1 ) + +// Internal Flash data +#define INTERNAL_FLASH_SIZE ( 512 * 1024 ) +#define INTERNAL_FLASH_SECTOR_ARRAY { 16384, 16384, 16384, 16384, 65536, 131072, 131072, 131072 } +#define INTERNAL_FLASH_START_ADDRESS 0x08000000 + +// Interrupt list for this CPU +#define PLATFORM_CPU_CONSTANTS_INTS\ + _C( INT_GPIO_POSEDGE ), \ + _C( INT_GPIO_NEGEDGE ), \ + _C( INT_TMR_MATCH ), \ + _C( INT_UART_RX ), + +#endif // #ifndef __CPU_STM32F401RE_H__ + From 68a5a0f26cd1f7cfba2047a238de76c9b89663df Mon Sep 17 00:00:00 2001 From: James Snyder Date: Fri, 17 Apr 2015 10:52:38 -0500 Subject: [PATCH 04/26] correct typo in cpu header for stm32f411re --- src/platform/stm32f4/cpu_stm32f411re.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platform/stm32f4/cpu_stm32f411re.h b/src/platform/stm32f4/cpu_stm32f411re.h index f3e5d83c..bdaa6149 100644 --- a/src/platform/stm32f4/cpu_stm32f411re.h +++ b/src/platform/stm32f4/cpu_stm32f411re.h @@ -1,7 +1,7 @@ -// CPU definition file for STM32F401RE +// CPU definition file for STM32F411RE -#ifndef __CPU_STM32F401RE_H__ -#define __CPU_STM32F401RE_H__ +#ifndef __CPU_STM32F411RE_H__ +#define __CPU_STM32F411RE_H__ #include "type.h" #include "stacks.h" @@ -48,5 +48,5 @@ u32 platform_s_cpu_get_frequency(); _C( INT_TMR_MATCH ), \ _C( INT_UART_RX ), -#endif // #ifndef __CPU_STM32F401RE_H__ +#endif // #ifndef __CPU_STM32F411RE_H__ From 51b800acd6a7e888f3e5d926eb475f5452594793 Mon Sep 17 00:00:00 2001 From: denis Date: Wed, 11 Mar 2015 20:46:48 +0300 Subject: [PATCH 05/26] improve shell compatibility with vt100, fix #57 --- src/linenoise.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linenoise.c b/src/linenoise.c index fb415830..77c9e1ff 100644 --- a/src/linenoise.c +++ b/src/linenoise.c @@ -131,7 +131,7 @@ static void refreshLine(const char *prompt, char *buf, size_t len, size_t pos, s } /* Cursor to left edge */ - snprintf(seq,MAX_SEQ_LEN,"\x1b[0G"); + snprintf(seq,MAX_SEQ_LEN,"\r"); term_putstr( seq, strlen( seq ) ); /* Write the prompt and the current buffer content */ term_putstr( prompt, strlen( prompt ) ); @@ -140,7 +140,7 @@ static void refreshLine(const char *prompt, char *buf, size_t len, size_t pos, s snprintf(seq,MAX_SEQ_LEN,"\x1b[0K"); term_putstr( seq, strlen( seq ) ); /* Move cursor to original position. */ - snprintf(seq,MAX_SEQ_LEN,"\x1b[0G\x1b[%dC", (int)(pos+plen)); + snprintf(seq,MAX_SEQ_LEN,"\r\x1b[%dC", (int)(pos+plen)); term_putstr( seq, strlen( seq ) ); } From 943c5a83b94e3418269737f3caeb013dd7144cad Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Mon, 20 Apr 2015 15:36:09 +0200 Subject: [PATCH 06/26] Fix build for MBED, add initial support for LPCXpresso LPC1769 --- boards/known/lpcxpresso.lua | 26 ++++++++++++ build_data.lua | 2 +- src/platform/lpc17xx/cpu_lpc1769.h | 43 ++++++++++++++++++++ src/platform/lpc17xx/drivers/inc/lpc_types.h | 7 +--- src/platform/lpc17xx/type.h | 2 + 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 boards/known/lpcxpresso.lua create mode 100644 src/platform/lpc17xx/cpu_lpc1769.h diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua new file mode 100644 index 00000000..acce3522 --- /dev/null +++ b/boards/known/lpcxpresso.lua @@ -0,0 +1,26 @@ +-- LPCXpresso LPC1769 build configuration + +return { + cpu = 'lpc1769', + components = { + sercon = { uart = 0, speed = 115200 }, + romfs = true, + shell = true, + term = { lines = 25, cols = 80 }, + linenoise = { shell_lines = 10, lua_lines = 50 }, + rpc = { uart = 0, speed = 115200 }, + adc = { buf_size = 4 }, + xmodem = true, + lpc17xx_semifs = true + }, + config = { + egc = { mode = "alloc" }, + ram = { internal_rams = 2 } + }, + modules = { + generic = { 'all', "-spi", "-i2c", "-net" }, + platform = 'all', + platform_name = 'lpcxpresso' + }, +} + diff --git a/build_data.lua b/build_data.lua index e45a32e5..85ddcc12 100644 --- a/build_data.lua +++ b/build_data.lua @@ -114,7 +114,7 @@ local platform_list = stm32f4 = { cpus = { 'STM32F411RE', 'STM32F401RE', 'STM32F407VG', 'STM32F407ZG' }, arch = 'cortexm' }, avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, arch = 'avr32' }, lpc24xx = { cpus = { 'LPC2468' }, arch = 'arm' }, - lpc17xx = { cpus = { 'LPC1768' }, arch = 'cortexm' } + lpc17xx = { cpus = { 'LPC1768', 'LPC1769' }, arch = 'cortexm' } } -- Returns the platform of a given CPU diff --git a/src/platform/lpc17xx/cpu_lpc1769.h b/src/platform/lpc17xx/cpu_lpc1769.h new file mode 100644 index 00000000..c1c139ee --- /dev/null +++ b/src/platform/lpc17xx/cpu_lpc1769.h @@ -0,0 +1,43 @@ +// eLua platform configuration + +#ifndef __CPU_LPC1769_H__ +#define __CPU_LPC1769_H__ + +#include "stacks.h" + +// Number of resources (0 if not available/not implemented) +#define NUM_PIO 5 +#define NUM_SPI 0 +#define NUM_UART 4 +#define NUM_PWM 6 +#define NUM_ADC 8 +#define NUM_CAN 2 +#define NUM_TIMER 4 + +#define ADC_BIT_RESOLUTION 12 + +// CPU frequency (needed by the CPU module, 0 if not used) +u32 mbed_get_cpu_frequency(); +#define CPU_FREQUENCY mbed_get_cpu_frequency() + +// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...) +#define PIO_PREFIX '0' +// Pins per port configuration: +// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or +// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array +// Use #define PIO_PINS_PER_PORT 0 if this isn't needed +#define PIO_PINS_PER_PORT 32 + +// Allocator data: define your free memory zones here in two arrays +// (start address and end address) +#define SRAM_ORIGIN 0x10000000 +#define SRAM_SIZE 0x8000 +#define SRAM2_ORIGIN 0x2007C000 +#define SRAM2_SIZE 0x8000 +#define INTERNAL_RAM1_FIRST_FREE end +#define INTERNAL_RAM1_LAST_FREE ( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) +#define INTERNAL_RAM2_FIRST_FREE SRAM2_ORIGIN +#define INTERNAL_RAM2_LAST_FREE ( SRAM2_ORIGIN + SRAM2_SIZE - 1 ) + +#endif // #ifndef __CPU_LPC1769_H__ + diff --git a/src/platform/lpc17xx/drivers/inc/lpc_types.h b/src/platform/lpc17xx/drivers/inc/lpc_types.h index f7f9e2f2..5c517eaf 100644 --- a/src/platform/lpc17xx/drivers/inc/lpc_types.h +++ b/src/platform/lpc17xx/drivers/inc/lpc_types.h @@ -32,18 +32,13 @@ /* Includes ------------------------------------------------------------------- */ #include - +#include /* Public Types --------------------------------------------------------------- */ /** @defgroup LPC_Types_Public_Types * @{ */ -/** - * @brief Boolean Type definition - */ -typedef enum {FALSE = 0, TRUE = !FALSE} Bool; - /** * @brief Flag Status and Interrupt Flag Status type definition */ diff --git a/src/platform/lpc17xx/type.h b/src/platform/lpc17xx/type.h index 47ec5c04..46878987 100644 --- a/src/platform/lpc17xx/type.h +++ b/src/platform/lpc17xx/type.h @@ -19,5 +19,7 @@ typedef unsigned int BOOL; typedef volatile unsigned long* PREG; +typedef enum {FALSE = 0, TRUE = !FALSE} Bool; + #endif From e5d71d0a595604e8a43484f98614dfadb09aec1b Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Mon, 20 Apr 2015 23:50:10 +0200 Subject: [PATCH 07/26] Support different clock rates on LPC17xx (100MHz on MBED, 120MHz on LPCXPresso) --- boards/known/lpcxpresso.lua | 3 +- boards/known/mbed.lua | 3 +- config/configurations.lua | 3 +- src/platform/lpc17xx/system_LPC17xx.c | 69 ++++++++++++++------------- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index acce3522..3f5caca7 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -15,7 +15,8 @@ return { }, config = { egc = { mode = "alloc" }, - ram = { internal_rams = 2 } + ram = { internal_rams = 2 }, + clocks = { external = 12000000, cpu = 120000000, rtc=32768 } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, diff --git a/boards/known/mbed.lua b/boards/known/mbed.lua index 4ab4a2e9..8acd5e64 100644 --- a/boards/known/mbed.lua +++ b/boards/known/mbed.lua @@ -15,7 +15,8 @@ return { }, config = { egc = { mode = "alloc" }, - ram = { internal_rams = 2 } + ram = { internal_rams = 2 }, + clocks = { external = 12000000, cpu = 100000000, rtc=32768 } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, diff --git a/config/configurations.lua b/config/configurations.lua index 02c128ff..74369c8b 100644 --- a/config/configurations.lua +++ b/config/configurations.lua @@ -156,7 +156,8 @@ function init() configs.clocks = { attrs = { external = at.make_optional( at.int_attr( 'ELUA_BOARD_EXTERNAL_CLOCK_HZ', 1 ) ), - cpu = at.make_optional( at.int_attr( 'ELUA_BOARD_CPU_CLOCK_HZ', 1 ) ) + cpu = at.make_optional( at.int_attr( 'ELUA_BOARD_CPU_CLOCK_HZ', 1 ) ), + rtc = at.make_optional( at.int_attr( 'ELUA_BOARD_RTC_CLOCK_HZ', 1 ) ) } } diff --git a/src/platform/lpc17xx/system_LPC17xx.c b/src/platform/lpc17xx/system_LPC17xx.c index e1734625..452c272f 100644 --- a/src/platform/lpc17xx/system_LPC17xx.c +++ b/src/platform/lpc17xx/system_LPC17xx.c @@ -20,15 +20,15 @@ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. * + * @par + * Modified for usage in eLua. + * ******************************************************************************/ #include #include "LPC17xx.h" - -/* -//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ -*/ +#include /*--------------------- Clock Configuration ---------------------------------- // @@ -279,23 +279,6 @@ // // // -*/ -#define CLOCK_SETUP 1 -#define SCS_Val 0x00000020 -#define CLKSRCSEL_Val 0x00000001 -#define PLL0_SETUP 1 -#define PLL0CFG_Val 0x00050063 -#define PLL1_SETUP 1 -#define PLL1CFG_Val 0x00000023 -#define CCLKCFG_Val 0x00000003 -#define USBCLKCFG_Val 0x00000000 -#define PCLKSEL0_Val 0x00000000 -#define PCLKSEL1_Val 0x00000000 -#define PCONP_Val 0x042887DE -#define CLKOUTCFG_Val 0x00000000 - - -/*--------------------- Flash Accelerator Configuration ---------------------- // // Flash Accelerator Configuration // Reserved @@ -304,12 +287,43 @@ // <1=> 2 CPU clocks (for CPU clock up to 40 MHz) // <2=> 3 CPU clocks (for CPU clock up to 60 MHz) // <3=> 4 CPU clocks (for CPU clock up to 80 MHz) -// <4=> 5 CPU clocks (for CPU clock up to 100 MHz) +// <4=> 5 CPU clocks (for CPU clock up to 100 MHz, or 1769 up to 120MHz) // <5=> 6 CPU clocks (for any CPU clock) // */ +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ +#define XTAL ((DWORD)(ELUA_BOARD_EXTERNAL_CLOCK_HZ)) /* Oscillator frequency */ +#define OSC_CLK ((DWORD)( XTAL)) /* Main oscillator frequency */ +#define RTC_CLK ((DWORD)( ELUA_BOARD_RTC_CLOCK_HZ)) /* RTC oscillator frequency */ +#define IRC_OSC ((DWORD)( 4000000UL)) /* Internal RC oscillator frequency */ +#define CPU_CLK ( ELUA_BOARD_CPU_CLOCK_HZ) /* Desired CPU clock */ + +#define CLOCK_SETUP 1 +#define SCS_Val 0x00000020 +#define CLKSRCSEL_Val 0x00000001 +#define PLL0_SETUP 1 +/* In a perfect world, we'd calculate the PLL configuration from the information above. + * For now, just handle the two cases we actually know about. */ +#if CPU_CLK==100000000 + #define PLL0CFG_Val 0x00050063 +#elif CPU_CLK==120000000 + #define PLL0CFG_Val 0x00050077 +#else + #error "Unsupported CPU clock, please provide PLL configuration" +#endif +#define PLL1_SETUP 1 +#define PLL1CFG_Val 0x00000023 +#define CCLKCFG_Val 0x00000003 +#define USBCLKCFG_Val 0x00000000 +#define PCLKSEL0_Val 0x00000000 +#define PCLKSEL1_Val 0x00000000 +#define PCONP_Val 0x042887DE +#define CLKOUTCFG_Val 0x00000000 #define FLASH_SETUP 1 -#define FLASHCFG_Val 0x0000303A +#define FLASHCFG_Val 0x0000403A + /* //-------- <<< end of configuration section >>> ------------------------------ @@ -372,15 +386,6 @@ DEFINES *----------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------- - Define clocks - *----------------------------------------------------------------------------*/ -#define XTAL (12000000UL) /* Oscillator frequency */ -#define OSC_CLK ( XTAL) /* Main oscillator frequency */ -#define RTC_CLK ( 32000UL) /* RTC oscillator frequency */ -#define IRC_OSC ( 4000000UL) /* Internal RC oscillator frequency */ - - /* F_cco0 = (2 * M * F_in) / N */ #define __M (((PLL0CFG_Val ) & 0x7FFF) + 1) #define __N (((PLL0CFG_Val >> 16) & 0x00FF) + 1) From 3f09d29a733ef76ea964326b0d805e8a17a07229 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Tue, 21 Apr 2015 12:08:05 +0200 Subject: [PATCH 08/26] Remove configurability for RTC quartz, as this is 32768 anyways. --- boards/known/lpcxpresso.lua | 2 +- boards/known/mbed.lua | 2 +- config/configurations.lua | 3 +-- src/platform/lpc17xx/system_LPC17xx.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index 3f5caca7..318a5410 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -16,7 +16,7 @@ return { config = { egc = { mode = "alloc" }, ram = { internal_rams = 2 }, - clocks = { external = 12000000, cpu = 120000000, rtc=32768 } + clocks = { external = 12000000, cpu = 120000000 } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, diff --git a/boards/known/mbed.lua b/boards/known/mbed.lua index 8acd5e64..b7ed29ef 100644 --- a/boards/known/mbed.lua +++ b/boards/known/mbed.lua @@ -16,7 +16,7 @@ return { config = { egc = { mode = "alloc" }, ram = { internal_rams = 2 }, - clocks = { external = 12000000, cpu = 100000000, rtc=32768 } + clocks = { external = 12000000, cpu = 100000000 } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, diff --git a/config/configurations.lua b/config/configurations.lua index 74369c8b..02c128ff 100644 --- a/config/configurations.lua +++ b/config/configurations.lua @@ -156,8 +156,7 @@ function init() configs.clocks = { attrs = { external = at.make_optional( at.int_attr( 'ELUA_BOARD_EXTERNAL_CLOCK_HZ', 1 ) ), - cpu = at.make_optional( at.int_attr( 'ELUA_BOARD_CPU_CLOCK_HZ', 1 ) ), - rtc = at.make_optional( at.int_attr( 'ELUA_BOARD_RTC_CLOCK_HZ', 1 ) ) + cpu = at.make_optional( at.int_attr( 'ELUA_BOARD_CPU_CLOCK_HZ', 1 ) ) } } diff --git a/src/platform/lpc17xx/system_LPC17xx.c b/src/platform/lpc17xx/system_LPC17xx.c index 452c272f..ebbb5ee9 100644 --- a/src/platform/lpc17xx/system_LPC17xx.c +++ b/src/platform/lpc17xx/system_LPC17xx.c @@ -296,7 +296,7 @@ *----------------------------------------------------------------------------*/ #define XTAL ((DWORD)(ELUA_BOARD_EXTERNAL_CLOCK_HZ)) /* Oscillator frequency */ #define OSC_CLK ((DWORD)( XTAL)) /* Main oscillator frequency */ -#define RTC_CLK ((DWORD)( ELUA_BOARD_RTC_CLOCK_HZ)) /* RTC oscillator frequency */ +#define RTC_CLK ((DWORD)( 32768UL)) /* RTC oscillator frequency */ #define IRC_OSC ((DWORD)( 4000000UL)) /* Internal RC oscillator frequency */ #define CPU_CLK ( ELUA_BOARD_CPU_CLOCK_HZ) /* Desired CPU clock */ From 02e668c35ed09d1ce7ccc2e68c4ffcbc4c7dbc83 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Tue, 21 Apr 2015 13:46:19 +0200 Subject: [PATCH 09/26] Bring Bool definition more in line with other platforms. --- src/platform/lpc17xx/type.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/platform/lpc17xx/type.h b/src/platform/lpc17xx/type.h index 46878987..f36ed3df 100644 --- a/src/platform/lpc17xx/type.h +++ b/src/platform/lpc17xx/type.h @@ -1,6 +1,19 @@ #ifndef __TYPE_H__ #define __TYPE_H__ +#ifndef NULL +#define NULL ((void *)0) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + + typedef unsigned char u8; typedef signed char s8; typedef unsigned short u16; @@ -16,10 +29,9 @@ typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef unsigned int BOOL; +typedef unsigned int Bool; typedef volatile unsigned long* PREG; -typedef enum {FALSE = 0, TRUE = !FALSE} Bool; - #endif From a7950b4d086525ae3df0826f3f2dcb88aeca0937 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Tue, 21 Apr 2015 14:47:12 +0200 Subject: [PATCH 10/26] Build MBED PIO for MBED only --- src/platform/lpc17xx/build_config.lua | 16 ++++++++++------ src/platform/lpc17xx/conf.lua | 8 +++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/platform/lpc17xx/build_config.lua b/src/platform/lpc17xx/build_config.lua index ba3a34fc..6df16f79 100644 --- a/src/platform/lpc17xx/build_config.lua +++ b/src/platform/lpc17xx/build_config.lua @@ -4,18 +4,22 @@ module( ..., package.seeall ) -- Add specific components to the 'components' table -function add_platform_components( t ) +function add_platform_components( t, board, cpu ) t.lpc17xx_semifs = { macro = "BUILD_SEMIFS" } end -- Add specific configuration to the 'configs' table -function add_platform_configs( t ) +function add_platform_configs( t, board, cpu ) + end -- Return an array of all the available platform modules for the given cpu -function get_platform_modules( cpu ) - return { - pio = { map = "mbed_pio_map", open = "luaopen_mbed_pio" } - } +function get_platform_modules( board, cpu ) + local m = { } + board = board:upper() + if board == 'MBED' then + m.pio = { map = "mbed_pio_map", open = "luaopen_mbed_pio" } + end + return m end diff --git a/src/platform/lpc17xx/conf.lua b/src/platform/lpc17xx/conf.lua index 59c10b32..3f641133 100644 --- a/src/platform/lpc17xx/conf.lua +++ b/src/platform/lpc17xx/conf.lua @@ -3,7 +3,13 @@ addi( sf( 'src/platform/%s/drivers/inc', platform ) ) local fwlib_files = utils.get_files( sf( "src/platform/%s/drivers/src", platform ), ".*%.c$" ) -specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c mbed_pio.c" +specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c" + +local board = comp.board:upper() + +if board == "MBED" then + specific_files = specific_files .. " mbed_pio.c" +end local ldscript = "LPC17xx.ld" From 3361d28ded70f88121693dad77cd279cec11928d Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Tue, 21 Apr 2015 14:59:52 +0200 Subject: [PATCH 11/26] Disable semifs for LPCXpresso --- boards/known/lpcxpresso.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index 318a5410..38f8422c 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -10,8 +10,7 @@ return { linenoise = { shell_lines = 10, lua_lines = 50 }, rpc = { uart = 0, speed = 115200 }, adc = { buf_size = 4 }, - xmodem = true, - lpc17xx_semifs = true + xmodem = true }, config = { egc = { mode = "alloc" }, From 8e2366b75a5fd70b6eaaf20da846b3c8c05aa38b Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Tue, 21 Apr 2015 16:38:16 +0200 Subject: [PATCH 12/26] Rename CPU frequency calculation function, as it is platform-specific, not board-specific. --- src/platform/lpc17xx/cpu_lpc1768.h | 4 ++-- src/platform/lpc17xx/cpu_lpc1769.h | 4 ++-- src/platform/lpc17xx/platform.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platform/lpc17xx/cpu_lpc1768.h b/src/platform/lpc17xx/cpu_lpc1768.h index 76fcec9e..9a484b08 100644 --- a/src/platform/lpc17xx/cpu_lpc1768.h +++ b/src/platform/lpc17xx/cpu_lpc1768.h @@ -17,8 +17,8 @@ #define ADC_BIT_RESOLUTION 12 // CPU frequency (needed by the CPU module, 0 if not used) -u32 mbed_get_cpu_frequency(); -#define CPU_FREQUENCY mbed_get_cpu_frequency() +u32 lpc17xx_get_cpu_frequency(); +#define CPU_FREQUENCY lpc17xx_get_cpu_frequency() // PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...) #define PIO_PREFIX '0' diff --git a/src/platform/lpc17xx/cpu_lpc1769.h b/src/platform/lpc17xx/cpu_lpc1769.h index c1c139ee..a607e1dc 100644 --- a/src/platform/lpc17xx/cpu_lpc1769.h +++ b/src/platform/lpc17xx/cpu_lpc1769.h @@ -17,8 +17,8 @@ #define ADC_BIT_RESOLUTION 12 // CPU frequency (needed by the CPU module, 0 if not used) -u32 mbed_get_cpu_frequency(); -#define CPU_FREQUENCY mbed_get_cpu_frequency() +u32 lpc17xx_get_cpu_frequency(); +#define CPU_FREQUENCY lpc17xx_get_cpu_frequency() // PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...) #define PIO_PREFIX '0' diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c index f18b79b7..2c2b0a56 100644 --- a/src/platform/lpc17xx/platform.c +++ b/src/platform/lpc17xx/platform.c @@ -74,11 +74,11 @@ int platform_init() cans_init(); // System timer setup - cmn_systimer_set_base_freq( mbed_get_cpu_frequency() ); + cmn_systimer_set_base_freq( lpc17xx_get_cpu_frequency() ); cmn_systimer_set_interrupt_freq( SYSTICKHZ ); // Enable SysTick - SysTick_Config( mbed_get_cpu_frequency() / SYSTICKHZ ); + SysTick_Config( lpc17xx_get_cpu_frequency() / SYSTICKHZ ); // Common platform initialization code cmn_platform_init(); @@ -87,7 +87,7 @@ int platform_init() } extern u32 SystemCoreClock; -u32 mbed_get_cpu_frequency() +u32 lpc17xx_get_cpu_frequency() { return SystemCoreClock; } From 06148495f10270903de5d7fb291932a01eb38beb Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 23 Apr 2015 14:22:00 +0200 Subject: [PATCH 13/26] Work in progress support for configurable pin layout --- boards/known/lpcxpresso.lua | 9 ++- src/platform/lpc17xx/build_config.lua | 11 +++- src/platform/lpc17xx/conf.lua | 2 +- src/platform/lpc17xx/lpc17xx_pio.c | 79 +++++++++++++++++++++++++++ src/platform/lpc17xx/platform.c | 25 ++------- 5 files changed, 101 insertions(+), 25 deletions(-) create mode 100644 src/platform/lpc17xx/lpc17xx_pio.c diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index 38f8422c..084fd899 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -3,7 +3,7 @@ return { cpu = 'lpc1769', components = { - sercon = { uart = 0, speed = 115200 }, + sercon = { uart = 3, speed = 115200 }, romfs = true, shell = true, term = { lines = 25, cols = 80 }, @@ -15,7 +15,12 @@ return { config = { egc = { mode = "alloc" }, ram = { internal_rams = 2 }, - clocks = { external = 12000000, cpu = 120000000 } + clocks = { external = 12000000, cpu = 120000000 }, + map_pins = { + port = {0,0}, + pin = {0,1}, + pinfunction = {1,1} + } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, diff --git a/src/platform/lpc17xx/build_config.lua b/src/platform/lpc17xx/build_config.lua index 6df16f79..a1fe77ea 100644 --- a/src/platform/lpc17xx/build_config.lua +++ b/src/platform/lpc17xx/build_config.lua @@ -2,6 +2,7 @@ -- It is used by the generic board configuration system (config/) module( ..., package.seeall ) +local at = require "attributes" -- Add specific components to the 'components' table function add_platform_components( t, board, cpu ) @@ -10,12 +11,18 @@ end -- Add specific configuration to the 'configs' table function add_platform_configs( t, board, cpu ) - + t.map_pins = { + attrs = { + port = at.array_of( at.int_attr( 'LPC17XX_MAP_PORT' )), + pin = at.array_of( at.int_attr( 'LPC17XX_MAP_PIN' )), + pinfunction = at.array_of( at.int_attr( 'LPC17XX_MAP_PINFUNCTION' )) + } + } end -- Return an array of all the available platform modules for the given cpu function get_platform_modules( board, cpu ) - local m = { } + local m = { pio = { map = "lpc17xx_pio_map", open = "luaopen_lpc17xx_pio" } } board = board:upper() if board == 'MBED' then m.pio = { map = "mbed_pio_map", open = "luaopen_mbed_pio" } diff --git a/src/platform/lpc17xx/conf.lua b/src/platform/lpc17xx/conf.lua index 3f641133..41546277 100644 --- a/src/platform/lpc17xx/conf.lua +++ b/src/platform/lpc17xx/conf.lua @@ -3,7 +3,7 @@ addi( sf( 'src/platform/%s/drivers/inc', platform ) ) local fwlib_files = utils.get_files( sf( "src/platform/%s/drivers/src", platform ), ".*%.c$" ) -specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c" +specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c lpc17xx_pio.c" local board = comp.board:upper() diff --git a/src/platform/lpc17xx/lpc17xx_pio.c b/src/platform/lpc17xx/lpc17xx_pio.c new file mode 100644 index 00000000..c7fc6ecf --- /dev/null +++ b/src/platform/lpc17xx/lpc17xx_pio.c @@ -0,0 +1,79 @@ +// LPC17xx specific PIO support +#include +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +#include "platform.h" +#include "lrotable.h" +#include "platform_conf.h" +#include "auxmods.h" +#include "lpc17xx_pinsel.h" + +static int configpin( lua_State* L ) +{ + pio_type v = ( pio_type )luaL_checkinteger( L, 1 ); + int funcnum = luaL_checkinteger( L, 2 ); + int opendrain = luaL_checkinteger( L, 3 ); + int pinmode = luaL_checkinteger( L, 4 ); + PINSEL_CFG_Type PinCfg; + int port, pin; + + port = PLATFORM_IO_GET_PORT( v ); + pin = PLATFORM_IO_GET_PIN( v ); + if( PLATFORM_IO_IS_PORT( v ) || !platform_pio_has_port( port ) || !platform_pio_has_pin( port, pin ) ) + return luaL_error( L, "invalid pin" ); + + PinCfg.Funcnum = funcnum; + PinCfg.OpenDrain = opendrain; + PinCfg.Pinmode = pinmode; + PinCfg.Portnum = port; + PinCfg.Pinnum = pin; + PINSEL_ConfigPin(&PinCfg); + + return 0; +} + +// Module function map +#define MIN_OPT_LEVEL 2 +#include "lrodefs.h" +const LUA_REG_TYPE lpc17xx_pio_map[] = +{ +#if LUA_OPTIMIZE_MEMORY > 0 + { LSTRKEY( "__metatable" ), LROVAL( lpc17xx_pio_map ) }, + { LSTRKEY( "RES_PULLUP" ), LNUMVAL( PINSEL_PINMODE_PULLUP )}, + { LSTRKEY( "RES_TRISTATE" ), LNUMVAL( PINSEL_PINMODE_TRISTATE )}, + { LSTRKEY( "RES_PULLDOWN" ), LNUMVAL( PINSEL_PINMODE_PULLDOWN )}, + { LSTRKEY( "FUNCTION_0" ), LNUMVAL( PINSEL_FUNC_0 )}, + { LSTRKEY( "FUNCTION_1" ), LNUMVAL( PINSEL_FUNC_1 )}, + { LSTRKEY( "FUNCTION_2" ), LNUMVAL( PINSEL_FUNC_2 )}, + { LSTRKEY( "FUNCTION_3" ), LNUMVAL( PINSEL_FUNC_3 )}, + { LSTRKEY( "MODE_DEFAULT" ), LNUMVAL( PINSEL_PINMODE_NORMAL )}, + { LSTRKEY( "MODE_OD" ), LNUMVAL( PINSEL_PINMODE_OPENDRAIN )}, +#endif + { LSTRKEY( "configpin" ), LFUNCVAL( configpin ) }, + { LNILKEY, LNILVAL } +}; + +LUALIB_API int luaopen_lpc17xx_pio( lua_State *L ) +{ +#if LUA_OPTIMIZE_MEMORY > 0 + return 0; +#else + luaL_register( L, PS_LIB_TABLE_NAME, lpc17xx_pio_map ); + MOD_REG_NUMBER( L, "RES_PULLUP", PINSEL_PINMODE_PULLUP ); + MOD_REG_NUMBER( L, "RES_TRISTATE", PINSEL_PINMODE_TRISTATE ); + MOD_REG_NUMBER( L, "RES_PULLDOWN", PINSEL_PINMODE_PULLDOWN ); + MOD_REG_NUMBER( L, "FUNCTION_0", PINSEL_FUNC_0 ); + MOD_REG_NUMBER( L, "FUNCTION_1", PINSEL_FUNC_1 ); + MOD_REG_NUMBER( L, "FUNCTION_2", PINSEL_FUNC_2 ); + MOD_REG_NUMBER( L, "FUNCTION_3", PINSEL_FUNC_3 ); + MOD_REG_NUMBER( L, "MODE_DEFAULT", PINSEL_PINMODE_NORMAL ); + MOD_REG_NUMBER( L, "MODE_OD", PINSEL_PINMODE_OPENDRAIN ); + + // Set it as its own metatable + lua_pushvalue( L, -1 ); + lua_setmetatable( L, -2 ); + + return 1; +#endif +} diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c index 2c2b0a56..c0d19bc9 100644 --- a/src/platform/lpc17xx/platform.c +++ b/src/platform/lpc17xx/platform.c @@ -159,9 +159,8 @@ pio_type platform_pio_op( unsigned port, pio_type pinmask, int op ) // **************************************************************************** // UART section -// UART0: Rx = P0.3, Tx = P0.2 -// The other UARTs have assignable Rx/Tx pins and thus have to be configured -// by the user +// If you want to use an UART, make sure it is routed to your desired output +// pin. See section 8.5 of the LPC17xx User Manual. static LPC_UART_TypeDef* const uart[] = { LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3 }; @@ -171,21 +170,7 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st UART_CFG_Type UARTConfigStruct; // UART FIFO configuration Struct variable UART_FIFO_CFG_Type UARTFIFOConfigStruct; - // Pin configuration for UART0 - PINSEL_CFG_Type PinCfg; - - // UART0 Pin Config - PinCfg.Funcnum = 1; - PinCfg.OpenDrain = 0; - PinCfg.Pinmode = 0; - PinCfg.Pinnum = 2; - PinCfg.Portnum = 0; - PINSEL_ConfigPin(&PinCfg); - PinCfg.Pinnum = 3; - PINSEL_ConfigPin(&PinCfg); - - UARTConfigStruct.Baud_rate = ( uint32_t )baud; - + switch( databits ) { case 5: @@ -524,7 +509,7 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency ) } static const u8 adc_ports[] = { 0, 0, 0, 0, 1, 1, 0, 0 }; -static const u8 adc_pins[] = { 23, 24, 25, 26, 30, 31, 3, 2 }; +static const u8 adc_pins[] = { 23, 24, 25, 26, 30, 31, 3, 2 }; static const u8 adc_funcs[] = { 1, 1, 1, 1, 3, 3, 2, 2 }; // Prepare Hardware Channel @@ -544,7 +529,7 @@ int platform_adc_update_sequence( ) id = d->ch_state[ seq_tmp ]->id; PinCfg.Funcnum = adc_funcs[ id ]; - PinCfg.Pinnum = adc_pins[ id ]; + PinCfg.Pinnum = adc_pins[ id ]; PinCfg.Portnum = adc_ports[ id ]; PINSEL_ConfigPin(&PinCfg); } From 7845c8b34faf9da4bdc5008956501300086b3e85 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 23 Apr 2015 14:46:22 +0200 Subject: [PATCH 14/26] Proper functionality for remapping pins from board description, generic board package for remapping from within lua. --- boards/known/lpcxpresso.lua | 8 ++++---- boards/known/mbed.lua | 7 ++++++- src/platform/lpc17xx/platform.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index 084fd899..3a290c8d 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -16,10 +16,10 @@ return { egc = { mode = "alloc" }, ram = { internal_rams = 2 }, clocks = { external = 12000000, cpu = 120000000 }, - map_pins = { - port = {0,0}, - pin = {0,1}, - pinfunction = {1,1} + map_pins = { + port = { 0, 0 }, + pin = { 0, 1 }, + pinfunction = { 2, 2 } } }, modules = { diff --git a/boards/known/mbed.lua b/boards/known/mbed.lua index b7ed29ef..0fc8fb81 100644 --- a/boards/known/mbed.lua +++ b/boards/known/mbed.lua @@ -16,7 +16,12 @@ return { config = { egc = { mode = "alloc" }, ram = { internal_rams = 2 }, - clocks = { external = 12000000, cpu = 100000000 } + clocks = { external = 12000000, cpu = 100000000 }, + map_pins = { + port = { 0, 0 }, + pin = { 2, 2 }, + pinfunction = { 1, 1 } + } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c index c0d19bc9..9583f33e 100644 --- a/src/platform/lpc17xx/platform.c +++ b/src/platform/lpc17xx/platform.c @@ -38,12 +38,13 @@ static void platform_setup_timers(); static void platform_setup_pwm(); static void platform_setup_adcs(); static void cans_init( void ); +static void platform_setup_pins(); int platform_init() { // Set up microcontroller system and SystemCoreClock variable SystemInit(); - + // DeInit NVIC and SCBNVIC NVIC_DeInit(); NVIC_SCBDeInit(); @@ -73,6 +74,9 @@ int platform_init() // Setup CANs cans_init(); + // Setup pin routing + platform_setup_pins(); + // System timer setup cmn_systimer_set_base_freq( lpc17xx_get_cpu_frequency() ); cmn_systimer_set_interrupt_freq( SYSTICKHZ ); @@ -84,7 +88,7 @@ int platform_init() cmn_platform_init(); return PLATFORM_OK; -} +} extern u32 SystemCoreClock; u32 lpc17xx_get_cpu_frequency() @@ -104,7 +108,28 @@ void SysTick_Handler() // **************************************************************************** // PIO section - + +static const u8 map_ports[] = LPC17XX_MAP_PORT; +static const u8 map_pins [] = LPC17XX_MAP_PIN; +static const u8 map_funcs[] = LPC17XX_MAP_PINFUNCTION; + +static void platform_setup_pins(void) +{ + PINSEL_CFG_Type PinCfg; + u8 i; + + PinCfg.OpenDrain = PINSEL_PINMODE_NORMAL; + PinCfg.Pinmode = PINSEL_PINMODE_PULLUP; + + for(i=0; i Date: Thu, 23 Apr 2015 14:51:29 +0200 Subject: [PATCH 15/26] Only include either generic lpc17xx PIO module or MBED specific, not both --- src/platform/lpc17xx/conf.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform/lpc17xx/conf.lua b/src/platform/lpc17xx/conf.lua index 41546277..f91dec2e 100644 --- a/src/platform/lpc17xx/conf.lua +++ b/src/platform/lpc17xx/conf.lua @@ -3,16 +3,18 @@ addi( sf( 'src/platform/%s/drivers/inc', platform ) ) local fwlib_files = utils.get_files( sf( "src/platform/%s/drivers/src", platform ), ".*%.c$" ) -specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c lpc17xx_pio.c" +specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c" local board = comp.board:upper() if board == "MBED" then specific_files = specific_files .. " mbed_pio.c" +else + specific_files = specific_files .. " lpc17xx_pio.c" end local ldscript = "LPC17xx.ld" - + -- Prepend with path specific_files = fwlib_files .. " " .. utils.prepend_path( specific_files, sf( "src/platform/%s", platform ) ) specific_files = specific_files .. " src/platform/cortex_utils.s src/platform/arm_cortex_interrupts.c" From e47ec9438afbca4130de8cd25b0074aec630b0d6 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 23 Apr 2015 14:52:39 +0200 Subject: [PATCH 16/26] Delete trailing whitespace --- src/platform/lpc17xx/platform.c | 159 ++++++++++++++++---------------- 1 file changed, 79 insertions(+), 80 deletions(-) diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c index 9583f33e..71499bb3 100644 --- a/src/platform/lpc17xx/platform.c +++ b/src/platform/lpc17xx/platform.c @@ -134,45 +134,45 @@ static void platform_setup_pins(void) pio_type platform_pio_op( unsigned port, pio_type pinmask, int op ) { pio_type retval = 1; - + switch( op ) { - case PLATFORM_IO_PORT_SET_VALUE: + case PLATFORM_IO_PORT_SET_VALUE: GPIO_SetValue(port, pinmask); break; - + case PLATFORM_IO_PIN_SET: GPIO_SetValue(port, pinmask); break; - + case PLATFORM_IO_PIN_CLEAR: GPIO_ClearValue(port, pinmask); break; - + case PLATFORM_IO_PORT_DIR_OUTPUT: GPIO_SetDir(port, 0xFFFFFFFF, 1); - break; + break; case PLATFORM_IO_PIN_DIR_OUTPUT: GPIO_SetDir(port, pinmask, 1); break; - + case PLATFORM_IO_PORT_DIR_INPUT: GPIO_SetDir(port, 0xFFFFFFFF, 0); break; case PLATFORM_IO_PIN_DIR_INPUT: GPIO_SetDir(port, pinmask, 0); - break; - + break; + case PLATFORM_IO_PORT_GET_VALUE: retval = GPIO_ReadValue(port); break; - + case PLATFORM_IO_PIN_GET: retval = ( GPIO_ReadValue(port) & pinmask ) ? 1 : 0; break; - + default: retval = 0; break; @@ -197,13 +197,13 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st UART_FIFO_CFG_Type UARTFIFOConfigStruct; UARTConfigStruct.Baud_rate = ( uint32_t )baud; - + switch( databits ) { case 5: UARTConfigStruct.Databits = UART_DATABIT_5; break; - + case 6: UARTConfigStruct.Databits = UART_DATABIT_6; break; @@ -216,33 +216,33 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st UARTConfigStruct.Databits = UART_DATABIT_8; break; } - + if( stopbits == PLATFORM_UART_STOPBITS_2 ) UARTConfigStruct.Stopbits = UART_STOPBIT_2; else UARTConfigStruct.Stopbits = UART_STOPBIT_1; - + switch( parity ) { case PLATFORM_UART_PARITY_NONE: UARTConfigStruct.Parity = UART_PARITY_NONE; break; - + case PLATFORM_UART_PARITY_ODD: UARTConfigStruct.Parity = UART_PARITY_ODD; break; - + case PLATFORM_UART_PARITY_EVEN: UARTConfigStruct.Parity = UART_PARITY_EVEN; break; - + case PLATFORM_UART_PARITY_MARK: UARTConfigStruct.Parity = UART_PARITY_SP_1; break; - + case PLATFORM_UART_PARITY_SPACE: UARTConfigStruct.Parity = UART_PARITY_SP_0; - break; + break; } UART_Init(uart[ id ], &UARTConfigStruct); @@ -250,10 +250,10 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st // Get default FIFO config and initialize UART_FIFOConfigStructInit(&UARTFIFOConfigStruct); UART_FIFOConfig(uart[ id ], &UARTFIFOConfigStruct); - + // Enable Transmit UART_TxCmd(uart[ id ], ENABLE); - + return baud; // FIXME: find a way to actually get baud } @@ -265,7 +265,7 @@ void platform_s_uart_send( unsigned id, u8 data ) int platform_s_uart_recv( unsigned id, timer_data_type timeout ) { u8 buffer; - + if( timeout == 0 ) { if ( UART_Receive(uart[ id ], &buffer, 1, NONE_BLOCKING) == 0 ) @@ -273,7 +273,7 @@ int platform_s_uart_recv( unsigned id, timer_data_type timeout ) else return ( int )buffer; } - + UART_Receive(uart[ id ], &buffer, 1, BLOCKING); return ( int )buffer; } @@ -309,7 +309,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock ) TIM_Init( tmr[ id ], TIM_TIMER_MODE, &TIM_ConfigStruct ); TIM_Cmd( tmr[ id ], ENABLE ); TIM_ResetCounter( tmr[ id ] ); - + return clock; } @@ -317,11 +317,11 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock ) static void platform_setup_timers() { unsigned i; - + // Power on clocks on APB1 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM2, ENABLE); CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCTIM3, ENABLE); - + // Set base frequency to 1MHz, as we can't use a better resolution anyway for( i = 0; i < 4; i ++ ) platform_timer_set_clock( i, 1000000ULL ); @@ -336,7 +336,7 @@ void platform_s_timer_delay( unsigned id, timer_data_type delay_us ) TIM_ResetCounter( tmr[ id ] ); while( tmr[ id ]->TC < last ); } - + timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data ) { u32 res = 0; @@ -347,7 +347,7 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data ) TIM_Cmd( tmr[ id ], ENABLE ); TIM_ResetCounter( tmr[ id ] ); break; - + case PLATFORM_TIMER_OP_READ: res = tmr[ id ]->TC; break; @@ -355,7 +355,7 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data ) case PLATFORM_TIMER_OP_SET_CLOCK: res = platform_timer_set_clock( id, data ); break; - + case PLATFORM_TIMER_OP_GET_CLOCK: res = platform_timer_get_clock( id ); break; @@ -402,13 +402,13 @@ int platform_adc_check_timer_id( unsigned id, unsigned timer_id ) } void platform_adc_stop( unsigned id ) -{ +{ elua_adc_ch_state *s = adc_get_ch_state( id ); elua_adc_dev_state *d = adc_get_dev_state( 0 ); - + s->op_pending = 0; INACTIVATE_CHANNEL( d, id ); - + // If there are no more active channels, stop the sequencer if( d->ch_active == 0 && d->running == 1 ) { @@ -424,17 +424,17 @@ void ADC_IRQHandler(void) elua_adc_dev_state *d = adc_get_dev_state( 0 ); elua_adc_ch_state *s = d->ch_state[ d->seq_ctr ]; //int i; - + // Disable sampling & current sequence channel ADC_StartCmd( LPC_ADC, 0 ); ADC_ChannelCmd( LPC_ADC, s->id, DISABLE ); ADC_IntConfig( LPC_ADC, s->id, DISABLE ); if ( ADC_ChannelGetStatus( LPC_ADC, s->id, ADC_DATA_DONE ) ) - { + { d->sample_buf[ d->seq_ctr ] = ( u16 )ADC_ChannelGetData( LPC_ADC, s->id ); s->value_fresh = 1; - + if ( s->logsmoothlen > 0 && s->smooth_ready == 0) adc_smooth_data( s->id ); #if defined( BUF_ENABLE_ADC ) @@ -444,11 +444,11 @@ void ADC_IRQHandler(void) s->value_fresh = 0; } #endif - + if ( adc_samples_available( s->id ) >= s->reqsamples && s->freerunning == 0 ) - platform_adc_stop( s->id ); + platform_adc_stop( s->id ); } - + // Set up for next channel acquisition if we're still running if( d->running == 1 ) { @@ -456,14 +456,14 @@ void ADC_IRQHandler(void) if( d->seq_ctr < ( d->seq_len - 1 ) ) d->seq_ctr++; else if( d->seq_ctr == ( d->seq_len - 1 ) ) - { + { adc_update_dev_sequence( 0 ); d->seq_ctr = 0; // reset sequence counter if on last sequence entry } - + ADC_ChannelCmd( LPC_ADC, d->ch_state[ d->seq_ctr ]->id, ENABLE ); ADC_IntConfig( LPC_ADC, d->ch_state[ d->seq_ctr ]->id, ENABLE ); - + if( d->clocked == 1 && d->seq_ctr == 0 ) // always use clock for first in clocked sequence ADC_StartCmd( LPC_ADC, adc_trig[ d->timer_id ] ); @@ -477,20 +477,20 @@ void ADC_IRQHandler(void) static void platform_setup_adcs() { unsigned id; - + for( id = 0; id < NUM_ADC; id ++ ) adc_init_ch_state( id ); - + NVIC_SetPriority(ADC_IRQn, ((0x01<<3)|0x01)); ADC_Init(LPC_ADC, 13000000); - + // Default enables CH0, disable channel ADC_ChannelCmd( LPC_ADC, 0, DISABLE ); - + // Default enables ADC interrupt only on global, switch to per-channel ADC_IntConfig( LPC_ADC, ADC_ADGINTEN, DISABLE ); - + platform_adc_set_clock( 0, 0 ); } @@ -505,15 +505,15 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency ) if ( frequency > 0 ) { d->clocked = 1; - + // Max Sampling Rate on LPC1768 is 200 kS/s if ( frequency > 200000 ) frequency = 200000; - + // Run timer at 1MHz TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL; TIM_ConfigStruct.PrescaleValue = 1; - + TIM_MatchConfigStruct.MatchChannel = 1; TIM_MatchConfigStruct.IntOnMatch = FALSE; TIM_MatchConfigStruct.ResetOnMatch = TRUE; @@ -521,9 +521,9 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency ) TIM_MatchConfigStruct.ExtMatchOutputType = TIM_EXTMATCH_TOGGLE; // Set match value to period (in uS) associated with frequency TIM_MatchConfigStruct.MatchValue = ( 1000000ULL / ( frequency * 2 ) ) - 1; - + frequency = 1000000ULL / (TIM_MatchConfigStruct.MatchValue + 1); - + // Set configuration for Tim_config and Tim_MatchConfig TIM_Init( tmr[ d->timer_id ], TIM_TIMER_MODE, &TIM_ConfigStruct ); TIM_ConfigMatch( tmr[ d->timer_id ], &TIM_MatchConfigStruct ); @@ -531,7 +531,7 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency ) } else d->clocked = 0; - + return frequency; } @@ -541,38 +541,38 @@ static const u8 adc_funcs[] = { 1, 1, 1, 1, 3, 3, 2, 2 }; // Prepare Hardware Channel int platform_adc_update_sequence( ) -{ - elua_adc_dev_state *d = adc_get_dev_state( 0 ); +{ + elua_adc_dev_state *d = adc_get_dev_state( 0 ); PINSEL_CFG_Type PinCfg; u8 seq_tmp; unsigned id; - + // Enable Needed Pins PinCfg.OpenDrain = 0; PinCfg.Pinmode = 0; - + for( seq_tmp = 0; seq_tmp < d->seq_len; seq_tmp++ ) { id = d->ch_state[ seq_tmp ]->id; - + PinCfg.Funcnum = adc_funcs[ id ]; PinCfg.Pinnum = adc_pins[ id ]; PinCfg.Portnum = adc_ports[ id ]; PINSEL_ConfigPin(&PinCfg); } - + return PLATFORM_OK; } int platform_adc_start_sequence() -{ +{ elua_adc_dev_state *d = adc_get_dev_state( 0 ); - + if( d->running != 1 ) { adc_update_dev_sequence( 0 ); - + // Start sampling on first channel d->seq_ctr = 0; ADC_ChannelCmd( LPC_ADC, d->ch_state[ d->seq_ctr ]->id, ENABLE ); @@ -580,7 +580,7 @@ int platform_adc_start_sequence() d->running = 1; NVIC_EnableIRQ( ADC_IRQn ); - + if( d->clocked == 1 ) { ADC_StartCmd( LPC_ADC, adc_trig[ d->timer_id ] ); @@ -590,7 +590,7 @@ int platform_adc_start_sequence() else ADC_StartCmd( LPC_ADC, ADC_START_NOW ); } - + return PLATFORM_OK; } @@ -611,7 +611,7 @@ u32 platform_pwm_get_clock( unsigned id ) u32 platform_pwm_set_clock( unsigned id, u32 clock ) { PWM_TIMERCFG_Type PWMCfgDat; - + PWMCfgDat.PrescaleOption = PWM_TIMER_PRESCALE_USVAL; PWMCfgDat.PrescaleValue = 1000000ULL / clock; PWM_Init( LPC_PWM1, PWM_MODE_TIMER, &PWMCfgDat ); @@ -623,10 +623,10 @@ u32 platform_pwm_set_clock( unsigned id, u32 clock ) static void platform_setup_pwm() { PWM_MATCHCFG_Type PWMMatchCfgDat; - + // Keep clock in reset, set PWM code PWM_ResetCounter( LPC_PWM1 ); - + // Set match mode (reset on MR0 match) PWMMatchCfgDat.IntOnMatch = DISABLE; PWMMatchCfgDat.MatchChannel = 0; @@ -642,13 +642,13 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty ) { PWM_MATCHCFG_Type PWMMatchCfgDat; u32 divisor = platform_pwm_get_clock( id ) / frequency - 1; - + PWM_MatchUpdate( LPC_PWM1, 0, divisor, PWM_MATCH_UPDATE_NOW ); // PWM1 cycle rate PWM_MatchUpdate( LPC_PWM1, id, ( divisor * duty ) / 100, PWM_MATCH_UPDATE_NOW ); // PWM1 channel edge position - + if ( id > 1 ) // Channel one is permanently single-edge PWM_ChannelConfig( LPC_PWM1, id, PWM_CHANNEL_SINGLE_EDGE ); - + PWMMatchCfgDat.IntOnMatch = DISABLE; PWMMatchCfgDat.MatchChannel = id; PWMMatchCfgDat.ResetOnMatch = DISABLE; @@ -685,7 +685,7 @@ void CAN_IRQHandler(void) // CAN1 Error (bits 1~10 cleared when read) if (LPC_CAN1->ICR & (1<<2 | 1<<5 | 1<<7)) can_err_flag[0] = 1; - + // CAN1 Receive if (LPC_CAN1->ICR & (1<<0)) { @@ -713,7 +713,7 @@ void cans_init( void ) u32 platform_can_setup( unsigned id, u32 clock ) -{ +{ LPC_CAN_TypeDef * canx; uint32_t div; @@ -724,13 +724,13 @@ u32 platform_can_setup( unsigned id, u32 clock ) default: return 0; } - CAN_DeInit(canx); + CAN_DeInit(canx); CAN_Init(canx, clock); - CAN_ModeConfig(canx, CAN_OPERATING_MODE, ENABLE); - CAN_IRQCmd(canx, CANINT_RIE, ENABLE); // Receive IRQ - CAN_IRQCmd(canx, CANINT_EIE, ENABLE); // Error IRQ - CAN_IRQCmd(canx, CANINT_BEIE, ENABLE); // Bus error IRQ - LPC_CANAF->AFMR = 2; // Filter bypass (receive all messages) + CAN_ModeConfig(canx, CAN_OPERATING_MODE, ENABLE); + CAN_IRQCmd(canx, CANINT_RIE, ENABLE); // Receive IRQ + CAN_IRQCmd(canx, CANINT_EIE, ENABLE); // Error IRQ + CAN_IRQCmd(canx, CANINT_BEIE, ENABLE); // Bus error IRQ + LPC_CANAF->AFMR = 2; // Filter bypass (receive all messages) NVIC_EnableIRQ(CAN_IRQn); // Enable IRQs // Fix clock @@ -812,7 +812,7 @@ int platform_can_recv( unsigned id, u32 *canid, u8 *idtype, u8 *len, u8 *data ) if( can_rx_flag[id] != 0 ) { memcpy(data, &(can_msg_rx[id].dataA), 4); - memcpy(data+4, &(can_msg_rx[id].dataB), 4); + memcpy(data+4, &(can_msg_rx[id].dataB), 4); can_rx_flag[id] = 0; @@ -825,4 +825,3 @@ int platform_can_recv( unsigned id, u32 *canid, u8 *idtype, u8 *len, u8 *data ) else return PLATFORM_UNDERFLOW; } - From b2c5cab75868ee516ba1402d58143c0ea77d5ca1 Mon Sep 17 00:00:00 2001 From: James Snyder Date: Thu, 23 Apr 2015 19:42:49 -0500 Subject: [PATCH 17/26] correct pin configuration for mbed uart --- boards/known/mbed.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/known/mbed.lua b/boards/known/mbed.lua index 0fc8fb81..aa9861d5 100644 --- a/boards/known/mbed.lua +++ b/boards/known/mbed.lua @@ -19,7 +19,7 @@ return { clocks = { external = 12000000, cpu = 100000000 }, map_pins = { port = { 0, 0 }, - pin = { 2, 2 }, + pin = { 2, 3 }, pinfunction = { 1, 1 } } }, From cc425be82158fdbecae4b27e23f1f79547f26da6 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Tue, 21 Apr 2015 17:45:21 +0200 Subject: [PATCH 18/26] Import of LPCUSB library. --- .../lpc17xx/usbstack/inc/lpcusb_type.h | 68 ++ src/platform/lpc17xx/usbstack/inc/type.h | 38 ++ src/platform/lpc17xx/usbstack/inc/usbapi.h | 121 ++++ src/platform/lpc17xx/usbstack/inc/usbdebug.h | 44 ++ src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h | 148 +++++ src/platform/lpc17xx/usbstack/inc/usbstruct.h | 121 ++++ src/platform/lpc17xx/usbstack/readme.txt | 47 ++ .../lpc17xx/usbstack/src/usbcontrol.c | 234 +++++++ src/platform/lpc17xx/usbstack/src/usbhw_lpc.c | 627 ++++++++++++++++++ src/platform/lpc17xx/usbstack/src/usbinit.c | 85 +++ src/platform/lpc17xx/usbstack/src/usbstdreq.c | 434 ++++++++++++ 11 files changed, 1967 insertions(+) create mode 100644 src/platform/lpc17xx/usbstack/inc/lpcusb_type.h create mode 100644 src/platform/lpc17xx/usbstack/inc/type.h create mode 100644 src/platform/lpc17xx/usbstack/inc/usbapi.h create mode 100644 src/platform/lpc17xx/usbstack/inc/usbdebug.h create mode 100644 src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h create mode 100644 src/platform/lpc17xx/usbstack/inc/usbstruct.h create mode 100644 src/platform/lpc17xx/usbstack/readme.txt create mode 100644 src/platform/lpc17xx/usbstack/src/usbcontrol.c create mode 100644 src/platform/lpc17xx/usbstack/src/usbhw_lpc.c create mode 100644 src/platform/lpc17xx/usbstack/src/usbinit.c create mode 100644 src/platform/lpc17xx/usbstack/src/usbstdreq.c diff --git a/src/platform/lpc17xx/usbstack/inc/lpcusb_type.h b/src/platform/lpc17xx/usbstack/inc/lpcusb_type.h new file mode 100644 index 00000000..1c765432 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/lpcusb_type.h @@ -0,0 +1,68 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/** + @file + primitive types used in the USB stack + */ + +// *********************************************** +// Code Red Technologies - port to RDB1768 board +// In order to avoid clashing with the NXP-produced type.h file, this +// one has been renamed to lpcusb_type.h, the NXP-produced type.h has +// been included, and the duplicate contents of this file commented out. +// *********************************************** + + +#ifndef _LPCUSB_TYPE_H_ +#define _LPCUSB_TYPE_H_ + +// CodeRed - include NXP-produced type.h file +#include "type.h" + +typedef unsigned char U8; /**< unsigned 8-bit */ +typedef unsigned short int U16; /**< unsigned 16-bit */ +typedef unsigned int U32; /**< unsigned 32-bit */ + + +// CodeRed - comment out defines duplicated in NXP type.h + +//typedef int BOOL; /**< #TRUE or #FALSE */ + +//#define TRUE 1 /**< TRUE */ +//#define FALSE 0 /**< FALSE */ + +//#ifndef NULL +//#define NULL ((void*)0) /**< NULL pointer */ +//#endif +//#endif + +/* some other useful macros */ +#define MIN(x,y) ((x)<(y)?(x):(y)) /**< MIN */ +#define MAX(x,y) ((x)>(y)?(x):(y)) /**< MAX */ + +#endif /* _LPCUSB_TYPE_H_ */ + diff --git a/src/platform/lpc17xx/usbstack/inc/type.h b/src/platform/lpc17xx/usbstack/inc/type.h new file mode 100644 index 00000000..89d36850 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/type.h @@ -0,0 +1,38 @@ +/***************************************************************************** + * type.h: Type definition Header file for NXP LPC17xx Family + * Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.08.21 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef unsigned int BOOL; + +typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; + +/* Pointer to Function returning Void (any number of parameters) */ +typedef void (*PFV)(); + +#endif /* __TYPE_H__ */ diff --git a/src/platform/lpc17xx/usbstack/inc/usbapi.h b/src/platform/lpc17xx/usbstack/inc/usbapi.h new file mode 100644 index 00000000..5c9f6a24 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbapi.h @@ -0,0 +1,121 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file +*/ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +#include "lpcusb_type.h" + +#include "usbstruct.h" // for TSetupPacket + +/************************************************************************* + USB configuration +**************************************************************************/ + +#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */ + +/************************************************************************* + USB hardware interface +**************************************************************************/ + +// endpoint status sent through callback +#define EP_STATUS_DATA (1<<0) /**< EP has data */ +#define EP_STATUS_STALLED (1<<1) /**< EP is stalled */ +#define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */ +#define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */ +#define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */ + +// device status sent through callback +#define DEV_STATUS_CONNECT (1<<0) /**< device just got connected */ +#define DEV_STATUS_SUSPEND (1<<2) /**< device entered suspend state */ +#define DEV_STATUS_RESET (1<<4) /**< device just got reset */ + +// interrupt bits for NACK events in USBHwNakIntEnable +// (these bits conveniently coincide with the LPC176x USB controller bit) +#define INACK_CI (1<<1) /**< interrupt on NACK for control in */ +#define INACK_CO (1<<2) /**< interrupt on NACK for control out */ +#define INACK_II (1<<3) /**< interrupt on NACK for interrupt in */ +#define INACK_IO (1<<4) /**< interrupt on NACK for interrupt out */ +#define INACK_BI (1<<5) /**< interrupt on NACK for bulk in */ +#define INACK_BO (1<<6) /**< interrupt on NACK for bulk out */ + +BOOL USBHwInit (void); +void USBHwISR (void); + +void USBHwNakIntEnable (U8 bIntBits); + +void USBHwConnect (BOOL fConnect); + +void USBHwSetAddress (U8 bAddr); +void USBHwConfigDevice (BOOL fConfigured); + +// endpoint operations +void USBHwEPConfig (U8 bEP, U16 wMaxPacketSize); +int USBHwEPRead (U8 bEP, U8 *pbBuf, int iMaxLen); +int USBHwEPWrite (U8 bEP, U8 *pbBuf, int iLen); +void USBHwEPStall (U8 bEP, BOOL fStall); +U8 USBHwEPGetStatus (U8 bEP); + +/** Endpoint interrupt handler callback */ +typedef void (TFnEPIntHandler) (U8 bEP, U8 bEPStatus); +void USBHwRegisterEPIntHandler (U8 bEP, TFnEPIntHandler *pfnHandler); + +/** Device status handler callback */ +typedef void (TFnDevIntHandler) (U8 bDevStatus); +void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler); + +/** Frame event handler callback */ +typedef void (TFnFrameHandler)(U16 wFrame); +void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler); + + +/************************************************************************* + USB application interface +**************************************************************************/ + +// initialise the complete stack, including HW +BOOL USBInit(void); + +/** Request handler callback (standard, vendor, class) */ +typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, U8 **ppbData); +void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, U8 *pbDataStore); +void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler); + +/** Descriptor handler callback */ +typedef BOOL (TFnGetDescriptor)(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData); + +/** Default standard request handler */ +BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData); + +/** Default EP0 handler */ +void USBHandleControlTransfer(U8 bEP, U8 bEPStat); + +/** Descriptor handling */ +void USBRegisterDescriptors(const U8 *pabDescriptors); +BOOL USBGetDescriptor(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData); diff --git a/src/platform/lpc17xx/usbstack/inc/usbdebug.h b/src/platform/lpc17xx/usbstack/inc/usbdebug.h new file mode 100644 index 00000000..bb3fb152 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbdebug.h @@ -0,0 +1,44 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// CodeRed - comment out this printf, as will use real one from stdio.h +// to implement output via semihosting + +//int printf(const char *format, ...); +# include + +// CodeRed - added DEBUG_MESSAGES, so still get output for Release builds +//#define DEBUG_MESSAGES 1 +//#ifdef DEBUG +#ifdef DEBUG_MESSAGES +#define DBG printf +#define ASSERT(x) if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);} +#else +#define DBG(x ...) +#define ASSERT(x) +#endif + diff --git a/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h b/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h new file mode 100644 index 00000000..b2071d14 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h @@ -0,0 +1,148 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** + Hardware definitions for the LPC176x USB controller + + These are private to the usbhw module +*/ + +// CodeRed - pull in defines from NXP header file +#include "LPC17xx.h" + + +// CodeRed - these registers have been renamed on LPC176x +#define USBReEP USBReEp +#define OTG_CLK_CTRL USBClkCtrl +#define OTG_CLK_STAT USBClkSt + +/* USBIntSt bits */ +#define USB_INT_REQ_LP (1<<0) +#define USB_INT_REQ_HP (1<<1) +#define USB_INT_REQ_DMA (1<<2) +#define USB_need_clock (1<<8) +#define EN_USB_BITS (1<<31) + +/* USBDevInt... bits */ +#define FRAME (1<<0) +#define EP_FAST (1<<1) +#define EP_SLOW (1<<2) +#define DEV_STAT (1<<3) +#define CCEMTY (1<<4) +#define CDFULL (1<<5) +#define RxENDPKT (1<<6) +#define TxENDPKT (1<<7) +#define EP_RLZED (1<<8) +#define ERR_INT (1<<9) + +/* USBRxPLen bits */ +#define PKT_LNGTH (1<<0) +#define PKT_LNGTH_MASK 0x3FF +#define DV (1<<10) +#define PKT_RDY (1<<11) + +/* USBCtrl bits */ +#define RD_EN (1<<0) +#define WR_EN (1<<1) +#define LOG_ENDPOINT (1<<2) + +/* protocol engine command codes */ + /* device commands */ +#define CMD_DEV_SET_ADDRESS 0xD0 +#define CMD_DEV_CONFIG 0xD8 +#define CMD_DEV_SET_MODE 0xF3 +#define CMD_DEV_READ_CUR_FRAME_NR 0xF5 +#define CMD_DEV_READ_TEST_REG 0xFD +#define CMD_DEV_STATUS 0xFE /* read/write */ +#define CMD_DEV_GET_ERROR_CODE 0xFF +#define CMD_DEV_READ_ERROR_STATUS 0xFB + /* endpoint commands */ +#define CMD_EP_SELECT 0x00 +#define CMD_EP_SELECT_CLEAR 0x40 +#define CMD_EP_SET_STATUS 0x40 +#define CMD_EP_CLEAR_BUFFER 0xF2 +#define CMD_EP_VALIDATE_BUFFER 0xFA + +/* set address command */ +#define DEV_ADDR (1<<0) +#define DEV_EN (1<<7) + +/* configure device command */ +#define CONF_DEVICE (1<<0) + +/* set mode command */ +#define AP_CLK (1<<0) +#define INAK_CI (1<<1) +#define INAK_CO (1<<2) +#define INAK_II (1<<3) +#define INAK_IO (1<<4) +#define INAK_BI (1<<5) +#define INAK_BO (1<<6) + +/* set get device status command */ +#define CON (1<<0) +#define CON_CH (1<<1) +#define SUS (1<<2) +#define SUS_CH (1<<3) +#define RST (1<<4) + +/* get error code command */ +// ... + +/* Select Endpoint command read bits */ +#define EPSTAT_FE (1<<0) +#define EPSTAT_ST (1<<1) +#define EPSTAT_STP (1<<2) +#define EPSTAT_PO (1<<3) +#define EPSTAT_EPN (1<<4) +#define EPSTAT_B1FULL (1<<5) +#define EPSTAT_B2FULL (1<<6) + +/* CMD_EP_SET_STATUS command */ +#define EP_ST (1<<0) +#define EP_DA (1<<5) +#define EP_RF_MO (1<<6) +#define EP_CND_ST (1<<7) + +/* read error status command */ +#define PID_ERR (1<<0) +#define UEPKT (1<<1) +#define DCRC (1<<2) +#define TIMEOUT (1<<3) +#define EOP (1<<4) +#define B_OVRN (1<<5) +#define BTSTF (1<<6) +#define TGL_ERR (1<<7) + + + + + + + + diff --git a/src/platform/lpc17xx/usbstack/inc/usbstruct.h b/src/platform/lpc17xx/usbstack/inc/usbstruct.h new file mode 100644 index 00000000..b30e5247 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbstruct.h @@ -0,0 +1,121 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** + Definitions of structures of standard USB packets +*/ + +#ifndef _USBSTRUCT_H_ +#define _USBSTRUCT_H_ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +//#include "type.h" +#include "lpcusb_type.h" + + +/** setup packet definitions */ +typedef struct { + U8 bmRequestType; /**< characteristics of the specific request */ + U8 bRequest; /**< specific request */ + U16 wValue; /**< request specific parameter */ + U16 wIndex; /**< request specific parameter */ + U16 wLength; /**< length of data transfered in data phase */ +} TSetupPacket; + + +#define REQTYPE_GET_DIR(x) (((x)>>7)&0x01) +#define REQTYPE_GET_TYPE(x) (((x)>>5)&0x03) +#define REQTYPE_GET_RECIP(x) ((x)&0x1F) + +#define REQTYPE_DIR_TO_DEVICE 0 +#define REQTYPE_DIR_TO_HOST 1 + +#define REQTYPE_TYPE_STANDARD 0 +#define REQTYPE_TYPE_CLASS 1 +#define REQTYPE_TYPE_VENDOR 2 +#define REQTYPE_TYPE_RESERVED 3 + +#define REQTYPE_RECIP_DEVICE 0 +#define REQTYPE_RECIP_INTERFACE 1 +#define REQTYPE_RECIP_ENDPOINT 2 +#define REQTYPE_RECIP_OTHER 3 + +/* standard requests */ +#define REQ_GET_STATUS 0x00 +#define REQ_CLEAR_FEATURE 0x01 +#define REQ_SET_FEATURE 0x03 +#define REQ_SET_ADDRESS 0x05 +#define REQ_GET_DESCRIPTOR 0x06 +#define REQ_SET_DESCRIPTOR 0x07 +#define REQ_GET_CONFIGURATION 0x08 +#define REQ_SET_CONFIGURATION 0x09 +#define REQ_GET_INTERFACE 0x0A +#define REQ_SET_INTERFACE 0x0B +#define REQ_SYNCH_FRAME 0x0C + +/* class requests HID */ +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B + +/* feature selectors */ +#define FEA_ENDPOINT_HALT 0x00 +#define FEA_REMOTE_WAKEUP 0x01 +#define FEA_TEST_MODE 0x02 + +/* + USB descriptors +*/ + +/** USB descriptor header */ +typedef struct { + U8 bLength; /**< descriptor length */ + U8 bDescriptorType; /**< descriptor type */ +} TUSBDescHeader; + +#define DESC_DEVICE 1 +#define DESC_CONFIGURATION 2 +#define DESC_STRING 3 +#define DESC_INTERFACE 4 +#define DESC_ENDPOINT 5 +#define DESC_DEVICE_QUALIFIER 6 +#define DESC_OTHER_SPEED 7 +#define DESC_INTERFACE_POWER 8 + +#define DESC_HID_HID 0x21 +#define DESC_HID_REPORT 0x22 +#define DESC_HID_PHYSICAL 0x23 + +#define GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define GET_DESC_INDEX(x) ((x)&0xFF) + +#endif /* _USBSTRUCT_H_ */ + diff --git a/src/platform/lpc17xx/usbstack/readme.txt b/src/platform/lpc17xx/usbstack/readme.txt new file mode 100644 index 00000000..d46d38c3 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/readme.txt @@ -0,0 +1,47 @@ +USB stack for LPC17xx. Based on the library distributed by Code Red +Technologies, which in turn is based on the LPCUSB project for the +LPC2148, originally written by Bertrik Sikken. + +I'm taking the liberty to just edit the code without annotating +edits, even removing Code Red annotations, as git will preserve +all this history for us. + +Original README follows. + + + +Code Red Technologies RDB1768 Board - USB Stack Example +======================================================= + +The USB stack and associated examples provided with RDB1768 board are +based on the open source LPCUSB stack, originally written for the NXP +LPC214x microcontrollers. The original sources for the USB stack and +and examples can be found at: + + http://sourceforge.net/projects/lpcusb/ + +with additional information at: + + http://wiki.sikken.nl/index.php?title=LPCUSB + +We have tried to keep the changes to the codebase down to a minimum, and +have commented where changes have been made as much as possible + +Support +------- +This example project is based on the open source LPCUSB stack. +Code Red can provide support on using this project as supplied to +users with a valid support contract with us. But if you require +assistance on the general use of the stack or on extending the +example, then we would recommend that you raise your questions +to an appropriate community forum, such as.... + +http://tech.groups.yahoo.com/group/lpc2000/messages + +USBstack +-------- +This is the main project which builds the LPCUSB stack as a library. +This is then used in building the various RDB1768 USB examples projects. + + + diff --git a/src/platform/lpc17xx/usbstack/src/usbcontrol.c b/src/platform/lpc17xx/usbstack/src/usbcontrol.c new file mode 100644 index 00000000..baf90fe6 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbcontrol.c @@ -0,0 +1,234 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + Control transfer handler. + + This module handles control transfers and is normally installed on the + endpoint 0 callback. + + Control transfers can be of the following type: + 0 Standard; + 1 Class; + 2 Vendor; + 3 Reserved. + + A callback can be installed for each of these control transfers using + USBRegisterRequestHandler. + When an OUT request arrives, data is collected in the data store provided + with the USBRegisterRequestHandler call. When the transfer is done, the + callback is called. + When an IN request arrives, the callback is called immediately to either + put the control transfer data in the data store, or to get a pointer to + control transfer data. The data is then packetised and sent to the host. +*/ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +//#include "type.h" +#include "lpcusb_type.h" + +#include "usbdebug.h" + +#include "usbstruct.h" +#include "usbapi.h" + + + +#define MAX_CONTROL_SIZE 128 /**< maximum total size of control transfer data */ +#define MAX_REQ_HANDLERS 4 /**< standard, class, vendor, reserved */ + +static TSetupPacket Setup; /**< setup packet */ + +static U8 *pbData; /**< pointer to data buffer */ +static int iResidue; /**< remaining bytes in buffer */ +static int iLen; /**< total length of control transfer */ + +/** Array of installed request handler callbacks */ +static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL}; +/** Array of installed request data pointers */ +static U8 *apbDataStore[4] = {NULL, NULL, NULL, NULL}; + +/** + Local function to handle a request by calling one of the installed + request handlers. + + In case of data going from host to device, the data is at *ppbData. + In case of data going from device to host, the handler can either + choose to write its data at *ppbData or update the data pointer. + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in,out] ppbData Data buffer. + + @return TRUE if the request was handles successfully + */ +static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) +{ + TFnHandleRequest *pfnHandler; + int iType; + + iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); + pfnHandler = apfnReqHandlers[iType]; + if (pfnHandler == NULL) { + DBG("No handler for reqtype %d\n", iType); + return FALSE; + } + + return pfnHandler(pSetup, piLen, ppbData); +} + + +/** + Local function to stall the control endpoint + + @param [in] bEPStat Endpoint status + */ +static void StallControlPipe(U8 bEPStat) +{ + U8 *pb; + int i; + + USBHwEPStall(0x80, TRUE); + +// dump setup packet + DBG("STALL on ["); + pb = (U8 *)&Setup; + for (i = 0; i < 8; i++) { + DBG(" %02x", *pb++); + } + DBG("] stat=%x\n", bEPStat); +} + + +/** + Sends next chunk of data (possibly 0 bytes) to host + */ +static void DataIn(void) +{ + int iChunk; + + iChunk = MIN(MAX_PACKET_SIZE0, iResidue); + USBHwEPWrite(0x80, pbData, iChunk); + pbData += iChunk; + iResidue -= iChunk; +} + + +/** + * Handles IN/OUT transfers on EP0 + * + * @param [in] bEP Endpoint address + * @param [in] bEPStat Endpoint status + */ +void USBHandleControlTransfer(U8 bEP, U8 bEPStat) +{ + int iChunk, iType; + + if (bEP == 0x00) { + // OUT transfer + if (bEPStat & EP_STATUS_SETUP) { + // setup packet, reset request message state machine + USBHwEPRead(0x00, (U8 *)&Setup, sizeof(Setup)); + DBG("S%x", Setup.bRequest); + + // defaults for data pointer and residue + iType = REQTYPE_GET_TYPE(Setup.bmRequestType); + pbData = apbDataStore[iType]; + iResidue = Setup.wLength; + iLen = Setup.wLength; + + if ((Setup.wLength == 0) || + (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) { + // ask installed handler to process request + if (!_HandleRequest(&Setup, &iLen, &pbData)) { + DBG("_HandleRequest1 failed\n"); + StallControlPipe(bEPStat); + return; + } + // send smallest of requested and offered length + iResidue = MIN(iLen, Setup.wLength); + // send first part (possibly a zero-length status message) + DataIn(); + } + } + else { + if (iResidue > 0) { + // store data + iChunk = USBHwEPRead(0x00, pbData, iResidue); + if (iChunk < 0) { + StallControlPipe(bEPStat); + return; + } + pbData += iChunk; + iResidue -= iChunk; + if (iResidue == 0) { + // received all, send data to handler + iType = REQTYPE_GET_TYPE(Setup.bmRequestType); + pbData = apbDataStore[iType]; + if (!_HandleRequest(&Setup, &iLen, &pbData)) { + DBG("_HandleRequest2 failed\n"); + StallControlPipe(bEPStat); + return; + } + // send status to host + DataIn(); + } + } + else { + // absorb zero-length status message + iChunk = USBHwEPRead(0x00, NULL, 0); + DBG(iChunk > 0 ? "?" : ""); + } + } + } + else if (bEP == 0x80) { + // IN transfer + // send more data if available (possibly a 0-length packet) + DataIn(); + } + else { + ASSERT(FALSE); + } +} + + +/** + Registers a callback for handling requests + + @param [in] iType Type of request, e.g. REQTYPE_TYPE_STANDARD + @param [in] *pfnHandler Callback function pointer + @param [in] *pbDataStore Data storage area for this type of request + */ +void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, U8 *pbDataStore) +{ + ASSERT(iType >= 0); + ASSERT(iType < 4); + apfnReqHandlers[iType] = pfnHandler; + apbDataStore[iType] = pbDataStore; +} + diff --git a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c new file mode 100644 index 00000000..2f0f658c --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c @@ -0,0 +1,627 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + USB hardware layer + */ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +//#include "type.h" +#include "lpcusb_type.h" + +#include "usbdebug.h" +#include "usbhw_lpc.h" +#include "usbapi.h" +// Configure LED pin functions +// +// LED pin functions +// +// Function Pin Port Bits Pin Select Register +// ------------------- --- ----- ---- ------------------- +// P2.0 GPIO Port 2.0 xx P2.0 1:0 PINSEL4 +// P2.1 GPIO Port 2.1 xx P2.1 3:2 PINSEL4 +// P2.2 GPIO Port 2.2 xx P2.2 5:4 PINSEL4 +// P2.3 GPIO Port 2.3 xx P2.3 7:6 PINSEL4 +// P2.4 GPIO Port 2.4 xx P2.4 9:8 PINSEL4 +// P2.5 GPIO Port 2.5 xx P2.5 11:10 PINSEL4 +// P2.6 GPIO Port 2.6 xx P2.6 13:12 PINSEL4 +// P2.7 GPIO Port 2.7 xx P2.7 15:14 PINSEL4 +// +// OFF - LED state 0 +// ON - LED state 1 +// +// '*' as GPIO + +#define NO_LEDS 8 + +#define LED_0 (1 << 0) +#define LED_1 (1 << 1) +#define LED_2 (1 << 2) +#define LED_3 (1 << 3) +#define LED_4 (1 << 4) +#define LED_5 (1 << 5) +#define LED_6 (1 << 6) +#define LED_7 (1 << 7) + +#ifdef DEBUG +// comment out the following line if you don't want to use debug LEDs +//#define DEBUG_LED +#endif + +#ifdef DEBUG_LED +#define DEBUG_LED_ON(x) FIO2SET = (1 << x); +#define DEBUG_LED_OFF(x) FIO2CLR = (1 << x); +#define DEBUG_LED_INIT(x) PINSEL2 &= ~(0x3 << (2*x)); FIO2DIR |= (1 << x); DEBUG_LED_OFF(x); +#else +#define DEBUG_LED_INIT(x) /**< LED initialisation macro */ +#define DEBUG_LED_ON(x) /**< turn LED on */ +#define DEBUG_LED_OFF(x) /**< turn LED off */ +#endif + +/** Installed device interrupt handler */ +static TFnDevIntHandler *_pfnDevIntHandler = NULL; +/** Installed endpoint interrupt handlers */ +static TFnEPIntHandler *_apfnEPIntHandlers[16]; +/** Installed frame interrupt handlers */ +static TFnFrameHandler *_pfnFrameHandler = NULL; + +/** convert from endpoint address to endpoint index */ +#define EP2IDX(bEP) ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7)) +/** convert from endpoint index to endpoint address */ +#define IDX2EP(idx) ((((idx)<<7)&0x80)|(((idx)>>1)&0xF)) + + + +/** + Local function to wait for a device interrupt (and clear it) + + @param [in] dwIntr Bitmask of interrupts to wait for + */ +static void Wait4DevInt(U32 dwIntr) +{ + // wait for specific interrupt + while ((LPC_USB->USBDevIntSt & dwIntr) != dwIntr); + // clear the interrupt bits + LPC_USB->USBDevIntClr = dwIntr; +} + + +/** + Local function to send a command to the USB protocol engine + + @param [in] bCmd Command to send + */ +static void USBHwCmd(U8 bCmd) +{ + // clear CDFULL/CCEMTY + LPC_USB->USBDevIntClr = CDFULL | CCEMTY; + // write command code + LPC_USB->USBCmdCode = 0x00000500 | (bCmd << 16); + Wait4DevInt(CCEMTY); +} + + +/** + Local function to send a command + data to the USB protocol engine + + @param [in] bCmd Command to send + @param [in] bData Data to send + */ +static void USBHwCmdWrite(U8 bCmd, U16 bData) +{ + // write command code + USBHwCmd(bCmd); + + // write command data + LPC_USB->USBCmdCode = 0x00000100 | (bData << 16); + Wait4DevInt(CCEMTY); +} + + +/** + Local function to send a command to the USB protocol engine and read data + + @param [in] bCmd Command to send + + @return the data + */ +static U8 USBHwCmdRead(U8 bCmd) +{ + // write command code + USBHwCmd(bCmd); + + // get data + LPC_USB->USBCmdCode = 0x00000200 | (bCmd << 16); + Wait4DevInt(CDFULL); + return LPC_USB->USBCmdData; +} + + +/** + 'Realizes' an endpoint, meaning that buffer space is reserved for + it. An endpoint needs to be realised before it can be used. + + From experiments, it appears that a USB reset causes USBReEP to + re-initialise to 3 (= just the control endpoints). + However, a USB bus reset does not disturb the USBMaxPSize settings. + + @param [in] idx Endpoint index + @param [in] wMaxPSize Maximum packet size for this endpoint + */ +static void USBHwEPRealize(int idx, U16 wMaxPSize) +{ + LPC_USB->USBReEP |= (1 << idx); + LPC_USB->USBEpInd = idx; + LPC_USB->USBMaxPSize = wMaxPSize; + Wait4DevInt(EP_RLZED); +} + + +/** + Enables or disables an endpoint + + @param [in] idx Endpoint index + @param [in] fEnable TRUE to enable, FALSE to disable + */ +static void USBHwEPEnable(int idx, BOOL fEnable) +{ + USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA); +} + + +/** + Configures an endpoint and enables it + + @param [in] bEP Endpoint number + @param [in] wMaxPacketSize Maximum packet size for this EP + */ +void USBHwEPConfig(U8 bEP, U16 wMaxPacketSize) +{ + int idx; + + idx = EP2IDX(bEP); + + // realise EP + USBHwEPRealize(idx, wMaxPacketSize); + + // enable EP + USBHwEPEnable(idx, TRUE); +} + + +/** + Registers an endpoint event callback + + @param [in] bEP Endpoint number + @param [in] pfnHandler Callback function + */ +void USBHwRegisterEPIntHandler(U8 bEP, TFnEPIntHandler *pfnHandler) +{ + int idx; + + idx = EP2IDX(bEP); + + ASSERT(idx<32); + + /* add handler to list of EP handlers */ + _apfnEPIntHandlers[idx / 2] = pfnHandler; + + /* enable EP interrupt */ + LPC_USB->USBEpIntEn |= (1 << idx); + LPC_USB->USBDevIntEn |= EP_SLOW; + + DBG("Registered handler for EP 0x%x\n", bEP); +} + + +/** + Registers an device status callback + + @param [in] pfnHandler Callback function + */ +void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler) +{ + _pfnDevIntHandler = pfnHandler; + + // enable device interrupt + LPC_USB->USBDevIntEn |= DEV_STAT; + + DBG("Registered handler for device status\n"); +} + + +/** + Registers the frame callback + + @param [in] pfnHandler Callback function + */ +void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler) +{ + _pfnFrameHandler = pfnHandler; + + // enable device interrupt + LPC_USB->USBDevIntEn |= FRAME; + + DBG("Registered handler for frame\n"); +} + + +/** + Sets the USB address. + + @param [in] bAddr Device address to set + */ +void USBHwSetAddress(U8 bAddr) +{ + USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr); +} + + +/** + Connects or disconnects from the USB bus + + @param [in] fConnect If TRUE, connect, otherwise disconnect + */ +void USBHwConnect(BOOL fConnect) +{ + USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0); +} + + +/** + Enables interrupt on NAK condition + + For IN endpoints a NAK is generated when the host wants to read data + from the device, but none is available in the endpoint buffer. + For OUT endpoints a NAK is generated when the host wants to write data + to the device, but the endpoint buffer is still full. + + The endpoint interrupt handlers can distinguish regular (ACK) interrupts + from NAK interrupt by checking the bits in their bEPStatus argument. + + @param [in] bIntBits Bitmap indicating which NAK interrupts to enable + */ +void USBHwNakIntEnable(U8 bIntBits) +{ + USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits); +} + + +/** + Gets the status from a specific endpoint. + + @param [in] bEP Endpoint number + @return Endpoint status byte (containing EP_STATUS_xxx bits) + */ +U8 USBHwEPGetStatus(U8 bEP) +{ + int idx = EP2IDX(bEP); + + return USBHwCmdRead(CMD_EP_SELECT | idx); +} + + +/** + Sets the stalled property of an endpoint + + @param [in] bEP Endpoint number + @param [in] fStall TRUE to stall, FALSE to unstall + */ +void USBHwEPStall(U8 bEP, BOOL fStall) +{ + int idx = EP2IDX(bEP); + + USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0); +} + + +/** + Writes data to an endpoint buffer + + @param [in] bEP Endpoint number + @param [in] pbBuf Endpoint data + @param [in] iLen Number of bytes to write + + @return TRUE if the data was successfully written or <0 in case of error. +*/ +int USBHwEPWrite(U8 bEP, U8 *pbBuf, int iLen) +{ + int idx; + + idx = EP2IDX(bEP); + + // set write enable for specific endpoint + LPC_USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2); + + // set packet length + LPC_USB->USBTxPLen = iLen; + + // write data + while (LPC_USB->USBCtrl & WR_EN) { + LPC_USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0]; + pbBuf += 4; + } + + // select endpoint and validate buffer + USBHwCmd(CMD_EP_SELECT | idx); + USBHwCmd(CMD_EP_VALIDATE_BUFFER); + + return iLen; +} + + +/** + Reads data from an endpoint buffer + + @param [in] bEP Endpoint number + @param [in] pbBuf Endpoint data + @param [in] iMaxLen Maximum number of bytes to read + + @return the number of bytes available in the EP (possibly more than iMaxLen), + or <0 in case of error. + */ +int USBHwEPRead(U8 bEP, U8 *pbBuf, int iMaxLen) +{ + int i, idx; + U32 dwData, dwLen; + + idx = EP2IDX(bEP); + + // set read enable bit for specific endpoint + LPC_USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2); + + // wait for PKT_RDY + do { + dwLen = LPC_USB->USBRxPLen; + } while ((dwLen & PKT_RDY) == 0); + + // packet valid? + if ((dwLen & DV) == 0) { + return -1; + } + + // get length + dwLen &= PKT_LNGTH_MASK; + + // get data + dwData = 0; + for (i = 0; i < dwLen; i++) { + if ((i % 4) == 0) { + dwData = LPC_USB->USBRxData; + } + if ((pbBuf != NULL) && (i < iMaxLen)) { + pbBuf[i] = dwData & 0xFF; + } + dwData >>= 8; + } + + // make sure RD_EN is clear + LPC_USB->USBCtrl = 0; + + // select endpoint and clear buffer + USBHwCmd(CMD_EP_SELECT | idx); + USBHwCmd(CMD_EP_CLEAR_BUFFER); + + return dwLen; +} + + +/** + Sets the 'configured' state. + + All registered endpoints are 'realised' and enabled, and the + 'configured' bit is set in the device status register. + + @param [in] fConfigured If TRUE, configure device, else unconfigure + */ +void USBHwConfigDevice(BOOL fConfigured) +{ + // set configured bit + USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0); +} + + +/** + USB interrupt handler + + @todo Get all 11 bits of frame number instead of just 8 + + Endpoint interrupts are mapped to the slow interrupt + */ +void USBHwISR(void) +{ + U32 dwStatus; + U32 dwIntBit; + U8 bEPStat, bDevStat, bStat; + int i; + U16 wFrame; + + // LED9 monitors total time in interrupt routine + DEBUG_LED_ON(6); + + // handle device interrupts + dwStatus = LPC_USB->USBDevIntSt; + + // frame interrupt + if (dwStatus & FRAME) { + // clear int + LPC_USB->USBDevIntClr = FRAME; + // call handler + if (_pfnFrameHandler != NULL) { + wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR); + _pfnFrameHandler(wFrame); + } + } + + // device status interrupt + if (dwStatus & DEV_STAT) { + /* Clear DEV_STAT interrupt before reading DEV_STAT register. + This prevents corrupted device status reads, see + LPC2148 User manual revision 2, 25 july 2006. + */ + LPC_USB->USBDevIntClr = DEV_STAT; + bDevStat = USBHwCmdRead(CMD_DEV_STATUS); + if (bDevStat & (CON_CH | SUS_CH | RST)) { + // convert device status into something HW independent + bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) | + ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) | + ((bDevStat & RST) ? DEV_STATUS_RESET : 0); + // call handler + if (_pfnDevIntHandler != NULL) { + DEBUG_LED_ON(5); + _pfnDevIntHandler(bStat); + DEBUG_LED_OFF(5); + } + } + } + + // endpoint interrupt + if (dwStatus & EP_SLOW) { + // clear EP_SLOW + LPC_USB->USBDevIntClr = EP_SLOW; + // check all endpoints + for (i = 0; i < 32; i++) { + dwIntBit = (1 << i); + if (LPC_USB->USBEpIntSt & dwIntBit) { + // clear int (and retrieve status) + LPC_USB->USBEpIntClr = dwIntBit; + Wait4DevInt(CDFULL); + bEPStat = LPC_USB->USBCmdData; + // convert EP pipe stat into something HW independent + bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) | + ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) | + ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | + ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | + ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0); + // call handler + if (_apfnEPIntHandlers[i / 2] != NULL) { + DEBUG_LED_ON(7); + _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); + DEBUG_LED_OFF(7); + } + } + } + } + + DEBUG_LED_OFF(6); +} + + + +/** + Initialises the USB hardware + + This function assumes that the hardware is connected as shown in + section 10.1 of the LPC2148 data sheet: + * P0.31 controls a switch to connect a 1.5k pull-up to D+ if low. + * P0.23 is connected to USB VCC. + + Embedded artists board: make sure to disconnect P0.23 LED as it + acts as a pull-up and so prevents detection of USB disconnect. + + @return TRUE if the hardware was successfully initialised + */ +BOOL USBHwInit(void) +{ +/* CodeRed - comment out original code + * + // configure P0.23 for Vbus sense + PINSEL1 = (PINSEL1 & ~(3 << 14)) | (1 << 14); // P0.23 + // configure P0.31 for CONNECT + PINSEL1 = (PINSEL1 & ~(3 << 30)) | (2 << 30); // P0.31 +*/ + + // CodeRed - set up USB pins + + // P2.9 -> USB_CONNECT + LPC_PINCON->PINSEL4 &= ~0x000C0000; + LPC_PINCON->PINSEL4 |= 0x00040000; + + // P1.18 -> USB_UP_LED + // P1.30 -> VBUS + LPC_PINCON->PINSEL3 &= ~0x30000030; + LPC_PINCON->PINSEL3 |= 0x20000010; + + // P0.29 -> USB_D+ + // P0.30 -> USB_D- + LPC_PINCON->PINSEL1 &= ~0x3C000000; + LPC_PINCON->PINSEL1 |= 0x14000000; + + + // enable PUSB + LPC_SC->PCONP |= (1 << 31); + +/* CodeRed - Comment out original PLL code + * PLL now set up by NXP code in target.c within example projects + * + // initialise PLL + PLL1CON = 1; // enable PLL + PLL1CFG = (1 << 5) | 3; // P = 2, M = 4 + PLL1FEED = 0xAA; + PLL1FEED = 0x55; + while ((PLL1STAT & (1 << 10)) == 0); + + PLL1CON = 3; // enable and connect + PLL1FEED = 0xAA; + PLL1FEED = 0x55; + +*/ + + +// AWB added USB clock enable +// These are actually the USBClkCtrl and USBClkSt registers +// OTG_CLK_CTRL = 0x12; /* Dev clock, AHB clock enable */ +// while ((OTG_CLK_STAT & 0x12) != 0x12); + + LPC_USB->USBClkCtrl = 0x1A; /* Dev clock, AHB clock enable */ + while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); + + + // disable/clear all interrupts for now + LPC_USB->USBDevIntEn = 0; + LPC_USB->USBDevIntClr = 0xFFFFFFFF; + LPC_USB->USBDevIntPri = 0; + + LPC_USB->USBEpIntEn = 0; + LPC_USB->USBEpIntClr = 0xFFFFFFFF; + LPC_USB->USBEpIntPri = 0; + + // by default, only ACKs generate interrupts + USBHwNakIntEnable(0); + + // CodeRed - commented out LEDs - not used by current port + // init debug leds + /* + DEBUG_LED_INIT(5); + DEBUG_LED_INIT(6); + DEBUG_LED_INIT(7); + */ + + return TRUE; +} + diff --git a/src/platform/lpc17xx/usbstack/src/usbinit.c b/src/platform/lpc17xx/usbstack/src/usbinit.c new file mode 100644 index 00000000..90b9341d --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbinit.c @@ -0,0 +1,85 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + USB stack initialisation + */ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +//#include "type.h" +#include "lpcusb_type.h" + +#include "usbdebug.h" +#include "usbapi.h" + + +/** data storage area for standard requests */ +static U8 abStdReqData[8]; + + +/** + USB reset handler + + @param [in] bDevStatus Device status + */ +static void HandleUsbReset(U8 bDevStatus) +{ + if (bDevStatus & DEV_STATUS_RESET) { + DBG("\n!"); + } +} + + +/** + Initialises the USB hardware and sets up the USB stack by + installing default callbacks. + + @return TRUE if initialisation was successful + */ +BOOL USBInit(void) +{ + // init hardware + USBHwInit(); + + // register bus reset handler + USBHwRegisterDevIntHandler(HandleUsbReset); + + // register control transfer handler on EP0 + USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer); + USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer); + + // setup control endpoints + USBHwEPConfig(0x00, MAX_PACKET_SIZE0); + USBHwEPConfig(0x80, MAX_PACKET_SIZE0); + + // register standard request handler + USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData); + + return TRUE; +} + diff --git a/src/platform/lpc17xx/usbstack/src/usbstdreq.c b/src/platform/lpc17xx/usbstack/src/usbstdreq.c new file mode 100644 index 00000000..5b159002 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbstdreq.c @@ -0,0 +1,434 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + Standard request handler. + + This modules handles the 'chapter 9' processing, specifically the + standard device requests in table 9-3 from the universal serial bus + specification revision 2.0 + + Specific types of devices may specify additional requests (for example + HID devices add a GET_DESCRIPTOR request for interfaces), but they + will not be part of this module. + + @todo some requests have to return a request error if device not configured: + @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME + @todo this applies to the following if endpoint != 0: + @todo SET_FEATURE, GET_FEATURE +*/ + +// CodeRed - include the LPCUSB type.h file rather than NXP one directly +//#include "type.h" +#include "lpcusb_type.h" + +#include "usbdebug.h" +#include "usbstruct.h" +#include "usbapi.h" + +#define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */ + + +/* general descriptor field offsets */ +#define DESC_bLength 0 /**< length offset */ +#define DESC_bDescriptorType 1 /**< descriptor type offset */ + +/* config descriptor field offsets */ +#define CONF_DESC_wTotalLength 2 /**< total length offset */ +#define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */ +#define CONF_DESC_bmAttributes 7 /**< configuration characteristics */ + +/* interface descriptor field offsets */ +#define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */ + +/* endpoint descriptor field offsets */ +#define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */ +#define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */ + + +/** Currently selected configuration */ +static U8 bConfiguration = 0; +/** Installed custom request handler */ +static TFnHandleRequest *pfnHandleCustomReq = NULL; +/** Pointer to registered descriptors */ +static const U8 *pabDescrip = NULL; + + +/** + Registers a pointer to a descriptor block containing all descriptors + for the device. + + @param [in] pabDescriptors The descriptor byte array + */ +void USBRegisterDescriptors(const U8 *pabDescriptors) +{ + pabDescrip = pabDescriptors; +} + + +/** + Parses the list of installed USB descriptors and attempts to find + the specified USB descriptor. + + @param [in] wTypeIndex Type and index of the descriptor + @param [in] wLangID Language ID of the descriptor (currently unused) + @param [out] *piLen Descriptor length + @param [out] *ppbData Descriptor data + + @return TRUE if the descriptor was found, FALSE otherwise + */ +BOOL USBGetDescriptor(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData) +{ + U8 bType, bIndex; + U8 *pab; + int iCurIndex; + + ASSERT(pabDescrip != NULL); + + bType = GET_DESC_TYPE(wTypeIndex); + bIndex = GET_DESC_INDEX(wTypeIndex); + + pab = (U8 *)pabDescrip; + iCurIndex = 0; + + while (pab[DESC_bLength] != 0) { + if (pab[DESC_bDescriptorType] == bType) { + if (iCurIndex == bIndex) { + // set data pointer + *ppbData = pab; + // get length from structure + if (bType == DESC_CONFIGURATION) { + // configuration descriptor is an exception, length is at offset 2 and 3 + *piLen = (pab[CONF_DESC_wTotalLength]) | + (pab[CONF_DESC_wTotalLength + 1] << 8); + } + else { + // normally length is at offset 0 + *piLen = pab[DESC_bLength]; + } + return TRUE; + } + iCurIndex++; + } + // skip to next descriptor + pab += pab[DESC_bLength]; + } + // nothing found + DBG("Desc %x not found!\n", wTypeIndex); + return FALSE; +} + + +/** + Configures the device according to the specified configuration index and + alternate setting by parsing the installed USB descriptor list. + A configuration index of 0 unconfigures the device. + + @param [in] bConfigIndex Configuration index + @param [in] bAltSetting Alternate setting number + + @todo function always returns TRUE, add stricter checking? + + @return TRUE if successfully configured, FALSE otherwise + */ +static BOOL USBSetConfiguration(U8 bConfigIndex, U8 bAltSetting) +{ + U8 *pab; + U8 bCurConfig, bCurAltSetting; + U8 bEP; + U16 wMaxPktSize; + + ASSERT(pabDescrip != NULL); + + if (bConfigIndex == 0) { + // unconfigure device + USBHwConfigDevice(FALSE); + } + else { + // configure endpoints for this configuration/altsetting + pab = (U8 *)pabDescrip; + bCurConfig = 0xFF; + bCurAltSetting = 0xFF; + + while (pab[DESC_bLength] != 0) { + + switch (pab[DESC_bDescriptorType]) { + + case DESC_CONFIGURATION: + // remember current configuration index + bCurConfig = pab[CONF_DESC_bConfigurationValue]; + break; + + case DESC_INTERFACE: + // remember current alternate setting + bCurAltSetting = pab[INTF_DESC_bAlternateSetting]; + break; + + case DESC_ENDPOINT: + if ((bCurConfig == bConfigIndex) && + (bCurAltSetting == bAltSetting)) { + // endpoint found for desired config and alternate setting + bEP = pab[ENDP_DESC_bEndpointAddress]; + wMaxPktSize = (pab[ENDP_DESC_wMaxPacketSize]) | + (pab[ENDP_DESC_wMaxPacketSize + 1] << 8); + // configure endpoint + USBHwEPConfig(bEP, wMaxPktSize); + } + break; + + default: + break; + } + // skip to next descriptor + pab += pab[DESC_bLength]; + } + + // configure device + USBHwConfigDevice(TRUE); + } + + return TRUE; +} + + +/** + Local function to handle a standard device request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in,out] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) +{ + U8 *pbData = *ppbData; + + switch (pSetup->bRequest) { + + case REQ_GET_STATUS: + // bit 0: self-powered + // bit 1: remote wakeup = not supported + pbData[0] = 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_SET_ADDRESS: + USBHwSetAddress(pSetup->wValue); + break; + + case REQ_GET_DESCRIPTOR: + DBG("D%x", pSetup->wValue); + return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData); + + case REQ_GET_CONFIGURATION: + // indicate if we are configured + pbData[0] = bConfiguration; + *piLen = 1; + break; + + case REQ_SET_CONFIGURATION: + if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) { + DBG("USBSetConfiguration failed!\n"); + return FALSE; + } + // configuration successful, update current configuration + bConfiguration = pSetup->wValue & 0xFF; + break; + + case REQ_CLEAR_FEATURE: + case REQ_SET_FEATURE: + if (pSetup->wValue == FEA_REMOTE_WAKEUP) { + // put DEVICE_REMOTE_WAKEUP code here + } + if (pSetup->wValue == FEA_TEST_MODE) { + // put TEST_MODE code here + } + return FALSE; + + case REQ_SET_DESCRIPTOR: + DBG("Device req %d not implemented\n", pSetup->bRequest); + return FALSE; + + default: + DBG("Illegal device req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Local function to handle a standard interface request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) +{ + U8 *pbData = *ppbData; + + switch (pSetup->bRequest) { + + case REQ_GET_STATUS: + // no bits specified + pbData[0] = 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_CLEAR_FEATURE: + case REQ_SET_FEATURE: + // not defined for interface + return FALSE; + + case REQ_GET_INTERFACE: // TODO use bNumInterfaces + // there is only one interface, return n-1 (= 0) + pbData[0] = 0; + *piLen = 1; + break; + + case REQ_SET_INTERFACE: // TODO use bNumInterfaces + // there is only one interface (= 0) + if (pSetup->wValue != 0) { + return FALSE; + } + *piLen = 0; + break; + + default: + DBG("Illegal interface req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Local function to handle a standard endpoint request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdEndPointReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) +{ + U8 *pbData = *ppbData; + + switch (pSetup->bRequest) { + case REQ_GET_STATUS: + // bit 0 = endpointed halted or not + pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_CLEAR_FEATURE: + if (pSetup->wValue == FEA_ENDPOINT_HALT) { + // clear HALT by unstalling + USBHwEPStall(pSetup->wIndex, FALSE); + break; + } + // only ENDPOINT_HALT defined for endpoints + return FALSE; + + case REQ_SET_FEATURE: + if (pSetup->wValue == FEA_ENDPOINT_HALT) { + // set HALT by stalling + USBHwEPStall(pSetup->wIndex, TRUE); + break; + } + // only ENDPOINT_HALT defined for endpoints + return FALSE; + + case REQ_SYNCH_FRAME: + DBG("EP req %d not implemented\n", pSetup->bRequest); + return FALSE; + + default: + DBG("Illegal EP req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Default handler for standard ('chapter 9') requests + + If a custom request handler was installed, this handler is called first. + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) +{ + // try the custom request handler first + if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) { + return TRUE; + } + + switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) { + case REQTYPE_RECIP_DEVICE: return HandleStdDeviceReq(pSetup, piLen, ppbData); + case REQTYPE_RECIP_INTERFACE: return HandleStdInterfaceReq(pSetup, piLen, ppbData); + case REQTYPE_RECIP_ENDPOINT: return HandleStdEndPointReq(pSetup, piLen, ppbData); + default: return FALSE; + } +} + + +/** + Registers a callback for custom device requests + + In USBHandleStandardRequest, the custom request handler gets a first + chance at handling the request before it is handed over to the 'chapter 9' + request handler. + + This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR + request is sent to an interface, which is not covered by the 'chapter 9' + specification. + + @param [in] pfnHandler Callback function pointer + */ +void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler) +{ + pfnHandleCustomReq = pfnHandler; +} + From 480d6352eabe95797a5836d10c3b10285ac1c79c Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 23 Apr 2015 16:23:08 +0200 Subject: [PATCH 19/26] Bring type definitions in line with eLua standard conventions. --- src/platform/lpc17xx/conf.lua | 2 + .../lpc17xx/usbstack/inc/lpcusb_type.h | 68 - src/platform/lpc17xx/usbstack/inc/type.h | 38 - .../lpc17xx/usbstack/src/usbcontrol.c | 43 +- src/platform/lpc17xx/usbstack/src/usbhw_lpc.c | 1251 ++++++++--------- src/platform/lpc17xx/usbstack/src/usbinit.c | 25 +- src/platform/lpc17xx/usbstack/src/usbstdreq.c | 865 ++++++------ 7 files changed, 1088 insertions(+), 1204 deletions(-) delete mode 100644 src/platform/lpc17xx/usbstack/inc/lpcusb_type.h delete mode 100644 src/platform/lpc17xx/usbstack/inc/type.h diff --git a/src/platform/lpc17xx/conf.lua b/src/platform/lpc17xx/conf.lua index f91dec2e..cda5d2cb 100644 --- a/src/platform/lpc17xx/conf.lua +++ b/src/platform/lpc17xx/conf.lua @@ -1,8 +1,10 @@ -- Configuration file for the LPC17xx backend addi( sf( 'src/platform/%s/drivers/inc', platform ) ) +addi( sf( 'src/platform/%s/usbstack/inc', platform ) ) local fwlib_files = utils.get_files( sf( "src/platform/%s/drivers/src", platform ), ".*%.c$" ) +fwlib_files = fwlib_files .. " " .. utils.get_files( sf( "src/platform/%s/usbstack/src", platform ), ".*%.c$" ) specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c" local board = comp.board:upper() diff --git a/src/platform/lpc17xx/usbstack/inc/lpcusb_type.h b/src/platform/lpc17xx/usbstack/inc/lpcusb_type.h deleted file mode 100644 index 1c765432..00000000 --- a/src/platform/lpc17xx/usbstack/inc/lpcusb_type.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - LPCUSB, an USB device driver for LPC microcontrollers - Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/** - @file - primitive types used in the USB stack - */ - -// *********************************************** -// Code Red Technologies - port to RDB1768 board -// In order to avoid clashing with the NXP-produced type.h file, this -// one has been renamed to lpcusb_type.h, the NXP-produced type.h has -// been included, and the duplicate contents of this file commented out. -// *********************************************** - - -#ifndef _LPCUSB_TYPE_H_ -#define _LPCUSB_TYPE_H_ - -// CodeRed - include NXP-produced type.h file -#include "type.h" - -typedef unsigned char U8; /**< unsigned 8-bit */ -typedef unsigned short int U16; /**< unsigned 16-bit */ -typedef unsigned int U32; /**< unsigned 32-bit */ - - -// CodeRed - comment out defines duplicated in NXP type.h - -//typedef int BOOL; /**< #TRUE or #FALSE */ - -//#define TRUE 1 /**< TRUE */ -//#define FALSE 0 /**< FALSE */ - -//#ifndef NULL -//#define NULL ((void*)0) /**< NULL pointer */ -//#endif -//#endif - -/* some other useful macros */ -#define MIN(x,y) ((x)<(y)?(x):(y)) /**< MIN */ -#define MAX(x,y) ((x)>(y)?(x):(y)) /**< MAX */ - -#endif /* _LPCUSB_TYPE_H_ */ - diff --git a/src/platform/lpc17xx/usbstack/inc/type.h b/src/platform/lpc17xx/usbstack/inc/type.h deleted file mode 100644 index 89d36850..00000000 --- a/src/platform/lpc17xx/usbstack/inc/type.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************** - * type.h: Type definition Header file for NXP LPC17xx Family - * Microprocessors - * - * Copyright(C) 2008, NXP Semiconductor - * All rights reserved. - * - * History - * 2008.08.21 ver 1.00 Prelimnary version, first Release - * -******************************************************************************/ -#ifndef __TYPE_H__ -#define __TYPE_H__ - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (1) -#endif - -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; -typedef unsigned int BOOL; - -typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; -typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; - -/* Pointer to Function returning Void (any number of parameters) */ -typedef void (*PFV)(); - -#endif /* __TYPE_H__ */ diff --git a/src/platform/lpc17xx/usbstack/src/usbcontrol.c b/src/platform/lpc17xx/usbstack/src/usbcontrol.c index baf90fe6..fd07486a 100644 --- a/src/platform/lpc17xx/usbstack/src/usbcontrol.c +++ b/src/platform/lpc17xx/usbstack/src/usbcontrol.c @@ -1,5 +1,5 @@ /* - LPCUSB, an USB device driver for LPC microcontrollers + LPCUSB, an USB device driver for LPC microcontrollers Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) Redistribution and use in source and binary forms, with or without @@ -16,7 +16,7 @@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @@ -28,10 +28,10 @@ /** @file Control transfer handler. - + This module handles control transfers and is normally installed on the endpoint 0 callback. - + Control transfers can be of the following type: 0 Standard; 1 Class; @@ -48,9 +48,7 @@ control transfer data. The data is then packetised and sent to the host. */ -// CodeRed - include the LPCUSB type.h file rather than NXP one directly -//#include "type.h" -#include "lpcusb_type.h" +#include "type.h" #include "usbdebug.h" @@ -64,34 +62,34 @@ static TSetupPacket Setup; /**< setup packet */ -static U8 *pbData; /**< pointer to data buffer */ +static u8 *pbData; /**< pointer to data buffer */ static int iResidue; /**< remaining bytes in buffer */ static int iLen; /**< total length of control transfer */ /** Array of installed request handler callbacks */ static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL}; /** Array of installed request data pointers */ -static U8 *apbDataStore[4] = {NULL, NULL, NULL, NULL}; +static u8 *apbDataStore[4] = {NULL, NULL, NULL, NULL}; /** Local function to handle a request by calling one of the installed request handlers. - + In case of data going from host to device, the data is at *ppbData. In case of data going from device to host, the handler can either choose to write its data at *ppbData or update the data pointer. - + @param [in] pSetup The setup packet @param [in,out] *piLen Pointer to data length @param [in,out] ppbData Data buffer. @return TRUE if the request was handles successfully */ -static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) +static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData) { TFnHandleRequest *pfnHandler; int iType; - + iType = REQTYPE_GET_TYPE(pSetup->bmRequestType); pfnHandler = apfnReqHandlers[iType]; if (pfnHandler == NULL) { @@ -105,19 +103,19 @@ static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) /** Local function to stall the control endpoint - + @param [in] bEPStat Endpoint status */ -static void StallControlPipe(U8 bEPStat) +static void StallControlPipe(u8 bEPStat) { - U8 *pb; + u8 *pb; int i; USBHwEPStall(0x80, TRUE); // dump setup packet DBG("STALL on ["); - pb = (U8 *)&Setup; + pb = (u8 *)&Setup; for (i = 0; i < 8; i++) { DBG(" %02x", *pb++); } @@ -145,7 +143,7 @@ static void DataIn(void) * @param [in] bEP Endpoint address * @param [in] bEPStat Endpoint status */ -void USBHandleControlTransfer(U8 bEP, U8 bEPStat) +void USBHandleControlTransfer(u8 bEP, u8 bEPStat) { int iChunk, iType; @@ -153,7 +151,7 @@ void USBHandleControlTransfer(U8 bEP, U8 bEPStat) // OUT transfer if (bEPStat & EP_STATUS_SETUP) { // setup packet, reset request message state machine - USBHwEPRead(0x00, (U8 *)&Setup, sizeof(Setup)); + USBHwEPRead(0x00, (u8 *)&Setup, sizeof(Setup)); DBG("S%x", Setup.bRequest); // defaults for data pointer and residue @@ -176,7 +174,7 @@ void USBHandleControlTransfer(U8 bEP, U8 bEPStat) DataIn(); } } - else { + else { if (iResidue > 0) { // store data iChunk = USBHwEPRead(0x00, pbData, iResidue); @@ -219,16 +217,15 @@ void USBHandleControlTransfer(U8 bEP, U8 bEPStat) /** Registers a callback for handling requests - + @param [in] iType Type of request, e.g. REQTYPE_TYPE_STANDARD @param [in] *pfnHandler Callback function pointer @param [in] *pbDataStore Data storage area for this type of request */ -void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, U8 *pbDataStore) +void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, u8 *pbDataStore) { ASSERT(iType >= 0); ASSERT(iType < 4); apfnReqHandlers[iType] = pfnHandler; apbDataStore[iType] = pbDataStore; } - diff --git a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c index 2f0f658c..c8256902 100644 --- a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c +++ b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c @@ -1,627 +1,624 @@ -/* - LPCUSB, an USB device driver for LPC microcontrollers - Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/** @file - USB hardware layer - */ - -// CodeRed - include the LPCUSB type.h file rather than NXP one directly -//#include "type.h" -#include "lpcusb_type.h" - -#include "usbdebug.h" -#include "usbhw_lpc.h" -#include "usbapi.h" -// Configure LED pin functions -// -// LED pin functions -// -// Function Pin Port Bits Pin Select Register -// ------------------- --- ----- ---- ------------------- -// P2.0 GPIO Port 2.0 xx P2.0 1:0 PINSEL4 -// P2.1 GPIO Port 2.1 xx P2.1 3:2 PINSEL4 -// P2.2 GPIO Port 2.2 xx P2.2 5:4 PINSEL4 -// P2.3 GPIO Port 2.3 xx P2.3 7:6 PINSEL4 -// P2.4 GPIO Port 2.4 xx P2.4 9:8 PINSEL4 -// P2.5 GPIO Port 2.5 xx P2.5 11:10 PINSEL4 -// P2.6 GPIO Port 2.6 xx P2.6 13:12 PINSEL4 -// P2.7 GPIO Port 2.7 xx P2.7 15:14 PINSEL4 -// -// OFF - LED state 0 -// ON - LED state 1 -// -// '*' as GPIO - -#define NO_LEDS 8 - -#define LED_0 (1 << 0) -#define LED_1 (1 << 1) -#define LED_2 (1 << 2) -#define LED_3 (1 << 3) -#define LED_4 (1 << 4) -#define LED_5 (1 << 5) -#define LED_6 (1 << 6) -#define LED_7 (1 << 7) - -#ifdef DEBUG -// comment out the following line if you don't want to use debug LEDs -//#define DEBUG_LED -#endif - -#ifdef DEBUG_LED -#define DEBUG_LED_ON(x) FIO2SET = (1 << x); -#define DEBUG_LED_OFF(x) FIO2CLR = (1 << x); -#define DEBUG_LED_INIT(x) PINSEL2 &= ~(0x3 << (2*x)); FIO2DIR |= (1 << x); DEBUG_LED_OFF(x); -#else -#define DEBUG_LED_INIT(x) /**< LED initialisation macro */ -#define DEBUG_LED_ON(x) /**< turn LED on */ -#define DEBUG_LED_OFF(x) /**< turn LED off */ -#endif - -/** Installed device interrupt handler */ -static TFnDevIntHandler *_pfnDevIntHandler = NULL; -/** Installed endpoint interrupt handlers */ -static TFnEPIntHandler *_apfnEPIntHandlers[16]; -/** Installed frame interrupt handlers */ -static TFnFrameHandler *_pfnFrameHandler = NULL; - -/** convert from endpoint address to endpoint index */ -#define EP2IDX(bEP) ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7)) -/** convert from endpoint index to endpoint address */ -#define IDX2EP(idx) ((((idx)<<7)&0x80)|(((idx)>>1)&0xF)) - - - -/** - Local function to wait for a device interrupt (and clear it) - - @param [in] dwIntr Bitmask of interrupts to wait for - */ -static void Wait4DevInt(U32 dwIntr) -{ - // wait for specific interrupt - while ((LPC_USB->USBDevIntSt & dwIntr) != dwIntr); - // clear the interrupt bits - LPC_USB->USBDevIntClr = dwIntr; -} - - -/** - Local function to send a command to the USB protocol engine - - @param [in] bCmd Command to send - */ -static void USBHwCmd(U8 bCmd) -{ - // clear CDFULL/CCEMTY - LPC_USB->USBDevIntClr = CDFULL | CCEMTY; - // write command code - LPC_USB->USBCmdCode = 0x00000500 | (bCmd << 16); - Wait4DevInt(CCEMTY); -} - - -/** - Local function to send a command + data to the USB protocol engine - - @param [in] bCmd Command to send - @param [in] bData Data to send - */ -static void USBHwCmdWrite(U8 bCmd, U16 bData) -{ - // write command code - USBHwCmd(bCmd); - - // write command data - LPC_USB->USBCmdCode = 0x00000100 | (bData << 16); - Wait4DevInt(CCEMTY); -} - - -/** - Local function to send a command to the USB protocol engine and read data - - @param [in] bCmd Command to send - - @return the data - */ -static U8 USBHwCmdRead(U8 bCmd) -{ - // write command code - USBHwCmd(bCmd); - - // get data - LPC_USB->USBCmdCode = 0x00000200 | (bCmd << 16); - Wait4DevInt(CDFULL); - return LPC_USB->USBCmdData; -} - - -/** - 'Realizes' an endpoint, meaning that buffer space is reserved for - it. An endpoint needs to be realised before it can be used. - - From experiments, it appears that a USB reset causes USBReEP to - re-initialise to 3 (= just the control endpoints). - However, a USB bus reset does not disturb the USBMaxPSize settings. - - @param [in] idx Endpoint index - @param [in] wMaxPSize Maximum packet size for this endpoint - */ -static void USBHwEPRealize(int idx, U16 wMaxPSize) -{ - LPC_USB->USBReEP |= (1 << idx); - LPC_USB->USBEpInd = idx; - LPC_USB->USBMaxPSize = wMaxPSize; - Wait4DevInt(EP_RLZED); -} - - -/** - Enables or disables an endpoint - - @param [in] idx Endpoint index - @param [in] fEnable TRUE to enable, FALSE to disable - */ -static void USBHwEPEnable(int idx, BOOL fEnable) -{ - USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA); -} - - -/** - Configures an endpoint and enables it - - @param [in] bEP Endpoint number - @param [in] wMaxPacketSize Maximum packet size for this EP - */ -void USBHwEPConfig(U8 bEP, U16 wMaxPacketSize) -{ - int idx; - - idx = EP2IDX(bEP); - - // realise EP - USBHwEPRealize(idx, wMaxPacketSize); - - // enable EP - USBHwEPEnable(idx, TRUE); -} - - -/** - Registers an endpoint event callback - - @param [in] bEP Endpoint number - @param [in] pfnHandler Callback function - */ -void USBHwRegisterEPIntHandler(U8 bEP, TFnEPIntHandler *pfnHandler) -{ - int idx; - - idx = EP2IDX(bEP); - - ASSERT(idx<32); - - /* add handler to list of EP handlers */ - _apfnEPIntHandlers[idx / 2] = pfnHandler; - - /* enable EP interrupt */ - LPC_USB->USBEpIntEn |= (1 << idx); - LPC_USB->USBDevIntEn |= EP_SLOW; - - DBG("Registered handler for EP 0x%x\n", bEP); -} - - -/** - Registers an device status callback - - @param [in] pfnHandler Callback function - */ -void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler) -{ - _pfnDevIntHandler = pfnHandler; - - // enable device interrupt - LPC_USB->USBDevIntEn |= DEV_STAT; - - DBG("Registered handler for device status\n"); -} - - -/** - Registers the frame callback - - @param [in] pfnHandler Callback function - */ -void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler) -{ - _pfnFrameHandler = pfnHandler; - - // enable device interrupt - LPC_USB->USBDevIntEn |= FRAME; - - DBG("Registered handler for frame\n"); -} - - -/** - Sets the USB address. - - @param [in] bAddr Device address to set - */ -void USBHwSetAddress(U8 bAddr) -{ - USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr); -} - - -/** - Connects or disconnects from the USB bus - - @param [in] fConnect If TRUE, connect, otherwise disconnect - */ -void USBHwConnect(BOOL fConnect) -{ - USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0); -} - - -/** - Enables interrupt on NAK condition - - For IN endpoints a NAK is generated when the host wants to read data - from the device, but none is available in the endpoint buffer. - For OUT endpoints a NAK is generated when the host wants to write data - to the device, but the endpoint buffer is still full. - - The endpoint interrupt handlers can distinguish regular (ACK) interrupts - from NAK interrupt by checking the bits in their bEPStatus argument. - - @param [in] bIntBits Bitmap indicating which NAK interrupts to enable - */ -void USBHwNakIntEnable(U8 bIntBits) -{ - USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits); -} - - -/** - Gets the status from a specific endpoint. - - @param [in] bEP Endpoint number - @return Endpoint status byte (containing EP_STATUS_xxx bits) - */ -U8 USBHwEPGetStatus(U8 bEP) -{ - int idx = EP2IDX(bEP); - - return USBHwCmdRead(CMD_EP_SELECT | idx); -} - - -/** - Sets the stalled property of an endpoint - - @param [in] bEP Endpoint number - @param [in] fStall TRUE to stall, FALSE to unstall - */ -void USBHwEPStall(U8 bEP, BOOL fStall) -{ - int idx = EP2IDX(bEP); - - USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0); -} - - -/** - Writes data to an endpoint buffer - - @param [in] bEP Endpoint number - @param [in] pbBuf Endpoint data - @param [in] iLen Number of bytes to write - - @return TRUE if the data was successfully written or <0 in case of error. -*/ -int USBHwEPWrite(U8 bEP, U8 *pbBuf, int iLen) -{ - int idx; - - idx = EP2IDX(bEP); - - // set write enable for specific endpoint - LPC_USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2); - - // set packet length - LPC_USB->USBTxPLen = iLen; - - // write data - while (LPC_USB->USBCtrl & WR_EN) { - LPC_USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0]; - pbBuf += 4; - } - - // select endpoint and validate buffer - USBHwCmd(CMD_EP_SELECT | idx); - USBHwCmd(CMD_EP_VALIDATE_BUFFER); - - return iLen; -} - - -/** - Reads data from an endpoint buffer - - @param [in] bEP Endpoint number - @param [in] pbBuf Endpoint data - @param [in] iMaxLen Maximum number of bytes to read - - @return the number of bytes available in the EP (possibly more than iMaxLen), - or <0 in case of error. - */ -int USBHwEPRead(U8 bEP, U8 *pbBuf, int iMaxLen) -{ - int i, idx; - U32 dwData, dwLen; - - idx = EP2IDX(bEP); - - // set read enable bit for specific endpoint - LPC_USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2); - - // wait for PKT_RDY - do { - dwLen = LPC_USB->USBRxPLen; - } while ((dwLen & PKT_RDY) == 0); - - // packet valid? - if ((dwLen & DV) == 0) { - return -1; - } - - // get length - dwLen &= PKT_LNGTH_MASK; - - // get data - dwData = 0; - for (i = 0; i < dwLen; i++) { - if ((i % 4) == 0) { - dwData = LPC_USB->USBRxData; - } - if ((pbBuf != NULL) && (i < iMaxLen)) { - pbBuf[i] = dwData & 0xFF; - } - dwData >>= 8; - } - - // make sure RD_EN is clear - LPC_USB->USBCtrl = 0; - - // select endpoint and clear buffer - USBHwCmd(CMD_EP_SELECT | idx); - USBHwCmd(CMD_EP_CLEAR_BUFFER); - - return dwLen; -} - - -/** - Sets the 'configured' state. - - All registered endpoints are 'realised' and enabled, and the - 'configured' bit is set in the device status register. - - @param [in] fConfigured If TRUE, configure device, else unconfigure - */ -void USBHwConfigDevice(BOOL fConfigured) -{ - // set configured bit - USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0); -} - - -/** - USB interrupt handler - - @todo Get all 11 bits of frame number instead of just 8 - - Endpoint interrupts are mapped to the slow interrupt - */ -void USBHwISR(void) -{ - U32 dwStatus; - U32 dwIntBit; - U8 bEPStat, bDevStat, bStat; - int i; - U16 wFrame; - - // LED9 monitors total time in interrupt routine - DEBUG_LED_ON(6); - - // handle device interrupts - dwStatus = LPC_USB->USBDevIntSt; - - // frame interrupt - if (dwStatus & FRAME) { - // clear int - LPC_USB->USBDevIntClr = FRAME; - // call handler - if (_pfnFrameHandler != NULL) { - wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR); - _pfnFrameHandler(wFrame); - } - } - - // device status interrupt - if (dwStatus & DEV_STAT) { - /* Clear DEV_STAT interrupt before reading DEV_STAT register. - This prevents corrupted device status reads, see - LPC2148 User manual revision 2, 25 july 2006. - */ - LPC_USB->USBDevIntClr = DEV_STAT; - bDevStat = USBHwCmdRead(CMD_DEV_STATUS); - if (bDevStat & (CON_CH | SUS_CH | RST)) { - // convert device status into something HW independent - bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) | - ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) | - ((bDevStat & RST) ? DEV_STATUS_RESET : 0); - // call handler - if (_pfnDevIntHandler != NULL) { - DEBUG_LED_ON(5); - _pfnDevIntHandler(bStat); - DEBUG_LED_OFF(5); - } - } - } - - // endpoint interrupt - if (dwStatus & EP_SLOW) { - // clear EP_SLOW - LPC_USB->USBDevIntClr = EP_SLOW; - // check all endpoints - for (i = 0; i < 32; i++) { - dwIntBit = (1 << i); - if (LPC_USB->USBEpIntSt & dwIntBit) { - // clear int (and retrieve status) - LPC_USB->USBEpIntClr = dwIntBit; - Wait4DevInt(CDFULL); - bEPStat = LPC_USB->USBCmdData; - // convert EP pipe stat into something HW independent - bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) | - ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) | - ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | - ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | - ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0); - // call handler - if (_apfnEPIntHandlers[i / 2] != NULL) { - DEBUG_LED_ON(7); - _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); - DEBUG_LED_OFF(7); - } - } - } - } - - DEBUG_LED_OFF(6); -} - - - -/** - Initialises the USB hardware - - This function assumes that the hardware is connected as shown in - section 10.1 of the LPC2148 data sheet: - * P0.31 controls a switch to connect a 1.5k pull-up to D+ if low. - * P0.23 is connected to USB VCC. - - Embedded artists board: make sure to disconnect P0.23 LED as it - acts as a pull-up and so prevents detection of USB disconnect. - - @return TRUE if the hardware was successfully initialised - */ -BOOL USBHwInit(void) -{ -/* CodeRed - comment out original code - * - // configure P0.23 for Vbus sense - PINSEL1 = (PINSEL1 & ~(3 << 14)) | (1 << 14); // P0.23 - // configure P0.31 for CONNECT - PINSEL1 = (PINSEL1 & ~(3 << 30)) | (2 << 30); // P0.31 -*/ - - // CodeRed - set up USB pins - - // P2.9 -> USB_CONNECT - LPC_PINCON->PINSEL4 &= ~0x000C0000; - LPC_PINCON->PINSEL4 |= 0x00040000; - - // P1.18 -> USB_UP_LED - // P1.30 -> VBUS - LPC_PINCON->PINSEL3 &= ~0x30000030; - LPC_PINCON->PINSEL3 |= 0x20000010; - - // P0.29 -> USB_D+ - // P0.30 -> USB_D- - LPC_PINCON->PINSEL1 &= ~0x3C000000; - LPC_PINCON->PINSEL1 |= 0x14000000; - - - // enable PUSB - LPC_SC->PCONP |= (1 << 31); - -/* CodeRed - Comment out original PLL code - * PLL now set up by NXP code in target.c within example projects - * - // initialise PLL - PLL1CON = 1; // enable PLL - PLL1CFG = (1 << 5) | 3; // P = 2, M = 4 - PLL1FEED = 0xAA; - PLL1FEED = 0x55; - while ((PLL1STAT & (1 << 10)) == 0); - - PLL1CON = 3; // enable and connect - PLL1FEED = 0xAA; - PLL1FEED = 0x55; - -*/ - - -// AWB added USB clock enable -// These are actually the USBClkCtrl and USBClkSt registers -// OTG_CLK_CTRL = 0x12; /* Dev clock, AHB clock enable */ -// while ((OTG_CLK_STAT & 0x12) != 0x12); - - LPC_USB->USBClkCtrl = 0x1A; /* Dev clock, AHB clock enable */ - while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); - - - // disable/clear all interrupts for now - LPC_USB->USBDevIntEn = 0; - LPC_USB->USBDevIntClr = 0xFFFFFFFF; - LPC_USB->USBDevIntPri = 0; - - LPC_USB->USBEpIntEn = 0; - LPC_USB->USBEpIntClr = 0xFFFFFFFF; - LPC_USB->USBEpIntPri = 0; - - // by default, only ACKs generate interrupts - USBHwNakIntEnable(0); - - // CodeRed - commented out LEDs - not used by current port - // init debug leds - /* - DEBUG_LED_INIT(5); - DEBUG_LED_INIT(6); - DEBUG_LED_INIT(7); - */ - - return TRUE; -} - +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + USB hardware layer + */ + +#include "type.h" + +#include "usbdebug.h" +#include "usbhw_lpc.h" +#include "usbapi.h" +// Configure LED pin functions +// +// LED pin functions +// +// Function Pin Port Bits Pin Select Register +// ------------------- --- ----- ---- ------------------- +// P2.0 GPIO Port 2.0 xx P2.0 1:0 PINSEL4 +// P2.1 GPIO Port 2.1 xx P2.1 3:2 PINSEL4 +// P2.2 GPIO Port 2.2 xx P2.2 5:4 PINSEL4 +// P2.3 GPIO Port 2.3 xx P2.3 7:6 PINSEL4 +// P2.4 GPIO Port 2.4 xx P2.4 9:8 PINSEL4 +// P2.5 GPIO Port 2.5 xx P2.5 11:10 PINSEL4 +// P2.6 GPIO Port 2.6 xx P2.6 13:12 PINSEL4 +// P2.7 GPIO Port 2.7 xx P2.7 15:14 PINSEL4 +// +// OFF - LED state 0 +// ON - LED state 1 +// +// '*' as GPIO + +#define NO_LEDS 8 + +#define LED_0 (1 << 0) +#define LED_1 (1 << 1) +#define LED_2 (1 << 2) +#define LED_3 (1 << 3) +#define LED_4 (1 << 4) +#define LED_5 (1 << 5) +#define LED_6 (1 << 6) +#define LED_7 (1 << 7) + +#ifdef DEBUG +// comment out the following line if you don't want to use debug LEDs +//#define DEBUG_LED +#endif + +#ifdef DEBUG_LED +#define DEBUG_LED_ON(x) FIO2SET = (1 << x); +#define DEBUG_LED_OFF(x) FIO2CLR = (1 << x); +#define DEBUG_LED_INIT(x) PINSEL2 &= ~(0x3 << (2*x)); FIO2DIR |= (1 << x); DEBUG_LED_OFF(x); +#else +#define DEBUG_LED_INIT(x) /**< LED initialisation macro */ +#define DEBUG_LED_ON(x) /**< turn LED on */ +#define DEBUG_LED_OFF(x) /**< turn LED off */ +#endif + +/** Installed device interrupt handler */ +static TFnDevIntHandler *_pfnDevIntHandler = NULL; +/** Installed endpoint interrupt handlers */ +static TFnEPIntHandler *_apfnEPIntHandlers[16]; +/** Installed frame interrupt handlers */ +static TFnFrameHandler *_pfnFrameHandler = NULL; + +/** convert from endpoint address to endpoint index */ +#define EP2IDX(bEP) ((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7)) +/** convert from endpoint index to endpoint address */ +#define IDX2EP(idx) ((((idx)<<7)&0x80)|(((idx)>>1)&0xF)) + + + +/** + Local function to wait for a device interrupt (and clear it) + + @param [in] dwIntr Bitmask of interrupts to wait for + */ +static void Wait4DevInt(u32 dwIntr) +{ + // wait for specific interrupt + while ((LPC_USB->USBDevIntSt & dwIntr) != dwIntr); + // clear the interrupt bits + LPC_USB->USBDevIntClr = dwIntr; +} + + +/** + Local function to send a command to the USB protocol engine + + @param [in] bCmd Command to send + */ +static void USBHwCmd(u8 bCmd) +{ + // clear CDFULL/CCEMTY + LPC_USB->USBDevIntClr = CDFULL | CCEMTY; + // write command code + LPC_USB->USBCmdCode = 0x00000500 | (bCmd << 16); + Wait4DevInt(CCEMTY); +} + + +/** + Local function to send a command + data to the USB protocol engine + + @param [in] bCmd Command to send + @param [in] bData Data to send + */ +static void USBHwCmdWrite(u8 bCmd, u16 bData) +{ + // write command code + USBHwCmd(bCmd); + + // write command data + LPC_USB->USBCmdCode = 0x00000100 | (bData << 16); + Wait4DevInt(CCEMTY); +} + + +/** + Local function to send a command to the USB protocol engine and read data + + @param [in] bCmd Command to send + + @return the data + */ +static u8 USBHwCmdRead(u8 bCmd) +{ + // write command code + USBHwCmd(bCmd); + + // get data + LPC_USB->USBCmdCode = 0x00000200 | (bCmd << 16); + Wait4DevInt(CDFULL); + return LPC_USB->USBCmdData; +} + + +/** + 'Realizes' an endpoint, meaning that buffer space is reserved for + it. An endpoint needs to be realised before it can be used. + + From experiments, it appears that a USB reset causes USBReEP to + re-initialise to 3 (= just the control endpoints). + However, a USB bus reset does not disturb the USBMaxPSize settings. + + @param [in] idx Endpoint index + @param [in] wMaxPSize Maximum packet size for this endpoint + */ +static void USBHwEPRealize(int idx, u16 wMaxPSize) +{ + LPC_USB->USBReEP |= (1 << idx); + LPC_USB->USBEpInd = idx; + LPC_USB->USBMaxPSize = wMaxPSize; + Wait4DevInt(EP_RLZED); +} + + +/** + Enables or disables an endpoint + + @param [in] idx Endpoint index + @param [in] fEnable TRUE to enable, FALSE to disable + */ +static void USBHwEPEnable(int idx, BOOL fEnable) +{ + USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA); +} + + +/** + Configures an endpoint and enables it + + @param [in] bEP Endpoint number + @param [in] wMaxPacketSize Maximum packet size for this EP + */ +void USBHwEPConfig(u8 bEP, u16 wMaxPacketSize) +{ + int idx; + + idx = EP2IDX(bEP); + + // realise EP + USBHwEPRealize(idx, wMaxPacketSize); + + // enable EP + USBHwEPEnable(idx, TRUE); +} + + +/** + Registers an endpoint event callback + + @param [in] bEP Endpoint number + @param [in] pfnHandler Callback function + */ +void USBHwRegisterEPIntHandler(u8 bEP, TFnEPIntHandler *pfnHandler) +{ + int idx; + + idx = EP2IDX(bEP); + + ASSERT(idx<32); + + /* add handler to list of EP handlers */ + _apfnEPIntHandlers[idx / 2] = pfnHandler; + + /* enable EP interrupt */ + LPC_USB->USBEpIntEn |= (1 << idx); + LPC_USB->USBDevIntEn |= EP_SLOW; + + DBG("Registered handler for EP 0x%x\n", bEP); +} + + +/** + Registers an device status callback + + @param [in] pfnHandler Callback function + */ +void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler) +{ + _pfnDevIntHandler = pfnHandler; + + // enable device interrupt + LPC_USB->USBDevIntEn |= DEV_STAT; + + DBG("Registered handler for device status\n"); +} + + +/** + Registers the frame callback + + @param [in] pfnHandler Callback function + */ +void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler) +{ + _pfnFrameHandler = pfnHandler; + + // enable device interrupt + LPC_USB->USBDevIntEn |= FRAME; + + DBG("Registered handler for frame\n"); +} + + +/** + Sets the USB address. + + @param [in] bAddr Device address to set + */ +void USBHwSetAddress(u8 bAddr) +{ + USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr); +} + + +/** + Connects or disconnects from the USB bus + + @param [in] fConnect If TRUE, connect, otherwise disconnect + */ +void USBHwConnect(BOOL fConnect) +{ + USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0); +} + + +/** + Enables interrupt on NAK condition + + For IN endpoints a NAK is generated when the host wants to read data + from the device, but none is available in the endpoint buffer. + For OUT endpoints a NAK is generated when the host wants to write data + to the device, but the endpoint buffer is still full. + + The endpoint interrupt handlers can distinguish regular (ACK) interrupts + from NAK interrupt by checking the bits in their bEPStatus argument. + + @param [in] bIntBits Bitmap indicating which NAK interrupts to enable + */ +void USBHwNakIntEnable(u8 bIntBits) +{ + USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits); +} + + +/** + Gets the status from a specific endpoint. + + @param [in] bEP Endpoint number + @return Endpoint status byte (containing EP_STATUS_xxx bits) + */ +u8 USBHwEPGetStatus(u8 bEP) +{ + int idx = EP2IDX(bEP); + + return USBHwCmdRead(CMD_EP_SELECT | idx); +} + + +/** + Sets the stalled property of an endpoint + + @param [in] bEP Endpoint number + @param [in] fStall TRUE to stall, FALSE to unstall + */ +void USBHwEPStall(u8 bEP, BOOL fStall) +{ + int idx = EP2IDX(bEP); + + USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0); +} + + +/** + Writes data to an endpoint buffer + + @param [in] bEP Endpoint number + @param [in] pbBuf Endpoint data + @param [in] iLen Number of bytes to write + + @return TRUE if the data was successfully written or <0 in case of error. +*/ +int USBHwEPWrite(u8 bEP, u8 *pbBuf, int iLen) +{ + int idx; + + idx = EP2IDX(bEP); + + // set write enable for specific endpoint + LPC_USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2); + + // set packet length + LPC_USB->USBTxPLen = iLen; + + // write data + while (LPC_USB->USBCtrl & WR_EN) { + LPC_USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0]; + pbBuf += 4; + } + + // select endpoint and validate buffer + USBHwCmd(CMD_EP_SELECT | idx); + USBHwCmd(CMD_EP_VALIDATE_BUFFER); + + return iLen; +} + + +/** + Reads data from an endpoint buffer + + @param [in] bEP Endpoint number + @param [in] pbBuf Endpoint data + @param [in] iMaxLen Maximum number of bytes to read + + @return the number of bytes available in the EP (possibly more than iMaxLen), + or <0 in case of error. + */ +int USBHwEPRead(u8 bEP, u8 *pbBuf, int iMaxLen) +{ + int i, idx; + u32 dwData, dwLen; + + idx = EP2IDX(bEP); + + // set read enable bit for specific endpoint + LPC_USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2); + + // wait for PKT_RDY + do { + dwLen = LPC_USB->USBRxPLen; + } while ((dwLen & PKT_RDY) == 0); + + // packet valid? + if ((dwLen & DV) == 0) { + return -1; + } + + // get length + dwLen &= PKT_LNGTH_MASK; + + // get data + dwData = 0; + for (i = 0; i < dwLen; i++) { + if ((i % 4) == 0) { + dwData = LPC_USB->USBRxData; + } + if ((pbBuf != NULL) && (i < iMaxLen)) { + pbBuf[i] = dwData & 0xFF; + } + dwData >>= 8; + } + + // make sure RD_EN is clear + LPC_USB->USBCtrl = 0; + + // select endpoint and clear buffer + USBHwCmd(CMD_EP_SELECT | idx); + USBHwCmd(CMD_EP_CLEAR_BUFFER); + + return dwLen; +} + + +/** + Sets the 'configured' state. + + All registered endpoints are 'realised' and enabled, and the + 'configured' bit is set in the device status register. + + @param [in] fConfigured If TRUE, configure device, else unconfigure + */ +void USBHwConfigDevice(BOOL fConfigured) +{ + // set configured bit + USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0); +} + + +/** + USB interrupt handler + + @todo Get all 11 bits of frame number instead of just 8 + + Endpoint interrupts are mapped to the slow interrupt + */ +void USBHwISR(void) +{ + u32 dwStatus; + u32 dwIntBit; + u8 bEPStat, bDevStat, bStat; + int i; + u16 wFrame; + + // LED9 monitors total time in interrupt routine + DEBUG_LED_ON(6); + + // handle device interrupts + dwStatus = LPC_USB->USBDevIntSt; + + // frame interrupt + if (dwStatus & FRAME) { + // clear int + LPC_USB->USBDevIntClr = FRAME; + // call handler + if (_pfnFrameHandler != NULL) { + wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR); + _pfnFrameHandler(wFrame); + } + } + + // device status interrupt + if (dwStatus & DEV_STAT) { + /* Clear DEV_STAT interrupt before reading DEV_STAT register. + This prevents corrupted device status reads, see + LPC2148 User manual revision 2, 25 july 2006. + */ + LPC_USB->USBDevIntClr = DEV_STAT; + bDevStat = USBHwCmdRead(CMD_DEV_STATUS); + if (bDevStat & (CON_CH | SUS_CH | RST)) { + // convert device status into something HW independent + bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) | + ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) | + ((bDevStat & RST) ? DEV_STATUS_RESET : 0); + // call handler + if (_pfnDevIntHandler != NULL) { + DEBUG_LED_ON(5); + _pfnDevIntHandler(bStat); + DEBUG_LED_OFF(5); + } + } + } + + // endpoint interrupt + if (dwStatus & EP_SLOW) { + // clear EP_SLOW + LPC_USB->USBDevIntClr = EP_SLOW; + // check all endpoints + for (i = 0; i < 32; i++) { + dwIntBit = (1 << i); + if (LPC_USB->USBEpIntSt & dwIntBit) { + // clear int (and retrieve status) + LPC_USB->USBEpIntClr = dwIntBit; + Wait4DevInt(CDFULL); + bEPStat = LPC_USB->USBCmdData; + // convert EP pipe stat into something HW independent + bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) | + ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) | + ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) | + ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) | + ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0); + // call handler + if (_apfnEPIntHandlers[i / 2] != NULL) { + DEBUG_LED_ON(7); + _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); + DEBUG_LED_OFF(7); + } + } + } + } + + DEBUG_LED_OFF(6); +} + + + +/** + Initialises the USB hardware + + This function assumes that the hardware is connected as shown in + section 10.1 of the LPC2148 data sheet: + * P0.31 controls a switch to connect a 1.5k pull-up to D+ if low. + * P0.23 is connected to USB VCC. + + Embedded artists board: make sure to disconnect P0.23 LED as it + acts as a pull-up and so prevents detection of USB disconnect. + + @return TRUE if the hardware was successfully initialised + */ +BOOL USBHwInit(void) +{ +/* CodeRed - comment out original code + * + // configure P0.23 for Vbus sense + PINSEL1 = (PINSEL1 & ~(3 << 14)) | (1 << 14); // P0.23 + // configure P0.31 for CONNECT + PINSEL1 = (PINSEL1 & ~(3 << 30)) | (2 << 30); // P0.31 +*/ + + // CodeRed - set up USB pins + + // P2.9 -> USB_CONNECT + LPC_PINCON->PINSEL4 &= ~0x000C0000; + LPC_PINCON->PINSEL4 |= 0x00040000; + + // P1.18 -> USB_UP_LED + // P1.30 -> VBUS + LPC_PINCON->PINSEL3 &= ~0x30000030; + LPC_PINCON->PINSEL3 |= 0x20000010; + + // P0.29 -> USB_D+ + // P0.30 -> USB_D- + LPC_PINCON->PINSEL1 &= ~0x3C000000; + LPC_PINCON->PINSEL1 |= 0x14000000; + + + // enable PUSB + LPC_SC->PCONP |= (1 << 31); + +/* CodeRed - Comment out original PLL code + * PLL now set up by NXP code in target.c within example projects + * + // initialise PLL + PLL1CON = 1; // enable PLL + PLL1CFG = (1 << 5) | 3; // P = 2, M = 4 + PLL1FEED = 0xAA; + PLL1FEED = 0x55; + while ((PLL1STAT & (1 << 10)) == 0); + + PLL1CON = 3; // enable and connect + PLL1FEED = 0xAA; + PLL1FEED = 0x55; + +*/ + + +// AWB added USB clock enable +// These are actually the USBClkCtrl and USBClkSt registers +// OTG_CLK_CTRL = 0x12; /* Dev clock, AHB clock enable */ +// while ((OTG_CLK_STAT & 0x12) != 0x12); + + LPC_USB->USBClkCtrl = 0x1A; /* Dev clock, AHB clock enable */ + while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); + + + // disable/clear all interrupts for now + LPC_USB->USBDevIntEn = 0; + LPC_USB->USBDevIntClr = 0xFFFFFFFF; + LPC_USB->USBDevIntPri = 0; + + LPC_USB->USBEpIntEn = 0; + LPC_USB->USBEpIntClr = 0xFFFFFFFF; + LPC_USB->USBEpIntPri = 0; + + // by default, only ACKs generate interrupts + USBHwNakIntEnable(0); + + // CodeRed - commented out LEDs - not used by current port + // init debug leds + /* + DEBUG_LED_INIT(5); + DEBUG_LED_INIT(6); + DEBUG_LED_INIT(7); + */ + + return TRUE; +} diff --git a/src/platform/lpc17xx/usbstack/src/usbinit.c b/src/platform/lpc17xx/usbstack/src/usbinit.c index 90b9341d..41ea93fc 100644 --- a/src/platform/lpc17xx/usbstack/src/usbinit.c +++ b/src/platform/lpc17xx/usbstack/src/usbinit.c @@ -1,5 +1,5 @@ /* - LPCUSB, an USB device driver for LPC microcontrollers + LPCUSB, an USB device driver for LPC microcontrollers Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) Redistribution and use in source and binary forms, with or without @@ -16,7 +16,7 @@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @@ -30,24 +30,22 @@ USB stack initialisation */ -// CodeRed - include the LPCUSB type.h file rather than NXP one directly -//#include "type.h" -#include "lpcusb_type.h" +#include "type.h" #include "usbdebug.h" #include "usbapi.h" /** data storage area for standard requests */ -static U8 abStdReqData[8]; +static u8 abStdReqData[8]; /** USB reset handler - + @param [in] bDevStatus Device status */ -static void HandleUsbReset(U8 bDevStatus) +static void HandleUsbReset(u8 bDevStatus) { if (bDevStatus & DEV_STATUS_RESET) { DBG("\n!"); @@ -58,28 +56,27 @@ static void HandleUsbReset(U8 bDevStatus) /** Initialises the USB hardware and sets up the USB stack by installing default callbacks. - + @return TRUE if initialisation was successful */ BOOL USBInit(void) { // init hardware USBHwInit(); - + // register bus reset handler USBHwRegisterDevIntHandler(HandleUsbReset); - + // register control transfer handler on EP0 USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer); USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer); - + // setup control endpoints USBHwEPConfig(0x00, MAX_PACKET_SIZE0); USBHwEPConfig(0x80, MAX_PACKET_SIZE0); - + // register standard request handler USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData); return TRUE; } - diff --git a/src/platform/lpc17xx/usbstack/src/usbstdreq.c b/src/platform/lpc17xx/usbstack/src/usbstdreq.c index 5b159002..981cea8e 100644 --- a/src/platform/lpc17xx/usbstack/src/usbstdreq.c +++ b/src/platform/lpc17xx/usbstack/src/usbstdreq.c @@ -1,434 +1,431 @@ -/* - LPCUSB, an USB device driver for LPC microcontrollers - Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/** @file - Standard request handler. - - This modules handles the 'chapter 9' processing, specifically the - standard device requests in table 9-3 from the universal serial bus - specification revision 2.0 - - Specific types of devices may specify additional requests (for example - HID devices add a GET_DESCRIPTOR request for interfaces), but they - will not be part of this module. - - @todo some requests have to return a request error if device not configured: - @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME - @todo this applies to the following if endpoint != 0: - @todo SET_FEATURE, GET_FEATURE -*/ - -// CodeRed - include the LPCUSB type.h file rather than NXP one directly -//#include "type.h" -#include "lpcusb_type.h" - -#include "usbdebug.h" -#include "usbstruct.h" -#include "usbapi.h" - -#define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */ - - -/* general descriptor field offsets */ -#define DESC_bLength 0 /**< length offset */ -#define DESC_bDescriptorType 1 /**< descriptor type offset */ - -/* config descriptor field offsets */ -#define CONF_DESC_wTotalLength 2 /**< total length offset */ -#define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */ -#define CONF_DESC_bmAttributes 7 /**< configuration characteristics */ - -/* interface descriptor field offsets */ -#define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */ - -/* endpoint descriptor field offsets */ -#define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */ -#define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */ - - -/** Currently selected configuration */ -static U8 bConfiguration = 0; -/** Installed custom request handler */ -static TFnHandleRequest *pfnHandleCustomReq = NULL; -/** Pointer to registered descriptors */ -static const U8 *pabDescrip = NULL; - - -/** - Registers a pointer to a descriptor block containing all descriptors - for the device. - - @param [in] pabDescriptors The descriptor byte array - */ -void USBRegisterDescriptors(const U8 *pabDescriptors) -{ - pabDescrip = pabDescriptors; -} - - -/** - Parses the list of installed USB descriptors and attempts to find - the specified USB descriptor. - - @param [in] wTypeIndex Type and index of the descriptor - @param [in] wLangID Language ID of the descriptor (currently unused) - @param [out] *piLen Descriptor length - @param [out] *ppbData Descriptor data - - @return TRUE if the descriptor was found, FALSE otherwise - */ -BOOL USBGetDescriptor(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData) -{ - U8 bType, bIndex; - U8 *pab; - int iCurIndex; - - ASSERT(pabDescrip != NULL); - - bType = GET_DESC_TYPE(wTypeIndex); - bIndex = GET_DESC_INDEX(wTypeIndex); - - pab = (U8 *)pabDescrip; - iCurIndex = 0; - - while (pab[DESC_bLength] != 0) { - if (pab[DESC_bDescriptorType] == bType) { - if (iCurIndex == bIndex) { - // set data pointer - *ppbData = pab; - // get length from structure - if (bType == DESC_CONFIGURATION) { - // configuration descriptor is an exception, length is at offset 2 and 3 - *piLen = (pab[CONF_DESC_wTotalLength]) | - (pab[CONF_DESC_wTotalLength + 1] << 8); - } - else { - // normally length is at offset 0 - *piLen = pab[DESC_bLength]; - } - return TRUE; - } - iCurIndex++; - } - // skip to next descriptor - pab += pab[DESC_bLength]; - } - // nothing found - DBG("Desc %x not found!\n", wTypeIndex); - return FALSE; -} - - -/** - Configures the device according to the specified configuration index and - alternate setting by parsing the installed USB descriptor list. - A configuration index of 0 unconfigures the device. - - @param [in] bConfigIndex Configuration index - @param [in] bAltSetting Alternate setting number - - @todo function always returns TRUE, add stricter checking? - - @return TRUE if successfully configured, FALSE otherwise - */ -static BOOL USBSetConfiguration(U8 bConfigIndex, U8 bAltSetting) -{ - U8 *pab; - U8 bCurConfig, bCurAltSetting; - U8 bEP; - U16 wMaxPktSize; - - ASSERT(pabDescrip != NULL); - - if (bConfigIndex == 0) { - // unconfigure device - USBHwConfigDevice(FALSE); - } - else { - // configure endpoints for this configuration/altsetting - pab = (U8 *)pabDescrip; - bCurConfig = 0xFF; - bCurAltSetting = 0xFF; - - while (pab[DESC_bLength] != 0) { - - switch (pab[DESC_bDescriptorType]) { - - case DESC_CONFIGURATION: - // remember current configuration index - bCurConfig = pab[CONF_DESC_bConfigurationValue]; - break; - - case DESC_INTERFACE: - // remember current alternate setting - bCurAltSetting = pab[INTF_DESC_bAlternateSetting]; - break; - - case DESC_ENDPOINT: - if ((bCurConfig == bConfigIndex) && - (bCurAltSetting == bAltSetting)) { - // endpoint found for desired config and alternate setting - bEP = pab[ENDP_DESC_bEndpointAddress]; - wMaxPktSize = (pab[ENDP_DESC_wMaxPacketSize]) | - (pab[ENDP_DESC_wMaxPacketSize + 1] << 8); - // configure endpoint - USBHwEPConfig(bEP, wMaxPktSize); - } - break; - - default: - break; - } - // skip to next descriptor - pab += pab[DESC_bLength]; - } - - // configure device - USBHwConfigDevice(TRUE); - } - - return TRUE; -} - - -/** - Local function to handle a standard device request - - @param [in] pSetup The setup packet - @param [in,out] *piLen Pointer to data length - @param [in,out] ppbData Data buffer. - - @return TRUE if the request was handled successfully - */ -static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) -{ - U8 *pbData = *ppbData; - - switch (pSetup->bRequest) { - - case REQ_GET_STATUS: - // bit 0: self-powered - // bit 1: remote wakeup = not supported - pbData[0] = 0; - pbData[1] = 0; - *piLen = 2; - break; - - case REQ_SET_ADDRESS: - USBHwSetAddress(pSetup->wValue); - break; - - case REQ_GET_DESCRIPTOR: - DBG("D%x", pSetup->wValue); - return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData); - - case REQ_GET_CONFIGURATION: - // indicate if we are configured - pbData[0] = bConfiguration; - *piLen = 1; - break; - - case REQ_SET_CONFIGURATION: - if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) { - DBG("USBSetConfiguration failed!\n"); - return FALSE; - } - // configuration successful, update current configuration - bConfiguration = pSetup->wValue & 0xFF; - break; - - case REQ_CLEAR_FEATURE: - case REQ_SET_FEATURE: - if (pSetup->wValue == FEA_REMOTE_WAKEUP) { - // put DEVICE_REMOTE_WAKEUP code here - } - if (pSetup->wValue == FEA_TEST_MODE) { - // put TEST_MODE code here - } - return FALSE; - - case REQ_SET_DESCRIPTOR: - DBG("Device req %d not implemented\n", pSetup->bRequest); - return FALSE; - - default: - DBG("Illegal device req %d\n", pSetup->bRequest); - return FALSE; - } - - return TRUE; -} - - -/** - Local function to handle a standard interface request - - @param [in] pSetup The setup packet - @param [in,out] *piLen Pointer to data length - @param [in] ppbData Data buffer. - - @return TRUE if the request was handled successfully - */ -static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) -{ - U8 *pbData = *ppbData; - - switch (pSetup->bRequest) { - - case REQ_GET_STATUS: - // no bits specified - pbData[0] = 0; - pbData[1] = 0; - *piLen = 2; - break; - - case REQ_CLEAR_FEATURE: - case REQ_SET_FEATURE: - // not defined for interface - return FALSE; - - case REQ_GET_INTERFACE: // TODO use bNumInterfaces - // there is only one interface, return n-1 (= 0) - pbData[0] = 0; - *piLen = 1; - break; - - case REQ_SET_INTERFACE: // TODO use bNumInterfaces - // there is only one interface (= 0) - if (pSetup->wValue != 0) { - return FALSE; - } - *piLen = 0; - break; - - default: - DBG("Illegal interface req %d\n", pSetup->bRequest); - return FALSE; - } - - return TRUE; -} - - -/** - Local function to handle a standard endpoint request - - @param [in] pSetup The setup packet - @param [in,out] *piLen Pointer to data length - @param [in] ppbData Data buffer. - - @return TRUE if the request was handled successfully - */ -static BOOL HandleStdEndPointReq(TSetupPacket *pSetup, int *piLen, U8 **ppbData) -{ - U8 *pbData = *ppbData; - - switch (pSetup->bRequest) { - case REQ_GET_STATUS: - // bit 0 = endpointed halted or not - pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0; - pbData[1] = 0; - *piLen = 2; - break; - - case REQ_CLEAR_FEATURE: - if (pSetup->wValue == FEA_ENDPOINT_HALT) { - // clear HALT by unstalling - USBHwEPStall(pSetup->wIndex, FALSE); - break; - } - // only ENDPOINT_HALT defined for endpoints - return FALSE; - - case REQ_SET_FEATURE: - if (pSetup->wValue == FEA_ENDPOINT_HALT) { - // set HALT by stalling - USBHwEPStall(pSetup->wIndex, TRUE); - break; - } - // only ENDPOINT_HALT defined for endpoints - return FALSE; - - case REQ_SYNCH_FRAME: - DBG("EP req %d not implemented\n", pSetup->bRequest); - return FALSE; - - default: - DBG("Illegal EP req %d\n", pSetup->bRequest); - return FALSE; - } - - return TRUE; -} - - -/** - Default handler for standard ('chapter 9') requests - - If a custom request handler was installed, this handler is called first. - - @param [in] pSetup The setup packet - @param [in,out] *piLen Pointer to data length - @param [in] ppbData Data buffer. - - @return TRUE if the request was handled successfully - */ -BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData) -{ - // try the custom request handler first - if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) { - return TRUE; - } - - switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) { - case REQTYPE_RECIP_DEVICE: return HandleStdDeviceReq(pSetup, piLen, ppbData); - case REQTYPE_RECIP_INTERFACE: return HandleStdInterfaceReq(pSetup, piLen, ppbData); - case REQTYPE_RECIP_ENDPOINT: return HandleStdEndPointReq(pSetup, piLen, ppbData); - default: return FALSE; - } -} - - -/** - Registers a callback for custom device requests - - In USBHandleStandardRequest, the custom request handler gets a first - chance at handling the request before it is handed over to the 'chapter 9' - request handler. - - This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR - request is sent to an interface, which is not covered by the 'chapter 9' - specification. - - @param [in] pfnHandler Callback function pointer - */ -void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler) -{ - pfnHandleCustomReq = pfnHandler; -} - +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/** @file + Standard request handler. + + This modules handles the 'chapter 9' processing, specifically the + standard device requests in table 9-3 from the universal serial bus + specification revision 2.0 + + Specific types of devices may specify additional requests (for example + HID devices add a GET_DESCRIPTOR request for interfaces), but they + will not be part of this module. + + @todo some requests have to return a request error if device not configured: + @todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME + @todo this applies to the following if endpoint != 0: + @todo SET_FEATURE, GET_FEATURE +*/ + +#include "type.h" + +#include "usbdebug.h" +#include "usbstruct.h" +#include "usbapi.h" + +#define MAX_DESC_HANDLERS 4 /**< device, interface, endpoint, other */ + + +/* general descriptor field offsets */ +#define DESC_bLength 0 /**< length offset */ +#define DESC_bDescriptorType 1 /**< descriptor type offset */ + +/* config descriptor field offsets */ +#define CONF_DESC_wTotalLength 2 /**< total length offset */ +#define CONF_DESC_bConfigurationValue 5 /**< configuration value offset */ +#define CONF_DESC_bmAttributes 7 /**< configuration characteristics */ + +/* interface descriptor field offsets */ +#define INTF_DESC_bAlternateSetting 3 /**< alternate setting offset */ + +/* endpoint descriptor field offsets */ +#define ENDP_DESC_bEndpointAddress 2 /**< endpoint address offset */ +#define ENDP_DESC_wMaxPacketSize 4 /**< maximum packet size offset */ + + +/** Currently selected configuration */ +static u8 bConfiguration = 0; +/** Installed custom request handler */ +static TFnHandleRequest *pfnHandleCustomReq = NULL; +/** Pointer to registered descriptors */ +static const u8 *pabDescrip = NULL; + + +/** + Registers a pointer to a descriptor block containing all descriptors + for the device. + + @param [in] pabDescriptors The descriptor byte array + */ +void USBRegisterDescriptors(const u8 *pabDescriptors) +{ + pabDescrip = pabDescriptors; +} + + +/** + Parses the list of installed USB descriptors and attempts to find + the specified USB descriptor. + + @param [in] wTypeIndex Type and index of the descriptor + @param [in] wLangID Language ID of the descriptor (currently unused) + @param [out] *piLen Descriptor length + @param [out] *ppbData Descriptor data + + @return TRUE if the descriptor was found, FALSE otherwise + */ +BOOL USBGetDescriptor(u16 wTypeIndex, u16 wLangID, int *piLen, u8 **ppbData) +{ + u8 bType, bIndex; + u8 *pab; + int iCurIndex; + + ASSERT(pabDescrip != NULL); + + bType = GET_DESC_TYPE(wTypeIndex); + bIndex = GET_DESC_INDEX(wTypeIndex); + + pab = (u8 *)pabDescrip; + iCurIndex = 0; + + while (pab[DESC_bLength] != 0) { + if (pab[DESC_bDescriptorType] == bType) { + if (iCurIndex == bIndex) { + // set data pointer + *ppbData = pab; + // get length from structure + if (bType == DESC_CONFIGURATION) { + // configuration descriptor is an exception, length is at offset 2 and 3 + *piLen = (pab[CONF_DESC_wTotalLength]) | + (pab[CONF_DESC_wTotalLength + 1] << 8); + } + else { + // normally length is at offset 0 + *piLen = pab[DESC_bLength]; + } + return TRUE; + } + iCurIndex++; + } + // skip to next descriptor + pab += pab[DESC_bLength]; + } + // nothing found + DBG("Desc %x not found!\n", wTypeIndex); + return FALSE; +} + + +/** + Configures the device according to the specified configuration index and + alternate setting by parsing the installed USB descriptor list. + A configuration index of 0 unconfigures the device. + + @param [in] bConfigIndex Configuration index + @param [in] bAltSetting Alternate setting number + + @todo function always returns TRUE, add stricter checking? + + @return TRUE if successfully configured, FALSE otherwise + */ +static BOOL USBSetConfiguration(u8 bConfigIndex, u8 bAltSetting) +{ + u8 *pab; + u8 bCurConfig, bCurAltSetting; + u8 bEP; + u16 wMaxPktSize; + + ASSERT(pabDescrip != NULL); + + if (bConfigIndex == 0) { + // unconfigure device + USBHwConfigDevice(FALSE); + } + else { + // configure endpoints for this configuration/altsetting + pab = (u8 *)pabDescrip; + bCurConfig = 0xFF; + bCurAltSetting = 0xFF; + + while (pab[DESC_bLength] != 0) { + + switch (pab[DESC_bDescriptorType]) { + + case DESC_CONFIGURATION: + // remember current configuration index + bCurConfig = pab[CONF_DESC_bConfigurationValue]; + break; + + case DESC_INTERFACE: + // remember current alternate setting + bCurAltSetting = pab[INTF_DESC_bAlternateSetting]; + break; + + case DESC_ENDPOINT: + if ((bCurConfig == bConfigIndex) && + (bCurAltSetting == bAltSetting)) { + // endpoint found for desired config and alternate setting + bEP = pab[ENDP_DESC_bEndpointAddress]; + wMaxPktSize = (pab[ENDP_DESC_wMaxPacketSize]) | + (pab[ENDP_DESC_wMaxPacketSize + 1] << 8); + // configure endpoint + USBHwEPConfig(bEP, wMaxPktSize); + } + break; + + default: + break; + } + // skip to next descriptor + pab += pab[DESC_bLength]; + } + + // configure device + USBHwConfigDevice(TRUE); + } + + return TRUE; +} + + +/** + Local function to handle a standard device request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in,out] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, u8 **ppbData) +{ + u8 *pbData = *ppbData; + + switch (pSetup->bRequest) { + + case REQ_GET_STATUS: + // bit 0: self-powered + // bit 1: remote wakeup = not supported + pbData[0] = 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_SET_ADDRESS: + USBHwSetAddress(pSetup->wValue); + break; + + case REQ_GET_DESCRIPTOR: + DBG("D%x", pSetup->wValue); + return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData); + + case REQ_GET_CONFIGURATION: + // indicate if we are configured + pbData[0] = bConfiguration; + *piLen = 1; + break; + + case REQ_SET_CONFIGURATION: + if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) { + DBG("USBSetConfiguration failed!\n"); + return FALSE; + } + // configuration successful, update current configuration + bConfiguration = pSetup->wValue & 0xFF; + break; + + case REQ_CLEAR_FEATURE: + case REQ_SET_FEATURE: + if (pSetup->wValue == FEA_REMOTE_WAKEUP) { + // put DEVICE_REMOTE_WAKEUP code here + } + if (pSetup->wValue == FEA_TEST_MODE) { + // put TEST_MODE code here + } + return FALSE; + + case REQ_SET_DESCRIPTOR: + DBG("Device req %d not implemented\n", pSetup->bRequest); + return FALSE; + + default: + DBG("Illegal device req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Local function to handle a standard interface request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdInterfaceReq(TSetupPacket *pSetup, int *piLen, u8 **ppbData) +{ + u8 *pbData = *ppbData; + + switch (pSetup->bRequest) { + + case REQ_GET_STATUS: + // no bits specified + pbData[0] = 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_CLEAR_FEATURE: + case REQ_SET_FEATURE: + // not defined for interface + return FALSE; + + case REQ_GET_INTERFACE: // TODO use bNumInterfaces + // there is only one interface, return n-1 (= 0) + pbData[0] = 0; + *piLen = 1; + break; + + case REQ_SET_INTERFACE: // TODO use bNumInterfaces + // there is only one interface (= 0) + if (pSetup->wValue != 0) { + return FALSE; + } + *piLen = 0; + break; + + default: + DBG("Illegal interface req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Local function to handle a standard endpoint request + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +static BOOL HandleStdEndPointReq(TSetupPacket *pSetup, int *piLen, u8 **ppbData) +{ + u8 *pbData = *ppbData; + + switch (pSetup->bRequest) { + case REQ_GET_STATUS: + // bit 0 = endpointed halted or not + pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0; + pbData[1] = 0; + *piLen = 2; + break; + + case REQ_CLEAR_FEATURE: + if (pSetup->wValue == FEA_ENDPOINT_HALT) { + // clear HALT by unstalling + USBHwEPStall(pSetup->wIndex, FALSE); + break; + } + // only ENDPOINT_HALT defined for endpoints + return FALSE; + + case REQ_SET_FEATURE: + if (pSetup->wValue == FEA_ENDPOINT_HALT) { + // set HALT by stalling + USBHwEPStall(pSetup->wIndex, TRUE); + break; + } + // only ENDPOINT_HALT defined for endpoints + return FALSE; + + case REQ_SYNCH_FRAME: + DBG("EP req %d not implemented\n", pSetup->bRequest); + return FALSE; + + default: + DBG("Illegal EP req %d\n", pSetup->bRequest); + return FALSE; + } + + return TRUE; +} + + +/** + Default handler for standard ('chapter 9') requests + + If a custom request handler was installed, this handler is called first. + + @param [in] pSetup The setup packet + @param [in,out] *piLen Pointer to data length + @param [in] ppbData Data buffer. + + @return TRUE if the request was handled successfully + */ +BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData) +{ + // try the custom request handler first + if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) { + return TRUE; + } + + switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) { + case REQTYPE_RECIP_DEVICE: return HandleStdDeviceReq(pSetup, piLen, ppbData); + case REQTYPE_RECIP_INTERFACE: return HandleStdInterfaceReq(pSetup, piLen, ppbData); + case REQTYPE_RECIP_ENDPOINT: return HandleStdEndPointReq(pSetup, piLen, ppbData); + default: return FALSE; + } +} + + +/** + Registers a callback for custom device requests + + In USBHandleStandardRequest, the custom request handler gets a first + chance at handling the request before it is handed over to the 'chapter 9' + request handler. + + This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR + request is sent to an interface, which is not covered by the 'chapter 9' + specification. + + @param [in] pfnHandler Callback function pointer + */ +void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler) +{ + pfnHandleCustomReq = pfnHandler; +} From 39c45210135705ebbdfcf6629563dcef256f2402 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 23 Apr 2015 23:34:09 +0200 Subject: [PATCH 20/26] Make sure everything compiles, is nicely dependent on USB CDC activation in board config. --- boards/known/lpcxpresso.lua | 1 + src/platform/lpc17xx/build_config.lua | 2 + .../lpc17xx/drivers/src/lpc17xx_usb_cdc.c | 479 ++++++++++++++++++ src/platform/lpc17xx/platform.c | 8 + src/platform/lpc17xx/usbstack/inc/usbapi.h | 241 +++++---- src/platform/lpc17xx/usbstack/inc/usbdebug.h | 14 +- src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h | 12 +- src/platform/lpc17xx/usbstack/inc/usbstruct.h | 24 +- .../lpc17xx/usbstack/src/usbcontrol.c | 11 +- src/platform/lpc17xx/usbstack/src/usbhw_lpc.c | 5 + src/platform/lpc17xx/usbstack/src/usbinit.c | 5 + src/platform/lpc17xx/usbstack/src/usbstdreq.c | 5 + 12 files changed, 649 insertions(+), 158 deletions(-) create mode 100644 src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index 3a290c8d..d55eb67b 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -6,6 +6,7 @@ return { sercon = { uart = 3, speed = 115200 }, romfs = true, shell = true, + cdc = true, term = { lines = 25, cols = 80 }, linenoise = { shell_lines = 10, lua_lines = 50 }, rpc = { uart = 0, speed = 115200 }, diff --git a/src/platform/lpc17xx/build_config.lua b/src/platform/lpc17xx/build_config.lua index a1fe77ea..f04b2c48 100644 --- a/src/platform/lpc17xx/build_config.lua +++ b/src/platform/lpc17xx/build_config.lua @@ -3,10 +3,12 @@ module( ..., package.seeall ) local at = require "attributes" +local comps = require "components" -- Add specific components to the 'components' table function add_platform_components( t, board, cpu ) t.lpc17xx_semifs = { macro = "BUILD_SEMIFS" } + t.cdc = comps.cdc_uart() end -- Add specific configuration to the 'configs' table diff --git a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c new file mode 100644 index 00000000..726eceb3 --- /dev/null +++ b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c @@ -0,0 +1,479 @@ +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "platform_conf.h" + +#ifdef BUILD_USB_CDC + +#include +#include // memcpy + +#include "LPC17xx.h" +#include "type.h" + +#include "usbapi.h" +#include "usbdebug.h" + +#ifdef CDC_BUF_SIZE + #define VCOM_FIFO_SIZE (1<head = 0; + fifo->tail = 0; + fifo->buf = buf; +} + + +BOOL fifo_put(fifo_t *fifo, u8 c) +{ + int next; + + // check if FIFO has room + next = (fifo->head + 1) % VCOM_FIFO_SIZE; + if (next == fifo->tail) { + // full + return FALSE; + } + + fifo->buf[fifo->head] = c; + fifo->head = next; + + return TRUE; +} + + +BOOL fifo_get(fifo_t *fifo, u8 *pc) +{ + int next; + + // check if FIFO has data + if (fifo->head == fifo->tail) { + return FALSE; + } + + next = (fifo->tail + 1) % VCOM_FIFO_SIZE; + + *pc = fifo->buf[fifo->tail]; + fifo->tail = next; + + return TRUE; +} + + +int fifo_avail(fifo_t *fifo) +{ + return (VCOM_FIFO_SIZE + fifo->head - fifo->tail) % VCOM_FIFO_SIZE; +} + + +int fifo_free(fifo_t *fifo) +{ + return (VCOM_FIFO_SIZE - 1 - fifo_avail(fifo)); +} + + + + +#define BAUD_RATE 115200 + +#define INT_IN_EP 0x81 +#define BULK_OUT_EP 0x05 +#define BULK_IN_EP 0x82 + +#define MAX_PACKET_SIZE 64 + +#define LE_WORD(x) ((x)&0xFF),((x)>>8) + +// CDC definitions +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +// data structure for GET_LINE_CODING / SET_LINE_CODING class requests +typedef struct { + u32 dwDTERate; + u8 bCharFormat; + u8 bParityType; + u8 bDataBits; +} TLineCoding; + +static TLineCoding LineCoding = {115200, 0, 0, 8}; +static u8 abBulkBuf[64]; +static u8 abClassReqData[8]; + +static u8 txdata[VCOM_FIFO_SIZE]; +static u8 rxdata[VCOM_FIFO_SIZE]; + +static fifo_t txfifo; +static fifo_t rxfifo; + +// forward declaration of interrupt handler +void USBIntHandler(void); + +static const u8 abDescriptors[] = { + +// device descriptor + 0x12, + DESC_DEVICE, + LE_WORD(0x0101), // bcdUSB + 0x02, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + MAX_PACKET_SIZE0, // bMaxPacketSize + LE_WORD(0xFFFF), // idVendor + LE_WORD(0x0005), // idProduct + LE_WORD(0x0100), // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x03, // iSerialNumber + 0x01, // bNumConfigurations + +// configuration descriptor + 0x09, + DESC_CONFIGURATION, + LE_WORD(67), // wTotalLength + 0x02, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0xC0, // bmAttributes + 0x32, // bMaxPower +// control class interface + 0x09, + DESC_INTERFACE, + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndPoints + 0x02, // bInterfaceClass + 0x02, // bInterfaceSubClass + 0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module + 0x00, // iInterface +// header functional descriptor + 0x05, + CS_INTERFACE, + 0x00, + LE_WORD(0x0110), +// call management functional descriptor + 0x05, + CS_INTERFACE, + 0x01, + 0x01, // bmCapabilities = device handles call management + 0x01, // bDataInterface +// ACM functional descriptor + 0x04, + CS_INTERFACE, + 0x02, + 0x02, // bmCapabilities +// union functional descriptor + 0x05, + CS_INTERFACE, + 0x06, + 0x00, // bMasterInterface + 0x01, // bSlaveInterface0 +// notification EP + 0x07, + DESC_ENDPOINT, + INT_IN_EP, // bEndpointAddress + 0x03, // bmAttributes = intr + LE_WORD(8), // wMaxPacketSize + 0x0A, // bInterval +// data class interface descriptor + 0x09, + DESC_INTERFACE, + 0x01, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndPoints + 0x0A, // bInterfaceClass = data + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface +// data EP OUT + 0x07, + DESC_ENDPOINT, + BULK_OUT_EP, // bEndpointAddress + 0x02, // bmAttributes = bulk + LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize + 0x00, // bInterval +// data EP in + 0x07, + DESC_ENDPOINT, + BULK_IN_EP, // bEndpointAddress + 0x02, // bmAttributes = bulk + LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize + 0x00, // bInterval + + // string descriptors + 0x04, + DESC_STRING, + LE_WORD(0x0409), + + 0x0E, + DESC_STRING, + 'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0, + + 0x14, + DESC_STRING, + 'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0, + + 0x12, + DESC_STRING, + 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0, + +// terminating zero + 0 +}; + + +/** + Local function to handle incoming bulk data + + @param [in] bEP + @param [in] bEPStatus + */ +static void BulkOut(u8 bEP, u8 bEPStatus) +{ + int i, iLen; + + if (fifo_free(&rxfifo) < MAX_PACKET_SIZE) { + // may not fit into fifo + return; + } + + // get data from USB into intermediate buffer + iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf)); + for (i = 0; i < iLen; i++) { + // put into FIFO + if (!fifo_put(&rxfifo, abBulkBuf[i])) { + // overflow... :( + ASSERT(FALSE); + break; + } + } +} + + +/** + Local function to handle outgoing bulk data + + @param [in] bEP + @param [in] bEPStatus + */ +static void BulkIn(u8 bEP, u8 bEPStatus) +{ + int i, iLen; + + if (fifo_avail(&txfifo) == 0) { + // no more data, disable further NAK interrupts until next USB frame + USBHwNakIntEnable(0); + return; + } + + // get bytes from transmit FIFO into intermediate buffer + for (i = 0; i < MAX_PACKET_SIZE; i++) { + if (!fifo_get(&txfifo, &abBulkBuf[i])) { + break; + } + } + iLen = i; + + // send over USB + if (iLen > 0) { + USBHwEPWrite(bEP, abBulkBuf, iLen); + } +} + + +/** + Local function to handle the USB-CDC class requests + + @param [in] pSetup + @param [out] piLen + @param [out] ppbData + */ +static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData) +{ + switch (pSetup->bRequest) { + + // set line coding + case SET_LINE_CODING: +DBG("SET_LINE_CODING\n"); + memcpy((u8 *)&LineCoding, *ppbData, 7); + *piLen = 7; +DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n", + LineCoding.dwDTERate, + LineCoding.bCharFormat, + LineCoding.bParityType, + LineCoding.bDataBits); + break; + + // get line coding + case GET_LINE_CODING: +DBG("GET_LINE_CODING\n"); + *ppbData = (u8 *)&LineCoding; + *piLen = 7; + break; + + // set control line state + case SET_CONTROL_LINE_STATE: + // bit0 = DTR, bit = RTS +DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue); + break; + + default: + return FALSE; + } + return TRUE; +} + + +/** + Initialises the VCOM port. + Call this function before using VCOM_putchar or VCOM_getchar + */ +void VCOM_init(void) +{ + fifo_init(&txfifo, txdata); + fifo_init(&rxfifo, rxdata); +} + + +/** + Writes one character to VCOM port + + @param [in] c character to write + @returns character written, or EOF if character could not be written + */ +int VCOM_putchar(int c) +{ + return fifo_put(&txfifo, c) ? c : EOF; +} + + +/** + Reads one character from VCOM port + + @returns character read, or EOF if character could not be read + */ +int VCOM_getchar(void) +{ + u8 c; + + return fifo_get(&rxfifo, &c) ? c : EOF; +} + + +/** + Interrupt handler + + Simply calls the USB ISR + */ +//void USBIntHandler(void) +void USB_IRQHandler(void) +{ + USBHwISR(); +} + + +static void USBFrameHandler(u16 wFrame) +{ + if (fifo_avail(&txfifo) > 0) { + // data available, enable NAK interrupt on bulk in + USBHwNakIntEnable(INACK_BI); + } +} + +void enable_USB_interrupts(void); + + +void platform_setup_usb_cdc(void) +{ + int c; + + printf("Initialising USB stack\n"); + + // initialise stack + USBInit(); + + // register descriptors + USBRegisterDescriptors(abDescriptors); + + // register class request handler + USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData); + + // register endpoint handlers + USBHwRegisterEPIntHandler(INT_IN_EP, NULL); + USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn); + USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut); + + // register frame handler + USBHwRegisterFrameHandler(USBFrameHandler); + + // enable bulk-in interrupts on NAKs + USBHwNakIntEnable(INACK_BI); + + // initialise VCOM + VCOM_init(); + printf("Starting USB communication\n"); + +/* CodeRed - comment out original interrupt setup code + // set up USB interrupt + VICIntSelect &= ~(1<<22); // select IRQ for USB + VICIntEnable |= (1<<22); + + (*(&VICVectCntl0+INT_VECT_NUM)) = 0x20 | 22; // choose highest priority ISR slot + (*(&VICVectAddr0+INT_VECT_NUM)) = (int)USBIntHandler; + + enableIRQ(); +*/ + +// CodeRed - add in interrupt setup code for RDB1768 + +#ifndef POLLED_USBSERIAL + //enable_USB_interrupts(); + NVIC_EnableIRQ(USB_IRQn); + +#endif + + // connect to bus + + printf("Connecting to USB bus\n"); + USBHwConnect(TRUE); +} + +#endif diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c index 71499bb3..bbcff5ec 100644 --- a/src/platform/lpc17xx/platform.c +++ b/src/platform/lpc17xx/platform.c @@ -39,6 +39,9 @@ static void platform_setup_pwm(); static void platform_setup_adcs(); static void cans_init( void ); static void platform_setup_pins(); +#ifdef BUILD_USB_CDC +static void platform_setup_usb_cdc(); +#endif int platform_init() { @@ -84,6 +87,11 @@ int platform_init() // Enable SysTick SysTick_Config( lpc17xx_get_cpu_frequency() / SYSTICKHZ ); +#ifdef BUILD_USB_CDC +// Setup USB CDC + platform_setup_usb_cdc(); +#endif + // Common platform initialization code cmn_platform_init(); diff --git a/src/platform/lpc17xx/usbstack/inc/usbapi.h b/src/platform/lpc17xx/usbstack/inc/usbapi.h index 5c9f6a24..74fbeb56 100644 --- a/src/platform/lpc17xx/usbstack/inc/usbapi.h +++ b/src/platform/lpc17xx/usbstack/inc/usbapi.h @@ -1,121 +1,120 @@ -/* - LPCUSB, an USB device driver for LPC microcontrollers - Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - @file -*/ - -// CodeRed - include the LPCUSB type.h file rather than NXP one directly -#include "lpcusb_type.h" - -#include "usbstruct.h" // for TSetupPacket - -/************************************************************************* - USB configuration -**************************************************************************/ - -#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */ - -/************************************************************************* - USB hardware interface -**************************************************************************/ - -// endpoint status sent through callback -#define EP_STATUS_DATA (1<<0) /**< EP has data */ -#define EP_STATUS_STALLED (1<<1) /**< EP is stalled */ -#define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */ -#define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */ -#define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */ - -// device status sent through callback -#define DEV_STATUS_CONNECT (1<<0) /**< device just got connected */ -#define DEV_STATUS_SUSPEND (1<<2) /**< device entered suspend state */ -#define DEV_STATUS_RESET (1<<4) /**< device just got reset */ - -// interrupt bits for NACK events in USBHwNakIntEnable -// (these bits conveniently coincide with the LPC176x USB controller bit) -#define INACK_CI (1<<1) /**< interrupt on NACK for control in */ -#define INACK_CO (1<<2) /**< interrupt on NACK for control out */ -#define INACK_II (1<<3) /**< interrupt on NACK for interrupt in */ -#define INACK_IO (1<<4) /**< interrupt on NACK for interrupt out */ -#define INACK_BI (1<<5) /**< interrupt on NACK for bulk in */ -#define INACK_BO (1<<6) /**< interrupt on NACK for bulk out */ - -BOOL USBHwInit (void); -void USBHwISR (void); - -void USBHwNakIntEnable (U8 bIntBits); - -void USBHwConnect (BOOL fConnect); - -void USBHwSetAddress (U8 bAddr); -void USBHwConfigDevice (BOOL fConfigured); - -// endpoint operations -void USBHwEPConfig (U8 bEP, U16 wMaxPacketSize); -int USBHwEPRead (U8 bEP, U8 *pbBuf, int iMaxLen); -int USBHwEPWrite (U8 bEP, U8 *pbBuf, int iLen); -void USBHwEPStall (U8 bEP, BOOL fStall); -U8 USBHwEPGetStatus (U8 bEP); - -/** Endpoint interrupt handler callback */ -typedef void (TFnEPIntHandler) (U8 bEP, U8 bEPStatus); -void USBHwRegisterEPIntHandler (U8 bEP, TFnEPIntHandler *pfnHandler); - -/** Device status handler callback */ -typedef void (TFnDevIntHandler) (U8 bDevStatus); -void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler); - -/** Frame event handler callback */ -typedef void (TFnFrameHandler)(U16 wFrame); -void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler); - - -/************************************************************************* - USB application interface -**************************************************************************/ - -// initialise the complete stack, including HW -BOOL USBInit(void); - -/** Request handler callback (standard, vendor, class) */ -typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, U8 **ppbData); -void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, U8 *pbDataStore); -void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler); - -/** Descriptor handler callback */ -typedef BOOL (TFnGetDescriptor)(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData); - -/** Default standard request handler */ -BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData); - -/** Default EP0 handler */ -void USBHandleControlTransfer(U8 bEP, U8 bEPStat); - -/** Descriptor handling */ -void USBRegisterDescriptors(const U8 *pabDescriptors); -BOOL USBGetDescriptor(U16 wTypeIndex, U16 wLangID, int *piLen, U8 **ppbData); +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file +*/ + +#include "type.h" + +#include "usbstruct.h" // for TSetupPacket + +/************************************************************************* + USB configuration +**************************************************************************/ + +#define MAX_PACKET_SIZE0 64 /**< maximum packet size for EP 0 */ + +/************************************************************************* + USB hardware interface +**************************************************************************/ + +// endpoint status sent through callback +#define EP_STATUS_DATA (1<<0) /**< EP has data */ +#define EP_STATUS_STALLED (1<<1) /**< EP is stalled */ +#define EP_STATUS_SETUP (1<<2) /**< EP received setup packet */ +#define EP_STATUS_ERROR (1<<3) /**< EP data was overwritten by setup packet */ +#define EP_STATUS_NACKED (1<<4) /**< EP sent NAK */ + +// device status sent through callback +#define DEV_STATUS_CONNECT (1<<0) /**< device just got connected */ +#define DEV_STATUS_SUSPEND (1<<2) /**< device entered suspend state */ +#define DEV_STATUS_RESET (1<<4) /**< device just got reset */ + +// interrupt bits for NACK events in USBHwNakIntEnable +// (these bits conveniently coincide with the LPC176x USB controller bit) +#define INACK_CI (1<<1) /**< interrupt on NACK for control in */ +#define INACK_CO (1<<2) /**< interrupt on NACK for control out */ +#define INACK_II (1<<3) /**< interrupt on NACK for interrupt in */ +#define INACK_IO (1<<4) /**< interrupt on NACK for interrupt out */ +#define INACK_BI (1<<5) /**< interrupt on NACK for bulk in */ +#define INACK_BO (1<<6) /**< interrupt on NACK for bulk out */ + +BOOL USBHwInit (void); +void USBHwISR (void); + +void USBHwNakIntEnable (u8 bIntBits); + +void USBHwConnect (BOOL fConnect); + +void USBHwSetAddress (u8 bAddr); +void USBHwConfigDevice (BOOL fConfigured); + +// endpoint operations +void USBHwEPConfig (u8 bEP, u16 wMaxPacketSize); +int USBHwEPRead (u8 bEP, u8 *pbBuf, int iMaxLen); +int USBHwEPWrite (u8 bEP, u8 *pbBuf, int iLen); +void USBHwEPStall (u8 bEP, BOOL fStall); +u8 USBHwEPGetStatus (u8 bEP); + +/** Endpoint interrupt handler callback */ +typedef void (TFnEPIntHandler) (u8 bEP, u8 bEPStatus); +void USBHwRegisterEPIntHandler (u8 bEP, TFnEPIntHandler *pfnHandler); + +/** Device status handler callback */ +typedef void (TFnDevIntHandler) (u8 bDevStatus); +void USBHwRegisterDevIntHandler (TFnDevIntHandler *pfnHandler); + +/** Frame event handler callback */ +typedef void (TFnFrameHandler)(u16 wFrame); +void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler); + + +/************************************************************************* + USB application interface +**************************************************************************/ + +// initialise the complete stack, including HW +BOOL USBInit(void); + +/** Request handler callback (standard, vendor, class) */ +typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, u8 **ppbData); +void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, u8 *pbDataStore); +void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler); + +/** Descriptor handler callback */ +typedef BOOL (TFnGetDescriptor)(u16 wTypeIndex, u16 wLangID, int *piLen, u8 **ppbData); + +/** Default standard request handler */ +BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, u8 **ppbData); + +/** Default EP0 handler */ +void USBHandleControlTransfer(u8 bEP, u8 bEPStat); + +/** Descriptor handling */ +void USBRegisterDescriptors(const u8 *pabDescriptors); +BOOL USBGetDescriptor(u16 wTypeIndex, u16 wLangID, int *piLen, u8 **ppbData); diff --git a/src/platform/lpc17xx/usbstack/inc/usbdebug.h b/src/platform/lpc17xx/usbstack/inc/usbdebug.h index bb3fb152..5b3ea63b 100644 --- a/src/platform/lpc17xx/usbstack/inc/usbdebug.h +++ b/src/platform/lpc17xx/usbstack/inc/usbdebug.h @@ -1,5 +1,5 @@ /* - LPCUSB, an USB device driver for LPC microcontrollers + LPCUSB, an USB device driver for LPC microcontrollers Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) Redistribution and use in source and binary forms, with or without @@ -16,7 +16,7 @@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @@ -25,15 +25,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// CodeRed - comment out this printf, as will use real one from stdio.h -// to implement output via semihosting - -//int printf(const char *format, ...); # include -// CodeRed - added DEBUG_MESSAGES, so still get output for Release builds -//#define DEBUG_MESSAGES 1 -//#ifdef DEBUG +#define DEBUG_MESSAGES 1 + #ifdef DEBUG_MESSAGES #define DBG printf #define ASSERT(x) if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);} @@ -41,4 +36,3 @@ #define DBG(x ...) #define ASSERT(x) #endif - diff --git a/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h b/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h index b2071d14..a8c1ad09 100644 --- a/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h +++ b/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h @@ -1,5 +1,5 @@ /* - LPCUSB, an USB device driver for LPC microcontrollers + LPCUSB, an USB device driver for LPC microcontrollers Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) Redistribution and use in source and binary forms, with or without @@ -16,7 +16,7 @@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @@ -138,11 +138,3 @@ #define B_OVRN (1<<5) #define BTSTF (1<<6) #define TGL_ERR (1<<7) - - - - - - - - diff --git a/src/platform/lpc17xx/usbstack/inc/usbstruct.h b/src/platform/lpc17xx/usbstack/inc/usbstruct.h index b30e5247..1f07a636 100644 --- a/src/platform/lpc17xx/usbstack/inc/usbstruct.h +++ b/src/platform/lpc17xx/usbstack/inc/usbstruct.h @@ -1,5 +1,5 @@ /* - LPCUSB, an USB device driver for LPC microcontrollers + LPCUSB, an USB device driver for LPC microcontrollers Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) Redistribution and use in source and binary forms, with or without @@ -16,7 +16,7 @@ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY @@ -33,18 +33,15 @@ #ifndef _USBSTRUCT_H_ #define _USBSTRUCT_H_ -// CodeRed - include the LPCUSB type.h file rather than NXP one directly -//#include "type.h" -#include "lpcusb_type.h" - +#include "type.h" /** setup packet definitions */ typedef struct { - U8 bmRequestType; /**< characteristics of the specific request */ - U8 bRequest; /**< specific request */ - U16 wValue; /**< request specific parameter */ - U16 wIndex; /**< request specific parameter */ - U16 wLength; /**< length of data transfered in data phase */ + u8 bmRequestType; /**< characteristics of the specific request */ + u8 bRequest; /**< specific request */ + u16 wValue; /**< request specific parameter */ + u16 wIndex; /**< request specific parameter */ + u16 wLength; /**< length of data transfered in data phase */ } TSetupPacket; @@ -97,8 +94,8 @@ typedef struct { /** USB descriptor header */ typedef struct { - U8 bLength; /**< descriptor length */ - U8 bDescriptorType; /**< descriptor type */ + u8 bLength; /**< descriptor length */ + u8 bDescriptorType; /**< descriptor type */ } TUSBDescHeader; #define DESC_DEVICE 1 @@ -118,4 +115,3 @@ typedef struct { #define GET_DESC_INDEX(x) ((x)&0xFF) #endif /* _USBSTRUCT_H_ */ - diff --git a/src/platform/lpc17xx/usbstack/src/usbcontrol.c b/src/platform/lpc17xx/usbstack/src/usbcontrol.c index fd07486a..e1290f8d 100644 --- a/src/platform/lpc17xx/usbstack/src/usbcontrol.c +++ b/src/platform/lpc17xx/usbstack/src/usbcontrol.c @@ -25,6 +25,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "platform_conf.h" + +#ifdef BUILD_USB_CDC /** @file Control transfer handler. @@ -55,7 +58,7 @@ #include "usbstruct.h" #include "usbapi.h" - +#include "utils.h" #define MAX_CONTROL_SIZE 128 /**< maximum total size of control transfer data */ #define MAX_REQ_HANDLERS 4 /**< standard, class, vendor, reserved */ @@ -130,7 +133,7 @@ static void DataIn(void) { int iChunk; - iChunk = MIN(MAX_PACKET_SIZE0, iResidue); + iChunk = UMIN(MAX_PACKET_SIZE0, iResidue); USBHwEPWrite(0x80, pbData, iChunk); pbData += iChunk; iResidue -= iChunk; @@ -169,7 +172,7 @@ void USBHandleControlTransfer(u8 bEP, u8 bEPStat) return; } // send smallest of requested and offered length - iResidue = MIN(iLen, Setup.wLength); + iResidue = UMIN(iLen, Setup.wLength); // send first part (possibly a zero-length status message) DataIn(); } @@ -229,3 +232,5 @@ void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, u8 *pbDa apfnReqHandlers[iType] = pfnHandler; apbDataStore[iType] = pbDataStore; } + +#endif diff --git a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c index c8256902..d2b3f723 100644 --- a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c +++ b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c @@ -25,6 +25,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "platform_conf.h" + +#ifdef BUILD_USB_CDC /** @file USB hardware layer @@ -622,3 +625,5 @@ BOOL USBHwInit(void) return TRUE; } + +#endif diff --git a/src/platform/lpc17xx/usbstack/src/usbinit.c b/src/platform/lpc17xx/usbstack/src/usbinit.c index 41ea93fc..0ebd4326 100644 --- a/src/platform/lpc17xx/usbstack/src/usbinit.c +++ b/src/platform/lpc17xx/usbstack/src/usbinit.c @@ -25,6 +25,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "platform_conf.h" + +#ifdef BUILD_USB_CDC /** @file USB stack initialisation @@ -80,3 +83,5 @@ BOOL USBInit(void) return TRUE; } + +#endif diff --git a/src/platform/lpc17xx/usbstack/src/usbstdreq.c b/src/platform/lpc17xx/usbstack/src/usbstdreq.c index 981cea8e..fbe07f9f 100644 --- a/src/platform/lpc17xx/usbstack/src/usbstdreq.c +++ b/src/platform/lpc17xx/usbstack/src/usbstdreq.c @@ -25,6 +25,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "platform_conf.h" + +#ifdef BUILD_USB_CDC /** @file Standard request handler. @@ -429,3 +432,5 @@ void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler) { pfnHandleCustomReq = pfnHandler; } + +#endif From 480acc200b334e08d9ddeddfc7aff1074f9e946e Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Thu, 23 Apr 2015 23:53:04 +0200 Subject: [PATCH 21/26] Some more cleanup. --- .../lpc17xx/drivers/src/lpc17xx_usb_cdc.c | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c index 726eceb3..c78895f7 100644 --- a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c +++ b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c @@ -402,8 +402,10 @@ int VCOM_getchar(void) Interrupt handler Simply calls the USB ISR + + This gets installed by overriding a WEAK linker symbol + */ -//void USBIntHandler(void) void USB_IRQHandler(void) { USBHwISR(); @@ -451,25 +453,9 @@ void platform_setup_usb_cdc(void) VCOM_init(); printf("Starting USB communication\n"); -/* CodeRed - comment out original interrupt setup code - // set up USB interrupt - VICIntSelect &= ~(1<<22); // select IRQ for USB - VICIntEnable |= (1<<22); - - (*(&VICVectCntl0+INT_VECT_NUM)) = 0x20 | 22; // choose highest priority ISR slot - (*(&VICVectAddr0+INT_VECT_NUM)) = (int)USBIntHandler; - - enableIRQ(); -*/ - -// CodeRed - add in interrupt setup code for RDB1768 - -#ifndef POLLED_USBSERIAL - //enable_USB_interrupts(); + // enable IRQ NVIC_EnableIRQ(USB_IRQn); -#endif - // connect to bus printf("Connecting to USB bus\n"); From 6512ce66c984e16733ee2a8616cc4cc1a4b8e81e Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Fri, 24 Apr 2015 14:30:27 +0200 Subject: [PATCH 22/26] Hook up USB pins using board description mechanism, call USB CDC functions from platform UART code. --- boards/known/lpcxpresso.lua | 7 +- .../lpc17xx/drivers/src/lpc17xx_usb_cdc.c | 3 - src/platform/lpc17xx/platform.c | 33 ++++- src/platform/lpc17xx/usbstack/src/usbhw_lpc.c | 129 +++--------------- 4 files changed, 49 insertions(+), 123 deletions(-) diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index d55eb67b..e394126f 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -17,10 +17,11 @@ return { egc = { mode = "alloc" }, ram = { internal_rams = 2 }, clocks = { external = 12000000, cpu = 120000000 }, + -- P0.0 UART3 TX, P0.1 UART3 RX, P0.29 USB D+, P0.30 USB D-, P1.18 USB_UP_LED, P2.9 USB CONNECT map_pins = { - port = { 0, 0 }, - pin = { 0, 1 }, - pinfunction = { 2, 2 } + port = { 0, 0, 0, 0, 1, 2 }, + pin = { 0, 1, 29, 30, 18, 9 }, + pinfunction = { 2, 2, 1, 1, 1, 1 } } }, modules = { diff --git a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c index c78895f7..2dd58328 100644 --- a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c +++ b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c @@ -420,9 +420,6 @@ static void USBFrameHandler(u16 wFrame) } } -void enable_USB_interrupts(void); - - void platform_setup_usb_cdc(void) { int c; diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c index bbcff5ec..3f0cef7b 100644 --- a/src/platform/lpc17xx/platform.c +++ b/src/platform/lpc17xx/platform.c @@ -28,6 +28,7 @@ #include "lpc17xx_pwm.h" #include "lpc17xx_adc.h" #include "lpc17xx_can.h" +#include "lpc17xx_usb_cdc.h" #define SYSTICKHZ 10 @@ -39,9 +40,6 @@ static void platform_setup_pwm(); static void platform_setup_adcs(); static void cans_init( void ); static void platform_setup_pins(); -#ifdef BUILD_USB_CDC -static void platform_setup_usb_cdc(); -#endif int platform_init() { @@ -206,6 +204,11 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st UARTConfigStruct.Baud_rate = ( uint32_t )baud; +#ifdef BUILD_USB_CDC + if( id == CDC_UART_ID ) + return 0; +#endif + switch( databits ) { case 5: @@ -267,12 +270,34 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st void platform_s_uart_send( unsigned id, u8 data ) { - UART_Send(uart[ id ], &data, 1, BLOCKING); +#ifdef BUILD_USB_CDC + if( id == CDC_UART_ID ) + VCOM_putchar( data ); + else +#endif + { + UART_Send(uart[ id ], &data, 1, BLOCKING); + } } int platform_s_uart_recv( unsigned id, timer_data_type timeout ) { u8 buffer; + int rc; + + /* Polling is bad style. Replace me with something interrupt-driven. */ +#ifdef BUILD_USB_CDC + if( id == CDC_UART_ID ) + { + do + { + rc = VCOM_getchar(); + if( (timeout == 0) && (rc == EOF) ) + return -1; + } while( rc == EOF ); + return rc; + } +#endif if( timeout == 0 ) { diff --git a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c index d2b3f723..889042a5 100644 --- a/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c +++ b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c @@ -38,51 +38,6 @@ #include "usbdebug.h" #include "usbhw_lpc.h" #include "usbapi.h" -// Configure LED pin functions -// -// LED pin functions -// -// Function Pin Port Bits Pin Select Register -// ------------------- --- ----- ---- ------------------- -// P2.0 GPIO Port 2.0 xx P2.0 1:0 PINSEL4 -// P2.1 GPIO Port 2.1 xx P2.1 3:2 PINSEL4 -// P2.2 GPIO Port 2.2 xx P2.2 5:4 PINSEL4 -// P2.3 GPIO Port 2.3 xx P2.3 7:6 PINSEL4 -// P2.4 GPIO Port 2.4 xx P2.4 9:8 PINSEL4 -// P2.5 GPIO Port 2.5 xx P2.5 11:10 PINSEL4 -// P2.6 GPIO Port 2.6 xx P2.6 13:12 PINSEL4 -// P2.7 GPIO Port 2.7 xx P2.7 15:14 PINSEL4 -// -// OFF - LED state 0 -// ON - LED state 1 -// -// '*' as GPIO - -#define NO_LEDS 8 - -#define LED_0 (1 << 0) -#define LED_1 (1 << 1) -#define LED_2 (1 << 2) -#define LED_3 (1 << 3) -#define LED_4 (1 << 4) -#define LED_5 (1 << 5) -#define LED_6 (1 << 6) -#define LED_7 (1 << 7) - -#ifdef DEBUG -// comment out the following line if you don't want to use debug LEDs -//#define DEBUG_LED -#endif - -#ifdef DEBUG_LED -#define DEBUG_LED_ON(x) FIO2SET = (1 << x); -#define DEBUG_LED_OFF(x) FIO2CLR = (1 << x); -#define DEBUG_LED_INIT(x) PINSEL2 &= ~(0x3 << (2*x)); FIO2DIR |= (1 << x); DEBUG_LED_OFF(x); -#else -#define DEBUG_LED_INIT(x) /**< LED initialisation macro */ -#define DEBUG_LED_ON(x) /**< turn LED on */ -#define DEBUG_LED_OFF(x) /**< turn LED off */ -#endif /** Installed device interrupt handler */ static TFnDevIntHandler *_pfnDevIntHandler = NULL; @@ -462,9 +417,6 @@ void USBHwISR(void) int i; u16 wFrame; - // LED9 monitors total time in interrupt routine - DEBUG_LED_ON(6); - // handle device interrupts dwStatus = LPC_USB->USBDevIntSt; @@ -494,9 +446,7 @@ void USBHwISR(void) ((bDevStat & RST) ? DEV_STATUS_RESET : 0); // call handler if (_pfnDevIntHandler != NULL) { - DEBUG_LED_ON(5); _pfnDevIntHandler(bStat); - DEBUG_LED_OFF(5); } } } @@ -521,15 +471,11 @@ void USBHwISR(void) ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0); // call handler if (_apfnEPIntHandlers[i / 2] != NULL) { - DEBUG_LED_ON(7); _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); - DEBUG_LED_OFF(7); } } } } - - DEBUG_LED_OFF(6); } @@ -537,68 +483,33 @@ void USBHwISR(void) /** Initialises the USB hardware - This function assumes that the hardware is connected as shown in - section 10.1 of the LPC2148 data sheet: - * P0.31 controls a switch to connect a 1.5k pull-up to D+ if low. - * P0.23 is connected to USB VCC. + To make sure this works, I/O pin functions need to be mapped inside + the board description as follows: + + * P0.29 USB D+ + * P0.30 USB D- + * P1.18 USB_UP_LED + * P2.9 USB CONNECT + + To do this, use a map_pins clause inside the configuration section + as follows: + + map_pins = { + port = { 0, 0, 1, 2 }, + pin = { 29, 30, 18, 9 }, + pinfunction = { 1, 1, 1, 1 } + } - Embedded artists board: make sure to disconnect P0.23 LED as it - acts as a pull-up and so prevents detection of USB disconnect. @return TRUE if the hardware was successfully initialised */ BOOL USBHwInit(void) { -/* CodeRed - comment out original code - * - // configure P0.23 for Vbus sense - PINSEL1 = (PINSEL1 & ~(3 << 14)) | (1 << 14); // P0.23 - // configure P0.31 for CONNECT - PINSEL1 = (PINSEL1 & ~(3 << 30)) | (2 << 30); // P0.31 -*/ - - // CodeRed - set up USB pins - - // P2.9 -> USB_CONNECT - LPC_PINCON->PINSEL4 &= ~0x000C0000; - LPC_PINCON->PINSEL4 |= 0x00040000; - - // P1.18 -> USB_UP_LED - // P1.30 -> VBUS - LPC_PINCON->PINSEL3 &= ~0x30000030; - LPC_PINCON->PINSEL3 |= 0x20000010; - - // P0.29 -> USB_D+ - // P0.30 -> USB_D- - LPC_PINCON->PINSEL1 &= ~0x3C000000; - LPC_PINCON->PINSEL1 |= 0x14000000; // enable PUSB LPC_SC->PCONP |= (1 << 31); -/* CodeRed - Comment out original PLL code - * PLL now set up by NXP code in target.c within example projects - * - // initialise PLL - PLL1CON = 1; // enable PLL - PLL1CFG = (1 << 5) | 3; // P = 2, M = 4 - PLL1FEED = 0xAA; - PLL1FEED = 0x55; - while ((PLL1STAT & (1 << 10)) == 0); - - PLL1CON = 3; // enable and connect - PLL1FEED = 0xAA; - PLL1FEED = 0x55; - -*/ - - -// AWB added USB clock enable -// These are actually the USBClkCtrl and USBClkSt registers -// OTG_CLK_CTRL = 0x12; /* Dev clock, AHB clock enable */ -// while ((OTG_CLK_STAT & 0x12) != 0x12); - LPC_USB->USBClkCtrl = 0x1A; /* Dev clock, AHB clock enable */ while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); @@ -615,14 +526,6 @@ BOOL USBHwInit(void) // by default, only ACKs generate interrupts USBHwNakIntEnable(0); - // CodeRed - commented out LEDs - not used by current port - // init debug leds - /* - DEBUG_LED_INIT(5); - DEBUG_LED_INIT(6); - DEBUG_LED_INIT(7); - */ - return TRUE; } From 58bbea8bfd830a6ac470b514c8752d2ddb7bbb51 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Fri, 24 Apr 2015 14:30:49 +0200 Subject: [PATCH 23/26] Add header file for USB CDC driver. --- .../lpc17xx/drivers/inc/lpc17xx_usb_cdc.h | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/platform/lpc17xx/drivers/inc/lpc17xx_usb_cdc.h diff --git a/src/platform/lpc17xx/drivers/inc/lpc17xx_usb_cdc.h b/src/platform/lpc17xx/drivers/inc/lpc17xx_usb_cdc.h new file mode 100644 index 00000000..2a3aaf84 --- /dev/null +++ b/src/platform/lpc17xx/drivers/inc/lpc17xx_usb_cdc.h @@ -0,0 +1,22 @@ +#ifndef __LPC17XX_USB_CDC_H +#define __LPC17XX_USB_CDC_H + +#include "type.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +int VCOM_putchar(int c); +int VCOM_getchar(void); +void platform_setup_usb_cdc(void); + + +#ifdef __cplusplus +} +#endif + + +#endif /* __LPC17XX_USB_CDC_H */ From a61e3e60667b6eb8f3bd8cd662ce482bf9294bd3 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Fri, 24 Apr 2015 14:37:20 +0200 Subject: [PATCH 24/26] Switch LPCXpresso default console to USB --- boards/known/lpcxpresso.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua index e394126f..316b10d0 100644 --- a/boards/known/lpcxpresso.lua +++ b/boards/known/lpcxpresso.lua @@ -3,7 +3,7 @@ return { cpu = 'lpc1769', components = { - sercon = { uart = 3, speed = 115200 }, + sercon = { uart = "cdc", speed = 115200 }, romfs = true, shell = true, cdc = true, From 296ce919c6bdb73e501ee265dcc39885be7449b0 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Fri, 24 Apr 2015 14:40:13 +0200 Subject: [PATCH 25/26] Turn off USB debug --- src/platform/lpc17xx/usbstack/inc/usbdebug.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/platform/lpc17xx/usbstack/inc/usbdebug.h b/src/platform/lpc17xx/usbstack/inc/usbdebug.h index 5b3ea63b..c0c10789 100644 --- a/src/platform/lpc17xx/usbstack/inc/usbdebug.h +++ b/src/platform/lpc17xx/usbstack/inc/usbdebug.h @@ -27,8 +27,6 @@ # include -#define DEBUG_MESSAGES 1 - #ifdef DEBUG_MESSAGES #define DBG printf #define ASSERT(x) if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);} From a35bf942745edaced36c44784aa24900e447fd30 Mon Sep 17 00:00:00 2001 From: Andreas Bogk Date: Fri, 24 Apr 2015 14:52:28 +0200 Subject: [PATCH 26/26] Use NXP USB CDC example VID:PID --- src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c index 2dd58328..4558e31d 100644 --- a/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c +++ b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c @@ -157,8 +157,8 @@ static const u8 abDescriptors[] = { 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol MAX_PACKET_SIZE0, // bMaxPacketSize - LE_WORD(0xFFFF), // idVendor - LE_WORD(0x0005), // idProduct + LE_WORD(0x1fc9), // idVendor + LE_WORD(0x2047), // idProduct LE_WORD(0x0100), // bcdDevice 0x01, // iManufacturer 0x02, // iProduct