blob: 1cbf70c552028234c4f4e4c99238299c122fd50a [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#include "uart_stdout.h"
18#include "peripheral_memmap.h" /* peripheral memory map definitions */
19
20#include <stdio.h>
21#include <stdint.h>
22
23#define CNTLQ 0x11
24#define CNTLS 0x13
25#define DEL 0x7F
26#define BACKSPACE 0x08
27#define CR 0x0D
28#define LF 0x0A
29#define ESC 0x1B
30
31#define UARTBASE (PL011_UART0_BASE)
32
33/*****************************************************************************/
34/* UART Control Register Locations */
35/*****************************************************************************/
36#define UART0_DR *((volatile unsigned *) UARTBASE)
37#define UART0_RSR *((volatile unsigned *)(UARTBASE + 0x04))
38#define UART0_ECR *((volatile unsigned *)(UARTBASE + 0x04))
39#define UART0_LCRH *((volatile unsigned *)(UARTBASE + 0x2C))
40#define UART0_LCRM *((volatile unsigned *)(UARTBASE + 0x28))
41#define UART0_LCRL *((volatile unsigned *)(UARTBASE + 0x24))
42#define UART0_CR *((volatile unsigned *)(UARTBASE + 0x30))
43#define UART0_FR *((volatile unsigned *)(UARTBASE + 0x18))
44#define UART0_IIR *((volatile unsigned *)(UARTBASE + 0x1C))
45#define UART0_ICR *((volatile unsigned *)(UARTBASE + 0x44))
46
47/*****************************************************************************/
48/* Received Status Register - RSR */
49/*****************************************************************************/
50#define RSR_OVERRUN_ERROR 0x08
51#define RSR_BREAK_ERROR 0x04
52#define RSR_PARITY_ERROR 0x02
53#define RSR_FRAMING_ERROR 0x01
54
55/*****************************************************************************/
56/* Line Control High Byte Register - LCRH */
57/*****************************************************************************/
58#define LCRH_WORD_LENGTH_8 0x60
59#define LCRH_WORD_LENGTH_7 0x40
60#define LCRH_WORD_LENGTH_6 0x20
61#define LCRH_WORD_LENGTH_5 0x00
62#define LCRH_FIFO_ENABLED 0x10
63#define LCRH_2_STOP_BITS 0x08
64#define LCRH_EVEN_PARITY 0x04
65#define LCRH_PARITY_ENABLE 0x02
66#define LCRH_SEND_BREAK 0x01
67
68/*****************************************************************************/
69/* Line Control Medium Byte Register - LCRM */
70/* This register specifies the high byte of the Baud rate divisor */
71/*****************************************************************************/
72#define LCRM_BAUD_460800 0x00
73#define LCRM_BAUD_230400 0x00
74#define LCRM_BAUD_115200 0x00
75#define LCRM_BAUD_76800 0x00
76#define LCRM_BAUD_57600 0x00
77#define LCRM_BAUD_38400 0x00
78#define LCRM_BAUD_19200 0x00
79#define LCRM_BAUD_14400 0x00
80#define LCRM_BAUD_9600 0x00
81#define LCRM_BAUD_2400 0x01
82#define LCRM_BAUD_1200 0x02
83
84/*****************************************************************************/
85/* Line Control Low Byte Register - LCRL */
86/* This register specifies the low byte of the Baud rate divisor */
87/*****************************************************************************/
88#define LCRL_BAUD_460800 0x01
89#define LCRL_BAUD_230400 0x03
90#define LCRL_BAUD_115200 0x07
91#define LCRL_BAUD_76800 0x0B
92#define LCRL_BAUD_57600 0x0F
93#define LCRL_BAUD_38400 0xC
94#define LCRL_BAUD_19200 0x2F
95#define LCRL_BAUD_14400 0x3F
96#define LCRL_BAUD_9600 0x5F
97#define LCRL_BAUD_2400 0x7F
98#define LCRL_BAUD_1200 0xFF
99
100/*****************************************************************************/
101/* Control Register - CR */
102/*****************************************************************************/
103#define CR_LOOP_BACK_EN 0x80
104#define CR_TIMEOUT_INT_EN 0x40
105#define CR_TX_INT_ENABLE 0x100
106#define CR_RX_INT_ENABLE 0x200
107#define CR_MODSTAT_INT_EN 0x08
108#define CR_UART_ENABLE 0x01
109
110/*****************************************************************************/
111/* Flag Register - FR */
112/*****************************************************************************/
113#define FR_TX_FIFO_EMPTY 0x80
114#define FR_RX_FIFO_FULL 0x40
115#define FR_TX_FIFO_FULL 0x20
116#define FR_RX_FIFO_EMPTY 0x10
117#define FR_BUSY 0x08
118#define FR_CARRIER_DETECT 0x04
119#define FR_SET_READY 0x02
120#define FR_CLEAR_TO_SEND 0x01
121
122/*****************************************************************************/
123/* Interrupt Identification Register - IIR */
124/*****************************************************************************/
125#define IIR_RX_TIME_OUT 0x08
126#define IIR_TX 0x04
127#define IIR_RX 0x02
128#define IIR_MODEM 0x01
129
130void UartStdOutInit(void)
131{
132 /* Disable the serial port while setting the baud rate and word length. */
133 UART0_CR = 0;
134
135 /* Clear the receive status register. */
136 UART0_ECR = 0;
137
138 /* Set the correct baud rate and word length. */
139 UART0_LCRL = LCRL_BAUD_115200;
140 UART0_LCRM = LCRM_BAUD_115200;
141 UART0_LCRH = LCRH_WORD_LENGTH_8;
142
143 /* Explicitly disable FIFO's for char mode. */
144 UART0_LCRH &= ~LCRH_FIFO_ENABLED;
145
146 /* Enable UART0 (and RX/TX) without interrupts. */
147 UART0_CR = CR_UART_ENABLE | CR_TX_INT_ENABLE | CR_RX_INT_ENABLE;
148}
149
150unsigned char UartPutc(unsigned char ch)
151{
152 if (ch == '\n') {
153 (void) UartPutc('\r');
154 }
155 while (UART0_FR & FR_TX_FIFO_FULL)
156 ;
157 UART0_DR = ch;
158
159 return ch;
160}
161
162unsigned char UartGetc(void)
163{
164 unsigned char c;
165 while (UART0_FR & FR_RX_FIFO_EMPTY)
166 ;
167 c = UART0_DR;
168 if (c == '\r') {
169 c = '\n';
170 }
171
172 return c;
173}
174
175bool GetLine (char *lp, unsigned int len)
176{
177 unsigned int cnt = 0;
178 char c;
179
180 do {
181 c = UartGetc();
182 switch (c) {
183 case CNTLQ: /* ignore Control S/Q. */
184 case CNTLS:
185 break;
186 case BACKSPACE:
187 case DEL:
188 if (cnt == 0) {
189 break;
190 }
191 cnt--; /* decrement count. */
192 lp--; /* and line pointer. */
193 UartPutc (0x08); /* echo backspace. */
194 UartPutc (' ');
195 UartPutc (0x08);
196 fflush (stdout);
197 break;
198 case ESC:
199 case 0:
200 *lp = 0; /* ESC - stop editing line. */
201 return false;
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100202 case CR: /* CR - done, stop editing line. */
203 UartPutc (*lp = c); /* Echo and store character. */
204 lp++; /* Increment line pointer */
205 cnt++; /* and count. */
206 c = LF;
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100207 UartPutc (*lp = c); /* Echo and store character. */
Isabella Gottardic5d8bda2021-07-21 10:35:08 +0100208 fflush (stdout);
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100209 lp++; /* Increment line pointer */
210 cnt++; /* and count. */
Kshitij Sisodia659fcd92021-05-19 10:30:06 +0100211 break;
alexander3c798932021-03-26 21:42:19 +0000212 default:
213 UartPutc (*lp = c); /* echo and store character. */
214 fflush (stdout);
215 lp++; /* increment line pointer. */
216 cnt++; /* and count. */
217 break;
218 }
219 } while (cnt < len - 2 && c != LF); /* check limit and CR. */
220 *lp = 0; /* mark end of string. */
221 return true;
222}
223
224__attribute__((noreturn)) void UartEndSimulation(int code)
225{
226 UartPutc((char) 0x4); // End of simulation
227 UartPutc((char) code); // Exit code
228 while(1);
229}