serial: add serial_flush()
authorCyprien LAPLACE <cyprien@cypou.net>
Sun, 5 Apr 2015 12:23:50 +0000 (14:23 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 16:03:04 +0000 (17:03 +0100)
Only return once all the in-buffer characters are sent.
Also call uart handler while waiting interrupt off!

Now hard fault are visible :)

drivers/serial.c
include/drivers/serial.h

index 5730b9d..27735a1 100644 (file)
@@ -83,11 +83,8 @@ static struct uart_device uarts[NUM_UARTS] = {
        },
 };
 
-/* Generic UART handler */
-static void UART_Handler(struct uart_device* uart)
+static void uart_check_rx(struct uart_device* uart, uint32_t intr)
 {
-       uint32_t intr = uart->regs->func.intr_pending;
-
        if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_RX) {
                uint8_t data = uart->regs->func.buffer;
                if (uart->rx_callback != NULL) {
@@ -98,6 +95,10 @@ static void UART_Handler(struct uart_device* uart)
                        uart->regs->func.buffer = data;
                }
        }
+}
+
+static void uart_check_tx(struct uart_device* uart, uint32_t intr)
+{
        /* We are currently sending, send next char */
        if ((intr & LPC_UART_INT_MASK) == LPC_UART_INT_TX) {
                if (uart->out_buff && uart->sending && (uart->out_length > uart->sending)) {
@@ -109,6 +110,15 @@ static void UART_Handler(struct uart_device* uart)
        }
 }
 
+/* Generic UART handler */
+static void UART_Handler(struct uart_device* uart)
+{
+       uint32_t intr = uart->regs->func.intr_pending;
+
+       uart_check_rx(uart, intr);
+       uart_check_tx(uart, intr);
+}
+
 
 /* Handlers */
 void UART_0_Handler(void)
@@ -163,7 +173,10 @@ int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
 
        /* If UART is sending wait for buffer empty */
        /* FIXME : be smart for OS, call scheduler or return */
-       do {} while (uart->sending != 0);
+       while (uart->sending != 0) {
+               if (get_priority_mask() == 0)
+                       uart_check_tx(uart, uart->regs->func.intr_pending);
+       }
 
        if (length > SERIAL_OUT_BUFF_SIZE) {
                length = SERIAL_OUT_BUFF_SIZE;
@@ -181,6 +194,35 @@ int serial_write(uint32_t uart_num, const char *buf, uint32_t length)
 }
 
 
+/***************************************************************************** */
+/*    Serial Flush
+ *
+ * Wait until all characters have been sent
+ * Returns -1 on error, 0 on success.
+ * Possible errors: requested uart does not exists or unable to acquire uart lock.
+ *
+ * Warning for Real Time : This implementation will block if there's already a
+ * transmission ongoing.
+ */
+int serial_flush(uint32_t uart_num)
+{
+       struct uart_device* uart = NULL;
+
+       if (uart_num >= NUM_UARTS)
+               return -1;
+
+       uart = &uarts[uart_num];
+
+       /* Active wait for message to be sent. If interrupts are
+        * disabled, call the UART handler while waiting. */
+       while (uart->sending) {
+               if (get_priority_mask() == 0)
+                       uart_check_tx(uart, uart->regs->func.intr_pending);
+       }
+
+       return 0;
+}
+
 
 /***************************************************************************** */
 /*   UART Setup : private part : Clocks, Pins, Power and Mode   */
index dede5f0..c31e855 100644 (file)
  */
 int serial_write(uint32_t uart_num, const char *buf, uint32_t length);
 
+/***************************************************************************** */
+/*    Serial Flush
+ *
+ * Wait until all characters have been sent
+ * Returns -1 on error, 0 on success.
+ * Possible errors: requested uart does not exists or unable to acquire uart lock.
+ *
+ * Warning for Real Time : This implementation will block if there's already a
+ * transmission ongoing.
+ */
+int serial_flush(uint32_t uart_num);