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