#![expect(unused)]
pub mod commands {
pub const GET_VERSION: u8 = 0xf1;
pub const JTAG_COMMAND: u8 = 0xf2;
pub const DFU_COMMAND: u8 = 0xf3;
pub const SWIM_COMMAND: u8 = 0xf4;
pub const GET_CURRENT_MODE: u8 = 0xf5;
pub const GET_TARGET_VOLTAGE: u8 = 0xf7;
pub const GET_VERSION_EXT: u8 = 0xfb;
pub const DFU_EXIT: u8 = 0x07;
pub const SWIM_EXIT: u8 = 0x01;
pub const JTAG_READMEM_32BIT: u8 = 0x07;
pub const JTAG_WRITEMEM_32BIT: u8 = 0x08;
pub const JTAG_READMEM_8BIT: u8 = 0x0c;
pub const JTAG_WRITEMEM_8BIT: u8 = 0x0d;
pub const JTAG_EXIT: u8 = 0x21;
pub const JTAG_ENTER: u8 = 0x20;
pub const JTAG_ENTER2: u8 = 0x30;
pub const JTAG_READ_CORE_REG: u8 = 0x33;
pub const JTAG_WRITE_CORE_REG: u8 = 0x34;
pub const JTAG_WRITE_DEBUG_REG: u8 = 0x35;
pub const JTAG_READ_DEBUG_REG: u8 = 0x36;
pub const JTAG_GETLASTRWSTATUS2: u8 = 0x3e; pub const JTAG_DRIVE_NRST: u8 = 0x3c;
pub const SWO_START_TRACE_RECEPTION: u8 = 0x40;
pub const SWO_STOP_TRACE_RECEPTION: u8 = 0x41;
pub const SWO_GET_TRACE_NEW_RECORD_NB: u8 = 0x42;
pub const SWD_SET_FREQ: u8 = 0x43; pub const JTAG_SET_FREQ: u8 = 0x44; pub const JTAG_READ_DAP_REG: u8 = 0x45; pub const JTAG_WRITE_DAP_REG: u8 = 0x46; pub const JTAG_READMEM_16BIT: u8 = 0x47; pub const JTAG_WRITEMEM_16BIT: u8 = 0x48; pub const JTAG_INIT_AP: u8 = 0x4b; pub const JTAG_CLOSE_AP_DBG: u8 = 0x4c; pub const SET_COM_FREQ: u8 = 0x61; pub const GET_COM_FREQ: u8 = 0x62;
pub const JTAG_ENTER_SWD: u8 = 0xa3;
pub const JTAG_ENTER_JTAG_NO_CORE_RESET: u8 = 0xa4;
pub const JTAG_DRIVE_NRST_LOW: u8 = 0x00;
pub const JTAG_DRIVE_NRST_HIGH: u8 = 0x01;
pub const JTAG_DRIVE_NRST_PULSE: u8 = 0x02;
pub const JTAG_AP_NO_CORE: u8 = 0x00;
pub const JTAG_AP_CORTEXM_CORE: u8 = 0x01;
pub const JTAG_STLINK_SWD_COM: u8 = 0x00;
pub const JTAG_STLINK_JTAG_COM: u8 = 0x01;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Status {
JtagOk,
JtagUnknownError,
JtagSpiError,
JtagDmaError,
JtagUnknownJtagChain,
JtagNoDeviceConnected,
JtagInternalError,
JtagCmdWait,
JtagCmdError,
JtagGetIdcodeError,
JtagAlignmentError,
JtagDbgPowerError,
JtagWriteError,
JtagWriteVerifError,
JtagAlreadyOpenedInOtherMode,
SwdApWait,
SwdApFault,
SwdApError,
SwdApParityError,
SwdDpWait,
SwdDpFault,
SwdDpError,
SwdDpParityError,
SwdApWdataError,
SwdApStickyError,
SwdApStickyorunError,
BadApError,
SwoNotAvailable,
JtagFreqNotSupported,
JtagUnknownCmd,
Other(u8),
}
impl From<u8> for Status {
fn from(value: u8) -> Status {
match value {
0x80 => Self::JtagOk,
0x01 => Self::JtagUnknownError,
0x02 => Self::JtagSpiError,
0x03 => Self::JtagDmaError,
0x04 => Self::JtagUnknownJtagChain,
0x05 => Self::JtagNoDeviceConnected,
0x06 => Self::JtagInternalError,
0x07 => Self::JtagCmdWait,
0x08 => Self::JtagCmdError,
0x09 => Self::JtagGetIdcodeError,
0x0A => Self::JtagAlignmentError,
0x0B => Self::JtagDbgPowerError,
0x0C => Self::JtagWriteError,
0x0D => Self::JtagWriteVerifError,
0x0E => Self::JtagAlreadyOpenedInOtherMode,
0x10 => Self::SwdApWait,
0x11 => Self::SwdApFault,
0x12 => Self::SwdApError,
0x13 => Self::SwdApParityError,
0x14 => Self::SwdDpWait,
0x15 => Self::SwdDpFault,
0x16 => Self::SwdDpError,
0x17 => Self::SwdDpParityError,
0x18 => Self::SwdApWdataError,
0x19 => Self::SwdApStickyError,
0x1A => Self::SwdApStickyorunError,
0x1D => Self::BadApError,
0x20 => Self::SwoNotAvailable,
0x41 => Self::JtagFreqNotSupported,
0x42 => Self::JtagUnknownCmd,
v => Self::Other(v),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SwdFrequencyToDelayCount {
Hz4600000 = 0,
Hz1800000 = 1, Hz1200000 = 2,
Hz950000 = 3,
Hz650000 = 5,
Hz480000 = 7,
Hz400000 = 9,
Hz360000 = 10,
Hz240000 = 15,
Hz150000 = 25,
Hz125000 = 31,
Hz100000 = 40,
}
impl SwdFrequencyToDelayCount {
pub(crate) fn find_setting(frequency: u32) -> Option<SwdFrequencyToDelayCount> {
Some(match frequency {
_ if frequency >= 4_600 => Self::Hz4600000,
_ if frequency >= 1_800 => Self::Hz1800000,
_ if frequency >= 1_200 => Self::Hz1200000,
_ if frequency >= 950 => Self::Hz950000,
_ if frequency >= 650 => Self::Hz650000,
_ if frequency >= 480 => Self::Hz480000,
_ if frequency >= 400 => Self::Hz400000,
_ if frequency >= 360 => Self::Hz360000,
_ if frequency >= 240 => Self::Hz240000,
_ if frequency >= 150 => Self::Hz150000,
_ if frequency >= 125 => Self::Hz125000,
_ if frequency >= 100 => Self::Hz100000,
_ => return None,
})
}
pub(crate) fn to_khz(self) -> u32 {
match self {
Self::Hz4600000 => 4600,
Self::Hz1800000 => 1800,
Self::Hz1200000 => 1200,
Self::Hz950000 => 950,
Self::Hz650000 => 650,
Self::Hz480000 => 480,
Self::Hz400000 => 400,
Self::Hz360000 => 360,
Self::Hz240000 => 240,
Self::Hz150000 => 150,
Self::Hz125000 => 125,
Self::Hz100000 => 100,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JTagFrequencyToDivider {
Hz18000000 = 2,
Hz9000000 = 4,
Hz4500000 = 8,
Hz2250000 = 16,
Hz1120000 = 32, Hz560000 = 64,
Hz280000 = 128,
Hz140000 = 256,
}
impl JTagFrequencyToDivider {
pub(crate) fn find_setting(frequency: u32) -> Option<Self> {
Some(match frequency {
_ if frequency >= 18_000 => Self::Hz18000000,
_ if frequency >= 9_000 => Self::Hz9000000,
_ if frequency >= 4_500 => Self::Hz4500000,
_ if frequency >= 2_225 => Self::Hz2250000,
_ if frequency >= 1_120 => Self::Hz1120000,
_ if frequency >= 560 => Self::Hz560000,
_ if frequency >= 280 => Self::Hz280000,
_ if frequency >= 140 => Self::Hz140000,
_ => return None,
})
}
pub(crate) fn to_khz(self) -> u32 {
match self {
Self::Hz18000000 => 18_000,
Self::Hz9000000 => 9_000,
Self::Hz4500000 => 4_500,
Self::Hz2250000 => 2_250,
Self::Hz1120000 => 1_120,
Self::Hz560000 => 560,
Self::Hz280000 => 280,
Self::Hz140000 => 140,
}
}
}
#[derive(Debug)]
pub(crate) enum Mode {
Dfu = 0x00,
MassStorage = 0x01,
Jtag = 0x02,
Swim = 0x03,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_too_low_swd_speed() {
assert!(SwdFrequencyToDelayCount::find_setting(0).is_none());
assert!(SwdFrequencyToDelayCount::find_setting(1).is_none());
assert!(SwdFrequencyToDelayCount::find_setting(99).is_none());
}
#[test]
fn test_swd_speed() {
assert_eq!(
SwdFrequencyToDelayCount::find_setting(100).unwrap(),
SwdFrequencyToDelayCount::Hz100000
);
assert_eq!(
SwdFrequencyToDelayCount::find_setting(124).unwrap(),
SwdFrequencyToDelayCount::Hz100000
);
assert_eq!(
SwdFrequencyToDelayCount::find_setting(125).unwrap(),
SwdFrequencyToDelayCount::Hz125000
);
assert_eq!(
SwdFrequencyToDelayCount::find_setting(46_000).unwrap(),
SwdFrequencyToDelayCount::Hz4600000
);
assert_eq!(
SwdFrequencyToDelayCount::find_setting(u32::MAX).unwrap(),
SwdFrequencyToDelayCount::Hz4600000
);
}
#[test]
fn test_too_low_jtag_speed() {
assert!(JTagFrequencyToDivider::find_setting(0).is_none());
assert!(JTagFrequencyToDivider::find_setting(1).is_none());
assert!(JTagFrequencyToDivider::find_setting(139).is_none());
}
#[test]
fn test_jtag_speed() {
assert_eq!(
JTagFrequencyToDivider::find_setting(140).unwrap(),
JTagFrequencyToDivider::Hz140000
);
assert_eq!(
JTagFrequencyToDivider::find_setting(279).unwrap(),
JTagFrequencyToDivider::Hz140000
);
assert_eq!(
JTagFrequencyToDivider::find_setting(280).unwrap(),
JTagFrequencyToDivider::Hz280000
);
assert_eq!(
JTagFrequencyToDivider::find_setting(18_000).unwrap(),
JTagFrequencyToDivider::Hz18000000
);
assert_eq!(
JTagFrequencyToDivider::find_setting(u32::MAX).unwrap(),
JTagFrequencyToDivider::Hz18000000
);
}
}