diff options
| author | Keith Packard <keithp@keithp.com> | 2013-04-20 00:20:55 -0500 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2013-05-17 03:50:07 -0700 | 
| commit | 9e8f6ba8b779cd9635f82d6da5f113715c3ee4c7 (patch) | |
| tree | 1fe626c49e3749630063b623a17f9a8c578cc112 | |
| parent | f9d0eb3f3154f98abb0c8952d7171f3e7d3de9b2 (diff) | |
altos/lpc: Get USART running
Adds a simple demo thread that spews data to the serial port
Signed-off-by: Keith Packard <keithp@keithp.com>
| -rw-r--r-- | src/lpc/ao_serial_lpc.c | 106 | ||||
| -rw-r--r-- | src/lpc/lpc.h | 189 | ||||
| -rw-r--r-- | src/lpc/registers.ld | 1 | ||||
| -rw-r--r-- | src/lpcxpresso/ao_demo.c | 11 | ||||
| -rw-r--r-- | src/lpcxpresso/ao_pins.h | 9 | 
5 files changed, 283 insertions, 33 deletions
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  | 
