From f560c961ae4fedec0c9f11d5b3635fcb0d67ed8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Mar 2012 16:18:26 -0700 Subject: [PATCH] Add support for multiple serial ports on STM32L Signed-off-by: Keith Packard --- src/stm-demo/ao_pins.h | 2 + src/stm/ao_serial_stm.c | 236 ++++++++++++++++++++++++++++------------ 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 -__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 */ -- 2.30.2