CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
platform-uart.hh
Go to the documentation of this file.
1#pragma once
2
3#ifndef DEFAULT_UART_BAUD_RATE
4# define DEFAULT_UART_BAUD_RATE 921'600
5#endif
6
7#include <bitpack.hh>
8#include <platform/concepts/uart.hh>
9#include <utils.hh>
10
11/**
12 * \file
13 */
14
15/**
16 * OpenTitan UART
17 *
18 * This peripheral's source and documentation can be found at:
19 * https://github.com/lowRISC/opentitan/tree/ab878b5d3578939a04db72d4ed966a56a869b2ed/hw/ip/uart
20 *
21 * Rendered register documentation is served at:
22 * https://opentitan.org/book/hw/ip/uart/doc/registers.html
23 */
25{
26 struct Interrupts : Bitpack<uint32_t>
27 {
28 BITPACK_USUAL_PREFIX;
32 BITPACK_MEMBER_ADD_ENUM_BOOL_CLEARED_ASSERTED(ReceiveOverflowError, 3);
38 };
39
40 struct InterruptState : BitpackDerived<Interrupts>
41 {
42 BITPACK_DERIVED_PREFIX;
43
44 // TransmitWatermark is a status, not an event, so RO, not RW1C.
45 BITPACK_DERIVED_FIELD_CONST_FOR_TYPE(TransmitWatermark, true);
46
47 // ReceiveWatermark is a status, not an event, so RO, not RW1C.
48 BITPACK_DERIVED_FIELD_CONST_FOR_TYPE(ReceiveWatermark, true);
49
50 // TransmitEmpty is a status, not an event, so RO, not RW1C.
51 BITPACK_DERIVED_FIELD_CONST_FOR_TYPE(TransmitEmpty, true);
52 };
53
54 InterruptState interruptState;
55 Interrupts interruptEnable;
56 Interrupts interruptTest;
57
58 /**
59 * Alert Test Register (unused).
60 */
61 uint32_t alertTest;
62
63 struct Control : Bitpack<uint32_t>
64 {
65 BITPACK_USUAL_PREFIX;
71 BITPACK_MEMBER_ADD_ENUM(Parity, uint8_t, 6, 7) {
72 None = 0b00,
73 Even = 0b01,
74 Odd = 0b11,
75 };
76
77 BITPACK_MEMBER_ADD_ENUM(BreakLevel, uint8_t, 8, 9) {
78 Level2 = 0b00,
79 Level4 = 0b01,
80 Level8 = 0b10,
81 Level16 = 0b11,
82 };
83 BITPACK_MEMBER_ADD_NUMERIC(Nco, uint16_t, 16, 31);
84 } control;
85
86 const struct Status : Bitpack<uint32_t>
87 {
88 BITPACK_USUAL_PREFIX;
95 } status; // NOLINT(readability-identifier-naming)
96
97 /**
98 * UART Read Data.
99 */
100 uint32_t readData;
101 /**
102 * UART Write Data.
103 */
104 uint32_t writeData;
105
106 struct FIFOControl : Bitpack<uint32_t>
107 {
108 BITPACK_USUAL_PREFIX;
109
110 BITPACK_MEMBER_ADD_ENUM_BOOL(Receive, AsIs, Reset, 0);
111 BITPACK_MEMBER_ADD_ENUM_BOOL(Transmit, AsIs, Reset, 1);
112
113 BITPACK_MEMBER_ADD_ENUM(ReceiveWatermark, uint8_t, 2, 4) {
114 Level1 = 0b000,
115 Level2 = 0b001,
116 Level4 = 0b010,
117 Level8 = 0b011,
118 Level16 = 0b100,
119 Level32 = 0b101,
120 Level62 = 0b110,
121 };
122 BITPACK_MEMBER_ADD_ENUM(TransmitWatermark, uint8_t, 5, 7) {
123 Level1 = 0b000,
124 Level2 = 0b001,
125 Level4 = 0b010,
126 Level8 = 0b011,
127 Level16 = 0b100,
128 };
129 } fifoControl;
130
131 /**
132 * UART FIFO Status Register.
133 */
134 const struct FIFOStatus : Bitpack<uint32_t>
135 {
136 BITPACK_USUAL_PREFIX;
137
138 BITPACK_MEMBER_ADD_NUMERIC(TransmitLevel, uint8_t, 0, 7);
139 BITPACK_MEMBER_ADD_NUMERIC(ReceiveLevel, uint8_t, 16, 23);
140 } fifoStatus; // NOLINT(readability-identifier-naming)
141
142 /**
143 * Transmit Pin Override Control.
144 *
145 * Gives direct software control over the transmit pin state.
146 */
147 uint32_t override;
148 /**
149 * UART Oversampled Values.
150 */
151 uint32_t values;
152 /**
153 * UART Receive Timeout Control.
154 */
156
157 /**
158 * Configure parity.
159 *
160 * When `enableParity` is set, parity will be enabled.
161 * When `oddParity` is set, the odd parity will be used.
162 */
163 void parity(bool enableParity = true, bool oddParity = false) volatile
164 {
165 using enum Control::Parity;
166 control.set(enableParity ? (oddParity ? Odd : Even) : None);
167 }
168
169 /**
170 * Configure loopback.
171 *
172 * When `systemLoopback` is set, outgoing transmitted bits are routed back
173 * the receiving line. When `lineLoopback` is set, incoming received bits
174 * are forwarded to the transmit line.
175 */
176 void loopback(bool systemLoopback = true,
177 bool lineLoopback = false) volatile
178 {
179 control.alter([=](auto v) {
181 v, =, SystemLoopback{systemLoopback});
182 BITPACK_OPERATE_VALUE_DEPENDENT(v, =, LineLoopback{lineLoopback});
183 return v;
184 });
185 }
186
187 /// Clears the contents of the receive and transmit FIFOs.
188 void fifos_clear() volatile
189 {
190 fifoControl.alter([](auto v) {
191 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Transmit::Reset);
192 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Receive::Reset);
193 return v;
194 });
195 }
196
197 /**
198 * Sets the level transmit watermark.
199 *
200 * When the number of bytes in the transmit FIFO reach this level,
201 * the transmit watermark interrupt will fire.
202 */
203 void transmit_watermark(FIFOControl::TransmitWatermark level) volatile
204 {
205 fifoControl.set(level);
206 }
207
208 /**
209 * Sets the level receive watermark.
210 *
211 * When the number of bytes in the receive FIFO reach this level,
212 * the receive watermark interrupt will fire.
213 */
214 void receive_watermark(FIFOControl::ReceiveWatermark level) volatile
215 {
216 fifoControl.set(level);
217 }
218
219 /// Enable the given interrupt by name
220 template<typename Interrupt>
221 void interrupt_enable() volatile
222 {
223 interruptEnable.member<Interrupt>() = Interrupt{true};
224 }
225
226 /// Disable the given interrupt by name
227 template<typename Interrupt>
228 void interrupt_disable() volatile
229 {
230 interruptEnable.member<Interrupt>() = Interrupt{false};
231 }
232
233 /// Enable the given interrupt(s) by value
234 void interrupt_enable(Interrupts interrupt) volatile
235 {
236 interruptEnable.alter([interrupt](auto v) {
237 return decltype(v){v.raw() | interrupt.raw()};
238 });
239 }
240
241 /// Disable the given interrupt(s) by value
242 void interrupt_disable(Interrupts interrupt) volatile
243 {
244 interruptEnable.alter([interrupt](auto v) {
245 return decltype(v){v.raw() & ~interrupt.raw()};
246 });
247 }
248
249 void init(unsigned baudRate = DEFAULT_UART_BAUD_RATE) volatile
250 {
251 // Nco = 2^20 * baud rate / cpu frequency
252 const uint16_t Nco =
253 ((static_cast<uint64_t>(baudRate) << 20) / CPU_TIMER_HZ);
254
255 control.alter([=](auto v) {
256 BITPACK_OPERATE_VALUE_DEPENDENT(v, =, Nco{Nco});
257 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Transmit::Enabled);
258 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Receive::Enabled);
259 return v;
260 });
261 }
262
263 /// Turn off the transceivers
264 void disable() volatile
265 {
266 control.alter([=](auto v) {
267 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Transmit::Disabled);
268 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Receive::Disabled);
269 return v;
270 });
271 }
272
273 /**
274 * Reset the control register to all zeros. That disables the transceivers,
275 * clears any loopbacks, disables parity, and so on.
276 */
277 void reset() volatile
278 {
279 control = decltype(control){0};
280 }
281
282 [[gnu::always_inline]] uint16_t transmit_fifo_level() volatile
283 {
284 return BITPACK_MEMBER_DECLTYPE(fifoStatus.read(), TransmitLevel).raw();
285 }
286
287 [[gnu::always_inline]] uint16_t receive_fifo_level() volatile
288 {
289 return BITPACK_MEMBER_DECLTYPE(fifoStatus.read(), ReceiveLevel).raw();
290 }
291
292 bool can_write() volatile
293 {
295 status.read(), ==, TransmitFull::Cleared);
296 }
297
298 bool can_read() volatile
299 {
301 status.read(), ==, ReceiveEmpty::Cleared);
302 }
303
304 /**
305 * Write one byte, blocking until the byte is written.
306 */
307 void blocking_write(uint8_t byte) volatile
308 {
309 while (!can_write())
310 {
311 }
312 writeData = byte;
313 }
314
315 /**
316 * Read one byte, blocking until a byte is available.
317 */
318 uint8_t blocking_read() volatile
319 {
320 while (!can_read())
321 {
322 }
323 return readData;
324 }
325};
326
327#ifndef CHERIOT_PLATFORM_CUSTOM_UART
328using Uart = OpenTitanUart;
329static_assert(IsUart<Uart>);
330#endif
constexpr Storage raw() const
A shorter way of spelling static_cast<Storage>(...).
Definition bitpack.hh:404
constexpr void alter(this Self &&self, auto &&f)
Convenience function for unconditionally changing several sub-fields at once.
Definition bitpack.hh:880
constexpr Bitpack()
Definition bitpack.hh:330
const auto read(this Self &&self)
Return a snapshot of the underlying Storage.
Definition bitpack.hh:416
Utility class to delete copy and move contructors.
Definition utils.hh:105
Concept for checking that a UART driver exposes the right interface.
Definition uart.hh:13
#define BITPACK_MEMBER_ADD_ENUM_BOOL_CLEARED_ASSERTED(Type, BitIndex,...)
Define a new boolean scoped enumeration with values named "Cleared" (0) and "Asserted" (1) at the giv...
Definition bitpack.hh:997
#define BITPACK_MEMBER_ADD_ENUM(Type, Base,...)
Encapsulate the gyrations required to define an enum class-typed field and its associated field_info_...
Definition bitpack.hh:964
#define BITPACK_MEMBER_ADD_ENUM_BOOL(Type, FalseVal, TrueVal, BitIndex,...)
Define a new scoped enumeration type whose underlying type is bool, with the given false and true val...
Definition bitpack.hh:987
#define BITPACK_MEMBER_ADD_NUMERIC(Type, Base,...)
Encapsulate the gyrations required to define a Numeric-typed field and its associated field_info_for_...
Definition bitpack.hh:1013
#define BITPACK_MEMBER_ADD_ENUM_BOOL_DISABLED_ENABLED(Type, BitIndex,...)
Define a new boolean scoped enumeration with values named "Disabled" (0) and "Enabled" (1) at the giv...
Definition bitpack.hh:1004
#define BITPACK_DERIVED_FIELD_CONST_FOR_TYPE(Type, c)
Modify the constness field information for a type in a derived bitpack.
Definition bitpack.hh:1102
#define BITPACK_MEMBER_DECLTYPE(b, T)
A convenience macro that presumes the type T is defined within the Bitpack b and finds such a field's...
Definition bitpack.hh:1054
#define BITPACK_OPERATE_VALUE_DEPENDENT(b, operator,value)
BITPACK_OPERATE_VALUE with dependent qualification for the type of the bitpack.
Definition bitpack.hh:1246
#define BITPACK_OPERATE_VALUE_DECLTYPE(b, operator,value)
Given a bitpack b – not a Proxy of a Field therein – qualify the given value with the bitpack's type ...
Definition bitpack.hh:1238
It is occasionally useful to derive one bitpack from another.
Definition bitpack.hh:914
UART FIFO Status Register.
OpenTitan UART.
void transmit_watermark(FIFOControl::TransmitWatermark level) volatile
Sets the level transmit watermark.
void reset() volatile
Reset the control register to all zeros.
void loopback(bool systemLoopback=true, bool lineLoopback=false) volatile
Configure loopback.
void blocking_write(uint8_t byte) volatile
Write one byte, blocking until the byte is written.
void interrupt_enable(Interrupts interrupt) volatile
Enable the given interrupt(s) by value.
uint32_t alertTest
Alert Test Register (unused).
void interrupt_enable() volatile
Enable the given interrupt by name.
uint32_t timeoutControl
UART Receive Timeout Control.
void parity(bool enableParity=true, bool oddParity=false) volatile
Configure parity.
uint32_t readData
UART Read Data.
void interrupt_disable() volatile
Disable the given interrupt by name.
void fifos_clear() volatile
Clears the contents of the receive and transmit FIFOs.
uint32_t writeData
UART Write Data.
void disable() volatile
Turn off the transceivers.
void receive_watermark(FIFOControl::ReceiveWatermark level) volatile
Sets the level receive watermark.
void interrupt_disable(Interrupts interrupt) volatile
Disable the given interrupt(s) by value.
uint32_t values
UART Oversampled Values.
uint8_t blocking_read() volatile
Read one byte, blocking until a byte is available.
Miscellaneous utility functions and classes.