blob: 41e5170da0e2d2cf2ee05d36e75db9ff5f1e4edf [file] [log] [blame]
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01001/*
2 * Copyright (c) 2016 Open-RnD Sp. z o.o.
Erwan Gouriou8c079e92016-11-14 11:53:52 +01003 * Copyright (c) 2016 Linaro Limited.
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01004 *
David B. Kinderac74d8b2017-01-18 17:01:01 -08005 * SPDX-License-Identifier: Apache-2.0
Maciek Borzecki5a73ca62016-03-03 15:33:20 +01006 */
7
8/**
9 * @brief Driver for UART port on STM32F10x family processor.
10 *
11 * Based on reference manual:
12 * STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx
13 * advanced ARM ® -based 32-bit MCUs
14 *
15 * Chapter 27: Universal synchronous asynchronous receiver
16 * transmitter (USART)
17 */
18
Flavio Santesb04cdcd2016-12-04 14:59:37 -060019#include <kernel.h>
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010020#include <arch/cpu.h>
21#include <misc/__assert.h>
22#include <board.h>
23#include <init.h>
24#include <uart.h>
25#include <clock_control.h>
26
27#include <sections.h>
28#include <clock_control/stm32_clock_control.h>
29#include "uart_stm32.h"
30
31/* convenience defines */
32#define DEV_CFG(dev) \
Marcus Shawcroftf34d5512016-10-06 19:47:13 +010033 ((const struct uart_stm32_config * const)(dev)->config->config_info)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010034#define DEV_DATA(dev) \
35 ((struct uart_stm32_data * const)(dev)->driver_data)
36#define UART_STRUCT(dev) \
Erwan Gouriou8c079e92016-11-14 11:53:52 +010037 ((USART_TypeDef *)(DEV_CFG(dev))->uconf.base)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010038
Erwan Gouriou8c079e92016-11-14 11:53:52 +010039#define TIMEOUT 1000
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010040
41static int uart_stm32_poll_in(struct device *dev, unsigned char *c)
42{
Erwan Gouriou8c079e92016-11-14 11:53:52 +010043 struct uart_stm32_data *data = DEV_DATA(dev);
44 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010045
Kumar Galaccad5bf2017-04-21 10:03:20 -050046 if (HAL_UART_Receive(UartHandle, (u8_t *)c, 1, TIMEOUT) == HAL_OK) {
Erwan Gouriou8c079e92016-11-14 11:53:52 +010047 return 0;
48 } else {
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010049 return -1;
50 }
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010051}
52
53static unsigned char uart_stm32_poll_out(struct device *dev,
54 unsigned char c)
55{
Erwan Gouriou8c079e92016-11-14 11:53:52 +010056 struct uart_stm32_data *data = DEV_DATA(dev);
57 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010058
Kumar Galaccad5bf2017-04-21 10:03:20 -050059 HAL_UART_Transmit(UartHandle, (u8_t *)&c, 1, TIMEOUT);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010060
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010061 return c;
62}
63
64static inline void __uart_stm32_get_clock(struct device *dev)
65{
Erwan Gouriou8c079e92016-11-14 11:53:52 +010066 struct uart_stm32_data *data = DEV_DATA(dev);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010067 struct device *clk =
68 device_get_binding(STM32_CLOCK_CONTROL_NAME);
69
70 __ASSERT_NO_MSG(clk);
71
Erwan Gouriou8c079e92016-11-14 11:53:52 +010072 data->clock = clk;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +010073}
74
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +010075#ifdef CONFIG_UART_INTERRUPT_DRIVEN
76
Kumar Galaccad5bf2017-04-21 10:03:20 -050077static int uart_stm32_fifo_fill(struct device *dev, const u8_t *tx_data,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +010078 int size)
79{
Erwan Gouriou8c079e92016-11-14 11:53:52 +010080 struct uart_stm32_data *data = DEV_DATA(dev);
81 UART_HandleTypeDef *UartHandle = &data->huart;
Kumar Galaccad5bf2017-04-21 10:03:20 -050082 u8_t num_tx = 0;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +010083
Erwan Gouriou8c079e92016-11-14 11:53:52 +010084 while ((size - num_tx > 0) && __HAL_UART_GET_FLAG(UartHandle,
85 UART_FLAG_TXE)) {
86 /* TXE flag will be cleared with byte write to DR register */
87
88 /* Send a character (8bit , parity none) */
89#if defined(CONFIG_SOC_SERIES_STM32F1X) || defined(CONFIG_SOC_SERIES_STM32F4X)
90 /* Use direct access for F1, F4 until Low Level API is available
91 * Once it is we can remove the if/else
92 */
93 UartHandle->Instance->DR = (tx_data[num_tx++] &
Kumar Galaccad5bf2017-04-21 10:03:20 -050094 (u8_t)0x00FF);
Erwan Gouriou8c079e92016-11-14 11:53:52 +010095#else
96 LL_USART_TransmitData8(UartHandle->Instance, tx_data[num_tx++]);
97#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +010098 }
99
100 return num_tx;
101}
102
Kumar Galaccad5bf2017-04-21 10:03:20 -0500103static int uart_stm32_fifo_read(struct device *dev, u8_t *rx_data,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100104 const int size)
105{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100106 struct uart_stm32_data *data = DEV_DATA(dev);
107 UART_HandleTypeDef *UartHandle = &data->huart;
Kumar Galaccad5bf2017-04-21 10:03:20 -0500108 u8_t num_rx = 0;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100109
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100110 while ((size - num_rx > 0) && __HAL_UART_GET_FLAG(UartHandle,
111 UART_FLAG_RXNE)) {
112 /* Clear the interrupt */
113 __HAL_UART_CLEAR_FLAG(UartHandle, UART_FLAG_RXNE);
114
115 /* Receive a character (8bit , parity none) */
116#if defined(CONFIG_SOC_SERIES_STM32F1X) || defined(CONFIG_SOC_SERIES_STM32F4X)
117 /* Use direct access for F1, F4 until Low Level API is available
118 * Once it is we can remove the if/else
119 */
Kumar Galaccad5bf2017-04-21 10:03:20 -0500120 rx_data[num_rx++] = (u8_t)(UartHandle->Instance->DR &
121 (u8_t)0x00FF);
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100122#else
123 rx_data[num_rx++] = LL_USART_ReceiveData8(UartHandle->Instance);
124#endif
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100125 }
126 return num_rx;
127}
128
129static void uart_stm32_irq_tx_enable(struct device *dev)
130{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100131 struct uart_stm32_data *data = DEV_DATA(dev);
132 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100133
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100134 __HAL_UART_ENABLE_IT(UartHandle, UART_IT_TC);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100135}
136
137static void uart_stm32_irq_tx_disable(struct device *dev)
138{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100139 struct uart_stm32_data *data = DEV_DATA(dev);
140 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100141
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100142 __HAL_UART_DISABLE_IT(UartHandle, UART_IT_TC);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100143}
144
145static int uart_stm32_irq_tx_ready(struct device *dev)
146{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100147 struct uart_stm32_data *data = DEV_DATA(dev);
148 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100149
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100150 return __HAL_UART_GET_FLAG(UartHandle, UART_FLAG_TXE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100151}
152
Paul Sokolovsky0fdc9b52017-05-11 17:57:29 +0300153static int uart_stm32_irq_tx_complete(struct device *dev)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100154{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100155 struct uart_stm32_data *data = DEV_DATA(dev);
156 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100157
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100158 return __HAL_UART_GET_FLAG(UartHandle, UART_FLAG_TXE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100159}
160
161static void uart_stm32_irq_rx_enable(struct device *dev)
162{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100163 struct uart_stm32_data *data = DEV_DATA(dev);
164 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100165
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100166 __HAL_UART_ENABLE_IT(UartHandle, UART_IT_RXNE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100167}
168
169static void uart_stm32_irq_rx_disable(struct device *dev)
170{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100171 struct uart_stm32_data *data = DEV_DATA(dev);
172 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100173
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100174 __HAL_UART_DISABLE_IT(UartHandle, UART_IT_RXNE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100175}
176
177static int uart_stm32_irq_rx_ready(struct device *dev)
178{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100179 struct uart_stm32_data *data = DEV_DATA(dev);
180 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100181
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100182 return __HAL_UART_GET_FLAG(UartHandle, UART_FLAG_RXNE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100183}
184
185static void uart_stm32_irq_err_enable(struct device *dev)
186{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100187 struct uart_stm32_data *data = DEV_DATA(dev);
188 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100189
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100190 /* Enable FE, ORE interruptions */
191 __HAL_UART_ENABLE_IT(UartHandle, UART_IT_ERR);
192 /* Enable Line break detection */
193 __HAL_UART_ENABLE_IT(UartHandle, UART_IT_LBD);
194 /* Enable parity error interruption */
195 __HAL_UART_ENABLE_IT(UartHandle, UART_IT_PE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100196}
197
198static void uart_stm32_irq_err_disable(struct device *dev)
199{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100200 struct uart_stm32_data *data = DEV_DATA(dev);
201 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100202
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100203 /* Disable FE, ORE interruptions */
204 __HAL_UART_DISABLE_IT(UartHandle, UART_IT_ERR);
205 /* Disable Line break detection */
206 __HAL_UART_DISABLE_IT(UartHandle, UART_IT_LBD);
207 /* Disable parity error interruption */
208 __HAL_UART_DISABLE_IT(UartHandle, UART_IT_PE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100209}
210
211static int uart_stm32_irq_is_pending(struct device *dev)
212{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100213 struct uart_stm32_data *data = DEV_DATA(dev);
214 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100215
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100216 return __HAL_UART_GET_FLAG(UartHandle, UART_FLAG_TXE | UART_FLAG_RXNE);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100217}
218
219static int uart_stm32_irq_update(struct device *dev)
220{
221 return 1;
222}
223
224static void uart_stm32_irq_callback_set(struct device *dev,
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100225 uart_irq_callback_t cb)
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100226{
227 struct uart_stm32_data *data = DEV_DATA(dev);
228
229 data->user_cb = cb;
230}
231
232static void uart_stm32_isr(void *arg)
233{
234 struct device *dev = arg;
235 struct uart_stm32_data *data = DEV_DATA(dev);
236
237 if (data->user_cb) {
238 data->user_cb(dev);
239 }
240}
241
242#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
243
Marcus Shawcroftd3ea5392016-10-24 08:38:49 +0100244static const struct uart_driver_api uart_stm32_driver_api = {
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100245 .poll_in = uart_stm32_poll_in,
246 .poll_out = uart_stm32_poll_out,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100247#ifdef CONFIG_UART_INTERRUPT_DRIVEN
248 .fifo_fill = uart_stm32_fifo_fill,
249 .fifo_read = uart_stm32_fifo_read,
250 .irq_tx_enable = uart_stm32_irq_tx_enable,
251 .irq_tx_disable = uart_stm32_irq_tx_disable,
252 .irq_tx_ready = uart_stm32_irq_tx_ready,
Paul Sokolovsky0fdc9b52017-05-11 17:57:29 +0300253 .irq_tx_complete = uart_stm32_irq_tx_complete,
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100254 .irq_rx_enable = uart_stm32_irq_rx_enable,
255 .irq_rx_disable = uart_stm32_irq_rx_disable,
256 .irq_rx_ready = uart_stm32_irq_rx_ready,
257 .irq_err_enable = uart_stm32_irq_err_enable,
258 .irq_err_disable = uart_stm32_irq_err_disable,
259 .irq_is_pending = uart_stm32_irq_is_pending,
260 .irq_update = uart_stm32_irq_update,
261 .irq_callback_set = uart_stm32_irq_callback_set,
262#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100263};
264
265/**
266 * @brief Initialize UART channel
267 *
268 * This routine is called to reset the chip in a quiescent state.
269 * It is assumed that this function is called only once per UART.
270 *
271 * @param dev UART device struct
272 *
273 * @return 0
274 */
275static int uart_stm32_init(struct device *dev)
276{
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100277 const struct uart_stm32_config *config = DEV_CFG(dev);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100278 struct uart_stm32_data *data = DEV_DATA(dev);
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100279 UART_HandleTypeDef *UartHandle = &data->huart;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100280
281 __uart_stm32_get_clock(dev);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100282 /* enable clock */
Erwan Gouriou424c3382017-04-11 11:06:05 +0200283#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100284 clock_control_on(data->clock,
285 (clock_control_subsys_t *)&config->pclken);
Erwan Gouriou424c3382017-04-11 11:06:05 +0200286#else
287 clock_control_on(data->clock, config->clock_subsys);
Kumar Gala2f9d83d2016-10-28 10:16:51 -0500288#endif
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100289
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100290 UartHandle->Instance = UART_STRUCT(dev);
291 UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
292 UartHandle->Init.StopBits = UART_STOPBITS_1;
293 UartHandle->Init.Parity = UART_PARITY_NONE;
294 UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
295 UartHandle->Init.Mode = UART_MODE_TX_RX;
296 UartHandle->Init.OverSampling = UART_OVERSAMPLING_16;
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100297
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100298 HAL_UART_Init(UartHandle);
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100299
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100300#ifdef CONFIG_UART_INTERRUPT_DRIVEN
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100301 config->uconf.irq_config_func(dev);
Maciek Borzecki0cd7ff82016-03-13 19:37:25 +0100302#endif
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100303 return 0;
304}
305
Florian Vaussardf27a5a32017-05-01 15:21:52 +0200306/* Define clocks */
307#ifdef CONFIG_CLOCK_CONTROL_STM32_CUBE
308 #define STM32_CLOCK_UART(type, apb, n) \
309 .pclken = { .bus = STM32_CLOCK_BUS_ ## apb, \
310 .enr = LL_##apb##_GRP1_PERIPH_##type##n }
311#else
312 #define STM32_CLOCK_UART(type, apb, n) \
313 .clock_subsys = UINT_TO_POINTER( \
314 STM32F10X_CLOCK_SUBSYS_##type##n)
315#endif /* CLOCK_CONTROL_STM32_CUBE */
316
317#ifdef CONFIG_UART_INTERRUPT_DRIVEN
318#define STM32_UART_IRQ_HANDLER_DECL(n) \
319 static void uart_stm32_irq_config_func_##n(struct device *dev)
320#define STM32_UART_IRQ_HANDLER_FUNC(n) \
321 .irq_config_func = uart_stm32_irq_config_func_##n,
322#define STM32_UART_IRQ_HANDLER(n) \
323static void uart_stm32_irq_config_func_##n(struct device *dev) \
324{ \
325 IRQ_CONNECT(PORT_ ## n ## _IRQ, \
326 CONFIG_UART_STM32_PORT_ ## n ## _IRQ_PRI, \
327 uart_stm32_isr, DEVICE_GET(uart_stm32_ ## n), \
328 0); \
329 irq_enable(PORT_ ## n ## _IRQ); \
330}
331#else
332#define STM32_UART_IRQ_HANDLER_DECL(n)
333#define STM32_UART_IRQ_HANDLER_FUNC(n)
334#define STM32_UART_IRQ_HANDLER(n)
335#endif
336
337#define UART_DEVICE_INIT_STM32(type, n, apb) \
338STM32_UART_IRQ_HANDLER_DECL(n); \
339 \
340static const struct uart_stm32_config uart_stm32_dev_cfg_##n = { \
341 .uconf = { \
342 .base = (u8_t *)CONFIG_UART_STM32_PORT_ ## n ## _BASE_ADDRESS, \
343 STM32_UART_IRQ_HANDLER_FUNC(n) \
344 }, \
345 STM32_CLOCK_UART(type, apb, n), \
346}; \
347 \
348static struct uart_stm32_data uart_stm32_dev_data_##n = { \
349 .huart = { \
350 .Init = { \
351 .BaudRate = CONFIG_UART_STM32_PORT_##n##_BAUD_RATE \
352 } \
353 } \
354}; \
355 \
356DEVICE_AND_API_INIT(uart_stm32_##n, CONFIG_UART_STM32_PORT_##n##_NAME, \
357 &uart_stm32_init, \
358 &uart_stm32_dev_data_##n, &uart_stm32_dev_cfg_##n, \
359 PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
360 &uart_stm32_driver_api); \
361 \
362STM32_UART_IRQ_HANDLER(n)
Erwan Gouriou8c079e92016-11-14 11:53:52 +0100363
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100364#ifdef CONFIG_UART_STM32_PORT_1
Florian Vaussardf27a5a32017-05-01 15:21:52 +0200365UART_DEVICE_INIT_STM32(USART, 1, APB2)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100366#endif /* CONFIG_UART_STM32_PORT_1 */
367
368#ifdef CONFIG_UART_STM32_PORT_2
Florian Vaussardf27a5a32017-05-01 15:21:52 +0200369UART_DEVICE_INIT_STM32(USART, 2, APB1)
Maciek Borzecki5a73ca62016-03-03 15:33:20 +0100370#endif /* CONFIG_UART_STM32_PORT_2 */
Erwan Gouriou2fcf3432016-11-14 11:59:45 +0100371
Erwan Gouriou2fcf3432016-11-14 11:59:45 +0100372#ifdef CONFIG_UART_STM32_PORT_3
Florian Vaussardf27a5a32017-05-01 15:21:52 +0200373UART_DEVICE_INIT_STM32(USART, 3, APB1)
Erwan Gouriou2fcf3432016-11-14 11:59:45 +0100374#endif /* CONFIG_UART_STM32_PORT_3 */