source: rtems/c/src/lib/libbsp/arm/atsam/console/console.c @ ad76eb32

Last change on this file since ad76eb32 was ad76eb32, checked in by Joel Sherrill <joel@…>, on Mar 29, 2016 at 6:10:49 PM

arm/atsam: Remove include of <rtems/console.h> from <bsp.h> and fix warnings

  • Property mode set to 100644
File size: 10.7 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
24typedef struct {
25  rtems_termios_device_context base;
26  Usart *regs;
27  rtems_vector_number irq;
28  uint32_t id;
29  bool console;
30#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
31  bool transmitting;
32#endif
33} atsam_usart_context;
34
35static atsam_usart_context atsam_usart_instances[] = {
36  {
37    .regs = USART0,
38    .irq = USART0_IRQn,
39    .id = ID_USART0
40  }
41#ifdef USART1
42  , {
43    .regs = USART1,
44    .irq = USART1_IRQn,
45    .id = ID_USART1
46  }
47#endif
48#ifdef USART2
49  , {
50    .regs = USART2,
51    .irq = USART2_IRQn,
52    .id = ID_USART2
53  }
54#endif
55};
56
57#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
58static void atsam_usart_interrupt(void *arg)
59{
60  rtems_termios_tty *tty = arg;
61  atsam_usart_context *ctx = rtems_termios_get_device_context(tty);
62  Usart *regs = ctx->regs;
63  uint32_t csr = regs->US_CSR;
64
65  while ((csr & US_CSR_RXRDY) != 0) {
66    char c = (char) regs->US_RHR;
67
68    rtems_termios_enqueue_raw_characters(tty, &c, 1);
69
70    csr = regs->US_CSR;
71  }
72
73  if (ctx->transmitting && (csr & US_CSR_TXEMPTY) != 0) {
74    rtems_termios_dequeue_characters(tty, 1);
75  }
76}
77#endif
78
79static bool atsam_usart_set_attributes(
80  rtems_termios_device_context *base,
81  const struct termios *term
82)
83{
84  atsam_usart_context *ctx = (atsam_usart_context *) base;
85  Usart *regs = ctx->regs;
86  rtems_termios_baud_t baud;
87  uint32_t mr;
88
89  baud = rtems_termios_baud_to_number(term->c_cflag);
90  regs->US_BRGR = (BOARD_MCK / baud) / 16;
91
92  if ((term->c_cflag & CREAD) != 0) {
93    regs->US_CR = US_CR_RXEN | US_CR_TXEN;
94  } else {
95    regs->US_CR = US_CR_TXEN;
96  }
97
98  mr = US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK;
99
100  switch (term->c_cflag & CSIZE) {
101    case CS5:
102      mr |= US_MR_CHRL_5_BIT;
103      break;
104    case CS6:
105      mr |= US_MR_CHRL_6_BIT;
106      break;
107    case CS7:
108      mr |= US_MR_CHRL_7_BIT;
109      break;
110    default:
111      mr |= US_MR_CHRL_8_BIT;
112      break;
113  }
114
115  if ((term->c_cflag & PARENB) != 0) {
116    if ((term->c_cflag & PARODD) != 0) {
117      mr |= US_MR_PAR_ODD;
118    } else {
119      mr |= US_MR_PAR_EVEN;
120    }
121  } else {
122    mr |= US_MR_PAR_NO;
123  }
124
125  if ((term->c_cflag & CSTOPB) != 0) {
126    mr |= US_MR_NBSTOP_2_BIT;
127  } else {
128    mr |= US_MR_NBSTOP_1_BIT;
129  }
130
131  regs->US_MR = mr;
132
133  return true;
134}
135
136static bool atsam_usart_first_open(
137  rtems_termios_tty *tty,
138  rtems_termios_device_context *base,
139  struct termios *term,
140  rtems_libio_open_close_args_t *args
141)
142{
143  atsam_usart_context *ctx = (atsam_usart_context *) base;
144  Usart *regs = ctx->regs;
145#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
146  rtems_status_code sc;
147#endif
148
149  regs->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RSTSTA;
150  regs->US_IDR = 0xffffffff;
151
152  PMC_EnablePeripheral(ctx->id);
153
154  rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD);
155  atsam_usart_set_attributes(base, term);
156
157#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
158  regs->US_IER = US_IDR_RXRDY;
159  sc = rtems_interrupt_handler_install(
160    ctx->irq,
161    "USART",
162    RTEMS_INTERRUPT_SHARED,
163    atsam_usart_interrupt,
164    tty
165  );
166  if (sc != RTEMS_SUCCESSFUL) {
167    return false;
168  }
169#endif
170
171  return true;
172}
173
174static void atsam_usart_last_close(
175  rtems_termios_tty *tty,
176  rtems_termios_device_context *base,
177  rtems_libio_open_close_args_t *args
178)
179{
180  atsam_usart_context *ctx = (atsam_usart_context *) base;
181
182#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
183  rtems_interrupt_handler_remove(ctx->irq, atsam_usart_interrupt, tty);
184#endif
185
186  if (!ctx->console) {
187    PMC_DisablePeripheral(ctx->id);
188  }
189}
190
191static void atsam_usart_write(
192  rtems_termios_device_context *base,
193  const char *buf,
194  size_t len
195)
196{
197  atsam_usart_context *ctx = (atsam_usart_context *) base;
198  Usart *regs = ctx->regs;
199
200#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
201  if (len > 0) {
202    ctx->transmitting = true;
203    regs->US_THR = buf[0];
204    regs->US_IER = US_IDR_TXEMPTY;
205  } else {
206    ctx->transmitting = false;
207    regs->US_IDR = US_IDR_TXEMPTY;
208  }
209#else
210  size_t i;
211
212  for (i = 0; i < len; ++i) {
213    while ((regs->US_CSR & US_CSR_TXEMPTY) == 0) {
214      /* Wait */
215    }
216
217    regs->US_THR = buf[i];
218  }
219#endif
220}
221
222#ifndef ATSAM_CONSOLE_USE_INTERRUPTS
223static int atsam_usart_read(rtems_termios_device_context *base)
224{
225  atsam_usart_context *ctx = (atsam_usart_context *) base;
226  Usart *regs = ctx->regs;
227
228  if ((regs->US_CSR & US_CSR_RXRDY) != 0) {
229    return (char) regs->US_RHR;
230  } else {
231    return -1;
232  }
233}
234#endif
235
236static const rtems_termios_device_handler atsam_usart_handler = {
237  .first_open = atsam_usart_first_open,
238  .last_close = atsam_usart_last_close,
239  .write = atsam_usart_write,
240  .set_attributes = atsam_usart_set_attributes,
241#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
242  .mode = TERMIOS_IRQ_DRIVEN
243#else
244  .poll_read = atsam_usart_read,
245  .mode = TERMIOS_POLLED
246#endif
247};
248
249typedef struct {
250  rtems_termios_device_context base;
251  Uart *regs;
252  rtems_vector_number irq;
253  uint32_t id;
254  bool console;
255#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
256  bool transmitting;
257#endif
258} atsam_uart_context;
259
260static atsam_uart_context atsam_uart_instances[] = {
261  {
262    .regs = UART0,
263    .irq = UART0_IRQn,
264    .id = ID_UART0
265  }
266#ifdef UART1
267  , {
268    .regs = UART1,
269    .irq = UART1_IRQn,
270    .id = ID_UART1
271  }
272#endif
273#ifdef UART2
274  , {
275    .regs = UART2,
276    .irq = UART2_IRQn,
277    .id = ID_UART2
278  }
279#endif
280#ifdef UART3
281  , {
282    .regs = UART3,
283    .irq = UART3_IRQn,
284    .id = ID_UART3
285  }
286#endif
287#ifdef UART4
288  , {
289    .regs = UART4,
290    .irq = UART4_IRQn,
291    .id = ID_UART4
292  }
293#endif
294};
295
296#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
297static void atsam_uart_interrupt(void *arg)
298{
299  rtems_termios_tty *tty = arg;
300  atsam_uart_context *ctx = rtems_termios_get_device_context(tty);
301  Uart *regs = ctx->regs;
302  uint32_t sr = regs->UART_SR;
303
304  while ((sr & UART_SR_RXRDY) != 0) {
305    char c = (char) regs->UART_RHR;
306
307    rtems_termios_enqueue_raw_characters(tty, &c, 1);
308
309    sr = regs->UART_SR;
310  }
311
312  if (ctx->transmitting && (sr & UART_SR_TXEMPTY) != 0) {
313    rtems_termios_dequeue_characters(tty, 1);
314  }
315}
316#endif
317
318static bool atsam_uart_set_attributes(
319  rtems_termios_device_context *base,
320  const struct termios *term
321)
322{
323  atsam_uart_context *ctx = (atsam_uart_context *) base;
324  Uart *regs = ctx->regs;
325  rtems_termios_baud_t baud;
326  uint32_t mr;
327
328  baud = rtems_termios_baud_to_number(term->c_cflag);
329  regs->UART_BRGR = (BOARD_MCK / baud) / 16;
330
331  if ((term->c_cflag & CREAD) != 0) {
332    regs->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
333  } else {
334    regs->UART_CR = UART_CR_TXEN;
335  }
336
337  mr = UART_MR_FILTER_DISABLED | UART_MR_BRSRCCK_PERIPH_CLK;
338
339  if ((term->c_cflag & CSIZE) != CS8) {
340    return false;
341  }
342
343  if ((term->c_cflag & PARENB) != 0) {
344    if ((term->c_cflag & PARODD) != 0) {
345      mr |= UART_MR_PAR_ODD;
346    } else {
347      mr |= UART_MR_PAR_EVEN;
348    }
349  } else {
350    mr |= UART_MR_PAR_NO;
351  }
352
353  if ((term->c_cflag & CSTOPB) != 0) {
354    return false;
355  }
356
357  regs->UART_MR = mr;
358
359  return true;
360}
361
362static bool atsam_uart_first_open(
363  rtems_termios_tty *tty,
364  rtems_termios_device_context *base,
365  struct termios *term,
366  rtems_libio_open_close_args_t *args
367)
368{
369  atsam_uart_context *ctx = (atsam_uart_context *) base;
370  Uart *regs = ctx->regs;
371#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
372  rtems_status_code sc;
373#endif
374
375  regs->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RSTSTA;
376  regs->UART_IDR = 0xffffffff;
377
378  PMC_EnablePeripheral(ctx->id);
379
380  rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD);
381  atsam_uart_set_attributes(base, term);
382
383#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
384  regs->UART_IER = UART_IDR_RXRDY;
385  sc = rtems_interrupt_handler_install(
386    ctx->irq,
387    "UART",
388    RTEMS_INTERRUPT_SHARED,
389    atsam_uart_interrupt,
390    tty
391  );
392  if (sc != RTEMS_SUCCESSFUL) {
393    return false;
394  }
395#endif
396
397  return true;
398}
399
400static void atsam_uart_last_close(
401  rtems_termios_tty *tty,
402  rtems_termios_device_context *base,
403  rtems_libio_open_close_args_t *args
404)
405{
406  atsam_uart_context *ctx = (atsam_uart_context *) base;
407
408#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
409  rtems_interrupt_handler_remove(ctx->irq, atsam_uart_interrupt, tty);
410#endif
411
412  if (!ctx->console) {
413    PMC_DisablePeripheral(ctx->id);
414  }
415}
416
417static void atsam_uart_write(
418  rtems_termios_device_context *base,
419  const char *buf,
420  size_t len
421)
422{
423  atsam_uart_context *ctx = (atsam_uart_context *) base;
424  Uart *regs = ctx->regs;
425
426#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
427  if (len > 0) {
428    ctx->transmitting = true;
429    regs->UART_THR = buf[0];
430    regs->UART_IER = UART_IDR_TXEMPTY;
431  } else {
432    ctx->transmitting = false;
433    regs->UART_IDR = UART_IDR_TXEMPTY;
434  }
435#else
436  size_t i;
437
438  for (i = 0; i < len; ++i) {
439    while ((regs->UART_SR & UART_SR_TXEMPTY) == 0) {
440      /* Wait */
441    }
442
443    regs->UART_THR = buf[i];
444  }
445#endif
446}
447
448#ifndef ATSAM_CONSOLE_USE_INTERRUPTS
449static int atsam_uart_read(rtems_termios_device_context *base)
450{
451  atsam_uart_context *ctx = (atsam_uart_context *) base;
452  Uart *regs = ctx->regs;
453
454  if ((regs->UART_SR & UART_SR_RXRDY) != 0) {
455    return (char) regs->UART_RHR;
456  } else {
457    return -1;
458  }
459}
460#endif
461
462static const rtems_termios_device_handler atsam_uart_handler = {
463  .first_open = atsam_uart_first_open,
464  .last_close = atsam_uart_last_close,
465  .write = atsam_uart_write,
466  .set_attributes = atsam_uart_set_attributes,
467#ifdef ATSAM_CONSOLE_USE_INTERRUPTS
468  .mode = TERMIOS_IRQ_DRIVEN
469#else
470  .poll_read = atsam_uart_read,
471  .mode = TERMIOS_POLLED
472#endif
473};
474
475rtems_status_code console_initialize(
476  rtems_device_major_number major,
477  rtems_device_minor_number minor,
478  void *arg
479)
480{
481  size_t i;
482
483  rtems_termios_initialize();
484
485  for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_usart_instances); ++i) {
486    char usart[] = "/dev/ttyUSARTX";
487
488    usart[sizeof(usart) - 2] = (char) ('0' + i);
489    rtems_termios_device_install(
490      &usart[0],
491      major,
492      minor,
493      &atsam_usart_handler,
494      NULL,
495      &atsam_usart_instances[i].base
496    );
497
498#if ATSAM_CONSOLE_DEVICE_TYPE == 0
499    if (i == ATSAM_CONSOLE_DEVICE_INDEX) {
500      atsam_usart_instances[i].console = true;
501      rtems_io_register_name(CONSOLE_DEVICE_NAME, major, minor);
502    }
503#endif
504
505    ++minor;
506  }
507
508  for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_uart_instances); ++i) {
509    char uart[] = "/dev/ttyUARTX";
510
511    uart[sizeof(uart) - 2] = (char) ('0' + i);
512    rtems_termios_device_install(
513      &uart[0],
514      major,
515      minor,
516      &atsam_uart_handler,
517      NULL,
518      &atsam_uart_instances[i].base
519    );
520
521#if ATSAM_CONSOLE_DEVICE_TYPE == 1
522    if (i == ATSAM_CONSOLE_DEVICE_INDEX) {
523      atsam_uart_instances[i].console = true;
524      rtems_io_register_name(CONSOLE_DEVICE_NAME, major, minor);
525    }
526#endif
527
528    ++minor;
529  }
530
531  return RTEMS_SUCCESSFUL;
532}
Note: See TracBrowser for help on using the repository browser.