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, 5, 6) {
72 None = 0b00,
73 Even = 0b01,
74 Odd = 0b11,
75 };
76
77 BITPACK_MEMBER_ADD_NUMERIC(BreakLevel, uint8_t, 8, 9);
78 BITPACK_MEMBER_ADD_NUMERIC(Nco, uint16_t, 16, 31);
79 } control;
80
81 const struct Status : Bitpack<uint32_t>
82 {
83 BITPACK_USUAL_PREFIX;
90 } status; // NOLINT(readability-identifier-naming)
91
92 /**
93 * UART Read Data.
94 */
95 uint32_t readData;
96 /**
97 * UART Write Data.
98 */
99 uint32_t writeData;
100
101 struct FIFOControl : Bitpack<uint32_t>
102 {
103 BITPACK_USUAL_PREFIX;
104
105 BITPACK_MEMBER_ADD_ENUM_BOOL(Receive, AsIs, Reset, 0);
106 BITPACK_MEMBER_ADD_ENUM_BOOL(Transmit, AsIs, Reset, 1);
107
108 BITPACK_MEMBER_ADD_ENUM(ReceiveWatermark, uint8_t, 2, 4) {
109 Level1 = 0b000,
110 Level2 = 0b001,
111 Level4 = 0b010,
112 Level8 = 0b011,
113 Level16 = 0b100,
114 Level32 = 0b101,
115 Level62 = 0b110,
116 };
117 BITPACK_MEMBER_ADD_ENUM(TransmitWatermark, uint8_t, 5, 7) {
118 Level1 = 0b000,
119 Level2 = 0b001,
120 Level4 = 0b010,
121 Level8 = 0b011,
122 Level16 = 0b100,
123 };
124 } fifoControl;
125
126 /**
127 * UART FIFO Status Register.
128 */
129 const struct FIFOStatus : Bitpack<uint32_t>
130 {
131 BITPACK_USUAL_PREFIX;
132
133 BITPACK_MEMBER_ADD_NUMERIC(TransmitLevel, uint8_t, 0, 7);
134 BITPACK_MEMBER_ADD_NUMERIC(ReceiveLevel, uint8_t, 16, 23);
135 } fifoStatus; // NOLINT(readability-identifier-naming)
136
137 /**
138 * Transmit Pin Override Control.
139 *
140 * Gives direct software control over the transmit pin state.
141 */
142 uint32_t override;
143 /**
144 * UART Oversampled Values.
145 */
146 uint32_t values;
147 /**
148 * UART Receive Timeout Control.
149 */
151
152 /**
153 * Configure parity.
154 *
155 * When `enableParity` is set, parity will be enabled.
156 * When `oddParity` is set, the odd parity will be used.
157 */
158 void parity(bool enableParity = true, bool oddParity = false) volatile
159 {
160 using enum Control::Parity;
161 control.set(enableParity ? (oddParity ? Odd : Even) : None);
162 }
163
164 /**
165 * Configure loopback.
166 *
167 * When `systemLoopback` is set, outgoing transmitted bits are routed back
168 * the receiving line. When `lineLoopback` is set, incoming received bits
169 * are forwarded to the transmit line.
170 */
171 void loopback(bool systemLoopback = true,
172 bool lineLoopback = false) volatile
173 {
174 control.alter([=](auto v) {
176 v, =, SystemLoopback{systemLoopback});
177 BITPACK_OPERATE_VALUE_DEPENDENT(v, =, LineLoopback{lineLoopback});
178 return v;
179 });
180 }
181
182 /// Clears the contents of the receive and transmit FIFOs.
183 void fifos_clear() volatile
184 {
185 fifoControl.alter([](auto v) {
186 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Transmit::Reset);
187 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Receive::Reset);
188 return v;
189 });
190 }
191
192 /**
193 * Sets the level transmit watermark.
194 *
195 * When the number of bytes in the transmit FIFO reach this level,
196 * the transmit watermark interrupt will fire.
197 */
198 void transmit_watermark(FIFOControl::TransmitWatermark level) volatile
199 {
200 fifoControl.set(level);
201 }
202
203 /**
204 * Sets the level receive watermark.
205 *
206 * When the number of bytes in the receive FIFO reach this level,
207 * the receive watermark interrupt will fire.
208 */
209 void receive_watermark(FIFOControl::ReceiveWatermark level) volatile
210 {
211 fifoControl.set(level);
212 }
213
214 /// Enable the given interrupt by name
215 template<typename Interrupt>
216 void interrupt_enable() volatile
217 {
218 interruptEnable.member<Interrupt>() = Interrupt{true};
219 }
220
221 /// Disable the given interrupt by name
222 template<typename Interrupt>
223 void interrupt_disable() volatile
224 {
225 interruptEnable.member<Interrupt>() = Interrupt{false};
226 }
227
228 /// Enable the given interrupt(s) by value
229 void interrupt_enable(Interrupts interrupt) volatile
230 {
231 interruptEnable.alter([interrupt](auto v) {
232 return decltype(v){v.raw() | interrupt.raw()};
233 });
234 }
235
236 /// Disable the given interrupt(s) by value
237 void interrupt_disable(Interrupts interrupt) volatile
238 {
239 interruptEnable.alter([interrupt](auto v) {
240 return decltype(v){v.raw() & ~interrupt.raw()};
241 });
242 }
243
244 void init(unsigned baudRate = DEFAULT_UART_BAUD_RATE) volatile
245 {
246 // Nco = 2^20 * baud rate / cpu frequency
247 const uint16_t Nco =
248 ((static_cast<uint64_t>(baudRate) << 20) / CPU_TIMER_HZ);
249
250 control.alter([=](auto v) {
251 BITPACK_OPERATE_VALUE_DEPENDENT(v, =, Nco{Nco});
252 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Transmit::Enabled);
253 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Receive::Enabled);
254 return v;
255 });
256 }
257
258 /// Turn off the transceivers
259 void disable() volatile
260 {
261 control.alter([=](auto v) {
262 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Transmit::Disabled);
263 BITPACK_OPERATE_VALUE_DECLTYPE(v, =, Receive::Disabled);
264 return v;
265 });
266 }
267
268 /**
269 * Reset the control register to all zeros. That disables the transceivers,
270 * clears any loopbacks, disables parity, and so on.
271 */
272 void reset() volatile
273 {
274 control = decltype(control){0};
275 }
276
277 [[gnu::always_inline]] uint16_t transmit_fifo_level() volatile
278 {
279 return BITPACK_MEMBER_DECLTYPE(fifoStatus.read(), TransmitLevel).raw();
280 }
281
282 [[gnu::always_inline]] uint16_t receive_fifo_level() volatile
283 {
284 return BITPACK_MEMBER_DECLTYPE(fifoStatus.read(), ReceiveLevel).raw();
285 }
286
287 bool can_write() volatile
288 {
290 status.read(), ==, TransmitFull::Cleared);
291 }
292
293 bool can_read() volatile
294 {
296 status.read(), ==, ReceiveEmpty::Cleared);
297 }
298
299 /**
300 * Write one byte, blocking until the byte is written.
301 */
302 void blocking_write(uint8_t byte) volatile
303 {
304 while (!can_write())
305 {
306 }
307 writeData = byte;
308 }
309
310 /**
311 * Read one byte, blocking until a byte is available.
312 */
313 uint8_t blocking_read() volatile
314 {
315 while (!can_read())
316 {
317 }
318 return readData;
319 }
320};
321
322#ifndef CHERIOT_PLATFORM_CUSTOM_UART
323using Uart = OpenTitanUart;
324static_assert(IsUart<Uart>);
325#endif
constexpr Storage raw() const
A shorter way of spelling static_cast<Storage>(...).
Definition bitpack.hh:403
constexpr void alter(this Self &&self, auto &&f)
Convenience function for unconditionally changing several sub-fields at once.
Definition bitpack.hh:879
constexpr Bitpack()
Definition bitpack.hh:329
const auto read(this Self &&self)
Return a snapshot of the underlying Storage.
Definition bitpack.hh:415
Utility class to delete copy and move contructors.
Definition utils.hh:53
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:996
#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:963
#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:986
#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:1012
#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:1003
#define BITPACK_DERIVED_FIELD_CONST_FOR_TYPE(Type, c)
Modify the constness field information for a type in a derived bitpack.
Definition bitpack.hh:1101
#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:1053
#define BITPACK_OPERATE_VALUE_DEPENDENT(b, operator,value)
BITPACK_OPERATE_VALUE with dependent qualification for the type of the bitpack.
Definition bitpack.hh:1245
#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:1237
It is occasionally useful to derive one bitpack from another.
Definition bitpack.hh:913
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.