1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6
7use std::error::Error;
8use std::ffi::{CStr, CString};
9use std::fmt;
10use std::ptr;
11
12#[derive(Debug)]
16pub struct BlackMagicProbeError {
17 message: String,
18}
19
20pub const VENDOR_ID: u16 = VENDOR_ID_BMP as u16;
21pub const PRODUCT_IDS: [u16; 2] = [PRODUCT_ID_BMP_BL as u16, PRODUCT_ID_BMP as u16];
22
23impl fmt::Display for BlackMagicProbeError {
24 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25 write!(f, "{}", self.message)
26 }
27}
28
29impl Error for BlackMagicProbeError {}
30pub type Result<T> = std::result::Result<T, BlackMagicProbeError>;
32
33#[derive(Debug)]
34pub struct Probe {
35 serial: String,
37}
38
39const MAX_SPEED: u32 = 4_000_000;
40
41impl Probe {
42 pub fn open_by_serial(serial: &str) -> Result<Self> {
44 unsafe { bmda_probe_info.type_ = probe_type_PROBE_TYPE_BMP }
46 let input = CString::new(serial).expect("CString conversion failed");
47 let options = bmda_cli_options {
49 opt_target_dev: 1,
50 opt_flash_size: 0xffffffff,
51 opt_flash_start: 0xffffffff,
52 opt_max_swj_frequency: MAX_SPEED,
53 opt_scanmode: bmp_scan_mode_BMP_SCAN_SWD,
54 opt_mode: bmda_cli_mode_BMP_MODE_DEBUG,
55
56 opt_tpwr: false,
57 opt_list_only: false,
58 opt_connect_under_reset: false,
59 external_resistor_swd: false,
60 fast_poll: false,
61 opt_no_hl: false,
62 opt_flash_file: ptr::null_mut(),
63 opt_device: ptr::null_mut(),
64 opt_serial: ptr::null_mut(),
65 opt_targetid: 0,
66 opt_ident_string: ptr::null_mut(),
67 opt_position: 0,
68 opt_cable: ptr::null_mut(),
69 opt_monitor: ptr::null_mut(),
70 };
71 let result = unsafe { serial_open(&options, input.as_ptr()) };
72 if result == false {
73 return Err(BlackMagicProbeError {
74 message: "Could not open serial device".to_string(),
75 });
76 }
77 let bmp = Probe {
78 serial: serial.to_string(),
79 };
80
81 let result = unsafe { remote_init(true) };
82 if result == false {
83 return Err(BlackMagicProbeError {
84 message: "Could not initialize device".to_string(),
85 });
86 }
87
88 let ret: Result<Probe> = Ok(bmp);
89 return ret;
90 }
91
92 pub fn close() {
93 unsafe { serial_close() }
94 }
95
96 pub fn nrst_set(&self, assert: bool) -> Result<bool> {
99 unsafe { remote_nrst_set_val(assert) }
100 Ok(true)
101 }
102
103 pub fn nrst_get(&self) -> bool {
105 unsafe { remote_nrst_get_val() }
106 }
107
108 pub fn max_speed_get(&self) -> u32 {
110 unsafe { platform_max_frequency_get() }
111 }
112
113 pub fn max_speed_set(&self, speed: u32) {
115 unsafe { platform_max_frequency_set(speed) }
116 }
117
118 pub fn set_power(&self, enable: bool) -> Result<bool> {
119 if unsafe { platform_target_set_power(enable) } {
120 return Ok(enable);
121 }
122 Err(BlackMagicProbeError {
123 message: "Could not set target power".to_string(),
124 })
125 }
126
127 pub fn target_voltage(&self) -> Result<f32> {
129 let cstr = unsafe { platform_target_voltage() };
130 let c_str = unsafe { CStr::from_ptr(cstr) };
131
132 match c_str.to_str() {
134 Ok(rust_str) => {
135 let numeric_str: String = rust_str
138 .chars()
139 .filter(|c| c.is_digit(10) || *c == '.')
140 .collect();
141
142 if let Ok(float_value) = numeric_str.parse::<f32>() {
144 return Ok(float_value);
145 } else {
146 return Err(BlackMagicProbeError {
147 message: "Failed to parse the string as a float.".to_string(),
148 });
149 }
150 }
151 Err(_) => {
152 return Err(BlackMagicProbeError {
153 message: "Invalid UTF-8 data in C string".to_string(),
154 });
155 }
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 #[test]
164 fn test_remote_hex_string_to_num() {
165 use super::remote_hex_string_to_num;
166 use std::ffi::CString; let input = CString::new("").expect("CString conversion failed");
168 let result = unsafe { remote_hex_string_to_num(0, input.as_ptr()) };
169 assert_eq!(result, 0);
170 let input = CString::new("1").expect("CString conversion failed");
171 let result = unsafe { remote_hex_string_to_num(1, input.as_ptr()) };
172 assert_eq!(result, 1);
173 let input = CString::new("123456789ABCDEF").expect("CString conversion failed");
174 let result = unsafe { remote_hex_string_to_num(15, input.as_ptr()) };
175 assert_eq!(result, 0x123456789ABCDEF);
176 }
177
178 #[test]
179 #[ignore]
180 fn test_bmp_hil() {
185 use std::thread::sleep;
186 use std::time::Duration;
187 let duration = Duration::from_millis(10);
188 let serial = "98B72495";
189 let target_voltage: f32 = 1.8;
190
191 let bmp = super::Probe::open_by_serial(serial).unwrap();
193
194 sleep(duration);
196 assert_eq!(bmp.target_voltage().unwrap(), target_voltage);
197
198 let speed1 = bmp.max_speed_get();
200 assert!(speed1 > 0);
201 bmp.max_speed_set(speed1 / 2);
202 let speed2 = bmp.max_speed_get();
203 assert!(speed2 < speed1);
204
205 assert!(bmp.nrst_set(true).unwrap());
207 assert!(bmp.nrst_get());
208 assert!(bmp.nrst_set(false).unwrap());
209 assert!(!bmp.nrst_get());
210
211 }
219}
220