blob: cb5466d3156ef72e70521de9bc67d0a76dc14982 [file] [log] [blame]
Marc Moreno Berengue20dab392017-11-29 13:18:58 +00001/*
Avinash Mehta788036c2018-03-15 12:38:43 +00002 * Copyright (c) 2017-2018 ARM Limited
Marc Moreno Berengue20dab392017-11-29 13:18:58 +00003 *
4 * Licensed under the Apace License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apace.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "uart_stdout.h"
18
19#include <assert.h>
20#include <stdio.h>
21#include <string.h>
Avinash Mehta788036c2018-03-15 12:38:43 +000022#ifdef TARGET_MUSCA_A
23#include "uart_pl011_drv.h"
24#else
Marc Moreno Berengue20dab392017-11-29 13:18:58 +000025#include "arm_uart_drv.h"
Avinash Mehta788036c2018-03-15 12:38:43 +000026#endif
Marc Moreno Berengue20dab392017-11-29 13:18:58 +000027#include "Driver_USART.h"
28
29#define ASSERT_HIGH(X) assert(X == ARM_DRIVER_OK)
30
31/* Imports USART driver */
32extern ARM_DRIVER_USART Driver_USART0;
33extern ARM_DRIVER_USART Driver_USART1;
34
35/* Struct FILE is implemented in stdio.h. Used to redirect printf to UART */
36FILE __stdout;
37
38/* Redirects printf to UART */
39__attribute__ ((weak)) int fputc(int ch, FILE *f) {
40 /* Send byte to USART */
41 uart_putc(ch);
42
43 /* Return character written */
44 return ch;
45}
46
Avinash Mehta788036c2018-03-15 12:38:43 +000047#ifdef TARGET_MUSCA_A
48extern struct uart_pl011_dev_t UART0_DEV_S, UART0_DEV_NS;
49extern struct uart_pl011_dev_t UART1_DEV_S, UART1_DEV_NS;
50#else
Marc Moreno Berengue20dab392017-11-29 13:18:58 +000051extern struct arm_uart_dev_t ARM_UART0_DEV_S, ARM_UART0_DEV_NS;
52extern struct arm_uart_dev_t ARM_UART1_DEV_S, ARM_UART1_DEV_NS;
Avinash Mehta788036c2018-03-15 12:38:43 +000053#endif
Marc Moreno Berengue20dab392017-11-29 13:18:58 +000054
55/* Generic driver to be configured and used */
56ARM_DRIVER_USART *Driver_USART = NULL;
57
58void uart_init(enum uart_channel uchan)
59{
60 int32_t ret = ARM_DRIVER_OK;
61
62 /* Add a configuration step for the UART channel to use, 0 or 1 */
63 switch(uchan) {
64 case UART0_CHANNEL:
65 /* UART0 is configured as a non-secure peripheral, so we wouldn't be
66 * able to access it using its secure alias. Ideally, we would want
67 * to use UART1 only from S side as it's a secure peripheral, but for
68 * simplicity, leave the option to use UART0 and use a workaround
69 */
Avinash Mehta788036c2018-03-15 12:38:43 +000070#ifdef TARGET_MUSCA_A
71 memcpy(&UART0_DEV_S, &UART0_DEV_NS, sizeof(struct uart_pl011_dev_t));
72#else
Marc Moreno Berengue20dab392017-11-29 13:18:58 +000073 memcpy(&ARM_UART0_DEV_S, &ARM_UART0_DEV_NS, sizeof(struct arm_uart_dev_t));
Avinash Mehta788036c2018-03-15 12:38:43 +000074#endif
Marc Moreno Berengue20dab392017-11-29 13:18:58 +000075 Driver_USART = &Driver_USART0;
76 break;
77 case UART1_CHANNEL:
78 Driver_USART = &Driver_USART1;
79 break;
80 default:
81 ret = ARM_DRIVER_ERROR;
82 }
83 ASSERT_HIGH(ret);
84
85 ret = Driver_USART->Initialize(NULL);
86 ASSERT_HIGH(ret);
87
88 ret = Driver_USART->Control(ARM_USART_MODE_ASYNCHRONOUS, 115200);
89 ASSERT_HIGH(ret);
90}
91
92void uart_putc(unsigned char c)
93{
94 int32_t ret = ARM_DRIVER_OK;
95
96 ret = Driver_USART->Send(&c, 1);
97 ASSERT_HIGH(ret);
98}
99
100unsigned char uart_getc(void)
101{
102 unsigned char c = 0;
103 int32_t ret = ARM_DRIVER_OK;
104
105 ret = Driver_USART->Receive(&c, 1);
106 ASSERT_HIGH(ret);
107
108 return c;
109}