From bcc65597d3d20f1d58df784100af766cee5f0f20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Apr 2013 15:54:13 -0500 Subject: lpc: Initial lpcxpresso bits This gets the LPC11U14 clock set to the PLL and blinks the LED. Signed-off-by: Keith Packard --- src/lpc/Makefile.defs | 42 +++ src/lpc/altos.ld | 72 +++++ src/lpc/ao_arch.h | 122 ++++++++ src/lpc/ao_arch_funcs.h | 147 ++++++++++ src/lpc/ao_interrupt.c | 155 +++++++++++ src/lpc/ao_led_lpc.c | 65 +++++ src/lpc/ao_romconfig.c | 25 ++ src/lpc/ao_serial_lpc.c | 154 +++++++++++ src/lpc/ao_timer_lpc.c | 165 +++++++++++ src/lpc/baud_rate | 131 +++++++++ src/lpc/figure-checksum | 39 +++ src/lpc/lpc.h | 723 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lpc/registers.ld | 9 + 13 files changed, 1849 insertions(+) create mode 100644 src/lpc/Makefile.defs create mode 100644 src/lpc/altos.ld create mode 100644 src/lpc/ao_arch.h create mode 100644 src/lpc/ao_arch_funcs.h create mode 100644 src/lpc/ao_interrupt.c create mode 100644 src/lpc/ao_led_lpc.c create mode 100644 src/lpc/ao_romconfig.c create mode 100644 src/lpc/ao_serial_lpc.c create mode 100644 src/lpc/ao_timer_lpc.c create mode 100644 src/lpc/baud_rate create mode 100755 src/lpc/figure-checksum create mode 100644 src/lpc/lpc.h create mode 100644 src/lpc/registers.ld (limited to 'src/lpc') diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs new file mode 100644 index 00000000..c18284d2 --- /dev/null +++ b/src/lpc/Makefile.defs @@ -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 index 00000000..7a99e66b --- /dev/null +++ b/src/lpc/altos.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 index 00000000..61182160 --- /dev/null +++ b/src/lpc/ao_arch.h @@ -0,0 +1,122 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +/* + * 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 index 00000000..39222b9d --- /dev/null +++ b/src/lpc/ao_arch_funcs.h @@ -0,0 +1,147 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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<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 index 00000000..b5e67007 --- /dev/null +++ b/src/lpc/ao_interrupt.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include + +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 index 00000000..098dad6b --- /dev/null +++ b/src/lpc/ao_led_lpc.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +__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 index 00000000..cbb922ec --- /dev/null +++ b/src/lpc/ao_romconfig.c @@ -0,0 +1,25 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 index 00000000..e47f743e --- /dev/null +++ b/src/lpc/ao_serial_lpc.c @@ -0,0 +1,154 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include + +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 index 00000000..aa796acf --- /dev/null +++ b/src/lpc/ao_timer_lpc.c @@ -0,0 +1,165 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +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 index 00000000..2bfbf309 --- /dev/null +++ b/src/lpc/baud_rate @@ -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 \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 index 00000000..0b1de578 --- /dev/null +++ b/src/lpc/figure-checksum @@ -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 index 00000000..87af494a --- /dev/null +++ b/src/lpc/lpc.h @@ -0,0 +1,723 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 + +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 index 00000000..cd6ac5f5 --- /dev/null +++ b/src/lpc/registers.ld @@ -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; -- cgit v1.2.3 From f9d0eb3f3154f98abb0c8952d7171f3e7d3de9b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Apr 2013 16:15:52 -0500 Subject: altos/lpc: Get 100Hz timer running Use systick, which is built into the ARM core Signed-off-by: Keith Packard --- src/lpc/ao_led_lpc.c | 5 +++-- src/lpc/ao_timer_lpc.c | 2 +- src/lpcxpresso/ao_demo.c | 26 ++++++++++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c index 098dad6b..7bef51ba 100644 --- a/src/lpc/ao_led_lpc.c +++ b/src/lpc/ao_led_lpc.c @@ -22,13 +22,13 @@ __pdata uint16_t ao_led_enable; void ao_led_on(uint16_t colors) { - lpc_gpio.pin[LED_PORT] = 0xffffffff; + lpc_gpio.pin[LED_PORT] |= colors; } void ao_led_off(uint16_t colors) { - lpc_gpio.pin[LED_PORT] = 0; + lpc_gpio.pin[LED_PORT] &= ~colors; } void @@ -44,6 +44,7 @@ ao_led_set(uint16_t colors) void ao_led_toggle(uint16_t colors) { + lpc_gpio.pin[LED_PORT] ^= colors; } void diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index aa796acf..51e82525 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -61,7 +61,7 @@ ao_timer_set_adc_interval(uint8_t interval) } #endif -#define SYSTICK_RELOAD ((AO_LPC_CLKOUT / 2) / 100 - 1) +#define SYSTICK_RELOAD ((AO_LPC_SYSCLK / 2) / 100 - 1) /* Initialize our 100Hz clock */ void diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c index bb8402f7..56fef706 100644 --- a/src/lpcxpresso/ao_demo.c +++ b/src/lpcxpresso/ao_demo.c @@ -17,6 +17,15 @@ #include "ao.h" +struct ao_task demo_task; + +static void demo(void) { + for (;;) { + ao_delay(100); + ao_led_toggle(AO_LED_RED); + } +} + int main(void) { @@ -24,13 +33,22 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_clock_init(); + ao_timer_init(); + + ao_task_init(); + + ao_add_task(&demo_task, demo, "demo"); + + ao_start_scheduler(); for (;;) { ao_led_off(AO_LED_RED); - for (i = 0; i < 100000; i++) - ao_arch_nop(); + for (;;) + if (ao_tick_count & 1) + break; ao_led_on(AO_LED_RED); - for (i = 0; i < 100000; i++) - ao_arch_nop(); + for (;;) + if (!(ao_tick_count & 1)) + break; } } -- cgit v1.2.3 From 9e8f6ba8b779cd9635f82d6da5f113715c3ee4c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Apr 2013 00:20:55 -0500 Subject: altos/lpc: Get USART running Adds a simple demo thread that spews data to the serial port Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 106 ++++++++++++++++++-------- src/lpc/lpc.h | 189 +++++++++++++++++++++++++++++++++++++++++++++++ src/lpc/registers.ld | 1 + src/lpcxpresso/ao_demo.c | 11 +++ src/lpcxpresso/ao_pins.h | 9 ++- 5 files changed, 283 insertions(+), 33 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index e47f743e..4ecaa175 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -27,10 +27,9 @@ 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 + while (!(lpc_usart.lsr & (1 << LPC_USART_LSR_TEMT))) + ; + lpc_usart.rbr_thr = c; } static void @@ -39,35 +38,28 @@ _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 + ao_fifo_remove(ao_usart_tx_fifo, lpc_usart.rbr_thr); } } void lpc_usart_isr(void) { -#if 0 - uint32_t sr; - - sr = usart->reg->sr; - usart->reg->sr = 0; + (void) lpc_usart.iir_fcr; - if (sr & (1 << STM_USART_SR_RXNE)) { - char c = usart->reg->dr; + while (lpc_usart.lsr & (1 << LPC_USART_LSR_RDR)) { + char c = lpc_usart.rbr_thr; if (!ao_fifo_full(ao_usart_rx_fifo)) ao_fifo_insert(ao_usart_rx_fifo, c); - ao_wakeup(ao_usart_rx_fifo); + ao_wakeup(&ao_usart_rx_fifo); if (stdin) ao_wakeup(&ao_stdin_ready); } - if (sr & (1 << STM_USART_SR_TC)) { + if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { ao_usart_tx_started = 0; - _ao_usart_tx_start(usart); - ao_wakeup(ao_usart_tx_fifo); + _ao_serial_tx_start(); + ao_wakeup(&ao_usart_tx_fifo); } -#endif } int @@ -116,24 +108,33 @@ ao_serial_drain(void) ao_arch_release_interrupts(); } +#include "ao_serial_lpc.h" + 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" + /* Flip to allow access to divisor latches */ + lpc_usart.lcr |= (1 << LPC_USART_LCR_DLAB); + + /* DL LSB */ + lpc_usart.rbr_thr = ao_usart_speeds[speed].dl & 0xff; + + /* DL MSB */ + lpc_usart.ier = (ao_usart_speeds[speed].dl >> 8) & 0xff; + + lpc_usart.fdr = ((ao_usart_speeds[speed].divaddval << LPC_USART_FDR_DIVADDVAL) | + (ao_usart_speeds[speed].mulval << LPC_USART_FDR_MULVAL)); + + /* Turn access to divisor latches back off */ + lpc_usart.lcr &= ~(1 << LPC_USART_LCR_DLAB); +} 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) | @@ -149,6 +150,53 @@ ao_serial_init(void) /* Turn on the USART */ lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_USART); -} - + /* Turn on the USART clock */ + lpc_scb.uartclkdiv = AO_LPC_CLKOUT / AO_LPC_USARTCLK; + + /* Configure USART */ + + /* Enable FIFOs, reset fifo contents, interrupt on 1 received char */ + lpc_usart.iir_fcr = ((1 << LPC_USART_FCR_FIFOEN) | + (1 << LPC_USART_FCR_RXFIFORES) | + (1 << LPC_USART_FCR_TXFIFORES) | + (LPC_USART_FCR_RXTL_1 << LPC_USART_FCR_RXTL)); + + /* 8 n 1 */ + lpc_usart.lcr = ((LPC_USART_LCR_WLS_8 << LPC_USART_LCR_WLS) | + (LPC_USART_LCR_SBS_1 << LPC_USART_LCR_SBS) | + (0 << LPC_USART_LCR_PE) | + (LPC_USART_LCR_PS_ODD << LPC_USART_LCR_PS) | + (0 << LPC_USART_LCR_BC) | + (0 << LPC_USART_LCR_DLAB)); + + /* Disable flow control */ + lpc_usart.mcr = ((0 << LPC_USART_MCR_DTRCTRL) | + (0 << LPC_USART_MCR_RTSCTRL) | + (0 << LPC_USART_MCR_LMS) | + (0 << LPC_USART_MCR_RTSEN) | + (0 << LPC_USART_MCR_CTSEN)); + + /* 16x oversampling */ + lpc_usart.osr = ((0 << LPC_USART_OSR_OSFRAC) | + ((16 - 1) << LPC_USART_OSR_OSINT) | + (0 << LPC_USART_OSR_FDINT)); + + /* Full duplex */ + lpc_usart.hden = ((0 << LPC_USART_HDEN_HDEN)); + + /* Set baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + /* Enable interrupts */ + lpc_usart.ier = ((1 << LPC_USART_IER_RBRINTEN) | + (1 << LPC_USART_IER_THREINTEN)); + + lpc_nvic_set_enable(LPC_ISR_USART_POS); + lpc_nvic_set_priority(LPC_ISR_USART_POS, 0); +#if USE_SERIAL_0_STDIN + ao_add_stdio(_ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +} diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 87af494a..81cd0cc8 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -720,4 +720,193 @@ struct lpc_usart { extern struct lpc_usart lpc_usart; +#define LPC_USART_IER_RBRINTEN 0 +#define LPC_USART_IER_THREINTEN 1 +#define LPC_USART_IER_RSLINTEN 2 +#define LPC_USART_IER_MSINTEN 3 +#define LPC_USART_IER_ABEOINTEN 8 +#define LPC_USART_IER_ABTOINTEN 9 + +#define LPC_USART_IIR_INTSTATUS 0 +#define LPC_USART_IIR_INTID 1 +#define LPC_USART_IIR_INTID_RLS 3 +#define LPC_USART_IIR_INTID_RDA 2 +#define LPC_USART_IIR_INTID_CTI 6 +#define LPC_USART_IIR_INTID_THRE 1 +#define LPC_USART_IIR_INTID_MS 0 +#define LPC_USART_IIR_INTID_MASK 7 +#define LPC_USART_IIR_FIFOEN 6 +#define LPC_USART_IIR_ABEOINT 8 +#define LPC_USART_IIR_ABTOINT 9 + +#define LPC_USART_FCR_FIFOEN 0 +#define LPC_USART_FCR_RXFIFORES 1 +#define LPC_USART_FCR_TXFIFORES 2 +#define LPC_USART_FCR_RXTL 6 +#define LPC_USART_FCR_RXTL_1 0 +#define LPC_USART_FCR_RXTL_4 1 +#define LPC_USART_FCR_RXTL_8 2 +#define LPC_USART_FCR_RXTL_14 3 + +#define LPC_USART_LCR_WLS 0 +#define LPC_USART_LCR_WLS_5 0 +#define LPC_USART_LCR_WLS_6 1 +#define LPC_USART_LCR_WLS_7 2 +#define LPC_USART_LCR_WLS_8 3 +#define LPC_USART_LCR_WLS_MASK 3 +#define LPC_USART_LCR_SBS 2 +#define LPC_USART_LCR_SBS_1 0 +#define LPC_USART_LCR_SBS_2 1 +#define LPC_USART_LCR_SBS_MASK 1 +#define LPC_USART_LCR_PE 3 +#define LPC_USART_LCR_PS 4 +#define LPC_USART_LCR_PS_ODD 0 +#define LPC_USART_LCR_PS_EVEN 1 +#define LPC_USART_LCR_PS_ONE 2 +#define LPC_USART_LCR_PS_ZERO 3 +#define LPC_USART_LCR_PS_MASK 3 +#define LPC_USART_LCR_BC 6 +#define LPC_USART_LCR_DLAB 7 + +#define LPC_USART_MCR_DTRCTRL 0 +#define LPC_USART_MCR_RTSCTRL 1 +#define LPC_USART_MCR_LMS 4 +#define LPC_USART_MCR_RTSEN 6 +#define LPC_USART_MCR_CTSEN 7 + +#define LPC_USART_LSR_RDR 0 +#define LPC_USART_LSR_OE 1 +#define LPC_USART_LSR_PE 2 +#define LPC_USART_LSR_FE 3 +#define LPC_USART_LSR_BI 4 +#define LPC_USART_LSR_THRE 5 +#define LPC_USART_LSR_TEMT 6 +#define LPC_USART_LSR_RXFE 7 +#define LPC_USART_LSR_TXERR 8 + +#define LPC_USART_MSR_DCTS 0 +#define LPC_USART_MSR_DDSR 1 +#define LPC_USART_MSR_TERI 2 +#define LPC_USART_MSR_DDCD 3 +#define LPC_USART_MSR_CTS 4 +#define LPC_USART_MSR_DSR 5 +#define LPC_USART_MSR_RI 6 +#define LPC_USART_MSR_DCD 7 + +#define LPC_USART_ACR_START 0 +#define LPC_USART_ACR_MODE 1 +#define LPC_USART_ACR_AUTORESTART 2 +#define LPC_USART_ACR_ABEOINTCLR 8 +#define LPC_USART_ACR_ABTOINTCLR 9 + +#define LPC_USART_FDR_DIVADDVAL 0 +#define LPC_USART_FDR_MULVAL 4 + +#define LPC_USART_OSR_OSFRAC 1 +#define LPC_USART_OSR_OSINT 4 +#define LPC_USART_OSR_FDINT 8 + +#define LPC_USART_TER_TXEN 7 + +#define LPC_USART_HDEN_HDEN 0 + +#define LPC_ISR_PIN_INT0_POS 0 +#define LPC_ISR_PIN_INT1_POS 1 +#define LPC_ISR_PIN_INT2_POS 2 +#define LPC_ISR_PIN_INT3_POS 3 +#define LPC_ISR_PIN_INT4_POS 4 +#define LPC_ISR_PIN_INT5_POS 5 +#define LPC_ISR_PIN_INT6_POS 6 +#define LPC_ISR_PIN_INT7_POS 7 +#define LPC_ISR_GINT0_POS 8 +#define LPC_ISR_GINT1_POS 9 +#define LPC_ISR_SSP1_POS 14 +#define LPC_ISR_I2C_POS 15 +#define LPC_ISR_CT16B0_POS 16 +#define LPC_ISR_CT16B1_POS 17 +#define LPC_ISR_CT32B0_POS 18 +#define LPC_ISR_CT32B1_POS 19 +#define LPC_ISR_SSP0_POS 20 +#define LPC_ISR_USART_POS 21 +#define LPC_ISR_USB_IRQ_POS 22 +#define LPC_ISR_USB_FIQ_POS 23 +#define LPC_ISR_ADC_POS 24 +#define LPC_ISR_WWDT_POS 25 +#define LPC_ISR_BOD_POS 26 +#define LPC_ISR_FLASH_POS 27 +#define LPC_ISR_USB_WAKEUP_POS 30 + +struct lpc_nvic { + vuint32_t iser; /* 0x000 0xe000e100 Set Enable Register */ + + uint8_t _unused020[0x080 - 0x004]; + + vuint32_t icer; /* 0x080 0xe000e180 Clear Enable Register */ + + uint8_t _unused0a0[0x100 - 0x084]; + + vuint32_t ispr; /* 0x100 0xe000e200 Set Pending Register */ + + uint8_t _unused120[0x180 - 0x104]; + + vuint32_t icpr; /* 0x180 0xe000e280 Clear Pending Register */ + + uint8_t _unused1a0[0x300 - 0x184]; + + vuint32_t ipr[8]; /* 0x300 0xe000e400 Priority Register */ +}; + +extern struct lpc_nvic lpc_nvic; + +static inline void +lpc_nvic_set_enable(int irq) { + lpc_nvic.iser |= (1 << irq); +} + +static inline void +lpc_nvic_clear_enable(int irq) { + lpc_nvic.icer |= (1 << irq); +} + +static inline int +lpc_nvic_enabled(int irq) { + return (lpc_nvic.iser >> irq) & 1; +} + + +static inline void +lpc_nvic_set_pending(int irq) { + lpc_nvic.ispr = (1 << irq); +} + +static inline void +lpc_nvic_clear_pending(int irq) { + lpc_nvic.icpr = (1 << irq); +} + +static inline int +lpc_nvic_pending(int irq) { + return (lpc_nvic.ispr >> irq) & 1; +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +lpc_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = lpc_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + lpc_nvic.ipr[n] = v; +} + +static inline uint8_t +lpc_nvic_get_priority(int irq) { + return (lpc_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + #endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index cd6ac5f5..e444d832 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -7,3 +7,4 @@ lpc_gpio_group0 = 0x4005c000; lpc_gpio_group1 = 0x40060000; lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; +lpc_nvic = 0xe000e100; diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c index 56fef706..eae9503e 100644 --- a/src/lpcxpresso/ao_demo.c +++ b/src/lpcxpresso/ao_demo.c @@ -26,6 +26,14 @@ static void demo(void) { } } +static struct ao_task serial_task; + +static void serial(void) { + for (;;) { + printf ("hello, world\n"); + } +} + int main(void) { @@ -35,9 +43,12 @@ main(void) ao_clock_init(); ao_timer_init(); + ao_serial_init(); + ao_task_init(); ao_add_task(&demo_task, demo, "demo"); + ao_add_task(&serial_task, serial, "serial"); ao_start_scheduler(); diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h index 56391c2b..7748f73c 100644 --- a/src/lpcxpresso/ao_pins.h +++ b/src/lpcxpresso/ao_pins.h @@ -40,8 +40,9 @@ /* USART */ -#define HAS_SERIAL 1 +#define HAS_SERIAL 1 +#define USE_SERIAL_0_STDIN 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 +#define SERIAL_0_14_15 0 +#define SERIAL_0_17_18 0 +#define SERIAL_0_26_27 0 -- cgit v1.2.3 From 9bf67798b134ad796c2f4bc9240ee450722148ec Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Apr 2013 00:40:38 -0500 Subject: altos/lpc: Take advantage of USART TX fifo The USART has a 16-byte TX fifo; keep rough track of how full it is to avoid waiting for an interrupt after every TX byte. Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index 4ecaa175..c0424699 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -20,7 +20,10 @@ struct ao_fifo ao_usart_rx_fifo; struct ao_fifo ao_usart_tx_fifo; -uint8_t ao_usart_tx_started; +uint8_t ao_usart_tx_avail; +uint8_t ao_usart_tx_avail_min; + +#define LPC_USART_TX_FIFO_SIZE 16 void ao_debug_out(char c) @@ -35,9 +38,10 @@ ao_debug_out(char c) 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 (!ao_fifo_empty(ao_usart_tx_fifo) && ao_usart_tx_avail) { + ao_usart_tx_avail--; + if (ao_usart_tx_avail < ao_usart_tx_avail_min) + ao_usart_tx_avail_min = ao_usart_tx_avail; ao_fifo_remove(ao_usart_tx_fifo, lpc_usart.rbr_thr); } } @@ -56,7 +60,7 @@ lpc_usart_isr(void) ao_wakeup(&ao_stdin_ready); } if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { - ao_usart_tx_started = 0; + ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; _ao_serial_tx_start(); ao_wakeup(&ao_usart_tx_fifo); } @@ -162,6 +166,9 @@ ao_serial_init(void) (1 << LPC_USART_FCR_TXFIFORES) | (LPC_USART_FCR_RXTL_1 << LPC_USART_FCR_RXTL)); + ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; + ao_usart_tx_avail_min = LPC_USART_TX_FIFO_SIZE; + /* 8 n 1 */ lpc_usart.lcr = ((LPC_USART_LCR_WLS_8 << LPC_USART_LCR_WLS) | (LPC_USART_LCR_SBS_1 << LPC_USART_LCR_SBS) | -- cgit v1.2.3 From 91d201abcbe9373360919406427b7e4fb9e1b42e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 17:10:24 -0500 Subject: altos/lpc: Start adding USB register definitions Just the bare struct, no defines yet. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 1136 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lpc/lpc.h | 18 + src/lpc/registers.ld | 1 + 3 files changed, 1155 insertions(+) create mode 100644 src/lpc/ao_usb_lpc.c (limited to 'src/lpc') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c new file mode 100644 index 00000000..af2bd271 --- /dev/null +++ b/src/lpc/ao_usb_lpc.c @@ -0,0 +1,1136 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_usb.h" +#include "ao_product.h" + +#define USB_DEBUG 1 +#define USB_DEBUG_DATA 1 +#define USB_ECHO 1 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args); +#else +#define debug(format, args...) +#endif + +#if USB_DEBUG_DATA +#define debug_data(format, args...) printf(format, ## args); +#else +#define debug_data(format, args...) +#endif + +struct ao_task ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} ao_usb_setup; + +static uint8_t ao_usb_ep0_state; + +/* Pending EP0 IN data */ +static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ +static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ + +/* Temp buffer for smaller EP0 in data */ +static uint8_t ao_usb_ep0_in_buf[2]; + +/* Pending EP0 OUT data */ +static uint8_t *ao_usb_ep0_out_data; +static uint8_t ao_usb_ep0_out_len; + +/* + * Objects allocated in special USB memory + */ + +/* Buffer description tables */ +static union lpc_usb_bdt *ao_usb_bdt; +/* USB address of end of allocated storage */ +static uint16_t ao_usb_sram_addr; + +/* Pointer to ep0 tx/rx buffers in USB memory */ +static uint32_t *ao_usb_ep0_tx_buffer; +static uint32_t *ao_usb_ep0_rx_buffer; + +/* Pointer to bulk data tx/rx buffers in USB memory */ +static uint32_t *ao_usb_in_tx_buffer; +static uint32_t *ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ +static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t ao_usb_tx_count; + +static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t ao_usb_rx_count, ao_usb_rx_pos; + +/* + * End point register indices + */ + +#define AO_USB_CONTROL_EPR 0 +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 + +/* Marks when we don't need to send an IN packet. + * This happens only when the last IN packet is not full, + * otherwise the host will expect to keep seeing packets. + * Send a zero-length packet as required + */ +static uint8_t ao_usb_in_flushed; + +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t ao_usb_in_pending; + +/* Marks when an OUT packet has been received by the hardware + * but not pulled to the shadow buffer. + */ +static uint8_t ao_usb_out_avail; +static uint8_t ao_usb_running; +static uint8_t ao_usb_configuration; +static uint8_t ueienx_0; + +#define AO_USB_EP0_GOT_RESET 1 +#define AO_USB_EP0_GOT_SETUP 2 +#define AO_USB_EP0_GOT_RX_DATA 4 +#define AO_USB_EP0_GOT_TX_ACK 8 + +static uint8_t ao_usb_ep0_receive; +static uint8_t ao_usb_address; +static uint8_t ao_usb_address_pending; + +static inline uint32_t set_toggle(uint32_t current_value, + uint32_t mask, + uint32_t desired_value) +{ + return (current_value ^ desired_value) & mask; +} + +static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) +{ + return (uint32_t *) (lpc_usb_sram + 2 * sram_addr); +} + +static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { + return (epr >> USB_USB_EPR_STAT_RX) & USB_USB_EPR_STAT_RX_MASK; +} + +static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { + return (epr >> USB_USB_EPR_STAT_TX) & USB_USB_EPR_STAT_TX_MASK; +} + +static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { + return (epr >> USB_USB_EPR_CTR_RX) & 1; +} + +static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { + return (epr >> USB_USB_EPR_CTR_TX) & 1; +} + +static inline uint32_t ao_usb_epr_setup(uint32_t epr) { + return (epr >> USB_USB_EPR_SETUP) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { + return (epr >> USB_USB_EPR_DTOG_RX) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { + return (epr >> USB_USB_EPR_DTOG_TX) & 1; +} + +/* + * Set current device address and mark the + * interface as active + */ +void +ao_usb_set_address(uint8_t address) +{ + debug("ao_usb_set_address %02x\n", address); + lpc_usb.daddr = (1 << USB_USB_DADDR_EF) | address; + ao_usb_address_pending = 0; +} + +/* + * Write these values to preserve register contents under HW changes + */ + +#define USB_USB_EPR_INVARIANT ((1 << USB_USB_EPR_CTR_RX) | \ + (USB_USB_EPR_DTOG_RX_WRITE_INVARIANT << USB_USB_EPR_DTOG_RX) | \ + (USB_USB_EPR_STAT_RX_WRITE_INVARIANT << USB_USB_EPR_STAT_RX) | \ + (1 << USB_USB_EPR_CTR_TX) | \ + (USB_USB_EPR_DTOG_TX_WRITE_INVARIANT << USB_USB_EPR_DTOG_TX) | \ + (USB_USB_EPR_STAT_TX_WRITE_INVARIANT << USB_USB_EPR_STAT_TX)) + +#define USB_USB_EPR_INVARIANT_MASK ((1 << USB_USB_EPR_CTR_RX) | \ + (USB_USB_EPR_DTOG_RX_MASK << USB_USB_EPR_DTOG_RX) | \ + (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX) | \ + (1 << USB_USB_EPR_CTR_TX) | \ + (USB_USB_EPR_DTOG_TX_MASK << USB_USB_EPR_DTOG_TX) | \ + (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define USB_USB_EPR_PRESERVE_MASK ((USB_USB_EPR_EP_TYPE_MASK << USB_USB_EPR_EP_TYPE) | \ + (1 << USB_USB_EPR_EP_KIND) | \ + (USB_USB_EPR_EA_MASK << USB_USB_EPR_EA)) + +#define TX_DBG 0 +#define RX_DBG 0 + +#if TX_DBG +#define _tx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _tx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _tx_dbg0(msg) +#define _tx_dbg1(msg,value) +#endif + +#if RX_DBG +#define _rx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _rx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _rx_dbg0(msg) +#define _rx_dbg1(msg,value) +#endif + +#if TX_DBG || RX_DBG +static void _dbg(int line, char *msg, uint32_t value); +#endif + +/* + * Set the state of the specified endpoint register to a new + * value. This is tricky because the bits toggle where the new + * value is one, and we need to write invariant values in other + * spots of the register. This hardware is strange... + */ +static void +_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + uint32_t epr_write, epr_old; + + _tx_dbg1("set_stat_tx top", stat_tx); + epr_old = epr_write = lpc_usb.epr[ep]; + epr_write &= USB_USB_EPR_PRESERVE_MASK; + epr_write |= USB_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX, + stat_tx << USB_USB_EPR_STAT_TX); + lpc_usb.epr[ep] = epr_write; + _tx_dbg1("set_stat_tx bottom", epr_write); +} + +static void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + ao_arch_block_interrupts(); + _ao_usb_set_stat_tx(ep, stat_tx); + ao_arch_release_interrupts(); +} + +static void +_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint32_t epr_write, epr_old; + + epr_write = epr_old = lpc_usb.epr[ep]; + epr_write &= USB_USB_EPR_PRESERVE_MASK; + epr_write |= USB_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX, + stat_rx << USB_USB_EPR_STAT_RX); + lpc_usb.epr[ep] = epr_write; +} + +static void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + ao_arch_block_interrupts(); + _ao_usb_set_stat_rx(ep, stat_rx); + ao_arch_release_interrupts(); +} + +/* + * Set just endpoint 0, for use during startup + */ + +static void +ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +{ + uint32_t epr; + ao_arch_block_interrupts(); + epr = lpc_usb.epr[ep]; + epr = ((0 << USB_USB_EPR_CTR_RX) | + (epr & (1 << USB_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX), + (stat_rx << USB_USB_EPR_STAT_RX)) | + (type << USB_USB_EPR_EP_TYPE) | + (0 << USB_USB_EPR_EP_KIND) | + (0 << USB_USB_EPR_CTR_TX) | + (epr & (1 << USB_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX), + (stat_tx << USB_USB_EPR_STAT_TX)) | + (addr << USB_USB_EPR_EA)); + lpc_usb.epr[ep] = epr; + ao_arch_release_interrupts(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + ep, epr, lpc_usb.epr[ep]); +} + +static void +ao_usb_set_ep0(void) +{ + uint32_t epr; + int e; + + ao_usb_sram_addr = 0; + + /* buffer table is at the start of USB memory */ + lpc_usb.btable = 0; + ao_usb_bdt = (void *) lpc_usb_sram; + + ao_usb_sram_addr += 8 * USB_USB_BDT_SIZE; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_tx = 0; + ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_CONTROL_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, + USB_USB_EPR_EP_TYPE_CONTROL, + USB_USB_EPR_STAT_RX_VALID, + USB_USB_EPR_STAT_TX_NAK); + + /* Clear all of the other endpoints */ + for (e = 1; e < 8; e++) { + ao_usb_init_ep(e, 0, + USB_USB_EPR_EP_TYPE_CONTROL, + USB_USB_EPR_STAT_RX_DISABLED, + USB_USB_EPR_STAT_TX_DISABLED); + } + + ao_usb_set_address(0); +} + +static void +ao_usb_set_configuration(void) +{ + uint32_t epr; + + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_INT_SIZE; + + ao_usb_init_ep(AO_USB_INT_EPR, + AO_USB_INT_EP, + USB_USB_EPR_EP_TYPE_INTERRUPT, + USB_USB_EPR_STAT_RX_DISABLED, + USB_USB_EPR_STAT_TX_NAK); + + /* Set up the OUT end point */ + ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_OUT_SIZE; + + ao_usb_init_ep(AO_USB_OUT_EPR, + AO_USB_OUT_EP, + USB_USB_EPR_EP_TYPE_BULK, + USB_USB_EPR_STAT_RX_VALID, + USB_USB_EPR_STAT_TX_DISABLED); + + /* Set up the IN end point */ + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + + ao_usb_init_ep(AO_USB_IN_EPR, + AO_USB_IN_EP, + USB_USB_EPR_EP_TYPE_BULK, + USB_USB_EPR_STAT_RX_DISABLED, + USB_USB_EPR_STAT_TX_NAK); + + ao_usb_running = 1; +} + +static uint16_t control_count; +static uint16_t int_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +void +lpc_usb_lp_isr(void) +{ + uint32_t istr = lpc_usb.istr; + + if (istr & (1 << USB_USB_ISTR_CTR)) { + uint8_t ep = istr & USB_USB_ISTR_EP_ID_MASK; + uint32_t epr, epr_write; + + /* Preserve the SW write bits, don't mess with most HW writable bits, + * clear the CTR_RX and CTR_TX bits + */ + epr = lpc_usb.epr[ep]; + epr_write = epr; + epr_write &= USB_USB_EPR_PRESERVE_MASK; + epr_write |= USB_USB_EPR_INVARIANT; + epr_write &= ~(1 << USB_USB_EPR_CTR_RX); + epr_write &= ~(1 << USB_USB_EPR_CTR_TX); + lpc_usb.epr[ep] = epr_write; + + switch (ep) { + case 0: + ++control_count; + if (ao_usb_epr_ctr_rx(epr)) { + if (ao_usb_epr_setup(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + } + if (ao_usb_epr_ctr_tx(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + ao_wakeup(&ao_usb_ep0_receive); + break; + case AO_USB_OUT_EPR: + ++out_count; + if (ao_usb_epr_ctr_rx(epr)) { + _rx_dbg1("RX ISR", epr); + ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); + ao_wakeup(&ao_stdin_ready); + _rx_dbg0("stdin awoken"); + } + break; + case AO_USB_IN_EPR: + ++in_count; + _tx_dbg1("TX ISR", epr); + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + break; + case AO_USB_INT_EPR: + ++int_count; + if (ao_usb_epr_ctr_tx(epr)) + _ao_usb_set_stat_tx(AO_USB_INT_EPR, USB_USB_EPR_STAT_TX_NAK); + break; + } + return; + } + + if (istr & (1 << USB_USB_ISTR_RESET)) { + ++reset_count; + lpc_usb.istr &= ~(1 << USB_USB_ISTR_RESET); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_wakeup(&ao_usb_ep0_receive); + } +} + +void +lpc_usb_fs_wkup(void) +{ + /* USB wakeup, just clear the bit for now */ + lpc_usb.istr &= ~(1 << USB_USB_ISTR_WKUP); +} + +/* The USB memory holds 16 bit values on 32 bit boundaries + * and must be accessed only in 32 bit units. Sigh. + */ + +static inline void +ao_usb_write_byte(uint8_t byte, uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) { + *base = (*base & 0xff) | ((uint32_t) byte << 8); + } else { + *base = (*base & 0xff00) | byte; + } +} + +static inline void +ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) +{ + base[offset>>1] = data; +} + +static void +ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src++, base, offset++); + bytes--; + } + while (bytes >= 2) { + debug_data (" %02x %02x", src[0], src[1]); + ao_usb_write_short((src[1] << 8) | src[0], base, offset); + offset += 2; + src += 2; + bytes -= 2; + } + if (bytes) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src, base, offset); + } +} + +static inline uint8_t +ao_usb_read_byte(uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) + return (*base >> 8) & 0xff; + else + return *base & 0xff; +} + +static inline uint16_t +ao_usb_read_short(uint32_t *base, uint16_t offset) +{ + return base[offset>>1]; +} + +static void +ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + *dst++ = ao_usb_read_byte(base, offset++); + debug_data (" %02x", dst[-1]); + bytes--; + } + while (bytes >= 2) { + uint16_t s = ao_usb_read_short(base, offset); + dst[0] = s; + dst[1] = s >> 8; + debug_data (" %02x %02x", dst[0], dst[1]); + offset += 2; + dst += 2; + bytes -= 2; + } + if (bytes) { + *dst = ao_usb_read_byte(base, offset); + debug_data (" %02x", dst[0]); + } +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + uint8_t this_len; + + /* Check to see if the endpoint is still busy */ + if (ao_usb_epr_stat_tx(lpc_usb.epr[0]) == USB_USB_EPR_STAT_TX_VALID) { + debug("EP0 not accepting IN data\n"); + return; + } + + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + if (this_len < AO_USB_CONTROL_SIZE) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + + ao_usb_ep0_in_len -= this_len; + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; + ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, USB_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", lpc_usb.epr[AO_USB_CONTROL_EPR]); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(void) +{ + uint16_t len = ao_usb_bdt[0].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + + /* Pull all of the data out of the packet */ + debug_data ("Fill EP0 len %d:", len); + ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, 0, len); + debug_data ("\n"); + ao_usb_ep0_out_data += len; + + /* ACK the packet */ + ao_usb_set_stat_rx(0, USB_USB_EPR_STAT_RX_VALID); +} + +static void +ao_usb_ep0_in_reset(void) +{ + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; +} + +static void +ao_usb_ep0_in_queue_byte(uint8_t a) +{ + if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf)) + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_in_set(const uint8_t *data, uint8_t len) +{ + ao_usb_ep0_in_data = data; + ao_usb_ep0_in_len = len; +} + +static void +ao_usb_ep0_out_set(uint8_t *data, uint8_t len) +{ + ao_usb_ep0_out_data = data; + ao_usb_ep0_out_len = len; +} + +static void +ao_usb_ep0_in_start(uint8_t max) +{ + /* Don't send more than asked for */ + if (ao_usb_ep0_in_len > max) + ao_usb_ep0_in_len = max; + ao_usb_ep0_flush(); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + uint8_t len; + if (type == AO_USB_DESC_CONFIGURATION) + len = descriptor[2]; + else + len = descriptor[0]; + ao_usb_ep0_in_set(descriptor, len); + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8); + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + + ao_usb_ep0_in_reset(); + + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_address = ao_usb_setup.value; + ao_usb_address_pending = 1; + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_in_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case AO_USB_SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7); + break; + case AO_USB_GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7); + break; + case AO_USB_SET_CONTROL_LINE_STATE: + break; + } + break; + } + + /* If we're not waiting to receive data from the host, + * queue an IN response + */ + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_in_start(ao_usb_setup.length); +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + uint8_t receive; + ao_arch_critical( + while (!(receive = ao_usb_ep0_receive)) + ao_sleep(&ao_usb_ep0_receive); + ao_usb_ep0_receive = 0; + ); + + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + continue; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); + } + } + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) + ao_usb_set_address(ao_usb_address); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); + } + } +} + +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in_send(void) +{ + _tx_dbg0("in_send start"); + debug ("send %d\n", ao_usb_tx_count); + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + ao_usb_in_pending = 1; + if (ao_usb_tx_count != AO_USB_IN_SIZE) + ao_usb_in_flushed = 1; + ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + ao_usb_tx_count = 0; + _ao_usb_set_stat_tx(AO_USB_IN_EPR, USB_USB_EPR_STAT_TX_VALID); + _tx_dbg0("in_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx_count < AO_USB_IN_SIZE) + break; + + _tx_dbg0("in_wait top"); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + _tx_dbg0("in_wait bottom"); + } +} + +void +ao_usb_flush(void) +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + ao_arch_block_interrupts(); + while (!ao_usb_in_flushed) { + _tx_dbg0("flush top"); + _ao_usb_in_send(); + _tx_dbg0("flush end"); + } + ao_arch_release_interrupts(); +} + +void +ao_usb_putchar(char c) +{ + if (!ao_usb_running) + return; + + ao_arch_block_interrupts(); + _ao_usb_in_wait(); + + ao_usb_in_flushed = 0; + ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + + /* Send the packet when full */ + if (ao_usb_tx_count == AO_USB_IN_SIZE) { + _tx_dbg0("putchar full"); + _ao_usb_in_send(); + _tx_dbg0("putchar flushed"); + } + ao_arch_release_interrupts(); +} + +static void +_ao_usb_out_recv(void) +{ + _rx_dbg0("out_recv top"); + ao_usb_out_avail = 0; + + ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + _rx_dbg1("out_recv count", ao_usb_rx_count); + debug ("recv %d\n", ao_usb_rx_count); + debug_data("Fill OUT len %d:", ao_usb_rx_count); + ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); + debug_data("\n"); + ao_usb_rx_pos = 0; + + /* ACK the packet */ + _ao_usb_set_stat_rx(AO_USB_OUT_EPR, USB_USB_EPR_STAT_RX_VALID); +} + +int +_ao_usb_pollchar(void) +{ + uint8_t c; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + if (ao_usb_rx_pos != ao_usb_rx_count) + break; + + _rx_dbg0("poll check"); + /* Check to see if a packet has arrived */ + if (!ao_usb_out_avail) { + _rx_dbg0("poll none"); + return AO_READ_AGAIN; + } + _ao_usb_out_recv(); + } + + /* Pull a character out of the fifo */ + c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + return c; +} + +char +ao_usb_getchar(void) +{ + int c; + + ao_arch_block_interrupts(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + ao_arch_release_interrupts(); + return c; +} + +void +ao_usb_disable(void) +{ + ao_arch_block_interrupts(); + lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); + lpc_usb.istr = 0; + + /* Disable USB pull-up */ + lpc_syscfg.pmc &= ~(1 << USB_SYSCFG_PMC_USB_PU); + + /* Switch off the device */ + lpc_usb.cntr = (1 << USB_USB_CNTR_PDWN) | (1 << USB_USB_CNTR_FRES); + + /* Disable the interface */ + lpc_rcc.apb1enr &+ ~(1 << USB_RCC_APB1ENR_USBEN); + ao_arch_release_interrupts(); +} + +void +ao_usb_enable(void) +{ + int t; + + /* Enable USB registers and RAM */ + lpc_scb.sysahbclkctrl |= ((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | + (1 << LPC_SCB_SYSAHBCLKCTRL_USBRAM)); + + /* Enable USB PHY */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + + /* Turn on USB clock, use 48MHz clock unchanged */ + lpc_scb.usbclkdiv = 1; + + /* Configure interrupts */ + ao_arch_block_interrupts(); + + /* Enable interrupts */ + lpc_usb. + /* Route interrupts */ + + lpc_nvic_set_priority(USB_ISR_USB_LP_POS, 3); + lpc_nvic_set_enable(USB_ISR_USB_LP_POS); + + ao_usb_configuration = 0; + + lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); + + /* Clear the power down bit */ + lpc_usb.cntr = 0; + + /* Clear any spurious interrupts */ + lpc_usb.istr = 0; + + debug ("ao_usb_enable\n"); + + /* Enable interrupts */ + lpc_usb.cntr = ((1 << USB_USB_CNTR_CTRM) | + (0 << USB_USB_CNTR_PMAOVRM) | + (0 << USB_USB_CNTR_ERRM) | + (0 << USB_USB_CNTR_WKUPM) | + (0 << USB_USB_CNTR_SUSPM) | + (1 << USB_USB_CNTR_RESETM) | + (0 << USB_USB_CNTR_SOFM) | + (0 << USB_USB_CNTR_ESOFM) | + (0 << USB_USB_CNTR_RESUME) | + (0 << USB_USB_CNTR_FSUSP) | + (0 << USB_USB_CNTR_LP_MODE) | + (0 << USB_USB_CNTR_PDWN) | + (0 << USB_USB_CNTR_FRES)); + + ao_arch_release_interrupts(); + + for (t = 0; t < 1000; t++) + ao_arch_nop(); + /* Enable USB pull-up */ + lpc_syscfg.pmc |= (1 << USB_SYSCFG_PMC_USB_PU); +} + +#if USB_ECHO +struct ao_task ao_usb_echo_task; + +static void +ao_usb_echo(void) +{ + char c; + + for (;;) { + c = ao_usb_getchar(); + ao_usb_putchar(c); + ao_usb_flush(); + } +} +#endif + +#if USB_DEBUG +static void +ao_usb_irq(void) +{ + printf ("control: %d out: %d in: %d int: %d reset: %d\n", + control_count, out_count, in_count, int_count, reset_count); +} + +__code struct ao_cmds ao_usb_cmds[] = { + { ao_usb_irq, "I\0Show USB interrupt counts" }, + { 0, NULL } +}; +#endif + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + debug ("ao_usb_init\n"); + ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); +#if USB_ECHO + ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); +#endif +#if USB_DEBUG + ao_cmd_register(&ao_usb_cmds[0]); +#endif +#if !USB_ECHO + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +#endif +} + +#if TX_DBG || RX_DBG + +struct ao_usb_dbg { + int line; + char *msg; + uint32_t value; + uint32_t primask; +#if TX_DBG + uint16_t in_count; + uint32_t in_epr; + uint32_t in_pending; + uint32_t tx_count; + uint32_t in_flushed; +#endif +#if RX_DBG + uint8_t rx_count; + uint8_t rx_pos; + uint8_t out_avail; + uint32_t out_epr; +#endif +}; + +#define NUM_USB_DBG 128 + +static struct ao_usb_dbg dbg[128]; +static int dbg_i; + +static void _dbg(int line, char *msg, uint32_t value) +{ + uint32_t primask; + dbg[dbg_i].line = line; + dbg[dbg_i].msg = msg; + dbg[dbg_i].value = value; + asm("mrs %0,primask" : "=&r" (primask)); + dbg[dbg_i].primask = primask; +#if TX_DBG + dbg[dbg_i].in_count = in_count; + dbg[dbg_i].in_epr = lpc_usb.epr[AO_USB_IN_EPR]; + dbg[dbg_i].in_pending = ao_usb_in_pending; + dbg[dbg_i].tx_count = ao_usb_tx_count; + dbg[dbg_i].in_flushed = ao_usb_in_flushed; +#endif +#if RX_DBG + dbg[dbg_i].rx_count = ao_usb_rx_count; + dbg[dbg_i].rx_pos = ao_usb_rx_pos; + dbg[dbg_i].out_avail = ao_usb_out_avail; + dbg[dbg_i].out_epr = lpc_usb.epr[AO_USB_OUT_EPR]; +#endif + if (++dbg_i == NUM_USB_DBG) + dbg_i = 0; +} +#endif diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 81cd0cc8..5a1987f5 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -810,6 +810,24 @@ extern struct lpc_usart lpc_usart; #define LPC_USART_HDEN_HDEN 0 +struct lpc_usb { + vuint32_t devcmdstat; + vuint32_t info; + vuint32_t epliststart; + vuint32_t databufstart; + vuint32_t lpm; + vuint32_t epskip; + vuint32_t epinuse; + vuint32_t epbufcfg; + vuint32_t intstat; + vuint32_t inten; + vuint32_t intsetstat; + vuint32_t introuting; + vuint32_t eptoggle; +} lpc_usb; + +extern struct lpc_usb lpc_usb; + #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 #define LPC_ISR_PIN_INT2_POS 2 diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index e444d832..51a0612f 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -5,6 +5,7 @@ lpc_scb = 0x40048000; lpc_gpio_pin = 0x4004c000; lpc_gpio_group0 = 0x4005c000; lpc_gpio_group1 = 0x40060000; +lpc_usb = 0x40080000; lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; lpc_nvic = 0xe000e100; -- cgit v1.2.3 From 918342016705303baa1630c62c290aaf2dcc2801 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Apr 2013 20:38:32 -0700 Subject: altos/lpc: Start adding USB register defines Signed-off-by: Keith Packard --- src/lpc/lpc.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src/lpc') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 5a1987f5..da9ac534 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -828,6 +828,67 @@ struct lpc_usb { extern struct lpc_usb lpc_usb; +#define LPC_USB_DEVCMDSTAT_DEV_ADDR 0 +#define LPC_USB_DEVCMDSTAT_DEV_ADDR_MASK 0x7f +#define LPC_USB_DEVCMDSTAT_DEV_EN 7 +#define LPC_USB_DEVCMDSTAT_SETUP 8 +#define LPC_USB_DEVCMDSTAT_PLL_ON 9 +#define LPC_USB_DEVCMDSTAT_LPM_SUP 11 +#define LPC_USB_DEVCMDSTAT_INTONNAK_AO 12 +#define LPC_USB_DEVCMDSTAT_INTONNAK_AI 13 +#define LPC_USB_DEVCMDSTAT_INTONNAK_CO 14 +#define LPC_USB_DEVCMDSTAT_INTONNAK_CI 15 +#define LPC_USB_DEVCMDSTAT_DCON 16 +#define LPC_USB_DEVCMDSTAT_DSUS 17 +#define LPC_USB_DEVCMDSTAT_LPM_SUS 19 +#define LPC_USB_DEVCMDSTAT_LPM_REWP 20 +#define LPC_USB_DEVCMDSTAT_DCON_C 24 +#define LPC_USB_DEVCMDSTAT_DSUS_C 25 +#define LPC_USB_DEVCMDSTAT_DRES_C 26 +#define LPC_USB_DEVCMDSTAT_VBUSDEBOUNCED 28 + +#define LPC_USB_INFO_FRAME_NR 0 +#define LPC_USB_INFO_FRAME_NR_MASK 0x3ff +#define LPC_USB_INFO_ERR_CODE 11 +#define LPC_USB_INFO_ERR_CODE_NO_ERROR 0 +#define LPC_USB_INFO_ERR_CODE_PID_ENCODING_ERROR 1 +#define LPC_USB_INFO_ERR_CODE_PID_UNKNOWN 2 +#define LPC_USB_INFO_ERR_CODE_PACKET_UNEXPECTED 3 +#define LPC_USB_INFO_ERR_CODE_TOKEN_CRC_ERROR 4 +#define LPC_USB_INFO_ERR_CODE_DATA_CRC_ERROR 5 +#define LPC_USB_INFO_ERR_CODE_TIME_OUT 6 +#define LPC_USB_INFO_ERR_CODE_BABBLE 7 +#define LPC_USB_INFO_ERR_CODE_TRUNCATED_EOP 8 +#define LPC_USB_INFO_ERR_CODE_SENT_RECEIVED_NAK 9 +#define LPC_USB_INFO_ERR_CODE_SENT_STALL 0xa +#define LPC_USB_INFO_ERR_CODE_OVERRUN 0xb +#define LPC_USB_INFO_ERR_CODE_SENT_EMPTY_PACKET 0xc +#define LPC_USB_INFO_ERR_CODE_BITSTUFF_ERROR 0xd +#define LPC_USB_INFO_ERR_CODE_SYNC_ERROR 0xe +#define LPC_USB_INFO_ERR_CODE_WRONG_DATA_TOGGLE 0xf +#define LPC_USB_INFO_ERR_CODE_MASK 0xf + +#define LPC_USB_EPLISTSTART_EP_LIST 0 + +#define LPC_USB_DATABUFSTART_DA_BUF 0 + +#define LPC_USB_LPM_HIRD_HW 0 +#define LPC_USB_LPM_HIRD_HW_MASK 0xf +#define LPC_USB_LPM_HIRD_SW 4 +#define LPC_USB_LPM_HIRD_SW_MASK 0xf +#define LPC_USB_LPM_DATA_PENDING 8 + +#define LPC_USB_EPSKIP_SKIP 0 + +#define LPC_USB_EPINUSE(ep) ((ep) + 2) + +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ + #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 #define LPC_ISR_PIN_INT2_POS 2 -- cgit v1.2.3 From 6c35e21a86ab32bc91eb10a60c071b702fc0f963 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 May 2013 19:27:17 -0700 Subject: altos: Finish off LPC USB register definitions Signed-off-by: Keith Packard --- src/lpc/lpc.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 8 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index da9ac534..4e229838 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -880,14 +880,65 @@ extern struct lpc_usb lpc_usb; #define LPC_USB_EPSKIP_SKIP 0 -#define LPC_USB_EPINUSE(ep) ((ep) + 2) - -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ +#define LPC_USB_EPINUSE_BUF(ep) (ep) + +#define LPC_USB_EPBUFCFG_BUF_SB(ep) (ep) + +#define LPC_USB_INTSTAT_EP0OUT 0 +#define LPC_USB_INTSTAT_EP0IN 1 +#define LPC_USB_INTSTAT_EP1OUT 2 +#define LPC_USB_INTSTAT_EP1IN 3 +#define LPC_USB_INTSTAT_EP2OUT 4 +#define LPC_USB_INTSTAT_EP2IN 5 +#define LPC_USB_INTSTAT_EP3OUT 6 +#define LPC_USB_INTSTAT_EP3IN 7 +#define LPC_USB_INTSTAT_EP4OUT 8 +#define LPC_USB_INTSTAT_EP4IN 9 +#define LPC_USB_INTSTAT_FRAME_INT 30 +#define LPC_USB_INTSTAT_DEV_INT 31 + +#define LPC_USB_INTIN_EP_INT_EN(ep) (ep) +#define LPC_USB_INTIN_FRAME_INT_EN 30 +#define LPC_USB_INTIN_DEV_INT_EN 31 + +#define LPC_USB_INTSETSTAT_EP_SET_INT(ep) (ep) +#define LPC_USB_INTSETSTAT_FRAME_SET_INT 30 +#define LPC_USB_INTSETSTAT_DEV_SET_INT 31 + +#define LPC_USB_INTROUTING_ROUTE_INT(ep) (ep) +#define LPC_USB_INTROUTING_INT30 30 +#define LPC_USB_INTROUTING_INT31 31 + +#define LPC_USB_EPTOGGLE_TOGGLE(ep) (ep) + +struct lpc_usb_ep { + vuint16_t buffer_offset; + vuint16_t buffer_status_nbytes; +}; + +struct lpc_usb_epn { + struct lpc_usb_ep out[2]; + struct lpc_usb_ep in[2]; +}; + +struct lpc_usb_endpoint { + struct lpc_usb_ep ep0_out; + vuint16_t setup_offset; + vuint16_t reserved_06; + struct lpc_usb_ep ep0_in; + vuint16_t reserved_0c; + vuint16_t reserved_0e; + struct lpc_usb_epn epn[4]; +}; + +#define LPC_USB_EP_STATUS_ACTIVE 15 +#define LPC_USB_EP_STATUS_DISABLED 14 +#define LPC_USB_EP_STATUS_STALL 13 +#define LPC_USB_EP_STATUS_TOGGLE_RESET 12 +#define LPC_USB_EP_STATUS_RATE_FEEDBACK 11 +#define LPC_USB_EP_STATUS_ENDPOINT_TYPE 10 +#define LPC_USB_EP_STATUS_OFFSET 0 +#define LPC_USB_EP_STATUS_OFFSET_MASK 0x3ff #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 -- cgit v1.2.3 From ac089d4fb930b7dbc4161259fd9bddba94395ebc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 17 May 2013 03:36:47 -0700 Subject: altos/lpc: Get USB working The lpc demo now has a USB command line. Also allocates system stack so we know when ram is tight at build time Signed-off-by: Keith Packard --- src/lpc/Makefile.defs | 2 +- src/lpc/altos.ld | 5 +- src/lpc/ao_arch.h | 8 +- src/lpc/ao_arch_funcs.h | 2 +- src/lpc/ao_timer_lpc.c | 33 +- src/lpc/ao_usb_lpc.c | 811 ++++++++++++++++++++--------------------------- src/lpc/lpc.h | 89 +++--- src/lpc/registers.ld | 2 + src/lpcxpresso/Makefile | 2 + src/lpcxpresso/ao_demo.c | 26 +- src/lpcxpresso/ao_pins.h | 5 +- 11 files changed, 446 insertions(+), 539 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index c18284d2..b63bdd12 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -7,7 +7,7 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util -CC=arm-none-eabi-gcc +CC=/usr/bin/arm-none-eabi-gcc SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a SAT_CFLAGS=-I$(SAT)/include diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 7a99e66b..bcfba1ea 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -17,7 +17,8 @@ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K - ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K + ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 512 + stack (!w) : ORIGIN = 0x10000000 + 4K - 512, LENGTH = 512 } INCLUDE registers.ld @@ -63,7 +64,7 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); PROVIDE(end = .); } diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 61182160..99c646f9 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -45,7 +45,10 @@ #define __interrupt(n) #define __at(n) -#define ao_arch_reboot() +#define ao_arch_reboot() arm_scb.aircr = ((0x05fa << 16) | \ + (0 << 15) | \ + (1 << 2) | \ + (0 << 1)) #define ao_arch_nop() asm("nop") @@ -114,7 +117,8 @@ extern const uint32_t ao_radio_cal; void ao_adc_init(void); - +#define AO_USB_OUT_EP 2 +#define AO_USB_IN_EP 3 void ao_serial_init(void); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 39222b9d..96ae0366 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -124,7 +124,7 @@ static inline void ao_arch_restore_stack(void) { /* Restore APSR */ asm("pop {r0}"); - asm("msr apsr,r0"); + asm("msr apsr_nczvq,r0"); /* Restore general registers and return */ asm("pop {r0-r7,pc}\n"); diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 51e82525..51835baa 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -78,6 +78,14 @@ ao_timer_init(void) #define AO_LPC_FCCO_MIN 156000000 +static void +ao_clock_delay(void) +{ + uint32_t i; + for (i = 0; i < 200; i++) + ao_arch_nop(); +} + void ao_clock_init(void) { @@ -94,11 +102,15 @@ ao_clock_init(void) /* Turn the IRC clock back on */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); + ao_clock_delay(); /* Switch to the IRC clock */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + while (!(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++) @@ -110,14 +122,15 @@ ao_clock_init(void) /* Power down the PLL before touching the registers */ lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); + ao_clock_delay(); /* 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); + ao_clock_delay(); /* Configure the crystal clock */ lpc_scb.sysoscctrl = ((0 << LPC_SCB_SYSOSCCTRL_BYPASS) | /* using a crystal */ @@ -125,12 +138,16 @@ ao_clock_init(void) /* Turn on the external crystal clock */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + ao_clock_delay(); /* 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); + lpc_scb.syspllclkuen = (0 << LPC_SCB_SYSPLLCLKUEN_ENA); + lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); + while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA))) + ; /* Turn on the PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); @@ -145,17 +162,15 @@ ao_clock_init(void) /* 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; + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + while (!(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; diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index af2bd271..0f881720 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -19,9 +19,9 @@ #include "ao_usb.h" #include "ao_product.h" -#define USB_DEBUG 1 -#define USB_DEBUG_DATA 1 -#define USB_ECHO 1 +#define USB_DEBUG 0 +#define USB_DEBUG_DATA 0 +#define USB_ECHO 0 #if USB_DEBUG #define debug(format, args...) printf(format, ## args); @@ -62,35 +62,26 @@ static uint8_t ao_usb_ep0_out_len; * Objects allocated in special USB memory */ -/* Buffer description tables */ -static union lpc_usb_bdt *ao_usb_bdt; /* USB address of end of allocated storage */ -static uint16_t ao_usb_sram_addr; +static uint8_t *ao_usb_sram; /* Pointer to ep0 tx/rx buffers in USB memory */ -static uint32_t *ao_usb_ep0_tx_buffer; -static uint32_t *ao_usb_ep0_rx_buffer; +static uint8_t *ao_usb_ep0_tx_buffer; +static uint8_t *ao_usb_ep0_setup_buffer; +static uint8_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ -static uint32_t *ao_usb_in_tx_buffer; -static uint32_t *ao_usb_out_rx_buffer; +static uint8_t *ao_usb_in_tx_buffer; +static uint8_t *ao_usb_out_rx_buffer; -/* System ram shadow of USB buffer; writing individual bytes is - * too much of a pain (sigh) */ +/* Our data buffers */ static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; static uint8_t ao_usb_tx_count; static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; -/* - * End point register indices - */ - -#define AO_USB_CONTROL_EPR 0 -#define AO_USB_INT_EPR 1 -#define AO_USB_OUT_EPR 2 -#define AO_USB_IN_EPR 3 +static struct lpc_usb_endpoint lpc_usb_endpoint __attribute((aligned(256))); /* Marks when we don't need to send an IN packet. * This happens only when the last IN packet is not full, @@ -129,39 +120,6 @@ static inline uint32_t set_toggle(uint32_t current_value, return (current_value ^ desired_value) & mask; } -static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) -{ - return (uint32_t *) (lpc_usb_sram + 2 * sram_addr); -} - -static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { - return (epr >> USB_USB_EPR_STAT_RX) & USB_USB_EPR_STAT_RX_MASK; -} - -static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { - return (epr >> USB_USB_EPR_STAT_TX) & USB_USB_EPR_STAT_TX_MASK; -} - -static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { - return (epr >> USB_USB_EPR_CTR_RX) & 1; -} - -static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { - return (epr >> USB_USB_EPR_CTR_TX) & 1; -} - -static inline uint32_t ao_usb_epr_setup(uint32_t epr) { - return (epr >> USB_USB_EPR_SETUP) & 1; -} - -static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { - return (epr >> USB_USB_EPR_DTOG_RX) & 1; -} - -static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { - return (epr >> USB_USB_EPR_DTOG_TX) & 1; -} - /* * Set current device address and mark the * interface as active @@ -170,36 +128,24 @@ void ao_usb_set_address(uint8_t address) { debug("ao_usb_set_address %02x\n", address); - lpc_usb.daddr = (1 << USB_USB_DADDR_EF) | address; + lpc_usb.devcmdstat = ((address << LPC_USB_DEVCMDSTAT_DEV_ADDR) | + (1 << LPC_USB_DEVCMDSTAT_DEV_EN) | + (0 << LPC_USB_DEVCMDSTAT_SETUP) | + (0 << LPC_USB_DEVCMDSTAT_PLL_ON) | + (0 << LPC_USB_DEVCMDSTAT_LPM_SUP) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_AO) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_AI) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_CO) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_CI) | + (1 << LPC_USB_DEVCMDSTAT_DCON) | + (0 << LPC_USB_DEVCMDSTAT_DSUS) | + (0 << LPC_USB_DEVCMDSTAT_DCON_C) | + (0 << LPC_USB_DEVCMDSTAT_DSUS_C) | + (0 << LPC_USB_DEVCMDSTAT_DRES_C) | + (0 << LPC_USB_DEVCMDSTAT_VBUSDEBOUNCED)); ao_usb_address_pending = 0; } -/* - * Write these values to preserve register contents under HW changes - */ - -#define USB_USB_EPR_INVARIANT ((1 << USB_USB_EPR_CTR_RX) | \ - (USB_USB_EPR_DTOG_RX_WRITE_INVARIANT << USB_USB_EPR_DTOG_RX) | \ - (USB_USB_EPR_STAT_RX_WRITE_INVARIANT << USB_USB_EPR_STAT_RX) | \ - (1 << USB_USB_EPR_CTR_TX) | \ - (USB_USB_EPR_DTOG_TX_WRITE_INVARIANT << USB_USB_EPR_DTOG_TX) | \ - (USB_USB_EPR_STAT_TX_WRITE_INVARIANT << USB_USB_EPR_STAT_TX)) - -#define USB_USB_EPR_INVARIANT_MASK ((1 << USB_USB_EPR_CTR_RX) | \ - (USB_USB_EPR_DTOG_RX_MASK << USB_USB_EPR_DTOG_RX) | \ - (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX) | \ - (1 << USB_USB_EPR_CTR_TX) | \ - (USB_USB_EPR_DTOG_TX_MASK << USB_USB_EPR_DTOG_TX) | \ - (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX)) - -/* - * These bits are purely under sw control, so preserve them in the - * register by re-writing what was read - */ -#define USB_USB_EPR_PRESERVE_MASK ((USB_USB_EPR_EP_TYPE_MASK << USB_USB_EPR_EP_TYPE) | \ - (1 << USB_USB_EPR_EP_KIND) | \ - (USB_USB_EPR_EA_MASK << USB_USB_EPR_EA)) - #define TX_DBG 0 #define RX_DBG 0 @@ -224,338 +170,192 @@ static void _dbg(int line, char *msg, uint32_t value); #endif /* - * Set the state of the specified endpoint register to a new - * value. This is tricky because the bits toggle where the new - * value is one, and we need to write invariant values in other - * spots of the register. This hardware is strange... + * Set just endpoint 0, for use during startup */ -static void -_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) + +static uint8_t * +ao_usb_alloc_sram(uint16_t size) { - uint32_t epr_write, epr_old; - - _tx_dbg1("set_stat_tx top", stat_tx); - epr_old = epr_write = lpc_usb.epr[ep]; - epr_write &= USB_USB_EPR_PRESERVE_MASK; - epr_write |= USB_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX, - stat_tx << USB_USB_EPR_STAT_TX); - lpc_usb.epr[ep] = epr_write; - _tx_dbg1("set_stat_tx bottom", epr_write); + uint8_t *addr = ao_usb_sram; + + ao_usb_sram += (size + 63) & ~63; + return addr; } -static void -ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +static uint16_t +ao_usb_sram_offset(uint8_t *addr) { - ao_arch_block_interrupts(); - _ao_usb_set_stat_tx(ep, stat_tx); - ao_arch_release_interrupts(); + return (uint16_t) ((intptr_t) addr >> 6); } static void -_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { - uint32_t epr_write, epr_old; - - epr_write = epr_old = lpc_usb.epr[ep]; - epr_write &= USB_USB_EPR_PRESERVE_MASK; - epr_write |= USB_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX, - stat_rx << USB_USB_EPR_STAT_RX); - lpc_usb.epr[ep] = epr_write; +ao_usb_set_ep(vuint32_t *ep, uint8_t *addr, uint16_t nbytes) +{ + *ep = ((ao_usb_sram_offset(addr) << LPC_USB_EP_OFFSET) | + (nbytes << LPC_USB_EP_NBYTES) | + (0 << LPC_USB_EP_ENDPOINT_ISO) | + (0 << LPC_USB_EP_RATE_FEEDBACK) | + (0 << LPC_USB_EP_TOGGLE_RESET) | + (0 << LPC_USB_EP_STALL) | + (0 << LPC_USB_EP_DISABLED) | + (1 << LPC_USB_EP_ACTIVE)); } -static void -ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { - ao_arch_block_interrupts(); - _ao_usb_set_stat_rx(ep, stat_rx); - ao_arch_release_interrupts(); +static inline uint16_t +ao_usb_ep_count(vuint32_t *ep) +{ + return (*ep >> LPC_USB_EP_NBYTES) & LPC_USB_EP_NBYTES_MASK; } -/* - * Set just endpoint 0, for use during startup - */ - -static void -ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +static inline uint8_t +ao_usb_ep_stall(vuint32_t *ep) { - uint32_t epr; - ao_arch_block_interrupts(); - epr = lpc_usb.epr[ep]; - epr = ((0 << USB_USB_EPR_CTR_RX) | - (epr & (1 << USB_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX), - (stat_rx << USB_USB_EPR_STAT_RX)) | - (type << USB_USB_EPR_EP_TYPE) | - (0 << USB_USB_EPR_EP_KIND) | - (0 << USB_USB_EPR_CTR_TX) | - (epr & (1 << USB_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX), - (stat_tx << USB_USB_EPR_STAT_TX)) | - (addr << USB_USB_EPR_EA)); - lpc_usb.epr[ep] = epr; - ao_arch_release_interrupts(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - ep, epr, lpc_usb.epr[ep]); + return (*ep >> LPC_USB_EP_STALL) & 1; } -static void -ao_usb_set_ep0(void) +static inline vuint32_t * +ao_usb_ep0_out(void) { - uint32_t epr; - int e; - - ao_usb_sram_addr = 0; - - /* buffer table is at the start of USB memory */ - lpc_usb.btable = 0; - ao_usb_bdt = (void *) lpc_usb_sram; - - ao_usb_sram_addr += 8 * USB_USB_BDT_SIZE; - - /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ - - ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; - ao_usb_bdt[0].single.count_tx = 0; - ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_CONTROL_SIZE; - - ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; - ao_usb_bdt[0].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | - (((AO_USB_CONTROL_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); - ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + return &lpc_usb_endpoint.ep0_out; +} - ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, - USB_USB_EPR_EP_TYPE_CONTROL, - USB_USB_EPR_STAT_RX_VALID, - USB_USB_EPR_STAT_TX_NAK); +static inline vuint32_t * +ao_usb_ep0_in(void) +{ + return &lpc_usb_endpoint.ep0_in; +} - /* Clear all of the other endpoints */ - for (e = 1; e < 8; e++) { - ao_usb_init_ep(e, 0, - USB_USB_EPR_EP_TYPE_CONTROL, - USB_USB_EPR_STAT_RX_DISABLED, - USB_USB_EPR_STAT_TX_DISABLED); - } +static inline vuint32_t * +ao_usb_epn_out(uint8_t n) +{ + return &lpc_usb_endpoint.epn[n-1].out[0]; +} - ao_usb_set_address(0); +static inline vuint32_t * +ao_usb_epn_in(uint8_t n) +{ + return &lpc_usb_endpoint.epn[n-1].in[0]; } static void -ao_usb_set_configuration(void) +ao_usb_set_epn_in(uint8_t n, uint8_t *addr, uint16_t nbytes) { - uint32_t epr; - - debug ("ao_usb_set_configuration\n"); - - /* Set up the INT end point */ - ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; - ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_INT_SIZE; - - ao_usb_init_ep(AO_USB_INT_EPR, - AO_USB_INT_EP, - USB_USB_EPR_EP_TYPE_INTERRUPT, - USB_USB_EPR_STAT_RX_DISABLED, - USB_USB_EPR_STAT_TX_NAK); - - /* Set up the OUT end point */ - ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; - ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | - (((AO_USB_OUT_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); - ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_OUT_SIZE; - - ao_usb_init_ep(AO_USB_OUT_EPR, - AO_USB_OUT_EP, - USB_USB_EPR_EP_TYPE_BULK, - USB_USB_EPR_STAT_RX_VALID, - USB_USB_EPR_STAT_TX_DISABLED); - - /* Set up the IN end point */ - ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; - ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_IN_SIZE; - - ao_usb_init_ep(AO_USB_IN_EPR, - AO_USB_IN_EP, - USB_USB_EPR_EP_TYPE_BULK, - USB_USB_EPR_STAT_RX_DISABLED, - USB_USB_EPR_STAT_TX_NAK); - - ao_usb_running = 1; + ao_usb_set_ep(ao_usb_epn_in(n), addr, nbytes); } -static uint16_t control_count; -static uint16_t int_count; -static uint16_t in_count; -static uint16_t out_count; -static uint16_t reset_count; - -void -lpc_usb_lp_isr(void) +static void +ao_usb_set_epn_out(uint8_t n, uint8_t *addr, uint16_t nbytes) { - uint32_t istr = lpc_usb.istr; - - if (istr & (1 << USB_USB_ISTR_CTR)) { - uint8_t ep = istr & USB_USB_ISTR_EP_ID_MASK; - uint32_t epr, epr_write; - - /* Preserve the SW write bits, don't mess with most HW writable bits, - * clear the CTR_RX and CTR_TX bits - */ - epr = lpc_usb.epr[ep]; - epr_write = epr; - epr_write &= USB_USB_EPR_PRESERVE_MASK; - epr_write |= USB_USB_EPR_INVARIANT; - epr_write &= ~(1 << USB_USB_EPR_CTR_RX); - epr_write &= ~(1 << USB_USB_EPR_CTR_TX); - lpc_usb.epr[ep] = epr_write; - - switch (ep) { - case 0: - ++control_count; - if (ao_usb_epr_ctr_rx(epr)) { - if (ao_usb_epr_setup(epr)) - ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; - else - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; - } - if (ao_usb_epr_ctr_tx(epr)) - ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; - ao_wakeup(&ao_usb_ep0_receive); - break; - case AO_USB_OUT_EPR: - ++out_count; - if (ao_usb_epr_ctr_rx(epr)) { - _rx_dbg1("RX ISR", epr); - ao_usb_out_avail = 1; - _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); - _rx_dbg0("stdin awoken"); - } - break; - case AO_USB_IN_EPR: - ++in_count; - _tx_dbg1("TX ISR", epr); - if (ao_usb_epr_ctr_tx(epr)) { - ao_usb_in_pending = 0; - ao_wakeup(&ao_usb_in_pending); - } - break; - case AO_USB_INT_EPR: - ++int_count; - if (ao_usb_epr_ctr_tx(epr)) - _ao_usb_set_stat_tx(AO_USB_INT_EPR, USB_USB_EPR_STAT_TX_NAK); - break; - } - return; - } - - if (istr & (1 << USB_USB_ISTR_RESET)) { - ++reset_count; - lpc_usb.istr &= ~(1 << USB_USB_ISTR_RESET); - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; - ao_wakeup(&ao_usb_ep0_receive); - } + ao_usb_set_ep(ao_usb_epn_out(n), addr, nbytes); } -void -lpc_usb_fs_wkup(void) +static inline uint16_t +ao_usb_epn_out_count(uint8_t n) { - /* USB wakeup, just clear the bit for now */ - lpc_usb.istr &= ~(1 << USB_USB_ISTR_WKUP); + return ao_usb_ep_count(ao_usb_epn_out(n)); } -/* The USB memory holds 16 bit values on 32 bit boundaries - * and must be accessed only in 32 bit units. Sigh. - */ +static inline uint16_t +ao_usb_epn_in_count(uint8_t n) +{ + return ao_usb_ep_count(ao_usb_epn_in(n)); +} -static inline void -ao_usb_write_byte(uint8_t byte, uint32_t *base, uint16_t offset) +static uint8_t * +ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes) { - base += offset >> 1; - if (offset & 1) { - *base = (*base & 0xff) | ((uint32_t) byte << 8); - } else { - *base = (*base & 0xff00) | byte; - } + uint8_t *addr = ao_usb_alloc_sram(nbytes); + + ao_usb_set_ep(ep, addr, set_nbytes); + return addr; } -static inline void -ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) +static void +ao_usb_disable_ep(vuint32_t *ep) { - base[offset>>1] = data; + *ep = ((0 << LPC_USB_EP_OFFSET) | + (0 << LPC_USB_EP_NBYTES) | + (0 << LPC_USB_EP_ENDPOINT_ISO) | + (0 << LPC_USB_EP_RATE_FEEDBACK) | + (0 << LPC_USB_EP_TOGGLE_RESET) | + (0 << LPC_USB_EP_STALL) | + (1 << LPC_USB_EP_DISABLED) | + (0 << LPC_USB_EP_ACTIVE)); } static void -ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) { - if (!bytes) - return; - if (offset & 1) { - debug_data (" %02x", src[0]); - ao_usb_write_byte(*src++, base, offset++); - bytes--; - } - while (bytes >= 2) { - debug_data (" %02x %02x", src[0], src[1]); - ao_usb_write_short((src[1] << 8) | src[0], base, offset); - offset += 2; - src += 2; - bytes -= 2; - } - if (bytes) { - debug_data (" %02x", src[0]); - ao_usb_write_byte(*src, base, offset); - } + uint8_t *addr; + + addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes); + if (out_addr) + *out_addr = addr; + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); + + addr = ao_usb_enable_ep(ao_usb_epn_in(n), in_bytes, 0); + if (in_addr) + *in_addr = addr; + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); } -static inline uint8_t -ao_usb_read_byte(uint32_t *base, uint16_t offset) +static void +ao_usb_disable_epn(uint8_t n) { - base += offset >> 1; - if (offset & 1) - return (*base >> 8) & 0xff; - else - return *base & 0xff; + ao_usb_disable_ep(ao_usb_epn_out(n)); + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); + ao_usb_disable_ep(ao_usb_epn_in(n)); + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); } -static inline uint16_t -ao_usb_read_short(uint32_t *base, uint16_t offset) +static void +ao_usb_set_ep0(void) { - return base[offset>>1]; + int e; + + /* Everything is single buffered for now */ + lpc_usb.epbufcfg = 0; + lpc_usb.epinuse = 0; + lpc_usb.epskip = 0xffffffff; + + ao_usb_set_address(0); + lpc_usb.intstat = 0xc00003ff; + + ao_usb_configuration = 0; + + ao_usb_sram = lpc_usb_sram; + + lpc_usb.epliststart = (uint32_t) (intptr_t) &lpc_usb_endpoint; + lpc_usb.databufstart = ((uint32_t) (intptr_t) ao_usb_sram) & 0xffc00000; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_ep0_rx_buffer = ao_usb_enable_ep(ao_usb_ep0_out(), AO_USB_CONTROL_SIZE, AO_USB_CONTROL_SIZE); + ao_usb_ep0_setup_buffer = ao_usb_alloc_sram(AO_USB_CONTROL_SIZE); + lpc_usb_endpoint.setup = ao_usb_sram_offset(ao_usb_ep0_setup_buffer); + ao_usb_ep0_tx_buffer = ao_usb_enable_ep(ao_usb_ep0_in(), AO_USB_CONTROL_SIZE, 0); + + /* Clear all of the other endpoints */ + for (e = 1; e <= 4; e++) + ao_usb_disable_epn(e); + } static void -ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) +ao_usb_set_configuration(void) { - if (!bytes) - return; - if (offset & 1) { - *dst++ = ao_usb_read_byte(base, offset++); - debug_data (" %02x", dst[-1]); - bytes--; - } - while (bytes >= 2) { - uint16_t s = ao_usb_read_short(base, offset); - dst[0] = s; - dst[1] = s >> 8; - debug_data (" %02x %02x", dst[0], dst[1]); - offset += 2; - dst += 2; - bytes -= 2; - } - if (bytes) { - *dst = ao_usb_read_byte(base, offset); - debug_data (" %02x", dst[0]); - } + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); + + /* Set up the OUT end point */ + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL); + + /* Set up the IN end point */ + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer); + + ao_usb_running = 1; } /* Send an IN data packet */ @@ -564,12 +364,6 @@ ao_usb_ep0_flush(void) { uint8_t this_len; - /* Check to see if the endpoint is still busy */ - if (ao_usb_epr_stat_tx(lpc_usb.epr[0]) == USB_USB_EPR_STAT_TX_VALID) { - debug("EP0 not accepting IN data\n"); - return; - } - this_len = ao_usb_ep0_in_len; if (this_len > AO_USB_CONTROL_SIZE) this_len = AO_USB_CONTROL_SIZE; @@ -580,34 +374,43 @@ ao_usb_ep0_flush(void) ao_usb_ep0_in_len -= this_len; debug_data ("Flush EP0 len %d:", this_len); - ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + memcpy(ao_usb_ep0_tx_buffer, ao_usb_ep0_in_data, this_len); debug_data ("\n"); ao_usb_ep0_in_data += this_len; /* Mark the endpoint as TX valid to send the packet */ - ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; - ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, USB_USB_EPR_STAT_TX_VALID); - debug ("queue tx. epr 0 now %08x\n", lpc_usb.epr[AO_USB_CONTROL_EPR]); + ao_usb_set_ep(ao_usb_ep0_in(), ao_usb_ep0_tx_buffer, this_len); + debug ("queue tx. 0 now %08x\n", *ao_usb_ep0_in()); } /* Read data from the ep0 OUT fifo */ static void ao_usb_ep0_fill(void) { - uint16_t len = ao_usb_bdt[0].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + uint16_t len; + uint8_t *rx_buffer; + + /* Pull all of the data out of the packet */ + if (lpc_usb.devcmdstat & (1 << LPC_USB_DEVCMDSTAT_SETUP)) { + rx_buffer = ao_usb_ep0_setup_buffer; + len = 8; + } else { + rx_buffer = ao_usb_ep0_rx_buffer; + len = AO_USB_CONTROL_SIZE - ao_usb_ep_count(ao_usb_ep0_out()); + } if (len > ao_usb_ep0_out_len) len = ao_usb_ep0_out_len; ao_usb_ep0_out_len -= len; - /* Pull all of the data out of the packet */ debug_data ("Fill EP0 len %d:", len); - ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, 0, len); + memcpy(ao_usb_ep0_out_data, rx_buffer, len); debug_data ("\n"); ao_usb_ep0_out_data += len; /* ACK the packet */ - ao_usb_set_stat_rx(0, USB_USB_EPR_STAT_RX_VALID); + ao_usb_set_ep(ao_usb_ep0_out(), ao_usb_ep0_rx_buffer, AO_USB_CONTROL_SIZE); + lpc_usb.devcmdstat |= (1 << LPC_USB_DEVCMDSTAT_SETUP); } static void @@ -772,55 +575,109 @@ ao_usb_ep0_setup(void) ao_usb_ep0_in_start(ao_usb_setup.length); } -/* End point 0 receives all of the control messages. */ static void -ao_usb_ep0(void) +ao_usb_ep0_handle(uint8_t receive) { - uint8_t intx, udint; + ao_usb_ep0_receive = 0; - debug ("usb task started\n"); - ao_usb_ep0_state = AO_USB_EP0_IDLE; - for (;;) { - uint8_t receive; - ao_arch_critical( - while (!(receive = ao_usb_ep0_receive)) - ao_sleep(&ao_usb_ep0_receive); - ao_usb_ep0_receive = 0; - ); - - if (receive & AO_USB_EP0_GOT_RESET) { - debug ("\treset\n"); - ao_usb_set_ep0(); - continue; - } - if (receive & AO_USB_EP0_GOT_SETUP) { - debug ("\tsetup\n"); - ao_usb_ep0_setup(); - } - if (receive & AO_USB_EP0_GOT_RX_DATA) { - debug ("\tgot rx data\n"); - if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len == 0) { - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - ao_usb_ep0_in_start(0); - } + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + return; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); } } - if (receive & AO_USB_EP0_GOT_TX_ACK) { - debug ("\tgot tx ack\n"); - - /* Wait until the IN packet is received from addr 0 - * before assigning our local address - */ - if (ao_usb_address_pending) - ao_usb_set_address(ao_usb_address); - if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) - ao_usb_ep0_flush(); + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) + ao_usb_set_address(ao_usb_address); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); + } +} + +static uint16_t control_count; +static uint16_t int_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +void +lpc_usb_irq_isr(void) +{ + uint32_t intstat = lpc_usb.intstat & lpc_usb.inten; + + lpc_usb.intstat = intstat; + /* Handle EP0 OUT packets */ + if (intstat & (1 << LPC_USB_INT_EPOUT(0))) { + if (lpc_usb.devcmdstat & (1 << LPC_USB_DEVCMDSTAT_SETUP)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + + ao_usb_ep0_handle(ao_usb_ep0_receive); + } + + /* Handle EP0 IN packets */ + if (intstat & (1 << LPC_USB_INT_EPIN(0))) { + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + + ao_usb_ep0_handle(ao_usb_ep0_receive); + } + + + /* Handle OUT packets */ + if (intstat & (1 << LPC_USB_INT_EPOUT(AO_USB_OUT_EP))) { + ++out_count; + _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP)); + ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); + ao_wakeup(&ao_stdin_ready); + _rx_dbg0("stdin awoken"); + } + + /* Handle IN packets */ + if (intstat & (1 << LPC_USB_INT_EPIN(AO_USB_IN_EP))) { + ++in_count; + _tx_dbg1("TX ISR", *ao_usb_epn_in(AO_USB_IN_EP)); + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + + /* NAK all INT EP IN packets */ + if (intstat & (1 << LPC_USB_INT_EPIN(AO_USB_INT_EP))) { + ; + } + + /* Check for reset */ + if (intstat & (1 << LPC_USB_INT_DEV)) { + if (lpc_usb.devcmdstat & (1 << LPC_USB_DEVCMDSTAT_DRES_C)) + { + lpc_usb.devcmdstat |= (1 << LPC_USB_DEVCMDSTAT_DRES_C); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_usb_ep0_handle(ao_usb_ep0_receive); } } } + + /* Queue the current IN buffer for transmission */ static void _ao_usb_in_send(void) @@ -832,10 +689,9 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); - ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count); ao_usb_tx_count = 0; - _ao_usb_set_stat_tx(AO_USB_IN_EPR, USB_USB_EPR_STAT_TX_VALID); _tx_dbg0("in_send end"); } @@ -905,17 +761,17 @@ _ao_usb_out_recv(void) _rx_dbg0("out_recv top"); ao_usb_out_avail = 0; - ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + ao_usb_rx_count = AO_USB_OUT_SIZE - ao_usb_epn_out_count(AO_USB_OUT_EP); _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d:", ao_usb_rx_count); - ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); + memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); debug_data("\n"); ao_usb_rx_pos = 0; /* ACK the packet */ - _ao_usb_set_stat_rx(AO_USB_OUT_EPR, USB_USB_EPR_STAT_RX_VALID); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE); } int @@ -960,17 +816,25 @@ void ao_usb_disable(void) { ao_arch_block_interrupts(); - lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); - lpc_usb.istr = 0; - /* Disable USB pull-up */ - lpc_syscfg.pmc &= ~(1 << USB_SYSCFG_PMC_USB_PU); + /* Disable interrupts */ + lpc_usb.inten = 0; + + lpc_nvic_clear_enable(LPC_ISR_USB_IRQ_POS); - /* Switch off the device */ - lpc_usb.cntr = (1 << USB_USB_CNTR_PDWN) | (1 << USB_USB_CNTR_FRES); + /* Disable the device */ + lpc_usb.devcmdstat = 0; + + /* Turn off USB clock */ + lpc_scb.usbclkdiv = 0; + + /* Disable USB PHY */ + lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + + /* Disable USB registers and RAM */ + lpc_scb.sysahbclkctrl &= ~((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | + (1 << LPC_SCB_SYSAHBCLKCTRL_USBRAM)); - /* Disable the interface */ - lpc_rcc.apb1enr &+ ~(1 << USB_RCC_APB1ENR_USBEN); ao_arch_release_interrupts(); } @@ -979,6 +843,23 @@ ao_usb_enable(void) { int t; + /* Enable USB pins */ +#if HAS_USB_CONNECT + lpc_ioconf.pio0_6 = ((LPC_IOCONF_FUNC_USB_CONNECT << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD) | + 0x80); +#endif +#if HAS_USB_VBUS + lpc_ioconf.pio0_3 = ((LPC_IOCONF_FUNC_USB_VBUS << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD) | + 0x80); +#endif /* Enable USB registers and RAM */ lpc_scb.sysahbclkctrl |= ((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | (1 << LPC_SCB_SYSAHBCLKCTRL_USBRAM)); @@ -986,52 +867,55 @@ ao_usb_enable(void) /* Enable USB PHY */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + /* Turn on USB PLL */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); + + lpc_scb.usbpllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) + ; + lpc_scb.usbpllctrl = 0x23; + while (!(lpc_scb.usbpllstat & 1)) + ; + + lpc_scb.usbclksel = 0; + /* Turn on USB clock, use 48MHz clock unchanged */ lpc_scb.usbclkdiv = 1; /* Configure interrupts */ ao_arch_block_interrupts(); - /* Enable interrupts */ - lpc_usb. - /* Route interrupts */ - - lpc_nvic_set_priority(USB_ISR_USB_LP_POS, 3); - lpc_nvic_set_enable(USB_ISR_USB_LP_POS); + /* Route all interrupts to the main isr */ + lpc_usb.introuting = 0; - ao_usb_configuration = 0; - - lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); + /* Configure NVIC */ - /* Clear the power down bit */ - lpc_usb.cntr = 0; + lpc_nvic_set_enable(LPC_ISR_USB_IRQ_POS); + lpc_nvic_set_priority(LPC_ISR_USB_IRQ_POS, 0); /* Clear any spurious interrupts */ - lpc_usb.istr = 0; + lpc_usb.intstat = 0xffffffff; debug ("ao_usb_enable\n"); /* Enable interrupts */ - lpc_usb.cntr = ((1 << USB_USB_CNTR_CTRM) | - (0 << USB_USB_CNTR_PMAOVRM) | - (0 << USB_USB_CNTR_ERRM) | - (0 << USB_USB_CNTR_WKUPM) | - (0 << USB_USB_CNTR_SUSPM) | - (1 << USB_USB_CNTR_RESETM) | - (0 << USB_USB_CNTR_SOFM) | - (0 << USB_USB_CNTR_ESOFM) | - (0 << USB_USB_CNTR_RESUME) | - (0 << USB_USB_CNTR_FSUSP) | - (0 << USB_USB_CNTR_LP_MODE) | - (0 << USB_USB_CNTR_PDWN) | - (0 << USB_USB_CNTR_FRES)); + lpc_usb.inten = ((1 << LPC_USB_INT_EPOUT(0)) | + (1 << LPC_USB_INT_EPIN(0)) | + (1 << LPC_USB_INT_EPIN(AO_USB_INT_EP)) | + (1 << LPC_USB_INT_EPOUT(AO_USB_OUT_EP)) | + (1 << LPC_USB_INT_EPIN(AO_USB_IN_EP)) | + (1 << LPC_USB_INT_DEV)); ao_arch_release_interrupts(); + lpc_usb.devcmdstat = 0; for (t = 0; t < 1000; t++) ao_arch_nop(); - /* Enable USB pull-up */ - lpc_syscfg.pmc |= (1 << USB_SYSCFG_PMC_USB_PU); + + ao_usb_set_ep0(); } #if USB_ECHO @@ -1070,7 +954,6 @@ ao_usb_init(void) ao_usb_enable(); debug ("ao_usb_init\n"); - ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif @@ -1091,7 +974,7 @@ struct ao_usb_dbg { uint32_t primask; #if TX_DBG uint16_t in_count; - uint32_t in_epr; + uint32_t in_ep; uint32_t in_pending; uint32_t tx_count; uint32_t in_flushed; @@ -1100,13 +983,13 @@ struct ao_usb_dbg { uint8_t rx_count; uint8_t rx_pos; uint8_t out_avail; - uint32_t out_epr; + uint32_t out_ep; #endif }; -#define NUM_USB_DBG 128 +#define NUM_USB_DBG 8 -static struct ao_usb_dbg dbg[128]; +static struct ao_usb_dbg dbg[NUM_USB_DBG]; static int dbg_i; static void _dbg(int line, char *msg, uint32_t value) @@ -1119,7 +1002,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].primask = primask; #if TX_DBG dbg[dbg_i].in_count = in_count; - dbg[dbg_i].in_epr = lpc_usb.epr[AO_USB_IN_EPR]; + dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP); dbg[dbg_i].in_pending = ao_usb_in_pending; dbg[dbg_i].tx_count = ao_usb_tx_count; dbg[dbg_i].in_flushed = ao_usb_in_flushed; @@ -1128,7 +1011,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].rx_count = ao_usb_rx_count; dbg[dbg_i].rx_pos = ao_usb_rx_pos; dbg[dbg_i].out_avail = ao_usb_out_avail; - dbg[dbg_i].out_epr = lpc_usb.epr[AO_USB_OUT_EPR]; + dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP); #endif if (++dbg_i == NUM_USB_DBG) dbg_i = 0; diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 4e229838..4141f356 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -116,7 +116,7 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_SSEL0 1 #define LPC_IOCONF_FUNC_CT16B0_CAP0 2 -/* PIO0_3 +/* PIO0_3 */ #define LPC_IOCONF_FUNC_PIO0_3 0 #define LPC_IOCONF_FUNC_USB_VBUS 1 @@ -395,7 +395,7 @@ struct lpc_scb { vuint32_t syspllclksel; /* 0x40 */ vuint32_t syspllclkuen; vuint32_t usbpllclksel; - vuint32_t usbplllclkuen; + vuint32_t usbpllclkuen; uint32_t r50[8]; @@ -600,8 +600,13 @@ extern struct lpc_scb lpc_scb; #define LPC_SCB_USBCLKUEN_ENA 0 #define LPC_SCB_USBCLKDIV_DIV 0 -#define LPC_SCB_CLKOUTSEL_ -#define LPC_SCB_CLKOUTUEN_ +#define LPC_SCB_CLKOUTSEL_SEL 0 +#define LPC_SCB_CLKOUTSEL_SEL_IRC 0 +#define LPC_SCB_CLKOUTSEL_SEL_SYSOSC 1 +#define LPC_SCB_CLKOUTSEL_SEL_LF 2 +#define LPC_SCB_CLKOUTSEL_SEL_MAIN_CLOCK 3 + +#define LPC_SCB_CLKOUTUEN_ENA 0 #define LPC_SCB_PDRUNCFG_IRCOUT_PD 0 #define LPC_SCB_PDRUNCFG_IRC_PD 1 @@ -823,6 +828,7 @@ struct lpc_usb { vuint32_t inten; vuint32_t intsetstat; vuint32_t introuting; + uint32_t r30; vuint32_t eptoggle; } lpc_usb; @@ -884,18 +890,11 @@ extern struct lpc_usb lpc_usb; #define LPC_USB_EPBUFCFG_BUF_SB(ep) (ep) -#define LPC_USB_INTSTAT_EP0OUT 0 -#define LPC_USB_INTSTAT_EP0IN 1 -#define LPC_USB_INTSTAT_EP1OUT 2 -#define LPC_USB_INTSTAT_EP1IN 3 -#define LPC_USB_INTSTAT_EP2OUT 4 -#define LPC_USB_INTSTAT_EP2IN 5 -#define LPC_USB_INTSTAT_EP3OUT 6 -#define LPC_USB_INTSTAT_EP3IN 7 -#define LPC_USB_INTSTAT_EP4OUT 8 -#define LPC_USB_INTSTAT_EP4IN 9 -#define LPC_USB_INTSTAT_FRAME_INT 30 -#define LPC_USB_INTSTAT_DEV_INT 31 +#define LPC_USB_INT_EPOUT(ep) ((ep) << 1) +#define LPC_USB_INT_EPIN(ep) (((ep) << 1) + 1) + +#define LPC_USB_INT_FRAME 30 +#define LPC_USB_INT_DEV 31 #define LPC_USB_INTIN_EP_INT_EN(ep) (ep) #define LPC_USB_INTIN_FRAME_INT_EN 30 @@ -911,34 +910,34 @@ extern struct lpc_usb lpc_usb; #define LPC_USB_EPTOGGLE_TOGGLE(ep) (ep) -struct lpc_usb_ep { - vuint16_t buffer_offset; - vuint16_t buffer_status_nbytes; -}; - struct lpc_usb_epn { - struct lpc_usb_ep out[2]; - struct lpc_usb_ep in[2]; + vuint32_t out[2]; + vuint32_t in[2]; }; struct lpc_usb_endpoint { - struct lpc_usb_ep ep0_out; - vuint16_t setup_offset; - vuint16_t reserved_06; - struct lpc_usb_ep ep0_in; - vuint16_t reserved_0c; - vuint16_t reserved_0e; + vuint32_t ep0_out; + vuint32_t setup; + vuint32_t ep0_in; + vuint32_t reserved_0c; struct lpc_usb_epn epn[4]; }; -#define LPC_USB_EP_STATUS_ACTIVE 15 -#define LPC_USB_EP_STATUS_DISABLED 14 -#define LPC_USB_EP_STATUS_STALL 13 -#define LPC_USB_EP_STATUS_TOGGLE_RESET 12 -#define LPC_USB_EP_STATUS_RATE_FEEDBACK 11 -#define LPC_USB_EP_STATUS_ENDPOINT_TYPE 10 -#define LPC_USB_EP_STATUS_OFFSET 0 -#define LPC_USB_EP_STATUS_OFFSET_MASK 0x3ff +/* Assigned in registers.ld to point at the base + * of USB ram + */ + +extern uint8_t lpc_usb_sram[]; + +#define LPC_USB_EP_ACTIVE 31 +#define LPC_USB_EP_DISABLED 30 +#define LPC_USB_EP_STALL 29 +#define LPC_USB_EP_TOGGLE_RESET 28 +#define LPC_USB_EP_RATE_FEEDBACK 27 +#define LPC_USB_EP_ENDPOINT_ISO 26 +#define LPC_USB_EP_NBYTES 16 +#define LPC_USB_EP_NBYTES_MASK 0x3ff +#define LPC_USB_EP_OFFSET 0 #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 @@ -1039,4 +1038,20 @@ lpc_nvic_get_priority(int irq) { return (lpc_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); } +struct arm_scb { + vuint32_t cpuid; + vuint32_t icsr; + uint32_t reserved08; + vuint32_t aircr; + + vuint32_t scr; + vuint32_t ccr; + uint32_t reserved18; + vuint32_t shpr2; + + vuint32_t shpr3; +}; + +extern struct arm_scb arm_scb; + #endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index 51a0612f..0201e55f 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -9,3 +9,5 @@ lpc_usb = 0x40080000; lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; lpc_nvic = 0xe000e100; +arm_scb = 0xe000ed00; +lpc_usb_sram = 0x20004000; diff --git a/src/lpcxpresso/Makefile b/src/lpcxpresso/Makefile index bac222cc..3745f283 100644 --- a/src/lpcxpresso/Makefile +++ b/src/lpcxpresso/Makefile @@ -23,8 +23,10 @@ ALTOS_SRC = \ ao_panic.c \ ao_led_lpc.c \ ao_task.c \ + ao_cmd.c \ ao_timer_lpc.c \ ao_serial_lpc.c \ + ao_usb_lpc.c \ ao_stdio.c PRODUCT=LpcDemo-v0.0 diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c index eae9503e..0c931611 100644 --- a/src/lpcxpresso/ao_demo.c +++ b/src/lpcxpresso/ao_demo.c @@ -15,24 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" - -struct ao_task demo_task; - -static void demo(void) { - for (;;) { - ao_delay(100); - ao_led_toggle(AO_LED_RED); - } -} - -static struct ao_task serial_task; - -static void serial(void) { - for (;;) { - printf ("hello, world\n"); - } -} +#include +#include int main(void) @@ -44,12 +28,10 @@ main(void) ao_timer_init(); ao_serial_init(); - + ao_usb_init(); + ao_cmd_init(); ao_task_init(); - ao_add_task(&demo_task, demo, "demo"); - ao_add_task(&serial_task, serial, "serial"); - ao_start_scheduler(); for (;;) { diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h index 7748f73c..c0074ce2 100644 --- a/src/lpcxpresso/ao_pins.h +++ b/src/lpcxpresso/ao_pins.h @@ -34,7 +34,10 @@ #define LEDS_AVAILABLE AO_LED_RED -#define HAS_USB 0 +#define HAS_USB 1 + +#define HAS_USB_CONNECT 1 +#define HAS_USB_VBUS 1 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From 935a7ff38010ec4ad19f315f8a2a1557c01ae554 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:13:17 -0700 Subject: altos: Add LPC spi driver Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 15 ++++ src/lpc/ao_arch_funcs.h | 51 +++++++++++++ src/lpc/ao_spi_lpc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 260 insertions(+) create mode 100644 src/lpc/ao_spi_lpc.c (limited to 'src/lpc') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 99c646f9..d9f72e1a 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -28,6 +28,8 @@ #define AO_LED_TYPE uint16_t +#define AO_PORT_TYPE uint32_t + #ifndef AO_TICK_TYPE #define AO_TICK_TYPE uint16_t #define AO_TICK_SIGNED int16_t @@ -123,4 +125,17 @@ ao_adc_init(void); void ao_serial_init(void); +/* SPI definitions */ + +#define AO_SPI_SPEED_12MHz 2 +#define AO_SPI_SPEED_6MHz 4 +#define AO_SPI_SPEED_4MHz 6 +#define AO_SPI_SPEED_2MHz 12 +#define AO_SPI_SPEED_1MHz 24 +#define AO_SPI_SPEED_500kHz 48 +#define AO_SPI_SPEED_250kHz 96 +#define AO_SPI_SPEED_125kHz 192 + +#define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz + #endif /* _AO_ARCH_H_ */ diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 96ae0366..94d876f6 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -144,4 +144,55 @@ static inline void ao_arch_restore_stack(void) { ao_arch_release_interrupts(); \ } while (0) +/* + * SPI + */ + +#define ao_spi_set_cs(port,mask) (lpc_gpio.clr[port] = (mask)) +#define ao_spi_clr_cs(port,mask) (lpc_gpio.set[port] = (mask)) + +#define ao_spi_get_mask(port,mask,bus,speed) do { \ + ao_spi_get(bus, speed); \ + ao_spi_set_cs(port, mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask,bus) do { \ + ao_spi_clr_cs(reg,mask); \ + ao_spi_put(bus); \ + } while (0) + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1< + * + * 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 + +static uint8_t ao_spi_mutex[LPC_NUM_SPI]; + +static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 }; + +static uint8_t spi_dev_null; + +#define spi_loop(len, put, get) do { \ + while (len--) { \ + /* Wait for space in the fifo */ \ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_TNF)) == 0) \ + ; \ + /* send a byte */ \ + lpc_ssp->dr = put; \ + \ + /* recv a byte */ \ + get lpc_ssp->dr; \ + } \ + \ + /* Wait for the fifo to drain */ \ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_BSY))) \ + ; \ + } while (0); + +void +ao_spi_send(void *block, uint16_t len, uint8_t id) +{ + uint8_t *b = block; + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, *b++, (void)); +} + +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t id) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, value, (void)); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t id) +{ + uint8_t *b = block; + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, 0xff, *b++ =); +} + +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t id) +{ + uint8_t *o = out; + uint8_t *i = in; + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, *o++, *i++ =); +} + +void +ao_spi_get(uint8_t id, uint32_t speed) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + ao_mutex_get(&ao_spi_mutex[id]); + + /* Set the clock prescale */ + lpc_ssp->cpsr = speed; + + /* Enable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (1 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); +} + +void +ao_spi_put(uint8_t id) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + /* Disable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (0 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); + ao_mutex_put(&ao_spi_mutex[id]); +} + +static void +ao_spi_channel_init(uint8_t id) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + uint8_t d; + + lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) | + (LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) | + (0 << LPC_SSP_CR0_CPOL) | + (0 << LPC_SSP_CR0_CPHA) | + (0 << LPC_SSP_CR0_SCR)); + /* Drain the receive fifo */ + for (d = 0; d < LPC_SSP_FIFOSIZE; d++) + (void) lpc_ssp->dr; +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_0 + /* Configure pins */ + lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_SCK0); + lpc_ioconf.pio0_8 = ao_lpc_alternate(LPC_IOCONF_FUNC_MISO0); + lpc_ioconf.pio0_9 = ao_lpc_alternate(LPC_IOCONF_FUNC_MOSI0); + + /* Enable the device */ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP0); + + /* Turn on the clock */ + lpc_scb.ssp0clkdiv = 1; + + /* Reset the device */ + lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); + lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); + ao_spi_channel_init(0); +#endif + +#if HAS_SPI_1 + +#if SPI_SCK1_P1_15 + lpc_ioconf.pio1_15 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_15_SCK1); +#define HAS_SCK1 +#endif +#if SPI_SCK1_P1_20 + lpc_ioconf.pio1_20 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_20_SCK1); +#define HAS_SCK1 +#endif +#ifndef HAS_SCK1 +#error "No pin specified for SCK1" +#endif + +#if SPI_MISO1_P0_22 + lpc_ioconf.pio0_22 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_22_MISO1); +#define HAS_MISO1 +#endif +#if SPI_MISO1_P1_21 + lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_21_MISO1); +#define HAS_MISO1 +#endif +#ifndef HAS_MISO1 +#error "No pin specified for MISO1" +#endif + +#if SPI_MOSI1_P0_21 + lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); +#define HAS_MOSI1 +#endif +#if SPI_MOSI1_P1_22 + lpc_ioconf.pio1_22 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_22_MOSI1); +#define HAS_MOSI1 +#endif +#ifndef HAS_MOSI1 +#error "No pin specified for MOSI1" +#endif + + /* Enable the device */ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP1); + + /* Turn on the clock */ + lpc_scb.ssp1clkdiv = 1; + + /* De-assert reset */ + lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); + ao_spi_channel_init(1); +#endif /* HAS_SPI_1 */ +} -- cgit v1.2.3 From 15ca452b60271e3a0f7327216df04eef5b985240 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:14:16 -0700 Subject: altos: LPC interrupt priorities are just 0-3 Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index d9f72e1a..fb68f6be 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -111,10 +111,10 @@ extern const uint32_t ao_radio_cal; #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 +#define AO_LPC_NVIC_HIGH_PRIORITY 0 +#define AO_LPC_NVIC_CLOCK_PRIORITY 1 +#define AO_LPC_NVIC_MED_PRIORITY 2 +#define AO_LPC_NVIC_LOW_PRIORITY 3 void ao_adc_init(void); -- cgit v1.2.3 From 08887678f900adae81dcb1a7f5353d98d127aafd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:14:57 -0700 Subject: altos/lpc: Fix ao_enable_input, add ao_enable_analog Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 94d876f6..bc4c47ee 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -36,16 +36,29 @@ } while (0) #define ao_enable_input(port,bit,mode) do { \ + vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \ + vuint32_t _mode; \ 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); \ + _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \ else if (mode == AO_EXTI_MODE_PULL_DOWN) \ - stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN); \ + _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \ else \ - stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ + _mode = LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE; \ + *_ioconf = ((*_ioconf & ~(LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)) | \ + _mode | \ + (1 << LPC_IOCONF_ADMODE)); \ } while (0) +#define ao_enable_analog(port,bit) do { \ + vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \ + ao_enable_port(port); \ + lpc_gpio.dir[port] &= ~(1 << bit); \ + *_ioconf = *_ioconf & ~((1 << LPC_IOCONF_ADMODE) | \ + (LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)); \ + } while (0) + #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) static inline uint32_t -- cgit v1.2.3 From 2b0b7bf1462341718e582223a880f2dfcd79e2ad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:15:58 -0700 Subject: altos/lpc: Clean up broken IOCONF defines Missing comment closes Signed-off-by: Keith Packard --- src/lpc/lpc.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 4141f356..db825e93 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -137,7 +137,7 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_PIO0_7 0 #define LPC_IOCONF_FUNC_CTS 1 -/* PIO0_8 +/* PIO0_8 */ #define LPC_IOCONF_FUNC_PIO0_8 0 #define LPC_IOCONF_FUNC_MISO0 1 #define LPC_IOCONF_FUNC_CT16B0_MAT0 2 @@ -211,13 +211,13 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO0_21 */ #define LPC_IOCONF_FUNC_PIO0_21 0 #define LPC_IOCONF_FUNC_CT16B1_MAT0 1 -#define LPC_IOCONF_FUNC_MOSI1 2 +#define LPC_IOCONF_FUNC_PIO0_21_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 +#define LPC_IOCONF_FUNC_PIO0_22_MISO1 3 /* PIO0_23 */ #define LPC_IOCONF_FUNC_PIO0_23 0 @@ -284,7 +284,7 @@ extern struct lpc_ioconf lpc_ioconf; #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 +#define LPC_IOCONF_FUNC_PIO1_15_SCK1 3 /* PIO1_16 */ #define LPC_IOCONF_FUNC_PIO1_16 0 @@ -319,7 +319,7 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO1_22 */ #define LPC_IOCONF_FUNC_PIO1_22 0 #define LPC_IOCONF_FUNC_RI 1 -#define LPC_IOCONF_FUNC_MOSI1 2 +#define LPC_IOCONF_FUNC_PIO1_22_MOSI1 2 /* PIO1_23 */ #define LPC_IOCONF_FUNC_PIO1_23 0 @@ -359,6 +359,13 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_MASK 0x7 +#define ao_lpc_alternate(func) (((func) << LPC_IOCONF_FUNC) | \ + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | \ + (0 << LPC_IOCONF_HYS) | \ + (0 << LPC_IOCONF_INV) | \ + (0 << LPC_IOCONF_OD) | \ + 0x80) + #define LPC_IOCONF_MODE 3 #define LPC_IOCONF_MODE_INACTIVE 0 #define LPC_IOCONF_MODE_PULL_DOWN 1 @@ -369,6 +376,8 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_HYS 5 #define LPC_IOCONF_INV 6 +#define LPC_IOCONF_ADMODE 7 +#define LPC_IOCONF_FILTR 8 #define LPC_IOCONF_OD 10 struct lpc_scb { -- cgit v1.2.3 From ed25a46571d988ccf37ae915dff97b5f00bcf9cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:16:41 -0700 Subject: altos/lpc: add gpio int, spi, adc and ct32b defines to lpc.h Lots more devices Signed-off-by: Keith Packard --- src/lpc/lpc.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/lpc/registers.ld | 7 ++- 2 files changed, 165 insertions(+), 11 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index db825e93..2493a1ff 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -454,17 +454,9 @@ struct lpc_scb { vuint32_t irqlatency; /* 0x170 */ vuint32_t nmisrc; - vuint32_t pintsel0; - vuint32_t pintsel1; + vuint32_t pintsel[8]; - 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 usbclkctrl; /* 0x198 */ vuint32_t usbclkst; uint32_t r1a0[6*4]; /* 0x1a0 */ @@ -637,6 +629,18 @@ struct lpc_flash { extern struct lpc_flash lpc_flash; struct lpc_gpio_pin { + vuint32_t isel; /* 0x00 */ + vuint32_t ienr; + vuint32_t sienr; + vuint32_t cienr; + + vuint32_t ienf; /* 0x10 */ + vuint32_t sienf; + vuint32_t cienf; + vuint32_t rise; + + vuint32_t fall; /* 0x20 */ + vuint32_t ist; }; extern struct lpc_gpio_pin lpc_gpio_pin; @@ -1063,4 +1067,149 @@ struct arm_scb { extern struct arm_scb arm_scb; +struct lpc_ssp { + vuint32_t cr0; /* 0x00 */ + vuint32_t cr1; + vuint32_t dr; + vuint32_t sr; + + vuint32_t cpsr; /* 0x10 */ + vuint32_t imsc; + vuint32_t ris; + vuint32_t mis; + + vuint32_t icr; /* 0x20 */ +}; + +extern struct lpc_ssp lpc_ssp0, lpc_ssp1; + +#define LPC_NUM_SPI 2 + +#define LPC_SSP_FIFOSIZE 8 + +#define LPC_SSP_CR0_DSS 0 +#define LPC_SSP_CR0_DSS_4 0x3 +#define LPC_SSP_CR0_DSS_5 0x4 +#define LPC_SSP_CR0_DSS_6 0x5 +#define LPC_SSP_CR0_DSS_7 0x6 +#define LPC_SSP_CR0_DSS_8 0x7 +#define LPC_SSP_CR0_DSS_9 0x8 +#define LPC_SSP_CR0_DSS_10 0x9 +#define LPC_SSP_CR0_DSS_11 0xa +#define LPC_SSP_CR0_DSS_12 0xb +#define LPC_SSP_CR0_DSS_13 0xc +#define LPC_SSP_CR0_DSS_14 0xd +#define LPC_SSP_CR0_DSS_15 0xe +#define LPC_SSP_CR0_DSS_16 0xf +#define LPC_SSP_CR0_FRF 4 +#define LPC_SSP_CR0_FRF_SPI 0 +#define LPC_SSP_CR0_FRF_TI 1 +#define LPC_SSP_CR0_FRF_MICROWIRE 2 +#define LPC_SSP_CR0_CPOL 6 +#define LPC_SSP_CR0_CPOL_LOW 0 +#define LPC_SSP_CR0_CPOL_HIGH 1 +#define LPC_SSP_CR0_CPHA 7 +#define LPC_SSP_CR0_CPHA_FIRST 0 +#define LPC_SSP_CR0_CPHA_SECOND 1 +#define LPC_SSP_CR0_SCR 8 + +#define LPC_SSP_CR1_LBM 0 +#define LPC_SSP_CR1_SSE 1 +#define LPC_SSP_CR1_MS 2 +#define LPC_SSP_CR1_MS_MASTER 0 +#define LPC_SSP_CR1_MS_SLAVE 1 +#define LPC_SSP_CR1_SOD 3 + +#define LPC_SSP_SR_TFE 0 +#define LPC_SSP_SR_TNF 1 +#define LPC_SSP_SR_RNE 2 +#define LPC_SSP_SR_RFF 3 +#define LPC_SSP_SR_BSY 4 + +#define LPC_SSP_IMSC_RORIM 0 +#define LPC_SSP_IMSC_RTIM 1 +#define LPC_SSP_IMSC_RXIM 2 +#define LPC_SSP_IMSC_TXIM 3 + +#define LPC_SSP_RIS_RORRIS 0 +#define LPC_SSP_RIS_RTRIS 1 +#define LPC_SSP_RIS_RXRIS 2 +#define LPC_SSP_RIS_TXRIS 3 + +#define LPC_SSP_MIS_RORMIS 0 +#define LPC_SSP_MIS_RTMIS 1 +#define LPC_SSP_MIS_RXMIS 2 +#define LPC_SSP_MIS_TXMIS 3 + +#define LPC_SSP_ICR_RORIC 0 +#define LPC_SSP_ICR_RTIC 1 + +struct lpc_adc { + vuint32_t cr; /* 0x00 */ + vuint32_t gdr; + uint32_t r08; + vuint32_t inten; + + vuint32_t dr[8]; /* 0x10 */ + + vuint32_t stat; /* 0x30 */ +}; + +extern struct lpc_adc lpc_adc; + +#define LPC_ADC_CR_SEL 0 +#define LPC_ADC_CR_CLKDIV 8 +#define LPC_ADC_CR_BURST 16 +#define LPC_ADC_CR_CLKS 17 +#define LPC_ADC_CR_CLKS_11 0 +#define LPC_ADC_CR_CLKS_10 1 +#define LPC_ADC_CR_CLKS_9 2 +#define LPC_ADC_CR_CLKS_8 3 +#define LPC_ADC_CR_CLKS_7 4 +#define LPC_ADC_CR_CLKS_6 5 +#define LPC_ADC_CR_CLKS_5 6 +#define LPC_ADC_CR_CLKS_4 7 + +#define LPC_ADC_INTEN_ADINTEN 0 +#define LPC_ADC_INTEN_ADGINTEN 8 + +#define LPC_ADC_STAT_DONE 0 +#define LPC_ADC_STAT_OVERRUN 8 +#define LPC_ADC_STAT_ADINT 16 + +struct lpc_ct32b { + vuint32_t ir; /* 0x00 */ + vuint32_t tcr; + vuint32_t tc; + vuint32_t pr; + + vuint32_t pc; /* 0x10 */ + vuint32_t mcr; + vuint32_t mr[4]; /* 0x18 */ + vuint32_t ccr; /* 0x28 */ + vuint32_t cr0; + + vuint32_t cr1_0; /* 0x30 (only for ct32b0 */ + vuint32_t cr1_1; /* 0x34 (only for ct32b1 */ + uint32_t r38; + vuint32_t emr; + + uint32_t r40[12]; + + vuint32_t ctcr; /* 0x70 */ + vuint32_t pwmc; +}; + +extern struct lpc_ct32b lpc_ct32b0, lpc_ct32b1; + +#define LPC_CT32B_TCR_CEN 0 +#define LPC_CT32B_TCR_CRST 1 + +#define LPC_CT32B_MCR_MR0R 1 + +#define LPC_CT32B_PWMC_PWMEN0 0 +#define LPC_CT32B_PWMC_PWMEN1 1 +#define LPC_CT32B_PWMC_PWMEN2 2 +#define LPC_CT32B_PWMC_PWMEN3 3 + #endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index 0201e55f..51866e07 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -1,8 +1,14 @@ +lpc_usb_sram = 0x20004000; lpc_usart = 0x40008000; +lpc_ct32b0 = 0x40014000; +lpc_ct32b1 = 0x40018000; +lpc_adc = 0x4001c000; lpc_flash = 0x4003c000; +lpc_ssp0 = 0x40040000; lpc_ioconf = 0x40044000; lpc_scb = 0x40048000; lpc_gpio_pin = 0x4004c000; +lpc_ssp1 = 0x40058000; lpc_gpio_group0 = 0x4005c000; lpc_gpio_group1 = 0x40060000; lpc_usb = 0x40080000; @@ -10,4 +16,3 @@ lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; lpc_nvic = 0xe000e100; arm_scb = 0xe000ed00; -lpc_usb_sram = 0x20004000; -- cgit v1.2.3 From 166977c65bddb50d600a3c1e1f278c425b673697 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:18:19 -0700 Subject: altos/lpc: Add ADC driver Uses burst mode to get the whole set of values in one interrupt Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/lpc/ao_adc_lpc.c (limited to 'src/lpc') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c new file mode 100644 index 00000000..70e8b2d6 --- /dev/null +++ b/src/lpc/ao_adc_lpc.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +#ifndef AO_ADC_0 +#define AO_ADC_0 0 +#endif + +#ifndef AO_ADC_1 +#define AO_ADC_1 0 +#endif + +#ifndef AO_ADC_2 +#define AO_ADC_2 0 +#endif + +#ifndef AO_ADC_3 +#define AO_ADC_3 0 +#endif + +#ifndef AO_ADC_4 +#define AO_ADC_4 0 +#endif + +#ifndef AO_ADC_5 +#define AO_ADC_5 0 +#endif + +#ifndef AO_ADC_6 +#define AO_ADC_6 0 +#endif + +#ifndef AO_ADC_7 +#define AO_ADC_7 0 +#endif + +#if AO_ADC_7 +# define AO_ADC_LAST 7 +#else +# if AO_ADC_6 +# define AO_ADC_LAST 6 +# else +# if AO_ADC_5 +# define AO_ADC_LAST 5 +# else +# if AO_ADC_4 +# define AO_ADC_LAST 4 +# else +# if AO_ADC_3 +# define AO_ADC_LAST 3 +# else +# if AO_ADC_2 +# define AO_ADC_LAST 2 +# else +# if AO_ADC_1 +# define AO_ADC_LAST 1 +# else +# if AO_ADC_0 +# define AO_ADC_LAST 0 +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif + +static uint8_t ao_adc_ready; + +void lpc_adc_isr(void) +{ + uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc; + vuint32_t *in = &lpc_adc.dr[0]; + + /* Store converted values in packet */ + +#if AO_ADC_0 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_1 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_2 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_3 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_4 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_5 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_6 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_7 + *out++ = ((uint16_t) *in++) >> 1; +#endif + + AO_DATA_PRESENT(AO_DATA_ADC); + if (ao_data_present == AO_DATA_ALL) { +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; +#endif +#if HAS_MMA655X + ao_data_ring[ao_data_head].mma655x = ao_mma655x_current; +#endif +#if HAS_HMC5883 + ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; +#endif +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif + ao_data_ring[ao_data_head].tick = ao_tick_count; + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); + } + ao_adc_ready = 1; +} + +#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ + (AO_ADC_1 << 1) | \ + (AO_ADC_2 << 2) | \ + (AO_ADC_3 << 3) | \ + (AO_ADC_4 << 4) | \ + (AO_ADC_5 << 5) | \ + (AO_ADC_6 << 6) | \ + (AO_ADC_7 << 7)) + +#define AO_ADC_CLKDIV (AO_LPC_CLKOUT / 4500000) + +/* + * Start the ADC sequence using the DMA engine + */ +void +ao_adc_poll(void) +{ + if (!ao_adc_ready) + return; + ao_adc_ready = 0; + + lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (1 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); +} + +static void +ao_adc_dump(void) __reentrant +{ + struct ao_data packet; + int16_t *d; + uint8_t i; + + ao_data_get(&packet); +#ifdef AO_ADC_DUMP + AO_ADC_DUMP(&packet); +#else + printf("tick: %5u", packet.tick); + d = (int16_t *) (&packet.adc); + for (i = 0; i < AO_NUM_ADC; i++) + printf (" %2d: %5d", i, d[i]); + printf("\n"); +#endif +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC); + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD); + + /* Enable interrupt when last channel is complete */ + lpc_adc.inten = (1 << AO_ADC_LAST); + + lpc_nvic_set_enable(LPC_ISR_ADC_POS); + lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); +#if AO_ADC_0 + ao_enable_analog(0, 11); +#endif +#if AO_ADC_1 + ao_enable_analog(0, 12); +#endif +#if AO_ADC_2 + ao_enable_analog(0, 13); +#endif +#if AO_ADC_3 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_4 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_5 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_6 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_7 + ao_enable_analog(0, 14); +#endif + ao_cmd_register(&ao_adc_cmds[0]); + + ao_adc_ready = 1; +} -- cgit v1.2.3 From c0d0147251bfcebd753196b74c22c00c3116fd22 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:18:55 -0700 Subject: altos/lpc: Add beep driver Hardwired to our current beeper pin Signed-off-by: Keith Packard --- src/lpc/ao_beep_lpc.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/lpc/ao_beep_lpc.c (limited to 'src/lpc') diff --git a/src/lpc/ao_beep_lpc.c b/src/lpc/ao_beep_lpc.c new file mode 100644 index 00000000..281f981f --- /dev/null +++ b/src/lpc/ao_beep_lpc.c @@ -0,0 +1,83 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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" + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + lpc_ct32b1.tcr = ((0 << LPC_CT32B_TCR_CEN) | + (1 << LPC_CT32B_TCR_CRST)); + lpc_scb.sysahbclkctrl &= ~(1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); + } else { + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); + + /* Set prescaler to match cc1111 clocks + */ + lpc_ct32b1.pc = AO_LPC_CLKOUT / 750000 - 1; + + /* Write the desired data in the match registers */ + + /* Reset after two time units */ + lpc_ct32b1.mr[0] = beep << 1; + + /* Flip output after one time unit */ + lpc_ct32b1.mr[1] = beep; + + /* Reset on match 0 */ + lpc_ct32b1.mcr = (1 << LPC_CT32B_MCR_MR0R); + + /* PWM on match 1 */ + lpc_ct32b1.pwmc = (1 << LPC_CT32B_PWMC_PWMEN1); + + /* timer mode */ + lpc_ct32b1.ctcr = 0; + + /* And turn the timer on */ + lpc_ct32b1.tcr = ((1 << LPC_CT32B_TCR_CEN) | + (1 << LPC_CT32B_TCR_CRST)); + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on c32b1_mat1 + * which is on pin pio0_14 + */ + + lpc_ioconf.pio0_14 = ((LPC_IOCONF_FUNC_PIO0_14_CT32B1_MAT1 << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD)); + + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); + + /* Disable the counter and reset the value */ + lpc_ct32b1.tcr = ((0 << LPC_CT32B_TCR_CEN) | + (1 << LPC_CT32B_TCR_CRST)); +} -- cgit v1.2.3 From f5218e2544dcb659aec6c3adee50d61cab1bba3a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:19:41 -0700 Subject: altos/lpc: Add pin interrupt driver Signed-off-by: Keith Packard --- src/lpc/ao_exti.h | 47 ++++++++++++++++ src/lpc/ao_exti_lpc.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 src/lpc/ao_exti.h create mode 100644 src/lpc/ao_exti_lpc.c (limited to 'src/lpc') diff --git a/src/lpc/ao_exti.h b/src/lpc/ao_exti.h new file mode 100644 index 00000000..cbe63eaa --- /dev/null +++ b/src/lpc/ao_exti.h @@ -0,0 +1,47 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 + +void +ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)()); + +void +ao_exti_set_mode(uint8_t gpio, uint8_t pin, uint8_t mode); + +void +ao_exti_set_callback(uint8_t gpio, uint8_t pin, void (*callback)()); + +void +ao_exti_enable(uint8_t gpio, uint8_t pin); + +void +ao_exti_disable(uint8_t gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c new file mode 100644 index 00000000..2e42dabb --- /dev/null +++ b/src/lpc/ao_exti_lpc.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +#define LPC_NUM_PINS 56 +#define LPC_NUM_PINT 8 + +static void (*ao_exti_callback[LPC_NUM_PINT])(void); + +static uint8_t ao_pint_map[LPC_NUM_PINS]; +static uint8_t ao_pint_mode[LPC_NUM_PINS]; +static uint8_t ao_pint_inuse; +static uint8_t ao_pint_enabled; + +static void +ao_exti_isr(uint8_t pint) +{ + uint8_t mask = 1 << pint; + + if (lpc_gpio_pin.ist & mask) { + lpc_gpio_pin.ist = mask; + + (*ao_exti_callback) (); + } +} + +#define pin_isr(n) void lpc_pin_int ## n ## _isr(void) { ao_exti_isr(n); } +pin_isr(0) +pin_isr(1) +pin_isr(2) +pin_isr(3) +pin_isr(4) +pin_isr(5) +pin_isr(6) +pin_isr(7) + +#define pin_id(port,pin) ((port) * 24 + (pin)); + +void +ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint8_t id = pin_id(port,pin); + uint8_t pint; + uint32_t mask; + uint8_t prio; + + for (pint = 0; pint < LPC_NUM_PINT; pint++) + if ((ao_pint_inuse & (1 << pint)) == 0) + break; + if (pint == LPC_NUM_PINT) + ao_panic(AO_PANIC_EXTI); + + mask = (1 << pint); + ao_pint_inuse |= mask; + ao_pint_enabled &= ~mask; + + ao_pint_map[id] = pint; + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + lpc_scb.pintsel[pint] = id; + + ao_enable_input(port, pin, mode); + + /* Set edge triggered */ + lpc_gpio_pin.isel &= ~mask; + + ao_exti_set_mode(port, pin, mode); + + /* Set interrupt mask and rising/falling mode */ + + prio = AO_LPC_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_LPC_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_LPC_NVIC_HIGH_PRIORITY; + + /* Set priority and enable */ + lpc_nvic_set_priority(LPC_ISR_PIN_INT0_POS + pint, prio); + lpc_nvic_set_enable(LPC_ISR_PIN_INT0_POS + pint); +} + +void +ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) { + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + uint8_t mask = 1 << pint; + + ao_pint_mode[pint] = mode; + + if (mode & AO_EXTI_MODE_RISING) + lpc_gpio_pin.sienr = mask; + else + lpc_gpio_pin.cienr = mask; + + if (mode & AO_EXTI_MODE_FALLING) + lpc_gpio_pin.sienf = mask; + else + lpc_gpio_pin.cienf = mask; +} + +void +ao_exti_set_callback(uint8_t port, uint8_t pin, void (*callback)()) { + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + + ao_exti_callback[pint] = callback; +} + +void +ao_exti_enable(uint8_t port, uint8_t pin) +{ + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + uint8_t mask = 1 << pint; + + ao_pint_enabled |= mask; + ao_exti_set_mode(port, pin, ao_pint_mode[pint]); +} + +void +ao_exti_disable(uint8_t port, uint8_t pin) { + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + uint8_t mask = 1 << pint; + + ao_pint_enabled &= ~mask; + lpc_gpio_pin.cienr = mask; + lpc_gpio_pin.cienf = mask; +} + +void +ao_exti_init(void) +{ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_PINT); +} -- cgit v1.2.3 From 5311720525ac73e9d42067b68adf25fc2e054af5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:21:20 -0700 Subject: altos/lpc: Try a smaller stack. Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index fb68f6be..92405649 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,7 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 512 +#define AO_STACK_SIZE 192 #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From c4991db4809ae547fdb245e3cb42517fa7524de5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:21:43 -0700 Subject: altos/lpc: Use separate interrupt stack Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index bc4c47ee..3cd873ec 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -208,4 +208,17 @@ ao_spi_init(void); } \ } while (0) +#define HAS_ARCH_START_SCHEDULER 1 + +static inline void ao_arch_start_scheduler(void) { + uint32_t sp; + uint32_t control; + + asm("mrs %0,msp" : "=&r" (sp)); + asm("msr psp,%0" : : "r" (sp)); + asm("mrs %0,control" : "=&r" (control)); + control |= (1 << 1); + asm("msr control,%0" : : "r" (control)); +} + #endif /* _AO_ARCH_FUNCS_H_ */ -- cgit v1.2.3 From cbe5eee76faf386eefe69539935ab318944ac452 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:52:14 -0700 Subject: altos/lpc: Stick USB control structure in USB memory No reason to have that in regular ram, and it means we've got space for large enough stacks now Signed-off-by: Keith Packard --- src/lpc/altos.ld | 11 ++++++++--- src/lpc/ao_arch.h | 2 +- src/lpc/ao_usb_lpc.c | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index bcfba1ea..2778797a 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -17,8 +17,9 @@ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K - ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 512 - stack (!w) : ORIGIN = 0x10000000 + 4K - 512, LENGTH = 512 + ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 + usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 + stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128 } INCLUDE registers.ld @@ -63,9 +64,13 @@ SECTIONS { *(COMMON) __bss_end__ = .; } >ram + PROVIDE(end = .); + + .usb : { + *(.usb) + } > usb PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); - PROVIDE(end = .); } ENTRY(start); diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 92405649..9dbebf4a 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,7 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 192 +#define AO_STACK_SIZE 320 #define AO_LED_TYPE uint16_t diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 0f881720..cd896724 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -81,6 +81,7 @@ static uint8_t ao_usb_tx_count; static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; +__attribute__((section(".usb"))) static struct lpc_usb_endpoint lpc_usb_endpoint __attribute((aligned(256))); /* Marks when we don't need to send an IN packet. -- cgit v1.2.3 From 098fd43a740ee2a782f82b6b71965b60cdba2d62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:00:24 -0700 Subject: altos/lpc: Make EXTI code work. Clear rise/fall bits in ISR to avoid re-entering. Block interrupts around enable/disable bits. Create shared _ao_exti_set_enable function to control mask changes. Signed-off-by: Keith Packard --- src/lpc/ao_exti_lpc.c | 64 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 20 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c index 2e42dabb..ce98b4ad 100644 --- a/src/lpc/ao_exti_lpc.c +++ b/src/lpc/ao_exti_lpc.c @@ -35,8 +35,10 @@ ao_exti_isr(uint8_t pint) if (lpc_gpio_pin.ist & mask) { lpc_gpio_pin.ist = mask; + lpc_gpio_pin.rise = mask; + lpc_gpio_pin.fall = mask; - (*ao_exti_callback) (); + (*ao_exti_callback[pint]) (); } } @@ -52,6 +54,30 @@ pin_isr(7) #define pin_id(port,pin) ((port) * 24 + (pin)); +static void +_ao_exti_set_enable(uint8_t pint) +{ + uint8_t mask = 1 << pint; + uint8_t mode; + + if (ao_pint_enabled & mask) + mode = ao_pint_mode[pint]; + else + mode = 0; + + if (mode & AO_EXTI_MODE_RISING) + lpc_gpio_pin.sienr = mask; + else + lpc_gpio_pin.cienr = mask; + + if (mode & AO_EXTI_MODE_FALLING) + lpc_gpio_pin.sienf = mask; + else + lpc_gpio_pin.cienf = mask; + lpc_gpio_pin.rise = mask; + lpc_gpio_pin.fall = mask; +} + void ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) { uint8_t id = pin_id(port,pin); @@ -65,22 +91,23 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) if (pint == LPC_NUM_PINT) ao_panic(AO_PANIC_EXTI); + ao_arch_block_interrupts(); mask = (1 << pint); ao_pint_inuse |= mask; ao_pint_enabled &= ~mask; ao_pint_map[id] = pint; - ao_exti_callback[pin] = callback; + ao_exti_callback[pint] = callback; /* configure gpio to interrupt routing */ lpc_scb.pintsel[pint] = id; - ao_enable_input(port, pin, mode); - /* Set edge triggered */ lpc_gpio_pin.isel &= ~mask; - ao_exti_set_mode(port, pin, mode); + ao_pint_enabled &= ~mask; + ao_pint_mode[pint] = mode; + _ao_exti_set_enable(pint); /* Set interrupt mask and rising/falling mode */ @@ -93,25 +120,19 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) /* Set priority and enable */ lpc_nvic_set_priority(LPC_ISR_PIN_INT0_POS + pint, prio); lpc_nvic_set_enable(LPC_ISR_PIN_INT0_POS + pint); + ao_arch_release_interrupts(); } void -ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) { +ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) +{ uint8_t id = pin_id(port,pin); uint8_t pint = ao_pint_map[id]; - uint8_t mask = 1 << pint; + ao_arch_block_interrupts(); ao_pint_mode[pint] = mode; - - if (mode & AO_EXTI_MODE_RISING) - lpc_gpio_pin.sienr = mask; - else - lpc_gpio_pin.cienr = mask; - - if (mode & AO_EXTI_MODE_FALLING) - lpc_gpio_pin.sienf = mask; - else - lpc_gpio_pin.cienf = mask; + _ao_exti_set_enable(pint); + ao_arch_release_interrupts(); } void @@ -129,8 +150,10 @@ ao_exti_enable(uint8_t port, uint8_t pin) uint8_t pint = ao_pint_map[id]; uint8_t mask = 1 << pint; + ao_arch_block_interrupts(); ao_pint_enabled |= mask; - ao_exti_set_mode(port, pin, ao_pint_mode[pint]); + _ao_exti_set_enable(pint); + ao_arch_release_interrupts(); } void @@ -139,9 +162,10 @@ ao_exti_disable(uint8_t port, uint8_t pin) { uint8_t pint = ao_pint_map[id]; uint8_t mask = 1 << pint; + ao_arch_block_interrupts(); ao_pint_enabled &= ~mask; - lpc_gpio_pin.cienr = mask; - lpc_gpio_pin.cienf = mask; + _ao_exti_set_enable(pint); + ao_arch_release_interrupts(); } void -- cgit v1.2.3 From 35a05041d3ca3e69a146bd3bf8038c0f1cbc1b42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:04:29 -0700 Subject: altos: Add EXTI_PIN_NOCONFIGURE to exti interface, use for MS5607 This asks the EXTI code to not mess with the pin configuration so that the MS5607 driver can get interrupts on the MISO pin while still using it for SPI. Signed-off-by: Keith Packard --- src/attiny/ao_exti.h | 1 + src/drivers/ao_ms5607.c | 12 ++---------- src/lpc/ao_exti.h | 1 + src/lpc/ao_exti_lpc.c | 3 +++ src/stm/ao_exti.h | 1 + src/stm/ao_exti_stm.c | 30 ++++++++++++++++-------------- 6 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src/lpc') diff --git a/src/attiny/ao_exti.h b/src/attiny/ao_exti.h index 2ea4f47d..85bb2fba 100644 --- a/src/attiny/ao_exti.h +++ b/src/attiny/ao_exti.h @@ -30,5 +30,6 @@ ao_exti_setup_port(uint8_t pin, uint8_t mode, void (*callback)(void)); #define ao_exti_init() #define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_PIN_NOCONFIGURE 0 #endif /* _AO_EXTI_H_ */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 0eece584..8f1dcbe1 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -247,17 +247,9 @@ ao_ms5607_init(void) */ ao_exti_setup(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN, - AO_EXTI_MODE_RISING, + AO_EXTI_MODE_RISING| + AO_EXTI_PIN_NOCONFIGURE, ao_ms5607_isr); - -#ifdef STM_MODER_ALTERNATE - /* Reset the pin from INPUT to ALTERNATE so that SPI works - * This needs an abstraction at some point... - */ - stm_moder_set(AO_MS5607_MISO_PORT, - AO_MS5607_MISO_PIN, - STM_MODER_ALTERNATE); -#endif } #endif diff --git a/src/lpc/ao_exti.h b/src/lpc/ao_exti.h index cbe63eaa..e8599eb4 100644 --- a/src/lpc/ao_exti.h +++ b/src/lpc/ao_exti.h @@ -25,6 +25,7 @@ #define AO_EXTI_PRIORITY_LOW 16 #define AO_EXTI_PRIORITY_MED 0 #define AO_EXTI_PRIORITY_HIGH 32 +#define AO_EXTI_PIN_NOCONFIGURE 64 void ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c index ce98b4ad..588cf58c 100644 --- a/src/lpc/ao_exti_lpc.c +++ b/src/lpc/ao_exti_lpc.c @@ -91,6 +91,9 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) if (pint == LPC_NUM_PINT) ao_panic(AO_PANIC_EXTI); + if (!mode & AO_EXTI_PIN_NOCONFIGURE) + ao_enable_input(port, pin, mode); + ao_arch_block_interrupts(); mask = (1 << pint); ao_pint_inuse |= mask; diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 35b56b57..ebea224d 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -25,6 +25,7 @@ #define AO_EXTI_PRIORITY_LOW 16 #define AO_EXTI_PRIORITY_MED 0 #define AO_EXTI_PRIORITY_HIGH 32 +#define AO_EXTI_PIN_NOCONFIGURE 64 void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 1361d0d4..c1dcdf85 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -70,21 +70,23 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback /* configure gpio to interrupt routing */ stm_exticr_set(gpio, pin); - /* configure pin as input, setting selected pull-up/down mode */ - stm_moder_set(gpio, pin, STM_MODER_INPUT); - switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { - case 0: - default: - pupdr = STM_PUPDR_NONE; - break; - case AO_EXTI_MODE_PULL_UP: - pupdr = STM_PUPDR_PULL_UP; - break; - case AO_EXTI_MODE_PULL_DOWN: - pupdr = STM_PUPDR_PULL_DOWN; - break; + if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) { + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); } - stm_pupdr_set(gpio, pin, pupdr); /* Set interrupt mask and rising/falling mode */ stm_exti.imr &= ~mask; -- cgit v1.2.3 From 6343bd774f542a4f915cf1fca2053d03e93bf2c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:06:03 -0700 Subject: altos/lpc: Don't use loader to place USB endpoint data in USB ram Instead, just assign a fixed address in registers.ld. This avoids a confusing section in the elf file. Signed-off-by: Keith Packard --- src/lpc/altos.ld | 4 ---- src/lpc/ao_usb_lpc.c | 3 +-- src/lpc/registers.ld | 1 + 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 2778797a..4d6f35a8 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -66,10 +66,6 @@ SECTIONS { } >ram PROVIDE(end = .); - .usb : { - *(.usb) - } > usb - PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); } diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index cd896724..8070acc3 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -81,8 +81,7 @@ static uint8_t ao_usb_tx_count; static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; -__attribute__((section(".usb"))) -static struct lpc_usb_endpoint lpc_usb_endpoint __attribute((aligned(256))); +extern struct lpc_usb_endpoint lpc_usb_endpoint; /* Marks when we don't need to send an IN packet. * This happens only when the last IN packet is not full, diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index 51866e07..a523c39c 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -1,4 +1,5 @@ lpc_usb_sram = 0x20004000; +lpc_usb_endpoint = 0x20004700; lpc_usart = 0x40008000; lpc_ct32b0 = 0x40014000; lpc_ct32b1 = 0x40018000; -- cgit v1.2.3 From d51c9fda3478f205e4bcdf1b7bf21eb1e0a516bc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:07:52 -0700 Subject: altos/lpc: Pull ADC data from the correct registers Was just stepping through register space arbitrarily, which would have worked for EasyMini, but might have failed later if the ADC pin usage wasn't consecutive. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 70e8b2d6..9ecc7c13 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -86,34 +86,38 @@ static uint8_t ao_adc_ready; void lpc_adc_isr(void) { + uint32_t stat = lpc_adc.stat; uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc; vuint32_t *in = &lpc_adc.dr[0]; + lpc_adc.cr = 0; + lpc_adc.stat = 0; + /* Store converted values in packet */ #if AO_ADC_0 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[0] >> 1; #endif #if AO_ADC_1 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[1] >> 1; #endif #if AO_ADC_2 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[2] >> 1; #endif #if AO_ADC_3 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[3] >> 1; #endif #if AO_ADC_4 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[4] >> 1; #endif #if AO_ADC_5 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[5] >> 1; #endif #if AO_ADC_6 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[6] >> 1; #endif #if AO_ADC_7 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[7] >> 1; #endif AO_DATA_PRESENT(AO_DATA_ADC); -- cgit v1.2.3 From a78012782c779de3433b91e6b854b2fdbd7230fd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:17:48 -0700 Subject: altos/lpc: SPI runs off main clock (48MHz), not sysclk (24MHz) Update SPI speed definitions to match Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 9dbebf4a..f605e3d2 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -127,14 +127,13 @@ ao_serial_init(void); /* SPI definitions */ -#define AO_SPI_SPEED_12MHz 2 -#define AO_SPI_SPEED_6MHz 4 -#define AO_SPI_SPEED_4MHz 6 -#define AO_SPI_SPEED_2MHz 12 -#define AO_SPI_SPEED_1MHz 24 -#define AO_SPI_SPEED_500kHz 48 -#define AO_SPI_SPEED_250kHz 96 -#define AO_SPI_SPEED_125kHz 192 +#define AO_SPI_SPEED_12MHz 4 +#define AO_SPI_SPEED_6MHz 8 +#define AO_SPI_SPEED_4MHz 12 +#define AO_SPI_SPEED_2MHz 24 +#define AO_SPI_SPEED_1MHz 48 +#define AO_SPI_SPEED_500kHz 96 +#define AO_SPI_SPEED_250kHz 192 #define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz -- cgit v1.2.3 From 3fe11b277dd7268eb445d120c8f9537f95148891 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:18:44 -0700 Subject: altos/lpc: Missing parens around ao_gpio_set macro Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 3cd873ec..204d1227 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -25,7 +25,7 @@ #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_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)]) -- cgit v1.2.3 From 07d261c08214837b5d5cac4d2be43e51a0c47868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:19:15 -0700 Subject: altos/lpc: Fix beeper driver Set prescale limit, not current prescale value (pr instead of pc). Flip output 1 on PWM match (set emc toggle for channel 1). Don't hold counter in reset (turn off CRST bit). Signed-off-by: Keith Packard --- src/lpc/ao_beep_lpc.c | 10 +++++++--- src/lpc/lpc.h | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_beep_lpc.c b/src/lpc/ao_beep_lpc.c index 281f981f..eb9132b8 100644 --- a/src/lpc/ao_beep_lpc.c +++ b/src/lpc/ao_beep_lpc.c @@ -29,16 +29,19 @@ ao_beep(uint8_t beep) /* Set prescaler to match cc1111 clocks */ - lpc_ct32b1.pc = AO_LPC_CLKOUT / 750000 - 1; + lpc_ct32b1.pr = AO_LPC_SYSCLK / 750000 - 1; /* Write the desired data in the match registers */ /* Reset after two time units */ lpc_ct32b1.mr[0] = beep << 1; - /* Flip output after one time unit */ + /* PWM width is half of that */ lpc_ct32b1.mr[1] = beep; + /* Flip output 1 on PWM match */ + lpc_ct32b1.emr = (LPC_CT32B_EMR_EMC_TOGGLE << LPC_CT32B_EMR_EMC1); + /* Reset on match 0 */ lpc_ct32b1.mcr = (1 << LPC_CT32B_MCR_MR0R); @@ -50,7 +53,7 @@ ao_beep(uint8_t beep) /* And turn the timer on */ lpc_ct32b1.tcr = ((1 << LPC_CT32B_TCR_CEN) | - (1 << LPC_CT32B_TCR_CRST)); + (0 << LPC_CT32B_TCR_CRST)); } } @@ -73,6 +76,7 @@ ao_beep_init(void) (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | (0 << LPC_IOCONF_HYS) | (0 << LPC_IOCONF_INV) | + (1 << LPC_IOCONF_ADMODE) | (0 << LPC_IOCONF_OD)); lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 2493a1ff..1b48fcc9 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -1212,4 +1212,14 @@ extern struct lpc_ct32b lpc_ct32b0, lpc_ct32b1; #define LPC_CT32B_PWMC_PWMEN2 2 #define LPC_CT32B_PWMC_PWMEN3 3 +#define LPC_CT32B_EMR_EMC0 4 +#define LPC_CT32B_EMR_EMC1 6 +#define LPC_CT32B_EMR_EMC2 8 +#define LPC_CT32B_EMR_EMC3 10 + +#define LPC_CT32B_EMR_EMC_NOTHING 0 +#define LPC_CT32B_EMR_EMC_CLEAR 1 +#define LPC_CT32B_EMR_EMC_SET 2 +#define LPC_CT32B_EMR_EMC_TOGGLE 3 + #endif /* _LPC_H_ */ -- cgit v1.2.3 From e383d7a28d01729c50f933ceda77ea767d1b8087 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:22:20 -0700 Subject: altos/lpc: Create TX/RX busy macros for SPI driver Check for both fifo status *and* device busy to make sure the device is idle before we touch any registers. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 05688f52..e7edca4c 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -23,21 +23,25 @@ static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 } static uint8_t spi_dev_null; +#define tx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_TNF))) != (1 << LPC_SSP_SR_TNF) +#define rx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_RNE))) != (1 << LPC_SSP_SR_RNE) + #define spi_loop(len, put, get) do { \ while (len--) { \ /* Wait for space in the fifo */ \ - while ((lpc_ssp->sr & (1 << LPC_SSP_SR_TNF)) == 0) \ + while (tx_busy(lpc_ssp)) \ ; \ + \ /* send a byte */ \ lpc_ssp->dr = put; \ \ + /* Wait for byte to appear in the fifo */ \ + while (rx_busy(lpc_ssp)) \ + ; \ + \ /* recv a byte */ \ get lpc_ssp->dr; \ } \ - \ - /* Wait for the fifo to drain */ \ - while ((lpc_ssp->sr & (1 << LPC_SSP_SR_BSY))) \ - ; \ } while (0); void -- cgit v1.2.3 From 397109139fb9ff27ec7cfb0cafa65d1dbea053bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:24:11 -0700 Subject: altos/lpc: Leave SPI enabled all the time Might be able to turn it off with some care; more experimentation required. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index e7edca4c..7c830053 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -89,24 +89,11 @@ ao_spi_get(uint8_t id, uint32_t speed) /* Set the clock prescale */ lpc_ssp->cpsr = speed; - - /* Enable the device */ - lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | - (1 << LPC_SSP_CR1_SSE) | - (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | - (0 << LPC_SSP_CR1_SOD)); } void ao_spi_put(uint8_t id) { - struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - - /* Disable the device */ - lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | - (0 << LPC_SSP_CR1_SSE) | - (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | - (0 << LPC_SSP_CR1_SOD)); ao_mutex_put(&ao_spi_mutex[id]); } @@ -121,6 +108,13 @@ ao_spi_channel_init(uint8_t id) (0 << LPC_SSP_CR0_CPOL) | (0 << LPC_SSP_CR0_CPHA) | (0 << LPC_SSP_CR0_SCR)); + + /* Enable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (1 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); + /* Drain the receive fifo */ for (d = 0; d < LPC_SSP_FIFOSIZE; d++) (void) lpc_ssp->dr; -- cgit v1.2.3 From b9bb088a36fd351809f4c378356327ffa663c974 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:25:13 -0700 Subject: altos/lpc: Allow for alternate SPI SCLK0 pin usage SPI SCLK0 can appear on three different pins; let the application configure which one it wants. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 1 + src/lpc/ao_spi_lpc.c | 16 +++++++++++++++- src/lpc/lpc.h | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/lpc') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 5bcd4673..2307d7d2 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -53,6 +53,7 @@ /* SPI */ #define HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 #define HAS_SPI_1 1 #define SPI_SCK1_P1_15 1 #define SPI_MISO1_P0_22 1 diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 7c830053..12d44872 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -125,7 +125,21 @@ ao_spi_init(void) { #if HAS_SPI_0 /* Configure pins */ - lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_SCK0); +#if SPI_SCK0_P0_6 + lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_6_SCK0); +#define HAS_SCK0 +#endif +#if SPI_SCK0_P0_10 + lpc_ioconf.pio0_10 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_10_SCK0); +#define HAS_SCK0 +#endif +#if SPI_SCK0_P1_29 + lpc_ioconf.pio1_29 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_29_SCK0); +#define HAS_SCK0 +#endif +#ifndef HAS_SCK0 +#error "No pin specified for SCK0" +#endif lpc_ioconf.pio0_8 = ao_lpc_alternate(LPC_IOCONF_FUNC_MISO0); lpc_ioconf.pio0_9 = ao_lpc_alternate(LPC_IOCONF_FUNC_MOSI0); diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 1b48fcc9..49034c1c 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -131,7 +131,7 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO0_6 */ #define LPC_IOCONF_FUNC_PIO0_6 0 #define LPC_IOCONF_FUNC_USB_CONNECT 1 -#define LPC_IOCONF_FUNC_SCK0 2 +#define LPC_IOCONF_FUNC_PIO0_6_SCK0 2 /* PIO0_7 */ #define LPC_IOCONF_FUNC_PIO0_7 0 @@ -150,7 +150,7 @@ extern struct lpc_ioconf lpc_ioconf; /* 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_PIO0_10_SCK0 2 #define LPC_IOCONF_FUNC_CT16B0_MAT2 3 /* PIO0_11 */ -- cgit v1.2.3 From e0ad8b5b5e1b4c7a9ffba9d25f3c32ce708c3ec5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:26:07 -0700 Subject: altos/lpc: Configuring wrong pin for SPI1 MOSI Was setting configuration for PIO1_21 instead of PIO0_21. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 12d44872..ff107e40 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -182,7 +182,7 @@ ao_spi_init(void) #endif #if SPI_MOSI1_P0_21 - lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); + lpc_ioconf.pio0_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); #define HAS_MOSI1 #endif #if SPI_MOSI1_P1_22 -- cgit v1.2.3 From c1f01cd4406063191a51cb68fc4634eabfc60fc2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:27:05 -0700 Subject: altos/lpc: Reset SPI device at startup time Wasn't doing the reset sequence correctly (write 0, then write 1). Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index ff107e40..c3587698 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -199,7 +199,8 @@ ao_spi_init(void) /* Turn on the clock */ lpc_scb.ssp1clkdiv = 1; - /* De-assert reset */ + /* Reset the device */ + lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); ao_spi_channel_init(1); #endif /* HAS_SPI_1 */ -- cgit v1.2.3 From 35b120c4154df0351c3a802f86dda224a7643068 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:27:53 -0700 Subject: altos/lpc: Force idle mode if USB gets an address during boot time This lets EasyMini be booted to idle mode by simply plugging it into USB. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 8070acc3..aac0df04 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -605,8 +605,14 @@ ao_usb_ep0_handle(uint8_t receive) /* Wait until the IN packet is received from addr 0 * before assigning our local address */ - if (ao_usb_address_pending) + if (ao_usb_address_pending) { +#if HAS_FLIGHT + /* Go to idle mode if USB is connected + */ + ao_flight_force_idle = 1; +#endif ao_usb_set_address(ao_usb_address); + } if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) ao_usb_ep0_flush(); } -- cgit v1.2.3 From 7361371190bf3805b6d0414e61f697aca7c7cff1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Jun 2013 04:38:11 -0700 Subject: altos/lpc: Make ADC inputs work They're still very unstable (bouncing around a lot), but at least they seem to report useful stuff now. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 52 +++++++++++++++++++++++++++++-------------------- src/lpc/ao_arch_funcs.h | 18 +++++++++++++---- 2 files changed, 45 insertions(+), 25 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 9ecc7c13..25a121b5 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -82,19 +82,33 @@ # endif #endif +#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ + (AO_ADC_1 << 1) | \ + (AO_ADC_2 << 2) | \ + (AO_ADC_3 << 3) | \ + (AO_ADC_4 << 4) | \ + (AO_ADC_5 << 5) | \ + (AO_ADC_6 << 6) | \ + (AO_ADC_7 << 7)) + +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000 - 1) + static uint8_t ao_adc_ready; void lpc_adc_isr(void) { uint32_t stat = lpc_adc.stat; - uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc; - vuint32_t *in = &lpc_adc.dr[0]; + uint16_t *out; - lpc_adc.cr = 0; + lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (0 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); lpc_adc.stat = 0; /* Store converted values in packet */ + out = (uint16_t *) &ao_data_ring[ao_data_head].adc; #if AO_ADC_0 *out++ = lpc_adc.dr[0] >> 1; #endif @@ -141,16 +155,6 @@ void lpc_adc_isr(void) ao_adc_ready = 1; } -#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ - (AO_ADC_1 << 1) | \ - (AO_ADC_2 << 2) | \ - (AO_ADC_3 << 3) | \ - (AO_ADC_4 << 4) | \ - (AO_ADC_5 << 5) | \ - (AO_ADC_6 << 6) | \ - (AO_ADC_7 << 7)) - -#define AO_ADC_CLKDIV (AO_LPC_CLKOUT / 4500000) /* * Start the ADC sequence using the DMA engine @@ -204,29 +208,35 @@ ao_adc_init(void) lpc_nvic_set_enable(LPC_ISR_ADC_POS); lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); #if AO_ADC_0 - ao_enable_analog(0, 11); + ao_enable_analog(0, 11, 0); #endif #if AO_ADC_1 - ao_enable_analog(0, 12); + ao_enable_analog(0, 12, 1); #endif #if AO_ADC_2 - ao_enable_analog(0, 13); + ao_enable_analog(0, 13, 2); #endif #if AO_ADC_3 - ao_enable_analog(0, 14); + ao_enable_analog(0, 14, 3); #endif #if AO_ADC_4 - ao_enable_analog(0, 14); + ao_enable_analog(0, 15, 4); #endif #if AO_ADC_5 - ao_enable_analog(0, 14); + ao_enable_analog(0, 16, 5); #endif #if AO_ADC_6 - ao_enable_analog(0, 14); + ao_enable_analog(0, 22, 6); #endif #if AO_ADC_7 - ao_enable_analog(0, 14); + ao_enable_analog(0, 23, 7); #endif + + lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (0 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); + ao_cmd_register(&ao_adc_cmds[0]); ao_adc_ready = 1; diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 204d1227..179b2f4d 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -51,12 +51,22 @@ (1 << LPC_IOCONF_ADMODE)); \ } while (0) -#define ao_enable_analog(port,bit) do { \ - vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \ +#define lpc_token_paster_2(x,y) x ## y +#define lpc_token_evaluator_2(x,y) lpc_token_paster_2(x,y) +#define lpc_token_paster_3(x,y,z) x ## y ## z +#define lpc_token_evaluator_3(x,y,z) lpc_token_paster_3(x,y,z) +#define lpc_token_paster_4(w,x,y,z) w ## x ## y ## z +#define lpc_token_evaluator_4(w,x,y,z) lpc_token_paster_4(w,x,y,z) +#define analog_reg(port,bit) lpc_token_evaluator_4(pio,port,_,bit) +#define analog_func(id) lpc_token_evaluator_2(LPC_IOCONF_FUNC_AD,id) + +#define ao_enable_analog(port,bit,id) do { \ + uint32_t _mode; \ ao_enable_port(port); \ lpc_gpio.dir[port] &= ~(1 << bit); \ - *_ioconf = *_ioconf & ~((1 << LPC_IOCONF_ADMODE) | \ - (LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)); \ + _mode = ((analog_func(id) << LPC_IOCONF_FUNC) | \ + (0 << LPC_IOCONF_ADMODE)); \ + lpc_ioconf.analog_reg(port,bit) = _mode; \ } while (0) #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) -- cgit v1.2.3 From be9ee9ed2d041c4ab4e77ee2010fe3c7a1ca6597 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jun 2013 01:20:49 -0700 Subject: altos/lpc: Filter ADC inputs They're amazingly noisy on EasyMini, so just filter them as the only thing we use them for is battery and pyro numbers. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 39 +++++++++++++++++++++++++-------------- src/lpc/ao_arch_funcs.h | 6 ++---- src/lpc/lpc.h | 7 +++++++ 3 files changed, 34 insertions(+), 18 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 25a121b5..40173aa4 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -91,47 +91,58 @@ (AO_ADC_6 << 6) | \ (AO_ADC_7 << 7)) -#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000 - 1) +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000) -static uint8_t ao_adc_ready; +static uint8_t ao_adc_ready; + +static uint16_t ao_adc_prev[AO_NUM_ADC]; + +#define sample(id) do { \ + uint16_t p = *prev; \ + uint16_t v = lpc_adc.dr[id]; \ + p -= p >> 4; \ + p += v >> 4; \ + *prev++ = p; \ + *out++ = p >> 1; \ + } while (0) void lpc_adc_isr(void) { uint32_t stat = lpc_adc.stat; uint16_t *out; + uint16_t *prev; - lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | - (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | - (0 << LPC_ADC_CR_BURST) | - (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); + /* Turn off burst mode */ + lpc_adc.cr = 0; lpc_adc.stat = 0; /* Store converted values in packet */ out = (uint16_t *) &ao_data_ring[ao_data_head].adc; + prev = ao_adc_prev; #if AO_ADC_0 - *out++ = lpc_adc.dr[0] >> 1; + sample(0); #endif #if AO_ADC_1 - *out++ = lpc_adc.dr[1] >> 1; + sample(1); #endif #if AO_ADC_2 - *out++ = lpc_adc.dr[2] >> 1; + sample(2); #endif #if AO_ADC_3 - *out++ = lpc_adc.dr[3] >> 1; + sample(3); #endif #if AO_ADC_4 - *out++ = lpc_adc.dr[4] >> 1; + sample(4); #endif #if AO_ADC_5 - *out++ = lpc_adc.dr[5] >> 1; + sample(5); #endif #if AO_ADC_6 - *out++ = lpc_adc.dr[6] >> 1; + sample(6); #endif #if AO_ADC_7 - *out++ = lpc_adc.dr[7] >> 1; + sample(7); #endif AO_DATA_PRESENT(AO_DATA_ADC); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 179b2f4d..1bbb14f5 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -61,12 +61,10 @@ #define analog_func(id) lpc_token_evaluator_2(LPC_IOCONF_FUNC_AD,id) #define ao_enable_analog(port,bit,id) do { \ - uint32_t _mode; \ ao_enable_port(port); \ lpc_gpio.dir[port] &= ~(1 << bit); \ - _mode = ((analog_func(id) << LPC_IOCONF_FUNC) | \ - (0 << LPC_IOCONF_ADMODE)); \ - lpc_ioconf.analog_reg(port,bit) = _mode; \ + lpc_ioconf.analog_reg(port,bit) = ((analog_func(id) << LPC_IOCONF_FUNC) | \ + (0 << LPC_IOCONF_ADMODE)); \ } while (0) #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 49034c1c..d66f0dd0 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -1169,6 +1169,13 @@ extern struct lpc_adc lpc_adc; #define LPC_ADC_CR_CLKS_6 5 #define LPC_ADC_CR_CLKS_5 6 #define LPC_ADC_CR_CLKS_4 7 +#define LPC_ADC_CR_START 24 +#define LPC_ADC_CR_START_NONE 0 +#define LPC_ADC_CR_START_NOW 1 + +#define LPC_ADC_GDR_CHN 24 +#define LPC_ADC_GDR_OVERRUN 30 +#define LPC_ADC_GDR_DONE 31 #define LPC_ADC_INTEN_ADINTEN 0 #define LPC_ADC_INTEN_ADGINTEN 8 -- cgit v1.2.3 From 1676c7dbc3dcce2962be9ef9a58d37c7b48e3c0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 15:07:54 -0700 Subject: altos/lpc: Turn off more clocks, disable USART for easymini Try to reduce noise on the power supply. Signed-off-by: Keith Packard --- src/easymini-v0.1/Makefile | 1 - src/easymini-v0.1/ao_pins.h | 2 +- src/lpc/ao_timer_lpc.c | 11 +++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src/lpc') diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile index 612cc472..dfa7624c 100644 --- a/src/easymini-v0.1/Makefile +++ b/src/easymini-v0.1/Makefile @@ -39,7 +39,6 @@ ALTOS_SRC = \ ao_config.c \ ao_timer_lpc.c \ ao_exti_lpc.c \ - ao_serial_lpc.c \ ao_usb_lpc.c \ ao_spi_lpc.c \ ao_adc_lpc.c \ diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index d4fbe7a1..e14e1eb4 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -43,7 +43,7 @@ /* USART */ -#define HAS_SERIAL 1 +#define HAS_SERIAL 0 #define USE_SERIAL_0_STDIN 1 #define SERIAL_0_18_19 1 #define SERIAL_0_14_15 0 diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 51835baa..73a0e258 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -177,4 +177,15 @@ ao_clock_init(void) lpc_scb.ssp1clkdiv = 0; lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; + + /* Power down everything we don't need */ + lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | + (1 << LPC_SCB_PDRUNCFG_IRC_PD) | + (1 << LPC_SCB_PDRUNCFG_BOD_PD) | + (1 << LPC_SCB_PDRUNCFG_ADC_PD) | + (1 << LPC_SCB_PDRUNCFG_WDTOSC_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPLL_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | + (1 << 11) | + (7 << 13)); } -- cgit v1.2.3 From d040adeef9df4cda31dce603db81dc7ce19ec0d1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 22:31:31 -0700 Subject: altos/lpc: Don't disable all of the clocks just yet, USB doesn't work Signed-off-by: Keith Packard --- src/lpc/ao_timer_lpc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lpc') diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 73a0e258..62235d1e 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -178,6 +178,7 @@ ao_clock_init(void) lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; +#if 0 /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | @@ -188,4 +189,5 @@ ao_clock_init(void) (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | (1 << 11) | (7 << 13)); +#endif } -- cgit v1.2.3 From dcf769198863c1b0f1b05f41d0c052a3dbfef247 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 22:31:58 -0700 Subject: altos/lpc: Remove spurious semicolon Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index c3587698..a889137c 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -42,7 +42,7 @@ static uint8_t spi_dev_null; /* recv a byte */ \ get lpc_ssp->dr; \ } \ - } while (0); + } while (0) void ao_spi_send(void *block, uint16_t len, uint8_t id) -- cgit v1.2.3 From 298e54856b5f8809b43f24407caa4a6be60822f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Jun 2013 14:00:11 -0700 Subject: altos/lpc: Get the IRC turned off after boot time This involved carefully moving the USB away from the IRC before turning it off. Signed-off-by: Keith Packard --- src/lpc/ao_timer_lpc.c | 17 ++++++++++++++--- src/lpc/ao_usb_lpc.c | 10 +++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 62235d1e..c0de90a3 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -106,12 +106,18 @@ ao_clock_init(void) /* Switch to the IRC clock */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; - lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) ; + /* Switch USB to the main clock */ + 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); + while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_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) @@ -178,7 +184,13 @@ ao_clock_init(void) lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; -#if 0 + /* Switch USB PLL source to system osc so we can power down the IRC */ + lpc_scb.usbpllclksel = (LPC_SCB_USBPLLCLKSEL_SEL_SYSOSC << LPC_SCB_USBPLLCLKSEL_SEL); + lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) + ; + /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | @@ -189,5 +201,4 @@ ao_clock_init(void) (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | (1 << 11) | (7 << 13)); -#endif } diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index aac0df04..e574f1e2 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -834,8 +834,9 @@ ao_usb_disable(void) /* Turn off USB clock */ lpc_scb.usbclkdiv = 0; - /* Disable USB PHY */ - lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + /* Disable USB PHY and PLL */ + lpc_scb.pdruncfg |= ((1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPLL_PD)); /* Disable USB registers and RAM */ lpc_scb.sysahbclkctrl &= ~((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | @@ -877,7 +878,6 @@ ao_usb_enable(void) lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); lpc_scb.usbpllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); - lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) @@ -887,6 +887,10 @@ ao_usb_enable(void) ; lpc_scb.usbclksel = 0; + lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); + lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); + while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA))) + ; /* Turn on USB clock, use 48MHz clock unchanged */ lpc_scb.usbclkdiv = 1; -- cgit v1.2.3 From 025beb0fea011d0e3dab59b5d16e7ffae97c613c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Jun 2013 14:52:32 -0700 Subject: altos/lpc: Get rid of ADC filter Now that the source of the Vcc noise has been identified, remove the unnecessary ADC filtering. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 40173aa4..874d2d29 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -95,22 +95,12 @@ static uint8_t ao_adc_ready; -static uint16_t ao_adc_prev[AO_NUM_ADC]; - -#define sample(id) do { \ - uint16_t p = *prev; \ - uint16_t v = lpc_adc.dr[id]; \ - p -= p >> 4; \ - p += v >> 4; \ - *prev++ = p; \ - *out++ = p >> 1; \ - } while (0) +#define sample(id) (*out++ = lpc_adc.dr[id] >> 1) void lpc_adc_isr(void) { uint32_t stat = lpc_adc.stat; uint16_t *out; - uint16_t *prev; /* Turn off burst mode */ lpc_adc.cr = 0; @@ -119,7 +109,6 @@ void lpc_adc_isr(void) /* Store converted values in packet */ out = (uint16_t *) &ao_data_ring[ao_data_head].adc; - prev = ao_adc_prev; #if AO_ADC_0 sample(0); #endif -- cgit v1.2.3 From 23f11b188fc6aacd29e7f01a7d8a40853b7655df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Jun 2013 19:39:27 -0700 Subject: altos/lpc: Enable brown-out-detector Make sure the processor does something sensible when the power disappears. Signed-off-by: Keith Packard --- src/lpc/ao_timer_lpc.c | 11 ++++++++++- src/lpc/lpc.h | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index c0de90a3..44fb410e 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -100,6 +100,15 @@ ao_clock_init(void) (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) | (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON)); + /* Enable the brown-out detection at the highest voltage to + * make sure the flash part remains happy + */ + + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_BOD_PD); + lpc_scb.bodctrl = ((LPC_SCB_BOD_BODRSTLEV_2_63 << LPC_SCB_BOD_BODRSTLEV) | + (LPC_SCB_BOD_BODINTVAL_RESERVED << LPC_SCB_BOD_BODINTVAL) | + (1 << LPC_SCB_BOD_BODRSTENA)); + /* Turn the IRC clock back on */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); ao_clock_delay(); @@ -194,7 +203,7 @@ ao_clock_init(void) /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | - (1 << LPC_SCB_PDRUNCFG_BOD_PD) | + (0 << LPC_SCB_PDRUNCFG_BOD_PD) | (1 << LPC_SCB_PDRUNCFG_ADC_PD) | (1 << LPC_SCB_PDRUNCFG_WDTOSC_PD) | (1 << LPC_SCB_PDRUNCFG_USBPLL_PD) | diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index d66f0dd0..f13ec615 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -609,6 +609,18 @@ extern struct lpc_scb lpc_scb; #define LPC_SCB_CLKOUTUEN_ENA 0 +#define LPC_SCB_BOD_BODRSTLEV 0 +# define LPC_SCB_BOD_BODRSTLEV_1_46 0 +# define LPC_SCB_BOD_BODRSTLEV_2_06 1 +# define LPC_SCB_BOD_BODRSTLEV_2_35 2 +# define LPC_SCB_BOD_BODRSTLEV_2_63 3 +#define LPC_SCB_BOD_BODINTVAL 2 +# define LPC_SCB_BOD_BODINTVAL_RESERVED 0 +# define LPC_SCB_BOD_BODINTVAL_2_22 1 +# define LPC_SCB_BOD_BODINTVAL_2_52 2 +# define LPC_SCB_BOD_BODINTVAL_2_80 3 +#define LPC_SCB_BOD_BODRSTENA 4 + #define LPC_SCB_PDRUNCFG_IRCOUT_PD 0 #define LPC_SCB_PDRUNCFG_IRC_PD 1 #define LPC_SCB_PDRUNCFG_FLASH_PD 2 -- cgit v1.2.3 From 9081d881bc48bf7fdce617d300ac02c1a5962239 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Jun 2013 19:40:03 -0700 Subject: altos/lpc: Remove ao_usb_task structure It's not used Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index e574f1e2..4e6b9c66 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -35,8 +35,6 @@ #define debug_data(format, args...) #endif -struct ao_task ao_usb_task; - struct ao_usb_setup { uint8_t dir_type_recip; uint8_t request; -- cgit v1.2.3 From 58eda6f873f5d6e8e219f769bdf67ce4dbc96fd7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Jun 2013 19:40:59 -0700 Subject: altos/lpc: Don't disable all interrupts when disabling one interrupt The nvic iser and icer registers read value indicates all enabled interrupts, icer writes disable the set interrupts. Re-writing icer with the current value ends up disabling all interrupts, not exactly what we wanted. Signed-off-by: Keith Packard --- src/lpc/lpc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index f13ec615..8fb78649 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -1014,12 +1014,12 @@ extern struct lpc_nvic lpc_nvic; static inline void lpc_nvic_set_enable(int irq) { - lpc_nvic.iser |= (1 << irq); + lpc_nvic.iser = (1 << irq); } static inline void lpc_nvic_clear_enable(int irq) { - lpc_nvic.icer |= (1 << irq); + lpc_nvic.icer = (1 << irq); } static inline int -- cgit v1.2.3 From 0dd148e388944d8d265da51d62806c4a00b2c13d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 24 Jun 2013 14:23:53 -0700 Subject: altos/lpc: Add boot loader Support the USB boot loader, add USB pull-up support. Signed-off-by: Keith Packard --- src/easymini-v0.1/Makefile | 5 +- src/easymini-v0.1/ao_pins.h | 5 ++ src/easymini-v0.1/flash-loader/Makefile | 8 +++ src/easymini-v0.1/flash-loader/ao_pins.h | 33 +++++++++++++ src/lpc/altos-loader.ld | 80 ++++++++++++++++++++++++++++++ src/lpc/altos-standalone.ld | 85 ++++++++++++++++++++++++++++++++ src/lpc/altos.ld | 26 ++++++++-- src/lpc/ao_arch.h | 4 ++ src/lpc/ao_arch_funcs.h | 16 ++++-- src/lpc/ao_boot.h | 39 +++++++++++++++ src/lpc/ao_boot_chain.c | 67 +++++++++++++++++++++++++ src/lpc/ao_boot_pin.c | 46 +++++++++++++++++ src/lpc/ao_flash.h | 30 +++++++++++ src/lpc/ao_flash_loader_lpc.c | 32 ++++++++++++ src/lpc/ao_flash_lpc_pins.h | 32 ++++++++++++ src/lpc/ao_interrupt.c | 27 ++++++++-- src/lpc/ao_usb_lpc.c | 27 ++++++++-- src/lpc/lpc.h | 5 ++ src/product/ao_flash_pins.h | 2 + src/product/ao_flash_task.c | 13 ++--- 20 files changed, 557 insertions(+), 25 deletions(-) create mode 100644 src/easymini-v0.1/flash-loader/Makefile create mode 100644 src/easymini-v0.1/flash-loader/ao_pins.h create mode 100644 src/lpc/altos-loader.ld create mode 100644 src/lpc/altos-standalone.ld create mode 100644 src/lpc/ao_boot.h create mode 100644 src/lpc/ao_boot_chain.c create mode 100644 src/lpc/ao_boot_pin.c create mode 100644 src/lpc/ao_flash.h create mode 100644 src/lpc/ao_flash_loader_lpc.c create mode 100644 src/lpc/ao_flash_lpc_pins.h (limited to 'src/lpc') diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile index dfa7624c..9847656c 100644 --- a/src/easymini-v0.1/Makefile +++ b/src/easymini-v0.1/Makefile @@ -18,6 +18,7 @@ INC = \ # ALTOS_SRC = \ ao_interrupt.c \ + ao_boot_chain.c \ ao_romconfig.c \ ao_product.c \ ao_mutex.c \ @@ -48,7 +49,7 @@ ALTOS_SRC = \ PRODUCT=EasyMini-v0.1 PRODUCT_DEF=-DEASYMINI_V_0_1 -IDPRODUCT=0x000a +IDPRODUCT=0x0026 CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os @@ -62,7 +63,7 @@ all: $(PROG) LDFLAGS=-L../lpc -Wl,-Taltos.ld -$(PROG): Makefile $(OBJ) +$(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ao_product.h: ao-make-product.5c ../Version diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index e14e1eb4..6f102dbe 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #define HAS_BEEP 1 #define HAS_LED 1 +#define IS_FLASH_LOADER 0 + /* Crystal on the board */ #define AO_LPC_CLKIN 12000000 @@ -38,6 +40,9 @@ #define HAS_USB_CONNECT 0 #define HAS_USB_VBUS 0 +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 #define PACKET_HAS_SLAVE 0 diff --git a/src/easymini-v0.1/flash-loader/Makefile b/src/easymini-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..ab828b22 --- /dev/null +++ b/src/easymini-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=easymini-v0.1 +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/easymini-v0.1/flash-loader/ao_pins.h b/src/easymini-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..4330151d --- /dev/null +++ b/src/easymini-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_PINS_H_ +#define _AO_PINS_H_ + +#include + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#endif /* _AO_PINS_H_ */ diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld new file mode 100644 index 00000000..4f78f552 --- /dev/null +++ b/src/lpc/altos-loader.ld @@ -0,0 +1,80 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 : ORIGIN = 0x00000000, LENGTH = 4K + ram : ORIGIN = 0x10000000, LENGTH = 4k - 128 - 32 + usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 + stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128 +} + +INCLUDE registers.ld + +EXTERN (lpc_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .interrupt : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + } > rom + + .text ORIGIN(rom) + 0x100 : { + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + + *(.text*) /* Executable code */ + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.rodata*) /* Constants */ + __text_end__ = .; + } > rom + + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : { + __boot_start__ = .; + *(.boot) + __boot_end__ = .; + } >ram + + /* Data -- relocated to RAM, but written to ROM + */ + .data : { + __data_start__ = .; + *(.data) /* initialized data */ + __data_end__ = .; + } >ram AT>rom + + + .bss : { + __bss_start__ = .; + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); +} + +ENTRY(start); diff --git a/src/lpc/altos-standalone.ld b/src/lpc/altos-standalone.ld new file mode 100644 index 00000000..032406f8 --- /dev/null +++ b/src/lpc/altos-standalone.ld @@ -0,0 +1,85 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 - 128 - 32 + usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 + stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128 +} + +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 + + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot (NOLOAD) : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram + + /* 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(end = .); + + PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); +} + +ENTRY(start); + + diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 4d6f35a8..00d4f18a 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -16,7 +16,7 @@ */ MEMORY { - rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K + rom (rx) : ORIGIN = 0x00001000, LENGTH = 28K ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128 @@ -31,11 +31,15 @@ SECTIONS { * Rom contents */ - .text ORIGIN(rom) : { - __text_start__ = .; + .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) { + __interrupt_start__ = .; + __interrupt_rom__ = ORIGIN(rom); *(.interrupt) /* Interrupt vectors */ + __interrupt_end__ = .; + } > ram - . = ORIGIN(rom) + 0x100; + .text ORIGIN(rom) + 0x100 : { + __text_start__ = .; ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) @@ -50,9 +54,20 @@ SECTIONS { __text_end__ = .; } > rom + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram + /* Data -- relocated to RAM, but written to ROM */ - .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { __data_start__ = .; *(.data) /* initialized data */ __data_end__ = .; @@ -60,6 +75,7 @@ SECTIONS { } >ram .bss : { + __bss_start__ = .; *(.bss) *(COMMON) __bss_end__ = .; diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index f605e3d2..a8d3cfc4 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -137,4 +137,8 @@ ao_serial_init(void); #define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x00001000) +#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x00000000) +#define HAS_BOOT_LOADER 1 + #endif /* _AO_ARCH_H_ */ diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 1bbb14f5..9a3219a2 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -22,12 +22,13 @@ #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1< + * + * 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_BOOT_H_ +#define _AO_BOOT_H_ + +void +ao_boot_chain(uint32_t *base); + +void +ao_boot_check_pin(void); + +/* Return true to switch to application (if present) */ +int +ao_boot_check_chain(void); + +void +ao_boot_reboot(uint32_t *base); + +static inline void +ao_boot_loader(void) { + ao_boot_reboot(AO_BOOT_LOADER_BASE); +} + +#endif /* _AO_BOOT_H_ */ diff --git a/src/lpc/ao_boot_chain.c b/src/lpc/ao_boot_chain.c new file mode 100644 index 00000000..a08d1f2c --- /dev/null +++ b/src/lpc/ao_boot_chain.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include + +void +ao_boot_chain(uint32_t *base) +{ + uint32_t sp; + uint32_t pc; + + sp = base[0]; + pc = base[1]; + if (0x00000100 <= pc && pc <= 0x00008000 && (pc & 1) == 1) { + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); + } +} + +#define AO_BOOT_SIGNAL 0x5a5aa5a5 +#define AO_BOOT_CHECK 0xc3c33c3c + +struct ao_boot { + uint32_t *base; + uint32_t signal; + uint32_t check; +}; + +static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; + +int +ao_boot_check_chain(void) +{ + if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) { + ao_boot.signal = 0; + ao_boot.check = 0; + if (ao_boot.base == 0) + return 0; + ao_boot_chain(ao_boot.base); + } + return 1; +} + +void +ao_boot_reboot(uint32_t *base) +{ + ao_boot.base = base; + ao_boot.signal = AO_BOOT_SIGNAL; + ao_boot.check = AO_BOOT_CHECK; + ao_arch_reboot(); +} diff --git a/src/lpc/ao_boot_pin.c b/src/lpc/ao_boot_pin.c new file mode 100644 index 00000000..51ecc0a9 --- /dev/null +++ b/src/lpc/ao_boot_pin.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include +#include + +void +ao_boot_check_pin(void) +{ + uint16_t v; + + /* Enable power interface clock */ +// stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Enable the input pin */ + ao_enable_input(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, + AO_BOOT_APPLICATION_MODE); + + for (v = 0; v < 100; v++) + ao_arch_nop(); + + /* Read the value */ + v = ao_gpio_get(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, AO_BOOT_APPLICATION); + + /* Reset the chip to turn off the port and the power interface clock */ + ao_gpio_set_mode(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); + ao_disable_port(AO_BOOT_APPLICATION_GPIO); +// stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); + if (v == AO_BOOT_APPLICATION_VALUE) + ao_boot_chain(AO_BOOT_APPLICATION_BASE); +} diff --git a/src/lpc/ao_flash.h b/src/lpc/ao_flash.h new file mode 100644 index 00000000..aaf66b39 --- /dev/null +++ b/src/lpc/ao_flash.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_H_ +#define _AO_FLASH_H_ + +uint32_t +ao_flash_erase_page(uint8_t *page); + +uint32_t +ao_flash_page(uint8_t *page, uint8_t *src); + +uint32_t +ao_lpc_read_part_id(void); + +#endif /* _AO_FLASH_H_ */ diff --git a/src/lpc/ao_flash_loader_lpc.c b/src/lpc/ao_flash_loader_lpc.c new file mode 100644 index 00000000..2ab548cf --- /dev/null +++ b/src/lpc/ao_flash_loader_lpc.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_usb_init(); + + ao_flash_task(); + return 0; +} diff --git a/src/lpc/ao_flash_lpc_pins.h b/src/lpc/ao_flash_lpc_pins.h new file mode 100644 index 00000000..e2243d5c --- /dev/null +++ b/src/lpc/ao_flash_lpc_pins.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_FLASH_LPC_PINS_H_ +#define _AO_FLASH_LPC_PINS_H_ + +#include + +/* 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 + +#endif /* _AO_FLASH_STM_PINS_H_ */ diff --git a/src/lpc/ao_interrupt.c b/src/lpc/ao_interrupt.c index b5e67007..c4dc7867 100644 --- a/src/lpc/ao_interrupt.c +++ b/src/lpc/ao_interrupt.c @@ -17,12 +17,25 @@ #include #include +#include + +#ifndef IS_FLASH_LOADER +#error Should define IS_FLASH_LOADER +#define IS_FLASH_LOADER 0 +#endif + +#if !IS_FLASH_LOADER +#define RELOCATE_INTERRUPT 1 +#endif 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__; +#if RELOCATE_INTERRUPT +extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__; +#endif /* Interrupt functions */ @@ -35,10 +48,18 @@ void lpc_ignore_isr(void) { } -int x; - void start(void) { - x = 0; +#ifdef AO_BOOT_CHAIN + if (ao_boot_check_chain()) { +#ifdef AO_BOOT_PIN + ao_boot_check_pin(); +#endif + } +#endif +#if RELOCATE_INTERRUPT + memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__); + lpc_scb.sysmemremap = LPC_SCB_SYSMEMREMAP_MAP_RAM << LPC_SCB_SYSMEMREMAP_MAP; +#endif memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); main(); diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 4e6b9c66..144d1075 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -19,6 +19,16 @@ #include "ao_usb.h" #include "ao_product.h" +#ifndef USE_USB_STDIO +#define USE_USB_STDIO 1 +#endif + +#if USE_USB_STDIO +#define AO_USB_OUT_SLEEP_ADDR (&ao_stdin_ready) +#else +#define AO_USB_OUT_SLEEP_ADDR (&ao_usb_out_avail) +#endif + #define USB_DEBUG 0 #define USB_DEBUG_DATA 0 #define USB_ECHO 0 @@ -652,7 +662,7 @@ lpc_usb_irq_isr(void) _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP)); ao_usb_out_avail = 1; _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); + ao_wakeup(AO_USB_OUT_SLEEP_ADDR) _rx_dbg0("stdin awoken"); } @@ -811,7 +821,7 @@ ao_usb_getchar(void) ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_stdin_ready); + ao_sleep(AO_USB_OUT_SLEEP_ADDR); ao_arch_release_interrupts(); return c; } @@ -821,6 +831,9 @@ ao_usb_disable(void) { ao_arch_block_interrupts(); +#if HAS_USB_PULLUP + ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0); +#endif /* Disable interrupts */ lpc_usb.inten = 0; @@ -923,6 +936,10 @@ ao_usb_enable(void) for (t = 0; t < 1000; t++) ao_arch_nop(); +#if HAS_USB_PULLUP + ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1); +#endif + ao_usb_set_ep0(); } @@ -959,6 +976,10 @@ __code struct ao_cmds ao_usb_cmds[] = { void ao_usb_init(void) { +#if HAS_USB_PULLUP + ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0); +#endif + ao_usb_enable(); debug ("ao_usb_init\n"); @@ -968,7 +989,7 @@ ao_usb_init(void) #if USB_DEBUG ao_cmd_register(&ao_usb_cmds[0]); #endif -#if !USB_ECHO +#if USE_USB_STDIO ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif } diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 8fb78649..3300c86f 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -486,6 +486,11 @@ struct lpc_scb { extern struct lpc_scb lpc_scb; +#define LPC_SCB_SYSMEMREMAP_MAP 0 +# define LPC_SCB_SYSMEMREMAP_MAP_BOOT_LOADER 0 +# define LPC_SCB_SYSMEMREMAP_MAP_RAM 1 +# define LPC_SCB_SYSMEMREMAP_MAP_FLASH 2 + #define LPC_SCB_PRESETCTRL_SSP0_RST_N 0 #define LPC_SCB_PRESETCTRL_I2C_RST_N 1 #define LPC_SCB_PRESETCTRL_SSP1_RST_N 2 diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h index b774df6d..439ba75c 100644 --- a/src/product/ao_flash_pins.h +++ b/src/product/ao_flash_pins.h @@ -37,4 +37,6 @@ #define AO_BOOT_CHAIN 1 #define AO_BOOT_PIN 1 +#define IS_FLASH_LOADER 1 + #endif /* _AO_FLASH_PINS_H_ */ diff --git a/src/product/ao_flash_task.c b/src/product/ao_flash_task.c index fdc4d0aa..4cfbf75f 100644 --- a/src/product/ao_flash_task.c +++ b/src/product/ao_flash_task.c @@ -73,7 +73,7 @@ static void ao_block_erase(void) { uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; + void *p = (void *) addr; ao_flash_erase_page(p); } @@ -82,11 +82,8 @@ static void ao_block_write(void) { uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; - union { - uint8_t data8[256]; - uint32_t data32[64]; - } u; + void *p = (void *) addr; + uint8_t data[256]; uint16_t i; if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { @@ -94,8 +91,8 @@ ao_block_write(void) return; } for (i = 0; i < 256; i++) - u.data8[i] = ao_usb_getchar(); - ao_flash_page(p, u.data32); + data[i] = ao_usb_getchar(); + ao_flash_page(p, (void *) data); } static void -- cgit v1.2.3 From c542a2ed0f222bd0ec84e4a9651585d441dd7ccf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 24 Jun 2013 14:29:01 -0700 Subject: altos/lpc: Rename serial port to 'serial0' This lets existing serial port users find the right function. Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index c0424699..d6b0082a 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -67,7 +67,7 @@ lpc_usart_isr(void) } int -_ao_serial_pollchar(void) +_ao_serial0_pollchar(void) { int c; @@ -82,18 +82,18 @@ _ao_serial_pollchar(void) } char -ao_serial_getchar(void) +ao_serial0_getchar(void) { int c; ao_arch_block_interrupts(); - while ((c = _ao_serial_pollchar()) == AO_READ_AGAIN) + while ((c = _ao_serial0_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_usart_rx_fifo); ao_arch_release_interrupts(); return (char) c; } void -ao_serial_putchar(char c) +ao_serial0_putchar(char c) { ao_arch_block_interrupts(); while (ao_fifo_full(ao_usart_tx_fifo)) @@ -104,7 +104,7 @@ ao_serial_putchar(char c) } void -ao_serial_drain(void) +ao_serial0_drain(void) { ao_arch_block_interrupts(); while (!ao_fifo_empty(ao_usart_tx_fifo)) @@ -115,7 +115,7 @@ ao_serial_drain(void) #include "ao_serial_lpc.h" void -ao_serial_set_speed(uint8_t speed) +ao_serial0_set_speed(uint8_t speed) { if (speed > AO_SERIAL_SPEED_115200) return; @@ -193,7 +193,7 @@ ao_serial_init(void) lpc_usart.hden = ((0 << LPC_USART_HDEN_HDEN)); /* Set baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_9600); + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); /* Enable interrupts */ lpc_usart.ier = ((1 << LPC_USART_IER_RBRINTEN) | -- cgit v1.2.3 From a0dd93ccf0920260b41c4003955617fd0cd1c8b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:43:18 +0200 Subject: altos: Set default LPC stack to 512 bytes, Em to 384 bytes The default for lpc has been raised to 512 bytes, but Em doesn't have enough RAM for that. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 2 ++ src/lpc/ao_arch.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 6f102dbe..c09fb4c2 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #define HAS_BEEP 1 #define HAS_LED 1 +#define AO_STACK_SIZE 384 + #define IS_FLASH_LOADER 0 /* Crystal on the board */ diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index a8d3cfc4..d04bf2c8 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,9 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 320 +#ifndef AO_STACK_SIZE +#define AO_STACK_SIZE 512 +#endif #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 0dd55f66d79f54b450fd8122aecd84d68b810bf4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:45:06 +0200 Subject: altos: Wake up on LPC usart ISR only once Instead of waking up after every character, wait until the FIFO is empty to reduce overhead Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index d6b0082a..431ae98a 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -49,21 +49,25 @@ _ao_serial_tx_start(void) void lpc_usart_isr(void) { + uint8_t wake_input = 0; (void) lpc_usart.iir_fcr; while (lpc_usart.lsr & (1 << LPC_USART_LSR_RDR)) { char c = lpc_usart.rbr_thr; 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); + wake_input = 1; } if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; _ao_serial_tx_start(); ao_wakeup(&ao_usart_tx_fifo); } + if (wake_input) { + ao_wakeup(&ao_usart_rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); + } } int -- cgit v1.2.3 From 1aed2eb5c7d477a2f3d4fada22980041aba97cb8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Aug 2013 11:22:10 -0700 Subject: altos/lpc: Stop using burst mode for LPC ADC Burst mode doesn't stop after one round of conversions, so we end up getting incorrect values in whatever the last conversion register is. Just use single conversions and take an interrupt per channel. Also, slow down the ADC so that our values are more stable -- just need to make sure we get the whole conversion sequence done 100 times a second. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 119 ++++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 73 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 874d2d29..7005f86e 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -50,89 +50,65 @@ #define AO_ADC_7 0 #endif -#if AO_ADC_7 -# define AO_ADC_LAST 7 -#else -# if AO_ADC_6 -# define AO_ADC_LAST 6 -# else -# if AO_ADC_5 -# define AO_ADC_LAST 5 -# else -# if AO_ADC_4 -# define AO_ADC_LAST 4 -# else -# if AO_ADC_3 -# define AO_ADC_LAST 3 -# else -# if AO_ADC_2 -# define AO_ADC_LAST 2 -# else -# if AO_ADC_1 -# define AO_ADC_LAST 1 -# else -# if AO_ADC_0 -# define AO_ADC_LAST 0 -# endif -# endif -# endif -# endif -# endif -# endif -# endif -#endif - -#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ - (AO_ADC_1 << 1) | \ - (AO_ADC_2 << 2) | \ - (AO_ADC_3 << 3) | \ - (AO_ADC_4 << 4) | \ - (AO_ADC_5 << 5) | \ - (AO_ADC_6 << 6) | \ - (AO_ADC_7 << 7)) - -#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000) - -static uint8_t ao_adc_ready; +#define AO_ADC_NUM (AO_ADC_0 + AO_ADC_1 + AO_ADC_2 + AO_ADC_3 + \ + AO_ADC_4 + AO_ADC_5 + AO_ADC_6 + AO_ADC_7) -#define sample(id) (*out++ = lpc_adc.dr[id] >> 1) - -void lpc_adc_isr(void) -{ - uint32_t stat = lpc_adc.stat; - uint16_t *out; - - /* Turn off burst mode */ - lpc_adc.cr = 0; - lpc_adc.stat = 0; +/* ADC clock is divided by this value + 1, which ensures that + * the ADC clock will be strictly less than 4.5MHz as required + */ +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 450000) - /* Store converted values in packet */ +static uint8_t ao_adc_ready; +static uint8_t ao_adc_sequence; - out = (uint16_t *) &ao_data_ring[ao_data_head].adc; +static const uint8_t ao_adc_mask_seq[AO_ADC_NUM] = { #if AO_ADC_0 - sample(0); + 1 << 0, #endif #if AO_ADC_1 - sample(1); + 1 << 1, #endif #if AO_ADC_2 - sample(2); + 1 << 2, #endif #if AO_ADC_3 - sample(3); + 1 << 3, #endif #if AO_ADC_4 - sample(4); + 1 << 4, #endif #if AO_ADC_5 - sample(5); + 1 << 6, #endif #if AO_ADC_6 - sample(6); + 1 << 6, #endif #if AO_ADC_7 - sample(7); + 1 << 7, #endif +}; + +#define sample(id) (*out++ = (uint16_t) lpc_adc.dr[id] >> 1) + +static inline void lpc_adc_start(void) { + lpc_adc.cr = ((ao_adc_mask_seq[ao_adc_sequence] << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (0 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS) | + (LPC_ADC_CR_START_NOW << LPC_ADC_CR_START)); +} + +void lpc_adc_isr(void) +{ + uint16_t *out; + + /* Store converted value in packet */ + out = (uint16_t *) &ao_data_ring[ao_data_head].adc; + out[ao_adc_sequence] = (uint16_t) lpc_adc.gdr >> 1; + if (++ao_adc_sequence < AO_ADC_NUM) { + lpc_adc_start(); + return; + } AO_DATA_PRESENT(AO_DATA_ADC); if (ao_data_present == AO_DATA_ALL) { @@ -157,7 +133,7 @@ void lpc_adc_isr(void) /* - * Start the ADC sequence using the DMA engine + * Start the ADC sequence using burst mode */ void ao_adc_poll(void) @@ -165,11 +141,8 @@ ao_adc_poll(void) if (!ao_adc_ready) return; ao_adc_ready = 0; - - lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | - (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | - (1 << LPC_ADC_CR_BURST) | - (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); + ao_adc_sequence = 0; + lpc_adc_start(); } static void @@ -202,8 +175,8 @@ ao_adc_init(void) lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC); lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD); - /* Enable interrupt when last channel is complete */ - lpc_adc.inten = (1 << AO_ADC_LAST); + /* Enable interrupt when channel is complete */ + lpc_adc.inten = (1 << LPC_ADC_INTEN_ADGINTEN); lpc_nvic_set_enable(LPC_ISR_ADC_POS); lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); @@ -232,7 +205,7 @@ ao_adc_init(void) ao_enable_analog(0, 23, 7); #endif - lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + lpc_adc.cr = ((0 << LPC_ADC_CR_SEL) | (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | (0 << LPC_ADC_CR_BURST) | (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); -- cgit v1.2.3 From e908eb090fc2aaa03b35dc37c3e008b05ad44d80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Aug 2013 11:24:18 -0700 Subject: altos: Use installed arm compiler for LPC Signed-off-by: Keith Packard --- src/lpc/Makefile.defs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lpc') diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index b63bdd12..9e87cee1 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -12,6 +12,8 @@ SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a SAT_CFLAGS=-I$(SAT)/include +#CC=/opt/arm-gcc-bits/bin/arm-none-eabi-gcc + ifndef VERSION include ../Version endif -- cgit v1.2.3 From 10f88c46df9a266f62452dc25275c79a3bb0653d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:43:18 +0200 Subject: altos: Set default LPC stack to 512 bytes, Em to 384 bytes The default for lpc has been raised to 512 bytes, but Em doesn't have enough RAM for that. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 2 ++ src/lpc/ao_arch.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/lpc') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 6f102dbe..c09fb4c2 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #define HAS_BEEP 1 #define HAS_LED 1 +#define AO_STACK_SIZE 384 + #define IS_FLASH_LOADER 0 /* Crystal on the board */ diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index a8d3cfc4..d04bf2c8 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,9 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 320 +#ifndef AO_STACK_SIZE +#define AO_STACK_SIZE 512 +#endif #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From aa2948803d33dbee6f1eab30370178252df2b56d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:45:06 +0200 Subject: altos: Wake up on LPC usart ISR only once Instead of waking up after every character, wait until the FIFO is empty to reduce overhead Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index c0424699..b34de704 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -49,21 +49,25 @@ _ao_serial_tx_start(void) void lpc_usart_isr(void) { + uint8_t wake_input = 0; (void) lpc_usart.iir_fcr; while (lpc_usart.lsr & (1 << LPC_USART_LSR_RDR)) { char c = lpc_usart.rbr_thr; 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); + wake_input = 1; } if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; _ao_serial_tx_start(); ao_wakeup(&ao_usart_tx_fifo); } + if (wake_input) { + ao_wakeup(&ao_usart_rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); + } } int -- cgit v1.2.3 From 4188153548fca104bb49cda2d502c708fe4b49d7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Aug 2013 08:20:48 -0500 Subject: altos/lpc: Add bits for building flash loaders Signed-off-by: Keith Packard --- src/lpc/Makefile-flash.defs | 92 ++++++++++++++++++++++++++ src/lpc/ao_flash_lpc.c | 158 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 src/lpc/Makefile-flash.defs create mode 100644 src/lpc/ao_flash_lpc.c (limited to 'src/lpc') diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs new file mode 100644 index 00000000..6bdd204c --- /dev/null +++ b/src/lpc/Makefile-flash.defs @@ -0,0 +1,92 @@ +vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR) +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: + objcopy -O ihex $*.elf $@ + +CC=arm-none-eabi-gcc +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include $(TOPDIR)/Version +endif + +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +LDFLAGS=-L$(TOPDIR)/lpc -Wl,-Taltos-loader.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 $@ $< + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_flash_pins.h \ + ao_flash_lpc_pins.h \ + ao_flash_task.h \ + ao_pins.h \ + ao_product.h \ + Makefile + +# +# Common AltOS sources +# +SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_boot_pin.c \ + ao_product.c \ + ao_notask.c \ + ao_timer_lpc.c \ + ao_usb_lpc.c \ + ao_flash_lpc.c \ + ao_flash_task.c \ + ao_flash_loader_lpc.c + +OBJ=$(SRC:.c=.o) + +PRODUCT=AltosFlash-$(VERSION) +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os + +PROGNAME=altos-flash +PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf + +$(PROG): Makefile $(OBJ) altos-loader.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c $(TOPDIR)/Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +all: $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/lpc/ao_flash_lpc.c b/src/lpc/ao_flash_lpc.c new file mode 100644 index 00000000..5a31f39f --- /dev/null +++ b/src/lpc/ao_flash_lpc.c @@ -0,0 +1,158 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 +#include + +#define IAP_LOCATION 0x1fff1ff1 + +typedef void (*iap_func)(uint32_t *in, uint32_t *out); + +static void +iap(uint32_t *in, uint32_t *out) +{ + ao_arch_block_interrupts(); + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHREG); + ((iap_func) IAP_LOCATION)(in, out); + ao_arch_release_interrupts(); +} + +#define LPC_IAP_PREPARE_WRITE 50 +#define LPC_IAP_COPY_RAM_TO_FLASH 51 +#define LPC_IAP_ERASE_SECTOR 52 +#define LPC_IAP_BLANK_CHECK 53 +#define LPC_IAP_READ_PART_ID 54 +#define LPC_IAP_READ_BOOT_CODE_VERSION 55 +#define LPC_IAP_COMPARE 56 +#define LPC_IAP_REINVOKE_ISP 57 +#define LPC_IAP_READ_UID 58 +#define LPC_IAP_ERASE_PAGE 59 +#define LPC_IAP_EEPROM_WRITE 61 +#define LPC_IAP_EEPROM_READ 62 + +#define LPC_IAP_CMD_SUCCESS 0 +#define LPC_IAP_INVALID_COMMAND 1 +#define LPC_IAP_SRC_ADDR_ERROR 2 +#define LPC_IAP_DST_ADDR_ERROR 3 +#define LPC_IAP_SRC_ADDR_NOT_MAPPED 4 +#define LPC_IAP_DST_ADDR_NOT_MAPPED 5 +#define LPC_IAP_COUNT_ERROR 6 +#define LPC_IAP_INVALID_SECTOR 7 +#define LPC_IAP_SECTOR_NOT_BLANK 8 +#define LPC_IAP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9 +#define LPC_IAP_COMPARE_ERROR 10 +#define LPC_IAP_BUSY 11 +#define LPC_IAP_PARAM_ERROR 12 +#define LPC_IAP_ADDR_ERROR 13 +#define LPC_IAP_ADDR_NOT_MAPPED 14 +#define LPC_IAP_CMD_LOCKED 15 +#define LPC_IAP_INVALID_CODE 16 +#define LPC_IAP_INVALID_BAUD_RATE 17 +#define LPC_IAP_INVALID_STOP_BIT 18 +#define LPC_IAP_CODE_READ_PROTECTION_ENABLED 19 + +#define LPC_FLASH_BASE ((uint8_t *) 0x0) +#define LPC_FLASH_SECTOR 4096 +#define LPC_FLASH_SECTOR_MASK (LPC_FLASH_SECTOR - 1) +#define LPC_FLASH_SECTOR_SHIFT 12 + +static uint32_t iap_in[5], iap_out[5]; + +static uint32_t +ao_lpc_addr_to_sector(uint8_t *addr) +{ + uint32_t off = addr - LPC_FLASH_BASE; + + return off >> LPC_FLASH_SECTOR_SHIFT; +} + +static uint8_t +ao_lpc_addr_is_sector_aligned(uint8_t *addr) +{ + uint32_t off = addr - LPC_FLASH_BASE; + return (off & LPC_FLASH_SECTOR_MASK) == 0; +} + +static uint32_t +ao_lpc_prepare_write(uint32_t start_sector, uint32_t end_sector) +{ + iap_in[0] = LPC_IAP_PREPARE_WRITE; + iap_in[1] = start_sector; + iap_in[2] = end_sector; + iap(iap_in,iap_out); + return iap_out[0]; +} + +static uint32_t +ao_lpc_copy_ram_to_flash(uint8_t *dst, uint8_t *src, uint32_t len, uint32_t freq) +{ + iap_in[0] = LPC_IAP_COPY_RAM_TO_FLASH; + iap_in[1] = (uint32_t) dst; + iap_in[2] = (uint32_t) src; + iap_in[3] = len; + iap_in[4] = freq; + iap(iap_in,iap_out); + return iap_out[0]; +} + +static uint32_t +ao_lpc_erase_sector(uint32_t start_sector, uint32_t end_sector, uint32_t freq) +{ + iap_in[0] = LPC_IAP_ERASE_SECTOR; + iap_in[1] = start_sector; + iap_in[2] = end_sector; + iap_in[3] = freq; + iap(iap_in,iap_out); + return iap_out[0]; +} + +uint32_t +ao_lpc_read_part_id(void) +{ + iap_in[0] = LPC_IAP_READ_PART_ID; + iap(iap_in,iap_out); + return iap_out[1]; +} + +uint32_t +ao_flash_erase_page(uint8_t *page) +{ + uint32_t ret = LPC_IAP_CMD_SUCCESS; + if (ao_lpc_addr_is_sector_aligned(page)) { + uint32_t sector = ao_lpc_addr_to_sector(page); + ret = ao_lpc_prepare_write(sector, sector); + if (ret == LPC_IAP_CMD_SUCCESS) + ret = ao_lpc_erase_sector(sector, sector, AO_LPC_SYSCLK / 1000); + } + return ret; +} + +uint32_t +ao_flash_page(uint8_t *page, uint8_t *src) +{ + uint32_t sector = ao_lpc_addr_to_sector(page); + uint32_t ret; + + ret = ao_flash_erase_page(page); + if (ret != LPC_IAP_CMD_SUCCESS) + return ret; + ret = ao_lpc_prepare_write(sector, sector); + if (ret != LPC_IAP_CMD_SUCCESS) + return ret; + ret = ao_lpc_copy_ram_to_flash(page, src, 256, AO_LPC_SYSCLK / 1000); + return ret; +} -- cgit v1.2.3 From 8f7edcee2db30652ce0b147f282de3396c3786ad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Oct 2013 21:53:53 -0700 Subject: altos/lpc, altos/stm: ARM requires ISB after switching stack pointers This sticks a barrier in the CPU to prevent using the wrong stack register past the change. Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 1 + src/stm/ao_arch_funcs.h | 1 + 2 files changed, 2 insertions(+) (limited to 'src/lpc') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 9a3219a2..0891903e 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -235,6 +235,7 @@ static inline void ao_arch_start_scheduler(void) { asm("mrs %0,control" : "=&r" (control)); control |= (1 << 1); asm("msr control,%0" : : "r" (control)); + asm("isb"); } #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 9bb2d7cd..4bcc1023 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -354,6 +354,7 @@ static inline void ao_arch_start_scheduler(void) { asm("mrs %0,control" : "=&r" (control)); control |= (1 << 1); asm("msr control,%0" : : "r" (control)); + asm("isb"); } #endif -- cgit v1.2.3 From 258d225df1f4afe1cfdc9c43208bcd75d18cdf2d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Oct 2013 22:00:15 -0700 Subject: altos: Rename easymini-v0.1 to easymini-v1.0 The production boards are the same as the modified v0.1 boards Signed-off-by: Keith Packard --- src/Makefile | 5 +- src/easymini-v0.1/.gitignore | 2 - src/easymini-v0.1/Makefile | 85 ------------------ src/easymini-v0.1/ao_easymini.c | 46 ---------- src/easymini-v0.1/ao_pins.h | 143 ------------------------------- src/easymini-v0.1/flash-loader/Makefile | 8 -- src/easymini-v0.1/flash-loader/ao_pins.h | 33 ------- src/easymini-v1.0/.gitignore | 2 + src/easymini-v1.0/Makefile | 84 ++++++++++++++++++ src/easymini-v1.0/ao_easymini.c | 46 ++++++++++ src/easymini-v1.0/ao_pins.h | 136 +++++++++++++++++++++++++++++ src/easymini-v1.0/flash-loader/Makefile | 8 ++ src/easymini-v1.0/flash-loader/ao_pins.h | 33 +++++++ src/lpc/Makefile.defs | 8 +- 14 files changed, 314 insertions(+), 325 deletions(-) delete mode 100644 src/easymini-v0.1/.gitignore delete mode 100644 src/easymini-v0.1/Makefile delete mode 100644 src/easymini-v0.1/ao_easymini.c delete mode 100644 src/easymini-v0.1/ao_pins.h delete mode 100644 src/easymini-v0.1/flash-loader/Makefile delete mode 100644 src/easymini-v0.1/flash-loader/ao_pins.h create mode 100644 src/easymini-v1.0/.gitignore create mode 100644 src/easymini-v1.0/Makefile create mode 100644 src/easymini-v1.0/ao_easymini.c create mode 100644 src/easymini-v1.0/ao_pins.h create mode 100644 src/easymini-v1.0/flash-loader/Makefile create mode 100644 src/easymini-v1.0/flash-loader/ao_pins.h (limited to 'src/lpc') diff --git a/src/Makefile b/src/Makefile index 9a8cb837..23cd2920 100644 --- a/src/Makefile +++ b/src/Makefile @@ -33,11 +33,10 @@ ARMDIRS=\ telegps-v0.3 telegps-v0.3/flash-loader \ stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ - telescience-v0.2 telescience-v0.2/flash-loader \ - easymini-v0.1 easymini-v0.1/flash-loader + telescience-v0.2 telescience-v0.2/flash-loader ARMM0DIRS=\ - easymini-v0.1 + easymini-v1.0 easymini-v1.0/flash-loader ifneq ($(shell which sdcc),) SUBDIRS += $(SDCCDIRS) diff --git a/src/easymini-v0.1/.gitignore b/src/easymini-v0.1/.gitignore deleted file mode 100644 index e5f7d586..00000000 --- a/src/easymini-v0.1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -*.elf diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile deleted file mode 100644 index 9847656c..00000000 --- a/src/easymini-v0.1/Makefile +++ /dev/null @@ -1,85 +0,0 @@ -# -# 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_boot_chain.c \ - ao_romconfig.c \ - ao_product.c \ - ao_mutex.c \ - ao_panic.c \ - ao_stdio.c \ - ao_storage.c \ - ao_report.c \ - ao_ignite.c \ - ao_flight.c \ - ao_kalman.c \ - ao_sample.c \ - ao_data.c \ - ao_convert_pa.c \ - ao_led_lpc.c \ - ao_task.c \ - ao_log.c \ - ao_log_mini.c \ - ao_cmd.c \ - ao_config.c \ - ao_timer_lpc.c \ - ao_exti_lpc.c \ - ao_usb_lpc.c \ - ao_spi_lpc.c \ - ao_adc_lpc.c \ - ao_beep_lpc.c \ - ao_m25.c \ - ao_ms5607.c - -PRODUCT=EasyMini-v0.1 -PRODUCT_DEF=-DEASYMINI_V_0_1 -IDPRODUCT=0x0026 - -CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os - -PROGNAME=easymini-v0.1 -PROG=$(PROGNAME)-$(VERSION).elf - -SRC=$(ALTOS_SRC) ao_easymini.c -OBJ=$(SRC:.c=.o) - -all: $(PROG) - -LDFLAGS=-L../lpc -Wl,-Taltos.ld - -$(PROG): Makefile $(OBJ) altos.ld - $(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/easymini-v0.1/ao_easymini.c b/src/easymini-v0.1/ao_easymini.c deleted file mode 100644 index 97230b61..00000000 --- a/src/easymini-v0.1/ao_easymini.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 -#include - -void -main(void) -{ - ao_clock_init(); - ao_task_init(); - ao_timer_init(); - ao_exti_init(); - - ao_beep_init(); - - ao_adc_init(); - ao_spi_init(); - ao_storage_init(); - - ao_usb_init(); - - ao_cmd_init(); - ao_flight_init(); - ao_ms5607_init(); - ao_log_init(); - ao_report_init(); - ao_igniter_init(); - ao_config_init(); - - ao_start_scheduler(); -} diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h deleted file mode 100644 index e0eb10bf..00000000 --- a/src/easymini-v0.1/ao_pins.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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 1 -#define HAS_LED 1 - -#define AO_STACK_SIZE 384 - -#define IS_FLASH_LOADER 0 - -/* 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 1 - -#define HAS_USB_CONNECT 0 -#define HAS_USB_VBUS 0 -#define HAS_USB_PULLUP 1 -#define AO_USB_PULLUP_PORT 0 -#define AO_USB_PULLUP_PIN 20 - -#define PACKET_HAS_SLAVE 0 - -#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI - -/* USART */ - -#define HAS_SERIAL 0 -#define USE_SERIAL_0_STDIN 1 -#define SERIAL_0_18_19 1 -#define SERIAL_0_14_15 0 -#define SERIAL_0_17_18 0 -#define SERIAL_0_26_27 0 - -/* SPI */ - -#define HAS_SPI_0 1 -#define SPI_SCK0_P0_6 1 -#define HAS_SPI_1 1 -#define SPI_SCK1_P1_15 1 -#define SPI_MISO1_P0_22 1 -#define SPI_MOSI1_P0_21 1 - -/* M25 */ - -#define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT 0 -#define AO_M25_SPI_CS_MASK (1 << 23) -#define AO_M25_SPI_BUS 1 - -/* MS5607 */ - -#define HAS_MS5607 1 -#define HAS_MS5611 0 -#define AO_MS5607_PRIVATE_PINS 0 -#define AO_MS5607_CS_PORT 0 -#define AO_MS5607_CS_PIN 7 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) -#define AO_MS5607_MISO_PORT 0 -#define AO_MS5607_MISO_PIN 8 -#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) -#define AO_MS5607_SPI_INDEX 0 - -#define HAS_ACCEL 0 -#define HAS_GPS 0 -#define HAS_RADIO 0 -#define HAS_FLIGHT 1 -#define HAS_EEPROM 1 -#define HAS_TELEMETRY 0 -#define HAS_APRS 0 -#define HAS_LOG 1 -#define USE_INTERNAL_FLASH 0 -#define HAS_IGNITE 1 -#define HAS_IGNITE_REPORT 1 - -#define AO_DATA_RING 16 - -/* - * ADC - */ - -#define HAS_ADC 1 - -#define AO_NUM_ADC 3 - -#define AO_ADC_0 1 -#define AO_ADC_1 1 -#define AO_ADC_2 1 - -struct ao_adc { - int16_t sense_a; - int16_t sense_m; - int16_t v_batt; -}; - -/* - * Igniter - */ - -#define AO_IGNITER_CLOSED 400 -#define AO_IGNITER_OPEN 60 - -#define AO_IGNITER_DROGUE_PORT 0 -#define AO_IGNITER_DROGUE_PIN 2 -#define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) - -#define AO_IGNITER_MAIN_PORT 0 -#define AO_IGNITER_MAIN_PIN 3 -#define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) - -#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) -#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) - -#define AO_ADC_DUMP(p) \ - printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ - (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) diff --git a/src/easymini-v0.1/flash-loader/Makefile b/src/easymini-v0.1/flash-loader/Makefile deleted file mode 100644 index ab828b22..00000000 --- a/src/easymini-v0.1/flash-loader/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# AltOS flash loader build -# -# - -TOPDIR=../.. -HARDWARE=easymini-v0.1 -include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/easymini-v0.1/flash-loader/ao_pins.h b/src/easymini-v0.1/flash-loader/ao_pins.h deleted file mode 100644 index 4330151d..00000000 --- a/src/easymini-v0.1/flash-loader/ao_pins.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * 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_PINS_H_ -#define _AO_PINS_H_ - -#include - -#define AO_BOOT_PIN 1 -#define AO_BOOT_APPLICATION_GPIO 0 -#define AO_BOOT_APPLICATION_PIN 19 -#define AO_BOOT_APPLICATION_VALUE 1 -#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP - -#define HAS_USB_PULLUP 1 -#define AO_USB_PULLUP_PORT 0 -#define AO_USB_PULLUP_PIN 20 - -#endif /* _AO_PINS_H_ */ diff --git a/src/easymini-v1.0/.gitignore b/src/easymini-v1.0/.gitignore new file mode 100644 index 00000000..e5f7d586 --- /dev/null +++ b/src/easymini-v1.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +*.elf diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile new file mode 100644 index 00000000..ec305c94 --- /dev/null +++ b/src/easymini-v1.0/Makefile @@ -0,0 +1,84 @@ +# +# 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_boot_chain.c \ + ao_romconfig.c \ + ao_product.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_report.c \ + ao_ignite.c \ + ao_flight.c \ + ao_kalman.c \ + ao_sample.c \ + ao_data.c \ + ao_convert_pa.c \ + ao_task.c \ + ao_log.c \ + ao_log_mini.c \ + ao_cmd.c \ + ao_config.c \ + ao_timer_lpc.c \ + ao_exti_lpc.c \ + ao_usb_lpc.c \ + ao_spi_lpc.c \ + ao_adc_lpc.c \ + ao_beep_lpc.c \ + ao_m25.c \ + ao_ms5607.c + +PRODUCT=EasyMini-v1.0 +PRODUCT_DEF=-DEASYMINI_V_1_0 +IDPRODUCT=0x0026 + +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os + +PROGNAME=easymini-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_easymini.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../lpc -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) altos.ld + $(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/easymini-v1.0/ao_easymini.c b/src/easymini-v1.0/ao_easymini.c new file mode 100644 index 00000000..97230b61 --- /dev/null +++ b/src/easymini-v1.0/ao_easymini.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 +#include + +void +main(void) +{ + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_exti_init(); + + ao_beep_init(); + + ao_adc_init(); + ao_spi_init(); + ao_storage_init(); + + ao_usb_init(); + + ao_cmd_init(); + ao_flight_init(); + ao_ms5607_init(); + ao_log_init(); + ao_report_init(); + ao_igniter_init(); + ao_config_init(); + + ao_start_scheduler(); +} diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h new file mode 100644 index 00000000..e721030d --- /dev/null +++ b/src/easymini-v1.0/ao_pins.h @@ -0,0 +1,136 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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 1 +#define HAS_LED 0 + +#define AO_STACK_SIZE 384 + +#define IS_FLASH_LOADER 0 + +/* 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 HAS_USB 1 + +#define HAS_USB_CONNECT 0 +#define HAS_USB_VBUS 0 +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#define PACKET_HAS_SLAVE 0 + +#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI + +/* USART */ + +#define HAS_SERIAL 0 +#define USE_SERIAL_0_STDIN 1 +#define SERIAL_0_18_19 1 +#define SERIAL_0_14_15 0 +#define SERIAL_0_17_18 0 +#define SERIAL_0_26_27 0 + +/* SPI */ + +#define HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 +#define HAS_SPI_1 1 +#define SPI_SCK1_P1_15 1 +#define SPI_MISO1_P0_22 1 +#define SPI_MOSI1_P0_21 1 + +/* M25 */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT 0 +#define AO_M25_SPI_CS_MASK (1 << 23) +#define AO_M25_SPI_BUS 1 + +/* MS5607 */ + +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 0 +#define AO_MS5607_CS_PORT 0 +#define AO_MS5607_CS_PIN 7 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT 0 +#define AO_MS5607_MISO_PIN 8 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX 0 + +#define HAS_ACCEL 0 +#define HAS_GPS 0 +#define HAS_RADIO 0 +#define HAS_FLIGHT 1 +#define HAS_EEPROM 1 +#define HAS_TELEMETRY 0 +#define HAS_APRS 0 +#define HAS_LOG 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 + +#define AO_DATA_RING 16 + +/* + * ADC + */ + +#define HAS_ADC 1 + +#define AO_NUM_ADC 3 + +#define AO_ADC_0 1 +#define AO_ADC_1 1 +#define AO_ADC_2 1 + +struct ao_adc { + int16_t sense_a; + int16_t sense_m; + int16_t v_batt; +}; + +/* + * Igniter + */ + +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +#define AO_IGNITER_DROGUE_PORT 0 +#define AO_IGNITER_DROGUE_PIN 2 +#define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) + +#define AO_IGNITER_MAIN_PORT 0 +#define AO_IGNITER_MAIN_PIN 3 +#define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ + (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) diff --git a/src/easymini-v1.0/flash-loader/Makefile b/src/easymini-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..78bb4092 --- /dev/null +++ b/src/easymini-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=easymini-v1.0 +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/easymini-v1.0/flash-loader/ao_pins.h b/src/easymini-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..4330151d --- /dev/null +++ b/src/easymini-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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_PINS_H_ +#define _AO_PINS_H_ + +#include + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#endif /* _AO_PINS_H_ */ diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index 9e87cee1..2873d5e8 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -7,13 +7,11 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util -CC=/usr/bin/arm-none-eabi-gcc +CC=arm-none-eabi-gcc SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a SAT_CFLAGS=-I$(SAT)/include -#CC=/opt/arm-gcc-bits/bin/arm-none-eabi-gcc - ifndef VERSION include ../Version endif @@ -21,7 +19,7 @@ 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 +LDFLAGS=$(LPC_CFLAGS) -L../stm -Wl,-Taltos.ld NICKLE=nickle @@ -34,7 +32,7 @@ endif quiet ?= $($1) .c.o: - $(call quiet,CC) -c $(CFLAGS) -o $@ $< + $(call quiet,CC) -c $(CFLAGS) $< ao_serial_lpc.h: ../lpc/baud_rate ao_pins.h nickle ../lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ -- cgit v1.2.3 From 6a1e398e590121458176758858bb4210f3eb5a55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 8 Oct 2013 09:22:03 -0700 Subject: Add --with parameters to configure for compiler selection This allows the user to specify which compiler to use for each target CPU. Also checks to make sure the arm compiler supports -m0 and -m3 cpu type flags. The build now actually uses the specified compilers too. Signed-off-by: Keith Packard --- configure.ac | 155 +++++++++++++++++++++++++++++++++++++++--- src/Makedefs.in | 10 +++ src/Makefile | 25 +++---- src/avr-demo/Makefile | 10 +-- src/avr/Makefile.defs | 16 +++++ src/cc1111/Makefile.cc1111 | 3 +- src/lpc/Makefile-flash.defs | 10 +-- src/lpc/Makefile.defs | 23 ++++--- src/micropeak/Makefile | 12 +--- src/nanopeak-v0.1/Makefile | 12 +--- src/stm/Makefile-flash.defs | 11 +-- src/stm/Makefile.defs | 15 ++-- src/telepyro-v0.1/Makefile | 10 +-- src/telescience-pwm/Makefile | 12 +--- src/telescience-v0.1/Makefile | 12 +--- 15 files changed, 238 insertions(+), 98 deletions(-) create mode 100644 src/Makedefs.in create mode 100644 src/avr/Makefile.defs (limited to 'src/lpc') diff --git a/configure.ac b/configure.ac index e88109f9..729149da 100644 --- a/configure.ac +++ b/configure.ac @@ -180,21 +180,151 @@ if test "x$GCC" = "xyes"; then fi AC_SUBST(WARN_CFLAGS) -AC_CHECK_PROG([HAVE_SDCC], [sdcc], yes, no) +# +# Configure SDCC +# + +AC_ARG_WITH([sdcc], + [AS_HELP_STRING([--with-sdcc], + [Name of SDCC])], + [], + [with_sdcc=auto]) + +if test "x$with_sdcc" != "xno"; then + if test "x$with_sdcc" = "xauto"; then + with_sdcc="sdcc" + AC_CHECK_PROG([HAVE_SDCC],[$with_sdcc], yes, no) + else + HAVE_SDCC=yes + fi +else + HAVE_SDCC=no +fi + if test "x$HAVE_SDCC" = "xno"; then - AC_MSG_WARN([No sdcc found, cc1111 binaries will not be built]) + AC_MSG_WARN([SDCC not found, cc1111 binaries will not be built]) +else + SDCC=$with_sdcc +fi + +AC_SUBST(SDCC) +AC_SUBST(HAVE_SDCC) + +# +# Configure ARM compiler for STM32L and LPC11U14 +# + +AC_ARG_WITH([arm-cc], + [AS_HELP_STRING([--with-arm-cc], + [Name of ARM C compiler])], + [], + [with_arm_cc=auto]) + +if test "x$with_arm_cc" != "xno"; then + if test "x$with_arm_cc" = "xauto"; then + with_arm_cc="arm-none-eabi-gcc" + AC_CHECK_PROG([HAVE_ARM_CC],[$with_arm_cc], yes, no) + else + HAVE_ARM_CC=yes + fi +else + HAVE_ARM_CC=no fi -AC_CHECK_PROG([HAVE_ARM_GCC],[arm-none-eabi-gcc], yes, no,[/opt/cortex/bin]) -if test "x$HAVE_ARM_GCC" = "xno"; then - AC_MSG_WARN([No summon toolchain arm compiler found, STM32L binaries will not be built]) +if test "x$HAVE_ARM_CC" = "xno"; then + AC_MSG_WARN([Arm compiler not found, ARM binaries will not be built]) +else + ARM_CC=$with_arm_cc +fi +AC_SUBST(HAVE_ARM_CC) +AC_SUBST(ARM_CC) + +if test "x$HAVE_ARM_CC" = "xyes"; then + save_CC="$CC" + save_CFLAGS="$CFLAGS" + CC="$ARM_CC" + CFLAGS="-mthumb -mcpu=cortex-m0" + AC_LANG_PUSH([C]) + + AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m0]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], + [HAVE_ARM_M0_CC=yes], + [HAVE_ARM_M0_CC=no]) + AC_MSG_RESULT([$HAVE_ARM_M0]) + CFLAGS="-mthumb -mcpu=cortex-m3" + AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], + [HAVE_ARM_M3_CC=yes], + [HAVE_ARM_M3_CC=no]) + AC_MSG_RESULT([$HAVE_ARM_M3]) + AC_LANG_POP([C]) + CFLAGS="$save_CFLAGS" + CC="$save_CC" +else + HAVE_ARM_M3_CC=no + HAVE_ARM_M0_CC=no +fi +AC_SUBST(HAVE_ARM_M3_CC) +AC_SUBST(HAVE_ARM_M0_CC) + +if test "x$HAVE_ARM_M3_CC" = "xno"; then + AC_MSG_WARN([No cortex-m3 arm compiler found, STM32L binaries will not be built]) fi -AC_CHECK_PROG([HAVE_ARM_M0_GCC], [arm-none-eabi-gcc], yes, no,[/usr/bin]) -if test "x$HAVE_ARM_M0_GCC" = "xno"; then - AC_MSG_WARN([No linaro toolchain arm cortex-m0 compiler found, LPC11U14 binaries will not be built]) +if test "x$HAVE_ARM_M0_CC" = "xno"; then + AC_MSG_WARN([No cortex-m0 arm compiler found, LPC11U14 binaries will not be built]) fi +# +# Configure AVR compiler +# + +AC_ARG_WITH([avr-cc], + [AS_HELP_STRING([--with-avr-cc], + [Name of AVR C compiler])], + [], + [with_avr_cc=auto]) + +if test "x$with_avr_cc" != "xno"; then + if test "x$with_avr_cc" = "xauto"; then + with_avr_cc="avr-gcc" + AC_CHECK_PROG([HAVE_AVR_CC],[$with_avr_cc], yes, no) + else + HAVE_AVR_CC=yes + fi +else + HAVE_AVR_CC=no +fi + +AC_ARG_WITH([avr-objcopy], + [AS_HELP_STRING([--with-avr-objcopy], + [Name of AVR objcopy])], + [], + [with_avr_objcopy=auto]) + +if test "x$with_avr_objcopy" != "xno"; then + if test "x$with_avr_objcopy" = "xauto"; then + with_avr_objcopy="avr-objcopy" + AC_CHECK_PROG([HAVE_AVR_OBJCOPY],[$with_avr_objcopy], yes, no) + else + HAVE_AVR_OBJCOPY=yes + fi +else + HAVE_AVR_OBJCOPY=no +fi + +if test "x$HAVE_AVR_CC" = "xno" -o "x$HAVE_AVR_OBJCOPY" = "xno"; then + AC_MSG_WARN([AVR compiler and objcopy not found, atmel binaries will not be built]) + HAVE_AVR_CC=no +else + AVR_CC=$with_avr_cc + AVR_OBJCOPY=$with_avr_objcopy +fi + +AC_SUBST(AVR_CC) +AC_SUBST(AVR_OBJCOPY) +AC_SUBST(HAVE_AVR_CC) + AC_CHECK_PROG([HAVE_NICKLE], [nickle], yes, no) if test "x$HAVE_NICKLE" = "xno"; then AC_MSG_ERROR([Please install nickle to build AltOs]) @@ -213,6 +343,7 @@ AM_CONDITIONAL([LIBSTLINK], [test x$HAVE_STLINK != xno]) AC_OUTPUT([ Makefile +src/Makedefs altoslib/Makefile altosuilib/Makefile altosuilib/AltosUIVersion.java @@ -248,9 +379,13 @@ echo "" echo " Package: ${PACKAGE_NAME} ${PACKAGE_VERSION}" echo "" echo " Configuration" -echo " STM32L support..............: ${HAVE_ARM_GCC}" -echo " LPC11U14 support............: ${HAVE_ARM_M0_GCC}" +echo " Arm compiler................: ${ARM_CC}" +echo " STM32L support..............: ${HAVE_ARM_M3_CC}" +echo " LPC11U14 support............: ${HAVE_ARM_M0_CC}" +echo " SDCC........................: ${SDCC}" echo " CC1111 support..............: ${HAVE_SDCC}" +echo " AVR compiler................: ${AVR_CC} ${AVR_OBJCOPY}" +echo " AVR support.................: ${HAVE_AVR_CC}" echo " Android support.............: ${HAVE_ANDROID_SDK}" echo " STlink support..............: ${HAVE_STLINK}" echo "" diff --git a/src/Makedefs.in b/src/Makedefs.in new file mode 100644 index 00000000..6dc9ab0f --- /dev/null +++ b/src/Makedefs.in @@ -0,0 +1,10 @@ +ARM_CC=@ARM_CC@ +HAVE_ARM_M3_CC=@HAVE_ARM_M3_CC@ +HAVE_ARM_M0_CC=@HAVE_ARM_M0_CC@ + +SDCC=@SDCC@ +HAVE_SDCC=@HAVE_SDCC@ + +AVR_CC=@AVR_CC@ +AVR_OBJCOPY=@AVR_OBJCOPY@ +HAVE_AVR_CC=@HAVE_AVR_CC@ diff --git a/src/Makefile b/src/Makefile index 23cd2920..ae231c64 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath load_csv.5c kalman vpath matrix.5c kalman include Version +include Makedefs SDCCDIRS=\ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ @@ -23,10 +24,7 @@ SDCCDIRS=\ telefire-v0.1 telefire-v0.2 \ telemini-v2.0 -AVRDIRS=\ - telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 - -ARMDIRS=\ +ARMM3DIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ telemega-v0.3 telemega-v0.3/flash-loader \ megadongle-v0.1 megadongle-v0.1/flash-loader \ @@ -38,23 +36,26 @@ ARMDIRS=\ ARMM0DIRS=\ easymini-v1.0 easymini-v1.0/flash-loader -ifneq ($(shell which sdcc),) +AVRDIRS=\ + telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 + +ifeq ($(strip $(HAVE_SDCC)),yes) SUBDIRS += $(SDCCDIRS) endif -ifneq ($(shell which avr-gcc),) - SUBDIRS += $(AVRDIRS) +ifeq ($(strip ($HAVE_ARM_M3_CC)),yes) + SUBDIRS += $(ARMM3DIRS) endif -ifneq ($(shell which /opt/cortex/bin/arm-none-eabi-gcc),) - SUBDIRS += $(ARMDIRS) +ifneq ($(strip ($HAVE_ARM_M0_CC)),yes) + SUBDIRS += $(ARMM0DIRS) endif -ifneq ($(shell which /usr/bin/arm-none-eabi-gcc),) - SUBDIRS += $(ARMM0DIRS) +ifeq ($(strip $(HAVE_AVR_CC)),yes) + SUBDIRS += $(AVRDIRS) endif -ALLDIRS=$(SDCCDIRS) $(AVRDIRS) $(ARMDIRS) +ALLDIRS=$(SDCCDIRS) $(ARMM3DIRS) $(ARMM0DIRS) $(AVRDIRS) all: all-local all-recursive diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile index 93295166..6d9bfea2 100644 --- a/src/avr-demo/Makefile +++ b/src/avr-demo/Makefile @@ -11,18 +11,12 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -ifndef VERSION -include ../Version -endif INC = \ ao.h \ diff --git a/src/avr/Makefile.defs b/src/avr/Makefile.defs new file mode 100644 index 00000000..eeb9a881 --- /dev/null +++ b/src/avr/Makefile.defs @@ -0,0 +1,16 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +ifndef VERSION +include $(TOPDIR)/Version +endif + +include $(TOPDIR)/Makedefs + +CC=$(AVR_CC) +OBJCOPY=$(AVR_OBJCOPY) +LDSCRIPTS=/usr/lib/avr/lib/ldscripts + +PROGRAMMER=usbtiny +LOADCMD=avrdude diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index 0e19603b..78b653b3 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -1,4 +1,5 @@ -CC=sdcc +include ../Makedefs +CC=$(SDCC) CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index 6bdd204c..ab7181b9 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -6,14 +6,16 @@ vpath ao-make-product.5c $(TOPDIR)/util .elf.ihx: objcopy -O ihex $*.elf $@ -CC=arm-none-eabi-gcc -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include ifndef VERSION include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index 2873d5e8..d541230a 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -7,19 +7,24 @@ 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 TOPDIR +TOPDIR=.. +endif ifndef VERSION -include ../Version +include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include -AO_CFLAGS=-I. -I../lpc -I../core -I../drivers -I.. +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR) LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) -LDFLAGS=$(LPC_CFLAGS) -L../stm -Wl,-Taltos.ld +LDFLAGS=$(LPC_CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos.ld NICKLE=nickle @@ -34,8 +39,8 @@ quiet ?= $($1) .c.o: $(call quiet,CC) -c $(CFLAGS) $< -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.h: $(TOPDIR)/lpc/baud_rate ao_pins.h + nickle $(TOPDIR)/lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ ao_serial_lpc.o: ao_serial_lpc.h diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index e51b2847..35dfaab8 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -6,21 +6,15 @@ vpath % ../attiny:../drivers:../core:../product:.. vpath ao-make-product.5c ../util vpath make-altitude-pa ../util +include ../avr/Makefile.defs + MCU=attiny85 DUDECPUTYPE=t85 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr25.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x ALTOS_SRC = \ ao_micropeak.c \ diff --git a/src/nanopeak-v0.1/Makefile b/src/nanopeak-v0.1/Makefile index cb468a06..154d78f6 100644 --- a/src/nanopeak-v0.1/Makefile +++ b/src/nanopeak-v0.1/Makefile @@ -6,21 +6,15 @@ vpath % ../attiny:../drivers:../core:../product:.. vpath ao-make-product.5c ../util vpath make-altitude-pa ../util +include ../avr/Makefile.defs + MCU=attiny85 DUDECPUTYPE=t85 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr25.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x ALTOS_SRC = \ ao_micropeak.c \ diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 86f76d46..f429d9bd 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -6,14 +6,15 @@ vpath ao-make-product.5c $(TOPDIR)/util .elf.ihx: objcopy -O ihex $*.elf $@ -CC=/opt/cortex/bin/arm-none-eabi-gcc -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include - ifndef VERSION include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a +SAT_CFLAGS=-I$(SAT)/include AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 8ef30521..ede75f80 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -12,14 +12,19 @@ vpath ao-make-product.5c ../util .elf.ihx: objcopy -O ihex $*.elf $@ -SAT=/opt/cortex -CC=$(SAT)/bin/arm-none-eabi-gcc -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include +ifndef TOPDIR +TOPDIR=.. +endif ifndef VERSION -include ../Version +include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a +SAT_CFLAGS=-I$(SAT)/include AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 6743ba66..025b324a 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -5,18 +5,12 @@ vpath % .:..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -ifndef VERSION -include ../Version -endif INC = \ ao.h \ diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile index ce2a8fde..7f39d3f1 100644 --- a/src/telescience-pwm/Makefile +++ b/src/telescience-pwm/Makefile @@ -5,20 +5,14 @@ vpath % ..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr5.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x INC = \ ao.h \ diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 81054a75..a65b3ad0 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -5,20 +5,14 @@ vpath % ..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr5.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x INC = \ ao.h \ -- cgit v1.2.3 From d8d3835fedf9b7c4d203f321e72c2b086ebb3b97 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Oct 2013 00:00:05 -0700 Subject: altos: Use installed pdclib Switch over to the installed pdclib everywhere Signed-off-by: Keith Packard --- configure.ac | 17 +++++++++++++++-- src/easymini-v1.0/Makefile | 4 +--- src/lpc/Makefile-flash.defs | 43 +++++------------------------------------- src/lpc/Makefile-lpc.defs | 44 +++++++++++++++++++++++++++++++++++++++++++ src/lpc/Makefile.defs | 36 ++--------------------------------- src/lpcxpresso/Makefile | 2 +- src/megadongle-v0.1/Makefile | 2 +- src/stm-demo/Makefile | 2 +- src/stm-flash/Makefile | 2 +- src/stm/Makefile-flash.defs | 6 ++---- src/stm/Makefile.defs | 6 ++---- src/telegps-v0.1/Makefile | 2 +- src/telegps-v0.3/Makefile | 2 +- src/telelco-v0.1/Makefile | 2 +- src/telelco-v0.2/Makefile | 2 +- src/telemega-v0.1/Makefile | 2 +- src/telemega-v0.3/Makefile | 2 +- src/telemetrum-v2.0/Makefile | 2 +- src/telescience-v0.2/Makefile | 2 +- 19 files changed, 83 insertions(+), 97 deletions(-) create mode 100644 src/lpc/Makefile-lpc.defs (limited to 'src/lpc') diff --git a/configure.ac b/configure.ac index de344335..8024b7c6 100644 --- a/configure.ac +++ b/configure.ac @@ -242,22 +242,35 @@ AC_SUBST(ARM_CC) if test "x$HAVE_ARM_CC" = "xyes"; then save_CC="$CC" save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" CC="$ARM_CC" CFLAGS="-mthumb -mcpu=cortex-m0" + LIBS="-ffreestanding -nostdlib" AC_LANG_PUSH([C]) AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m0]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], [HAVE_ARM_M0_CC=yes], [HAVE_ARM_M0_CC=no]) - AC_MSG_RESULT([$HAVE_ARM_M0]) + AC_MSG_RESULT([$HAVE_ARM_M0_CC]) + + AC_CHECK_LIB(pdclib-cortex-m0,memcpy, + [], + [HAVE_ARM_M0_CC=no]) + CFLAGS="-mthumb -mcpu=cortex-m3" AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], [HAVE_ARM_M3_CC=yes], [HAVE_ARM_M3_CC=no]) - AC_MSG_RESULT([$HAVE_ARM_M3]) + AC_MSG_RESULT([$HAVE_ARM_M3_CC]) + + AC_CHECK_LIB(pdclib-cortex-m3,memcpy, + [], + [HAVE_ARM_M3_CC=no]) + AC_LANG_POP([C]) + LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CC="$save_CC" else diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile index ec305c94..6ab79425 100644 --- a/src/easymini-v1.0/Makefile +++ b/src/easymini-v1.0/Makefile @@ -60,10 +60,8 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -LDFLAGS=-L../lpc -Wl,-Taltos.ld - $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index ab7181b9..bb90b0d7 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -1,39 +1,4 @@ -vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR) -vpath ao-make-product.5c $(TOPDIR)/util - -.SUFFIXES: .elf .ihx - -.elf.ihx: - objcopy -O ihex $*.elf $@ - - -ifndef VERSION -include $(TOPDIR)/Version -endif -include $(TOPDIR)/Makedefs - -CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include - -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) - -LDFLAGS=-L$(TOPDIR)/lpc -Wl,-Taltos-loader.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 $@ $< +include $(TOPDIR)/lpc/Makefile-lpc.defs INC = \ ao.h \ @@ -68,13 +33,15 @@ PRODUCT=AltosFlash-$(VERSION) PRODUCT_DEF=-DALTOS_FLASH IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos-loader.ld PROGNAME=altos-flash PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf $(PROG): Makefile $(OBJ) altos-loader.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c $(TOPDIR)/Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs new file mode 100644 index 00000000..32a02a4c --- /dev/null +++ b/src/lpc/Makefile-lpc.defs @@ -0,0 +1,44 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +include $(TOPDIR)/Makedefs + +vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR) +vpath make-altitude $(TOPDIR)/util +vpath make-kalman $(TOPDIR)/util +vpath kalman.5c $(TOPDIR)/kalman +vpath kalman_filter.5c $(TOPDIR)/kalman +vpath load_csv.5c $(TOPDIR)/kalman +vpath matrix.5c $(TOPDIR)/kalman +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: + objcopy -O ihex $*.elf $@ + + +ifndef VERSION +include $(TOPDIR)/Version +endif + +CC=$(ARM_CC) + +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) + +NICKLE=nickle + +LIBS=-lpdclib-cortex-m0 -lgcc + +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 $@ $< diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index d541230a..b6d739c2 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -1,43 +1,11 @@ -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 - ifndef TOPDIR TOPDIR=.. endif -ifndef VERSION -include $(TOPDIR)/Version -endif +include $(TOPDIR)/lpc/Makefile-lpc.defs include $(TOPDIR)/Makedefs -CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include - -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR) -LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) - -LDFLAGS=$(LPC_CFLAGS) -L$(TOPDIR)/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) $< +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos.ld ao_serial_lpc.h: $(TOPDIR)/lpc/baud_rate ao_pins.h nickle $(TOPDIR)/lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ diff --git a/src/lpcxpresso/Makefile b/src/lpcxpresso/Makefile index 3745f283..374c052f 100644 --- a/src/lpcxpresso/Makefile +++ b/src/lpcxpresso/Makefile @@ -45,7 +45,7 @@ all: $(PROG) LDFLAGS=-L../lpc -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index 7f12963f..268f186f 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -69,7 +69,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 48fa07eb..990968c2 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -56,7 +56,7 @@ all: $(ELF) $(IHX) LDFLAGS=-L../stm -Wl,-Taltos.ld $(ELF): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile index 1ea35581..5c0699e1 100644 --- a/src/stm-flash/Makefile +++ b/src/stm-flash/Makefile @@ -41,7 +41,7 @@ all: $(PROG) LDFLAGS=-L../stm -Wl,-Taltos-loader.ld $(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index f429d9bd..159f8b9c 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -12,9 +12,7 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include +LIBS=-lpdclib-cortex-m3 -lgcc AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) @@ -73,7 +71,7 @@ PROGNAME=altos-flash PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf $(PROG): Makefile $(OBJ) altos-loader.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c $(TOPDIR)/Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index ede75f80..ee1cb658 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -22,12 +22,10 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include +LIBS=-lpdclib-cortex-m3 -lgcc AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. -STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index 64deddc6..170294e6 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -82,7 +82,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/telegps-v0.3/Makefile b/src/telegps-v0.3/Makefile index ca7d7c2b..d129d295 100644 --- a/src/telegps-v0.3/Makefile +++ b/src/telegps-v0.3/Makefile @@ -66,7 +66,7 @@ all: $(PROG) LDFLAGS=-L../lpc -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index 24083308..0f61788c 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -76,7 +76,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude.h: make-altitude nickle $< > $@ diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index f78ca9e2..bc5f8571 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -85,7 +85,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude.h: make-altitude nickle $< > $@ diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index bf756e96..bbf46f3c 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -112,7 +112,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude-pa.h: make-altitude-pa nickle $< > $@ diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index f2c0625f..6e5da721 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -112,7 +112,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude-pa.h: make-altitude-pa nickle $< > $@ diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index c03a5539..be72d493 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -101,7 +101,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude-pa.h: make-altitude-pa nickle $< > $@ diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index f16ef268..c53a6cc3 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -68,7 +68,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) -- cgit v1.2.3 From 52b19511222980138faddb2047707baceff0a596 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 8 Dec 2013 11:14:29 -0800 Subject: altos: Build .ihx files for all arm projects The .ihx version can be processed by the java loader Signed-off-by: Keith Packard --- src/easymini-v1.0/Makefile | 5 +++-- src/lpc/Makefile-lpc.defs | 3 ++- src/megadongle-v0.1/Makefile | 3 ++- src/stm/Makefile.defs | 3 ++- src/telegps-v0.1/Makefile | 3 ++- src/telelco-v0.1/Makefile | 3 ++- src/telelco-v0.2/Makefile | 3 ++- src/telemega-v0.1/Makefile | 3 ++- src/telemega-v0.3/Makefile | 3 ++- src/telemetrum-v2.0/Makefile | 3 ++- src/telescience-v0.2/Makefile | 3 ++- 11 files changed, 23 insertions(+), 12 deletions(-) (limited to 'src/lpc') diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile index 6ab79425..8042874f 100644 --- a/src/easymini-v1.0/Makefile +++ b/src/easymini-v1.0/Makefile @@ -54,11 +54,12 @@ CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os PROGNAME=easymini-v1.0 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_easymini.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) @@ -74,7 +75,7 @@ load: $(PROG) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o $(PROGNAME)-*.elf rm -f ao_product.h install: diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs index 32a02a4c..fbd413b0 100644 --- a/src/lpc/Makefile-lpc.defs +++ b/src/lpc/Makefile-lpc.defs @@ -16,13 +16,14 @@ vpath ao-make-product.5c $(TOPDIR)/util .SUFFIXES: .elf .ihx .elf.ihx: - objcopy -O ihex $*.elf $@ + $(ELFTOHEX) --output=$@ $*.elf ifndef VERSION include $(TOPDIR)/Version endif +ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex CC=$(ARM_CC) AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index 268f186f..a8c3a584 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -62,11 +62,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=megadongle-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_megadongle.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 0710d747..b1998f93 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -10,7 +10,7 @@ vpath ao-make-product.5c ../util .SUFFIXES: .elf .ihx .elf.ihx: - objcopy -O ihex $*.elf $@ + $(ELFTOHEX) --output=$@ $*.elf ifndef TOPDIR TOPDIR=.. @@ -30,6 +30,7 @@ STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -no LDFLAGS=-L../stm -Wl,-Taltos.ld NICKLE=nickle +ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex V=0 # The user has explicitly enabled quiet compilation. diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index f5533d51..96366cfc 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -74,11 +74,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telegps-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telegps.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index 0f61788c..e494403c 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -69,11 +69,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g PROGNAME=telelco-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telelco.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 2fb4db5e..32cf7edd 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -77,11 +77,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g PROGNAME=telelco-v0.2 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telelco.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index 7acaedd2..0166ebc9 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -122,11 +122,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telemega-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telemega.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index a25b8b68..12e4152c 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -124,11 +124,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telemega-v0.3 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telemega.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index a5370224..16408b03 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -95,11 +95,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telemetrum-v2.0 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telemetrum.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index c53a6cc3..d76183c5 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -61,11 +61,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telescience-v0.2 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telescience.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) -- cgit v1.2.3 From bb72b4018dd6a422afe1916d9538bb9ff1e45353 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 8 Dec 2013 11:15:37 -0800 Subject: altos: Change flash loader name to just AltosFlash Remove the software version string from the product name Signed-off-by: Keith Packard --- src/lpc/Makefile-flash.defs | 4 ++-- src/stm/Makefile-flash.defs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index bb90b0d7..4a245d10 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -29,7 +29,7 @@ SRC = \ OBJ=$(SRC:.c=.o) -PRODUCT=AltosFlash-$(VERSION) +PRODUCT=AltosFlash PRODUCT_DEF=-DALTOS_FLASH IDPRODUCT=0x000a @@ -53,7 +53,7 @@ all: $(PROG) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf rm -f ao_product.h install: diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 159f8b9c..be3ae799 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -61,7 +61,7 @@ SRC = \ OBJ=$(SRC:.c=.o) -PRODUCT=AltosFlash-$(VERSION) +PRODUCT=AltosFlash PRODUCT_DEF=-DALTOS_FLASH IDPRODUCT=0x000a @@ -83,7 +83,7 @@ all: $(PROG) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf rm -f ao_product.h install: -- cgit v1.2.3 From 1f035ac2df1cfa6964ae904aba0aedde279ca921 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Dec 2013 23:50:54 -0800 Subject: altos: Use all 16 bits of setup packet len when limiting reply len We were only using the low 8 bits of the setup packet reply max len, which meant that if the other side sent a weird max len (as Windows 7 does), then we'd truncate our setup reply to whatever was in the low 8 bits of that value. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 2 +- src/stm/ao_usb_stm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 144d1075..108822ce 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -450,7 +450,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) } static void -ao_usb_ep0_in_start(uint8_t max) +ao_usb_ep0_in_start(uint16_t max) { /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 11dde92e..b00390ec 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -572,7 +572,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) } static void -ao_usb_ep0_in_start(uint8_t max) +ao_usb_ep0_in_start(uint16_t max) { /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) -- cgit v1.2.3 From 012abeda6ae846d74729e96e7ed7c8af2edca572 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 18 Dec 2013 02:02:12 -0800 Subject: altos/lpc: Be a bit more resistant to toolchain section name changes Just add some wild cards on the ends of each section name in case the toolchain changes names in the future. Signed-off-by: Keith Packard --- src/lpc/altos-loader.ld | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld index 4f78f552..9df6e456 100644 --- a/src/lpc/altos-loader.ld +++ b/src/lpc/altos-loader.ld @@ -53,7 +53,7 @@ SECTIONS { */ .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : { __boot_start__ = .; - *(.boot) + *(.boot*) __boot_end__ = .; } >ram @@ -61,15 +61,15 @@ SECTIONS { */ .data : { __data_start__ = .; - *(.data) /* initialized data */ + *(.data*) /* initialized data */ __data_end__ = .; } >ram AT>rom .bss : { __bss_start__ = .; - *(.bss) - *(COMMON) + *(.bss*) + *(COMMON*) __bss_end__ = .; } >ram -- cgit v1.2.3 From 9c200c3bc742b4dd1a7e28bfce9d5b27e833aae5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 18 Dec 2013 10:01:29 -0800 Subject: altos: Build pdclib locally if necessary Signed-off-by: Keith Packard --- configure.ac | 36 +++++++++++++++++++++++++++++------- src/Makedefs.in | 4 ++++ src/Makefile | 9 ++++++++- src/lpc/Makefile-lpc.defs | 4 ++-- src/stm/Makefile.defs | 4 ++-- 5 files changed, 45 insertions(+), 12 deletions(-) (limited to 'src/lpc') diff --git a/configure.ac b/configure.ac index 1d80376c..b6e17355 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,25 @@ fi AC_SUBST(HAVE_ARM_CC) AC_SUBST(ARM_CC) +if test -d pdclib -a x"$HAVE_ARM_CC" = xyes; then + PDCLIB_INCLUDES='-I$(TOPDIR)/../pdclib/opt/include' + PDCLIB_LIBS_M0='-L$(TOPDIR)/../pdclib/opt/lib -lpdclib-cortex-m0' + PDCLIB_LIBS_M3='-L$(TOPDIR)/../pdclib/opt/lib -lpdclib-cortex-m3' + HAVE_PDCLIB=yes +else + PDCLIB_INCLUDES='' + PDCLIB_LIBS_M0='-lpdclib-cortex-m0' + PDCLIB_LIBS_M3='-lpdclib-cortex-m3' + HAVE_PDCLIB=no +fi + +AM_CONDITIONAL(PDCLIB, [test x$HAVE_PDCLIB = xyes]) + +AC_SUBST(PDCLIB_INCLUDES) +AC_SUBST(PDCLIB_LIBS_M0) +AC_SUBST(PDCLIB_LIBS_M3) +AC_SUBST(HAVE_PDCLIB) + if test "x$HAVE_ARM_CC" = "xyes"; then save_CC="$CC" save_CFLAGS="$CFLAGS" @@ -253,10 +272,6 @@ if test "x$HAVE_ARM_CC" = "xyes"; then [HAVE_ARM_M0_CC=no]) AC_MSG_RESULT([$HAVE_ARM_M0_CC]) - AC_CHECK_LIB(pdclib-cortex-m0,memcpy, - [], - [HAVE_ARM_M0_CC=no]) - CFLAGS="-mthumb -mcpu=cortex-m3" AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], @@ -264,9 +279,15 @@ if test "x$HAVE_ARM_CC" = "xyes"; then [HAVE_ARM_M3_CC=no]) AC_MSG_RESULT([$HAVE_ARM_M3_CC]) - AC_CHECK_LIB(pdclib-cortex-m3,memcpy, - [], - [HAVE_ARM_M3_CC=no]) + if test x$HAVE_PDCLIB != xyes; then + AC_CHECK_LIB(pdclib-cortex-m0,memcpy, + [], + [HAVE_ARM_M0_CC=no]) + + AC_CHECK_LIB(pdclib-cortex-m3,memcpy, + [], + [HAVE_ARM_M3_CC=no]) + fi AC_LANG_POP([C]) LIBS="$save_LIBS" @@ -459,6 +480,7 @@ echo " AVR compiler................: ${AVR_CC} ${AVR_OBJCOPY}" echo " AVR support.................: ${HAVE_AVR_CC}" echo " Android support.............: ${HAVE_ANDROID_SDK}" echo " STlink support..............: ${HAVE_STLINK}" +echo " Local pdclib................: ${HAVE_PDCLIB}" echo "" echo " Java paths" echo " freetts.....................: ${FREETTS}" diff --git a/src/Makedefs.in b/src/Makedefs.in index 6dc9ab0f..d4ef28be 100644 --- a/src/Makedefs.in +++ b/src/Makedefs.in @@ -1,6 +1,10 @@ ARM_CC=@ARM_CC@ HAVE_ARM_M3_CC=@HAVE_ARM_M3_CC@ HAVE_ARM_M0_CC=@HAVE_ARM_M0_CC@ +PDCLIB_INCLUDES=@PDCLIB_INCLUDES@ +PDCLIB_LIBS_M0=@PDCLIB_LIBS_M0@ +PDCLIB_LIBS_M3=@PDCLIB_LIBS_M3@ +HAVE_PDCLIB=@HAVE_PDCLIB@ SDCC=@SDCC@ HAVE_SDCC=@HAVE_SDCC@ diff --git a/src/Makefile b/src/Makefile index bdd3307a..2ba59d94 100644 --- a/src/Makefile +++ b/src/Makefile @@ -42,6 +42,10 @@ AVRDIRS=\ SUBDIRS= +ifeq ($(strip $(HAVE_PDCLIB)),yes) +PDCLIB=pdclib +endif + ifeq ($(strip $(HAVE_SDCC)),yes) SUBDIRS+=$(SDCCDIRS) endif @@ -92,7 +96,7 @@ uninstall: all-recursive: all-local -all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h +all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h $(PDCLIB) altitude.h: make-altitude nickle $< > $@ @@ -108,3 +112,6 @@ ao_whiten.h: make-whiten clean-local: rm -f altitude.h ao_kalman.h + +pdclib: + cd ../pdclib && make && make prefix=`pwd`/opt install diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs index fbd413b0..3d55cf67 100644 --- a/src/lpc/Makefile-lpc.defs +++ b/src/lpc/Makefile-lpc.defs @@ -26,12 +26,12 @@ endif ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex CC=$(ARM_CC) -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) $(PDCLIB_INCLUDES) LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) NICKLE=nickle -LIBS=-lpdclib-cortex-m0 -lgcc +LIBS=$(PDCLIB_LIBS_M0) -lgcc V=0 # The user has explicitly enabled quiet compilation. diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index b1998f93..9adcfeb3 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -22,9 +22,9 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -LIBS=-lpdclib-cortex-m3 -lgcc +LIBS=$(PDCLIB_LIBS_M3) -lgcc -AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I../math -I.. +AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I../math -I.. $(PDCLIB_INCLUDES) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld -- cgit v1.2.3 From 1ab12861c3e70d7c22b27d988546a925616a0adc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 18 Dec 2013 23:27:34 -0800 Subject: altos/lpc: Reset less of the device on USB reset. This leaves most of the device configured across USB reset, which appears to help when sending a IN reply to the first SETUP packet; without this change, the IN reply would always get a length of 0, which is fine for SET_ADDRESS, but not for GET_DESCRIPTOR_DEVICE, which OS X appears to send before setting the address (go figure). Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 108822ce..713fbc53 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -316,6 +316,13 @@ ao_usb_disable_epn(uint8_t n) ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); } +static void +ao_usb_reset(void) +{ + ao_usb_set_address(0); + ao_usb_configuration = 0; +} + static void ao_usb_set_ep0(void) { @@ -326,11 +333,8 @@ ao_usb_set_ep0(void) lpc_usb.epinuse = 0; lpc_usb.epskip = 0xffffffff; - ao_usb_set_address(0); lpc_usb.intstat = 0xc00003ff; - ao_usb_configuration = 0; - ao_usb_sram = lpc_usb_sram; lpc_usb.epliststart = (uint32_t) (intptr_t) &lpc_usb_endpoint; @@ -346,7 +350,7 @@ ao_usb_set_ep0(void) /* Clear all of the other endpoints */ for (e = 1; e <= 4; e++) ao_usb_disable_epn(e); - + ao_usb_reset(); } static void @@ -590,7 +594,7 @@ ao_usb_ep0_handle(uint8_t receive) if (receive & AO_USB_EP0_GOT_RESET) { debug ("\treset\n"); - ao_usb_set_ep0(); + ao_usb_reset(); return; } if (receive & AO_USB_EP0_GOT_SETUP) { @@ -936,11 +940,11 @@ ao_usb_enable(void) for (t = 0; t < 1000; t++) ao_arch_nop(); + ao_usb_set_ep0(); + #if HAS_USB_PULLUP ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1); #endif - - ao_usb_set_ep0(); } #if USB_ECHO -- cgit v1.2.3 From a04c1dd5df76c9127615bc797a9d9f764eec1234 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 19 Dec 2013 00:08:50 -0800 Subject: altos/lpc: Stop sending SETUP IN when the requested size is reached The host won't keep asking for SETUP IN packets once it has received the amount of data requested, so check to see if we've sent that much and flip back to IDLE state if so. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/lpc') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 713fbc53..686dc3a4 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -58,6 +58,7 @@ static uint8_t ao_usb_ep0_state; /* Pending EP0 IN data */ static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ +static uint16_t ao_usb_ep0_in_max; /* Requested amount from host */ /* Temp buffer for smaller EP0 in data */ static uint8_t ao_usb_ep0_in_buf[2]; @@ -380,10 +381,11 @@ ao_usb_ep0_flush(void) if (this_len > AO_USB_CONTROL_SIZE) this_len = AO_USB_CONTROL_SIZE; - if (this_len < AO_USB_CONTROL_SIZE) - ao_usb_ep0_state = AO_USB_EP0_IDLE; - ao_usb_ep0_in_len -= this_len; + ao_usb_ep0_in_max -= this_len; + + if (this_len < AO_USB_CONTROL_SIZE || ao_usb_ep0_in_max == 0) + ao_usb_ep0_state = AO_USB_EP0_IDLE; debug_data ("Flush EP0 len %d:", this_len); memcpy(ao_usb_ep0_tx_buffer, ao_usb_ep0_in_data, this_len); @@ -456,6 +458,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) static void ao_usb_ep0_in_start(uint16_t max) { + ao_usb_ep0_in_max = max; /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) ao_usb_ep0_in_len = max; -- cgit v1.2.3