Skip to content

Upstream bitbang-dap #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 86 additions & 93 deletions src/dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod request;
mod response;
mod state;

use bitflags::bitflags;
pub use command::*;
pub use request::*;
pub use response::*;
Expand All @@ -35,13 +36,26 @@ pub struct TransferConfig {
pub match_mask: u32,
}

bitflags! {
struct Capabilities: u8 {
const SWD = 0x01;
const JTAG = 0x02;
const SWO_UART = 0x04;
const SWO_MANCHESTER = 0x08;
const ATOMIC_COMMANDS = 0x10;
const TEST_DOMAIN_TIMER = 0x20;
const SWO_STREAMING = 0x40;
}
}

/// DAP handler.
pub struct Dap<'a, DEPS, LEDS, WAIT, JTAG, SWD, SWO> {
state: State<DEPS, SWD, JTAG>,
swo: Option<SWO>,
swo: SWO,
swo_streaming: bool,
version_string: &'a str,
transfer_config: TransferConfig,
capabilities: Capabilities,
// mode: Option<DapMode>,
leds: LEDS,
wait: WAIT,
Expand All @@ -61,11 +75,38 @@ where
dependencies: DEPS,
leds: LEDS,
wait: WAIT,
swo: Option<SWO>,
swo: SWO,
version_string: &'a str,
) -> Self {
// TODO: Replace with const assert
assert!(SWD::AVAILABLE || JTAG::AVAILABLE);
assert!(SWD::available(&dependencies) || JTAG::available(&dependencies));

let capabilities = {
let mut caps = Capabilities::empty();

// Bit 0: SWD optional
if SWD::available(&dependencies) {
caps.insert(Capabilities::SWD);
}
// Bit 1: JTAG optional
if JTAG::available(&dependencies) {
caps.insert(Capabilities::JTAG);
}
// Bit 2: SWO UART optional
// Bit 3: SWO Manchester optional
if swo.support().uart {
caps.insert(Capabilities::SWO_UART);
}
if swo.support().manchester {
caps.insert(Capabilities::SWO_MANCHESTER);
}
// Bit 4: Atomic commands not supported
// Bit 5: Test Domain Timer not supported
// Bit 6: SWO Streaming Trace optional
if swo.support().streaming {
caps.insert(Capabilities::SWO_STREAMING);
}
caps
};

Dap {
state: State::new(dependencies),
Expand All @@ -81,6 +122,7 @@ where
// mode: None,
leds,
wait,
capabilities,
}
}

Expand Down Expand Up @@ -152,7 +194,7 @@ where
}
}

