1pub mod command;
7pub mod config;
8
9mod gpio;
10mod i2c;
11mod spi;
12
13use crate::debug::openocd::OpenOcdJtagChain;
14use crate::io::emu::Emulator;
15use crate::io::gpio::{GpioBitbanging, GpioMonitoring, GpioPin, PinMode, PullMode};
16use crate::io::i2c::Bus;
17use crate::io::ioexpander::IoExpander;
18use crate::io::jtag::{JtagChain, JtagParams};
19use crate::io::spi::{Target, TransferMode};
20use crate::io::uart::Uart;
21use crate::io::usb::UsbContext;
22use crate::transport::{
23 Capability, FpgaOps, ProgressIndicator, ProxyOps, Transport, TransportError,
24 TransportInterfaceType, ioexpander,
25};
26
27use anyhow::{Result, bail, ensure};
28use indicatif::{ProgressBar, ProgressStyle};
29use serialport::Parity;
30use std::any::Any;
31use std::cell::{Cell, RefCell};
32use std::collections::hash_map::Entry;
33use std::collections::{HashMap, HashSet};
34use std::path::PathBuf;
35use std::rc::Rc;
36use std::time::Duration;
37use std::vec::Vec;
38
39pub struct NoProgressBar;
40
41impl ProgressIndicator for NoProgressBar {
42 fn new_stage(&self, _name: &str, _total: usize) {}
43 fn progress(&self, _absolute: usize) {}
44}
45
46pub struct StagedProgressBar {
50 pub current_progress_bar: Rc<RefCell<Option<indicatif::ProgressBar>>>,
51}
52
53impl Default for StagedProgressBar {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl StagedProgressBar {
60 const DEFAULT_TEMPLATE: &str = "[{elapsed_precise}] [{wide_bar}] {bytes}/{total_bytes} ({eta})";
61 const STAGE_TEMPLATE: &str =
62 "{msg}: [{elapsed_precise}] [{wide_bar}] {bytes}/{total_bytes} ({eta})";
63
64 pub fn new() -> Self {
65 Self {
66 current_progress_bar: Rc::new(RefCell::new(None)),
67 }
68 }
69
70 pub fn enable_steady_tick(&self, duration: Duration) {
71 let bar = self.current_progress_bar.borrow();
72 let bar = bar.as_ref().unwrap();
73 bar.enable_steady_tick(duration);
74 }
75
76 pub fn bytes_per_second(&self) -> f64 {
79 let bar = self.current_progress_bar.borrow();
80 let bar = bar.as_ref().unwrap();
81 bar.length().unwrap() as f64 / bar.elapsed().as_secs_f64()
82 }
83}
84
85impl ProgressIndicator for StagedProgressBar {
86 fn new_stage(&self, name: &str, total: usize) {
87 let progress = ProgressBar::new(total as u64);
88 if name.is_empty() {
89 progress.set_style(
90 ProgressStyle::default_bar()
91 .template(Self::DEFAULT_TEMPLATE)
92 .unwrap(),
93 );
94 } else {
95 progress.set_style(
96 ProgressStyle::default_bar()
97 .template(Self::STAGE_TEMPLATE)
98 .unwrap(),
99 );
100 }
101 self.current_progress_bar
102 .borrow_mut()
103 .replace(progress.with_message(name.to_string()));
104 }
105
106 fn progress(&self, pos: usize) {
107 let bar = self.current_progress_bar.borrow();
108 let bar = bar.as_ref().unwrap();
109 if pos as u64 == bar.length().unwrap() {
110 bar.finish();
111 return;
112 }
113 bar.set_position(pos as u64);
114 }
115}
116
117#[derive(Clone, Copy, Default, Debug)]
118pub struct PinConfiguration {
119 pub mode: Option<PinMode>,
121 pub level: Option<bool>,
124 pub pull_mode: Option<PullMode>,
126 pub volts: Option<f32>,
129 pub invert: Option<bool>,
130}
131
132fn merge_field<T>(f1: &mut Option<T>, f2: &Option<T>) -> Result<(), ()>
133where
134 T: PartialEq<T> + Clone,
135{
136 match (&*f1, f2) {
137 (Some(v1), Some(v2)) if *v1 != *v2 => return Err(()),
138 (None, _) => *f1 = f2.clone(),
139 _ => (),
140 }
141 Ok(())
142}
143
144impl PinConfiguration {
145 fn merge(&mut self, other: &PinConfiguration) -> Result<(), ()> {
150 merge_field(&mut self.mode, &other.mode)?;
151 merge_field(&mut self.level, &other.level)?;
152 merge_field(&mut self.pull_mode, &other.pull_mode)?;
153 merge_field(&mut self.volts, &other.volts)?;
154 merge_field(&mut self.invert, &other.invert)?;
155 Ok(())
156 }
157
158 #[must_use]
161 fn override_with(&self, overrides: Option<&Self>) -> Self {
162 let Some(overrides) = overrides else {
163 return *self;
164 };
165 let mut result = *self;
166 overrides.mode.map(|v| result.mode.replace(v));
167 overrides.level.map(|v| result.level.replace(v));
168 overrides.pull_mode.map(|v| result.pull_mode.replace(v));
169 overrides.volts.map(|v| result.volts.replace(v));
170 overrides.invert.map(|v| result.invert.replace(v));
171 result
172 }
173}
174
175#[derive(Default, Debug)]
176pub struct UartConfiguration {
177 pub underlying_instance: String,
178 pub baud_rate: Option<u32>,
179 pub parity: Option<config::UartParity>,
180 pub stop_bits: Option<config::UartStopBits>,
181 pub alias_of: Option<String>,
182}
183
184#[derive(Default, Debug)]
185pub struct SpiConfiguration {
186 pub underlying_instance: String,
187 pub mode: Option<TransferMode>,
188 pub serial_clock: Option<String>,
189 pub host_out_device_in: Option<String>,
190 pub host_in_device_out: Option<String>,
191 pub chip_select: Option<String>,
192 pub gsc_ready: Option<String>,
193 pub bits_per_word: Option<u32>,
194 pub bits_per_sec: Option<u32>,
195}
196
197#[derive(Default, Debug)]
198pub struct I2cConfiguration {
199 pub underlying_instance: String,
200 pub default_addr: Option<u8>,
201 pub bits_per_sec: Option<u32>,
202}
203
204pub struct TransportWrapperBuilder {
205 interface: String,
206 disable_dft_on_reset: bool,
207 reset_delay: Duration,
208 openocd_adapter_config: Option<PathBuf>,
209 provides_list: Vec<(String, String)>,
210 requires_list: Vec<(String, String)>,
211 pin_alias_map: HashMap<String, String>,
212 pin_on_io_expander_map: HashMap<String, config::IoExpanderPin>,
213 pin_conf_list: Vec<(String, PinConfiguration)>,
214 uart_conf_map: HashMap<String, config::UartConfiguration>,
215 spi_conf_map: HashMap<String, config::SpiConfiguration>,
216 i2c_conf_map: HashMap<String, config::I2cConfiguration>,
217 strapping_conf_map: HashMap<String, Vec<(String, PinConfiguration)>>,
218 io_expander_conf_map: HashMap<String, config::IoExpander>,
219 gpio_conf: HashSet<String>,
220}
221
222pub struct TransportWrapper {
226 transport: Rc<dyn Transport>,
227 disable_dft_on_reset: Cell<bool>,
228 reset_delay: Cell<Duration>,
229 openocd_adapter_config: Option<PathBuf>,
230 provides_map: HashMap<String, String>,
231 pin_map: HashMap<String, String>,
232 artificial_pin_map: HashMap<String, Rc<dyn GpioPin>>,
233 pin_conf_map: HashMap<String, PinConfiguration>,
234 uart_conf_map: HashMap<String, UartConfiguration>,
235 spi_conf_map: HashMap<String, SpiConfiguration>,
236 i2c_conf_map: HashMap<String, I2cConfiguration>,
237 strapping_conf_map: HashMap<String, HashMap<String, PinConfiguration>>,
238 gpio_conf: HashSet<String>,
239 pin_instance_map: RefCell<HashMap<String, Rc<gpio::GpioPinWrapper>>>,
248 spi_physical_map: RefCell<HashMap<String, Rc<spi::PhysicalSpiWrapper>>>,
249 spi_logical_map: RefCell<HashMap<String, Rc<spi::LogicalSpiWrapper>>>,
250 i2c_physical_map: RefCell<HashMap<String, Rc<i2c::PhysicalI2cWrapper>>>,
251 i2c_logical_map: RefCell<HashMap<String, Rc<i2c::LogicalI2cWrapper>>>,
252}
253
254impl TransportWrapperBuilder {
255 pub fn new(interface: String, disable_dft_on_reset: bool) -> Self {
256 Self {
257 interface,
258 disable_dft_on_reset,
259 reset_delay: Duration::from_millis(100),
260 openocd_adapter_config: None,
261 provides_list: Vec::new(),
262 requires_list: Vec::new(),
263 pin_alias_map: HashMap::new(),
264 pin_on_io_expander_map: HashMap::new(),
265 pin_conf_list: Vec::new(),
266 uart_conf_map: HashMap::new(),
267 spi_conf_map: HashMap::new(),
268 i2c_conf_map: HashMap::new(),
269 strapping_conf_map: HashMap::new(),
270 io_expander_conf_map: HashMap::new(),
271 gpio_conf: HashSet::new(),
272 }
273 }
274
275 fn record_pin_conf(
276 pin_conf_list: &mut Vec<(String, PinConfiguration)>,
277 pin_conf: &config::PinConfiguration,
278 ) {
279 if (None, None, None, None, None)
280 == (
281 pin_conf.mode,
282 pin_conf.pull_mode,
283 pin_conf.level,
284 pin_conf.volts,
285 pin_conf.invert,
286 )
287 {
288 return;
289 }
290 let mut conf_entry: PinConfiguration = PinConfiguration::default();
291 if let Some(pin_mode) = pin_conf.mode {
292 conf_entry.mode = Some(pin_mode);
293 }
294 if let Some(pull_mode) = pin_conf.pull_mode {
295 conf_entry.pull_mode = Some(pull_mode);
296 }
297 if let Some(level) = pin_conf.level {
298 conf_entry.level = Some(level);
299 }
300 if let Some(volts) = pin_conf.volts {
301 conf_entry.volts = Some(volts);
302 }
303 if let Some(invert) = pin_conf.invert {
304 conf_entry.invert = Some(invert);
305 }
306 pin_conf_list.push((pin_conf.name.to_string(), conf_entry))
307 }
308
309 fn record_uart_conf(
310 uart_conf_map: &mut HashMap<String, config::UartConfiguration>,
311 uart_conf: &config::UartConfiguration,
312 ) -> Result<(), ()> {
313 let entry = uart_conf_map
314 .entry(uart_conf.name.to_uppercase().to_string())
315 .or_insert_with(|| config::UartConfiguration {
316 name: uart_conf.name.clone(),
317 ..Default::default()
318 });
319 merge_field(&mut entry.baudrate, &uart_conf.baudrate)?;
320 merge_field(&mut entry.parity, &uart_conf.parity)?;
321 merge_field(&mut entry.stopbits, &uart_conf.stopbits)?;
322 merge_field(&mut entry.alias_of, &uart_conf.alias_of)?;
323 Ok(())
324 }
325
326 fn record_spi_conf(
327 spi_conf_map: &mut HashMap<String, config::SpiConfiguration>,
328 spi_conf: &config::SpiConfiguration,
329 ) -> Result<(), ()> {
330 let entry = spi_conf_map
331 .entry(spi_conf.name.to_string())
332 .or_insert_with(|| config::SpiConfiguration {
333 name: spi_conf.name.clone(),
334 ..Default::default()
335 });
336 merge_field(&mut entry.mode, &spi_conf.mode)?;
337 merge_field(&mut entry.bits_per_word, &spi_conf.bits_per_word)?;
338 merge_field(&mut entry.bits_per_sec, &spi_conf.bits_per_sec)?;
339 merge_field(&mut entry.serial_clock, &spi_conf.serial_clock)?;
340 merge_field(&mut entry.host_out_device_in, &spi_conf.host_out_device_in)?;
341 merge_field(&mut entry.host_in_device_out, &spi_conf.host_in_device_out)?;
342 merge_field(&mut entry.chip_select, &spi_conf.chip_select)?;
343 merge_field(&mut entry.alias_of, &spi_conf.alias_of)?;
344 Ok(())
345 }
346
347 fn record_i2c_conf(
348 i2c_conf_map: &mut HashMap<String, config::I2cConfiguration>,
349 i2c_conf: &config::I2cConfiguration,
350 ) -> Result<(), ()> {
351 let entry = i2c_conf_map
352 .entry(i2c_conf.name.to_string())
353 .or_insert_with(|| config::I2cConfiguration {
354 name: i2c_conf.name.clone(),
355 ..Default::default()
356 });
357 merge_field(&mut entry.address, &i2c_conf.address)?;
358 merge_field(&mut entry.bits_per_sec, &i2c_conf.bits_per_sec)?;
359 merge_field(&mut entry.alias_of, &i2c_conf.alias_of)?;
360 Ok(())
361 }
362
363 pub fn add_configuration_file(&mut self, file: config::ConfigurationFile) -> Result<()> {
364 if let Some(interface) = file.interface {
365 if self.interface.is_empty() {
366 self.interface = interface;
367 } else if self.interface == interface {
368 } else {
371 bail!(TransportError::InconsistentInterfaceConf(
372 self.interface.to_string(),
373 interface,
374 ))
375 }
376 }
377 for (key, value) in file.provides {
378 self.provides_list.push((key, value));
379 }
380 for (key, value) in file.requires {
381 self.requires_list.push((key, value));
382 }
383
384 if let Some(reset_delay) = file.reset_delay {
385 self.reset_delay = reset_delay;
386 }
387
388 for pin_conf in file.pins {
390 if let Some(alias_of) = &pin_conf.alias_of {
391 self.pin_alias_map
392 .insert(pin_conf.name.to_uppercase(), alias_of.clone());
393 } else if let Some(on_io_expander) = &pin_conf.on_io_expander {
394 ensure!(
395 &pin_conf.alias_of.is_none(),
396 TransportError::InconsistentConf(
397 TransportInterfaceType::Gpio,
398 pin_conf.name.to_string()
399 )
400 );
401 let uppercase_name = pin_conf.name.to_uppercase();
402 ensure!(
403 !self.pin_on_io_expander_map.contains_key(&uppercase_name),
404 TransportError::InconsistentConf(
405 TransportInterfaceType::Gpio,
406 pin_conf.name.to_string()
407 )
408 );
409 self.pin_on_io_expander_map
410 .insert(uppercase_name, on_io_expander.clone());
411 }
412 Self::record_pin_conf(&mut self.pin_conf_list, &pin_conf);
414 }
415 for strapping_conf in file.strappings {
416 let strapping_pin_map = self
417 .strapping_conf_map
418 .entry(strapping_conf.name.to_uppercase())
419 .or_default();
420 for pin_conf in strapping_conf.pins {
421 ensure!(
422 pin_conf.invert.is_none(),
423 TransportError::InvalidConfStrapInvert(
424 strapping_conf.name.to_string(),
425 pin_conf.name.to_string()
426 )
427 );
428 ensure!(
429 pin_conf.alias_of.is_none(),
430 TransportError::InvalidConfStrapAlias(
431 strapping_conf.name.to_string(),
432 pin_conf.name.to_string()
433 )
434 );
435 Self::record_pin_conf(strapping_pin_map, &pin_conf);
436 }
437 }
438 for spi_conf in file.spi {
439 Self::record_spi_conf(&mut self.spi_conf_map, &spi_conf).map_err(|_| {
440 TransportError::InconsistentConf(
441 TransportInterfaceType::Spi,
442 spi_conf.name.to_string(),
443 )
444 })?;
445 }
446 for i2c_conf in file.i2c {
447 Self::record_i2c_conf(&mut self.i2c_conf_map, &i2c_conf).map_err(|_| {
448 TransportError::InconsistentConf(
449 TransportInterfaceType::I2c,
450 i2c_conf.name.to_string(),
451 )
452 })?;
453 }
454 for uart_conf in file.uarts {
455 Self::record_uart_conf(&mut self.uart_conf_map, &uart_conf).map_err(|_| {
456 TransportError::InconsistentConf(
457 TransportInterfaceType::Uart,
458 uart_conf.name.to_string(),
459 )
460 })?;
461 }
462 for io_expander_conf in file.io_expanders {
463 match self
464 .io_expander_conf_map
465 .entry(io_expander_conf.name.to_string())
466 {
467 Entry::Vacant(v) => {
468 v.insert(io_expander_conf);
469 }
470 Entry::Occupied(_) => bail!(TransportError::InconsistentConf(
471 TransportInterfaceType::IoExpander,
472 io_expander_conf.name
473 )),
474 }
475 }
476 for pin in file.gpios {
477 self.gpio_conf.insert(pin);
478 }
479 Ok(())
480 }
481
482 fn consolidate_provides_map(
483 result_provides_map: &mut HashMap<String, String>,
484 provides_list: Vec<(String, String)>,
485 ) -> Result<()> {
486 for (key, value) in provides_list {
487 match result_provides_map.entry(key.clone()) {
488 Entry::Vacant(v) => {
489 v.insert(value);
490 }
491 Entry::Occupied(v) => {
492 if v.get() != &value {
493 bail!(TransportError::InconsistentConf(
494 TransportInterfaceType::Provides,
495 key
496 ))
497 }
498 }
499 }
500 }
501 Ok(())
502 }
503
504 fn verify_requires_list(
505 provides_map: &HashMap<String, String>,
506 requires_list: &Vec<(String, String)>,
507 ) -> Result<()> {
508 for (key, required_value) in requires_list {
509 match provides_map.get(key) {
510 Some(actual_value) if actual_value == required_value => (),
511 Some(actual_value) => bail!(TransportError::RequiresUnequal(
512 key.to_string(),
513 required_value.to_string(),
514 actual_value.to_string()
515 )),
516 None => bail!(TransportError::RequiresMissing(
517 key.to_string(),
518 required_value.to_string()
519 )),
520 }
521 }
522 Ok(())
523 }
524
525 fn consolidate_pin_conf_map(
526 pin_alias_map: &HashMap<String, String>,
527 pin_conf_list: &Vec<(String, PinConfiguration)>,
528 ) -> Result<HashMap<String, PinConfiguration>> {
529 let mut result_pin_conf_map: HashMap<String, PinConfiguration> = HashMap::new();
530 for (name, conf) in pin_conf_list {
531 result_pin_conf_map
532 .entry(map_name(pin_alias_map, name))
533 .or_default()
534 .merge(conf)
535 .map_err(|_| {
536 TransportError::InconsistentConf(TransportInterfaceType::Gpio, name.to_string())
537 })?;
538 }
539 Ok(result_pin_conf_map)
540 }
541
542 fn resolve_uart_conf(
543 name: &str,
544 uart_conf_map: &HashMap<String, config::UartConfiguration>,
545 ) -> Result<UartConfiguration> {
546 if let Some(entry) = uart_conf_map.get(name.to_uppercase().as_str()) {
547 let mut conf = if let Some(ref alias_of) = entry.alias_of {
548 Self::resolve_uart_conf(alias_of.as_str(), uart_conf_map)?
549 } else {
550 UartConfiguration {
551 underlying_instance: name.to_uppercase().to_string(),
552 ..Default::default()
553 }
554 };
555 if let Some(baud_rate) = entry.baudrate {
557 conf.baud_rate = Some(baud_rate);
558 }
559 if let Some(parity) = entry.parity {
560 conf.parity = Some(parity);
561 }
562 if let Some(stop_bits) = entry.stopbits {
563 conf.stop_bits = Some(stop_bits);
564 }
565 Ok(conf)
566 } else {
567 Ok(UartConfiguration {
568 underlying_instance: name.to_string(),
569 ..Default::default()
570 })
571 }
572 }
573
574 fn consolidate_uart_conf_map(
575 uart_conf_map: &HashMap<String, config::UartConfiguration>,
576 ) -> Result<HashMap<String, UartConfiguration>> {
577 let mut resolved_uart_conf_map = HashMap::new();
578 for name in uart_conf_map.keys() {
579 resolved_uart_conf_map
580 .insert(name.clone(), Self::resolve_uart_conf(name, uart_conf_map)?);
581 }
582 Ok(resolved_uart_conf_map)
583 }
584
585 fn resolve_spi_conf(
586 name: &str,
587 spi_conf_map: &HashMap<String, config::SpiConfiguration>,
588 pin_alias_map: &HashMap<String, String>,
589 ) -> SpiConfiguration {
590 if let Some(entry) = spi_conf_map.get(name) {
591 let mut conf = if let Some(ref alias_of) = entry.alias_of {
592 Self::resolve_spi_conf(alias_of.as_str(), spi_conf_map, pin_alias_map)
593 } else {
594 SpiConfiguration {
595 underlying_instance: name.to_string(),
596 ..Default::default()
597 }
598 };
599 if let Some(serial_clock) = entry.serial_clock.as_ref() {
601 conf.serial_clock = Some(map_name(pin_alias_map, serial_clock));
602 }
603 if let Some(host_out_device_in) = entry.host_out_device_in.as_ref() {
604 conf.host_out_device_in = Some(map_name(pin_alias_map, host_out_device_in));
605 }
606 if let Some(host_in_device_out) = entry.host_in_device_out.as_ref() {
607 conf.host_in_device_out = Some(map_name(pin_alias_map, host_in_device_out));
608 }
609 if let Some(chip_select) = entry.chip_select.as_ref() {
610 conf.chip_select = Some(map_name(pin_alias_map, chip_select));
611 }
612 if let Some(mode) = entry.mode {
613 conf.mode = Some(mode);
614 }
615 if let Some(bits_per_sec) = entry.bits_per_sec {
616 conf.bits_per_sec = Some(bits_per_sec);
617 }
618 if let Some(bits_per_word) = entry.bits_per_word {
619 conf.bits_per_word = Some(bits_per_word);
620 }
621 conf
622 } else {
623 SpiConfiguration {
624 underlying_instance: name.to_string(),
625 ..Default::default()
626 }
627 }
628 }
629
630 fn consolidate_spi_conf_map(
631 spi_conf_map: &HashMap<String, config::SpiConfiguration>,
632 pin_alias_map: &HashMap<String, String>,
633 ) -> Result<HashMap<String, SpiConfiguration>> {
634 let mut resolved_spi_conf_map = HashMap::new();
635 for name in spi_conf_map.keys() {
636 resolved_spi_conf_map.insert(
637 name.clone(),
638 Self::resolve_spi_conf(name, spi_conf_map, pin_alias_map),
639 );
640 }
641 Ok(resolved_spi_conf_map)
642 }
643
644 fn resolve_i2c_conf(
645 name: &str,
646 i2c_conf_map: &HashMap<String, config::I2cConfiguration>,
647 ) -> I2cConfiguration {
648 if let Some(entry) = i2c_conf_map.get(name) {
649 let mut conf = if let Some(ref alias_of) = entry.alias_of {
650 Self::resolve_i2c_conf(alias_of.as_str(), i2c_conf_map)
651 } else {
652 I2cConfiguration {
653 underlying_instance: name.to_string(),
654 ..Default::default()
655 }
656 };
657 if let Some(addr) = entry.address {
659 conf.default_addr = Some(addr);
660 }
661 if let Some(bits_per_sec) = entry.bits_per_sec {
662 conf.bits_per_sec = Some(bits_per_sec);
663 }
664 conf
665 } else {
666 I2cConfiguration {
667 underlying_instance: name.to_string(),
668 ..Default::default()
669 }
670 }
671 }
672
673 fn consolidate_i2c_conf_map(
674 i2c_conf_map: &HashMap<String, config::I2cConfiguration>,
675 ) -> Result<HashMap<String, I2cConfiguration>> {
676 let mut resolved_i2c_conf_map = HashMap::new();
677 for name in i2c_conf_map.keys() {
678 resolved_i2c_conf_map.insert(name.clone(), Self::resolve_i2c_conf(name, i2c_conf_map));
679 }
680 Ok(resolved_i2c_conf_map)
681 }
682
683 pub fn get_interface(&self) -> &str {
684 &self.interface
685 }
686
687 pub fn set_openocd_adapter_config(&mut self, openocd_adapter_config: &Option<PathBuf>) {
688 self.openocd_adapter_config = openocd_adapter_config.clone();
689 }
690
691 pub fn build(
692 self,
693 transport: Box<dyn crate::transport::Transport>,
694 ) -> Result<TransportWrapper> {
695 let mut provides_map = if transport
696 .capabilities()?
697 .request(Capability::PROXY)
698 .ok()
699 .is_ok()
700 {
701 transport.proxy_ops()?.provides_map()?
702 } else {
703 HashMap::new()
704 };
705 Self::consolidate_provides_map(&mut provides_map, self.provides_list)?;
706 Self::verify_requires_list(&provides_map, &self.requires_list)?;
707
708 let pin_conf_map =
709 Self::consolidate_pin_conf_map(&self.pin_alias_map, &self.pin_conf_list)?;
710 let mut strapping_conf_map: HashMap<String, HashMap<String, PinConfiguration>> =
711 HashMap::new();
712 for (strapping_name, pin_conf_map) in self.strapping_conf_map {
713 strapping_conf_map.insert(
714 strapping_name,
715 Self::consolidate_pin_conf_map(&self.pin_alias_map, &pin_conf_map)?,
716 );
717 }
718 let uart_conf_map = Self::consolidate_uart_conf_map(&self.uart_conf_map)?;
719 let spi_conf_map = Self::consolidate_spi_conf_map(&self.spi_conf_map, &self.pin_alias_map)?;
720 let i2c_conf_map = Self::consolidate_i2c_conf_map(&self.i2c_conf_map)?;
721 let mut transport_wrapper = TransportWrapper {
722 transport: Rc::from(transport),
723 disable_dft_on_reset: Cell::new(self.disable_dft_on_reset),
724 reset_delay: Cell::new(self.reset_delay),
725 openocd_adapter_config: self.openocd_adapter_config,
726 provides_map,
727 pin_map: self.pin_alias_map,
728 artificial_pin_map: HashMap::new(),
729 uart_conf_map,
730 pin_conf_map,
731 spi_conf_map,
732 i2c_conf_map,
733 strapping_conf_map,
734 gpio_conf: self.gpio_conf,
735 pin_instance_map: RefCell::new(HashMap::new()),
736 spi_physical_map: RefCell::new(HashMap::new()),
737 spi_logical_map: RefCell::new(HashMap::new()),
738 i2c_physical_map: RefCell::new(HashMap::new()),
739 i2c_logical_map: RefCell::new(HashMap::new()),
740 };
741 let mut io_expanders: HashMap<String, IoExpander> = HashMap::new();
742 for (name, conf) in self.io_expander_conf_map {
743 io_expanders.insert(
744 name.to_string(),
745 ioexpander::create(&conf, &transport_wrapper)?,
746 );
747 }
748 transport_wrapper
749 .artificial_pin_map
750 .insert("NULL".to_string(), Rc::new(NullPin::new()));
751 for (pinname, v) in self.pin_on_io_expander_map {
752 if let Some(io) = io_expanders.get(&v.io_expander) {
753 ensure!(
754 (v.pin_no as usize) < io.pins.len(),
755 TransportError::InvalidIoExpanderPinNo(v.io_expander.to_string(), v.pin_no)
756 );
757 transport_wrapper
758 .artificial_pin_map
759 .insert(pinname, io.pins[v.pin_no as usize].clone());
760 } else {
761 bail!(TransportError::InvalidIoExpanderName(
762 v.io_expander.to_string()
763 ));
764 }
765 }
766 Ok(transport_wrapper)
767 }
768}
769
770impl TransportWrapper {
771 pub fn ignore_dft_straps_on_reset(&self) -> Result<()> {
772 self.disable_dft_on_reset.set(false);
773 Ok(())
774 }
775
776 pub fn capabilities(&self) -> Result<crate::transport::Capabilities> {
779 let capabilities = self.transport.capabilities()?;
780 if self.openocd_adapter_config.is_some() {
781 Ok(capabilities.add(Capability::JTAG))
782 } else {
783 Ok(capabilities)
784 }
785 }
786
787 pub fn provides_map(&self) -> Result<&HashMap<String, String>> {
791 Ok(&self.provides_map)
792 }
793
794 pub fn query_provides(&self, key: &str) -> Result<&str> {
795 self.provides_map
796 .get(key)
797 .map(String::as_str)
798 .ok_or_else(|| {
799 TransportError::InvalidInstance(TransportInterfaceType::Provides, key.to_string())
800 .into()
801 })
802 }
803
804 pub fn jtag(&self, opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
806 if let Some(ref path) = self.openocd_adapter_config {
807 return Ok(Box::new(OpenOcdJtagChain::new(
809 &std::fs::read_to_string(path)?,
810 opts,
811 )?));
812 }
813 self.transport.jtag(opts)
816 }
817
818 pub fn spi(&self, name: &str) -> Result<Rc<dyn Target>> {
820 let name = name.to_uppercase();
821 let mut spi_logical_map = self.spi_logical_map.borrow_mut();
822 if let Some(instance) = spi_logical_map.get(&name) {
823 return Ok(instance.clone());
824 }
825 if let Some(spi_conf) = self.spi_conf_map.get(&name) {
826 let mut spi_physical_map = self.spi_physical_map.borrow_mut();
827 let physical_wrapper =
830 if let Some(instance) = spi_physical_map.get(&spi_conf.underlying_instance) {
831 instance.clone()
832 } else {
833 let instance = Rc::new(spi::PhysicalSpiWrapper::new(
834 self.transport.spi(spi_conf.underlying_instance.as_str())?,
835 ));
836 spi_physical_map.insert(spi_conf.underlying_instance.clone(), instance.clone());
837 instance
838 };
839
840 let new_wrapper = Rc::new(spi::LogicalSpiWrapper::new(
843 &*self.transport,
844 spi_conf,
845 physical_wrapper,
846 )?);
847 spi_logical_map.insert(name, new_wrapper.clone());
848 Ok(new_wrapper)
849 } else {
850 self.transport.spi(name.as_str())
851 }
852 }
853
854 pub fn i2c(&self, name: &str) -> Result<Rc<dyn Bus>> {
856 let name = name.to_uppercase();
857 let mut i2c_logical_map = self.i2c_logical_map.borrow_mut();
858 if let Some(instance) = i2c_logical_map.get(&name) {
859 return Ok(instance.clone());
860 }
861 if let Some(i2c_conf) = self.i2c_conf_map.get(&name) {
862 let mut i2c_physical_map = self.i2c_physical_map.borrow_mut();
863 let physical_wrapper =
866 if let Some(instance) = i2c_physical_map.get(&i2c_conf.underlying_instance) {
867 instance.clone()
868 } else {
869 let instance = Rc::new(i2c::PhysicalI2cWrapper::new(
870 self.transport.i2c(i2c_conf.underlying_instance.as_str())?,
871 ));
872 i2c_physical_map.insert(i2c_conf.underlying_instance.clone(), instance.clone());
873 instance
874 };
875
876 let new_wrapper = Rc::new(i2c::LogicalI2cWrapper::new(
879 &*self.transport,
880 i2c_conf,
881 physical_wrapper,
882 )?);
883 i2c_logical_map.insert(name, new_wrapper.clone());
884 Ok(new_wrapper)
885 } else {
886 self.transport.i2c(name.as_str())
887 }
888 }
889
890 pub fn uart(&self, name: &str) -> Result<Rc<dyn Uart>> {
892 let uart_conf = self.uart_conf_map.get(name.to_uppercase().as_str());
893 let uart_name = uart_conf
894 .map(|uart_conf| uart_conf.underlying_instance.as_str())
895 .unwrap_or(name);
896 let uart = self.transport.uart(uart_name)?;
897 if let Some(conf) = uart_conf {
898 if let Some(baud_rate) = conf.baud_rate {
902 if let Ok(current_baud_rate) = uart.get_baudrate() {
903 if current_baud_rate != baud_rate {
904 uart.set_baudrate(baud_rate)?;
905 }
906 } else {
907 log::warn!("Could not read UART baud rate to check it is {}", baud_rate);
908 }
909 }
910 if let Some(parity) = conf.parity {
911 let new_parity = match parity {
912 config::UartParity::None => Parity::None,
913 config::UartParity::Even => Parity::Even,
914 config::UartParity::Odd => Parity::Odd,
915 config::UartParity::Mark | config::UartParity::Space => {
916 log::warn!("Mark & Space parities not yet supported");
917 Parity::None
918 }
919 };
920 if let Ok(current_parity) = uart.get_parity() {
921 if current_parity != new_parity {
922 uart.set_parity(new_parity)?;
923 }
924 } else {
925 log::warn!("Could not read UART parity to check it is {}", new_parity);
926 }
927 }
928 }
930 Ok(uart)
931 }
932
933 pub fn usb(&self) -> Result<Rc<dyn UsbContext>> {
935 self.transport.usb()
936 }
937
938 pub fn gpio_pin(&self, name: &str) -> Result<Rc<dyn GpioPin>> {
940 let resolved_pin_name = map_name(&self.pin_map, name);
941 let mut pin_instance_map = self.pin_instance_map.borrow_mut();
942 if let Some(instance) = pin_instance_map.get(&resolved_pin_name) {
945 Ok(instance.clone())
946 } else {
947 let instance = if let Some(pin) = self.artificial_pin_map.get(&resolved_pin_name) {
948 pin.clone()
949 } else {
950 self.transport.gpio_pin(resolved_pin_name.as_str())?
951 };
952 let invert = self
953 .pin_conf_map
954 .get(&resolved_pin_name)
955 .and_then(|conf| conf.invert)
956 .unwrap_or(false);
957 let wrapper = Rc::new(gpio::GpioPinWrapper::new(instance, invert));
958 pin_instance_map.insert(resolved_pin_name, wrapper.clone());
959 Ok(wrapper)
960 }
961 }
962
963 pub fn gpio_pins(&self, names: &[String]) -> Result<Vec<Rc<dyn GpioPin>>> {
965 let mut result = Vec::new();
966 for name in names {
967 result.push(self.gpio_pin(name)?);
968 }
969 Ok(result)
970 }
971
972 pub fn gpios(&self) -> &HashSet<String> {
973 &self.gpio_conf
974 }
975
976 pub fn gpio_monitoring(&self) -> Result<Rc<dyn GpioMonitoring>> {
978 self.transport.gpio_monitoring()
979 }
980
981 pub fn gpio_bitbanging(&self) -> Result<Rc<dyn GpioBitbanging>> {
983 self.transport.gpio_bitbanging()
984 }
985
986 pub fn pin_strapping(&self, name: &str) -> Result<PinStrapping> {
987 let proxy = if self.capabilities()?.request(Capability::PROXY).ok().is_ok() {
988 Some(self.transport.clone())
989 } else {
990 None
991 };
992 let mut pins = Vec::new();
993 if let Some(strapping_conf_map) = self.strapping_conf_map.get(name) {
994 for (pin_name, conf) in strapping_conf_map {
995 pins.push(StrappedPin {
996 pin: self.gpio_pin(pin_name)?,
997 strapped: *conf,
998 original: self.pin_conf_map.get(pin_name).copied(),
999 });
1000 }
1001 } else if proxy.is_none() {
1002 bail!(TransportError::InvalidStrappingName(name.to_string()));
1003 }
1004 Ok(PinStrapping {
1005 proxy,
1006 name: name.to_string(),
1007 pins,
1008 })
1009 }
1010
1011 pub fn emulator(&self) -> Result<&dyn Emulator> {
1013 self.transport.emulator()
1014 }
1015
1016 pub fn fpga_ops(&self) -> Result<&dyn FpgaOps> {
1018 self.transport.fpga_ops()
1019 }
1020
1021 pub fn proxy_ops(&self) -> Result<&dyn ProxyOps> {
1023 self.transport.proxy_ops()
1024 }
1025
1026 pub fn dispatch(&self, action: &dyn Any) -> Result<Option<Box<dyn erased_serde::Serialize>>> {
1028 self.transport.dispatch(action)
1029 }
1030
1031 fn apply_pin_configuration(&self, name: &str, conf: &PinConfiguration) -> Result<()> {
1033 let pin = self.gpio_pin(name)?;
1034 pin.set(conf.mode, conf.level, conf.pull_mode, conf.volts)
1035 }
1036
1037 fn apply_pin_configurations(
1039 &self,
1040 conf_map: &HashMap<String, PinConfiguration>,
1041 overrides: Option<&HashMap<String, PinConfiguration>>,
1042 ) -> Result<()> {
1043 let update_pin = |name, conf: &PinConfiguration| {
1045 self.apply_pin_configuration(
1046 name,
1047 &conf.override_with(overrides.and_then(|o| o.get(name))),
1048 )
1049 };
1050 for (name, conf) in conf_map {
1057 if !self.artificial_pin_map.contains_key(name) {
1058 update_pin(name, conf)?;
1059 }
1060 }
1061 for (name, conf) in conf_map {
1062 if self.artificial_pin_map.contains_key(name) {
1063 update_pin(name, conf)?;
1064 }
1065 }
1066 Ok(())
1067 }
1068
1069 pub fn apply_default_configuration(&self, strapping_name: Option<&str>) -> Result<()> {
1072 if let Some(strapping_name) = strapping_name {
1073 if self.capabilities()?.request(Capability::PROXY).ok().is_ok() {
1074 self.proxy_ops()?
1075 .apply_default_configuration_with_strap(strapping_name)?;
1076 } else if let Some(strapping_conf_map) = self.strapping_conf_map.get(strapping_name) {
1077 self.transport.apply_default_configuration()?;
1079 self.apply_pin_configurations(&self.pin_conf_map, Some(strapping_conf_map))?;
1084 } else {
1085 bail!(TransportError::InvalidStrappingName(
1086 strapping_name.to_string(),
1087 ));
1088 }
1089 } else {
1090 self.transport.apply_default_configuration()?;
1091 self.apply_pin_configurations(&self.pin_conf_map, None)?;
1092 }
1093 self.pin_instance_map.borrow_mut().clear();
1096 self.spi_physical_map.borrow_mut().clear();
1097 self.spi_logical_map.borrow_mut().clear();
1098 self.i2c_physical_map.borrow_mut().clear();
1099 self.i2c_logical_map.borrow_mut().clear();
1100 Ok(())
1101 }
1102
1103 #[deprecated = "use [`reset`] or [`reset_with_delay`]"]
1104 pub fn reset_target(&self, reset_delay: Duration, clear_uart_rx: bool) -> Result<()> {
1105 let uart_rx = match clear_uart_rx {
1106 true => UartRx::Clear,
1107 false => UartRx::Keep,
1108 };
1109 self.reset_with_delay(uart_rx, reset_delay)
1110 }
1111
1112 pub fn reset(&self, uart_rx: UartRx) -> Result<()> {
1114 self.reset_with_delay(uart_rx, self.reset_delay.get())
1115 }
1116
1117 pub fn reset_with_delay(&self, uart_rx: UartRx, delay: Duration) -> Result<()> {
1119 log::info!("Asserting the reset signal");
1120
1121 if self.disable_dft_on_reset.get() {
1122 self.pin_strapping("PRERESET_DFT_DISABLE")?.apply()?;
1123 }
1124
1125 self.pin_strapping("RESET")?.apply()?;
1126 std::thread::sleep(delay);
1127
1128 if uart_rx == UartRx::Clear {
1129 log::info!("Clearing the UART RX buffer");
1130 self.uart("console")?.clear_rx_buffer()?;
1131 }
1132
1133 log::info!("Deasserting the reset signal");
1134 self.pin_strapping("RESET")?.remove()?;
1135
1136 if self.disable_dft_on_reset.get() {
1137 std::thread::sleep(Duration::from_millis(10));
1138 self.pin_strapping("PRERESET_DFT_DISABLE")?.remove()?;
1141 }
1142
1143 std::thread::sleep(delay);
1144
1145 Ok(())
1146 }
1147
1148 pub fn relinquish_exclusive_access<T>(&self, callback: impl FnOnce() -> T) -> Result<T> {
1157 let mut ret = None;
1158 self.transport.relinquish_exclusive_access(Box::new(|| {
1159 ret = Some(callback());
1160 }))?;
1161 Ok(ret.unwrap())
1162 }
1163}
1164
1165#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1166pub enum UartRx {
1167 Clear,
1168 Keep,
1169}
1170
1171fn map_name(map: &HashMap<String, String>, name: &str) -> String {
1174 let name = name.to_uppercase();
1175 match map.get(&name) {
1176 Some(v) => {
1177 if v.eq(&name) {
1178 name
1179 } else {
1180 map_name(map, v)
1181 }
1182 }
1183 None => name,
1184 }
1185}
1186
1187struct NullPin {
1192 has_warned: Cell<bool>,
1193}
1194
1195impl NullPin {
1196 fn new() -> Self {
1197 Self {
1198 has_warned: Cell::new(false),
1199 }
1200 }
1201
1202 fn warn(&self) {
1204 if !self.has_warned.get() {
1205 log::warn!("Accessed NULL pin");
1206 self.has_warned.set(true);
1207 }
1208 }
1209}
1210
1211impl GpioPin for NullPin {
1212 fn read(&self) -> Result<bool> {
1213 self.warn();
1214 Ok(false)
1215 }
1216
1217 fn write(&self, _value: bool) -> Result<()> {
1218 self.warn();
1219 Ok(())
1220 }
1221
1222 fn set_mode(&self, _mode: PinMode) -> Result<()> {
1223 self.warn();
1224 Ok(())
1225 }
1226
1227 fn set_pull_mode(&self, _mode: PullMode) -> Result<()> {
1228 self.warn();
1229 Ok(())
1230 }
1231}
1232
1233pub struct PinStrapping {
1236 name: String,
1237 proxy: Option<Rc<dyn Transport>>,
1238 pins: Vec<StrappedPin>,
1239}
1240
1241struct StrappedPin {
1242 pin: Rc<dyn GpioPin>,
1243 strapped: PinConfiguration,
1244 original: Option<PinConfiguration>,
1245}
1246
1247impl PinStrapping {
1248 pub fn apply(&self) -> Result<()> {
1251 if let Some(ref transport) = self.proxy {
1252 if let Err(e) = transport.proxy_ops()?.apply_pin_strapping(&self.name) {
1255 match e.downcast_ref::<TransportError>() {
1256 Some(TransportError::InvalidStrappingName(_)) => {
1257 if self.pins.is_empty() {
1258 return Err(e);
1259 }
1260 }
1261 _ => return Err(e),
1262 }
1263 }
1264 }
1265 for StrappedPin {
1266 pin,
1267 strapped: conf,
1268 original: _,
1269 } in &self.pins
1270 {
1271 pin.set(conf.mode, conf.level, conf.pull_mode, conf.volts)?
1272 }
1273 Ok(())
1274 }
1275
1276 pub fn remove(&self) -> Result<()> {
1280 if let Some(ref transport) = self.proxy {
1281 if let Err(e) = transport.proxy_ops()?.remove_pin_strapping(&self.name) {
1284 match e.downcast_ref::<TransportError>() {
1285 Some(TransportError::InvalidStrappingName(_)) => {
1286 if self.pins.is_empty() {
1287 return Err(e);
1288 }
1289 }
1290 _ => return Err(e),
1291 }
1292 }
1293 }
1294 for StrappedPin {
1295 pin,
1296 strapped: _,
1297 original,
1298 } in &self.pins
1299 {
1300 if let Some(conf) = original {
1301 pin.set(conf.mode, conf.level, conf.pull_mode, conf.volts)?
1302 }
1303 }
1304 Ok(())
1305 }
1306}