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 diff --git a/boards/known/arm2368.lua b/boards/known/arm2368.lua new file mode 100644 index 00000000..0c62efdd --- /dev/null +++ b/boards/known/arm2368.lua @@ -0,0 +1,26 @@ +-- CP-JR ARM2368 board build configuration +-- http://www.futurlec.com/ARM2368_Controller.shtml + +return { + cpu = 'lpc2368', + components = { + sercon = { uart = 0, speed = 115200, timer = 0 }, + romfs = true, + shell = true, + term = { lines = 25, cols = 80 }, + cints = true, + luaints = true, + linenoise = { shell_lines = 10, lua_lines = 50 }, + rpc = { uart = 0, speed = 115200 }, + adc = { buf_size = 4 }, + xmodem = true + }, + config = { + vtmr = { num = 4, freq = 4 }, + ram = { ext_start = { 0x40000000 }, ext_size = { 32 * 1024 } } + }, + modules = { + generic = { 'all', '-i2c', '-net', '-spi', '-can' } + } +} + diff --git a/boards/known/lpcxpresso.lua b/boards/known/lpcxpresso.lua new file mode 100644 index 00000000..316b10d0 --- /dev/null +++ b/boards/known/lpcxpresso.lua @@ -0,0 +1,33 @@ +-- LPCXpresso LPC1769 build configuration + +return { + cpu = 'lpc1769', + components = { + sercon = { uart = "cdc", 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 }, + adc = { buf_size = 4 }, + xmodem = true + }, + config = { + 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, 0, 0, 1, 2 }, + pin = { 0, 1, 29, 30, 18, 9 }, + pinfunction = { 2, 2, 1, 1, 1, 1 } + } + }, + modules = { + generic = { 'all', "-spi", "-i2c", "-net" }, + platform = 'all', + platform_name = 'lpcxpresso' + }, +} + diff --git a/boards/known/mbed.lua b/boards/known/mbed.lua index 4ab4a2e9..aa9861d5 100644 --- a/boards/known/mbed.lua +++ b/boards/known/mbed.lua @@ -15,7 +15,13 @@ return { }, config = { egc = { mode = "alloc" }, - ram = { internal_rams = 2 } + ram = { internal_rams = 2 }, + clocks = { external = 12000000, cpu = 100000000 }, + map_pins = { + port = { 0, 0 }, + pin = { 2, 3 }, + pinfunction = { 1, 1 } + } }, modules = { generic = { 'all', "-spi", "-i2c", "-net" }, 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..59fad400 100644 --- a/build_data.lua +++ b/build_data.lua @@ -113,6 +113,7 @@ local platform_list = stm32 = { cpus = { 'STM32F103ZE', 'STM32F103RE' }, arch = 'cortexm' }, stm32f4 = { cpus = { 'STM32F401RE', 'STM32F407VG', 'STM32F407ZG' }, arch = 'cortexm' }, avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, arch = 'avr32' }, + lpc23xx = { cpus = { 'LPC2368' }, arch = 'arm' }, lpc24xx = { cpus = { 'LPC2468' }, arch = 'arm' }, lpc17xx = { cpus = { 'LPC1768' }, arch = 'cortexm' } } 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 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 ) ); } diff --git a/src/platform/lpc17xx/build_config.lua b/src/platform/lpc17xx/build_config.lua index ba3a34fc..f04b2c48 100644 --- a/src/platform/lpc17xx/build_config.lua +++ b/src/platform/lpc17xx/build_config.lua @@ -2,20 +2,33 @@ -- It is used by the generic board configuration system (config/) module( ..., package.seeall ) +local at = require "attributes" +local comps = require "components" -- 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" } + t.cdc = comps.cdc_uart() end -- Add specific configuration to the 'configs' table -function add_platform_configs( t ) -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 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 = { 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" } + end + return m +end + diff --git a/src/platform/lpc17xx/conf.lua b/src/platform/lpc17xx/conf.lua index 59c10b32..cda5d2cb 100644 --- a/src/platform/lpc17xx/conf.lua +++ b/src/platform/lpc17xx/conf.lua @@ -1,12 +1,22 @@ -- 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$" ) -specific_files = "startup_LPC17xx.c system_LPC17xx.c core_cm3.c platform.c mbed_pio.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() + +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" 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 new file mode 100644 index 00000000..a607e1dc --- /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 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' +// 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/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 */ 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/drivers/src/lpc17xx_usb_cdc.c b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c new file mode 100644 index 00000000..4558e31d --- /dev/null +++ b/src/platform/lpc17xx/drivers/src/lpc17xx_usb_cdc.c @@ -0,0 +1,462 @@ +/* + 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(0x1fc9), // idVendor + LE_WORD(0x2047), // 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 + + This gets installed by overriding a WEAK linker symbol + + */ +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 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"); + + // enable IRQ + NVIC_EnableIRQ(USB_IRQn); + + // connect to bus + + printf("Connecting to USB bus\n"); + USBHwConnect(TRUE); +} + +#endif 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 f18b79b7..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 @@ -38,12 +39,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,21 +75,29 @@ int platform_init() // Setup CANs cans_init(); + // Setup pin routing + platform_setup_pins(); + // 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 ); + +#ifdef BUILD_USB_CDC +// Setup USB CDC + platform_setup_usb_cdc(); +#endif // Common platform initialization code cmn_platform_init(); return PLATFORM_OK; -} +} extern u32 SystemCoreClock; -u32 mbed_get_cpu_frequency() +u32 lpc17xx_get_cpu_frequency() { return SystemCoreClock; } @@ -104,50 +114,71 @@ 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; iTC < last ); } - + timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data ) { u32 res = 0; @@ -335,7 +380,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; @@ -343,7 +388,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; @@ -390,13 +435,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 ) { @@ -412,17 +457,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 ) @@ -432,11 +477,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 ) { @@ -444,14 +489,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 ] ); @@ -465,20 +510,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 ); } @@ -493,15 +538,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; @@ -509,9 +554,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 ); @@ -519,48 +564,48 @@ u32 platform_adc_set_clock( unsigned id, u32 frequency ) } else d->clocked = 0; - + return 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 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.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 ); @@ -568,7 +613,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 ] ); @@ -578,7 +623,7 @@ int platform_adc_start_sequence() else ADC_StartCmd( LPC_ADC, ADC_START_NOW ); } - + return PLATFORM_OK; } @@ -599,7 +644,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 ); @@ -611,10 +656,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; @@ -630,13 +675,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; @@ -673,7 +718,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)) { @@ -701,7 +746,7 @@ void cans_init( void ) u32 platform_can_setup( unsigned id, u32 clock ) -{ +{ LPC_CAN_TypeDef * canx; uint32_t div; @@ -712,13 +757,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 @@ -800,7 +845,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; @@ -813,4 +858,3 @@ int platform_can_recv( unsigned id, u32 *canid, u8 *idtype, u8 *len, u8 *data ) else return PLATFORM_UNDERFLOW; } - diff --git a/src/platform/lpc17xx/system_LPC17xx.c b/src/platform/lpc17xx/system_LPC17xx.c index e1734625..ebbb5ee9 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)( 32768UL)) /* 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) diff --git a/src/platform/lpc17xx/type.h b/src/platform/lpc17xx/type.h index 47ec5c04..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,6 +29,7 @@ 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; diff --git a/src/platform/lpc17xx/usbstack/inc/usbapi.h b/src/platform/lpc17xx/usbstack/inc/usbapi.h new file mode 100644 index 00000000..74fbeb56 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbapi.h @@ -0,0 +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 +*/ + +#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 new file mode 100644 index 00000000..c0c10789 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbdebug.h @@ -0,0 +1,36 @@ +/* + 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 + +#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..a8c1ad09 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbhw_lpc.h @@ -0,0 +1,140 @@ +/* + 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..1f07a636 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/inc/usbstruct.h @@ -0,0 +1,117 @@ +/* + 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_ + +#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 */ +} 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..e1290f8d --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbcontrol.c @@ -0,0 +1,236 @@ +/* + 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 + +/** @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. +*/ + +#include "type.h" + +#include "usbdebug.h" + +#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 */ + +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 = UMIN(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 = UMIN(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; +} + +#endif 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..889042a5 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbhw_lpc.c @@ -0,0 +1,532 @@ +/* + 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 + +/** @file + USB hardware layer + */ + +#include "type.h" + +#include "usbdebug.h" +#include "usbhw_lpc.h" +#include "usbapi.h" + +/** 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; + + // 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) { + _pfnDevIntHandler(bStat); + } + } + } + + // 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) { + _apfnEPIntHandlers[i / 2](IDX2EP(i), bStat); + } + } + } + } +} + + + +/** + Initialises the USB hardware + + 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 } + } + + + @return TRUE if the hardware was successfully initialised + */ +BOOL USBHwInit(void) +{ + + + // enable PUSB + LPC_SC->PCONP |= (1 << 31); + + 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); + + return TRUE; +} + +#endif diff --git a/src/platform/lpc17xx/usbstack/src/usbinit.c b/src/platform/lpc17xx/usbstack/src/usbinit.c new file mode 100644 index 00000000..0ebd4326 --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbinit.c @@ -0,0 +1,87 @@ +/* + 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 + +/** @file + USB stack initialisation + */ + +#include "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; +} + +#endif diff --git a/src/platform/lpc17xx/usbstack/src/usbstdreq.c b/src/platform/lpc17xx/usbstack/src/usbstdreq.c new file mode 100644 index 00000000..fbe07f9f --- /dev/null +++ b/src/platform/lpc17xx/usbstack/src/usbstdreq.c @@ -0,0 +1,436 @@ +/* + 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 + +/** @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; +} + +#endif diff --git a/src/platform/lpc23xx/LPC23xx.h b/src/platform/lpc23xx/LPC23xx.h new file mode 100644 index 00000000..be6dd24e --- /dev/null +++ b/src/platform/lpc23xx/LPC23xx.h @@ -0,0 +1,1167 @@ +/****************************************************************************** + * LPC23xx.h: Header file for NXP LPC23xx/24xx Family Microprocessors + * The header file is the super set of all hardware definition of the + * peripherals for the LPC23xx/24xx family microprocessor. + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2005.10.01 ver 1.00 Prelimnary version, first Release + * 2007.05.17 ver 1.01 several corrections + * 2007.09.05 ver 1.02 added VICVectPriorityx symbols + * 2007.09.05 ver 1.03 FIO1PIN1 value corrected + * +******************************************************************************/ + +#ifndef __LPC23xx_H +#define __LPC23xx_H + +/* Vectored Interrupt Controller (VIC) */ +#define VIC_BASE_ADDR 0xFFFFF000 +#define VICIRQStatus (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x000)) +#define VICFIQStatus (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x004)) +#define VICRawIntr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x008)) +#define VICIntSelect (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x00C)) +#define VICIntEnable (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x010)) +#define VICIntEnClr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x014)) +#define VICSoftInt (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x018)) +#define VICSoftIntClr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x01C)) +#define VICProtection (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x020)) +#define VICSWPrioMask (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x024)) + +#define VICVectAddr0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x100)) +#define VICVectAddr1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x104)) +#define VICVectAddr2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x108)) +#define VICVectAddr3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x10C)) +#define VICVectAddr4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x110)) +#define VICVectAddr5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x114)) +#define VICVectAddr6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x118)) +#define VICVectAddr7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x11C)) +#define VICVectAddr8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x120)) +#define VICVectAddr9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x124)) +#define VICVectAddr10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x128)) +#define VICVectAddr11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x12C)) +#define VICVectAddr12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x130)) +#define VICVectAddr13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x134)) +#define VICVectAddr14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x138)) +#define VICVectAddr15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x13C)) +#define VICVectAddr16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x140)) +#define VICVectAddr17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x144)) +#define VICVectAddr18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x148)) +#define VICVectAddr19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x14C)) +#define VICVectAddr20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x150)) +#define VICVectAddr21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x154)) +#define VICVectAddr22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x158)) +#define VICVectAddr23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x15C)) +#define VICVectAddr24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x160)) +#define VICVectAddr25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x164)) +#define VICVectAddr26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x168)) +#define VICVectAddr27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x16C)) +#define VICVectAddr28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x170)) +#define VICVectAddr29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x174)) +#define VICVectAddr30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x178)) +#define VICVectAddr31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x17C)) + +/* The name convention below is from previous LPC2000 family MCUs, in LPC23xx/24xx, +these registers are known as "VICVectPriority(x)". */ +#define VICVectCntl0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x200)) +#define VICVectCntl1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x204)) +#define VICVectCntl2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x208)) +#define VICVectCntl3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x20C)) +#define VICVectCntl4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x210)) +#define VICVectCntl5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x214)) +#define VICVectCntl6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x218)) +#define VICVectCntl7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x21C)) +#define VICVectCntl8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x220)) +#define VICVectCntl9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x224)) +#define VICVectCntl10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x228)) +#define VICVectCntl11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x22C)) +#define VICVectCntl12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x230)) +#define VICVectCntl13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x234)) +#define VICVectCntl14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x238)) +#define VICVectCntl15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x23C)) +#define VICVectCntl16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x240)) +#define VICVectCntl17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x244)) +#define VICVectCntl18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x248)) +#define VICVectCntl19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x24C)) +#define VICVectCntl20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x250)) +#define VICVectCntl21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x254)) +#define VICVectCntl22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x258)) +#define VICVectCntl23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x25C)) +#define VICVectCntl24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x260)) +#define VICVectCntl25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x264)) +#define VICVectCntl26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x268)) +#define VICVectCntl27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x26C)) +#define VICVectCntl28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x270)) +#define VICVectCntl29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x274)) +#define VICVectCntl30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x278)) +#define VICVectCntl31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x27C)) + +/* LPC23xx/24xx VICVectPriority(x)". */ +#define VICVectPriority0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x200)) +#define VICVectPriority1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x204)) +#define VICVectPriority2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x208)) +#define VICVectPriority3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x20C)) +#define VICVectPriority4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x210)) +#define VICVectPriority5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x214)) +#define VICVectPriority6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x218)) +#define VICVectPriority7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x21C)) +#define VICVectPriority8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x220)) +#define VICVectPriority9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x224)) +#define VICVectPriority10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x228)) +#define VICVectPriority11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x22C)) +#define VICVectPriority12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x230)) +#define VICVectPriority13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x234)) +#define VICVectPriority14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x238)) +#define VICVectPriority15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x23C)) +#define VICVectPriority16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x240)) +#define VICVectPriority17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x244)) +#define VICVectPriority18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x248)) +#define VICVectPriority19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x24C)) +#define VICVectPriority20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x250)) +#define VICVectPriority21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x254)) +#define VICVectPriority22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x258)) +#define VICVectPriority23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x25C)) +#define VICVectPriority24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x260)) +#define VICVectPriority25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x264)) +#define VICVectPriority26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x268)) +#define VICVectPriority27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x26C)) +#define VICVectPriority28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x270)) +#define VICVectPriority29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x274)) +#define VICVectPriority30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x278)) +#define VICVectPriority31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x27C)) + +#define VICVectAddr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0xF00)) + + +/* Pin Connect Block */ +#define PINSEL_BASE_ADDR 0xE002C000 +#define PINSEL0 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x00)) +#define PINSEL1 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x04)) +#define PINSEL2 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x08)) +#define PINSEL3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x0C)) +#define PINSEL4 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x10)) +#define PINSEL5 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x14)) +#define PINSEL6 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x18)) +#define PINSEL7 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x1C)) +#define PINSEL8 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x20)) +#define PINSEL9 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x24)) +#define PINSEL10 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x28)) + +#define PINMODE0 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x40)) +#define PINMODE1 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x44)) +#define PINMODE2 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x48)) +#define PINMODE3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x4C)) +#define PINMODE4 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x50)) +#define PINMODE5 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x54)) +#define PINMODE6 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x58)) +#define PINMODE7 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x5C)) +#define PINMODE8 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x60)) +#define PINMODE9 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x64)) + +/* General Purpose Input/Output (GPIO) */ +#define GPIO_BASE_ADDR 0xE0028000 +#define IOPIN0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x00)) +#define IOSET0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x04)) +#define IODIR0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x08)) +#define IOCLR0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x0C)) +#define IOPIN1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x10)) +#define IOSET1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x14)) +#define IODIR1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x18)) +#define IOCLR1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x1C)) + +/* GPIO Interrupt Registers */ +#define IO0_INT_EN_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x90)) +#define IO0_INT_EN_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x94)) +#define IO0_INT_STAT_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x84)) +#define IO0_INT_STAT_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x88)) +#define IO0_INT_CLR (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x8C)) + +#define IO2_INT_EN_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xB0)) +#define IO2_INT_EN_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xB4)) +#define IO2_INT_STAT_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xA4)) +#define IO2_INT_STAT_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xA8)) +#define IO2_INT_CLR (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xAC)) + +#define IO_INT_STAT (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x80)) + +#define PARTCFG_BASE_ADDR 0x3FFF8000 +#define PARTCFG (*(volatile unsigned long *)(PARTCFG_BASE_ADDR + 0x00)) + +/* Fast I/O setup */ +#define FIO_BASE_ADDR 0x3FFFC000 +#define FIO0DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x00)) +#define FIO0MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x10)) +#define FIO0PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x14)) +#define FIO0SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x18)) +#define FIO0CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x1C)) + +#define FIO1DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x20)) +#define FIO1MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x30)) +#define FIO1PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x34)) +#define FIO1SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x38)) +#define FIO1CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x3C)) + +#define FIO2DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x40)) +#define FIO2MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x50)) +#define FIO2PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x54)) +#define FIO2SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x58)) +#define FIO2CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x5C)) + +#define FIO3DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x60)) +#define FIO3MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x70)) +#define FIO3PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x74)) +#define FIO3SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x78)) +#define FIO3CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x7C)) + +#define FIO4DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x80)) +#define FIO4MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x90)) +#define FIO4PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x94)) +#define FIO4SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x98)) +#define FIO4CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x9C)) + +/* FIOs can be accessed through WORD, HALF-WORD or BYTE. */ +#define FIO0DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x00)) +#define FIO1DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x20)) +#define FIO2DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x40)) +#define FIO3DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x60)) +#define FIO4DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x80)) + +#define FIO0DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x01)) +#define FIO1DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x21)) +#define FIO2DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x41)) +#define FIO3DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x61)) +#define FIO4DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x81)) + +#define FIO0DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x02)) +#define FIO1DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x22)) +#define FIO2DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x42)) +#define FIO3DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x62)) +#define FIO4DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x82)) + +#define FIO0DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x03)) +#define FIO1DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x23)) +#define FIO2DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x43)) +#define FIO3DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x63)) +#define FIO4DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x83)) + +#define FIO0DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x00)) +#define FIO1DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x20)) +#define FIO2DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x40)) +#define FIO3DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x60)) +#define FIO4DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x80)) + +#define FIO0DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x02)) +#define FIO1DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x22)) +#define FIO2DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x42)) +#define FIO3DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x62)) +#define FIO4DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x82)) + +#define FIO0MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x10)) +#define FIO1MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x30)) +#define FIO2MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x50)) +#define FIO3MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x70)) +#define FIO4MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x90)) + +#define FIO0MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x11)) +#define FIO1MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x31)) +#define FIO2MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x51)) +#define FIO3MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x71)) +#define FIO4MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x91)) + +#define FIO0MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x12)) +#define FIO1MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x32)) +#define FIO2MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x52)) +#define FIO3MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x72)) +#define FIO4MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x92)) + +#define FIO0MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x13)) +#define FIO1MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x33)) +#define FIO2MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x53)) +#define FIO3MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x73)) +#define FIO4MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x93)) + +#define FIO0MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x10)) +#define FIO1MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x30)) +#define FIO2MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x50)) +#define FIO3MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x70)) +#define FIO4MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x90)) + +#define FIO0MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x12)) +#define FIO1MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x32)) +#define FIO2MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x52)) +#define FIO3MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x72)) +#define FIO4MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x92)) + +#define FIO0PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x14)) +#define FIO1PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x34)) +#define FIO2PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x54)) +#define FIO3PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x74)) +#define FIO4PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x94)) + +#define FIO0PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x15)) +#define FIO1PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x35)) +#define FIO2PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x55)) +#define FIO3PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x75)) +#define FIO4PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x95)) + +#define FIO0PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x16)) +#define FIO1PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x36)) +#define FIO2PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x56)) +#define FIO3PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x76)) +#define FIO4PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x96)) + +#define FIO0PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x17)) +#define FIO1PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x37)) +#define FIO2PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x57)) +#define FIO3PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x77)) +#define FIO4PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x97)) + +#define FIO0PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x14)) +#define FIO1PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x34)) +#define FIO2PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x54)) +#define FIO3PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x74)) +#define FIO4PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x94)) + +#define FIO0PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x16)) +#define FIO1PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x36)) +#define FIO2PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x56)) +#define FIO3PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x76)) +#define FIO4PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x96)) + +#define FIO0SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x18)) +#define FIO1SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x38)) +#define FIO2SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x58)) +#define FIO3SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x78)) +#define FIO4SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x98)) + +#define FIO0SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x19)) +#define FIO1SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x39)) +#define FIO2SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x59)) +#define FIO3SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x79)) +#define FIO4SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x99)) + +#define FIO0SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1A)) +#define FIO1SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3A)) +#define FIO2SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5A)) +#define FIO3SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7A)) +#define FIO4SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9A)) + +#define FIO0SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1B)) +#define FIO1SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3B)) +#define FIO2SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5B)) +#define FIO3SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7B)) +#define FIO4SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9B)) + +#define FIO0SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x18)) +#define FIO1SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x38)) +#define FIO2SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x58)) +#define FIO3SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x78)) +#define FIO4SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x98)) + +#define FIO0SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1A)) +#define FIO1SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3A)) +#define FIO2SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5A)) +#define FIO3SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7A)) +#define FIO4SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9A)) + +#define FIO0CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1C)) +#define FIO1CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3C)) +#define FIO2CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5C)) +#define FIO3CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7C)) +#define FIO4CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9C)) + +#define FIO0CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1D)) +#define FIO1CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3D)) +#define FIO2CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5D)) +#define FIO3CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7D)) +#define FIO4CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9D)) + +#define FIO0CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1E)) +#define FIO1CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3E)) +#define FIO2CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5E)) +#define FIO3CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7E)) +#define FIO4CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9E)) + +#define FIO0CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1F)) +#define FIO1CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3F)) +#define FIO2CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5F)) +#define FIO3CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7F)) +#define FIO4CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9F)) + +#define FIO0CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1C)) +#define FIO1CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3C)) +#define FIO2CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5C)) +#define FIO3CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7C)) +#define FIO4CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9C)) + +#define FIO0CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1E)) +#define FIO1CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3E)) +#define FIO2CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5E)) +#define FIO3CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7E)) +#define FIO4CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9E)) + + +/* System Control Block(SCB) modules include Memory Accelerator Module, +Phase Locked Loop, VPB divider, Power Control, External Interrupt, +Reset, and Code Security/Debugging */ +#define SCB_BASE_ADDR 0xE01FC000 + +/* Memory Accelerator Module (MAM) */ +#define MAMCR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x000)) +#define MAMTIM (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x004)) +#define MEMMAP (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x040)) + +/* Phase Locked Loop (PLL) */ +#define PLLCON (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x080)) +#define PLLCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x084)) +#define PLLSTAT (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x088)) +#define PLLFEED (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x08C)) + +/* Power Control */ +#define PCON (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x0C0)) +#define PCONP (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x0C4)) + +/* Clock Divider */ +// #define APBDIV (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x100)) +#define CCLKCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x104)) +#define USBCLKCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x108)) +#define CLKSRCSEL (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x10C)) +#define PCLKSEL0 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A8)) +#define PCLKSEL1 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1AC)) + +/* External Interrupts */ +#define EXTINT (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x140)) +#define INTWAKE (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x144)) +#define EXTMODE (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x148)) +#define EXTPOLAR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x14C)) + +/* Reset, reset source identification */ +#define RSIR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x180)) + +/* RSID, code security protection */ +#define CSPR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x184)) + +/* AHB configuration */ +#define AHBCFG1 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x188)) +#define AHBCFG2 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x18C)) + +/* System Controls and Status */ +#define SCS (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A0)) + +/* MPMC(EMC) registers, note: all the external memory controller(EMC) registers +are for LPC24xx only. */ +#define STATIC_MEM0_BASE 0x80000000 +#define STATIC_MEM1_BASE 0x81000000 +#define STATIC_MEM2_BASE 0x82000000 +#define STATIC_MEM3_BASE 0x83000000 + +#define DYNAMIC_MEM0_BASE 0xA0000000 +#define DYNAMIC_MEM1_BASE 0xB0000000 +#define DYNAMIC_MEM2_BASE 0xC0000000 +#define DYNAMIC_MEM3_BASE 0xD0000000 + +/* External Memory Controller (EMC) */ +#define EMC_BASE_ADDR 0xFFE08000 +#define EMC_CTRL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x000)) +#define EMC_STAT (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x004)) +#define EMC_CONFIG (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x008)) + +/* Dynamic RAM access registers */ +#define EMC_DYN_CTRL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x020)) +#define EMC_DYN_RFSH (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x024)) +#define EMC_DYN_RD_CFG (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x028)) +#define EMC_DYN_RP (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x030)) +#define EMC_DYN_RAS (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x034)) +#define EMC_DYN_SREX (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x038)) +#define EMC_DYN_APR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x03C)) +#define EMC_DYN_DAL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x040)) +#define EMC_DYN_WR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x044)) +#define EMC_DYN_RC (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x048)) +#define EMC_DYN_RFC (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x04C)) +#define EMC_DYN_XSR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x050)) +#define EMC_DYN_RRD (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x054)) +#define EMC_DYN_MRD (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x058)) + +#define EMC_DYN_CFG0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x100)) +#define EMC_DYN_RASCAS0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x104)) +#define EMC_DYN_CFG1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x120)) +#define EMC_DYN_RASCAS1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x124)) +#define EMC_DYN_CFG2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x140)) +#define EMC_DYN_RASCAS2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x144)) +#define EMC_DYN_CFG3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x160)) +#define EMC_DYN_RASCAS3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x164)) + +/* static RAM access registers */ +#define EMC_STA_CFG0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x200)) +#define EMC_STA_WAITWEN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x204)) +#define EMC_STA_WAITOEN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x208)) +#define EMC_STA_WAITRD0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x20C)) +#define EMC_STA_WAITPAGE0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x210)) +#define EMC_STA_WAITWR0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x214)) +#define EMC_STA_WAITTURN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x218)) + +#define EMC_STA_CFG1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x220)) +#define EMC_STA_WAITWEN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x224)) +#define EMC_STA_WAITOEN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x228)) +#define EMC_STA_WAITRD1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x22C)) +#define EMC_STA_WAITPAGE1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x230)) +#define EMC_STA_WAITWR1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x234)) +#define EMC_STA_WAITTURN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x238)) + +#define EMC_STA_CFG2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x240)) +#define EMC_STA_WAITWEN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x244)) +#define EMC_STA_WAITOEN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x248)) +#define EMC_STA_WAITRD2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x24C)) +#define EMC_STA_WAITPAGE2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x250)) +#define EMC_STA_WAITWR2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x254)) +#define EMC_STA_WAITTURN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x258)) + +#define EMC_STA_CFG3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x260)) +#define EMC_STA_WAITWEN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x264)) +#define EMC_STA_WAITOEN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x268)) +#define EMC_STA_WAITRD3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x26C)) +#define EMC_STA_WAITPAGE3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x270)) +#define EMC_STA_WAITWR3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x274)) +#define EMC_STA_WAITTURN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x278)) + +#define EMC_STA_EXT_WAIT (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x080)) + + +/* Timer 0 */ +#define TMR0_BASE_ADDR 0xE0004000 +#define T0IR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x00)) +#define T0TCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x04)) +#define T0TC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x08)) +#define T0PR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x0C)) +#define T0PC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x10)) +#define T0MCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x14)) +#define T0MR0 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x18)) +#define T0MR1 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x1C)) +#define T0MR2 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x20)) +#define T0MR3 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x24)) +#define T0CCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x28)) +#define T0CR0 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x2C)) +#define T0CR1 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x30)) +#define T0CR2 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x34)) +#define T0CR3 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x38)) +#define T0EMR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x3C)) +#define T0CTCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x70)) + +/* Timer 1 */ +#define TMR1_BASE_ADDR 0xE0008000 +#define T1IR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x00)) +#define T1TCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x04)) +#define T1TC (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x08)) +#define T1PR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x0C)) +#define T1PC (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x10)) +#define T1MCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x14)) +#define T1MR0 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x18)) +#define T1MR1 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x1C)) +#define T1MR2 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x20)) +#define T1MR3 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x24)) +#define T1CCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x28)) +#define T1CR0 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x2C)) +#define T1CR1 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x30)) +#define T1CR2 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x34)) +#define T1CR3 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x38)) +#define T1EMR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x3C)) +#define T1CTCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x70)) + +/* Timer 2 */ +#define TMR2_BASE_ADDR 0xE0070000 +#define T2IR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x00)) +#define T2TCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x04)) +#define T2TC (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x08)) +#define T2PR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x0C)) +#define T2PC (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x10)) +#define T2MCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x14)) +#define T2MR0 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x18)) +#define T2MR1 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x1C)) +#define T2MR2 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x20)) +#define T2MR3 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x24)) +#define T2CCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x28)) +#define T2CR0 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x2C)) +#define T2CR1 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x30)) +#define T2CR2 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x34)) +#define T2CR3 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x38)) +#define T2EMR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x3C)) +#define T2CTCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x70)) + +/* Timer 3 */ +#define TMR3_BASE_ADDR 0xE0074000 +#define T3IR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x00)) +#define T3TCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x04)) +#define T3TC (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x08)) +#define T3PR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x0C)) +#define T3PC (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x10)) +#define T3MCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x14)) +#define T3MR0 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x18)) +#define T3MR1 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x1C)) +#define T3MR2 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x20)) +#define T3MR3 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x24)) +#define T3CCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x28)) +#define T3CR0 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x2C)) +#define T3CR1 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x30)) +#define T3CR2 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x34)) +#define T3CR3 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x38)) +#define T3EMR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x3C)) +#define T3CTCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x70)) + + +/* Pulse Width Modulator (PWM) */ +#define PWM0_BASE_ADDR 0xE0014000 +#define PWM0IR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x00)) +#define PWM0TCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x04)) +#define PWM0TC (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x08)) +#define PWM0PR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x0C)) +#define PWM0PC (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x10)) +#define PWM0MCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x14)) +#define PWM0MR0 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x18)) +#define PWM0MR1 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x1C)) +#define PWM0MR2 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x20)) +#define PWM0MR3 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x24)) +#define PWM0CCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x28)) +#define PWM0CR0 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x2C)) +#define PWM0CR1 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x30)) +#define PWM0CR2 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x34)) +#define PWM0CR3 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x38)) +#define PWM0EMR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x3C)) +#define PWM0MR4 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x40)) +#define PWM0MR5 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x44)) +#define PWM0MR6 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x48)) +#define PWM0PCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x4C)) +#define PWM0LER (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x50)) +#define PWM0CTCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x70)) + +#define PWM1_BASE_ADDR 0xE0018000 +#define PWM1IR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x00)) +#define PWM1TCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x04)) +#define PWM1TC (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x08)) +#define PWM1PR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x0C)) +#define PWM1PC (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x10)) +#define PWM1MCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x14)) +#define PWM1MR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x18)) +#define PWM1MR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x1C)) +#define PWM1MR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x20)) +#define PWM1MR3 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x24)) +#define PWM1CCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x28)) +#define PWM1CR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x2C)) +#define PWM1CR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x30)) +#define PWM1CR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x34)) +#define PWM1CR3 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x38)) +#define PWM1EMR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x3C)) +#define PWM1MR4 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x40)) +#define PWM1MR5 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x44)) +#define PWM1MR6 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x48)) +#define PWM1PCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x4C)) +#define PWM1LER (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x50)) +#define PWM1CTCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x70)) + + +/* Universal Asynchronous Receiver Transmitter 0 (UART0) */ +#define UART0_BASE_ADDR 0xE000C000 +#define U0RBR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0THR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0DLL (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0DLM (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x04)) +#define U0IER (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x04)) +#define U0IIR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x08)) +#define U0FCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x08)) +#define U0LCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x0C)) +#define U0LSR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x14)) +#define U0SCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x1C)) +#define U0ACR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x20)) +#define U0ICR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x24)) +#define U0FDR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x28)) +#define U0TER (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 1 (UART1) */ +#define UART1_BASE_ADDR 0xE0010000 +#define U1RBR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1THR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1DLL (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1DLM (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x04)) +#define U1IER (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x04)) +#define U1IIR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x08)) +#define U1FCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x08)) +#define U1LCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x0C)) +#define U1MCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x10)) +#define U1LSR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x14)) +#define U1MSR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x18)) +#define U1SCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x1C)) +#define U1ACR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x20)) +#define U1FDR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x28)) +#define U1TER (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 2 (UART2) */ +#define UART2_BASE_ADDR 0xE0078000 +#define U2RBR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2THR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2DLL (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2DLM (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x04)) +#define U2IER (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x04)) +#define U2IIR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x08)) +#define U2FCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x08)) +#define U2LCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x0C)) +#define U2LSR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x14)) +#define U2SCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x1C)) +#define U2ACR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x20)) +#define U2ICR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x24)) +#define U2FDR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x28)) +#define U2TER (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 3 (UART3) */ +#define UART3_BASE_ADDR 0xE007C000 +#define U3RBR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3THR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3DLL (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3DLM (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x04)) +#define U3IER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x04)) +#define U3IIR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x08)) +#define U3FCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x08)) +#define U3LCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x0C)) +#define U3LSR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x14)) +#define U3SCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x1C)) +#define U3ACR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x20)) +#define U3ICR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x24)) +#define U3FDR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x28)) +#define U3TER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x30)) + +/* I2C Interface 0 */ +#define I2C0_BASE_ADDR 0xE001C000 +#define I20CONSET (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x00)) +#define I20STAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x04)) +#define I20DAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x08)) +#define I20ADR (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x0C)) +#define I20SCLH (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x10)) +#define I20SCLL (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x14)) +#define I20CONCLR (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x18)) + +/* I2C Interface 1 */ +#define I2C1_BASE_ADDR 0xE005C000 +#define I21CONSET (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x00)) +#define I21STAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x04)) +#define I21DAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x08)) +#define I21ADR (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x0C)) +#define I21SCLH (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x10)) +#define I21SCLL (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x14)) +#define I21CONCLR (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x18)) + +/* I2C Interface 2 */ +#define I2C2_BASE_ADDR 0xE0080000 +#define I22CONSET (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x00)) +#define I22STAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x04)) +#define I22DAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x08)) +#define I22ADR (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x0C)) +#define I22SCLH (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x10)) +#define I22SCLL (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x14)) +#define I22CONCLR (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x18)) + +/* SPI0 (Serial Peripheral Interface 0) */ +#define SPI0_BASE_ADDR 0xE0020000 +#define S0SPCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x00)) +#define S0SPSR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x04)) +#define S0SPDR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x08)) +#define S0SPCCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x0C)) +#define S0SPINT (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x1C)) + +/* SSP0 Controller */ +#define SSP0_BASE_ADDR 0xE0068000 +#define SSP0CR0 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x00)) +#define SSP0CR1 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x04)) +#define SSP0DR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x08)) +#define SSP0SR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x0C)) +#define SSP0CPSR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x10)) +#define SSP0IMSC (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x14)) +#define SSP0RIS (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x18)) +#define SSP0MIS (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x1C)) +#define SSP0ICR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x20)) +#define SSP0DMACR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x24)) + +/* SSP1 Controller */ +#define SSP1_BASE_ADDR 0xE0030000 +#define SSP1CR0 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x00)) +#define SSP1CR1 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x04)) +#define SSP1DR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x08)) +#define SSP1SR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x0C)) +#define SSP1CPSR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x10)) +#define SSP1IMSC (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x14)) +#define SSP1RIS (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x18)) +#define SSP1MIS (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x1C)) +#define SSP1ICR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x20)) +#define SSP1DMACR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x24)) + + +/* Real Time Clock */ +#define RTC_BASE_ADDR 0xE0024000 +#define RTC_ILR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x00)) +#define RTC_CTC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x04)) +#define RTC_CCR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x08)) +#define RTC_CIIR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x0C)) +#define RTC_AMR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x10)) +#define RTC_CTIME0 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x14)) +#define RTC_CTIME1 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x18)) +#define RTC_CTIME2 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x1C)) +#define RTC_SEC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x20)) +#define RTC_MIN (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x24)) +#define RTC_HOUR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x28)) +#define RTC_DOM (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x2C)) +#define RTC_DOW (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x30)) +#define RTC_DOY (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x34)) +#define RTC_MONTH (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x38)) +#define RTC_YEAR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x3C)) +#define RTC_CISS (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x40)) +#define RTC_ALSEC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x60)) +#define RTC_ALMIN (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x64)) +#define RTC_ALHOUR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x68)) +#define RTC_ALDOM (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x6C)) +#define RTC_ALDOW (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x70)) +#define RTC_ALDOY (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x74)) +#define RTC_ALMON (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x78)) +#define RTC_ALYEAR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x7C)) +#define RTC_PREINT (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x80)) +#define RTC_PREFRAC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x84)) + + +/* A/D Converter 0 (AD0) */ +#define AD0_BASE_ADDR 0xE0034000 +#define AD0CR (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x00)) +#define AD0GDR (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x04)) +#define AD0INTEN (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x0C)) +#define AD0DR0 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x10)) +#define AD0DR1 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x14)) +#define AD0DR2 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x18)) +#define AD0DR3 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x1C)) +#define AD0DR4 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x20)) +#define AD0DR5 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x24)) +#define AD0DR6 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x28)) +#define AD0DR7 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x2C)) +#define AD0STAT (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x30)) + + +/* D/A Converter */ +#define DAC_BASE_ADDR 0xE006C000 +#define DACR (*(volatile unsigned long *)(DAC_BASE_ADDR + 0x00)) + + +/* Watchdog */ +#define WDG_BASE_ADDR 0xE0000000 +#define WDMOD (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x00)) +#define WDTC (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x04)) +#define WDFEED (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x08)) +#define WDTV (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x0C)) +#define WDCLKSEL (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x10)) + +/* CAN CONTROLLERS AND ACCEPTANCE FILTER */ +#define CAN_ACCEPT_BASE_ADDR 0xE003C000 +#define CAN_AFMR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x00)) +#define CAN_SFF_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x04)) +#define CAN_SFF_GRP_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x08)) +#define CAN_EFF_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x0C)) +#define CAN_EFF_GRP_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x10)) +#define CAN_EOT (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x14)) +#define CAN_LUT_ERR_ADR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x18)) +#define CAN_LUT_ERR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x1C)) + +#define CAN_CENTRAL_BASE_ADDR 0xE0040000 +#define CAN_TX_SR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x00)) +#define CAN_RX_SR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x04)) +#define CAN_MSR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x08)) + +#define CAN1_BASE_ADDR 0xE0044000 +#define CAN1MOD (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x00)) +#define CAN1CMR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x04)) +#define CAN1GSR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x08)) +#define CAN1ICR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x0C)) +#define CAN1IER (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x10)) +#define CAN1BTR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x14)) +#define CAN1EWL (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x18)) +#define CAN1SR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x1C)) +#define CAN1RFS (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x20)) +#define CAN1RID (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x24)) +#define CAN1RDA (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x28)) +#define CAN1RDB (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x2C)) + +#define CAN1TFI1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x30)) +#define CAN1TID1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x34)) +#define CAN1TDA1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x38)) +#define CAN1TDB1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x3C)) +#define CAN1TFI2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x40)) +#define CAN1TID2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x44)) +#define CAN1TDA2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x48)) +#define CAN1TDB2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x4C)) +#define CAN1TFI3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x50)) +#define CAN1TID3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x54)) +#define CAN1TDA3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x58)) +#define CAN1TDB3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x5C)) + +#define CAN2_BASE_ADDR 0xE0048000 +#define CAN2MOD (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x00)) +#define CAN2CMR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x04)) +#define CAN2GSR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x08)) +#define CAN2ICR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x0C)) +#define CAN2IER (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x10)) +#define CAN2BTR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x14)) +#define CAN2EWL (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x18)) +#define CAN2SR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x1C)) +#define CAN2RFS (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x20)) +#define CAN2RID (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x24)) +#define CAN2RDA (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x28)) +#define CAN2RDB (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x2C)) + +#define CAN2TFI1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x30)) +#define CAN2TID1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x34)) +#define CAN2TDA1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x38)) +#define CAN2TDB1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x3C)) +#define CAN2TFI2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x40)) +#define CAN2TID2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x44)) +#define CAN2TDA2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x48)) +#define CAN2TDB2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x4C)) +#define CAN2TFI3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x50)) +#define CAN2TID3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x54)) +#define CAN2TDA3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x58)) +#define CAN2TDB3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x5C)) + + +/* MultiMedia Card Interface(MCI) Controller */ +#define MCI_BASE_ADDR 0xE008C000 +#define MCI_POWER (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x00)) +#define MCI_CLOCK (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x04)) +#define MCI_ARGUMENT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x08)) +#define MCI_COMMAND (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x0C)) +#define MCI_RESP_CMD (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x10)) +#define MCI_RESP0 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x14)) +#define MCI_RESP1 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x18)) +#define MCI_RESP2 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x1C)) +#define MCI_RESP3 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x20)) +#define MCI_DATA_TMR (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x24)) +#define MCI_DATA_LEN (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x28)) +#define MCI_DATA_CTRL (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x2C)) +#define MCI_DATA_CNT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x30)) +#define MCI_STATUS (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x34)) +#define MCI_CLEAR (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x38)) +#define MCI_MASK0 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x3C)) +#define MCI_MASK1 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x40)) +#define MCI_FIFO_CNT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x48)) +#define MCI_FIFO (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x80)) + + +/* I2S Interface Controller (I2S) */ +#define I2S_BASE_ADDR 0xE0088000 +#define I2S_DAO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x00)) +#define I2S_DAI (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x04)) +#define I2S_TX_FIFO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x08)) +#define I2S_RX_FIFO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x0C)) +#define I2S_STATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x10)) +#define I2S_DMA1 (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x14)) +#define I2S_DMA2 (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x18)) +#define I2S_IRQ (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x1C)) +#define I2S_TXRATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x20)) +#define I2S_RXRATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x24)) + + +/* General-purpose DMA Controller */ +#define DMA_BASE_ADDR 0xFFE04000 +#define GPDMA_INT_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x000)) +#define GPDMA_INT_TCSTAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x004)) +#define GPDMA_INT_TCCLR (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x008)) +#define GPDMA_INT_ERR_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x00C)) +#define GPDMA_INT_ERR_CLR (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x010)) +#define GPDMA_RAW_INT_TCSTAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x014)) +#define GPDMA_RAW_INT_ERR_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x018)) +#define GPDMA_ENABLED_CHNS (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x01C)) +#define GPDMA_SOFT_BREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x020)) +#define GPDMA_SOFT_SREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x024)) +#define GPDMA_SOFT_LBREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x028)) +#define GPDMA_SOFT_LSREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x02C)) +#define GPDMA_CONFIG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x030)) +#define GPDMA_SYNC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x034)) + +/* DMA channel 0 registers */ +#define GPDMA_CH0_SRC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x100)) +#define GPDMA_CH0_DEST (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x104)) +#define GPDMA_CH0_LLI (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x108)) +#define GPDMA_CH0_CTRL (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x10C)) +#define GPDMA_CH0_CFG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x110)) + +/* DMA channel 1 registers */ +#define GPDMA_CH1_SRC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x120)) +#define GPDMA_CH1_DEST (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x124)) +#define GPDMA_CH1_LLI (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x128)) +#define GPDMA_CH1_CTRL (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x12C)) +#define GPDMA_CH1_CFG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x130)) + + +/* USB Controller */ +#define USB_INT_BASE_ADDR 0xE01FC1C0 +#define USB_BASE_ADDR 0xFFE0C200 /* USB Base Address */ + +#define USB_INT_STAT (*(volatile unsigned long *)(USB_INT_BASE_ADDR + 0x00)) + +/* USB Device Interrupt Registers */ +#define DEV_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x00)) +#define DEV_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x04)) +#define DEV_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x08)) +#define DEV_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x0C)) +#define DEV_INT_PRIO (*(volatile unsigned long *)(USB_BASE_ADDR + 0x2C)) + +/* USB Device Endpoint Interrupt Registers */ +#define EP_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x30)) +#define EP_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x34)) +#define EP_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x38)) +#define EP_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x3C)) +#define EP_INT_PRIO (*(volatile unsigned long *)(USB_BASE_ADDR + 0x40)) + +/* USB Device Endpoint Realization Registers */ +#define REALIZE_EP (*(volatile unsigned long *)(USB_BASE_ADDR + 0x44)) +#define EP_INDEX (*(volatile unsigned long *)(USB_BASE_ADDR + 0x48)) +#define MAXPACKET_SIZE (*(volatile unsigned long *)(USB_BASE_ADDR + 0x4C)) + +/* USB Device Command Reagisters */ +#define CMD_CODE (*(volatile unsigned long *)(USB_BASE_ADDR + 0x10)) +#define CMD_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x14)) + +/* USB Device Data Transfer Registers */ +#define RX_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x18)) +#define TX_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x1C)) +#define RX_PLENGTH (*(volatile unsigned long *)(USB_BASE_ADDR + 0x20)) +#define TX_PLENGTH (*(volatile unsigned long *)(USB_BASE_ADDR + 0x24)) +#define USB_CTRL (*(volatile unsigned long *)(USB_BASE_ADDR + 0x28)) + +/* USB Device DMA Registers */ +#define DMA_REQ_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x50)) +#define DMA_REQ_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x54)) +#define DMA_REQ_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x58)) +#define UDCA_HEAD (*(volatile unsigned long *)(USB_BASE_ADDR + 0x80)) +#define EP_DMA_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x84)) +#define EP_DMA_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x88)) +#define EP_DMA_DIS (*(volatile unsigned long *)(USB_BASE_ADDR + 0x8C)) +#define DMA_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x90)) +#define DMA_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x94)) +#define EOT_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA0)) +#define EOT_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA4)) +#define EOT_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA8)) +#define NDD_REQ_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xAC)) +#define NDD_REQ_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB0)) +#define NDD_REQ_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB4)) +#define SYS_ERR_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB8)) +#define SYS_ERR_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xBC)) +#define SYS_ERR_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xC0)) + +/* USB Host and OTG registers are for LPC24xx only */ +/* USB Host Controller */ +#define USBHC_BASE_ADDR 0xFFE0C000 +#define HC_REVISION (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x00)) +#define HC_CONTROL (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x04)) +#define HC_CMD_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x08)) +#define HC_INT_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x0C)) +#define HC_INT_EN (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x10)) +#define HC_INT_DIS (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x14)) +#define HC_HCCA (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x18)) +#define HC_PERIOD_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x1C)) +#define HC_CTRL_HEAD_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x20)) +#define HC_CTRL_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x24)) +#define HC_BULK_HEAD_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x28)) +#define HC_BULK_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x2C)) +#define HC_DONE_HEAD (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x30)) +#define HC_FM_INTERVAL (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x34)) +#define HC_FM_REMAINING (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x38)) +#define HC_FM_NUMBER (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x3C)) +#define HC_PERIOD_START (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x40)) +#define HC_LS_THRHLD (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x44)) +#define HC_RH_DESCA (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x48)) +#define HC_RH_DESCB (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x4C)) +#define HC_RH_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x50)) +#define HC_RH_PORT_STAT1 (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x54)) +#define HC_RH_PORT_STAT2 (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x58)) + +/* USB OTG Controller */ +#define USBOTG_BASE_ADDR 0xFFE0C100 +#define OTG_INT_STAT (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x00)) +#define OTG_INT_EN (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x04)) +#define OTG_INT_SET (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x08)) +#define OTG_INT_CLR (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x0C)) +/* On LPC23xx, the name is USBPortSel, on LPC24xx, the name is OTG_STAT_CTRL */ +#define OTG_STAT_CTRL (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x10)) +#define OTG_TIMER (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x14)) + +#define USBOTG_I2C_BASE_ADDR 0xFFE0C300 +#define OTG_I2C_RX (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x00)) +#define OTG_I2C_TX (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x00)) +#define OTG_I2C_STS (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x04)) +#define OTG_I2C_CTL (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x08)) +#define OTG_I2C_CLKHI (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x0C)) +#define OTG_I2C_CLKLO (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x10)) + +/* On LPC23xx, the names are USBClkCtrl and USBClkSt; on LPC24xx, the names are +OTG_CLK_CTRL and OTG_CLK_STAT respectively. */ +#define USBOTG_CLK_BASE_ADDR 0xFFE0CFF0 +#define OTG_CLK_CTRL (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x04)) +#define OTG_CLK_STAT (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x08)) + +/* Note: below three register name convention is for LPC23xx USB device only, match +with the spec. update in USB Device Section. */ +#define USBPortSel (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x10)) +#define USBClkCtrl (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x04)) +#define USBClkSt (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x08)) + +/* Ethernet MAC (32 bit data bus) -- all registers are RW unless indicated in parentheses */ +#define MAC_BASE_ADDR 0xFFE00000 /* AHB Peripheral # 0 */ +#define MAC_MAC1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x000)) /* MAC config reg 1 */ +#define MAC_MAC2 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x004)) /* MAC config reg 2 */ +#define MAC_IPGT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x008)) /* b2b InterPacketGap reg */ +#define MAC_IPGR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x00C)) /* non b2b InterPacketGap reg */ +#define MAC_CLRT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x010)) /* CoLlision window/ReTry reg */ +#define MAC_MAXF (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x014)) /* MAXimum Frame reg */ +#define MAC_SUPP (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x018)) /* PHY SUPPort reg */ +#define MAC_TEST (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x01C)) /* TEST reg */ +#define MAC_MCFG (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x020)) /* MII Mgmt ConFiG reg */ +#define MAC_MCMD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x024)) /* MII Mgmt CoMmanD reg */ +#define MAC_MADR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x028)) /* MII Mgmt ADdRess reg */ +#define MAC_MWTD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x02C)) /* MII Mgmt WriTe Data reg (WO) */ +#define MAC_MRDD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x030)) /* MII Mgmt ReaD Data reg (RO) */ +#define MAC_MIND (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x034)) /* MII Mgmt INDicators reg (RO) */ + +#define MAC_SA0 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x040)) /* Station Address 0 reg */ +#define MAC_SA1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x044)) /* Station Address 1 reg */ +#define MAC_SA2 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x048)) /* Station Address 2 reg */ + +#define MAC_COMMAND (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x100)) /* Command reg */ +#define MAC_STATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x104)) /* Status reg (RO) */ +#define MAC_RXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x108)) /* Rx descriptor base address reg */ +#define MAC_RXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x10C)) /* Rx status base address reg */ +#define MAC_RXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x110)) /* Rx number of descriptors reg */ +#define MAC_RXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x114)) /* Rx produce index reg (RO) */ +#define MAC_RXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x118)) /* Rx consume index reg */ +#define MAC_TXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x11C)) /* Tx descriptor base address reg */ +#define MAC_TXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x120)) /* Tx status base address reg */ +#define MAC_TXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x124)) /* Tx number of descriptors reg */ +#define MAC_TXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x128)) /* Tx produce index reg */ +#define MAC_TXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x12C)) /* Tx consume index reg (RO) */ + +#define MAC_TSV0 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x158)) /* Tx status vector 0 reg (RO) */ +#define MAC_TSV1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x15C)) /* Tx status vector 1 reg (RO) */ +#define MAC_RSV (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x160)) /* Rx status vector reg (RO) */ + +#define MAC_FLOWCONTROLCNT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x170)) /* Flow control counter reg */ +#define MAC_FLOWCONTROLSTS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x174)) /* Flow control status reg */ + +#define MAC_RXFILTERCTRL (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x200)) /* Rx filter ctrl reg */ +#define MAC_RXFILTERWOLSTS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x204)) /* Rx filter WoL status reg (RO) */ +#define MAC_RXFILTERWOLCLR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x208)) /* Rx filter WoL clear reg (WO) */ + +#define MAC_HASHFILTERL (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x210)) /* Hash filter LSBs reg */ +#define MAC_HASHFILTERH (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x214)) /* Hash filter MSBs reg */ + +#define MAC_INTSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE0)) /* Interrupt status reg (RO) */ +#define MAC_INTENABLE (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE4)) /* Interrupt enable reg */ +#define MAC_INTCLEAR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE8)) /* Interrupt clear reg (WO) */ +#define MAC_INTSET (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFEC)) /* Interrupt set reg (WO) */ + +#define MAC_POWERDOWN (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFF4)) /* Power-down reg */ +#define MAC_MODULEID (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFFC)) /* Module ID reg (RO) */ + +#endif // __LPC23xx_H + diff --git a/src/platform/lpc23xx/conf.lua b/src/platform/lpc23xx/conf.lua new file mode 100644 index 00000000..ac142d1a --- /dev/null +++ b/src/platform/lpc23xx/conf.lua @@ -0,0 +1,43 @@ +-- Configuration file for the LPC23xx backend + +local cpumode = ( builder:get_option( 'cpumode' ) or 'arm' ):lower() + +specific_files = "startup.s irq.c target.c platform.c platform_int.c" + +local ldscript = "lpc2368.lds" + +-- Prepend with path +specific_files = utils.prepend_path( specific_files, sf( "src/platform/%s", platform ) ) +specific_files = specific_files .. " src/platform/arm_utils.s src/platform/arm_cortex_interrupts.c" +ldscript = sf( "src/platform/%s/%s", platform, ldscript ) + +addm{ "FOR" .. comp.cpu:upper(), 'gcc' } + +-- Standard GCC Flags +addcf{ '-ffunction-sections', '-fdata-sections', '-fno-strict-aliasing', '-Wall' } +addlf{ '-nostartfiles', '-nostdlib', '-T', ldscript, '-Wl,--gc-sections', '-Wl,--allow-multiple-definition' } +addaf{ '-x', 'assembler-with-cpp', '-Wall' } +addlib{ 'c','gcc','m' } + +-- Specific target configuration +local target_flags = '-mcpu=arm7tdmi' +if cpumode == 'thumb' then + target_flags = { target_flags, '-mthumb' } + addm( 'CPUMODE_THUMB' ) +else + addm( 'CPUMODE_ARM' ) +end + +addcf( target_flags ) +addlf{ target_flags, '-Wl,-e,entry' } +addaf{ target_flags, '-D___ASSEMBLY__' } + +-- Toolset data +tools.lpc23xx = {} + +-- Array of file names that will be checked against the 'prog' target; their absence will force a rebuild +tools.lpc23xx.prog_flist = { output .. ".hex" } + +-- We use 'gcc' as the assembler +toolset.asm = toolset.compile + diff --git a/src/platform/lpc23xx/cpu_lpc2368.h b/src/platform/lpc23xx/cpu_lpc2368.h new file mode 100644 index 00000000..4b64b341 --- /dev/null +++ b/src/platform/lpc23xx/cpu_lpc2368.h @@ -0,0 +1,48 @@ +// LPC2368 CPU definitions + +#ifndef __CPU_LPC2368_H__ +#define __CPU_LPC2368_H__ + +#include "stacks.h" +#include "target.h" +#include "platform_ints.h" + +// Number of resources (0 if not available/not implemented) +#define NUM_PIO 16 +#define NUM_SPI 1 +#define NUM_UART 3 +#define NUM_TIMER 4 +#define NUM_PHYS_TIMER 0 +#define NUM_PWM 6 +#define NUM_ADC 6 +#define NUM_CAN 2 + +// ADC Configuration Params +#define ADC_BIT_RESOLUTION 10 + +// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used) +#define CPU_FREQUENCY Fcclk + +// 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 + +// Internal RAM +#define SRAM_ORIGIN 0x40000000 +#define SRAM_SIZE ( 32 * 1024 ) // [TODO]: make this 96k? +#define INTERNAL_RAM1_FIRST_FREE end +#define INTERNAL_RAM1_LAST_FREE ( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) + +// 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_LPC2368_H__ + diff --git a/src/platform/lpc23xx/irq.c b/src/platform/lpc23xx/irq.c new file mode 100644 index 00000000..cc51cff9 --- /dev/null +++ b/src/platform/lpc23xx/irq.c @@ -0,0 +1,108 @@ +/***************************************************************************** + * irq.c: Interrupt handler C file for NXP LPC23xx/24xx Family Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.07.13 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ +#include "LPC23xx.h" /* LPC23XX/24xx Peripheral Registers */ +#include "type.h" +#include "irq.h" +#if FIQ +#include "timer.h" +#endif + +/****************************************************************************** +** Function name: FIQ_Handler +** +** Descriptions: FIQ interrupt handler called in startup +** parameters: +** +** Returned value: +** +******************************************************************************/ +// [TODO] make this GCC compatible if needed +#if FIQ +void FIQ_Handler( void ) __irq +{ +//#if FIQ + if ( VICFIQStatus & (0x1<<4) && VICIntEnable & (0x1<<4) ) + { + Timer0FIQHandler(); + } + if ( VICFIQStatus & (0x1<<5) && VICIntEnable & (0x1<<5) ) + { + Timer1FIQHandler(); + } + return; +//#endif +} +#endif + +/* Initialize the interrupt controller */ +/****************************************************************************** +** Function name: init_VIC +** +** Descriptions: Initialize VIC interrupt controller. +** parameters: None +** Returned value: None +** +******************************************************************************/ +void init_VIC(void) +{ + DWORD i = 0; + DWORD *vect_addr, *vect_prio; + + /* initialize VIC*/ + VICIntEnClr = 0xffffffff; + VICVectAddr = 0; + VICIntSelect = 0; + + /* set all the vector and vector control register to 0 */ + for ( i = 0; i < VIC_SIZE; i++ ) + { + vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + i*4); + vect_prio = (DWORD *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + i*4); + *vect_addr = 0x0; + *vect_prio = 0xF; + } + return; +} + +/****************************************************************************** +** Function name: install_irq +** +** Descriptions: Install interrupt handler +** parameters: Interrupt number, interrupt handler address, +** interrupt priority +** Returned value: true or false, return false if IntNum is out of range +** +******************************************************************************/ +DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority ) +{ + DWORD *vect_addr; + DWORD *vect_prio; + + VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */ + if ( IntNumber >= VIC_SIZE ) + { + return ( FALSE ); + } + else + { + /* find first un-assigned VIC address for the handler */ + vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4); + vect_prio = (DWORD *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + IntNumber*4); + *vect_addr = (DWORD)HandlerAddr; /* set interrupt vector */ + *vect_prio = Priority; + VICIntEnable |= 1 << IntNumber; /* Enable Interrupt */ + return( TRUE ); + } +} + +/****************************************************************************** +** End Of File +******************************************************************************/ diff --git a/src/platform/lpc23xx/irq.h b/src/platform/lpc23xx/irq.h new file mode 100644 index 00000000..e0fb898e --- /dev/null +++ b/src/platform/lpc23xx/irq.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * irq.h: Interrupt related Header file for NXP LPC23xx/24xx Family + * Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.09.01 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ +#ifndef __IRQ_H +#define __IRQ_H + +#define I_Bit 0x80 +#define F_Bit 0x40 + +#define SYS32Mode 0x1F +#define IRQ32Mode 0x12 +#define FIQ32Mode 0x11 + +/* Use FIQ, set below to 1, otherwise, it's 0 */ +#define FIQ 0 + +#define HIGHEST_PRIORITY 0x01 +#define LOWEST_PRIORITY 0x0F + +#define WDT_INT 0 +#define SWI_INT 1 +#define ARM_CORE0_INT 2 +#define ARM_CORE1_INT 3 +#define TIMER0_INT 4 +#define TIMER1_INT 5 +#define UART0_INT 6 +#define UART1_INT 7 +#define PWM0_1_INT 8 +#define I2C0_INT 9 +#define SPI0_INT 10 /* SPI and SSP0 share VIC slot */ +#define SSP0_INT 10 +#define SSP1_INT 11 +#define PLL_INT 12 +#define RTC_INT 13 +#define EINT0_INT 14 +#define EINT1_INT 15 +#define EINT2_INT 16 +#define EINT3_INT 17 +#define ADC0_INT 18 +#define I2C1_INT 19 +#define BOD_INT 20 +#define EMAC_INT 21 +#define USB_INT 22 +#define CAN_INT 23 +#define MCI_INT 24 +#define GPDMA_INT 25 +#define TIMER2_INT 26 +#define TIMER3_INT 27 +#define UART2_INT 28 +#define UART3_INT 29 +#define I2C2_INT 30 +#define I2S_INT 31 + +#define VIC_SIZE 32 + +#define VECT_ADDR_INDEX 0x100 +#define VECT_PRIO_INDEX 0x200 + +/* Be aware that, from compiler to compiler, nested interrupt will have to +be handled differently. More details can be found in Philips LPC2000 +family app-note AN10381 */ + +void init_VIC( void ); +DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority ); + +#endif /* end __IRQ_H */ + +/****************************************************************************** +** End Of File +******************************************************************************/ + diff --git a/src/platform/lpc23xx/lpc2368.lds b/src/platform/lpc23xx/lpc2368.lds new file mode 100644 index 00000000..0af589fb --- /dev/null +++ b/src/platform/lpc23xx/lpc2368.lds @@ -0,0 +1,63 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +MEMORY +{ + sram (W!RX) : ORIGIN = 0x40000000, LENGTH = 32k + flash (RX) : ORIGIN = 0x0, LENGTH = 512k +} + +SECTIONS +{ + .fixed : + { + . = ALIGN(4); + _sfixed = .; + PROVIDE(stext = .); + KEEP(*(.vectors)) + *(.text .text.*) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + . = ALIGN(4); + _efixed = .; + PROVIDE(etext = .); + _fini = .; + *(.fini) + } >flash + + .relocate : AT (_efixed) + { + . = ALIGN(4); + _srelocate = .; + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(4); + _erelocate = .; + } >sram + + .ARM.extab : + { + *(.ARM.extab*) + } >sram + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx*) + } >sram + __exidx_end = .; + + .bss (NOLOAD) : { + _szero = .; + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + _ezero = .; + } >sram + + end = .; +} diff --git a/src/platform/lpc23xx/platform.c b/src/platform/lpc23xx/platform.c new file mode 100644 index 00000000..8a3e7984 --- /dev/null +++ b/src/platform/lpc23xx/platform.c @@ -0,0 +1,834 @@ +// Platform-dependent functions + +#include "platform.h" +#include "type.h" +#include "devman.h" +#include "genstd.h" +#include "stacks.h" +#include +#include +#include +#include +#include +#include "utils.h" +#include "common.h" +#include "elua_adc.h" +#include "platform_conf.h" +#include "buf.h" +#include "elua_int.h" +#include "arm_constants.h" + +// Platform includes +#include "LPC23xx.h" /* LPC23xx/24xx definitions */ +#include "target.h" +#include "irq.h" +#include "uart.h" + +extern void enable_ints(); +extern void disable_ints(); + +// **************************************************************************** +// Platform initialization + +static void platform_setup_timers(); +static void platform_setup_pwm(); +static void platform_setup_adcs(); + +// Power management definitions +enum +{ + PCUART2 = 1ULL << 24, + PCUART3 = 1ULL << 25, + PCTIM2 = 1ULL << 22, + PCTIM3 = 1ULL << 23, + PCADC = 1ULL << 12 +}; + + +// CPU initialization +static void platform_setup_cpu() +{ + // Enable clock for UART2 and UART3 + PCONP |= PCUART2 | PCUART3; + + // Set clock for all the UARTs to the system clock (helps in baud generation) + PCLKSEL0 = ( PCLKSEL0 & 0xFFFFFC3F ) | 0x00000140; + PCLKSEL1 = ( PCLKSEL1 & 0xFFF0FFFF ) | 0x00050000; + + // Enable clock for Timer 2 and Timer 3 + PCONP |= PCTIM2 | PCTIM3; + + // Setup GPIO0 and GPIO1 in fast mode + SCS |= 1; +} + +int platform_init() +{ + // Complete CPU initialization + platform_setup_cpu(); + + // External memory + //platform_setup_extmem(); + + // Setup peripherals + platform_setup_timers(); + platform_setup_pwm(); + +#ifdef BUILD_ADC + // Setup ADCs + platform_setup_adcs(); +#endif + + // Common platform initialization code + cmn_platform_init(); + + return PLATFORM_OK; +} + +// **************************************************************************** +// PIO section + +static const u32 pio_fiodir[ NUM_PIO ] = { ( u32 )&FIO0DIR, ( u32 )&FIO1DIR, ( u32 )&FIO2DIR, ( u32 )&FIO3DIR, ( u32 )&FIO4DIR }; +static const u32 pio_fiopin[ NUM_PIO ] = { ( u32 )&FIO0PIN, ( u32 )&FIO1PIN, ( u32 )&FIO2PIN, ( u32 )&FIO3PIN, ( u32 )&FIO4PIN }; +static const u32 pio_fioset[ NUM_PIO ] = { ( u32 )&FIO0SET, ( u32 )&FIO1SET, ( u32 )&FIO2SET, ( u32 )&FIO3SET, ( u32 )&FIO4SET }; +static const u32 pio_fioclr[ NUM_PIO ] = { ( u32 )&FIO0CLR, ( u32 )&FIO1CLR, ( u32 )&FIO2CLR, ( u32 )&FIO3CLR, ( u32 )&FIO4CLR }; +static const u32 pio_pinmode[ NUM_PIO * 2 ] = { ( u32 )&PINMODE0, ( u32 )&PINMODE1, ( u32 )&PINMODE2, ( u32 )&PINMODE3, ( u32 )&PINMODE4, + ( u32 )&PINMODE5, ( u32 )&PINMODE6, ( u32 )&PINMODE7, ( u32 )&PINMODE8, ( u32 )&PINMODE9 }; + +// The platform I/O functions +pio_type platform_pio_op( unsigned port, pio_type pinmask, int op ) +{ + pio_type retval = 1; + PREG FIOxDIR = ( PREG )pio_fiodir[ port ]; + PREG FIOxPIN = ( PREG )pio_fiopin[ port ]; + PREG FIOxSET = ( PREG )pio_fioset[ port ]; + PREG FIOxCLR = ( PREG )pio_fioclr[ port ]; + PREG PINxMODE0 = ( PREG )pio_pinmode[ port * 2 ]; + PREG PINxMODE1 = ( PREG )pio_pinmode[ port * 2 + 1 ]; + u32 mask; + + switch( op ) + { + case PLATFORM_IO_PORT_SET_VALUE: + *FIOxPIN = pinmask; + break; + + case PLATFORM_IO_PIN_SET: + *FIOxSET = pinmask; + break; + + case PLATFORM_IO_PIN_CLEAR: + *FIOxCLR = pinmask; + break; + + case PLATFORM_IO_PORT_DIR_OUTPUT: + *FIOxDIR = 0xFFFFFFFF; + break; + + case PLATFORM_IO_PIN_DIR_OUTPUT: + *FIOxDIR |= pinmask; + break; + + case PLATFORM_IO_PORT_DIR_INPUT: + *FIOxDIR = 0; + break; + + case PLATFORM_IO_PIN_DIR_INPUT: + *FIOxDIR &= ~pinmask; + break; + + case PLATFORM_IO_PORT_GET_VALUE: + retval = *FIOxPIN; + break; + + case PLATFORM_IO_PIN_GET: + retval =( *FIOxPIN & pinmask ) ? 1 : 0; + break; + + case PLATFORM_IO_PIN_PULLUP: + if( port == 0 && ( pinmask & 0xF8000000 ) ) + printf( "Unable to set pullups on specified pin(s).\n" ); + else + { + for( mask = 1; mask < 16; mask ++ ) + if( pinmask & ( 1 << mask ) ) + *PINxMODE0 = *PINxMODE0 & ~( 3 << ( mask * 2 ) ); + for( mask = 16; mask < 32; mask ++ ) + if( pinmask & ( 1 << mask ) ) + *PINxMODE1 = *PINxMODE1 & ~( 3 << ( mask * 2 ) ); + } + break; + + case PLATFORM_IO_PIN_PULLDOWN: + if( port == 0 && ( pinmask & 0xF8000000 ) ) + printf( "Unable to set pulldowns on specified pin(s).\n" ); + else + { + for( mask = 1; mask < 16; mask ++ ) + if( pinmask & ( 1 << mask ) ) + *PINxMODE0 = ( *PINxMODE0 & ~( 3 << ( mask * 2 ) ) ) | ( 3 << ( mask * 2 ) ); + for( mask = 16; mask < 32; mask ++ ) + if( pinmask & ( 1 << mask ) ) + *PINxMODE1 = ( *PINxMODE1 & ~( 3 << ( mask * 2 ) ) ) | ( 3 << ( mask * 2 ) ); + } + break; + + case PLATFORM_IO_PIN_NOPULL: + if( port == 0 && ( pinmask & 0xF8000000 ) ) + printf( "Unable to reset pullups/pulldowns on specified pin(s).\n" ); + else + { + for( mask = 1; mask < 16; mask ++ ) + if( pinmask & ( 1 << mask ) ) + *PINxMODE0 = ( *PINxMODE0 & ~( 3 << ( mask * 2 ) ) ) | ( 2 << ( mask * 2 ) ); + for( mask = 16; mask < 32; mask ++ ) + if( pinmask & ( 1 << mask ) ) + *PINxMODE1 = ( *PINxMODE1 & ~( 3 << ( mask * 2 ) ) ) | ( 2 << ( mask * 2 ) ); + } + break; + + default: + retval = 0; + break; + } + return retval; +} + +// **************************************************************************** +// 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 +static const u32 uart_lcr[ NUM_UART ] = { ( u32 )&U0LCR, ( u32 )&U1LCR, ( u32 )&U2LCR, ( u32 )&U3LCR }; +static const u32 uart_dlm[ NUM_UART ] = { ( u32 )&U0DLM, ( u32 )&U1DLM, ( u32 )&U2DLM, ( u32 )&U3DLM }; +static const u32 uart_dll[ NUM_UART ] = { ( u32 )&U0DLL, ( u32 )&U1DLL, ( u32 )&U2DLL, ( u32 )&U3DLL }; +static const u32 uart_fcr[ NUM_UART ] = { ( u32 )&U0FCR, ( u32 )&U1FCR, ( u32 )&U2FCR, ( u32 )&U3FCR }; +static const u32 uart_thr[ NUM_UART ] = { ( u32 )&U0THR, ( u32 )&U1THR, ( u32 )&U2THR, ( u32 )&U3THR }; +static const u32 uart_lsr[ NUM_UART ] = { ( u32 )&U0LSR, ( u32 )&U1LSR, ( u32 )&U2LSR, ( u32 )&U3LSR }; +static const u32 uart_rbr[ NUM_UART ] = { ( u32 )&U0RBR, ( u32 )&U1RBR, ( u32 )&U2RBR, ( u32 )&U3RBR }; +static const u32 uart_fdr[ NUM_UART ] = { ( u32 )&U0FDR, ( u32 )&U1FDR, ( u32 )&U2FDR, ( u32 )&U3FDR }; + +u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int stopbits ) +{ + u32 temp, uclk, mul_frac_div, div_add_frac_div; + u32 diviser = 0; + u32 mul_frac_div_opt = 0; + u32 div_add_opt = 0; + u32 div_opt = 0; + u32 calc_baud = 0; + u32 rel_err = 0; + u32 rel_err_opt = 100000; + + PREG UxLCR = ( PREG )uart_lcr[ id ]; + PREG UxDLM = ( PREG )uart_dlm[ id ]; + PREG UxDLL = ( PREG )uart_dll[ id ]; + PREG UxFCR = ( PREG )uart_fcr[ id ]; + PREG UxFDR = ( PREG )uart_fdr[ id ]; + + // Set data bits, parity, stop bit + temp = 0; + switch( databits ) + { + case 5: + temp |= UART_DATABITS_5; + break; + + case 6: + temp |= UART_DATABITS_6; + break; + + case 7: + temp |= UART_DATABITS_7; + break; + + case 8: + temp |= UART_DATABITS_8; + break; + } + if( stopbits == PLATFORM_UART_STOPBITS_2 ) + temp |= UART_STOPBITS_2; + else + temp |= UART_STOPBITS_1; + if( parity != PLATFORM_UART_PARITY_NONE ) + { + temp |= UART_PARITY_ENABLE; + if( parity == PLATFORM_UART_PARITY_ODD ) + temp |= UART_PARITY_ODD; + else + temp |= UART_PARITY_EVEN; + } + *UxLCR = temp; + + // Divisor computation + //temp = ( Fpclk_UART >> 4 ) / baud; + uclk = Fpclk_UART >> 4; + + for( mul_frac_div = 1; mul_frac_div <= 15; mul_frac_div++ ) + { + for( div_add_frac_div = 1; div_add_frac_div <= 15; div_add_frac_div++ ) + { + temp = ( mul_frac_div * uclk ) / ( ( mul_frac_div + div_add_frac_div ) ); + + diviser = temp / baud; + + if ( ( temp % baud ) > ( baud / 2 ) ) + diviser++; + + if ( diviser > 2 && diviser < 65536 ) + { + calc_baud = temp / diviser; + + if (calc_baud <= baud) + rel_err = baud - calc_baud; + + if ((rel_err < rel_err_opt)) + { + mul_frac_div_opt = mul_frac_div ; + div_add_opt = div_add_frac_div; + div_opt = diviser; + rel_err_opt = rel_err; + if (rel_err == 0) + break; + } + } + } + } + // Set baud and divisors + *UxLCR |= UART_DLAB_ENABLE; + *UxDLM = div_opt >> 8; + *UxDLL = div_opt & 0xFF; + *UxLCR &= ~UART_DLAB_ENABLE; + *UxFDR = ( ( mul_frac_div_opt << 4 ) & 0xF0 ) | ( div_add_opt & 0x0F ); + + // Enable and reset Tx and Rx FIFOs + *UxFCR = UART_FIFO_ENABLE | UART_RXFIFO_RESET | UART_TXFIFO_RESET; + + // Setup PIOs for UART0. For the other ports, the user needs to specify what pin(s) + // are allocated for UART Rx/Tx. + if( id == 0 ) + PINSEL0 = ( PINSEL0 & 0xFFFFFF0F ) | 0x00000050; + + // Return the actual baud + return ( Fpclk_UART >> 4 ) / temp; +} + +void platform_s_uart_send( unsigned id, u8 data ) +{ + PREG UxTHR = ( PREG )uart_thr[ id ]; + PREG UxLSR = ( PREG )uart_lsr[ id ]; + + while( ( *UxLSR & LSR_THRE ) == 0 ); + *UxTHR = data; +} + +int platform_s_uart_recv( unsigned id, timer_data_type timeout ) +{ + PREG UxLSR = ( PREG )uart_lsr[ id ]; + PREG UxRBR = ( PREG )uart_rbr[ id ]; + + if( timeout == 0 ) + { + // Return data only if already available + if( *UxLSR & LSR_RDR ) + return *UxRBR; + else + return -1; + } + else + while( ( *UxLSR & LSR_RDR ) == 0 ); + return *UxRBR; +} + +int platform_s_uart_set_flow_control( unsigned id, int type ) +{ + return PLATFORM_ERR; +} + +// **************************************************************************** +// Timer section + +static const u32 tmr_tcr[] = { ( u32 )&T0TCR, ( u32 )&T1TCR, ( u32 )&T2TCR, ( u32 )&T3TCR }; +static const u32 tmr_tc[] = { ( u32 )&T0TC, ( u32 )&T1TC, ( u32 )&T2TC, ( u32 )&T3TC }; +static const u32 tmr_pr[] = { ( u32 )&T0PR, ( u32 )&T1PR, ( u32 )&T2PR, ( u32 )&T3PR }; +static const u32 tmr_pc[] = { ( u32 )&T0PC, ( u32 )&T1PC, ( u32 )&T2PC, ( u32 )&T3PC }; +static const u32 tmr_mr1[] = { ( u32 )&T0MR1, ( u32 )&T1MR1, ( u32 )&T2MR1, ( u32 )&T3MR1 }; +static const u32 tmr_mcr[] = { ( u32 )&T0MCR, ( u32 )&T1MCR, ( u32 )&T2MCR, ( u32 )&T3MCR }; +static const u32 tmr_emr[] = { ( u32 )&T0EMR, ( u32 )&T1EMR, ( u32 )&T2EMR, ( u32 )&T3EMR }; + +// Timer register definitions +enum +{ + TMR_ENABLE = 1, + TMR_RESET = 2 +}; + +// Helper function: get timer clock +static u32 platform_timer_get_clock( unsigned id ) +{ + PREG TxPR = ( PREG )tmr_pr[ id ]; + + return Fpclk / ( *TxPR + 1 ); +} + +// Helper function: set timer clock +static u32 platform_timer_set_clock( unsigned id, u32 clock ) +{ + u32 div = Fpclk / clock, prevtc; + PREG TxPR = ( PREG )tmr_pr[ id ]; + PREG TxPC = ( PREG )tmr_pc[ id ]; + PREG TxTCR = ( PREG )tmr_tcr[ id ]; + + prevtc = *TxTCR; + *TxTCR = 0; + *TxPC = 0; + *TxPR = div - 1; + *TxTCR = prevtc; + return Fpclk / div; +} + +static void int_handler_tmr() +{ + T3IR = 1; // clear interrupt + cmn_virtual_timer_cb(); // handle virtual timers if they're present + cmn_systimer_periodic(); // handle the system timer + VICVectAddr = 0; // ACK interrupt +} + +// Helper function: setup timers +static void platform_setup_timers() +{ + unsigned i; + PREG TxTCR; + + // Set base frequency to 1MHz, as we can't use a better resolution anyway + for( i = 0; i < 4; i ++ ) + { + TxTCR = ( PREG )tmr_tcr[ i ]; + *TxTCR = 0; + platform_timer_set_clock( i, 1000000ULL ); + } + + // Setup system timer + cmn_systimer_set_base_freq( 1000000 ); + cmn_systimer_set_interrupt_freq( VTMR_FREQ_HZ ); + + // Setup virtual timers / system timer here + // Timer 3 is allocated for virtual timers and the system timer, nothing else + T3TCR = TMR_RESET; + T3MR0 = 1000000ULL / VTMR_FREQ_HZ - 1; + T3IR = 0xFF; + // Set interrupt handle and eanble timer interrupt (and global interrupts) + T3MCR = 0x03; // interrupt on match with MR0 and clear on match + install_irq( TIMER3_INT, int_handler_tmr, HIGHEST_PRIORITY ); + platform_cpu_set_global_interrupts( PLATFORM_CPU_ENABLE ); + // Start timer + T3TCR = TMR_ENABLE; +} + +void platform_s_timer_delay( unsigned id, timer_data_type delay_us ) +{ + PREG TxTCR = ( PREG )tmr_tcr[ id ]; + PREG TxTC = ( PREG )tmr_tc[ id ]; + u32 last; + + last = ( ( u64 )delay_us * platform_timer_get_clock( id ) ) / 1000000; + *TxTCR = TMR_ENABLE | TMR_RESET; + *TxTCR = TMR_ENABLE; + while( *TxTC < last ); +} + +timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data ) +{ + u32 res = 0; + PREG TxTCR = ( PREG )tmr_tcr[ id ]; + PREG TxTC = ( PREG )tmr_tc[ id ]; + + switch( op ) + { + case PLATFORM_TIMER_OP_START: + *TxTCR = TMR_ENABLE | TMR_RESET; + *TxTCR = TMR_ENABLE; + break; + + case PLATFORM_TIMER_OP_READ: + res = *TxTC; + break; + + 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; + + case PLATFORM_TIMER_OP_GET_MAX_CNT: + res = 0xFFFFFFFF; + break; + } + return res; +} + +int platform_s_timer_set_match_int( unsigned id, timer_data_type period_us, int type ) +{ + return PLATFORM_TIMER_INT_INVALID_ID; +} + +u64 platform_timer_sys_raw_read() +{ + return T3TC; +} + +void platform_timer_sys_disable_int() +{ + T3MCR = 0x02; // clear on match, no interrupt +} + +void platform_timer_sys_enable_int() +{ + T3MCR = 0x03; // interrupt on match with MR0 and clear on match +} + +timer_data_type platform_timer_read_sys() +{ + return cmn_systimer_get(); +} + +// ***************************************************************************** +// ADC specific functions and variables + +#ifdef BUILD_ADC + +static const u32 adc_trig[] = { 6, 7, 0, 0 }; + +static const u32 adc_dr[] = { ( u32 )&AD0DR0, ( u32 )&AD0DR1, ( u32 )&AD0DR2, ( u32 )&AD0DR3, + ( u32 )&AD0DR4, ( u32 )&AD0DR5, ( u32 )&AD0DR6, ( u32 )&AD0DR7 }; + +static const u8 pclk_div[] = { 4, 1, 2, 8}; + +int platform_adc_check_timer_id( unsigned id, unsigned timer_id ) +{ + return ( ( timer_id == 1 ) ); +} + +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 ) + { + d->running = 0; + AD0CR &= 0xF8FFFF00; // stop ADC, disable channels + } +} + + + +static void adc_int_handler() +{ + elua_adc_dev_state *d = adc_get_dev_state( 0 ); + elua_adc_ch_state *s = d->ch_state[ d->seq_ctr ]; + u32 tmp, dreg_t; + + tmp = AD0STAT; // Clear interrupt flag + //AD0INTEN = 0; // Disable generating interrupts + + dreg_t = *( PREG )adc_dr[ s->id ]; + if ( dreg_t & ( 1UL << 31 ) ) + { + d->sample_buf[ d->seq_ctr ] = ( u16 )( ( dreg_t >> 6 ) & 0x3FF ); + AD0CR &= 0xF8FFFF00; // stop ADC, disable channels + s->value_fresh = 1; + + if ( s->logsmoothlen > 0 && s->smooth_ready == 0) + adc_smooth_data( s->id ); +#if defined( BUF_ENABLE_ADC ) + else if ( s->reqsamples > 1 ) + { + buf_write( BUF_ID_ADC, s->id, ( t_buf_data* )s->value_ptr ); + s->value_fresh = 0; + } +#endif + + if ( adc_samples_available( s->id ) >= s->reqsamples && s->freerunning == 0 ) + { + platform_adc_stop( s->id ); + } + } + + // Set up for next channel acquisition if we're still running + if( d->running == 1 ) + { + // Prep next channel in sequence, if applicable + 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 + } + + AD0CR |= ( 1ULL << d->ch_state[ d->seq_ctr ]->id ); + //AD0INTEN |= ( 1ULL << d->ch_state[ d->seq_ctr ]->id ); + + if( d->clocked == 1 && d->seq_ctr == 0 ) // always use clock for first in clocked sequence + { + AD0CR |= ( adc_trig[ d->timer_id ] << 24 ); + } + + // Start next conversion if unclocked or if clocked and sequence index > 0 + if( ( d->clocked == 1 && d->seq_ctr > 0 ) || d->clocked == 0 ) + { + AD0CR |= ( 1ULL << 24 ); // Start conversion now + } + } + VICVectAddr = 0; // ACK interrupt +} + +static void platform_setup_adcs() +{ + unsigned id; + + for( id = 0; id < NUM_ADC; id ++ ) + adc_init_ch_state( id ); + + PCONP |= PCADC; + + AD0CR = ( ( Fpclk / 4500000 - 1 ) << 8 ) | /* CLKDIV = Fpclk / 1000000 - 1 */ + ( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */ + ( 0 << 17 ) | /* CLKS = 0, 11 clocks/10 bits */ + ( 1 << 21 ) | /* PDN = 1, normal operation */ + ( 0 << 22 ) | /* TEST1:0 = 00 */ + ( 0 << 24 ) | /* START = 0 A/D conversion stops */ + ( 0 << 27 ); /* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */ + + // Default enables ADC interrupt only on global, switch to per-channel + //AD0INTEN &= ~( 1ULL << 8 ); + + install_irq( ADC0_INT, adc_int_handler, HIGHEST_PRIORITY ); +} + + +// NOTE: On this platform, there is only one ADC, clock settings apply to the whole device +u32 platform_adc_set_clock( unsigned id, u32 frequency ) +{ + elua_adc_dev_state *d = adc_get_dev_state( 0 ); + + if ( frequency > 0 ) + { + d->clocked = 1; + + // Max Sampling Rate on LPC2468 is 200 kS/s + if ( frequency > 200000 ) + frequency = 200000; + + // Set clock to 1 MHz + platform_timer_set_clock( d->timer_id, 1000000ULL ); + + // Set match to period in uS + *( PREG )tmr_mr1[ d->timer_id ] = ( u32 )( ( 1000000ULL / ( frequency * 2 ) ) - 1 ); + + // Reset on match + *( PREG )tmr_mcr[ d->timer_id ] |= ( 1ULL << 4 ); + + // Don't stop on match + *( PREG )tmr_mcr[ d->timer_id ] &= ~( 1ULL << 5 ); + + // Set match channel to 1 + *( PREG )tmr_emr[ d->timer_id ] |= ( 1ULL << 1 ); + + // Toggle output on match + *( PREG )tmr_emr[ d->timer_id ] |= ( 3ULL << 6 ); + + frequency = 1000000ULL / (*( PREG )tmr_mr1[ d->timer_id ] + 1); + } + else + d->clocked = 0; + + return 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, 12, 13 }; +static const u8 adc_funcs[] = { 1, 1, 1, 1, 3, 3, 3, 3 }; + +static const u32 pinsel_reg[] = { ( u32 )&PINSEL0, ( u32 )&PINSEL1, ( u32 )&PINSEL2, + ( u32 )&PINSEL3, ( u32 )&PINSEL4, ( u32 )&PINSEL5, + ( u32 )&PINSEL6, ( u32 )&PINSEL7, ( u32 )&PINSEL8, + ( u32 )&PINSEL9, ( u32 )&PINSEL10 }; + +// Prepare Hardware Channel +int platform_adc_update_sequence( ) +{ + elua_adc_dev_state *d = adc_get_dev_state( 0 ); + u8 seq_tmp; + unsigned id; + u32 pinnum, pinreg_idx; + + for( seq_tmp = 0; seq_tmp < d->seq_len; seq_tmp++ ) + { + id = d->ch_state[ seq_tmp ]->id; + pinnum = adc_pins[ id ]; + pinreg_idx = 2 * adc_ports[ id ]; + + if ( pinnum >= 16 ) + { + pinnum -= 16; + pinreg_idx++; + } + + *( PREG )pinsel_reg[ pinreg_idx ] &= ~( 0x03UL << pinnum * 2 ); + *( PREG )pinsel_reg[ pinreg_idx ] |= ( ( u32 )adc_funcs[ id ] << pinnum * 2 ); + } + + 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; + + // Enable channel & interrupt on channel conversion + AD0CR |= ( 1ULL << d->ch_state[ d->seq_ctr ]->id ); + //AD0INTEN |= ( 1ULL << d->ch_state[ d->seq_ctr ]->id ); + + d->running = 1; + + if( d->clocked == 1 ) + { + AD0CR |= ( adc_trig[ d->timer_id ] << 24 ); + platform_s_timer_op( d->timer_id, PLATFORM_TIMER_OP_START, 0); + } + else + AD0CR |= ( 1ULL << 24 ); + } + + return PLATFORM_OK; +} + +#endif // ifdef BUILD_ADC + + +// **************************************************************************** +// PWM functions + +static const u32 pwm_tcr[] = { ( u32 )&PWM0TCR, ( u32 )&PWM1TCR }; +static const u32 pwm_pr[] = { ( u32 )&PWM0PR, ( u32 )&PWM1PR }; +static const u32 pwm_pc[] = { ( u32 )&PWM0PC, ( u32 )&PWM1PC }; +static const u32 pwm_pcr[] = { ( u32 )&PWM0PCR, ( u32 )&PWM1PCR }; +static const u32 pwm_mcr[] = { ( u32 )&PWM0MCR, ( u32 )&PWM1MCR }; +static const u32 pwm_ler[] = { ( u32 )&PWM0LER, ( u32 )&PWM1LER }; +static const u32 pwm_channels[ 2 ][ 6 ] = +{ + { ( u32 )&PWM0MR1, ( u32 )&PWM0MR2, ( u32 )&PWM0MR3, ( u32 )&PWM0MR4, ( u32 )&PWM0MR5, ( u32 )&PWM0MR6 }, + { ( u32 )&PWM1MR1, ( u32 )&PWM1MR2, ( u32 )&PWM1MR3, ( u32 )&PWM1MR4, ( u32 )&PWM1MR5, ( u32 )&PWM1MR6 }, +}; + +// Timer register definitions +enum +{ + PWM_ENABLE = 1, + PWM_RESET = 2, + PWM_MODE = 8, + PWM_ENABLE_1 = 1 << 9, + PWM_ENABLE_2 = 1 << 10, + PWM_ENABLE_3 = 1 << 11, + PWM_ENABLE_4 = 1 << 12, + PWM_ENABLE_5 = 1 << 13, + PWM_ENABLE_6 = 1 << 14, +}; + +// Get timer clock +u32 platform_pwm_get_clock( unsigned id ) +{ + unsigned pwmid = id / 6; + PREG PWMxPR = ( PREG )pwm_pr[ pwmid ]; + + return Fpclk / ( *PWMxPR + 1 ); +} + +// Set timer clock +u32 platform_pwm_set_clock( unsigned id, u32 clock ) +{ + u32 div = Fpclk / clock, prevtc; + unsigned pwmid = id / 6; + PREG PWMxPR = ( PREG )pwm_pr[ pwmid ]; + PREG PWMxPC = ( PREG )pwm_pc[ pwmid ]; + PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ]; + + prevtc = *PWMxTCR; + *PWMxTCR = 0; + *PWMxPC = 0; + *PWMxPR = div - 1; + *PWMxTCR = prevtc; + return Fpclk / div; +} + +// Setup all PWM channels +static void platform_setup_pwm() +{ + unsigned i; + PREG temp; + + for( i = 0; i < 2; i ++ ) + { + // Keep clock in reset, set PWM code + temp = ( PREG )pwm_tcr[ i ]; + *temp = PWM_RESET; + // Set match mode (reset on MR0 match) + temp = ( PREG )pwm_mcr[ i ]; + *temp = 0x02; + // Set base frequency to 1MHz + platform_pwm_set_clock( i * 6, 1000000 ); + } +} + +u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty ) +{ + unsigned pwmid = id / 6, chid = id % 6; + PREG PWMxMR0 = pwmid == 0 ? ( PREG )&PWM0MR0 : ( PREG )&PWM1MR0; + PREG PWMxMRc = ( PREG )pwm_channels[ pwmid ][ chid ]; + PREG PWMxLER = ( PREG )pwm_ler[ pwmid ]; + u32 divisor; + + divisor = platform_pwm_get_clock( id ) / frequency - 1; + *PWMxMR0 = divisor; + *PWMxMRc = ( divisor * duty ) / 100; + *PWMxLER = 1 | ( 1 << ( chid + 1 ) ); + + return platform_pwm_get_clock( id ) / divisor; +} + +void platform_pwm_start( unsigned id ) +{ + unsigned pwmid = id / 6; + PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ]; + PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ]; + + *PWMxPCR = PWM_ENABLE_1 | PWM_ENABLE_2 | PWM_ENABLE_3 | PWM_ENABLE_4 | PWM_ENABLE_5 | PWM_ENABLE_6; + *PWMxTCR = PWM_ENABLE | PWM_MODE; +} + +void platform_pwm_stop( unsigned id ) +{ + unsigned pwmid = id / 6; + PREG PWMxTCR = ( PREG )pwm_tcr[ pwmid ]; + PREG PWMxPCR = ( PREG )pwm_pcr[ pwmid ]; + + *PWMxPCR = 0; + *PWMxTCR = PWM_RESET; +} diff --git a/src/platform/lpc23xx/platform_generic.h b/src/platform/lpc23xx/platform_generic.h new file mode 100644 index 00000000..9af64f99 --- /dev/null +++ b/src/platform/lpc23xx/platform_generic.h @@ -0,0 +1,44 @@ +// Platform-wide configuration file, included by platform_conf.h + +#ifndef __PLATFORM_GENERIC_H__ +#define __PLATFORM_GENERIC_H__ + +#define PLATFORM_HAS_SYSTIMER + +// If virtual timers are enabled, the last timer will be used only for them +#if VTMR_NUM_TIMERS > 0 +#undef NUM_TIMER +#define NUM_TIMER 3 +#endif + +// ***************************************************************************** +// CPU constants that should be exposed to the eLua "cpu" module + +#define PINSEL_BASE_ADDR 0xE002C000 +#define IO_PINSEL0 ( PINSEL_BASE_ADDR + 0x00 ) +#define IO_PINSEL1 ( PINSEL_BASE_ADDR + 0x04 ) +#define IO_PINSEL2 ( PINSEL_BASE_ADDR + 0x08 ) +#define IO_PINSEL3 ( PINSEL_BASE_ADDR + 0x0C ) +#define IO_PINSEL4 ( PINSEL_BASE_ADDR + 0x10 ) +#define IO_PINSEL5 ( PINSEL_BASE_ADDR + 0x14 ) +#define IO_PINSEL6 ( PINSEL_BASE_ADDR + 0x18 ) +#define IO_PINSEL7 ( PINSEL_BASE_ADDR + 0x1C ) +#define IO_PINSEL8 ( PINSEL_BASE_ADDR + 0x20 ) +#define IO_PINSEL9 ( PINSEL_BASE_ADDR + 0x24 ) +#define IO_PINSEL10 ( PINSEL_BASE_ADDR + 0x28 ) + +#define PLATFORM_CPU_CONSTANTS_PLATFORM\ + _C( IO_PINSEL0 ),\ + _C( IO_PINSEL1 ),\ + _C( IO_PINSEL2 ),\ + _C( IO_PINSEL3 ),\ + _C( IO_PINSEL4 ),\ + _C( IO_PINSEL5 ),\ + _C( IO_PINSEL6 ),\ + _C( IO_PINSEL7 ),\ + _C( IO_PINSEL8 ),\ + _C( IO_PINSEL9 ),\ + _C( IO_PINSEL10 ), + +#endif // #ifndef __PLATFORM_GENERIC_H__ + diff --git a/src/platform/lpc23xx/platform_int.c b/src/platform/lpc23xx/platform_int.c new file mode 100644 index 00000000..40b7a663 --- /dev/null +++ b/src/platform/lpc23xx/platform_int.c @@ -0,0 +1,263 @@ +// LPC23xx interrupt support + +// Generic headers +#include "platform.h" +#include "platform_conf.h" +#include "elua_int.h" +#include "common.h" + +// Platform-specific headers +#include "irq.h" +#include "LPC23xx.h" +#include "target.h" +#include "uart.h" + +// **************************************************************************** +// Interrupt handlers + +// ---------------------------------------------------------------------------- +// GPIO + +static PREG const posedge_status[] = { ( PREG )&IO0_INT_STAT_R, ( PREG )&IO2_INT_STAT_R }; +static PREG const negedge_status[] = { ( PREG )&IO0_INT_STAT_F, ( PREG )&IO2_INT_STAT_F }; +static PREG const intclr_regs[] = { ( PREG )&IO0_INT_CLR, ( PREG )&IO2_INT_CLR }; + +#define EINT3_BIT 3 + +// EINT3 (INT_GPIO) interrupt handler +static void int_handler_eint3() +{ + elua_int_id id = ELUA_INT_INVALID_INTERRUPT; + pio_code resnum = 0; + int pidx, pin; + + EXTINT |= 1 << EINT3_BIT; // clear interrupt + // Look for interrupt source + // In can only be GPIO0/GPIO2, as the EXT interrupts are not (yet) used + pidx = ( IO_INT_STAT & 1 ) ? 0 : 1; + if( *posedge_status[ pidx ] ) + { + id = INT_GPIO_POSEDGE; + pin = intlog2( *posedge_status[ pidx ] ); + } + else + { + id = INT_GPIO_NEGEDGE; + pin = intlog2( *negedge_status[ pidx ] ); + } + resnum = PLATFORM_IO_ENCODE( pidx * 2, pin, PLATFORM_IO_ENC_PIN ); + *intclr_regs[ pidx ] = 1 << pin; + + // Run the interrupt through eLua + cmn_int_handler( id, resnum ); + VICVectAddr = 0; // ACK interrupt +} + +// ---------------------------------------------------------------------------- +// UART + +static PREG const uart_ier[] = { ( PREG )&U0IER, ( PREG )&U1IER, ( PREG )&U2IER, ( PREG )&U3IER }; +static PREG const uart_iir[] = { ( PREG )&U0IIR, ( PREG )&U1IIR, ( PREG )&U2IIR, ( PREG )&U3IIR }; + +// Common UART interrupt handler +static void uart_rx_common_handler( elua_int_resnum resnum ) +{ + cmn_int_handler( INT_UART_RX, resnum ); + VICVectAddr = 0; +} + +// Interrupt handlers for individual UARTs +static void int_handler_uart0() +{ + uart_rx_common_handler( 0 ); +} + +static void int_handler_uart1() +{ + uart_rx_common_handler( 1 ); +} + +static void int_handler_uart2() +{ + uart_rx_common_handler( 2 ); +} + +static void int_handler_uart3() +{ + uart_rx_common_handler( 3 ); +} + +// **************************************************************************** +// GPIO helper functions + +static PREG const posedge_regs[] = { ( PREG )&IO0_INT_EN_R, NULL, ( PREG )&IO2_INT_EN_R }; +static PREG const negedge_regs[] = { ( PREG )&IO0_INT_EN_F, NULL, ( PREG )&IO0_INT_EN_F }; + +static int gpioh_get_int_status( elua_int_id id, elua_int_resnum resnum ) +{ + int port, pin; + + port = PLATFORM_IO_GET_PORT( resnum ); + pin = PLATFORM_IO_GET_PIN( resnum ); + if( id == INT_GPIO_POSEDGE ) + return *posedge_regs[ port ] & ( 1 << pin ); + else + return *negedge_regs[ port ] & ( 1 << pin ); + return 0; +} + +static int gpioh_set_int_status( elua_int_id id, elua_int_resnum resnum, int status ) +{ + int crt_status = gpioh_get_int_status( id, resnum ); + int port, pin; + + port = PLATFORM_IO_GET_PORT( resnum ); + pin = PLATFORM_IO_GET_PIN( resnum ); + if( id == INT_GPIO_POSEDGE ) + { + if( status == PLATFORM_CPU_ENABLE ) + *posedge_regs[ port ] |= 1 << pin; + else + *posedge_regs[ port ] &= ~( 1 << pin ); + } + else + { + if( status == PLATFORM_CPU_ENABLE ) + *negedge_regs[ port ] |= 1 << pin; + else + *negedge_regs[ port ] &= ~( 1 << pin ); + } + EXTINT |= 1 << EINT3_BIT; + return crt_status; +} + +static int gpioh_get_flag( elua_int_id id, elua_int_resnum resnum, int clear ) +{ + int pidx; + int flag = 0; + + // Look for interrupt source + // In can only be GPIO0/GPIO2, as the EXT interrupts are not (yet) used + pidx = ( IO_INT_STAT & 1 ) ? 0 : 1; + if( id == INT_GPIO_POSEDGE && ( *posedge_status[ pidx ] && ( 1 << resnum ) ) ) + flag = 1; + else if( id == INT_GPIO_NEGEDGE && ( *negedge_status[ pidx ] && ( 1 << resnum ) ) ) + flag = 1; + if( flag && clear ) + *intclr_regs[ pidx ] = 1 << resnum; + return flag; +} + +// **************************************************************************** +// Interrupt: INT_GPIO_POSEDGE + +static int int_gpio_posedge_set_status( elua_int_resnum resnum, int status ) +{ + return gpioh_set_int_status( INT_GPIO_POSEDGE, resnum, status ); +} + +static int int_gpio_posedge_get_status( elua_int_resnum resnum ) +{ + return gpioh_get_int_status( INT_GPIO_POSEDGE, resnum ); +} + +static int int_gpio_posedge_get_flag( elua_int_resnum resnum, int clear ) +{ + return gpioh_get_flag( INT_GPIO_POSEDGE, resnum, clear ); +} + +// **************************************************************************** +// Interrupt: INT_GPIO_NEGEDGE + +static int int_gpio_negedge_set_status( elua_int_resnum resnum, int status ) +{ + return gpioh_set_int_status( INT_GPIO_NEGEDGE, resnum, status ); +} + +static int int_gpio_negedge_get_status( elua_int_resnum resnum ) +{ + return gpioh_get_int_status( INT_GPIO_NEGEDGE, resnum ); +} + +static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear ) +{ + return gpioh_get_flag( INT_GPIO_NEGEDGE, resnum, clear ); +} + +// **************************************************************************** +// Interrupt: INT_TMR_MATCH + +static int int_tmr_match_set_status( elua_int_resnum resnum, int status ) +{ + return PLATFORM_INT_BAD_RESNUM; +} + +static int int_tmr_match_get_status( elua_int_resnum resnum ) +{ + return PLATFORM_INT_BAD_RESNUM; +} + +static int int_tmr_match_get_flag( elua_int_resnum resnum, int clear ) +{ + return PLATFORM_INT_BAD_RESNUM; +} + +// **************************************************************************** +// Interrupt: INT_UART_RX + +static int int_uart_rx_get_status( elua_int_resnum resnum ) +{ + PREG UxIER = uart_ier[ resnum ]; + + return ( *UxIER & IER_RBR ) ? 1 : 0; +} + +static int int_uart_rx_set_status( elua_int_resnum resnum, int status ) +{ + PREG UxIER = uart_ier[ resnum ]; + int prev = int_uart_rx_get_status( resnum ); + + if( status == PLATFORM_CPU_ENABLE ) + *UxIER |= IER_RBR; + else + *UxIER &= ~IER_RBR; + return prev; +} + +static int int_uart_rx_get_flag( elua_int_resnum resnum, int clear ) +{ + PREG UxIIR = uart_iir[ resnum ]; + + // 'clear' is not needed here, the interrupt will be cleared when reading the RBR register + ( void )clear; + if( ( *UxIIR & IIR_PEND ) == 0 ) + return ( ( *UxIIR >> 1 ) & 0x07 ) == IIR_RDA; + return 0; +} + +// **************************************************************************** +// Interrupt initialization + +typedef void ( *p_handler )(); + +void platform_int_init() +{ + install_irq( EINT3_INT, int_handler_eint3, HIGHEST_PRIORITY + 1 ); + install_irq( UART0_INT, int_handler_uart0, HIGHEST_PRIORITY + 2 ); + install_irq( UART1_INT, int_handler_uart1, HIGHEST_PRIORITY + 3 ); + install_irq( UART2_INT, int_handler_uart2, HIGHEST_PRIORITY + 4 ); + install_irq( UART3_INT, int_handler_uart3, HIGHEST_PRIORITY + 5 ); +} + +// **************************************************************************** +// Interrupt table +// Must have a 1-to-1 correspondence with the interrupt enum in platform_ints.h! + +const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ] = +{ + { int_gpio_posedge_set_status, int_gpio_posedge_get_status, int_gpio_posedge_get_flag }, + { int_gpio_negedge_set_status, int_gpio_negedge_get_status, int_gpio_negedge_get_flag }, + { int_tmr_match_set_status, int_tmr_match_get_status, int_tmr_match_get_flag }, + { int_uart_rx_set_status, int_uart_rx_get_status, int_uart_rx_get_flag } +}; + diff --git a/src/platform/lpc23xx/platform_ints.h b/src/platform/lpc23xx/platform_ints.h new file mode 100644 index 00000000..c3df8e76 --- /dev/null +++ b/src/platform/lpc23xx/platform_ints.h @@ -0,0 +1,15 @@ +// This header lists all interrupts defined for this platform + +#ifndef __PLATFORM_INTS_H__ +#define __PLATFORM_INTS_H__ + +#include "elua_int.h" + +#define INT_GPIO_POSEDGE ELUA_INT_FIRST_ID +#define INT_GPIO_NEGEDGE ( ELUA_INT_FIRST_ID + 1 ) +#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 2 ) +#define INT_UART_RX ( ELUA_INT_FIRST_ID + 3 ) +#define INT_ELUA_LAST INT_UART_RX + +#endif // #ifndef __PLATFORM_INTS_H__ + diff --git a/src/platform/lpc23xx/stacks.h b/src/platform/lpc23xx/stacks.h new file mode 100644 index 00000000..1199d9ee --- /dev/null +++ b/src/platform/lpc23xx/stacks.h @@ -0,0 +1,11 @@ +// Stack size definitions + +#ifndef __STACKS_H__ +#define __STACKS_H__ + +#define STACK_SIZE_USR 0x00000400 +#define STACK_SIZE_IRQ 0x00000100 +#define STACK_SIZE_TOTAL ( STACK_SIZE_USR + STACK_SIZE_IRQ ) + +#endif + diff --git a/src/platform/lpc23xx/startup.s b/src/platform/lpc23xx/startup.s new file mode 100644 index 00000000..a5581ca2 --- /dev/null +++ b/src/platform/lpc23xx/startup.s @@ -0,0 +1,128 @@ +#include "stacks.h" + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + + +#define ARM_MODE_USR 0x10 +#define ARM_MODE_FIQ 0x11 +#define ARM_MODE_IRQ 0x12 +#define ARM_MODE_SVC 0x13 +#define ARM_MODE_ABT 0x17 +#define ARM_MODE_UND 0x1B +#define ARM_MODE_SYS 0x1F + + +#define I_BIT 0x80 +#define F_BIT 0x40 + + +#define RAM_Base 0x40000000 +#define RAM_Size (32 * 1024) // [TODO] make this 96k? +#define Top_Stack (RAM_Base + RAM_Size) + +#define VectorAddress 0xFFFFFF00 + +//------------------------------------------------------------------------------ +// Startup routine +//------------------------------------------------------------------------------ + + .align 4 + .arm + +/* Exception vectors + *******************/ + .section .vectors, "a" + +resetVector: + ldr pc, =resetHandler /* Reset */ +undefVector: + b undefVector /* Undefined instruction */ +swiVector: + b swiVector /* Software interrupt */ +prefetchAbortVector: + b prefetchAbortVector /* Prefetch abort */ +dataAbortVector: + b dataAbortVector /* Data abort */ +reservedVector: + b reservedVector /* Reserved for future use */ +irqVector: + b irqHandler /* Generic IRQ handler */ +fiqVector: + b fiqVector /* Fast interrupt */ + +//------------------------------------------------------------------------------ +/// IRQ handler +//------------------------------------------------------------------------------ + +irqHandler: + sub lr, lr ,#4 + stmfd sp!, {r0-r3, r12, lr} + ldr r0, =VectorAddress + ldr r0, [r0] + mov lr, pc + bx r0 + ldmfd sp!, {r0-r3, r12, pc}^ + +//------------------------------------------------------------------------------ +/// Initializes the chip and branches to the main() function. +//------------------------------------------------------------------------------ + .section .text + .global entry + .extern main + .extern TargetResetInit + +entry: +resetHandler: + +/* Setup stacks for each mode */ + ldr r0, =Top_Stack + + /* Set IRQ Mode Stack & Pointer */ + msr CPSR_c, #ARM_MODE_IRQ|I_BIT|F_BIT + mov r13, r0 + sub r0, r0, #STACK_SIZE_IRQ + + /* Set SVC Mode Stack & Pointer - leave interrupts enabled */ + msr CPSR_c, #ARM_MODE_SVC|F_BIT + mov r13, r0 + sub r0, r0, #STACK_SIZE_USR + + +/* Perform low-level initialization of the chip using LowLevelInit() */ +/* Initialize the relocate segment */ + + ldr r0, =_efixed + ldr r1, =_srelocate + ldr r2, =_erelocate +CopyROMtoRAM: + cmp r1, r2 + ldrcc r3, [r0], #4 + strcc r3, [r1], #4 + bcc CopyROMtoRAM + +/* Clear the zero segment */ + ldr r0, =_szero + ldr r1, =_ezero + mov r2, #0 +ZeroBSS: + cmp r0, r1 + strcc r2, [r0], #4 + bcc ZeroBSS + + /* Call external initialization code */ + bl TargetResetInit + +/* Branch to main() + ******************/ + ldr r0, =main + mov lr, pc + bx r0 + +/* Loop indefinitely when program is finished */ +forever: + b forever + + .end + diff --git a/src/platform/lpc23xx/target.c b/src/platform/lpc23xx/target.c new file mode 100644 index 00000000..4f9b3564 --- /dev/null +++ b/src/platform/lpc23xx/target.c @@ -0,0 +1,197 @@ +/***************************************************************************** + * target.c: Target C file for NXP LPC23xx/24xx Family Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.07.13 ver 1.00 Prelimnary version, first Release + * +*****************************************************************************/ +#include "LPC23xx.h" +#include "type.h" +#include "irq.h" +#include "target.h" + +/****************************************************************************** +** Function name: TargetInit +** +** Descriptions: Initialize the target board; it is called in a necessary +** place, change it as needed +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void TargetInit(void) +{ + /* Add your codes here */ + return; +} + +/****************************************************************************** +** Function name: GPIOResetInit +** +** Descriptions: Initialize the target board before running the main() +** function; User may change it as needed, but may not +** deleted it. +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void GPIOResetInit( void ) +{ + /* Reset all GPIO pins to default: primary function */ + PINSEL0 = 0x00000000; + PINSEL1 = 0x00000000; + PINSEL2 = 0x00000000; + PINSEL3 = 0x00000000; + PINSEL4 = 0x00000000; + PINSEL5 = 0x00000000; + PINSEL6 = 0x00000000; + PINSEL7 = 0x00000000; + PINSEL8 = 0x00000000; + PINSEL9 = 0x00000000; + PINSEL10 = 0x00000000; + + IODIR0 = 0x00000000; + IODIR1 = 0x00000000; + IOSET0 = 0x00000000; + IOSET1 = 0x00000000; + + FIO0DIR = 0x00000000; + FIO1DIR = 0x00000000; + FIO2DIR = 0x00000000; + FIO3DIR = 0x00000000; + FIO4DIR = 0x00000000; + + FIO0SET = 0x00000000; + FIO1SET = 0x00000000; + FIO2SET = 0x00000000; + FIO3SET = 0x00000000; + FIO4SET = 0x00000000; + return; +} + +/****************************************************************************** +** Function name: ConfigurePLL +** +** Descriptions: Configure PLL switching to main OSC instead of IRC +** at power up and wake up from power down. +** This routine is used in TargetResetInit() and those +** examples using power down and wake up such as +** USB suspend to resume, ethernet WOL, and power management +** example +** parameters: None +** Returned value: None +** +******************************************************************************/ +void ConfigurePLL ( void ) +{ + DWORD MValue, NValue; + + if ( PLLSTAT & (1 << 25) ) + { + PLLCON = 1; /* Enable PLL, disconnected */ + PLLFEED = 0xaa; + PLLFEED = 0x55; + } + + PLLCON = 0; /* Disable PLL, disconnected */ + PLLFEED = 0xaa; + PLLFEED = 0x55; + + SCS |= 0x20; /* Enable main OSC */ + while( !(SCS & 0x40) ); /* Wait until main OSC is usable */ + + CLKSRCSEL = 0x1; /* select main OSC, 12MHz, as the PLL clock source */ + + PLLCFG = PLL_MValue | (PLL_NValue << 16); + PLLFEED = 0xaa; + PLLFEED = 0x55; + + PLLCON = 1; /* Enable PLL, disconnected */ + PLLFEED = 0xaa; + PLLFEED = 0x55; + + CCLKCFG = CCLKDivValue; /* Set clock divider */ +#if USE_USB + USBCLKCFG = USBCLKDivValue; /* usbclk = 288 MHz/6 = 48 MHz */ +#endif + + while ( ((PLLSTAT & (1 << 26)) == 0) ); /* Check lock bit status */ + + MValue = PLLSTAT & 0x00007FFF; + NValue = (PLLSTAT & 0x00FF0000) >> 16; + while ((MValue != PLL_MValue) && ( NValue != PLL_NValue) ); + + PLLCON = 3; /* enable and connect */ + PLLFEED = 0xaa; + PLLFEED = 0x55; + while ( ((PLLSTAT & (1 << 25)) == 0) ); /* Check connect bit status */ +} + +/****************************************************************************** +** Function name: TargetResetInit +** +** Descriptions: Initialize the target board before running the main() +** function; User may change it as needed, but may not +** deleted it. +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void TargetResetInit(void) +{ +#ifdef __DEBUG_RAM + MEMMAP = 0x2; /* remap to internal RAM */ +#endif + +#ifdef __DEBUG_FLASH + MEMMAP = 0x1; /* remap to internal flash */ +#endif + +#if USE_USB + PCONP |= 0x80000000; /* Turn On USB PCLK */ +#endif + /* Configure PLL, switch from IRC to Main OSC */ + ConfigurePLL(); + + /* Set system timers for each component */ +#if (Fpclk / (Fcclk / 4)) == 1 + PCLKSEL0 = 0x00000000; /* PCLK is 1/4 CCLK */ + PCLKSEL1 = 0x00000000; +#endif +#if (Fpclk / (Fcclk / 4)) == 2 + PCLKSEL0 = 0xAAAAAAAA; /* PCLK is 1/2 CCLK */ + PCLKSEL1 = 0xAAAAAAAA; +#endif +#if (Fpclk / (Fcclk / 4)) == 4 + PCLKSEL0 = 0x55555555; /* PCLK is the same as CCLK */ + PCLKSEL1 = 0x55555555; +#endif + + /* Set memory accelerater module*/ + MAMCR = 0; + +#if Fcclk < 20000000 + MAMTIM = 1; +#else +#if Fcclk < 40000000 + MAMTIM = 2; +#else + MAMTIM = 3; +#endif +#endif + MAMCR = 2; + + GPIOResetInit(); + + init_VIC(); +} + +/****************************************************************************** +** End Of File +******************************************************************************/ diff --git a/src/platform/lpc23xx/target.h b/src/platform/lpc23xx/target.h new file mode 100644 index 00000000..261afc98 --- /dev/null +++ b/src/platform/lpc23xx/target.h @@ -0,0 +1,169 @@ +/***************************************************************************** + * target.h: Header file for NXP LPC23xx/24xx Family Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.09.20 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ +#ifndef __TARGET_H +#define __TARGET_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Only choose one of them below, by default, it's Keil MCB2300 */ +/*#define ENG_BOARD_LPC24XX 0 +#define KEIL_BOARD_LPC23XX 1 +#define EA_BOARD_LPC24XX 0 +#define IAR_BOARD_LPC23XX 0*/ + +/* On EA and IAR boards, they use Micrel PHY. + on ENG and KEIL boards, they use National PHY */ +/*#define NATIONAL_PHY 1 +#define MICREL_PHY 2*/ + +/* If USB device is used, CCO will be 288Mhz( divided by 6) or 384Mhz( divided by 8) +to get precise USB clock 48Mhz. If USB is not used, you set any clock you want +but make sure the divider of the CCO should be an even number. If you want to +use USB, change "define USE_USB" from 0 to 1 */ + +#define USE_USB 0 + +/* PLL Setting Table Matrix */ +/* + Main Osc. CCLKCFG Fcco Fcclk M N + 12Mhz 29 300Mhz 10Mhz 24 1 + 12Mhz 35 360Mhz 10Mhz 14 0 + 12Mhz 27 336Mhz 12Mhz 13 0 + 12Mhz 17 360Mhz 20Mhz 14 0 + 12Mhz 13 336Mhz 24Mhz 13 0 + 12Mhz 11 300Mhz 25Mhz 24 1 + 12Mhz 9 300Mhz 30Mhz 24 1 + 12Mhz 11 360Mhz 30Mhz 14 0 + 12Mhz 9 320Mhz 32Mhz 39 2 + 12Mhz 9 350Mhz 35Mhz 174 11 + 12Mhz 7 312Mhz 39Mhz 12 0 + 12Mhz 7 360Mhz 45Mhz 14 0 + 12Mhz 5 300Mhz 50Mhz 24 1 + 12Mhz 5 312Mhz 52Mhz 12 0 + 12Mhz 5 336Mhz 56Mhz 13 0 + 12Mhz 3 300Mhz 75Mhz 24 1 + 12Mhz 3 312Mhz 78Mhz 12 0 + 12Mhz 3 320Mhz 80Mhz 39 2 + 12Mhz 3 336Mhz 84Mhz 13 0 +*/ + +/* These are limited number of Fcco configuration for +USB communication as the CPU clock and USB clock shares +the same PLL. The USB clock needs to be multiple of +48Mhz. */ +#if USE_USB /* 1 is USB, 0 is non-USB related */ +/* Fcck = 48Mhz, Fosc = 288Mhz, and USB 48Mhz */ +#define PLL_MValue 11 +#define PLL_NValue 0 +#define CCLKDivValue 5 +#define USBCLKDivValue 5 + +/* System configuration: Fosc, Fcclk, Fcco, Fpclk must be defined */ +/* PLL input Crystal frequence range 4KHz~20MHz. */ +#define Fosc 12000000 +/* System frequence,should be less than 80MHz. */ +#define Fcclk 48000000 +#define Fcco 288000000 + +#else // #if USE_USB + + +// [TODO]: use the PLL calculator XLS to increase frequency a bit +/* Fcck = 60Mhz, Fosc = 360Mhz, USB can't be divided into 48Mhz +in this case, so USBCLKDivValue is not needed. */ +#if 0 // 60MHz +#define PLL_MValue 14 +#define PLL_NValue 0 +#define CCLKDivValue 5 +#define Fcclk 60000000ULL +#else // 72MHz +#define PLL_MValue 14 +#define PLL_NValue 0 +#define CCLKDivValue 4 +#define Fcclk 72000000ULL +#endif + +/* System configuration: Fosc, Fcclk, Fcco, Fpclk must be defined */ +/* PLL input Crystal frequence range 4KHz~20MHz. */ +#define Fosc 12000000 +/* System frequence,should be less than 72MHz. */ +#define Fcco 360000000 + +#endif + +/* APB clock frequence , must be 1/2/4 multiples of ( Fcclk/4 ). */ +/* If USB is enabled, the minimum APB must be greater than 16Mhz */ +#if USE_USB +#define Fpclk (Fcclk / 2) +#else +#define Fpclk (Fcclk / 4) +#endif + +#define Fpclk_MHz (Fpclk / 1000000) +#define Fpclk_UART (Fcclk) +#define SYS_FREQ (Fcclk / 1000000) + +#ifdef ELUA_BOARD_ELUAPUC + +#if SYS_FREQ == (72) +#define EMC_PERIOD 13.88888888 // 72MHz +#elif SYS_FREQ == (60) +#define EMC_PERIOD 16.6 // 60MHz +#elif SYS_FREQ == (57) +#define EMC_PERIOD 17.4 // 57.6MHz +#elif SYS_FREQ == (48) +#define EMC_PERIOD 20.8 // 48MHz +#elif SYS_FREQ == (36) +#define EMC_PERIOD 27.8 // 36MHz +#elif SYS_FREQ == (24) +#define EMC_PERIOD 41.7 // 24MHz +#else +#error Frequency not defined +#endif + +#define SDRAM_REFRESH 15625 //max 64ms +#define SDRAM_TRP 18 // +#define SDRAM_TRAS 42 +#define SDRAM_TAPR 2 +#define SDRAM_TWR 2 +#define SDRAM_TDAL (SDRAM_TWR+P2C(SDRAM_TRP)) +#define SDRAM_TRC 60 //samsung 65 micron 66 +#define SDRAM_TRFC 60 +#define SDRAM_TXSR 70 +#define SDRAM_TRRD 12 +#define SDRAM_TMRD 2 + +#endif + +/****************************************************************************** +** Function name: TargetInit +** +** Descriptions: Initialize the target board; it is called in a +** necessary place, change it as needed +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +extern void TargetInit(void); +extern void ConfigurePLL( void ); +extern void TargetResetInit(void); + +#ifdef __cplusplus + } +#endif + +#endif /* end __TARGET_H */ +/****************************************************************************** +** End Of File +******************************************************************************/ diff --git a/src/platform/lpc23xx/type.h b/src/platform/lpc23xx/type.h new file mode 100644 index 00000000..15474e98 --- /dev/null +++ b/src/platform/lpc23xx/type.h @@ -0,0 +1,29 @@ +#ifndef __TYPE_H__ +#define __TYPE_H__ + +typedef unsigned char u8; +typedef signed char s8; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned long u32; +typedef signed long s32; +typedef unsigned long long u64; +typedef signed long long s64; + +#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 volatile unsigned long* PREG; + +#endif + diff --git a/src/platform/lpc23xx/uart.h b/src/platform/lpc23xx/uart.h new file mode 100644 index 00000000..be6234d9 --- /dev/null +++ b/src/platform/lpc23xx/uart.h @@ -0,0 +1,59 @@ +/***************************************************************************** + * uart.h: Header file for NXP LPC23xx Family Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.09.01 ver 1.00 Prelimnary version, first Release + * + * Modified by BogdanM for eLua +******************************************************************************/ + +#ifndef __UART_H +#define __UART_H + +#include "type.h" + +#define IER_RBR 0x01 +#define IER_THRE 0x02 +#define IER_RLS 0x04 + +#define IIR_PEND 0x01 +#define IIR_RLS 0x03 +#define IIR_RDA 0x02 +#define IIR_CTI 0x06 +#define IIR_THRE 0x01 + +#define LSR_RDR 0x01 +#define LSR_OE 0x02 +#define LSR_PE 0x04 +#define LSR_FE 0x08 +#define LSR_BI 0x10 +#define LSR_THRE 0x20 +#define LSR_TEMT 0x40 +#define LSR_RXFE 0x80 + +// UART setup constants +enum +{ + UART_DATABITS_5 = 0, + UART_DATABITS_6 = 1, + UART_DATABITS_7 = 2, + UART_DATABITS_8 = 3, + UART_STOPBITS_1 = 0, + UART_STOPBITS_2 = 4, + UART_PARITY_ENABLE = 8, + UART_PARITY_ODD = 0, + UART_PARITY_EVEN = 1 << 4, + UART_DLAB_ENABLE = 1 << 7, + UART_FIFO_ENABLE = 1, + UART_RXFIFO_RESET = 2, + UART_TXFIFO_RESET = 4 +}; + +#endif /* end __UART_H */ +/***************************************************************************** +** End Of File +******************************************************************************/ + diff --git a/src/platform/stm32f4/cpu_stm32f411re.h b/src/platform/stm32f4/cpu_stm32f411re.h new file mode 100644 index 00000000..bdaa6149 --- /dev/null +++ b/src/platform/stm32f4/cpu_stm32f411re.h @@ -0,0 +1,52 @@ +// CPU definition file for STM32F411RE + +#ifndef __CPU_STM32F411RE_H__ +#define __CPU_STM32F411RE_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_STM32F411RE_H__ +