diff options
Diffstat (limited to 'src/sam3x8e/serial.c')
-rw-r--r-- | src/sam3x8e/serial.c | 125 |
1 files changed, 10 insertions, 115 deletions
diff --git a/src/sam3x8e/serial.c b/src/sam3x8e/serial.c index f4a65aa0..b10e8d8b 100644 --- a/src/sam3x8e/serial.c +++ b/src/sam3x8e/serial.c @@ -1,32 +1,15 @@ // sam3x8e serial port // -// Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net> // // This file may be distributed under the terms of the GNU GPLv3 license. -#include <string.h> // memmove #include "autoconf.h" // CONFIG_SERIAL_BAUD #include "board/gpio.h" // gpio_peripheral -#include "board/io.h" // readl -#include "board/irq.h" // irq_save -#include "board/misc.h" // console_sendf -#include "command.h" // DECL_CONSTANT +#include "board/serial_irq.h" // serial_rx_data #include "sam3x8e.h" // UART #include "sched.h" // DECL_INIT -#define SERIAL_BUFFER_SIZE 96 -static char receive_buf[SERIAL_BUFFER_SIZE]; -static uint32_t receive_pos; -static char transmit_buf[SERIAL_BUFFER_SIZE]; -static uint32_t transmit_pos, transmit_max; - - -/**************************************************************** - * Serial hardware - ****************************************************************/ - -DECL_CONSTANT(SERIAL_BAUD, CONFIG_SERIAL_BAUD); - void serial_init(void) { @@ -54,108 +37,20 @@ void __visible UART_Handler(void) { uint32_t status = UART->UART_SR; - if (status & UART_SR_RXRDY) { - uint8_t data = UART->UART_RHR; - if (data == MESSAGE_SYNC) - sched_wake_tasks(); - if (receive_pos >= sizeof(receive_buf)) - // Serial overflow - ignore it as crc error will force retransmit - return; - receive_buf[receive_pos++] = data; - return; - } + if (status & UART_SR_RXRDY) + serial_rx_byte(UART->UART_RHR); if (status & UART_SR_TXRDY) { - if (transmit_pos >= transmit_max) + uint8_t data; + int ret = serial_get_tx_byte(&data); + if (ret) UART->UART_IDR = UART_IDR_TXRDY; else - UART->UART_THR = transmit_buf[transmit_pos++]; - } -} - -// Enable tx interrupts -static void -enable_tx_irq(void) -{ - UART->UART_IER = UART_IDR_TXRDY; -} - - -/**************************************************************** - * Console access functions - ****************************************************************/ - -// Remove from the receive buffer the given number of bytes -static void -console_pop_input(uint32_t len) -{ - uint32_t copied = 0; - for (;;) { - uint32_t rpos = readl(&receive_pos); - uint32_t needcopy = rpos - len; - if (needcopy) { - memmove(&receive_buf[copied], &receive_buf[copied + len] - , needcopy - copied); - copied = needcopy; - sched_wake_tasks(); - } - irqstatus_t flag = irq_save(); - if (rpos != readl(&receive_pos)) { - // Raced with irq handler - retry - irq_restore(flag); - continue; - } - receive_pos = needcopy; - irq_restore(flag); - break; + UART->UART_THR = data; } } -// Process any incoming commands -void -console_task(void) -{ - uint8_t pop_count; - uint32_t rpos = readl(&receive_pos); - int8_t ret = command_find_block(receive_buf, rpos, &pop_count); - if (ret > 0) - command_dispatch(receive_buf, pop_count); - if (ret) - console_pop_input(pop_count); -} -DECL_TASK(console_task); - -// Encode and transmit a "response" message void -console_sendf(const struct command_encoder *ce, va_list args) +serial_enable_tx_irq(void) { - // Verify space for message - uint32_t tpos = readl(&transmit_pos), tmax = readl(&transmit_max); - if (tpos >= tmax) { - tpos = tmax = 0; - writel(&transmit_max, 0); - writel(&transmit_pos, 0); - } - uint32_t max_size = ce->max_size; - if (tmax + max_size > sizeof(transmit_buf)) { - if (tmax + max_size - tpos > sizeof(transmit_buf)) - // Not enough space for message - return; - // Disable TX irq and move buffer - writel(&transmit_max, 0); - tpos = readl(&transmit_pos); - tmax -= tpos; - memmove(&transmit_buf[0], &transmit_buf[tpos], tmax); - writel(&transmit_pos, 0); - writel(&transmit_max, tmax); - enable_tx_irq(); - } - - // Generate message - char *buf = &transmit_buf[tmax]; - uint32_t msglen = command_encodef(buf, ce, args); - command_add_frame(buf, msglen); - - // Start message transmit - writel(&transmit_max, tmax + msglen); - enable_tx_irq(); + UART->UART_IER = UART_IDR_TXRDY; } |