#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
use std::error::Error;
use std::ffi::{CStr, CString};
use std::fmt;
use std::ptr;
#[derive(Debug)]
pub struct BlackMagicProbeError {
message: String,
}
pub const VENDOR_ID: u16 = VENDOR_ID_BMP as u16;
pub const PRODUCT_IDS: [u16; 2] = [PRODUCT_ID_BMP_BL as u16, PRODUCT_ID_BMP as u16];
impl fmt::Display for BlackMagicProbeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl Error for BlackMagicProbeError {}
pub type Result<T> = std::result::Result<T, BlackMagicProbeError>;
#[derive(Debug)]
pub struct Probe {
serial: String,
}
const MAX_SPEED: u32 = 4_000_000;
impl Probe {
pub fn open_by_serial(serial: &str) -> Result<Self> {
unsafe { bmda_probe_info.type_ = probe_type_PROBE_TYPE_BMP }
let input = CString::new(serial).expect("CString conversion failed");
let options = bmda_cli_options {
opt_target_dev: 1,
opt_flash_size: 0xffffffff,
opt_flash_start: 0xffffffff,
opt_max_swj_frequency: MAX_SPEED,
opt_scanmode: bmp_scan_mode_BMP_SCAN_SWD,
opt_mode: bmda_cli_mode_BMP_MODE_DEBUG,
opt_tpwr: false,
opt_list_only: false,
opt_connect_under_reset: false,
external_resistor_swd: false,
fast_poll: false,
opt_no_hl: false,
opt_flash_file: ptr::null_mut(),
opt_device: ptr::null_mut(),
opt_serial: ptr::null_mut(),
opt_targetid: 0,
opt_ident_string: ptr::null_mut(),
opt_position: 0,
opt_cable: ptr::null_mut(),
opt_monitor: ptr::null_mut(),
};
let result = unsafe { serial_open(&options, input.as_ptr()) };
if result == false {
return Err(BlackMagicProbeError {
message: "Could not open serial device".to_string(),
});
}
let bmp = Probe {
serial: serial.to_string(),
};
let result = unsafe { remote_init(true) };
if result == false {
return Err(BlackMagicProbeError {
message: "Could not initialize device".to_string(),
});
}
let ret: Result<Probe> = Ok(bmp);
return ret;
}
pub fn close() {
unsafe { serial_close() }
}
pub fn nrst_set(&self, assert: bool) -> Result<bool> {
unsafe { remote_nrst_set_val(assert) }
Ok(true)
}
pub fn nrst_get(&self) -> bool {
unsafe { remote_nrst_get_val() }
}
pub fn max_speed_get(&self) -> u32 {
unsafe { platform_max_frequency_get() }
}
pub fn max_speed_set(&self, speed: u32) {
unsafe { platform_max_frequency_set(speed) }
}
pub fn set_power(&self, enable: bool) -> Result<bool> {
if unsafe { platform_target_set_power(enable) } {
return Ok(enable);
}
Err(BlackMagicProbeError {
message: "Could not set target power".to_string(),
})
}
pub fn target_voltage(&self) -> Result<f32> {
let cstr = unsafe { platform_target_voltage() };
let c_str = unsafe { CStr::from_ptr(cstr) };
match c_str.to_str() {
Ok(rust_str) => {
let numeric_str: String = rust_str
.chars()
.filter(|c| c.is_digit(10) || *c == '.')
.collect();
if let Ok(float_value) = numeric_str.parse::<f32>() {
return Ok(float_value);
} else {
return Err(BlackMagicProbeError {
message: "Failed to parse the string as a float.".to_string(),
});
}
}
Err(_) => {
return Err(BlackMagicProbeError {
message: "Invalid UTF-8 data in C string".to_string(),
});
}
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_remote_hex_string_to_num() {
use super::remote_hex_string_to_num;
use std::ffi::CString; let input = CString::new("").expect("CString conversion failed");
let result = unsafe { remote_hex_string_to_num(0, input.as_ptr()) };
assert_eq!(result, 0);
let input = CString::new("1").expect("CString conversion failed");
let result = unsafe { remote_hex_string_to_num(1, input.as_ptr()) };
assert_eq!(result, 1);
let input = CString::new("123456789ABCDEF").expect("CString conversion failed");
let result = unsafe { remote_hex_string_to_num(15, input.as_ptr()) };
assert_eq!(result, 0x123456789ABCDEF);
}
#[test]
#[ignore]
fn test_bmp_hil() {
use std::thread::sleep;
use std::time::Duration;
let duration = Duration::from_millis(10);
let serial = "98B72495";
let target_voltage: f32 = 1.8;
let bmp = super::Probe::open_by_serial(serial).unwrap();
sleep(duration);
assert_eq!(bmp.target_voltage().unwrap(), target_voltage);
let speed1 = bmp.max_speed_get();
assert!(speed1 > 0);
bmp.max_speed_set(speed1 / 2);
let speed2 = bmp.max_speed_get();
assert!(speed2 < speed1);
assert!(bmp.nrst_set(true).unwrap());
assert!(bmp.nrst_get());
assert!(bmp.nrst_set(false).unwrap());
assert!(!bmp.nrst_get());
}
}