blob: 4cbc68cebd804cbc51f436553d65ed6c6b7e7388 [file] [log] [blame]
Jonny Svärdff265f92020-12-15 16:02:41 +01001/*
2 * Copyright (c) 2019-2020 Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/* Basic CMSDK APB UART driver */
20
21#include "uart_config.h"
22#include "uart_stdout.h"
23#include <stdint.h>
24#include <stdio.h>
25
26#define CNTLQ 0x11
27#define CNTLS 0x13
28#define DEL 0x7F
29#define BACKSPACE 0x08
30#define CR 0x0D
31#define LF 0x0A
32#define ESC 0x1B
33
34#define __IO volatile
35#define __I volatile const
36#define __O volatile
37
38typedef struct {
39 __IO uint32_t DATA; /* Offset: 0x000 (R/W) Data Register */
40 __IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register */
41 __IO uint32_t CTRL; /* Offset: 0x008 (R/W) Control Register */
42 union {
43 __I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */
44 __O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */
45 };
46 __IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */
47} CMSDK_UART_TypeDef;
48
49#define CMSDK_UART0_BASE UART0_BASE
50#define CMSDK_UART0 ((CMSDK_UART_TypeDef *)CMSDK_UART0_BASE)
51#define CMSDK_UART0_BAUDRATE UART0_BAUDRATE
52
53void UartStdOutInit(void) {
54 CMSDK_UART0->BAUDDIV = SYSTEM_CORE_CLOCK / CMSDK_UART0_BAUDRATE;
55
56 CMSDK_UART0->CTRL = ((1ul << 0) | /* TX enable */
57 (1ul << 1)); /* RX enable */
58}
59
60// Output a character
61unsigned char UartPutc(unsigned char my_ch) {
62 while ((CMSDK_UART0->STATE & 1))
63 ; // Wait if Transmit Holding register is full
64
65 if (my_ch == '\n') {
66 CMSDK_UART0->DATA = '\r';
67 while ((CMSDK_UART0->STATE & 1))
68 ; // Wait if Transmit Holding register is full
69 }
70
71 CMSDK_UART0->DATA = my_ch; // write to transmit holding register
72
73 return (my_ch);
74}
75
76// Get a character
77unsigned char UartGetc(void) {
78 unsigned char my_ch;
79 // unsigned int cnt;
80
81 while ((CMSDK_UART0->STATE & 2) == 0) // Wait if Receive Holding register is empty
82 ;
83
84 my_ch = CMSDK_UART0->DATA;
85
86 // Convert CR to LF
87 if (my_ch == '\r')
88 my_ch = '\n';
89
90 return (my_ch);
91}
92
93// Get line from terminal
94unsigned int GetLine(char *lp, unsigned int len) {
95 unsigned int cnt = 0;
96 char c;
97
98 do {
99 c = UartGetc();
100 switch (c) {
101 case CNTLQ: /* ignore Control S/Q */
102 case CNTLS:
103 break;
104 case BACKSPACE:
105 case DEL:
106 if (cnt == 0) {
107 break;
108 }
109 cnt--; /* decrement count */
110 lp--; /* and line pointer */
111 UartPutc(0x08); /* echo backspace */
112 UartPutc(' ');
113 UartPutc(0x08);
114 fflush(stdout);
115 break;
116 case ESC:
117 case 0:
118 *lp = 0; /* ESC - stop editing line */
119 return 0;
120 case CR: /* CR - done, stop editing line */
121 *lp = c;
122 lp++; /* increment line pointer */
123 cnt++; /* and count */
124 c = LF;
Bhavik Patel97906eb2020-12-17 15:32:16 +0100125 /* fall through */
Jonny Svärdff265f92020-12-15 16:02:41 +0100126 default:
127 UartPutc(*lp = c); /* echo and store character */
128 fflush(stdout);
129 lp++; /* increment line pointer */
130 cnt++; /* and count */
131 break;
132 }
133 } while (cnt < len - 2 && c != LF); /* check limit and CR */
134 *lp = 0; /* mark end of string */
135 return 1;
136}