diff options
| author | Keith Packard <keithp@keithp.com> | 2012-03-21 16:18:26 -0700 | 
|---|---|---|
| committer | Keith Packard <keithp@keithp.com> | 2012-03-28 21:37:03 -0700 | 
| commit | f560c961ae4fedec0c9f11d5b3635fcb0d67ed8e (patch) | |
| tree | 9859759edb9c75fbf8818c4aaae0a70b0e6f1942 /src | |
| parent | faf2bea4fdb3dca7fbed35423a4fe4459ee92ceb (diff) | |
Add support for multiple serial ports on STM32L
Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/stm-demo/ao_pins.h | 2 | ||||
| -rw-r--r-- | src/stm/ao_serial_stm.c | 236 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 2 | 
3 files changed, 168 insertions, 72 deletions
| diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 39d4fc3c..c72cd04b 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,6 +19,8 @@  #define _AO_PINS_H_  #define HAS_SERIAL_1		1 +#define HAS_SERIAL_2		1 +#define HAS_SERIAL_3		1  #define USE_SERIAL_STDIN	1  #define HAS_USB			0  #define HAS_BEEP		0 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 38f16e5e..9302bdf8 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -17,8 +17,22 @@  #include <ao.h> -__xdata struct ao_fifo	ao_usart1_rx_fifo; -__xdata struct ao_fifo	ao_usart1_tx_fifo; +struct ao_stm_usart { +	struct ao_fifo		rx_fifo; +	struct ao_fifo		tx_fifo; +	struct stm_usart	*reg; +	uint8_t			tx_started; +}; + +#if HAS_SERIAL_1 +struct ao_stm_usart ao_stm_usart1; +#endif +#if HAS_SERIAL_2 +struct ao_stm_usart ao_stm_usart2; +#endif +#if HAS_SERIAL_3 +struct ao_stm_usart ao_stm_usart3; +#endif  void  ao_debug_out(char c) @@ -29,107 +43,106 @@ ao_debug_out(char c)  	stm_usart1.dr = c;  } +#if 0  void  outbyte(char c)  {  	putchar(c);  } - -static __xdata uint8_t ao_serial_tx1_started; +#endif  static void -ao_serial_tx1_start(void) +ao_usart_tx_start(struct ao_stm_usart *usart)  { -	if (!ao_fifo_empty(ao_usart1_tx_fifo) && -	    !ao_serial_tx1_started) +	if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started)  	{ -		ao_serial_tx1_started = 1; -		ao_fifo_remove(ao_usart1_tx_fifo, stm_usart1.dr); +		usart->tx_started = 1; +		ao_fifo_remove(usart->tx_fifo, usart->reg->dr);  	}  } -void stm_usart1_isr(void) +static void +ao_usart_isr(struct ao_stm_usart *usart, int stdin)  {  	uint32_t	sr; -	sr = stm_usart1.sr; -	stm_usart1.sr = 0; +	sr = usart->reg->sr; +	usart->reg->sr = 0;  	if (sr & (1 << STM_USART_SR_RXNE)) { -		char c = stm_usart1.dr; -		if (!ao_fifo_full(ao_usart1_rx_fifo)) -			ao_fifo_insert(ao_usart1_rx_fifo, c); -		ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN -		ao_wakeup(&ao_stdin_ready); -#endif +		char c = usart->reg->dr; +		if (!ao_fifo_full(usart->rx_fifo)) +			ao_fifo_insert(usart->rx_fifo, c); +		ao_wakeup(&usart->rx_fifo); +		if (stdin) +			ao_wakeup(&ao_stdin_ready);  	}  	if (sr & (1 << STM_USART_SR_TC)) { -		ao_serial_tx1_started = 0; -		ao_serial_tx1_start(); -		ao_wakeup(&ao_usart1_tx_fifo); +		usart->tx_started = 0; +		ao_usart_tx_start(usart); +		ao_wakeup(&usart->tx_fifo);  	}  } +#if HAS_SERIAL_1 +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } +#endif +#if HAS_SERIAL_2 +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } +#endif +#if HAS_SERIAL_3 +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } +#endif +  char -ao_serial_getchar(void) __critical +ao_usart_getchar(struct ao_stm_usart *usart)  { -	char	c; +	char c;  	cli(); -	while (ao_fifo_empty(ao_usart1_rx_fifo)) -		ao_sleep(&ao_usart1_rx_fifo); -	ao_fifo_remove(ao_usart1_rx_fifo, c); +	while (ao_fifo_empty(usart->rx_fifo)) +		ao_sleep(&usart->rx_fifo); +	ao_fifo_remove(usart->rx_fifo, c);  	sei();  	return c;  } -#if USE_SERIAL_STDIN  char -ao_serial_pollchar(void) __critical +ao_usart_pollchar(struct ao_stm_usart *usart)  {  	char	c;  	cli(); -	if (ao_fifo_empty(ao_usart1_rx_fifo)) { +	if (ao_fifo_empty(usart->rx_fifo)) {  		sei();  		return AO_READ_AGAIN;  	} -	ao_fifo_remove(ao_usart1_rx_fifo,c); +	ao_fifo_remove(usart->rx_fifo,c);  	sei();  	return c;  } -#endif  void -ao_serial_putchar(char c) __critical +ao_usart_putchar(struct ao_stm_usart *usart, char c)  {  	cli(); -	while (ao_fifo_full(ao_usart1_tx_fifo)) -		ao_sleep(&ao_usart1_tx_fifo); -	ao_fifo_insert(ao_usart1_tx_fifo, c); -	ao_serial_tx1_start(); +	while (ao_fifo_full(usart->tx_fifo)) +		ao_sleep(&usart->tx_fifo); +	ao_fifo_insert(usart->tx_fifo, c); +	ao_usart_tx_start(usart);  	sei();  }  void -ao_serial_drain(void) __critical +ao_usart_drain(struct ao_stm_usart *usart)  {  	cli(); -	while (!ao_fifo_empty(ao_usart1_tx_fifo)) -		ao_sleep(&ao_usart1_tx_fifo); +	while (!ao_fifo_empty(usart->tx_fifo)) +		ao_sleep(&usart->tx_fifo);  	sei();  } -int _write(int file, char *ptr, int len) -{ -	int l = len; -	while (l--) -		ao_debug_out(*ptr++); -	return len; -} -  static const struct {  	uint32_t brr; -} ao_serial_speeds[] = { +} ao_usart_speeds[] = {  	[AO_SERIAL_SPEED_4800] = {  		STM_APB1 / 4800  	}, @@ -145,30 +158,17 @@ static const struct {  };  void -ao_serial_set_speed(uint8_t speed) +ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)  { -#if 0 -	ao_serial_drain(); -#endif  	if (speed > AO_SERIAL_SPEED_57600)  		return; -	stm_usart1.brr = ao_serial_speeds[speed].brr; +	stm_usart1.brr = ao_usart_speeds[speed].brr;  }  void -ao_serial_init(void) +ao_usart_init(struct ao_stm_usart *usart)  { -	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - -	stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); -	stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); -	stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); -	stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); -	 -	/* Enable USART1 */ -	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - -	stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | +	usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |  			  (1 << STM_USART_CR1_UE) |  			  (0 << STM_USART_CR1_M) |  			  (0 << STM_USART_CR1_WAKE) | @@ -184,7 +184,7 @@ ao_serial_init(void)  			  (0 << STM_USART_CR1_RWU) |  			  (0 << STM_USART_CR1_SBK)); -	stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | +	usart->reg->cr2 = ((0 << STM_USART_CR2_LINEN) |  			  (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |  			  (0 << STM_USART_CR2_CLKEN) |  			  (0 << STM_USART_CR2_CPOL) | @@ -194,7 +194,7 @@ ao_serial_init(void)  			  (0 << STM_USART_CR2_LBDL) |  			  (0 << STM_USART_CR2_ADD)); -	stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | +	usart->reg->cr3 = ((0 << STM_USART_CR3_ONEBITE) |  			  (0 << STM_USART_CR3_CTSIE) |  			  (0 << STM_USART_CR3_CTSE) |  			  (0 << STM_USART_CR3_RTSE) | @@ -208,15 +208,107 @@ ao_serial_init(void)  			  (0 << STM_USART_CR3_EIE));  	/* Pick a 9600 baud rate */ -	ao_serial_set_speed(AO_SERIAL_SPEED_9600); +	ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); +} + +void +ao_serial_init(void) +{ +#ifdef HAS_SERIAL_1 +	/* +	 *	TX	RX +	 *	PA9	PA10 +	 *	PB6	PB7 +	 */ + +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + +	stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); +	stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); +	stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); +	stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); +	 +	/* Enable USART */ +	stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); -	printf ("serial initialized\n"); +	ao_stm_usart1.reg = &stm_usart1; + +	stm_nvic_set_enable(STM_ISR_USART1_POS); +	stm_nvic_set_priority(STM_ISR_USART1_POS, 4);  #if USE_SERIAL_STDIN  	ao_add_stdio(ao_serial_pollchar,  		     ao_serial_putchar,  		     NULL);  #endif +#endif -	stm_nvic_set_enable(STM_ISR_USART1_POS); -	stm_nvic_set_priority(STM_ISR_USART1_POS, 4); +#if HAS_SERIAL_2 +	/* +	 *	TX	RX +	 *	PA2	PA3 +	 *	PD5	PD6 +	 */ + +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + +	stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE); +	stm_moder_set(&stm_gpioa, 3, STM_MODER_ALTERNATE); +	stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); +	stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); +	 +	/* Enable USART */ +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); + +	ao_stm_usart2.reg = &stm_usart2; + +	stm_nvic_set_enable(STM_ISR_USART2_POS); +	stm_nvic_set_priority(STM_ISR_USART2_POS, 4); +#endif + +#if HAS_SERIAL_3 +	/* +	 * 	TX	RX +	 *	PB10	PB11 +	 *	PC10	PC11 +	 *	PD8	PD9 +	 */ +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + +	stm_moder_set(&stm_gpiob, 10, STM_MODER_ALTERNATE); +	stm_moder_set(&stm_gpiob, 11, STM_MODER_ALTERNATE); +	stm_afr_set(&stm_gpiob, 10, STM_AFR_AF7); +	stm_afr_set(&stm_gpiob, 11, STM_AFR_AF7); +	 +	/* Enable USART */ +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); + +	ao_stm_usart3.reg = &stm_usart3; + +	stm_nvic_set_enable(STM_ISR_USART3_POS); +	stm_nvic_set_priority(STM_ISR_USART3_POS, 4); +#endif +} + +#if HAS_SERIAL_1 +char +ao_serial_getchar(void) +{ +	return ao_usart_getchar(&ao_stm_usart1); +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) +{ +	return ao_usart_pollchar(&ao_stm_usart1); +} +#endif + +void +ao_serial_putchar(char c) +{ +	ao_usart_putchar(&ao_stm_usart1, c);  } +#endif /* HAS_SERIAL_1 */ + + diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index d7c382a6..21dc9a14 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -174,6 +174,8 @@ struct stm_usart {  };  extern struct stm_usart	stm_usart1; +extern struct stm_usart stm_usart2; +extern struct stm_usart stm_usart3;  #define STM_USART_SR_CTS	(9)	/* CTS flag */  #define STM_USART_SR_LBD	(8)	/* LIN break detection flag */ | 
