source: rtems/bsps/arm/atsam/console/console.c @ d9c0dd3

5
Last change on this file since d9c0dd3 was d9c0dd3, checked in by Christian Mauderer <christian.mauderer@…>, on 01/11/22 at 08:20:53

bsp/atsam: Merge USART and UART driver

If no extended features of the USART are used and if the comparison
feature of the UART is not used, the two modules are compatible. The
drivers were nearly identical except for some names of the defines.

This patch merges the two drivers into one.

Update #4577

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <bsp.h>
16#include <bsp/irq.h>
17#include <bsp/fatal.h>
18#include <rtems/console.h>
19
20#include <rtems/termiostypes.h>
21
22#include <chip.h>
23
24#include <unistd.h>
25
26typedef struct {
27  rtems_termios_device_context base;
28  Uart *regs;
29  rtems_vector_number irq;
30  uint32_t id;
31  bool console;
32  bool is_usart;
33#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
34  bool transmitting;
35#endif
36} atsam_uart_context;
37
38static atsam_uart_context atsam_usart_instances[] = {
39  {
40    .regs = (Uart *)USART0,
41    .irq = USART0_IRQn,
42    .id = ID_USART0,
43    .is_usart = true,
44  }
45#ifdef USART1
46  , {
47    .regs = (Uart *)USART1,
48    .irq = USART1_IRQn,
49    .id = ID_USART1,
50    .is_usart = true,
51  }
52#endif
53#ifdef USART2
54  , {
55    .regs = (Uart *)USART2,
56    .irq = USART2_IRQn,
57    .id = ID_USART2,
58    .is_usart = true,
59  }
60#endif
61};
62
63static atsam_uart_context atsam_uart_instances[] = {
64  {
65    .regs = UART0,
66    .irq = UART0_IRQn,
67    .id = ID_UART0,
68    .is_usart = false,
69  }
70#ifdef UART1
71  , {
72    .regs = UART1,
73    .irq = UART1_IRQn,
74    .id = ID_UART1,
75    .is_usart = false,
76  }
77#endif
78#ifdef UART2
79  , {
80    .regs = UART2,
81    .irq = UART2_IRQn,
82    .id = ID_UART2,
83    .is_usart = false,
84  }
85#endif
86#ifdef UART3
87  , {
88    .regs = UART3,
89    .irq = UART3_IRQn,
90    .id = ID_UART3,
91    .is_usart = false,
92  }
93#endif
94#ifdef UART4
95  , {
96    .regs = UART4,
97    .irq = UART4_IRQn,
98    .id = ID_UART4,
99    .is_usart = false,
100  }
101#endif
102};
103
104#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
105static void atsam_uart_interrupt(void *arg)
106{
107  rtems_termios_tty *tty = arg;
108  atsam_uart_context *ctx = rtems_termios_get_device_context(tty);
109  Uart *regs = ctx->regs;
110  uint32_t sr = regs->UART_SR;
111
112  while ((sr & UART_SR_RXRDY) != 0) {
113    char c = (char) regs->UART_RHR;
114
115    rtems_termios_enqueue_raw_characters(tty, &c, 1);
116
117    sr = regs->UART_SR;
118  }
119
120  if (ctx->transmitting && (sr & UART_SR_TXEMPTY) != 0) {
121    rtems_termios_dequeue_characters(tty, 1);
122  }
123}
124#endif
125
126static bool atsam_uart_set_attributes(
127  rtems_termios_device_context *base,
128  const struct termios *term
129)
130{
131  atsam_uart_context *ctx = (atsam_uart_context *) base;
132  Uart *regs = ctx->regs;
133  rtems_termios_baud_t baud;
134  uint32_t mr;
135
136  baud = rtems_termios_baud_to_number(term->c_ospeed);
137  regs->UART_BRGR = (BOARD_MCK / baud) / 16;
138
139  if ((term->c_cflag & CREAD) != 0) {
140    regs->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
141  } else {
142    regs->UART_CR = UART_CR_TXEN;
143  }
144
145  if (ctx->is_usart) {
146    mr = US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK;
147  } else {
148    mr = UART_MR_FILTER_DISABLED | UART_MR_BRSRCCK_PERIPH_CLK;
149  }
150
151  if (ctx->is_usart) {
152    switch (term->c_cflag & CSIZE) {
153      case CS5:
154        mr |= US_MR_CHRL_5_BIT;
155        break;
156      case CS6:
157        mr |= US_MR_CHRL_6_BIT;
158        break;
159      case CS7:
160        mr |= US_MR_CHRL_7_BIT;
161        break;
162      default:
163        mr |= US_MR_CHRL_8_BIT;
164        break;
165    }
166  } else {
167    if ((term->c_cflag & CSIZE) != CS8) {
168      return false;
169    }
170  }
171
172  if ((term->c_cflag & PARENB) != 0) {
173    if ((term->c_cflag & PARODD) != 0) {
174      mr |= UART_MR_PAR_ODD;
175    } else {
176      mr |= UART_MR_PAR_EVEN;
177    }
178  } else {
179    mr |= UART_MR_PAR_NO;
180  }
181
182  if (ctx->is_usart) {
183    if ((term->c_cflag & CSTOPB) != 0) {
184      mr |= US_MR_NBSTOP_2_BIT;
185    } else {
186      mr |= US_MR_NBSTOP_1_BIT;
187    }
188  } else {
189    if ((term->c_cflag & CSTOPB) != 0) {
190      return false;
191    }
192  }
193
194  regs->UART_MR = mr;
195
196  return true;
197}
198
199static bool atsam_uart_first_open(
200  rtems_termios_tty *tty,
201  rtems_termios_device_context *base,
202  struct termios *term,
203  rtems_libio_open_close_args_t *args
204)
205{
206  atsam_uart_context *ctx = (atsam_uart_context *) base;
207  Uart *regs = ctx->regs;
208#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
209  rtems_status_code sc;
210#endif
211
212  regs->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RSTSTA;
213  regs->UART_IDR = 0xffffffff;
214
215  PMC_EnablePeripheral(ctx->id);
216
217  rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD);
218  atsam_uart_set_attributes(base, term);
219
220#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
221  regs->UART_IER = UART_IDR_RXRDY;
222  sc = rtems_interrupt_handler_install(
223    ctx->irq,
224    ctx->is_usart ? "USART" : "UART",
225    RTEMS_INTERRUPT_SHARED,
226    atsam_uart_interrupt,
227    tty
228  );
229  if (sc != RTEMS_SUCCESSFUL) {
230    return false;
231  }
232#endif
233
234  return true;
235}
236
237static void atsam_uart_last_close(
238  rtems_termios_tty *tty,
239  rtems_termios_device_context *base,
240  rtems_libio_open_close_args_t *args
241)
242{
243  atsam_uart_context *ctx = (atsam_uart_context *) base;
244
245#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
246  rtems_interrupt_handler_remove(ctx->irq, atsam_uart_interrupt, tty);
247#endif
248
249  if (!ctx->console) {
250    PMC_DisablePeripheral(ctx->id);
251  }
252}
253
254static void atsam_uart_write(
255  rtems_termios_device_context *base,
256  const char *buf,
257  size_t len
258)
259{
260  atsam_uart_context *ctx = (atsam_uart_context *) base;
261  Uart *regs = ctx->regs;
262
263#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
264  if (len > 0) {
265    ctx->transmitting = true;
266    regs->UART_THR = buf[0];
267    regs->UART_IER = UART_IDR_TXEMPTY;
268  } else {
269    ctx->transmitting = false;
270    regs->UART_IDR = UART_IDR_TXEMPTY;
271  }
272#else
273  size_t i;
274
275  for (i = 0; i < len; ++i) {
276    while ((regs->UART_SR & UART_SR_TXEMPTY) == 0) {
277      /* Wait */
278    }
279
280    regs->UART_THR = buf[i];
281  }
282#endif
283}
284
285#ifndef ATSAM_CONSOLE_USE_INTERRUPTS
286static int atsam_uart_read(rtems_termios_device_context *base)
287{
288  atsam_uart_context *ctx = (atsam_uart_context *) base;
289  Uart *regs = ctx->regs;
290
291  if ((regs->UART_SR & UART_SR_RXRDY) != 0) {
292    return (char) regs->UART_RHR;
293  } else {
294    return -1;
295  }
296}
297#endif
298
299static const rtems_termios_device_handler atsam_uart_handler = {
300  .first_open = atsam_uart_first_open,
301  .last_close = atsam_uart_last_close,
302  .write = atsam_uart_write,
303  .set_attributes = atsam_uart_set_attributes,
304#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
305  .mode = TERMIOS_IRQ_DRIVEN
306#else
307  .poll_read = atsam_uart_read,
308  .mode = TERMIOS_POLLED
309#endif
310};
311
312rtems_status_code console_initialize(
313  rtems_device_major_number major,
314  rtems_device_minor_number minor,
315  void *arg
316)
317{
318  size_t i;
319
320  rtems_termios_initialize();
321
322  for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_usart_instances); ++i) {
323    char usart[] = "/dev/ttyUSARTX";
324
325    usart[sizeof(usart) - 2] = (char) ('0' + i);
326    rtems_termios_device_install(
327      &usart[0],
328      &atsam_uart_handler,
329      NULL,
330      &atsam_usart_instances[i].base
331    );
332
333#if ATSAM_CONSOLE_DEVICE_TYPE == 0
334    if (i == ATSAM_CONSOLE_DEVICE_INDEX) {
335      atsam_usart_instances[i].console = true;
336      link(&usart[0], CONSOLE_DEVICE_NAME);
337    }
338#endif
339  }
340
341  for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_uart_instances); ++i) {
342    char uart[] = "/dev/ttyUARTX";
343
344    uart[sizeof(uart) - 2] = (char) ('0' + i);
345    rtems_termios_device_install(
346      &uart[0],
347      &atsam_uart_handler,
348      NULL,
349      &atsam_uart_instances[i].base
350    );
351
352#if ATSAM_CONSOLE_DEVICE_TYPE == 1
353    if (i == ATSAM_CONSOLE_DEVICE_INDEX) {
354      atsam_uart_instances[i].console = true;
355      link(&uart[0], CONSOLE_DEVICE_NAME);
356    }
357#endif
358  }
359
360  return RTEMS_SUCCESSFUL;
361}
Note: See TracBrowser for help on using the repository browser.