1use std::ops::RangeInclusive;
2use std::thread;
3use std::time;
4
5use crate::command::{self, Command};
6use crate::target::{OperatingMode, Target};
7use crate::{Error, ErrorKind, Result};
8
9#[derive(Debug)]
11pub enum ConnectError {
12 NoResponse,
14 BadResponse,
16 Failed,
18}
19
20pub struct Programmer {
22 target: Box<dyn Target>,
23}
24
25impl Programmer {
26 pub fn new(target: Box<dyn Target>) -> Programmer {
28 Programmer { target }
29 }
30
31 pub fn connect(mut self) -> Result<ProgrammerConnected> {
33 self.target.reset_into(OperatingMode::Boot);
34
35 self.target.clear_buffers()?;
36
37 for baud_rate in &[9600, 4800, 2400, 1200, 0] {
38 if *baud_rate == 0 {
39 return Err(Error::new(ErrorKind::Connect, "no response from target"));
40 }
41
42 self.target.set_baud_rate(*baud_rate)?;
43
44 let mut attempts = 0;
45 while self.target.bytes_to_read()? < 1 && attempts < 30 {
46 self.target.write(&[0x00])?;
47 thread::sleep(time::Duration::from_millis(10));
48
49 attempts += 1;
50 }
51
52 if self.target.bytes_to_read()? >= 1 {
53 break;
54 }
55 }
56
57 let mut response1 = [0u8; 1];
58 self.target.read_exact(&mut response1)?;
59 let response1 = response1[0];
60
61 if response1 != 0x00 {
62 return Err(Error::new(ErrorKind::Connect, "bad response from target"));
63 }
64
65 self.target.write(&[0x55])?;
66
67 let mut response2 = [0u8; 1];
68 self.target.read_exact(&mut response2)?;
69 let response2 = response2[0];
70
71 match response2 {
72 0xE6 => Ok(ProgrammerConnected {
73 target: self.target,
74 }),
75 0xFF => Err(Error::new(ErrorKind::Connect, "failed to connect")),
76 _ => Err(Error::new(ErrorKind::Connect, "bad response from target")),
77 }
78 }
79}
80
81pub struct ProgrammerConnected {
83 target: Box<dyn Target>,
84}
85
86impl ProgrammerConnected {
87 pub fn supported_devices(&mut self) -> Result<Vec<command::data::SupportedDevice>> {
89 let cmd = command::commands::SupportedDeviceInquiry {};
90 cmd.execute(&mut self.target)
91 }
92
93 pub fn select_device(
95 mut self,
96 device_code: &String,
97 ) -> Result<ProgrammerConnectedDeviceSelected> {
98 let cmd = command::commands::DeviceSelection {
99 device_code: device_code.clone(),
100 };
101 cmd.execute(&mut self.target)?;
102
103 Ok(ProgrammerConnectedDeviceSelected {
104 target: self.target,
105 })
106 }
107}
108
109pub struct ProgrammerConnectedDeviceSelected {
111 target: Box<dyn Target>,
112}
113
114impl ProgrammerConnectedDeviceSelected {
115 pub fn clock_modes(&mut self) -> Result<Vec<u8>> {
117 let cmd = command::commands::ClockModeInquiry {};
118 cmd.execute(&mut self.target)
119 }
120
121 pub fn select_clock_mode(
123 mut self,
124 clock_mode: u8,
125 ) -> Result<ProgrammerConnectedClockModeSelected> {
126 let cmd = command::commands::ClockModeSelection { mode: clock_mode };
127 cmd.execute(&mut self.target)?;
128
129 Ok(ProgrammerConnectedClockModeSelected {
130 target: self.target,
131 })
132 }
133}
134
135pub struct ProgrammerConnectedClockModeSelected {
137 target: Box<dyn Target>,
138}
139
140impl ProgrammerConnectedClockModeSelected {
141 pub fn multiplication_ratios(
143 &mut self,
144 ) -> Result<Vec<Vec<command::data::MultiplicationRatio>>> {
145 let cmd = command::commands::MultiplicationRatioInquiry {};
146 cmd.execute(&mut self.target)
147 }
148
149 pub fn operating_frequencies(&mut self) -> Result<Vec<RangeInclusive<u16>>> {
151 let cmd = command::commands::OperatingFrequencyInquiry {};
152 cmd.execute(&mut self.target)
153 }
154
155 pub fn set_new_bit_rate(
157 mut self,
158 bit_rate: u16,
159 input_frequency: u16,
160 multiplication_ratios: Vec<command::data::MultiplicationRatio>,
161 ) -> Result<ProgrammerConnectedNewBitRateSelected> {
162 let cmd = command::commands::NewBitRateSelection {
163 bit_rate: bit_rate,
164 input_frequency: input_frequency,
165 multiplication_ratios: multiplication_ratios,
166 };
167 cmd.execute(&mut self.target)?;
168
169 let baud_rate: u32 = (bit_rate as u32) * 100;
170 self.target.set_baud_rate(baud_rate)?;
171
172 let cmd = command::commands::NewBitRateSelectionConfirmation {};
173 cmd.execute(&mut self.target)?;
174
175 Ok(ProgrammerConnectedNewBitRateSelected {
176 target: self.target,
177 })
178 }
179}
180
181pub struct ProgrammerConnectedNewBitRateSelected {
183 target: Box<dyn Target>,
184}
185
186impl ProgrammerConnectedNewBitRateSelected {
187 pub fn user_boot_area(&mut self) -> Result<Vec<RangeInclusive<u32>>> {
189 let cmd = command::commands::UserBootAreaInformationInquiry {};
190 cmd.execute(&mut self.target)
191 }
192
193 pub fn user_area(&mut self) -> Result<Vec<RangeInclusive<u32>>> {
195 let cmd = command::commands::UserAreaInformationInquiry {};
196 cmd.execute(&mut self.target)
197 }
198
199 pub fn erasure_block(&mut self) -> Result<Vec<RangeInclusive<u32>>> {
201 let cmd = command::commands::ErasureBlockInformationInquiry {};
202 cmd.execute(&mut self.target)
203 }
204
205 pub fn programming_erasure_state_transition(
207 mut self,
208 ) -> Result<ProgrammerConnectedProgrammingErasureState> {
209 let cmd = command::commands::ProgrammingErasureStateTransition {};
210 let response = cmd.execute(&mut self.target)?;
211
212 match response {
213 command::commands::IDCodeProtectionStatus::Disabled => {
214 Ok(ProgrammerConnectedProgrammingErasureState {
215 target: self.target,
216 })
217 }
218 command::commands::IDCodeProtectionStatus::Enabled => {
219 panic!("Support for ID codes not implemented")
220 }
221 }
222 }
223}
224
225pub struct ProgrammerConnectedProgrammingErasureState {
227 target: Box<dyn Target>,
228}
229
230impl ProgrammerConnectedProgrammingErasureState {
231 pub fn program_user_or_data_area(mut self) -> Result<ProgrammerConnectedWaitingForData> {
233 let cmd = command::commands::UserDataAreaProgrammingSelection {};
234 cmd.execute(&mut self.target)?;
235
236 Ok(ProgrammerConnectedWaitingForData {
237 target: self.target,
238 })
239 }
240
241 pub fn read_memory(
243 &mut self,
244 area: command::data::MemoryArea,
245 start_address: u32,
246 size: u32,
247 ) -> Result<Vec<u8>> {
248 let cmd = command::commands::MemoryRead {
249 area,
250 start_address,
251 size,
252 };
253 cmd.execute(&mut self.target)
254 }
255
256 pub fn user_boot_area_checksum(&mut self) -> Result<u32> {
258 let cmd = command::commands::UserBootAreaChecksum {};
259 cmd.execute(&mut self.target)
260 }
261
262 pub fn user_area_checksum(&mut self) -> Result<u32> {
264 let cmd = command::commands::UserAreaChecksum {};
265 cmd.execute(&mut self.target)
266 }
267}
268
269pub struct ProgrammerConnectedWaitingForData {
271 target: Box<dyn Target>,
272}
273
274impl ProgrammerConnectedWaitingForData {
275 pub fn program_block(&mut self, address: u32, data: [u8; 256]) -> Result<()> {
277 let cmd = command::commands::X256ByteProgramming {
278 address: address,
279 data: data,
280 };
281 cmd.execute(&mut self.target)
282 }
283
284 pub fn end(mut self) -> Result<ProgrammerConnectedProgrammingErasureState> {
286 let cmd = command::commands::X256ByteProgramming {
287 address: 0xFFFFFFFF,
288 data: [0u8; 256],
289 };
290 cmd.execute(&mut self.target)?;
291
292 Ok(ProgrammerConnectedProgrammingErasureState {
293 target: self.target,
294 })
295 }
296}