use crate::architecture::arm::communication_interface::ArmProbeInterface;
use super::ArmError;
#[derive(Debug, Copy, Clone)]
pub enum SwoMode {
Uart,
Manchester,
}
#[derive(Debug, Copy, Clone)]
pub struct SwoConfig {
mode: SwoMode,
baud: u32,
tpiu_clk: u32,
tpiu_continuous_formatting: bool,
}
impl SwoConfig {
pub fn new(tpiu_clk: u32) -> Self {
SwoConfig {
mode: SwoMode::Uart,
baud: 1_000_000,
tpiu_clk,
tpiu_continuous_formatting: false,
}
}
pub fn set_baud(mut self, baud: u32) -> Self {
self.baud = baud;
self
}
pub fn set_mode(mut self, mode: SwoMode) -> Self {
self.mode = mode;
self
}
pub fn set_mode_uart(mut self) -> Self {
self.mode = SwoMode::Uart;
self
}
pub fn set_mode_manchester(mut self) -> Self {
self.mode = SwoMode::Manchester;
self
}
pub fn set_continuous_formatting(mut self, enabled: bool) -> Self {
self.tpiu_continuous_formatting = enabled;
self
}
pub fn mode(&self) -> SwoMode {
self.mode
}
pub fn baud(&self) -> u32 {
self.baud
}
pub fn tpiu_clk(&self) -> u32 {
self.tpiu_clk
}
pub fn tpiu_continuous_formatting(&self) -> bool {
self.tpiu_continuous_formatting
}
}
pub trait SwoAccess {
fn enable_swo(&mut self, config: &SwoConfig) -> Result<(), ArmError>;
fn disable_swo(&mut self) -> Result<(), ArmError>;
fn read_swo(&mut self) -> Result<Vec<u8>, ArmError> {
self.read_swo_timeout(std::time::Duration::from_millis(10))
}
fn read_swo_timeout(&mut self, timeout: std::time::Duration) -> Result<Vec<u8>, ArmError>;
fn swo_poll_interval_hint(&mut self, config: &SwoConfig) -> Option<std::time::Duration> {
match self.swo_buffer_size() {
Some(size) => poll_interval_from_buf_size(config, size),
None => None,
}
}
fn swo_buffer_size(&mut self) -> Option<usize> {
None
}
}
pub(crate) fn poll_interval_from_buf_size(
config: &SwoConfig,
buf_size: usize,
) -> Option<std::time::Duration> {
let time_to_full_ms = match config.mode() {
SwoMode::Uart => (1000 * buf_size as u32) / (config.baud() / 10),
SwoMode::Manchester => (500 * buf_size as u32) / (config.baud() / 8),
};
Some(std::time::Duration::from_millis(time_to_full_ms as u64 / 4))
}
pub struct SwoReader<'a> {
interface: &'a mut dyn ArmProbeInterface,
buf: Vec<u8>,
}
impl<'a> SwoReader<'a> {
pub(crate) fn new(interface: &'a mut dyn ArmProbeInterface) -> Self {
Self {
interface,
buf: Vec::new(),
}
}
}
impl<'a> std::io::Read for SwoReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
use core::cmp;
use std::{
io::{Error, ErrorKind},
mem,
};
self.buf.append(
&mut self
.interface
.read_swo()
.map_err(|e| Error::new(ErrorKind::Other, e))?,
);
let swo = {
let next_buf = self.buf.split_off(cmp::min(self.buf.len(), buf.len()));
mem::replace(&mut self.buf, next_buf)
};
buf[..swo.len()].copy_from_slice(&swo);
Ok(swo.len())
}
}