#include #include #include #include "serial_api.h" #include "serial_irq.h" #include "timer_dma.h" /* Defines */ #define SIRQ_LEN 1024 /* Port structure */ typedef struct { int rix; int wix; uint8_t buf[SIRQ_LEN]; } queue_t; struct sirq_t { serial_t uart; queue_t xmt; queue_t rcv; int irq; int buffered; }; /* Port data */ static sirq_t sirq_ports[SIRQ_NUM_UART]; /* Receive handler */ void sirq_handler(uint32_t _port, SerialIrq event) { sirq_t *port = (sirq_t *)_port; // Handle transmit // note: mbed seems to call TxIrq even it is not enabled, // so we need to manually prevent transmitting when the // port is set to buffered mode. if (event == TxIrq && (port->irq || !port->buffered)) { if (port->xmt.rix != port->xmt.wix) { int byte = port->xmt.buf[port->xmt.rix]; serial_putc(&port->uart, byte); port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN; } else { serial_irq_set(&port->uart, TxIrq, 0); port->irq = 0; } } // Handle receive if (event == RxIrq) { int byte = serial_getc(&port->uart); port->rcv.buf[port->rcv.wix] = byte; port->rcv.wix = (port->rcv.wix+1) % SIRQ_LEN; } } /* Open port */ sirq_t *sirq_open(sirq_uart_t uart, PinName tx, PinName rx, int baud, int buffered) { // Allocate port sirq_t *port = &sirq_ports[uart]; // Buffered ports only transmit on demand port->buffered = buffered; // Configure port serial_init(&port->uart, tx, rx); serial_baud(&port->uart, baud); // Set IRQ handlers serial_irq_handler(&port->uart, sirq_handler, (uint32_t)port); serial_irq_set(&port->uart, RxIrq, 1); return port; } /* Write byte to the port */ void sirq_putc(sirq_t *port, int byte) { port->xmt.buf[port->xmt.wix] = byte; port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN; if (!port->buffered) sirq_transmit(port); } /* Read byte from the port */ int sirq_getc(sirq_t *port) { int byte = 0; if (port->rcv.rix != port->rcv.wix) { byte = port->rcv.buf[port->rcv.rix]; port->rcv.rix = (port->rcv.rix+1) % SIRQ_LEN; } return byte; } /* Enable transmitter */ void sirq_transmit(sirq_t *port) { if (port->xmt.rix != port->xmt.wix && !port->irq) { port->irq = 1; serial_irq_set(&port->uart, TxIrq, 1); } } /* Buffered write */ void sirq_write(sirq_t *port, void *data, int len) { uint8_t *bytes = (uint8_t*)data; for (int i = 0; i < len; i++) sirq_putc(port, bytes[i]); } /* Check if port is writable */ int sirq_ready(sirq_t *port) { return port->rcv.rix != port->rcv.wix; } /* Debug print */ void sirq_debug(sirq_t *port) { sirq_printf("xmt - wix:%03x rix:%03x\r\n", port->xmt.wix, port->xmt.rix); sirq_printf("rcv - wix:%03x rix:%03x\r\n", port->rcv.wix, port->rcv.rix); sirq_printf("irq - ??\r\n"); sirq_printf("uart - ??\r\n"); } /* Write ASCII data to the output queue */ void sirq_vprintf(const char *fmt, va_list ap) { static char buf[512]; int len = vsnprintf(buf, sizeof(buf), fmt, ap); for (int i = 0; i < len; i++) sirq_putc(&sirq_ports[0], buf[i]); } void sirq_printf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); sirq_vprintf(fmt, ap); va_end(ap); }