fn process_info(&mut self, mut req: Request, resp: &mut ResponseWriter, version: DapVersion) {
fn process_info(&self, mut req: Request, resp: &mut ResponseWriter, version: DapVersion) {
match DapInfoID::try_from(req.next_u8()) {
// Return 0-length string for VendorID, ProductID, SerialNumber
// to indicate they should be read from USB descriptor instead
Expand All @@ -170,33 +212,11 @@ where
Ok(DapInfoID::TargetName) => resp.write_u8(0),
Ok(DapInfoID::Capabilities) => {
resp.write_u8(1);
// Bit 0: SWD supported
// Bit 1: JTAG supported
// Bit 2: SWO UART supported
// Bit 3: SWO Manchester not supported
// Bit 4: Atomic commands not supported
// Bit 5: Test Domain Timer not supported
// Bit 6: SWO Streaming Trace supported
let swd = (SWD::AVAILABLE as u8) << 0;
let jtag = (JTAG::AVAILABLE as u8) << 1;
let swo = match &self.swo {
Some(swo) => {
let support = swo.support();
(support.uart as u8) << 2 | (support.manchester as u8) << 3
}
None => 0,
};
let atomic = 0 << 4;
let swo_streaming = 1 << 6;
resp.write_u8(swd | jtag | swo | atomic | swo_streaming);
resp.write_u8(self.capabilities.bits);
}
Ok(DapInfoID::SWOTraceBufferSize) => {
resp.write_u8(4);
let size = match &self.swo {
Some(swo) => swo.buffer_size(),
None => 0,
};
resp.write_u32(size as u32);
resp.write_u32(self.swo.buffer_size());
}
Ok(DapInfoID::MaxPacketCount) => {
resp.write_u8(1);
Expand Down Expand Up @@ -249,11 +269,15 @@ where
info!(
"DAP connect: {}, SWD: {}, JTAG: {}",
port,
SWD::AVAILABLE,
JTAG::AVAILABLE
self.capabilities.contains(Capabilities::SWD),
self.capabilities.contains(Capabilities::JTAG),
);

match (SWD::AVAILABLE, JTAG::AVAILABLE, port) {
match (
self.capabilities.contains(Capabilities::SWD),
self.capabilities.contains(Capabilities::JTAG),
port,
) {
// SWD
(true, true, ConnectPort::Default)
| (true, true, ConnectPort::SWD)
Expand Down Expand Up @@ -298,8 +322,8 @@ where

let idx = req.next_u8();
let word = req.next_u32();
match (SWD::AVAILABLE, JTAG::AVAILABLE, &mut self.state) {
(_, true, State::Jtag(jtag)) => {
match &mut self.state {
State::Jtag(jtag) => {
let config = jtag.config();
if !config.select_index(idx) {
resp.write_err();
Expand All @@ -311,16 +335,14 @@ where

resp.write_ok();
}
(true, _, State::Swd(swd)) => {
State::Swd(swd) => {
let wait_retries = self.transfer_config.wait_retries;
match swd.write_dp(wait_retries, swd::DPRegister::DPIDR, word) {
Ok(_) => resp.write_ok(),
Err(_) => resp.write_err(),
}
}
_ => {
resp.write_err();
}
_ => resp.write_err(),
}
}

Expand Down Expand Up @@ -470,48 +492,34 @@ where
}

fn process_swo_mode(&mut self, mut req: Request, resp: &mut ResponseWriter) {
let mode = req.next_u8();
let success = match swo::SwoMode::try_from(req.next_u8()) {
Ok(mode) => self.swo.set_mode(mode),
_ => false,
};

let swo = if let Some(swo) = &mut self.swo {
swo
if success {
resp.write_ok();
} else {
resp.write_err();
return;
};

match swo::SwoMode::try_from(mode) {
Ok(mode) => {
swo.set_mode(mode);
resp.write_ok();
}
_ => resp.write_err(),
}
}

fn process_swo_baudrate(&mut self, mut req: Request, resp: &mut ResponseWriter) {
let target = req.next_u32();
let actual = if let Some(swo) = &mut self.swo {
swo.set_baudrate(target)
} else {
0
};
let actual = self.swo.set_baudrate(target);
resp.write_u32(actual);
}

fn process_swo_control(&mut self, mut req: Request, resp: &mut ResponseWriter) {
let swo = if let Some(swo) = &mut self.swo {
swo
} else {
resp.write_err();
return;
let success = match swo::SwoControl::try_from(req.next_u8()) {
Ok(control) => self.swo.set_control(control),
_ => false,
};

match swo::SwoControl::try_from(req.next_u8()) {
Ok(control) => {
swo.set_control(control);
resp.write_ok();
}
_ => resp.write_err(),
if success {
resp.write_ok();
} else {
resp.write_err();
}
}

Expand All @@ -520,11 +528,7 @@ where
// Bit 0: trace capture active
// Bit 6: trace stream error (always written as 0)
// Bit 7: trace buffer overflow (always written as 0)
let (active, len) = if let Some(swo) = &self.swo {
(swo.is_active(), swo.bytes_available())
} else {
(false, 0)
};
let (active, len) = (self.swo.is_active(), self.swo.bytes_available());

resp.write_u8(active as u8);
// Trace count: remaining bytes in buffer
Expand All @@ -536,11 +540,8 @@ where
// Bit 0: trace capture active
// Bit 6: trace stream error (always written as 0)
// Bit 7: trace buffer overflow (always written as 0)
let (active, len) = if let Some(swo) = &self.swo {
(swo.is_active(), swo.bytes_available())
} else {
(false, 0)
};
let (active, len) = (self.swo.is_active(), self.swo.bytes_available());

resp.write_u8(active as u8);
// Trace count: remaining bytes in buffer.
resp.write_u32(len);
Expand All @@ -551,11 +552,7 @@ where
}

fn process_swo_data(&mut self, mut req: Request, resp: &mut ResponseWriter) {
let active = if let Some(swo) = &mut self.swo {
swo.is_active()
} else {
false
};
let active = self.swo.is_active();

// Write status byte to response
resp.write_u8(active as u8);
Expand All @@ -572,11 +569,7 @@ where
}

// Read data from UART
let len = if let Some(swo) = &mut self.swo {
swo.polling_data(&mut buf)
} else {
0
};
let len = self.swo.polling_data(&mut buf);
resp.skip(len as _);

// Go back and write length
Expand Down Expand Up @@ -1261,7 +1254,7 @@ fn transfer_with_retry<DEPS>(
#[cfg(test)]
mod test {
use super::*;
use crate::mock_device::*;
use crate::{mock_device::*, swo::NoSwo};
use mockall::predicate::*;

struct FakeLEDs {}
Expand All @@ -1283,7 +1276,7 @@ mod test {
StdDelayUs,
MockSwdJtagDevice,
MockSwdJtagDevice,
swo::MockSwo,
NoSwo,
>;

#[test]
Expand All @@ -1292,7 +1285,7 @@ mod test {
MockSwdJtagDevice::new(),
FakeLEDs {},
StdDelayUs {},
None,
NoSwo,
"test_dap",
);

Expand All @@ -1319,7 +1312,7 @@ mod test {
MockSwdJtagDevice::new(),
FakeLEDs {},
StdDelayUs {},
None,
NoSwo,
"test_dap",
);

Expand Down Expand Up @@ -1349,7 +1342,7 @@ mod test {
MockSwdJtagDevice::new(),
FakeLEDs {},
StdDelayUs {},
None,
NoSwo,
"test_dap",
);

Expand Down Expand Up @@ -1382,7 +1375,7 @@ mod test {
MockSwdJtagDevice::new(),
FakeLEDs {},
StdDelayUs {},
None,
NoSwo,
"test_dap",
);

Expand Down Expand Up @@ -1416,7 +1409,7 @@ mod test {
MockSwdJtagDevice::new(),
FakeLEDs {},
StdDelayUs {},
None,
NoSwo,
"test_dap",
);

Expand Down
Loading