diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lpc/Makefile.defs | 2 | ||||
| -rw-r--r-- | src/lpc/altos.ld | 5 | ||||
| -rw-r--r-- | src/lpc/ao_arch.h | 8 | ||||
| -rw-r--r-- | src/lpc/ao_arch_funcs.h | 2 | ||||
| -rw-r--r-- | src/lpc/ao_timer_lpc.c | 33 | ||||
| -rw-r--r-- | src/lpc/ao_usb_lpc.c | 811 | ||||
| -rw-r--r-- | src/lpc/lpc.h | 89 | ||||
| -rw-r--r-- | src/lpc/registers.ld | 2 | ||||
| -rw-r--r-- | src/lpcxpresso/Makefile | 2 | ||||
| -rw-r--r-- | src/lpcxpresso/ao_demo.c | 26 | ||||
| -rw-r--r-- | src/lpcxpresso/ao_pins.h | 5 | 
11 files changed, 446 insertions, 539 deletions
| 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 <ao.h> +#include <ao_usb.h>  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 | 
