CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Toggle main menu visibility
Loading...
Searching...
No Matches
sdk
include
platform
generic-riscv
platform-uart.hh
1
// Copyright Microsoft and CHERIoT Contributors.
2
// SPDX-License-Identifier: MIT
3
4
#pragma once
5
6
#include <platform/concepts/uart.hh>
7
#include <stdint.h>
8
9
/**
10
* Generic 16550A memory-mapped register layout.
11
*
12
* The registers are 8 bits wide, but typically the bus supports only 4-byte
13
* (or larger) transactions and so they are padded to a 32-bit word. The
14
* template parameter allows this to be controlled.
15
*/
16
template
<
typename
RegisterType = u
int
32_t>
17
class
Uart16550
18
{
19
static
void
no_custom_init() {}
20
21
public
:
22
/**
23
* The interface to the read/write FIFOs for this UART.
24
*
25
* This is also the low byte of the divisor when the divisor latch (bit 7 of
26
* the `lineControl`) is set.
27
*/
28
RegisterType
data
;
29
/**
30
* Interrupt-enabled control / status. Write 1 to enabled, 0 to disable, to
31
* each of the low four bits:
32
*
33
* 0: Data-receive interrupt
34
* 1: Transmit holding register empty interrupt
35
* 2: Receive line status interrupts
36
* 3: Modem status interrupts.
37
*
38
* When bit 7 of `lineControl` is set, this is instead the
39
* divisor-latch-high register and stores the high 8 bits of the divisor.
40
*/
41
RegisterType
intrEnable
;
42
/**
43
* Interrupt identification and FIFO enable/disable.
44
*
45
* We only care about the low bit here, which enables the FIFO.
46
*/
47
RegisterType
intrIDandFifo
;
48
/**
49
* Specifies properties of the line (stop bit, parity, and so on). The
50
* only bit that we use is bit 7, the divisor latch, which enables writing
51
* the speed.
52
*/
53
RegisterType
lineControl
;
54
/**
55
* Modem control.
56
*/
57
RegisterType
modemControl
;
58
/**
59
* The line status word. The bits that we care about are:
60
*
61
* 0: Receive ready
62
* 5: Transmit buffer empty
63
*/
64
const
RegisterType
LineStatus
;
65
/**
66
* Modem status.
67
*/
68
const
RegisterType
ModemStatus
;
69
/**
70
* Scratch register. Unused.
71
*/
72
RegisterType
scratch
;
73
74
/**
75
* Returns true if the transmit buffer is empty.
76
*/
77
__always_inline
bool
can_write
()
volatile
78
{
79
#ifdef SIMULATION
80
// If we're in a simulator, we're running *much* slower than the thing
81
// handling the UART, so assume that you can always write to the UART.
82
return
true
;
83
#else
84
return
LineStatus
& (1 << 5);
85
#endif
86
}
87
88
/**
89
* Returns true if the receive buffer is not.
90
*/
91
__always_inline
bool
can_read
()
volatile
92
{
93
return
LineStatus
& (1 << 0);
94
}
95
96
/**
97
* Read one byte, blocking until a byte is available.
98
*/
99
uint8_t
blocking_read
()
volatile
100
{
101
while
(!
can_read
())
102
{
103
}
104
return
data
;
105
}
106
107
/**
108
* Write one byte, blocking until the byte is written.
109
*/
110
void
blocking_write
(uint8_t
byte
)
volatile
111
{
112
while
(!
can_write
())
113
{
114
}
115
data
= byte;
116
}
117
118
/**
119
* Initialise the UART.
120
*/
121
template
<
typename
T = decltype(no_custom_init)>
122
void
init
(
int
divisor = 1, T &&otherSetup = no_custom_init)
volatile
123
{
124
// Disable interrupts
125
intrEnable
= 0x00;
126
// Set the divisor latch (we're going to write the divisor) and set the
127
// character width to 8 bits, one stop bit, no parity.
128
lineControl
= 0x83;
129
// Set the divisor
130
data
= divisor & 0xff;
131
intrEnable
= (divisor >> 8) & 0xff;
132
// Run any other setup that we were asked to do.
133
otherSetup();
134
// Clear the divisor latch
135
lineControl
= 0x03;
136
// Enable the FIFO and reset
137
// Enabled bits:
138
// 0 - Enable FIFOs
139
// 1 - Clear receive FIFO
140
// 2 - Clear send FIFO
141
// 5 - 64-byte FIFO (if available)
142
intrIDandFifo
= 0x1;
143
}
144
};
145
146
// A platform can provide a custom version of this.
147
#ifndef CHERIOT_PLATFORM_CUSTOM_UART
148
/// The default UART type.
149
using
Uart =
Uart16550<uint32_t>
;
150
// Check that our UART matches the concept.
151
static_assert
(
IsUart<Uart>
);
152
#endif
Uart16550
Generic 16550A memory-mapped register layout.
Definition
platform-uart.hh:18
Uart16550< uint32_t >::modemControl
uint32_t modemControl
Definition
platform-uart.hh:57
Uart16550< uint32_t >::intrEnable
uint32_t intrEnable
Definition
platform-uart.hh:41
Uart16550< uint32_t >::ModemStatus
const uint32_t ModemStatus
Definition
platform-uart.hh:68
Uart16550::blocking_read
uint8_t blocking_read() volatile
Read one byte, blocking until a byte is available.
Definition
platform-uart.hh:99
Uart16550< uint32_t >::lineControl
uint32_t lineControl
Definition
platform-uart.hh:53
Uart16550::can_write
bool can_write() volatile
Returns true if the transmit buffer is empty.
Definition
platform-uart.hh:77
Uart16550< uint32_t >::scratch
uint32_t scratch
Definition
platform-uart.hh:72
Uart16550< uint32_t >::data
uint32_t data
Definition
platform-uart.hh:28
Uart16550::init
void init(int divisor=1, T &&otherSetup=no_custom_init) volatile
Initialise the UART.
Definition
platform-uart.hh:122
Uart16550::blocking_write
void blocking_write(uint8_t byte) volatile
Write one byte, blocking until the byte is written.
Definition
platform-uart.hh:110
Uart16550< uint32_t >::LineStatus
const uint32_t LineStatus
Definition
platform-uart.hh:64
Uart16550< uint32_t >::intrIDandFifo
uint32_t intrIDandFifo
Definition
platform-uart.hh:47
Uart16550::can_read
bool can_read() volatile
Returns true if the receive buffer is not.
Definition
platform-uart.hh:91
IsUart
Concept for checking that a UART driver exposes the right interface.
Definition
uart.hh:13
Generated by
1.18.0