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