1 /*
2  * Copyright (c) 2015 Eric Holland
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #include <stdarg.h>
9 #include <lk/reg.h>
10 #include <lk/debug.h>
11 #include <stdio.h>
12 #include <assert.h>
13 #include <lk/err.h>
14 #include <lib/cbuf.h>
15 #include <arch/arm/cm.h>
16 #include <arch/ops.h>
17 #include <dev/uart.h>
18 #include <dev/gpio.h>
19 #include <kernel/thread.h>
20 #include <platform/debug.h>
21 #include <target/debugconfig.h>
22 #include <target/gpioconfig.h>
23 
24 #define RXBUF_SIZE 16
25 
26 cbuf_t uart0_rx_buf;
27 
28 
29 
uart_init_early(void)30 void uart_init_early(void) {
31 #ifdef ENABLE_UART0
32 
33 #ifdef  UART0_TX_PIN
34     gpio_config(UART0_TX_PIN,GPIO_OUTPUT);
35     NRF_UART0->PSELTXD =   UART0_TX_PIN;
36 #endif
37 #ifdef  UART0_RX_PIN
38     gpio_config(UART0_RX_PIN,GPIO_INPUT);
39     NRF_UART0->PSELRXD =   UART0_RX_PIN;
40 #endif
41 
42     NRF_UART0->BAUDRATE =   UART_BAUDRATE_BAUDRATE_Baud115200   <<  UART_BAUDRATE_BAUDRATE_Pos;
43     NRF_UART0->CONFIG   =   UART_CONFIG_HWFC_Disabled << UART_CONFIG_HWFC_Pos | \
44                             UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos;
45     NVIC_DisableIRQ(UARTE0_UART0_IRQn);
46     NRF_UART0->ENABLE   =   UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos;
47     NRF_UART0->TXD = 'L';       //Must prime the tx queue with a character to start operation
48     NRF_UART0->TASKS_STARTTX=1;
49     NRF_UART0->TASKS_STARTRX=1;
50 #endif //ENABLE_UART0
51 }
52 
uart_init(void)53 void uart_init(void) {
54 #ifdef ENABLE_UART0
55     cbuf_initialize(&uart0_rx_buf, RXBUF_SIZE);
56     NRF_UART0->INTENSET = UART_INTENSET_RXDRDY_Enabled << UART_INTENSET_RXDRDY_Pos;
57     NRF_UART0->EVENTS_RXDRDY = 0;
58     NVIC_EnableIRQ(UARTE0_UART0_IRQn);
59     char c = NRF_UART0->RXD;
60     (void)c;
61 #endif //ENABLE_UART0
62 }
63 
nrf52_UARTE0_UART0_IRQ(void)64 void nrf52_UARTE0_UART0_IRQ(void) {
65     char c;
66     arm_cm_irq_entry();
67 
68     bool resched = false;
69     while ( NRF_UART0->EVENTS_RXDRDY > 0 ) {
70         NRF_UART0->EVENTS_RXDRDY = 0;
71         c = NRF_UART0->RXD;
72         if (!cbuf_space_avail(&uart0_rx_buf)) {
73             break;
74         }
75         cbuf_write_char(&uart0_rx_buf, c, false);
76         resched = true;
77     }
78 
79     arm_cm_irq_exit(resched);
80 }
81 
uart_putc(int port,char c)82 int uart_putc(int port, char c) {
83     while (NRF_UART0->EVENTS_TXDRDY == 0);
84     NRF_UART0->EVENTS_TXDRDY = 0;
85     NRF_UART0->TXD = c;
86     return 1;
87 }
88 
uart_getc(int port,bool wait)89 int uart_getc(int port, bool wait) {
90     cbuf_t *rxbuf = &uart0_rx_buf;
91 
92     char c;
93     if (cbuf_read_char(rxbuf, &c, wait) == 1)
94         return c;
95 
96     return -1;
97 }
98 
uart_flush_tx(int port)99 void uart_flush_tx(int port) {}
100 
uart_flush_rx(int port)101 void uart_flush_rx(int port) {}
102 
uart_init_port(int port,uint baud)103 void uart_init_port(int port, uint baud) {
104     // TODO - later
105     PANIC_UNIMPLEMENTED;
106 }
107