blob: 92a896d329993e9c72076c2b3f5658068ef820e2 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2012 Kent Ryhorchuk
3 * Copyright (c) 2015 Travis Geiselbrecht
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files
7 * (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge,
9 * publish, distribute, sublicense, and/or sell copies of the Software,
10 * and to permit persons to whom the Software is furnished to do so,
11 * subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#include <stdarg.h>
25#include <reg.h>
26#include <debug.h>
27#include <stdio.h>
28#include <assert.h>
29#include <err.h>
30#include <lib/cbuf.h>
31#include <kernel/thread.h>
32#include <platform/debug.h>
33#include <arch/ops.h>
34#include <dev/uart.h>
35#include <target/debugconfig.h>
36#include <platform/stm32.h>
37#include <arch/arm/cm.h>
38
39#define DEFAULT_FLOWCONTROL UART_HWCONTROL_NONE
40#define DEFAULT_BAUDRATE 115200
41#define DEFAULT_RXBUF_SIZE 16
42
43#define NUM_UARTS 8
44
45struct uart_instance {
46 UART_HandleTypeDef handle;
47 cbuf_t rx_buf;
48};
49
50#if ENABLE_UART1
51static struct uart_instance uart1;
52#ifndef UART1_FLOWCONTROL
53#define UART1_FLOWCONTROL DEFAULT_FLOWCONTROL
54#endif
55#ifndef UART1_BAUDRATE
56#define UART1_BAUDRATE DEFAULT_BAUDRATE
57#endif
58#ifndef UART1_RXBUF_SIZE
59#define UART1_RXBUF_SIZE DEFAULT_RXBUF_SIZE
60#endif
61#endif
62
63#if ENABLE_UART3
64static struct uart_instance uart3;
65#ifndef UART3_FLOWCONTROL
66#define UART3_FLOWCONTROL DEFAULT_FLOWCONTROL
67#endif
68#ifndef UART3_BAUDRATE
69#define UART3_BAUDRATE DEFAULT_BAUDRATE
70#endif
71#ifndef UART3_RXBUF_SIZE
72#define UART3_RXBUF_SIZE DEFAULT_RXBUF_SIZE
73#endif
74#endif
75
76#if ENABLE_UART2 || ENABLE_UART4 || ENABLE_UART5 || ENABLE_UART6 || ENABLE_UART7 || ENABLE_UART8
77#error add support for additional uarts
78#endif
79
80static struct uart_instance * const uart[NUM_UARTS + 1] = {
81#if ENABLE_UART1
82 [1] = &uart1,
83#endif
84#if ENABLE_UART3
85 [3] = &uart3,
86#endif
87};
88
89// This function is called by HAL_UART_Init().
90void HAL_UART_MspInit(UART_HandleTypeDef *huart)
91{
92 RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;
93
94 /* Select SysClk as source of UART clocks */
95 switch ((uintptr_t)huart->Instance) {
96 case (uintptr_t)USART1:
97 RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
98 RCC_PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
99 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
100
101 __HAL_RCC_USART1_CLK_ENABLE();
102 break;
103 case (uintptr_t)USART3:
104 RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3;
105 RCC_PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;
106 HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);
107
108 __HAL_RCC_USART3_CLK_ENABLE();
109 break;
110 default:
111 panic("unimplemented clock set up for uart\n");
112 }
113}
114
115static void usart_init_early(struct uart_instance *u, USART_TypeDef *usart, uint32_t baud, uint16_t flowcontrol)
116{
117 u->handle.Instance = usart;
118 u->handle.Init.BaudRate = baud;
119 u->handle.Init.WordLength = UART_WORDLENGTH_8B;
120 u->handle.Init.StopBits = UART_STOPBITS_1;
121 u->handle.Init.Parity = UART_PARITY_NONE;
122 u->handle.Init.Mode = UART_MODE_TX_RX;
123 u->handle.Init.HwFlowCtl = flowcontrol;
124 u->handle.Init.OverSampling = UART_OVERSAMPLING_8;
125 HAL_UART_Init(&u->handle);
126}
127
128static void usart_init(struct uart_instance *u, USART_TypeDef *usart, uint irqn, size_t rxsize)
129{
130 cbuf_initialize(&u->rx_buf, rxsize);
131
132 /* Enable the UART Parity Error Interrupt */
133 __HAL_UART_ENABLE_IT(&u->handle, UART_IT_PE);
134
135 /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
136 __HAL_UART_ENABLE_IT(&u->handle, UART_IT_ERR);
137
138 /* Enable the UART Data Register not empty Interrupt */
139 __HAL_UART_ENABLE_IT(&u->handle, UART_IT_RXNE);
140
141 HAL_NVIC_EnableIRQ(irqn);
142}
143
144void uart_init_early(void)
145{
146#if ENABLE_UART1
147 usart_init_early(uart[1], USART1, UART1_BAUDRATE, UART1_FLOWCONTROL);
148#endif
149#if ENABLE_UART3
150 usart_init_early(uart[3], USART3, UART3_BAUDRATE, UART3_FLOWCONTROL);
151#endif
152}
153
154void uart_init(void)
155{
156#ifdef ENABLE_UART1
157 usart_init(uart[1], USART1, USART1_IRQn, UART1_RXBUF_SIZE);
158#endif
159#ifdef ENABLE_UART3
160 usart_init(uart[3], USART3, USART3_IRQn, UART3_RXBUF_SIZE);
161#endif
162}
163
164static void stm32_usart_shared_irq(struct uart_instance *u)
165{
166 bool resched = false;
167
168 arm_cm_irq_entry();
169
170 /* UART parity error interrupt occurred -------------------------------------*/
171 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_PE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_PE) != RESET)) {
172 __HAL_UART_CLEAR_PEFLAG(&u->handle);
173
174 printf("UART PARITY ERROR\n");
175 }
176
177 /* UART frame error interrupt occurred --------------------------------------*/
178 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_FE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_ERR) != RESET)) {
179 __HAL_UART_CLEAR_FEFLAG(&u->handle);
180
181 printf("UART FRAME ERROR\n");
182 }
183
184 /* UART noise error interrupt occurred --------------------------------------*/
185 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_NE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_ERR) != RESET)) {
186 __HAL_UART_CLEAR_NEFLAG(&u->handle);
187
188 printf("UART NOISE ERROR\n");
189 }
190
191 /* UART Over-Run interrupt occurred -----------------------------------------*/
192 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_ORE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_ERR) != RESET)) {
193 __HAL_UART_CLEAR_OREFLAG(&u->handle);
194
195 printf("UART OVERRUN ERROR\n");
196 }
197
198 /* UART in mode Receiver ---------------------------------------------------*/
199 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_RXNE) != RESET)) {
200
201 /* we got a character */
202 uint8_t c = (uint8_t)(u->handle.Instance->RDR & 0xff);
203 if (cbuf_write_char(&u->rx_buf, c, false) != 1) {
204 printf("WARNING: uart cbuf overrun!\n");
205 }
206 resched = true;
207
208 /* Clear RXNE interrupt flag */
209 __HAL_UART_SEND_REQ(&u->handle, UART_RXDATA_FLUSH_REQUEST);
210 }
211
212 /* UART in mode Transmitter ------------------------------------------------*/
213 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_TXE) != RESET) &&(__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_TXE) != RESET)) {
214 ;
215 }
216
217 /* UART in mode Transmitter (transmission end) -----------------------------*/
218 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_TC) != RESET) &&(__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_TC) != RESET)) {
219 ;
220 }
221
222 arm_cm_irq_exit(resched);
223}
224
225#if ENABLE_UART1
226void stm32_USART1_IRQ(void)
227{
228 stm32_usart_shared_irq(uart[1]);
229}
230#endif
231
232#if ENABLE_UART3
233void stm32_USART3_IRQ(void)
234{
235 stm32_usart_shared_irq(uart[3]);
236}
237#endif
238
239int uart_putc(int port, char c)
240{
241 struct uart_instance *u = uart[port];
242 if (port < 0 || port > NUM_UARTS || !u)
243 return ERR_BAD_HANDLE;
244
245 while (__HAL_UART_GET_FLAG(&u->handle, UART_FLAG_TXE) == RESET)
246 ;
247 u->handle.Instance->TDR = (c & (uint8_t)0xFF);
248
249 return 1;
250}
251
252int uart_getc(int port, bool wait)
253{
254 struct uart_instance *u = uart[port];
255 if (port < 0 || port > NUM_UARTS || !u)
256 return ERR_BAD_HANDLE;
257
258 char c;
259 if (cbuf_read_char(&u->rx_buf, &c, wait) == 0)
260 return ERR_IO;
261 return c;
262}
263
264int uart_pputc(int port, char c)
265{
266 return uart_putc(port, c);
267}
268
269int uart_pgetc(int port)
270{
271 struct uart_instance *u = uart[port];
272 if (port < 0 || port > NUM_UARTS || !u)
273 return ERR_BAD_HANDLE;
274
275 if ((__HAL_UART_GET_IT(&u->handle, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&u->handle, UART_IT_RXNE) != RESET)) {
276 uint8_t c = (uint8_t)(u->handle.Instance->RDR & 0xff);
277 return c;
278 }
279 return ERR_IO;
280}
281
282void uart_flush_tx(int port) {}
283
284void uart_flush_rx(int port) {}
285
286void uart_init_port(int port, uint baud)
287{
288 // TODO - later
289 PANIC_UNIMPLEMENTED;
290}