diff options
Diffstat (limited to 'uart')
-rw-r--r-- | uart/uart.c | 238 | ||||
-rw-r--r-- | uart/uart.h | 28 |
2 files changed, 0 insertions, 266 deletions
diff --git a/uart/uart.c b/uart/uart.c deleted file mode 100644 index 3ead880..0000000 --- a/uart/uart.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * uart/uart.c -- hardware UART interface - * - * Copyright (C) 2016-2017 Tomasz Kramkowski <tk@the-tk.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#include <asm.h> -#include <cm4.h> -#include <reg/gpio.h> -#include <reg/port.h> -#include <reg/sim.h> -#include <reg/uart.h> -#include <stdarg.h> -#include <stddef.h> - -#include "uart.h" - -enum { - SBR_VAL = 39, - BRFA_VAL = 2, - SRBSZ = 2048, - FIFOSZ = 8, -}; - -static struct { - unsigned char buf[SRBSZ]; - int start, end; -} send_rb = { .start = 0, .end = 0 }; - -static inline size_t rb_store(void *_data, size_t size) -{ - unsigned char *data = _data; - size_t avail; - int start, end; - - start = send_rb.start; - end = send_rb.end; - avail = (start + sizeof send_rb.buf - end) % sizeof send_rb.buf - 1; - - if (size > avail) { - GPIOC_PSOR = BV(5); - size = avail; - } - - for (size_t i = 0; i < size; i++) - send_rb.buf[(end + i) % sizeof send_rb.buf] = data[i]; - send_rb.end = (end + size) % sizeof send_rb.buf; - - /* Enable Transmission Interrupt */ - CLI(); - SET_BIT(UART0_C2, C2_TIE); - STI(); - - return size; -} - -void uart_setup(void) -{ - /* Clock gating for UART0 */ - SET_BIT(SIM_SCGC4, SCGC4_UART0); - /* Disable TX and RX */ - SET_MASKED(UART0_C2, BV(C2_TE) | BV(C2_RE), 0); - /* Default settings */ - UART0_C1 = 0; - /* SBR and BRFA for baud rate */ - SET_MASKED(UART0_BDH, BDH_SBR_M, ((SBR_VAL & 0x1f00) >> 8) << BDH_SBR); - SET_MASKED(UART0_BDL, BDL_SBR_M, (SBR_VAL & 0xff) << BDL_SBR); - SET_MASKED(UART0_C4, C4_BRFA_M, BRFA_VAL << C4_BRFA); - /* flush and enable TX FIFO */ - UART0_CFIFO |= BV(CFIFO_TXFLUSH); - UART0_PFIFO |= BV(PFIFO_TXFE); - /* set watermark at 1 entry */ - SET_MASKED(UART0_TWFIFO, TWFIFO_TXWATER_M, 1 << TWFIFO_TXWATER); - /* NVIC enable interrupt */ - ISR_CLRPEND(45); - INTPRI(45) = 0xf0; - ISR_SETENA(45); - /* enable correct ALT MUX on TX pin */ - PORTB_PCR(17) = 3 << PCR_MUX; - /* enable TX */ - SET_MASKED(UART0_C2, BV(C2_TE), BV(C2_TE)); -} - -void uart_putchar(int c) -{ - static unsigned char buf[128]; - static size_t size = 0; - - if (c == '\n') - uart_putchar('\r'); - - buf[size++] = c; - - if (size >= sizeof buf || c == '\n') { - rb_store(buf, size); - size = 0; - } -} - -void uart_puts(const char *s) -{ - for (size_t i = 0; s[i]; i++) - uart_putchar(s[i]); - uart_putchar('\n'); -} - -static inline void putul(unsigned long n, int base) -{ - static const char *digits = "0123456789abcdef"; - int i; - char tmp[64]; - - if (base < 2 || base > 16) - return; - - if (n == 0) { - uart_putchar('0'); - return; - } - for (i = 0; n; i++) { - int res = n % base; - n = n / base; - tmp[i] = digits[res]; - } - - for (i -= 1; i >= 0; i--) - uart_putchar(tmp[i]); -} - -static inline void putl(long n) -{ - int i; - char tmp[64]; - - if (n < 0) { - uart_putchar('-'); - n *= -1; - } - - if (n == 0) { - uart_putchar('0'); - return; - } - - for (i = 0; n; i++) { - int res = n % 10; - n = n / 10; - tmp[i] = '0' + res; - } - - for (i -= 1; i >= 0; i--) - uart_putchar(tmp[i]); -} - -void uart_printf(const char *fmt, ...) -{ - va_list ap; - const char *p; - int ival; - unsigned uival; - long lival; - unsigned long ulival; - - va_start(ap, fmt); - for (p = fmt; *p; p++) { - if (*p != '%') { - uart_putchar(*p); - continue; - } - switch (*++p) { - case 'd': case 'i': - ival = va_arg(ap, int); - putl(ival); - break; - case 'o': case 'u': case 'x': - uival = va_arg(ap, unsigned); - switch (*p) { - case 'o': putul(uival, 8); break; - case 'u': putul(uival, 10); break; - case 'x': putul(uival, 16); break; - } - break; - case 'l': - switch (*++p) { - case 'd': case 'i': - lival = va_arg(ap, long); - putl(lival); - break; - case 'o': case 'u': case 'x': - ulival = va_arg(ap, unsigned long); - switch (*p) { - case 'o': putul(ulival, 8); break; - case 'u': putul(ulival, 10); break; - case 'x': putul(ulival, 16); break; - } - break; - } - } - } - va_end(ap); -} - -void uart0_isr(void) -{ - int avail, start, end, tosend; - - if (!GET_BIT(UART0_S1, S1_TDRE)) - return; - - avail = FIFOSZ - UART0_TCFIFO; - CLI(); - start = send_rb.start; - end = send_rb.end; - tosend = (end + sizeof send_rb.buf - start) % sizeof send_rb.buf; - if (tosend == 0) - UNSET_BIT(UART0_C2, C2_TIE); - STI(); - - if (tosend > avail) - tosend = avail; - - for (int i = 0; i < tosend; i++) - UART0_D = send_rb.buf[(start + i) % sizeof send_rb.buf]; - - send_rb.start = (start + tosend) % sizeof send_rb.buf; -} diff --git a/uart/uart.h b/uart/uart.h deleted file mode 100644 index bb5c6f7..0000000 --- a/uart/uart.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * uart/uart.h -- hardware UART interface - * - * Copyright (C) 2016-2017 Tomasz Kramkowski <tk@the-tk.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef FMK_UART_UART_H -#define FMK_UART_UART_H - -void uart_setup(void); -void uart_putchar(int c); -void uart_printf(const char *fmt, ...); -void uart_puts(const char *s); -void uart0_isr(void); - -#endif /* FMK_UART_UART_H */ |