lpc: Initial lpcxpresso bits
authorKeith Packard <keithp@keithp.com>
Thu, 18 Apr 2013 20:54:13 +0000 (15:54 -0500)
committerKeith Packard <keithp@keithp.com>
Fri, 17 May 2013 10:50:07 +0000 (03:50 -0700)
This gets the LPC11U14 clock set to the PLL and blinks the LED.

Signed-off-by: Keith Packard <keithp@keithp.com>
15 files changed:
src/lpc/Makefile.defs [new file with mode: 0644]
src/lpc/altos.ld [new file with mode: 0644]
src/lpc/ao_arch.h [new file with mode: 0644]
src/lpc/ao_arch_funcs.h [new file with mode: 0644]
src/lpc/ao_interrupt.c [new file with mode: 0644]
src/lpc/ao_led_lpc.c [new file with mode: 0644]
src/lpc/ao_romconfig.c [new file with mode: 0644]
src/lpc/ao_serial_lpc.c [new file with mode: 0644]
src/lpc/ao_timer_lpc.c [new file with mode: 0644]
src/lpc/baud_rate [new file with mode: 0644]
src/lpc/figure-checksum [new file with mode: 0755]
src/lpc/lpc.h [new file with mode: 0644]
src/lpc/registers.ld [new file with mode: 0644]
src/lpcxpresso/Makefile [new file with mode: 0644]
src/lpcxpresso/ao_pins.h [new file with mode: 0644]

diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs
new file mode 100644 (file)
index 0000000..c18284d
--- /dev/null
@@ -0,0 +1,42 @@
+vpath % ../lpc:../product:../drivers:../core:../util:../kalman:../aes:..
+vpath make-altitude ../util
+vpath make-kalman ../util
+vpath kalman.5c ../kalman
+vpath kalman_filter.5c ../kalman
+vpath load_csv.5c ../kalman
+vpath matrix.5c ../kalman
+vpath ao-make-product.5c ../util
+
+CC=arm-none-eabi-gcc
+SAT=/opt/cortex
+SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a
+SAT_CFLAGS=-I$(SAT)/include
+
+ifndef VERSION
+include ../Version
+endif
+
+AO_CFLAGS=-I. -I../lpc -I../core -I../drivers -I..
+LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS)
+
+LDFLAGS=-L../stm -Wl,-Taltos.ld
+
+NICKLE=nickle
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf "  $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+.c.o:
+       $(call quiet,CC) -c $(CFLAGS) -o $@ $<
+
+ao_serial_lpc.h: ../lpc/baud_rate ao_pins.h
+       nickle ../lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@
+
+ao_serial_lpc.o: ao_serial_lpc.h
+
+.DEFAULT_GOAL=all
diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld
new file mode 100644 (file)
index 0000000..7a99e66
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K
+       ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K
+}
+
+INCLUDE registers.ld
+
+EXTERN (lpc_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .text ORIGIN(rom) : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+
+               . = ORIGIN(rom) + 0x100;
+
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.rodata*)     /* Constants */
+
+       } > rom
+
+       .ARM.exidx : {
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               __text_end__ = .;
+       } > rom
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
+               __data_start__ = .;
+               *(.data)        /* initialized data */
+               __data_end__ = .;
+               __bss_start__ = .;
+       } >ram
+
+       .bss : {
+               *(.bss)
+               *(COMMON)
+               __bss_end__ = .;
+       } >ram
+
+       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
+       PROVIDE(end = .);
+}
+
+ENTRY(start);
+
+
diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h
new file mode 100644 (file)
index 0000000..6118216
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_ARCH_H_
+#define _AO_ARCH_H_
+
+#include <lpc.h>
+
+/*
+ * LPC11U14 definitions and code fragments for AltOS
+ */
+
+#define AO_STACK_SIZE  512
+
+#define AO_LED_TYPE    uint16_t
+
+#ifndef AO_TICK_TYPE
+#define AO_TICK_TYPE   uint16_t
+#define AO_TICK_SIGNED int16_t
+#endif
+
+/* Various definitions to make GCC look more like SDCC */
+
+#define ao_arch_naked_declare  __attribute__((naked))
+#define ao_arch_naked_define
+#define __pdata
+#define __data
+#define __xdata
+#define __code const
+#define __reentrant
+#define __interrupt(n)
+#define __at(n)
+
+#define ao_arch_reboot() 
+
+#define ao_arch_nop()          asm("nop")
+
+#define ao_arch_interrupt(n)   /* nothing */
+
+#undef putchar
+#undef getchar
+#define putchar(c)     ao_putchar(c)
+#define getchar                ao_getchar
+
+extern void putchar(char c);
+extern char getchar(void);
+
+/*
+ * ao_romconfig.c
+ */
+
+#define AO_ROMCONFIG_VERSION   2
+
+#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const
+
+extern const uint16_t ao_romconfig_version;
+extern const uint16_t ao_romconfig_check;
+extern const uint16_t ao_serial_number;
+extern const uint32_t ao_radio_cal;
+
+#define ao_arch_task_members\
+       uint32_t *sp;                   /* saved stack pointer */
+
+#define ao_arch_block_interrupts()     asm("cpsid i")
+#define ao_arch_release_interrupts()   asm("cpsie i")
+
+/*
+ * For now, we're running at a weird frequency
+ */
+
+#if AO_HSE
+#define AO_PLLSRC      AO_HSE
+#else
+#define AO_PLLSRC      STM_HSI_FREQ
+#endif
+
+#define AO_PLLVCO      (AO_PLLSRC * AO_PLLMUL)
+#define AO_SYSCLK      (AO_PLLVCO / AO_PLLDIV)
+#define AO_HCLK                (AO_SYSCLK / AO_AHB_PRESCALER)
+#define AO_PCLK1       (AO_HCLK / AO_APB1_PRESCALER)
+#define AO_PCLK2       (AO_HCLK / AO_APB2_PRESCALER)
+
+#if AO_APB1_PRESCALER == 1
+#define AO_TIM23467_CLK                AO_PCLK1
+#else
+#define AO_TIM23467_CLK                (2 * AO_PCLK1)
+#endif
+
+#if AO_APB2_PRESCALER == 1
+#define AO_TIM91011_CLK                AO_PCLK2
+#else
+#define AO_TIM91011_CLK                (2 * AO_PCLK2)
+#endif
+
+#define AO_STM_NVIC_HIGH_PRIORITY      4
+#define AO_STM_NVIC_CLOCK_PRIORITY     6
+#define AO_STM_NVIC_MED_PRIORITY       8
+#define AO_STM_NVIC_LOW_PRIORITY       10
+
+void
+ao_adc_init(void);
+
+
+
+void
+ao_serial_init(void);
+
+#endif /* _AO_ARCH_H_ */
diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h
new file mode 100644 (file)
index 0000000..39222b9
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_ARCH_FUNCS_H_
+#define _AO_ARCH_FUNCS_H_
+
+#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
+#define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
+
+#define ao_enable_port(port) (lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO))
+
+#define lpc_all_bit(port,bit)  (((port) << 5) | (bit))
+
+#define ao_gpio_set(port, bit, pin, v) (lpc_gpio.byte[lpc_all_bit(port,bit)] = v)
+
+#define ao_gpio_get(port, bit, pin)    (lpc_gpio_byte[lpc_all_bit(port,bit)])
+
+#define ao_enable_output(port,bit,pin,v) do {                  \
+               ao_enable_port(port);                           \
+               ao_gpio_set(port, bit, pin, v);                 \
+               lpc_gpio.dir[port] |= (1 << bit);               \
+       } while (0)
+
+#define ao_enable_input(port,bit,mode) do {                            \
+               ao_enable_port(port);                                   \
+               lpc_gpio.dir[port] &= ~(1 << bit);                      \
+               if (mode == AO_EXTI_MODE_PULL_UP)                       \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP);    \
+               else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
+                       stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN);  \
+               else                                                    \
+                       stm_pupdr_set(port, bit, STM_PUPDR_NONE);       \
+       } while (0)
+
+#define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
+
+static inline uint32_t
+ao_arch_irqsave(void) {
+       uint32_t        primask;
+       asm("mrs %0,primask" : "=&r" (primask));
+       ao_arch_block_interrupts();
+       return primask;
+}
+
+static inline void
+ao_arch_irqrestore(uint32_t primask) {
+       asm("msr primask,%0" : : "r" (primask));
+}
+
+static inline void
+ao_arch_memory_barrier() {
+       asm volatile("" ::: "memory");
+}
+
+static inline void
+ao_arch_init_stack(struct ao_task *task, void *start)
+{
+       uint32_t        *sp = (uint32_t *) (task->stack + AO_STACK_SIZE);
+       uint32_t        a = (uint32_t) start;
+       int             i;
+
+       /* Return address (goes into LR) */
+       ARM_PUSH32(sp, a);
+
+       /* Clear register values r0-r7 */
+       i = 8;
+       while (i--)
+               ARM_PUSH32(sp, 0);
+
+       /* APSR */
+       ARM_PUSH32(sp, 0);
+
+       /* PRIMASK with interrupts enabled */
+       ARM_PUSH32(sp, 0);
+
+       task->sp = sp;
+}
+
+static inline void ao_arch_save_regs(void) {
+       /* Save general registers */
+       asm("push {r0-r7,lr}\n");
+
+       /* Save APSR */
+       asm("mrs r0,apsr");
+       asm("push {r0}");
+
+       /* Save PRIMASK */
+       asm("mrs r0,primask");
+       asm("push {r0}");
+}
+
+static inline void ao_arch_save_stack(void) {
+       uint32_t        *sp;
+       asm("mov %0,sp" : "=&r" (sp) );
+       ao_cur_task->sp = (sp);
+       if ((uint8_t *) sp < &ao_cur_task->stack[0])
+               ao_panic (AO_PANIC_STACK);
+}
+
+static inline void ao_arch_restore_stack(void) {
+       uint32_t        sp;
+       sp = (uint32_t) ao_cur_task->sp;
+
+       /* Switch stacks */
+       asm("mov sp, %0" : : "r" (sp) );
+
+       /* Restore PRIMASK */
+       asm("pop {r0}");
+       asm("msr primask,r0");
+
+       /* Restore APSR */
+       asm("pop {r0}");
+       asm("msr apsr,r0");
+
+       /* Restore general registers and return */
+       asm("pop {r0-r7,pc}\n");
+}
+
+#define ao_arch_isr_stack()
+
+#define ao_arch_wait_interrupt() do {                  \
+               asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");        \
+               ao_arch_release_interrupts();                           \
+               ao_arch_block_interrupts();                             \
+       } while (0)
+
+#define ao_arch_critical(b) do {                               \
+               ao_arch_block_interrupts();                     \
+               do { b } while (0);                             \
+               ao_arch_release_interrupts();                   \
+       } while (0)
+
+#endif /* _AO_ARCH_FUNCS_H_ */
diff --git a/src/lpc/ao_interrupt.c b/src/lpc/ao_interrupt.c
new file mode 100644 (file)
index 0000000..b5e6700
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <string.h>
+
+extern void main(void);
+extern char __stack__;
+extern char __text_start__, __text_end__;
+extern char __data_start__, __data_end__;
+extern char __bss_start__, __bss_end__;
+
+/* Interrupt functions */
+
+void lpc_halt_isr(void)
+{
+       ao_panic(AO_PANIC_CRASH);
+}
+
+void lpc_ignore_isr(void)
+{
+}
+
+int x;
+
+void start(void) {
+       x = 0;
+       memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
+       memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
+       main();
+}
+
+#define STRINGIFY(x) #x
+
+#define isr(name) \
+       void __attribute__ ((weak)) lpc_ ## name ## _isr(void); \
+       _Pragma(STRINGIFY(weak lpc_ ## name ## _isr = lpc_ignore_isr))
+
+#define isr_halt(name) \
+       void __attribute__ ((weak)) lpc_ ## name ## _isr(void); \
+       _Pragma(STRINGIFY(weak lpc_ ## name ## _isr = lpc_halt_isr))
+
+isr(nmi)
+isr_halt(hardfault)
+isr_halt(memmanage)
+isr_halt(busfault)
+isr_halt(usagefault)
+isr(svc)
+isr(debugmon)
+isr(pendsv)
+isr(systick)
+
+isr(pin_int0)  /* IRQ0 */
+isr(pin_int1)
+isr(pin_int2)
+isr(pin_int3)
+isr(pin_int4)  /* IRQ4 */
+isr(pin_int5)
+isr(pin_int6)
+isr(pin_int7)
+
+isr(gint0)     /* IRQ8 */
+isr(gint1)
+isr(ssp1)
+isr(i2c)
+
+isr(ct16b0)    /* IRQ16 */
+isr(ct16b1)
+isr(ct32b0)
+isr(ct32b1)
+isr(ssp0)      /* IRQ20 */
+isr(usart)
+isr(usb_irq)
+isr(usb_fiq)
+
+isr(adc)       /* IRQ24 */
+isr(wwdt)
+isr(bod)
+isr(flash)
+
+isr(usb_wakeup)
+
+#define i(addr,name)   [(addr)/4] = lpc_ ## name ## _isr
+#define c(addr,value)  [(addr)/4] = (value)
+
+__attribute__ ((section(".interrupt")))
+const void *lpc_interrupt_vector[] = {
+       [0] = &__stack__,
+       [1] = start,
+       i(0x08, nmi),
+       i(0x0c, hardfault),
+       c(0x10, 0),
+       c(0x14, 0),
+       c(0x18, 0),
+       c(0x1c, 0),
+       c(0x20, 0),
+       c(0x24, 0),
+       c(0x28, 0),
+       i(0x2c, svc),
+       i(0x30, hardfault),
+       i(0x34, hardfault),
+       i(0x38, pendsv),
+       i(0x3c, systick),
+
+       i(0x40, pin_int0),      /* IRQ0 */
+       i(0x44, pin_int1),
+       i(0x48, pin_int2),
+       i(0x4c, pin_int3),
+       i(0x50, pin_int4),      /* IRQ4 */
+       i(0x54, pin_int5),
+       i(0x58, pin_int6),
+       i(0x5c, pin_int7),
+
+       i(0x60, gint0),         /* IRQ8 */
+       i(0x64, gint1),
+       i(0x68, hardfault),
+       i(0x6c, hardfault),
+       i(0x70, hardfault),     /* IRQ12 */
+       i(0x74, hardfault),
+       i(0x78, ssp1),
+       i(0x7c, i2c),
+
+       i(0x80, ct16b0),        /* IRQ16 */
+       i(0x84, ct16b1),
+       i(0x88, ct32b0),
+       i(0x8c, ct32b1),
+       i(0x90, ssp0),          /* IRQ20 */
+       i(0x94, usart),
+       i(0x98, usb_irq),
+       i(0x9c, usb_fiq),
+
+       i(0xa0, adc),           /* IRQ24 */
+       i(0xa4, wwdt),
+       i(0xa8, bod),
+       i(0xac, flash),
+
+       i(0xb0, hardfault),     /* IRQ28 */
+       i(0xb4, hardfault),
+       i(0xb8, usb_wakeup),
+       i(0xbc, hardfault),     
+};
diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c
new file mode 100644 (file)
index 0000000..098dad6
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+__pdata uint16_t ao_led_enable;
+
+void
+ao_led_on(uint16_t colors)
+{
+       lpc_gpio.pin[LED_PORT] = 0xffffffff;
+}
+
+void
+ao_led_off(uint16_t colors)
+{
+       lpc_gpio.pin[LED_PORT] = 0;
+}
+
+void
+ao_led_set(uint16_t colors)
+{
+       uint16_t        on = colors & ao_led_enable;
+       uint16_t        off = ~colors & ao_led_enable;
+
+       ao_led_off(off);
+       ao_led_on(on);
+}
+
+void
+ao_led_toggle(uint16_t colors)
+{
+}
+
+void
+ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
+{
+       ao_led_on(colors);
+       ao_delay(ticks);
+       ao_led_off(colors);
+}
+
+void
+ao_led_init(uint16_t enable)
+{
+       int     bit;
+
+       ao_led_enable = enable;
+       lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO);
+       lpc_gpio.dir[LED_PORT] |= enable;
+}
diff --git a/src/lpc/ao_romconfig.c b/src/lpc/ao_romconfig.c
new file mode 100644 (file)
index 0000000..cbb922e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION;
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION;
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0;
+#ifdef AO_RADIO_CAL_DEFAULT
+AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT;
+#endif
diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c
new file mode 100644 (file)
index 0000000..e47f743
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_serial.h>
+
+struct ao_fifo ao_usart_rx_fifo;
+struct ao_fifo ao_usart_tx_fifo;
+uint8_t                ao_usart_tx_started;
+
+void
+ao_debug_out(char c)
+{
+       if (c == '\n')
+               ao_debug_out('\r');
+#if 0
+       while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE)));
+       stm_usart1.dr = c;
+#endif
+}
+
+static void
+_ao_serial_tx_start(void)
+{
+       if (!ao_fifo_empty(ao_usart_tx_fifo) & !ao_usart_tx_started)
+       {
+               ao_usart_tx_started = 1;
+#if 0
+               ao_fifo_remove(ao_usart_tx_fifo, usart->reg->dr);
+#endif
+       }
+}
+
+void
+lpc_usart_isr(void)
+{
+#if 0
+       uint32_t        sr;
+
+       sr = usart->reg->sr;
+       usart->reg->sr = 0;
+
+       if (sr & (1 << STM_USART_SR_RXNE)) {
+               char c = usart->reg->dr;
+               if (!ao_fifo_full(ao_usart_rx_fifo))
+                       ao_fifo_insert(ao_usart_rx_fifo, c);
+               ao_wakeup(ao_usart_rx_fifo);
+               if (stdin)
+                       ao_wakeup(&ao_stdin_ready);
+       }
+       if (sr & (1 << STM_USART_SR_TC)) {
+               ao_usart_tx_started = 0;
+               _ao_usart_tx_start(usart);
+               ao_wakeup(ao_usart_tx_fifo);
+       }
+#endif
+}
+
+int
+_ao_serial_pollchar(void)
+{
+       int     c;
+       
+       if (ao_fifo_empty(ao_usart_rx_fifo))
+               c = AO_READ_AGAIN;
+       else {
+               uint8_t u;
+               ao_fifo_remove(ao_usart_rx_fifo,u);
+               c = u;
+       }
+       return c;
+}
+
+char
+ao_serial_getchar(void)
+{
+       int c;
+       ao_arch_block_interrupts();
+       while ((c = _ao_serial_pollchar()) == AO_READ_AGAIN)
+               ao_sleep(&ao_usart_rx_fifo);
+       ao_arch_release_interrupts();
+       return (char) c;
+}
+
+void
+ao_serial_putchar(char c)
+{
+       ao_arch_block_interrupts();
+       while (ao_fifo_full(ao_usart_tx_fifo))
+               ao_sleep(&ao_usart_tx_fifo);
+       ao_fifo_insert(ao_usart_tx_fifo, c);
+       _ao_serial_tx_start();
+       ao_arch_release_interrupts();
+}
+
+void
+ao_serial_drain(void)
+{
+       ao_arch_block_interrupts();
+       while (!ao_fifo_empty(ao_usart_tx_fifo))
+               ao_sleep(&ao_usart_tx_fifo);
+       ao_arch_release_interrupts();
+}
+
+void
+ao_serial_set_speed(uint8_t speed)
+{
+       if (speed > AO_SERIAL_SPEED_115200)
+               return;
+#if 0
+       usart->reg->brr = ao_usart_speeds[speed].brr;
+#endif
+}
+
+#include "ao_serial_lpc.h"
+
+void
+ao_serial_init(void)
+{
+       /* Turn on the USART clock */
+       lpc_scb.uartclkdiv = 1;
+
+#if SERIAL_0_18_19
+       lpc_ioconf.pio0_18 = ((LPC_IOCONF_FUNC_PIO0_18_RXD << LPC_IOCONF_FUNC) |
+                             (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) |
+                             (0 << LPC_IOCONF_HYS) |
+                             (0 << LPC_IOCONF_INV) |
+                             (0 << LPC_IOCONF_OD));
+       lpc_ioconf.pio0_19 = ((LPC_IOCONF_FUNC_PIO0_19_TXD << LPC_IOCONF_FUNC) |
+                             (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) |
+                             (0 << LPC_IOCONF_HYS) |
+                             (0 << LPC_IOCONF_INV) |
+                             (0 << LPC_IOCONF_OD));
+#endif
+
+       /* Turn on the USART */
+       lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_USART);
+}
+
+
diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c
new file mode 100644 (file)
index 0000000..aa796ac
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+volatile __data AO_TICK_TYPE ao_tick_count;
+
+uint16_t
+ao_time(void)
+{
+       return ao_tick_count;
+}
+
+#if AO_DATA_ALL
+volatile __data uint8_t        ao_data_interval = 1;
+volatile __data uint8_t        ao_data_count;
+#endif
+
+void lpc_systick_isr(void)
+{
+       if (lpc_systick.csr & (1 << LPC_SYSTICK_CSR_COUNTFLAG)) {
+               ++ao_tick_count;
+#if HAS_TASK_QUEUE
+               if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
+                       ao_task_check_alarm((uint16_t) ao_tick_count);
+#endif
+#if AO_DATA_ALL
+               if (++ao_data_count == ao_data_interval) {
+                       ao_data_count = 0;
+                       ao_adc_poll();
+#if (AO_DATA_ALL & ~(AO_DATA_ADC))
+                       ao_wakeup((void *) &ao_data_count);
+#endif
+               }
+#endif
+       }
+}
+
+#if HAS_ADC
+void
+ao_timer_set_adc_interval(uint8_t interval)
+{
+       ao_arch_critical(
+               ao_data_interval = interval;
+               ao_data_count = 0;
+               );
+}
+#endif
+
+#define SYSTICK_RELOAD ((AO_LPC_CLKOUT / 2) / 100 - 1)
+
+/* Initialize our 100Hz clock */
+void
+ao_timer_init(void)
+{
+       lpc_systick.rvr = SYSTICK_RELOAD;
+       lpc_systick.cvr = 0;
+       lpc_systick.csr = ((1 << LPC_SYSTICK_CSR_ENABLE) |
+                          (1 << LPC_SYSTICK_CSR_TICKINT) |
+                          (LPC_SYSTICK_CSR_CLKSOURCE_CPU_OVER_2 << LPC_SYSTICK_CSR_CLKSOURCE));
+}
+
+#define AO_LPC_M       ((AO_LPC_CLKOUT / AO_LPC_CLKIN) - 1)
+
+#define AO_LPC_FCCO_MIN        156000000
+
+void
+ao_clock_init(void)
+{
+       uint8_t         p;
+       uint32_t        i;
+
+       /* Turn off all perhipherals except for GPIO configuration */
+       lpc_scb.sysahbclkctrl = ((1 << LPC_SCB_SYSAHBCLKCTRL_SYS) |
+                                (1 << LPC_SCB_SYSAHBCLKCTRL_ROM) |
+                                (1 << LPC_SCB_SYSAHBCLKCTRL_RAM0) |
+                                (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) |
+                                (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |
+                                (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON));
+                                
+       /* Turn the IRC clock back on */
+       lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);
+       
+       /* Switch to the IRC clock */
+       lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;
+       lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);
+       lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
+       
+       /* Find a PLL post divider ratio that gets the FCCO in range */
+       for (p = 0; p < 4; p++)
+               if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN)
+                       break;
+
+       if (p == 4)
+               ao_panic(AO_PANIC_CRASH);
+
+       /* Power down the PLL before touching the registers */
+       lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);
+
+       /* Set PLL divider values */
+       lpc_scb.syspllctrl = ((AO_LPC_M << LPC_SCB_SYSPLLCTRL_MSEL) |
+                             (p << LPC_SCB_SYSPLLCTRL_PSEL));
+
+
+       /* Turn off the external crystal clock */
+       lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSOSC_PD);
+
+       /* Configure the crystal clock */
+       lpc_scb.sysoscctrl = ((0 << LPC_SCB_SYSOSCCTRL_BYPASS) |                           /* using a crystal */
+                             ((AO_LPC_CLKIN > 15000000) << LPC_SCB_SYSOSCCTRL_FREQRANGE));/* set range */
+
+       /* Turn on the external crystal clock */
+       lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSOSC_PD);
+
+       /* Select crystal as PLL input */
+
+       lpc_scb.syspllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL);
+       lpc_scb.syspllclkuen = 0;
+       lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA);
+       
+       /* Turn on the PLL */
+       lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);
+
+       /* Wait for it to lock */
+       
+       for (i = 0; i < 20000; i++)
+               if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK))
+                       break;
+       if (i == 20000)
+               ao_panic(AO_PANIC_CRASH);
+
+       /* Switch to the PLL */
+       lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_PLL_OUTPUT << LPC_SCB_MAINCLKSEL_SEL;
+       lpc_scb.mainclkuen = 0 << LPC_SCB_MAINCLKUEN_ENA;
+       lpc_scb.mainclkuen = 1 << LPC_SCB_MAINCLKUEN_ENA;
+
+       /* Set system clock divider */
+       lpc_scb.sysahbclkdiv = AO_LPC_CLKOUT / AO_LPC_SYSCLK;
+
+       /* Set USB clock source */
+       lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);
+       lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
+       lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
+
+       /* Shut down perhipheral clocks (enabled as needed) */
+       lpc_scb.ssp0clkdiv = 0;
+       lpc_scb.uartclkdiv = 0;
+       lpc_scb.ssp1clkdiv = 0;
+       lpc_scb.usbclkdiv = 0;
+       lpc_scb.clkoutdiv = 0;
+}
diff --git a/src/lpc/baud_rate b/src/lpc/baud_rate
new file mode 100644 (file)
index 0000000..2bfbf30
--- /dev/null
@@ -0,0 +1,131 @@
+#!/usr/bin/env nickle
+
+/*
+ * Given a main clock frequency,
+ * compute USART clock freq and a table
+ * of USART config parameters for our target baud rates
+ */
+
+real main_clock = 0;
+real usart_clock = 0;
+
+real[] baud_rates = { 4800, 9600, 19200, 57600, 115200 };
+
+void
+compute_baud_rate(real rate) {
+       int     divaddval;
+       int     mulval;
+
+       real    dl_est = usart_clock / (16 * rate);
+
+       if (dl_est == floor(dl_est)) {
+               divaddval = 0;
+               mulval = 1;
+       } else {
+               if (false) {
+
+                       /* This is how the docs suggest doing it; this
+                        * generates a rate which is reasonably close
+                        */
+
+                       real fr_est = 1.5;
+
+                       /* Compute fractional estimate */
+                       do {
+                               dl_est = floor(usart_clock / (16 * rate * fr_est) + 0.5);
+                               fr_est = usart_clock / (16 * rate * dl_est);
+                       } while (fr_est <= 1.1 || 1.9 <= fr_est);
+
+                       /* Given fractional estimate, compute divaddval/mulvals that work best */
+
+                       real best_dist = 1000;
+                       for (int tmp_divaddval = 1; tmp_divaddval < 15; tmp_divaddval++) {
+                               for (int tmp_mulval = 1; tmp_mulval < 16; tmp_mulval++) {
+                                       real fr = 1 + tmp_divaddval / tmp_mulval;
+                                       real dist = abs(fr - fr_est);
+                                       if (dist < best_dist) {
+                                               divaddval = tmp_divaddval;
+                                               mulval = tmp_mulval;
+                                               best_dist = dist;
+                                       }
+                               }
+                       }
+               } else {
+
+                       /* This exhaustively searches for the best match */
+
+                       real my_best_dist = 1e20;
+                       int my_best_dl;
+                       int my_best_divaddval;
+                       int my_best_mulval;
+                       for (int my_dl = 1; my_dl < 1024; my_dl++) {
+                               for (int my_mulval = 1; my_mulval < 16; my_mulval++) {
+                                       for (int my_divaddval = 0; my_divaddval < my_mulval; my_divaddval++) {
+                                               real my_rate = usart_clock / ((16 * my_dl) * (1 + my_divaddval/my_mulval));
+
+                                               real my_dist = abs(rate - my_rate);
+
+                                               if (my_dist == 0 && my_divaddval == 0) {
+                                                       my_dist = -1;
+                                               }
+
+                                               if (my_dist < my_best_dist) {
+                                                       my_best_dl = my_dl;
+                                                       my_best_divaddval = my_divaddval;
+                                                       my_best_mulval = my_mulval;
+                                                       my_best_dist = my_dist;
+                                               }
+                                       }
+                               }
+                       }
+
+                       dl_est = my_best_dl;
+                       divaddval = my_best_divaddval;
+                       mulval = my_best_mulval;
+               }
+       }
+
+       int dl = floor (dl_est);        
+
+       real actual = usart_clock / ((16 * dl) * (1 + divaddval/mulval));
+
+       printf("\t[AO_SERIAL_SPEED_%d] = { /* actual = %8.2f */\n", floor(rate), actual);
+       printf("\t\t.dl = %d,\n", dl);
+       printf("\t\t.divaddval = %d,\n", divaddval);
+       printf("\t\t.mulval = %d\n", mulval);
+       printf("\t},\n");
+}
+
+void
+main() {
+       if (dim(argv) < 2) {
+               printf ("usage: %s <main-clock>\n", argv[0]);
+               exit(1);
+       }
+       main_clock = string_to_real(argv[1]);
+
+       for (int div = 0; div < 4; div++) {
+               if (main_clock / (1 << div) <= 12000000) {
+                       usart_clock = main_clock / (1 << div);
+                       break;
+               }
+       }
+
+       if (usart_clock == 0) {
+               printf ("can't get usart clock in range\n");
+               exit(1);
+       }
+
+       printf ("#define AO_LPC_USARTCLK %d\n\n", floor(usart_clock));
+       printf("static const struct {\n");
+       printf("\tuint16_t dl;\n");
+       printf("\tuint8_t divaddval;\n");
+       printf("\tuint8_t mulval;\n");
+       printf("} ao_usart_speeds[] = {\n");
+       for (int i = 0; i < dim(baud_rates); i++) {
+               compute_baud_rate(baud_rates[i]);
+       }
+       printf ("};\n");
+}
+
+main();
diff --git a/src/lpc/figure-checksum b/src/lpc/figure-checksum
new file mode 100755 (executable)
index 0000000..0b1de57
--- /dev/null
@@ -0,0 +1,39 @@
+#!/usr/bin/env nickle
+
+autoimport Process;
+
+int byteflip(int x) {
+       return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | ((x << 24) & 0xff000000);
+}
+
+void main () {
+       file    input = popen(popen_direction.read, true, "objdump",
+                             "objdump", "-j", ".text",
+                             "--start-address=0",
+                             "--stop-address=0x20",
+                             "-s", argv[1]);
+       int sum = 0;
+
+       void add_in(int addr, int value) {
+               if (addr < 0x1c) {
+                       sum += value;
+               } else if (addr == 0x1c) {
+                       printf ("-DCKSUM=0x%08x\n", -sum & 0xffffffff);
+                       exit(0);
+               }
+       }
+       while (!File::end(input)) {
+               string line = File::fgets(input);
+               string[] words = String::wordsplit(line, " ");
+
+               if (dim(words) < 5)
+                   continue;
+               if (words[0] == "0000" || words[0] == "0010") {
+                       int addr = string_to_integer(words[0], 16);
+                       for (int i = 0; i < 4; i++)
+                               add_in(addr + i * 4, byteflip(string_to_integer(words[i+1], 16)));
+               }
+       }
+}
+
+main();
diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h
new file mode 100644 (file)
index 0000000..87af494
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _LPC_H_
+#define _LPC_H_
+
+#include <stdint.h>
+
+typedef volatile uint32_t      vuint32_t;
+typedef volatile uint16_t      vuint16_t;
+typedef volatile uint8_t       vuint8_t;
+typedef volatile void *                vvoid_t;
+
+struct lpc_ioconf {
+       vuint32_t       pio0_0;
+       vuint32_t       pio0_1;
+       vuint32_t       pio0_2;
+       vuint32_t       pio0_3;
+
+       vuint32_t       pio0_4;
+       vuint32_t       pio0_5;
+       vuint32_t       pio0_6;
+       vuint32_t       pio0_7;
+
+       vuint32_t       pio0_8;
+       vuint32_t       pio0_9;
+       vuint32_t       pio0_10;
+       vuint32_t       pio0_11;
+
+       vuint32_t       pio0_12;
+       vuint32_t       pio0_13;
+       vuint32_t       pio0_14;
+       vuint32_t       pio0_15;
+
+       vuint32_t       pio0_16;
+       vuint32_t       pio0_17;
+       vuint32_t       pio0_18;
+       vuint32_t       pio0_19;
+
+       vuint32_t       pio0_20;
+       vuint32_t       pio0_21;
+       vuint32_t       pio0_22;
+       vuint32_t       pio0_23;
+
+       vuint32_t       pio1_0;         /* 0x60 */
+       vuint32_t       pio1_1;
+       vuint32_t       pio1_2;
+       vuint32_t       pio1_3;
+
+       vuint32_t       pio1_4;
+       vuint32_t       pio1_5;
+       vuint32_t       pio1_6;
+       vuint32_t       pio1_7;
+
+       vuint32_t       pio1_8;         /* 0x80 */
+       vuint32_t       pio1_9;
+       vuint32_t       pio1_10;
+       vuint32_t       pio1_11;
+
+       vuint32_t       pio1_12;
+       vuint32_t       pio1_13;
+       vuint32_t       pio1_14;
+       vuint32_t       pio1_15;
+
+       vuint32_t       pio1_16;        /* 0xa0 */
+       vuint32_t       pio1_17;
+       vuint32_t       pio1_18;
+       vuint32_t       pio1_19;
+
+       vuint32_t       pio1_20;
+       vuint32_t       pio1_21;
+       vuint32_t       pio1_22;
+       vuint32_t       pio1_23;
+
+       vuint32_t       pio1_24;        /* 0xc0 */
+       vuint32_t       pio1_25;
+       vuint32_t       pio1_26;
+       vuint32_t       pio1_27;
+
+       vuint32_t       pio1_28;
+       vuint32_t       pio1_29;
+       vuint32_t       pio1_30;
+       vuint32_t       pio1_31;
+};
+
+extern struct lpc_ioconf lpc_ioconf;
+
+#define LPC_IOCONF_FUNC                0
+
+/* PIO0_0 */
+#define  LPC_IOCONF_FUNC_RESET         0
+#define  LPC_IOCONF_FUNC_PIO0_0                1
+
+/* PIO0_1 */
+#define  LPC_IOCONF_FUNC_PIO0_1                0
+#define  LPC_IOCONF_FUNC_CLKOUT                1
+#define  LPC_IOCONF_FUNC_CT32B0_MAT2   2
+#define  LPC_IOCONF_FUNC_USB_FTOGGLE   3
+
+/* PIO0_2 */
+#define  LPC_IOCONF_FUNC_PIO0_2                0
+#define  LPC_IOCONF_FUNC_SSEL0         1
+#define  LPC_IOCONF_FUNC_CT16B0_CAP0   2
+
+/* PIO0_3
+#define  LPC_IOCONF_FUNC_PIO0_3                0
+#define  LPC_IOCONF_FUNC_USB_VBUS      1
+
+/* PIO0_4
+#define  LPC_IOCONF_FUNC_PIO0_4                0
+#define  LPC_IOCONF_FUNC_I2C_SCL       1
+
+/* PIO0_5 */
+#define  LPC_IOCONF_FUNC_PIO0_5                0
+#define  LPC_IOCONF_FUNC_I2C_SDA       1
+
+/* PIO0_6 */
+#define  LPC_IOCONF_FUNC_PIO0_6                0
+#define  LPC_IOCONF_FUNC_USB_CONNECT   1
+#define  LPC_IOCONF_FUNC_SCK0          2
+
+/* PIO0_7 */
+#define  LPC_IOCONF_FUNC_PIO0_7                0
+#define  LPC_IOCONF_FUNC_CTS           1
+
+/* PIO0_8
+#define  LPC_IOCONF_FUNC_PIO0_8                0
+#define  LPC_IOCONF_FUNC_MISO0         1
+#define  LPC_IOCONF_FUNC_CT16B0_MAT0   2
+
+/* PIO0_9 */
+#define  LPC_IOCONF_FUNC_PIO0_9                0
+#define  LPC_IOCONF_FUNC_MOSI0         1
+#define  LPC_IOCONF_FUNC_CT16B0_MAT1   2
+
+/* PIO0_10 */
+#define  LPC_IOCONF_FUNC_SWCLK         0
+#define  LPC_IOCONF_FUNC_PIO0_10       1
+#define  LPC_IOCONF_FUNC_SCK0          2
+#define  LPC_IOCONF_FUNC_CT16B0_MAT2   3
+
+/* PIO0_11 */
+#define  LPC_IOCONF_FUNC_TDI           0
+#define  LPC_IOCONF_FUNC_PIO0_11       1
+#define  LPC_IOCONF_FUNC_AD0           2
+#define  LPC_IOCONF_FUNC_CT32B0_MAT3   3
+
+/* PIO0_12 */
+#define  LPC_IOCONF_FUNC_TMS           0
+#define  LPC_IOCONF_FUNC_PIO0_12       1
+#define  LPC_IOCONF_FUNC_AD1           2
+#define  LPC_IOCONF_FUNC_CT32B1_CAP0   3
+
+/* PIO0_13 */
+#define  LPC_IOCONF_FUNC_TD0           0
+#define  LPC_IOCONF_FUNC_PIO0_13       1
+#define  LPC_IOCONF_FUNC_AD2           2
+#define  LPC_IOCONF_FUNC_CT32B1_MAT0   3
+
+/* PIO0_14 */
+#define  LPC_IOCONF_FUNC_TRST          0
+#define  LPC_IOCONF_FUNC_PIO0_14       1
+#define  LPC_IOCONF_FUNC_AD3           2
+#define  LPC_IOCONF_FUNC_PIO0_14_CT32B1_MAT1   3
+
+/* PIO0_15 */
+#define  LPC_IOCONF_FUNC_SWDIO         0
+#define  LPC_IOCONF_FUNC_PIO0_15       1
+#define  LPC_IOCONF_FUNC_AD4           2
+#define  LPC_IOCONF_FUNC_CT32B1_MAT2   3
+
+/* PIO0_16 */
+#define  LPC_IOCONF_FUNC_PIO0_16       0
+#define  LPC_IOCONF_FUNC_AD5           1
+#define  LPC_IOCONF_FUNC_CT32B1_MAT3   2
+
+/* PIO0_17 */
+#define  LPC_IOCONF_FUNC_PIO0_17       0
+#define  LPC_IOCONF_FUNC_RTS           1
+#define  LPC_IOCONF_FUNC_CT32B0_CAP0   2
+#define  LPC_IOCONF_FUNC_SCLK          3
+
+/* PIO0_18 */
+#define  LPC_IOCONF_FUNC_PIO0_18               0
+#define  LPC_IOCONF_FUNC_PIO0_18_RXD           1
+#define  LPC_IOCONF_FUNC_PIO0_18_CT32B0_MAT0   2
+
+/* PIO0_19 */
+#define  LPC_IOCONF_FUNC_PIO0_19               0
+#define  LPC_IOCONF_FUNC_PIO0_19_TXD           1
+#define  LPC_IOCONF_FUNC_PIO0_19_CT32B0_MAT1   2
+
+/* PIO0_20 */
+#define  LPC_IOCONF_FUNC_PIO0_20       0
+#define  LPC_IOCONF_FUNC_CT16B1_CAP0   1
+
+/* PIO0_21 */
+#define  LPC_IOCONF_FUNC_PIO0_21       0
+#define  LPC_IOCONF_FUNC_CT16B1_MAT0   1
+#define  LPC_IOCONF_FUNC_MOSI1         2
+
+/* PIO0_22 */
+#define  LPC_IOCONF_FUNC_PIO0_22       0
+#define  LPC_IOCONF_FUNC_AD6           1
+#define  LPC_IOCONF_FUNC_CT16B1_MAT1   2
+#define  LPC_IOCONF_FUNC_MISO1         3
+
+/* PIO0_23 */
+#define  LPC_IOCONF_FUNC_PIO0_23       0
+#define  LPC_IOCONF_FUNC_AD7           1
+
+/* PIO1_0 */
+#define  LPC_IOCONF_FUNC_PIO1_0                0
+#define  LPC_IOCONF_FUNC_CT32B1_MAT1   1
+
+/* PIO1_1 */
+#define  LPC_IOCONF_FUNC_PIO1_1                0
+#define  LPC_IOCONF_FUNC_CT32B1_MAT1   1
+
+/* PIO1_2 */
+#define  LPC_IOCONF_FUNC_PIO1_2                0
+#define  LPC_IOCONF_FUNC_PIO1_2_CT32B1_MAT2    1
+
+/* PIO1_3*/
+#define  LPC_IOCONF_FUNC_PIO1_3                0
+#define  LPC_IOCONF_FUNC_PIO1_3_CT32B1_MAT3    1
+
+/* PIO1_4 */
+#define  LPC_IOCONF_FUNC_PIO1_4                0
+#define  LPC_IOCONF_FUNC_PIO1_4_CT32B1_CAP0    1
+
+/* PIO1_5 */
+#define  LPC_IOCONF_FUNC_PIO1_5                0
+#define  LPC_IOCONF_FUNC_CT32B1_CAP1   1
+
+/* PIO1_6 */
+#define  LPC_IOCONF_FUNC_PIO1_6                0
+
+/* PIO1_7 */
+#define  LPC_IOCONF_FUNC_PIO1_7                0
+
+/* PIO1_8 */
+#define  LPC_IOCONF_FUNC_PIO1_8                0
+
+/* PIO1_9 */
+#define  LPC_IOCONF_FUNC_PIO1_9                0
+
+/* PIO1_10 */
+#define  LPC_IOCONF_FUNC_PIO1_10       0
+
+/* PIO1_11 */
+#define  LPC_IOCONF_FUNC_PIO1_11       0
+
+/* PIO1_12 */
+#define  LPC_IOCONF_FUNC_PIO1_12       0
+
+/* PIO1_13 */
+#define  LPC_IOCONF_FUNC_PIO1_13       0
+#define  LPC_IOCONF_FUNC_DTR           1
+#define  LPC_IOCONF_FUNC_CT16B0_MAT0   2
+#define  LPC_IOCONF_FUNC_PIO1_13_TXD           3
+
+/* PIO1_14 */
+#define  LPC_IOCONF_FUNC_PIO1_14       0
+#define  LPC_IOCONF_FUNC_DSR           1
+#define  LPC_IOCONF_FUNC_CT16B0_MAT1   2
+#define  LPC_IOCONF_FUNC_PIO1_13_RXD           3
+
+/* PIO1_15 */
+#define  LPC_IOCONF_FUNC_PIO1_15       0
+#define  LPC_IOCONF_FUNC_DCD           1
+#define  LPC_IOCONF_FUNC_PIO1_15_CT16B0_MAT2   2
+#define  LPC_IOCONF_FUNC_SCK1          3
+
+/* PIO1_16 */
+#define  LPC_IOCONF_FUNC_PIO1_16       0
+#define  LPC_IOCONF_FUNC_RI            1
+#define  LPC_IOCONF_FUNC_CT16B0_CAP0   2
+
+/* PIO1_17 */
+#define  LPC_IOCONF_FUNC_PIO1_17       0
+#define  LPC_IOCONF_FUNC_CT16B0_CAP1   1
+#define  LPC_IOCONF_FUNC_PIO1_17_RXD           2
+
+/* PIO1_18 */
+#define  LPC_IOCONF_FUNC_PIO1_18       0
+#define  LPC_IOCONF_FUNC_CT16B1_CAP1   1
+#define  LPC_IOCONF_FUNC_PIO1_18_TXD           2
+
+/* PIO1_19 */
+#define  LPC_IOCONF_FUNC_PIO1_19       0
+#define  LPC_IOCONF_FUNC_DTR           1
+#define  LPC_IOCONF_FUNC_SSEL1         2
+
+/* PIO1_20 */
+#define  LPC_IOCONF_FUNC_PIO1_20       0
+#define  LPC_IOCONF_FUNC_DSR           1
+#define  LPC_IOCONF_FUNC_PIO1_20_SCK1          2
+
+/* PIO1_21 */
+#define  LPC_IOCONF_FUNC_PIO1_21       0
+#define  LPC_IOCONF_FUNC_DCD           1
+#define  LPC_IOCONF_FUNC_PIO1_21_MISO1         2
+
+/* PIO1_22 */
+#define  LPC_IOCONF_FUNC_PIO1_22       0
+#define  LPC_IOCONF_FUNC_RI            1
+#define  LPC_IOCONF_FUNC_MOSI1         2
+
+/* PIO1_23 */
+#define  LPC_IOCONF_FUNC_PIO1_23       0
+#define  LPC_IOCONF_FUNC_PIO1_23_CT16B1_MAT1   1
+#define  LPC_IOCONF_FUNC_SSEL1         2
+
+/* PIO1_24 */
+#define  LPC_IOCONF_FUNC_PIO1_24       0
+#define  LPC_IOCONF_FUNC_PIO1_24_CT32B0_MAT0   1
+
+/* PIO1_25 */
+#define  LPC_IOCONF_FUNC_PIO1_25       0
+#define  LPC_IOCONF_FUNC_PIO1_25_CT32B0_MAT1   1
+
+/* PIO1_26 */
+#define  LPC_IOCONF_FUNC_PIO1_26       0
+#define  LPC_IOCONF_FUNC_PIO1_26_CT32B0_MAT2   1
+#define  LPC_IOCONF_FUNC_PIO1_26_RXD           2
+
+/* PIO1_27 */
+#define  LPC_IOCONF_FUNC_PIO1_27       0
+#define  LPC_IOCONF_FUNC_PIO1_27_CT32B0_MAT3   1
+#define  LPC_IOCONF_FUNC_PIO1_27_TXD           2
+
+/* PIO1_28 */
+#define  LPC_IOCONF_FUNC_PIO1_28       0
+#define  LPC_IOCONF_FUNC_PIO1_28_CT32B0_CAP0   1
+#define  LPC_IOCONF_FUNC_PIO1_28_SCLK          2
+
+/* PIO1_29 */
+#define  LPC_IOCONF_FUNC_PIO1_29               0
+#define  LPC_IOCONF_FUNC_PIO1_29_SCK0          1
+#define  LPC_IOCONF_FUNC_PIO1_29_CT32B0_CAP1   2
+
+/* PIO1_31 */
+#define  LPC_IOCONF_FUNC_PIO1_31       0
+
+#define  LPC_IOCONF_FUNC_MASK          0x7
+
+#define LPC_IOCONF_MODE                        3
+#define  LPC_IOCONF_MODE_INACTIVE              0
+#define  LPC_IOCONF_MODE_PULL_DOWN             1
+#define  LPC_IOCONF_MODE_PULL_UP               2
+#define  LPC_IOCONF_MODE_REPEATER              3
+#define  LPC_IOCONF_MODE_MASK                  3
+
+#define LPC_IOCONF_HYS                 5
+
+#define LPC_IOCONF_INV                 6
+#define LPC_IOCONF_OD                  10
+
+struct lpc_scb {
+       vuint32_t       sysmemremap;    /* 0x00 */
+       vuint32_t       presetctrl;
+       vuint32_t       syspllctrl;
+       vuint32_t       syspllstat;
+
+       vuint32_t       usbpllctrl;     /* 0x10 */
+       vuint32_t       usbpllstat;
+       uint32_t        r18;
+       uint32_t        r1c;
+
+       vuint32_t       sysoscctrl;     /* 0x20 */
+       vuint32_t       wdtoscctrl;
+       uint32_t        r28;
+       uint32_t        r2c;
+
+       vuint32_t       sysrststat;     /* 0x30 */
+       uint32_t        r34;
+       uint32_t        r38;
+       uint32_t        r3c;
+
+       vuint32_t       syspllclksel;   /* 0x40 */
+       vuint32_t       syspllclkuen;
+       vuint32_t       usbpllclksel;
+       vuint32_t       usbplllclkuen;
+
+       uint32_t        r50[8];
+
+       vuint32_t       mainclksel;     /* 0x70 */
+       vuint32_t       mainclkuen;
+       vuint32_t       sysahbclkdiv;
+       uint32_t        r7c;            
+
+       vuint32_t       sysahbclkctrl;  /* 0x80 */
+       uint32_t        r84[3];
+
+       uint32_t        r90;            /* 0x90 */
+       vuint32_t       ssp0clkdiv;
+       vuint32_t       uartclkdiv;
+       vuint32_t       ssp1clkdiv;
+
+       uint32_t        ra0[8];
+
+       vuint32_t       usbclksel;      /* 0xc0 */
+       vuint32_t       usbclkuen;
+       vuint32_t       usbclkdiv;
+       uint32_t        rcc;
+
+       uint32_t        rd0[4];
+       
+       vuint32_t       clkoutsel;      /* 0xe0 */
+       vuint32_t       clkoutuen;
+       vuint32_t       clkoutdiv;
+       uint32_t        rec;
+       
+       uint32_t        rf0[4];         /* 0xf0 */
+       
+       vuint32_t       pioporcap0;     /* 0x100 */
+       vuint32_t       pioporcap1;
+       uint32_t        r102[2];
+
+       uint32_t        r110[4];        /* 0x110 */
+       uint32_t        r120[4];        /* 0x120 */
+       uint32_t        r130[4];        /* 0x130 */
+       uint32_t        r140[4];        /* 0x140 */
+       
+       vuint32_t       bodctrl;        /* 0x150 */
+       vuint32_t       systckcal;
+       uint32_t        r158[2];
+
+       uint32_t        r160[4];        /* 0x160 */
+
+       vuint32_t       irqlatency;     /* 0x170 */
+       vuint32_t       nmisrc;
+       vuint32_t       pintsel0;
+       vuint32_t       pintsel1;
+
+       vuint32_t       pintsel2;       /* 0x180 */
+       vuint32_t       pintsel3;
+       vuint32_t       pintsel4;
+       vuint32_t       pintsel5;
+
+       vuint32_t       pintsel6;       /* 0x190 */
+       vuint32_t       pintsel7;
+       vuint32_t       usbclkctrl;
+       vuint32_t       usbclkst;
+
+       uint32_t        r1a0[6*4];      /* 0x1a0 */
+
+       uint32_t        r200;           /* 0x200 */
+       vuint32_t       starterp0;
+       uint32_t        r208[2];
+
+       uint32_t        r210;           /* 0x210 */
+       vuint32_t       starterp1;
+       uint32_t        r218[2];
+
+       uint32_t        r220[4];        /* 0x220 */
+
+       vuint32_t       pdsleepcfg;     /* 0x230 */
+       vuint32_t       pdawakecfg;
+       vuint32_t       pdruncfg;
+       uint32_t        r23c;
+
+       uint32_t        r240[12 * 4];   /* 0x240 */
+
+       uint32_t        r300[15 * 4];   /* 0x300 */
+                            
+       uint32_t        r3f0;           /* 0x3f0 */
+       vuint32_t       device_id;
+};
+
+extern struct lpc_scb lpc_scb;
+
+#define LPC_SCB_PRESETCTRL_SSP0_RST_N  0
+#define LPC_SCB_PRESETCTRL_I2C_RST_N   1
+#define LPC_SCB_PRESETCTRL_SSP1_RST_N  2
+
+#define LPC_SCB_SYSPLLCTRL_MSEL                0
+#define LPC_SCB_SYSPLLCTRL_PSEL                5
+#define  LPC_SCB_SYSPLLCTRL_PSEL_1             0
+#define  LPC_SCB_SYSPLLCTRL_PSEL_2             1
+#define  LPC_SCB_SYSPLLCTRL_PSEL_4             2
+#define  LPC_SCB_SYSPLLCTRL_PSEL_8             3
+#define  LPC_SCB_SYSPLLCTRL_PSEL_MASK          3
+
+#define LPC_SCB_SYSPLLSTAT_LOCK                0
+
+#define LPC_SCB_USBPLLCTRL_MSEL                0
+#define LPC_SCB_USBPLLCTRL_PSEL                5
+#define  LPC_SCB_USBPLLCTRL_PSEL_1             0
+#define  LPC_SCB_USBPLLCTRL_PSEL_2             1
+#define  LPC_SCB_USBPLLCTRL_PSEL_4             2
+#define  LPC_SCB_USBPLLCTRL_PSEL_8             3
+#define  LPC_SCB_USBPLLCTRL_PSEL_MASK          3
+
+#define LPC_SCB_USBPLLSTAT_LOCK                0
+
+#define LPC_SCB_SYSOSCCTRL_BYPASS      0
+#define LPC_SCB_SYSOSCCTRL_FREQRANGE   1
+#define  LPC_SCB_SYSOSCCTRL_FREQRANGE_1_20     0
+#define  LPC_SCB_SYSOSCCTRL_FREQRANGE_15_25    1
+
+#define LPC_SCB_WDTOSCCTRL_DIVSEL              0
+#define  LPC_SCB_WDTOSCCTRL_DIVSEL_MASK                        0x1f
+#define LPC_SCB_WDTOSCCTRL_FREQSEL             5
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_0_6                        1
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_1_05               2
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_1_4                        3
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_1_75               4
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_2_1                        5
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_2_4                        6
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_2_7                        7
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_3_0                        8
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_3_25               9
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_3_5                        0x0a
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_3_75               0x0b
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_4_0                        0x0c
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_4_2                        0x0d
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_4_4                        0x0e
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_4_6                        0x0f
+#define  LPC_SCB_WDTOSCCTRL_FREQSEL_MASK               0x0f
+
+#define LPC_SCB_SYSRSTSTAT_POR         0
+#define LPC_SCB_SYSRSTSTAT_EXTRST      1
+#define LPC_SCB_SYSRSTSTAT_WDT         2
+#define LPC_SCB_SYSRSTSTAT_BOD         3
+#define LPC_SCB_SYSRSTSTAT_SYSRST      4
+
+#define LPC_SCB_SYSPLLCLKSEL_SEL       0
+#define  LPC_SCB_SYSPLLCLKSEL_SEL_IRC          0
+#define  LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC       1
+#define  LPC_SCB_SYSPLLCLKSEL_SEL_MASK         3
+
+#define LPC_SCB_SYSPLLCLKUEN_ENA       0
+
+#define LPC_SCB_USBPLLCLKSEL_SEL       0
+#define  LPC_SCB_USBPLLCLKSEL_SEL_IRC          0
+#define  LPC_SCB_USBPLLCLKSEL_SEL_SYSOSC       1
+#define  LPC_SCB_USBPLLCLKSEL_SEL_MASK         3
+
+#define LPC_SCB_USBPLLCLKUEN_ENA       0
+
+#define LPC_SCB_MAINCLKSEL_SEL         0
+#define  LPC_SCB_MAINCLKSEL_SEL_IRC            0
+#define  LPC_SCB_MAINCLKSEL_SEL_PLL_INPUT      1
+#define  LPC_SCB_MAINCLKSEL_SEL_WATCHDOG       2
+#define  LPC_SCB_MAINCLKSEL_SEL_PLL_OUTPUT     3
+#define  LPC_SCB_MAINCLKSEL_SEL_MASK           3
+
+#define LPC_SCB_MAINCLKUEN_ENA         0
+
+#define LPC_SCB_SYSAHBCLKDIV_DIV       0
+
+#define LPC_SCB_SYSAHBCLKCTRL_SYS      0
+#define LPC_SCB_SYSAHBCLKCTRL_ROM      1
+#define LPC_SCB_SYSAHBCLKCTRL_RAM0     2
+#define LPC_SCB_SYSAHBCLKCTRL_FLASHREG 3
+#define LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY       4
+#define LPC_SCB_SYSAHBCLKCTRL_I2C      5
+#define LPC_SCB_SYSAHBCLKCTRL_GPIO     6
+#define LPC_SCB_SYSAHBCLKCTRL_CT16B0   7
+#define LPC_SCB_SYSAHBCLKCTRL_CT16B1   8
+#define LPC_SCB_SYSAHBCLKCTRL_CT32B0   9
+#define LPC_SCB_SYSAHBCLKCTRL_CT32B1   10
+#define LPC_SCB_SYSAHBCLKCTRL_SSP0     11
+#define LPC_SCB_SYSAHBCLKCTRL_USART    12
+#define LPC_SCB_SYSAHBCLKCTRL_ADC      13
+#define LPC_SCB_SYSAHBCLKCTRL_USB      14
+#define LPC_SCB_SYSAHBCLKCTRL_WWDT     15
+#define LPC_SCB_SYSAHBCLKCTRL_IOCON    16
+#define LPC_SCB_SYSAHBCLKCTRL_SSP1     18
+#define LPC_SCB_SYSAHBCLKCTRL_PINT     19
+#define LPC_SCB_SYSAHBCLKCTRL_GROUP0INT        23
+#define LPC_SCB_SYSAHBCLKCTRL_GROUP1INT        24
+#define LPC_SCB_SYSAHBCLKCTRL_RAM1     26
+#define LPC_SCB_SYSAHBCLKCTRL_USBRAM   27
+
+#define LPC_SCB_SSP0CLKDIV_
+#define LPC_SCB_UARTCLKDIV_
+#define LPC_SCB_SSP1CLKDIV_
+
+#define LPC_SCB_USBCLKSEL_SEL          0
+#define LPC_SCB_USBCLKSEL_SEL_USB_PLL          0
+#define LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK       1
+
+#define LPC_SCB_USBCLKUEN_ENA          0
+#define LPC_SCB_USBCLKDIV_DIV          0
+
+#define LPC_SCB_CLKOUTSEL_
+#define LPC_SCB_CLKOUTUEN_
+
+#define LPC_SCB_PDRUNCFG_IRCOUT_PD     0
+#define LPC_SCB_PDRUNCFG_IRC_PD                1
+#define LPC_SCB_PDRUNCFG_FLASH_PD      2
+#define LPC_SCB_PDRUNCFG_BOD_PD                3
+#define LPC_SCB_PDRUNCFG_ADC_PD                4
+#define LPC_SCB_PDRUNCFG_SYSOSC_PD     5
+#define LPC_SCB_PDRUNCFG_WDTOSC_PD     6
+#define LPC_SCB_PDRUNCFG_SYSPLL_PD     7
+#define LPC_SCB_PDRUNCFG_USBPLL_PD     8
+#define LPC_SCB_PDRUNCFG_USBPAD_PD     10
+
+struct lpc_flash {
+       uint32_t        r0[4];          /* 0x0 */
+
+       vuint32_t       flashcfg;       /* 0x10 */
+};
+
+extern struct lpc_flash lpc_flash;
+
+struct lpc_gpio_pin {
+};
+
+extern struct lpc_gpio_pin lpc_gpio_pin;
+
+struct lpc_gpio_group0 {
+};
+
+extern struct lpc_gpio_group0 lpc_gpio_group0;
+
+struct lpc_gpio_group1 {
+};
+
+extern struct lpc_gpio_group1 lpc_gpio_group1;
+
+struct lpc_gpio {
+       vuint8_t        byte[0x40];     /* 0x0000 */
+
+       uint8_t         r0030[0x1000 - 0x40];
+
+       vuint32_t       word[0x40];     /* 0x1000 */
+
+       uint8_t         r1100[0x2000 - 0x1100];
+       
+       vuint32_t       dir[2];         /* 0x2000 */
+
+       uint8_t         r2008[0x2080 - 0x2008];
+
+       vuint32_t       mask[2];        /* 0x2080 */
+
+       uint8_t         r2088[0x2100 - 0x2088];
+
+       vuint32_t       pin[2];         /* 0x2100 */
+
+       uint8_t         r2108[0x2200 - 0x2108];
+
+       vuint32_t       set[2];         /* 0x2200 */
+
+       uint8_t         r2208[0x2280 - 0x2208];
+
+       vuint32_t       clr[2];         /* 0x2280 */
+
+       uint8_t         r2288[0x2300 - 0x2288];
+
+       vuint32_t       not[2];         /* 0x2300 */
+};
+
+extern struct lpc_gpio lpc_gpio;
+
+struct lpc_systick {
+       uint8_t         r0000[0x10];    /* 0x0000 */
+
+       vuint32_t       csr;            /* 0x0010 */
+       vuint32_t       rvr;
+       vuint32_t       cvr;
+       vuint32_t       calib;
+};
+
+extern struct lpc_systick lpc_systick;
+
+#define LPC_SYSTICK_CSR_ENABLE         0
+#define LPC_SYSTICK_CSR_TICKINT                1
+#define LPC_SYSTICK_CSR_CLKSOURCE      2
+#define  LPC_SYSTICK_CSR_CLKSOURCE_CPU_OVER_2          0
+#define  LPC_SYSTICK_CSR_CLKSOURCE_CPU                 1
+#define LPC_SYSTICK_CSR_COUNTFLAG      16
+
+struct lpc_usart {
+       vuint32_t       rbr_thr;        /* 0x0000 */
+       vuint32_t       ier;
+       vuint32_t       iir_fcr;
+       vuint32_t       lcr;
+
+       vuint32_t       mcr;            /* 0x0010 */
+       vuint32_t       lsr;
+       vuint32_t       msr;
+       vuint32_t       scr;
+
+       vuint32_t       acr;            /* 0x0020 */
+       vuint32_t       icr;
+       vuint32_t       fdr;
+       vuint32_t       osr;
+
+       vuint32_t       ter;            /* 0x0030 */
+       uint32_t        r34[3];
+
+       vuint32_t       hden;           /* 0x0040 */
+       uint32_t        r44;
+       vuint32_t       scictrl;
+       vuint32_t       rs485ctrl;
+
+       vuint32_t       rs485addrmatch; /* 0x0050 */
+       vuint32_t       rs485dly;
+       vuint32_t       syncctrl;
+};
+
+extern struct lpc_usart lpc_usart;
+
+#endif /* _LPC_H_ */
diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld
new file mode 100644 (file)
index 0000000..cd6ac5f
--- /dev/null
@@ -0,0 +1,9 @@
+lpc_usart      = 0x40008000;
+lpc_flash      = 0x4003c000;
+lpc_ioconf     = 0x40044000;
+lpc_scb                = 0x40048000;
+lpc_gpio_pin   = 0x4004c000;
+lpc_gpio_group0 = 0x4005c000;
+lpc_gpio_group1 = 0x40060000;
+lpc_gpio       = 0x50000000;
+lpc_systick    = 0xe000e000;
diff --git a/src/lpcxpresso/Makefile b/src/lpcxpresso/Makefile
new file mode 100644 (file)
index 0000000..bac222c
--- /dev/null
@@ -0,0 +1,64 @@
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_pins.h \
+       ao_product.h \
+       lpc.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+       ao_interrupt.c \
+       ao_romconfig.c \
+       ao_product.c \
+       ao_panic.c \
+       ao_led_lpc.c \
+       ao_task.c \
+       ao_timer_lpc.c \
+       ao_serial_lpc.c \
+       ao_stdio.c
+
+PRODUCT=LpcDemo-v0.0
+PRODUCT_DEF=-DLPC_DEMO
+IDPRODUCT=0x000a
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
+
+PROG=lpc-demo.elf
+
+SRC=$(ALTOS_SRC) ao_demo.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG)
+
+LDFLAGS=-L../lpc -Wl,-Taltos.ld
+
+$(PROG): Makefile $(OBJ)
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc
+
+ao_product.h: ao-make-product.5c ../Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+load: $(PROG)
+       lpc-load $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(PROG)
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h
new file mode 100644 (file)
index 0000000..56391c2
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define HAS_BEEP       0
+#define        HAS_LED         1
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN   12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT  48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK  24000000
+
+#define LED_PORT       0
+#define LED_PIN_RED    7
+
+#define AO_LED_RED     (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE AO_LED_RED
+
+#define HAS_USB                0
+
+#define PACKET_HAS_SLAVE       0
+
+/* USART */
+
+#define HAS_SERIAL     1
+#define SERIAL_0_18_19         1
+#define SERIAL_1_14_15         0
+#define SERIAL_1_17_18         0
+#define SERIAL_1_26_27         0