@@ -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