X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fstm%2Fao_serial_stm.c;h=e7b6ab78d71acfa79b3724c0e8379825b337e312;hb=7c9a111ac1c88467ce28e03b4a9d3eabc9d7015b;hp=ce33f97e97416eaaf2a9eddfb54ba9f19943cb9e;hpb=a4a841828924ee37f5201d4ff0aec38459f2d802;p=fw%2Faltos diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index ce33f97e..e7b6ab78 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -26,14 +26,19 @@ ao_debug_out(char c) stm_usart1.dr = c; } -static void +static int _ao_usart_tx_start(struct ao_stm_usart *usart) { if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) { usart->tx_started = 1; + usart->tx_running = 1; + usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); ao_fifo_remove(usart->tx_fifo, usart->reg->dr); + ao_wakeup(&usart->tx_fifo); + return 1; } + return 0; } static void @@ -52,45 +57,59 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) if (stdin) ao_wakeup(&ao_stdin_ready); } - if (sr & (1 << STM_USART_SR_TC)) { + if (sr & (1 << STM_USART_SR_TXE)) { usart->tx_started = 0; - _ao_usart_tx_start(usart); - ao_wakeup(&usart->tx_fifo); + if (!_ao_usart_tx_start(usart)) + usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); + } + if (sr & (1 << STM_USART_SR_TC)) { + usart->tx_running = 0; + usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE); + if (usart->draining) { + usart->draining = 0; + ao_wakeup(&usart->tx_fifo); + } } -} - -char -ao_usart_getchar(struct ao_stm_usart *usart) -{ - char c; - ao_arch_block_interrupts(); - while (ao_fifo_empty(usart->rx_fifo)) - ao_sleep(&usart->rx_fifo); - ao_fifo_remove(usart->rx_fifo, c); - ao_arch_release_interrupts(); - return c; } int -ao_usart_pollchar(struct ao_stm_usart *usart) +_ao_usart_pollchar(struct ao_stm_usart *usart) { int c; - - ao_arch_block_interrupts(); + if (ao_fifo_empty(usart->rx_fifo)) c = AO_READ_AGAIN; else { uint8_t u; ao_fifo_remove(usart->rx_fifo,u); c = u; + ao_usb_putchar(c); ao_usb_flush(); } - ao_arch_release_interrupts(); return c; } +char +ao_usart_getchar(struct ao_stm_usart *usart) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN) + ao_sleep(&usart->rx_fifo); + ao_arch_release_interrupts(); + ao_usb_putchar(c); ao_usb_flush(); + return (char) c; +} + +static inline uint8_t +_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout) +{ + return ao_sleep_for(&usart->rx_fifo, timeout); +} + void ao_usart_putchar(struct ao_stm_usart *usart, char c) { + ao_usb_putchar(c); ao_usb_flush(); ao_arch_block_interrupts(); while (ao_fifo_full(usart->tx_fifo)) ao_sleep(&usart->tx_fifo); @@ -99,12 +118,14 @@ ao_usart_putchar(struct ao_stm_usart *usart, char c) ao_arch_release_interrupts(); } -void +static void ao_usart_drain(struct ao_stm_usart *usart) { ao_arch_block_interrupts(); - while (!ao_fifo_empty(usart->tx_fifo)) + while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) { + usart->draining = 1; ao_sleep(&usart->tx_fifo); + } ao_arch_release_interrupts(); } @@ -147,7 +168,7 @@ ao_usart_init(struct ao_stm_usart *usart) (0 << STM_USART_CR1_PS) | (0 << STM_USART_CR1_PEIE) | (0 << STM_USART_CR1_TXEIE) | - (1 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_TCIE) | (1 << STM_USART_CR1_RXNEIE) | (0 << STM_USART_CR1_IDLEIE) | (1 << STM_USART_CR1_TE) | @@ -182,6 +203,13 @@ ao_usart_init(struct ao_stm_usart *usart) ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); } +void +ao_usart_set_flow(struct ao_stm_usart *usart) +{ + usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | + (1 << STM_USART_CR3_RTSE)); +} + #if HAS_SERIAL_1 struct ao_stm_usart ao_stm_usart1; @@ -201,14 +229,27 @@ ao_serial1_putchar(char c) } int -ao_serial1_pollchar(void) +_ao_serial1_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart1); +} + +uint8_t +_ao_serial1_sleep_for(uint16_t timeout) +{ + return _ao_usart_sleep_for(&ao_stm_usart1, timeout); +} + +void +ao_serial1_drain(void) { - return ao_usart_pollchar(&ao_stm_usart1); + ao_usart_drain(&ao_stm_usart1); } void ao_serial1_set_speed(uint8_t speed) { + ao_usart_drain(&ao_stm_usart1); ao_usart_set_speed(&ao_stm_usart1, speed); } #endif /* HAS_SERIAL_1 */ @@ -232,14 +273,27 @@ ao_serial2_putchar(char c) } int -ao_serial2_pollchar(void) +_ao_serial2_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart2); +} + +uint8_t +_ao_serial2_sleep_for(uint16_t timeout) { - return ao_usart_pollchar(&ao_stm_usart2); + return _ao_usart_sleep_for(&ao_stm_usart2, timeout); +} + +void +ao_serial2_drain(void) +{ + ao_usart_drain(&ao_stm_usart2); } void ao_serial2_set_speed(uint8_t speed) { + ao_usart_drain(&ao_stm_usart2); ao_usart_set_speed(&ao_stm_usart2, speed); } #endif /* HAS_SERIAL_2 */ @@ -263,16 +317,29 @@ ao_serial3_putchar(char c) } int -ao_serial3_pollchar(void) +_ao_serial3_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart3); +} + +uint8_t +_ao_serial3_sleep_for(uint16_t timeout) { - return ao_usart_pollchar(&ao_stm_usart3); + return _ao_usart_sleep_for(&ao_stm_usart3, timeout); } void ao_serial3_set_speed(uint8_t speed) { + ao_usart_drain(&ao_stm_usart3); ao_usart_set_speed(&ao_stm_usart3, speed); } + +void +ao_serial3_drain(void) +{ + ao_usart_drain(&ao_stm_usart3); +} #endif /* HAS_SERIAL_3 */ void @@ -308,8 +375,8 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); -#if USE_SERIAL_1_STDIN - ao_add_stdio(ao_serial1_pollchar, +#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN + ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, NULL); #endif @@ -327,26 +394,36 @@ ao_serial_init(void) stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); +#if USE_SERIAL_2_FLOW + stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7); +#endif #else #if SERIAL_2_PD5_PD6 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); stm_afr_set(&stm_gpiod, 5, STM_AFR_AF7); stm_afr_set(&stm_gpiod, 6, STM_AFR_AF7); +#if USE_SERIAL_2_FLOW +#error "Don't know how to set flowcontrol for serial 2 on PD" +#endif #else #error "No SERIAL_2 port configuration specified" -#endif +#endif #endif /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); ao_stm_usart2.reg = &stm_usart2; ao_usart_init(&ao_stm_usart2); +#if USE_SERIAL_2_FLOW + ao_usart_set_flow(&ao_stm_usart2); +#endif stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); -#if USE_SERIAL_2_STDIN - ao_add_stdio(ao_serial2_pollchar, +#if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN + ao_add_stdio(_ao_serial2_pollchar, ao_serial2_putchar, NULL); #endif @@ -389,12 +466,10 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART3_POS); stm_nvic_set_priority(STM_ISR_USART3_POS, 4); -#if USE_SERIAL_3_STDIN - ao_add_stdio(ao_serial3_pollchar, +#if USE_SERIAL_3_STDIN && !DELAY_SERIAL_3_STDIN + ao_add_stdio(_ao_serial3_pollchar, ao_serial3_putchar, NULL); #endif #endif } - -