Skip to content

Commit 9edaf1f

Browse files
committed
[otlib] Add support for other QEMU UARTs
Signed-off-by: James Wainwright <[email protected]>
1 parent 0547ea4 commit 9edaf1f

File tree

2 files changed

+49
-34
lines changed

2 files changed

+49
-34
lines changed

rules/opentitan/qemu.bzl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,15 @@ def _test_dispatch(ctx, exec_env, firmware):
436436
qemu_args += ["-chardev", "pty,id=monitor,path=qemu-monitor"]
437437
qemu_args += ["-mon", "chardev=monitor,mode=control"]
438438

439-
# Create a chardev for the console UART:
440-
qemu_args += ["-chardev", "pty,id=console"]
441-
qemu_args += ["-serial", "chardev:console"]
439+
# Create chardevs for each UART:
440+
qemu_args += ["-chardev", "pty,id=uart0"]
441+
qemu_args += ["-chardev", "pty,id=uart1"]
442+
qemu_args += ["-chardev", "pty,id=uart2"]
443+
qemu_args += ["-chardev", "pty,id=uart3"]
444+
qemu_args += ["-serial", "chardev:uart0"]
445+
qemu_args += ["-serial", "chardev:uart1"]
446+
qemu_args += ["-serial", "chardev:uart2"]
447+
qemu_args += ["-serial", "chardev:uart3"]
442448

443449
# Create a chardev for the log device:
444450
qemu_args += ["-chardev", "pty,id=log"]

sw/host/opentitanlib/src/transport/qemu/mod.rs

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub struct Qemu {
5151
reset: Rc<dyn GpioPin>,
5252

5353
/// Console UART.
54-
console: Option<Rc<dyn Uart>>,
54+
uarts: HashMap<String, Rc<dyn Uart>>,
5555

5656
/// SPI device.
5757
spi: Option<Rc<dyn Target>>,
@@ -72,7 +72,7 @@ impl Qemu {
7272
/// The transport will configure capabilities that it can find from the running QEMU instance.
7373
/// It looks for the following chardevs which should be connected to QEMU devices:
7474
///
75-
/// * `console` (pty) - connect to UART using `-serial chardev:console`.
75+
/// * `uart{n}` (pty) - connect to UARTs in order using `-serial chardev:uart{n}`.
7676
/// * `log` (pty) - connect to QEMU's log using `-global ot-ibex_wrapper.logdev=log`.
7777
/// * `spidev` (pty) - automatically connected to QEMU spi device.
7878
/// * `i2c{n}` (pty) - connect to I2C bus using `-device ot-i2c_host_proxy,bus=ot-i2c{n},chardev=i2c{n}`.
@@ -95,21 +95,29 @@ impl Qemu {
9595
.find_map(|c| (c.id == id).then_some(&c.kind))
9696
}
9797

98-
// Console UART:
99-
let console = match find_chardev(&chardevs, "console") {
100-
Some(ChardevKind::Pty { path }) => {
101-
let serial_port =
102-
SerialPortUart::open_pseudo(path.to_str().unwrap(), CONSOLE_BAUDRATE)
103-
.context("failed to open QEMU console PTY")?;
104-
let uart: Rc<dyn Uart> =
105-
Rc::new(QemuUart::new(Rc::clone(&monitor), "console", serial_port));
106-
Some(uart)
107-
}
108-
_ => {
109-
log::info!("could not find pty chardev with id=console, skipping UART");
110-
None
111-
}
112-
};
98+
// UARTs:
99+
let mut uarts = HashMap::new();
100+
for chardev in &chardevs {
101+
let Some(id) = chardev.id.strip_prefix("uart") else {
102+
continue;
103+
};
104+
105+
let ChardevKind::Pty { ref path } = chardev.kind else {
106+
continue;
107+
};
108+
109+
let serial_port = SerialPortUart::open_pseudo(path.to_str().unwrap(), CONSOLE_BAUDRATE)
110+
.context("failed to open QEMU console PTY")?;
111+
let uart: Rc<dyn Uart> =
112+
Rc::new(QemuUart::new(Rc::clone(&monitor), "console", serial_port));
113+
114+
uarts.insert(id.to_string(), uart);
115+
}
116+
if uarts.is_empty() {
117+
log::info!(
118+
"could not find pty chardevs with ids starting with `uart`, UART support disabled"
119+
);
120+
}
113121

114122
// QEMU log, not really a UART but modelled as one:
115123
let log = match find_chardev(&chardevs, "log") {
@@ -121,7 +129,7 @@ impl Qemu {
121129
Some(log)
122130
}
123131
_ => {
124-
log::info!("could not find pty chardev with id=log, skipping QEMU log");
132+
log::info!("could not find pty chardev with id=log, QEMU log unavailable");
125133
None
126134
}
127135
};
@@ -134,7 +142,7 @@ impl Qemu {
134142
Some(spi)
135143
}
136144
_ => {
137-
log::info!("could not find pty chardev with id=spidev, skipping SPI");
145+
log::info!("could not find pty chardev with id=spidev, SPI support disabled");
138146
None
139147
}
140148
};
@@ -157,9 +165,9 @@ impl Qemu {
157165
}
158166
if i2cs.is_empty() {
159167
log::info!(
160-
"could not find pty chardevs with ids starting with `i2c`, skipping I2C bus"
161-
);
162168
"could not find pty chardevs with ids starting with `i2c`, I2C support disabled"
169+
);
170+
}
163171

164172
// If there's a chardev called `gpio`, configure it as a PTY and use as the GPIO pins.
165173
let gpio = match find_chardev(&chardevs, "gpio") {
@@ -169,7 +177,7 @@ impl Qemu {
169177
Some(gpio)
170178
}
171179
_ => {
172-
log::info!("could not find pty chardev with id=gpio, skipping GPIO");
180+
log::info!("could not find pty chardev with id=gpio, GPIO support disabled");
173181
None
174182
}
175183
};
@@ -185,7 +193,7 @@ impl Qemu {
185193
Ok(Qemu {
186194
monitor,
187195
reset,
188-
console,
196+
uarts,
189197
log,
190198
spi,
191199
i2cs,
@@ -201,7 +209,7 @@ impl Transport for Qemu {
201209
// GPIO pin in `.gpio_pin` will cause an error if GPIO isn't connected.
202210
let mut cap = Capability::GPIO;
203211

204-
if self.console.is_some() || self.log.is_some() {
212+
if !self.uarts.is_empty() || self.log.is_some() {
205213
cap |= Capability::UART;
206214
}
207215

@@ -217,14 +225,15 @@ impl Transport for Qemu {
217225
}
218226

219227
fn uart(&self, instance: &str) -> anyhow::Result<Rc<dyn Uart>> {
220-
match instance {
221-
"0" => Ok(Rc::clone(
222-
self.console.as_ref().context("uart 0 not connected")?,
223-
)),
224-
"LOG" => Ok(Rc::clone(
228+
if instance == "LOG" {
229+
return Ok(Rc::clone(
225230
self.log.as_ref().context("QEMU log not connected")?,
226-
)),
227-
_ => Err(TransportError::InvalidInstance(
231+
));
232+
}
233+
234+
match self.uarts.get(instance) {
235+
Some(uart) => Ok(Rc::clone(uart)),
236+
None => Err(TransportError::InvalidInstance(
228237
TransportInterfaceType::Uart,
229238
instance.to_string(),
230239
)

0 commit comments

Comments
 (0)