summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-01-19 23:53:27 -0800
committerKeith Packard <keithp@keithp.com>2016-04-25 11:49:16 -0400
commit7c9a111ac1c88467ce28e03b4a9d3eabc9d7015b (patch)
tree60149978869c88be338068d07be470a70c162f56 /src
parenteee2ca7fa7fd77be8ca5806cad7e250053465048 (diff)
altos: Use TXE instead of TC for serial on STM32l
Using TXE allows for full-speed communication, rather than waiting for each byte to be transmitted before inserting the next into the queue. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'src')
-rw-r--r--src/stm/ao_arch_funcs.h2
-rw-r--r--src/stm/ao_serial_stm.c38
2 files changed, 33 insertions, 7 deletions
diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h
index f1d17ed1..6fcfd5f8 100644
--- a/src/stm/ao_arch_funcs.h
+++ b/src/stm/ao_arch_funcs.h
@@ -284,6 +284,8 @@ struct ao_stm_usart {
struct ao_fifo tx_fifo;
struct stm_usart *reg;
uint8_t tx_started;
+ uint8_t tx_running;
+ uint8_t draining;
};
#if HAS_SERIAL_1
diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c
index 9959e460..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,10 +57,18 @@ 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);
+ }
}
}
@@ -105,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();
}
@@ -153,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) |
@@ -234,6 +249,7 @@ ao_serial1_drain(void)
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 */
@@ -277,6 +293,7 @@ ao_serial2_drain(void)
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 */
@@ -314,8 +331,15 @@ _ao_serial3_sleep_for(uint16_t 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