1 /*
2  * Copyright (c) 2012 Kent Ryhorchuk
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 <lib/cbuf.h>
14 #include <kernel/thread.h>
15 #include <platform/debug.h>
16 #include <arch/ops.h>
17 #include <dev/uart.h>
18 #include <target/debugconfig.h>
19 #include <stm32f2xx_rcc.h>
20 #include <stm32f2xx_usart.h>
21 #include <arch/arm/cm.h>
22 
23 #define RXBUF_SIZE 16
24 
25 #ifdef ENABLE_UART1
26 cbuf_t uart1_rx_buf;
27 #ifndef UART1_FLOWCONTROL
28 #define UART1_FLOWCONTROL USART_HardwareFlowControl_None
29 #endif
30 #endif
31 
32 #ifdef ENABLE_UART2
33 cbuf_t uart2_rx_buf;
34 #ifndef UART2_FLOWCONTROL
35 #define UART2_FLOWCONTROL USART_HardwareFlowControl_None
36 #endif
37 #endif
38 
39 #ifdef ENABLE_UART3
40 cbuf_t uart3_rx_buf;
41 #ifndef UART3_FLOWCONTROL
42 #define UART3_FLOWCONTROL USART_HardwareFlowControl_None
43 #endif
44 #endif
45 
46 #ifdef ENABLE_UART1
47 #endif
48 #ifdef ENABLE_UART2
49 #endif
50 #ifdef ENABLE_UART3
51 #endif
52 
usart_init1_early(USART_TypeDef * usart,uint16_t flowcontrol,int irqn)53 static void usart_init1_early(USART_TypeDef *usart, uint16_t flowcontrol, int irqn) {
54     USART_InitTypeDef init;
55 
56     init.USART_BaudRate = 115200;
57     init.USART_WordLength = USART_WordLength_8b;
58     init.USART_StopBits = USART_StopBits_1;
59     init.USART_Parity = USART_Parity_No;
60     init.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
61     init.USART_HardwareFlowControl = flowcontrol;
62 
63     USART_Init(usart, &init);
64     USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
65     NVIC_DisableIRQ(irqn);
66     USART_Cmd(usart, ENABLE);
67 }
68 
usart_init1(USART_TypeDef * usart,int irqn,cbuf_t * rxbuf)69 static void usart_init1(USART_TypeDef *usart, int irqn, cbuf_t *rxbuf) {
70     cbuf_initialize(rxbuf, RXBUF_SIZE);
71     USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
72     NVIC_EnableIRQ(irqn);
73     USART_Cmd(usart, ENABLE);
74 }
75 
uart_init_early(void)76 void uart_init_early(void) {
77 #ifdef ENABLE_UART1
78     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
79 #endif
80 #ifdef ENABLE_UART2
81     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
82 #endif
83 #ifdef ENABLE_UART3
84     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
85 #endif
86 
87 #ifdef ENABLE_UART1
88     usart_init1_early(USART1, UART1_FLOWCONTROL, USART1_IRQn);
89 #endif
90 #ifdef ENABLE_UART2
91     usart_init1_early(USART2, UART2_FLOWCONTROL, USART2_IRQn);
92 #endif
93 #ifdef ENABLE_UART3
94     usart_init1_early(USART3, UART3_FLOWCONTROL, USART3_IRQn);
95 #endif
96 }
97 
uart_init(void)98 void uart_init(void) {
99 #ifdef ENABLE_UART1
100     usart_init1(USART1, USART1_IRQn, &uart1_rx_buf);
101 #endif
102 #ifdef ENABLE_UART2
103     usart_init1(USART2, USART2_IRQn, &uart2_rx_buf);
104 #endif
105 #ifdef ENABLE_UART3
106     usart_init1(USART3, USART3_IRQn, &uart3_rx_buf);
107 #endif
108 }
109 
uart_rx_irq(USART_TypeDef * usart,cbuf_t * rxbuf)110 void uart_rx_irq(USART_TypeDef *usart, cbuf_t *rxbuf) {
111     arm_cm_irq_entry();
112 
113     bool resched = false;
114     while (USART_GetFlagStatus(usart, USART_FLAG_RXNE)) {
115         if (!cbuf_space_avail(rxbuf)) {
116             // Overflow - let flow control do its thing by not
117             // reading the from the FIFO.
118             USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
119             break;
120         }
121 
122         char c = USART_ReceiveData(usart);
123         cbuf_write_char(rxbuf, c, false);
124         resched = true;
125     }
126 
127     arm_cm_irq_exit(resched);
128 }
129 
130 #ifdef ENABLE_UART1
stm32_USART1_IRQ(void)131 void stm32_USART1_IRQ(void) {
132     uart_rx_irq(USART1, &uart1_rx_buf);
133 }
134 #endif
135 
136 #ifdef ENABLE_UART2
stm32_USART2_IRQ(void)137 void stm32_USART2_IRQ(void) {
138     uart_rx_irq(USART2, &uart2_rx_buf);
139 }
140 #endif
141 
142 #ifdef ENABLE_UART3
stm32_USART3_IRQ(void)143 void stm32_USART3_IRQ(void) {
144     uart_rx_irq(USART3, &uart3_rx_buf);
145 }
146 #endif
147 
148 
usart_putc(USART_TypeDef * usart,char c)149 static void usart_putc(USART_TypeDef *usart, char c) {
150     while (USART_GetFlagStatus(usart, USART_FLAG_TXE) == 0);
151     USART_SendData(usart, c);
152     while (USART_GetFlagStatus(usart, USART_FLAG_TC) == 0);
153 }
154 
usart_getc(USART_TypeDef * usart,cbuf_t * rxbuf,bool wait)155 static int usart_getc(USART_TypeDef *usart, cbuf_t *rxbuf, bool wait) {
156     char c;
157     cbuf_read_char(rxbuf, &c, wait);
158     if (cbuf_space_avail(rxbuf) > RXBUF_SIZE/2)
159         USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
160 
161     return c;
162 }
163 
get_usart(int port)164 static USART_TypeDef *get_usart(int port) {
165     switch (port) {
166 #ifdef ENABLE_UART1
167         case 1:
168             return USART1;
169 #endif
170 #ifdef ENABLE_UART2
171         case 2:
172             return USART2;
173 #endif
174 #ifdef ENABLE_UART3
175         case 3:
176             return USART3;
177 #endif
178         default:
179             ASSERT(false);
180             return 0;
181     }
182 
183 }
184 
get_rxbuf(int port)185 static cbuf_t *get_rxbuf(int port) {
186     switch (port) {
187 #ifdef ENABLE_UART1
188         case 1:
189             return &uart1_rx_buf;
190 #endif
191 #ifdef ENABLE_UART2
192         case 2:
193             return &uart2_rx_buf;
194 #endif
195 #ifdef ENABLE_UART3
196         case 3:
197             return &uart3_rx_buf;
198 #endif
199         default:
200             ASSERT(false);
201             return 0;
202     }
203 
204 }
205 
uart_putc(int port,char c)206 int uart_putc(int port, char c) {
207     USART_TypeDef *usart = get_usart(port);
208     usart_putc(usart, c);
209     return 1;
210 }
211 
uart_getc(int port,bool wait)212 int uart_getc(int port, bool wait) {
213     cbuf_t *rxbuf = get_rxbuf(port);
214     USART_TypeDef *usart = get_usart(port);
215 
216     return usart_getc(usart, rxbuf, wait);
217 }
218 
uart_flush_tx(int port)219 void uart_flush_tx(int port) {}
220 
uart_flush_rx(int port)221 void uart_flush_rx(int port) {}
222 
uart_init_port(int port,uint baud)223 void uart_init_port(int port, uint baud) {
224     // TODO - later
225     PANIC_UNIMPLEMENTED;
226 }
227