1use core::fmt::Debug;
6use core::marker::PhantomData;
7
8use log::{trace, debug, info, error};
9
10use nb::block;
11use thiserror::Error;
12
13use embedded_hal::blocking::delay::DelayMs;
14use embedded_hal::serial::{Read, Write};
15
16#[cfg(feature = "linux")]
17extern crate linux_embedded_hal;
18#[cfg(feature = "linux")]
19pub mod linux;
20
21pub mod protocol;
22use protocol::*;
23
24
25pub trait SerialPort<E>: Write<u8, Error = E> + Read<u8, Error = E> {
27 fn set_rts(&mut self, level: bool) -> Result<(), E>;
28 fn set_dtr(&mut self, level: bool) -> Result<(), E>;
29}
30
31#[derive(Error, Clone, PartialEq, Debug)]
32pub enum Error<SerialError: Debug> {
33 #[error("Serial device error: {0:?}")]
34 Serial(SerialError),
35 #[error("Nack")]
36 Nack,
37 #[error("NoAck")]
38 NoAck,
39 #[error("Timeout")]
40 Timeout,
41 #[error("InvalidResponse")]
42 InvalidResponse,
43 #[error("BufferLength")]
44 BufferLength,
45 #[error("Io error: {0:?}")]
46 Io(std::io::ErrorKind),
47}
48
49impl<SerialError: Debug> From<SerialError> for Error<SerialError> {
50 fn from(e: SerialError) -> Self {
51 Self::Serial(e)
52 }
53}
54
55#[derive(Clone, PartialEq, Debug)]
56#[cfg_attr(feature = "structopt", derive(structopt::StructOpt))]
57pub struct Options {
58 #[cfg_attr(feature = "structopt", structopt(long))]
60 pub no_reset: bool,
61
62 #[cfg_attr(feature = "structopt", structopt(long, default_value = "100"))]
64 pub response_timeout_ms: u32,
65
66 #[cfg_attr(feature = "structopt", structopt(long, default_value = "10"))]
68 pub poll_delay_ms: u32,
69
70 #[cfg_attr(feature = "structopt", structopt(long, default_value = "100"))]
72 pub init_delay_ms: u32,
73
74 #[cfg_attr(feature = "structopt", structopt(long))]
76 pub no_progress: bool,
77}
78
79impl Default for Options {
80 fn default() -> Self {
81 Self {
82 no_reset: false,
83 no_progress: false,
84 response_timeout_ms: 100,
85 poll_delay_ms: 10,
86 init_delay_ms: 100,
87 }
88 }
89}
90
91pub struct Programmer<P, D, E> {
92 options: Options,
93 port: P,
94 delay: D,
95 _err: PhantomData<E>,
96}
97
98impl<P, D, E> Programmer<P, D, E>
99where
100 P: SerialPort<E>,
101 D: DelayMs<u32>,
102 E: core::fmt::Debug,
103{
104 pub fn new(port: P, delay: D, options: Options) -> Result<Self, Error<E>> {
106 let mut s = Self {
107 options,
108 port,
109 delay,
110 _err: PhantomData,
111 };
112
113 s.init()?;
114
115 Ok(s)
116 }
117
118 fn init(&mut self) -> Result<(), Error<E>> {
120 debug!("Resetting device");
122
123 self.reset(true)?;
124
125 debug!("Sending discovery character");
126
127 block!(self.port.write(UART_DISC)).unwrap();
129 block!(self.port.flush()).unwrap();
130
131 debug!("Awaiting bootloader response");
133 let _ = self.await_ack();
134
135 self.delay.delay_ms(100);
137
138 debug!("Reading bootloader info");
140 let version = self.info()?;
141 debug!("Bootloader version: 0x{:02x}", version);
142
143 self.delay.delay_ms(100);
144
145 Ok(())
147 }
148
149 pub fn info(&mut self) -> Result<u8, Error<E>> {
152 let mut data = [0u8; 12];
153
154 self.write_cmd(Command::Get)?;
156
157 self.await_ack()?;
159
160 let n = self.read_char()? as usize + 1;
162
163 debug!("Reading {} bytes", n);
164
165 if data.len() < n {
166 error!("RX buffer too short");
167 return Err(Error::BufferLength);
168 }
169
170 for i in 0..n {
172 data[i] = self.read_char()?;
173 }
174
175 self.await_ack()?;
177
178 debug!("Received: 0x{:02x?}", &data[..n]);
179
180 Ok(data[0])
181 }
182
183 pub fn erase(&mut self, page_offset: u8, page_count: u8) -> Result<(), Error<E>> {
185
186 debug!("Erasing {} pages from index {}", page_count, page_offset);
187 let pages: Vec<u8> = (page_count..page_offset+page_count).collect();
188
189 self.erase_pages(&pages)
190 }
191
192 pub fn erase_pages(&mut self, pages: &[u8]) -> Result<(), Error<E>> {
194 self.write_cmd(Command::Erase)?;
196 self.await_ack()?;
197
198 let len = (pages.len() - 1) as u8;
200 block!(self.port.write(len))?;
201
202 self.write_bytes_csum(pages)?;
204
205 self.await_ack()
206 }
207
208 pub fn erase_all(&mut self) -> Result<(), Error<E>> {
210 self.write_cmd(Command::Erase)?;
212 self.await_ack()?;
213
214 self.write_bytes(&[0xFF, 0x00])?;
215 self.await_ack()?;
216
217 Ok(())
218 }
219
220 pub fn read(&mut self, addr: u32, data: &mut [u8]) -> Result<(), Error<E>> {
222 let mut index = 0;
223
224 #[cfg(feature="indicatif")]
226 let mut p = match !self.options.no_progress {
227 true => {
228 let pb = indicatif::ProgressBar::new(data.len() as u64);
229
230 pb.set_style(indicatif::ProgressStyle::default_bar()
231 .template("{spinner:.green} [{elapsed_precise}] [{bar:80.cyan/blue}] {bytes}/{total_bytes} ({eta})")
232 .progress_chars("#>-"));
233
234 Some(pb)
235 },
236 _ => None,
237 };
238
239 for chunk in data.chunks_mut(MAX_CHUNK as usize) {
240 debug!("Read chunk at 0x{:08x}, length: {}", addr + index as u32, chunk.len());
241
242 self.read_mem_block(addr + index as u32, &mut chunk[..])?;
243
244 index += chunk.len();
245
246 #[cfg(feature="indicatif")]
248 if let Some(p) = &mut p {
249 p.inc(chunk.len() as u64)
250 }
251 }
252
253 Ok(())
254 }
255
256 fn read_mem_block(&mut self, addr: u32, data: &mut [u8]) -> Result<(), Error<E>> {
257 assert!(data.len() <= 256, "block size must be less than 256 bytes");
258
259 self.write_cmd(Command::ReadMemory)?;
261 self.await_ack()?;
262
263
264 let addr = [(addr >> 24) as u8, (addr >> 16) as u8, (addr >> 8) as u8, addr as u8];
266 let addr_csum = addr[0] ^ addr[1] ^ addr[2] ^ addr[3];
267
268 for a in &addr {
269 block!(self.port.write(*a))?;
270 }
271 block!(self.port.write(addr_csum))?;
272 block!(self.port.flush())?;
273
274 self.await_ack()?;
275
276
277 let len = (data.len() - 1) as u8;
279 self.write_bytes(&[len, !len])?;
280
281 self.await_ack()?;
282
283 for i in 0..data.len() {
285 data[i] = self.read_char()?;
286 }
287
288 Ok(())
289 }
290
291 pub fn write(&mut self, addr: u32, data: &[u8]) -> Result<(), Error<E>> {
293 let mut index = 0;
294
295 #[cfg(feature="indicatif")]
297 let mut p = match !self.options.no_progress {
298 true => {
299 let pb = indicatif::ProgressBar::new(data.len() as u64);
300
301 pb.set_style(indicatif::ProgressStyle::default_bar()
302 .template("{spinner:.green} [{elapsed_precise}] [{bar:80.cyan/blue}] {bytes}/{total_bytes} ({eta})")
303 .progress_chars("#>-"));
304
305 Some(pb)
306 },
307 _ => None,
308 };
309
310 for chunk in data.chunks(MAX_CHUNK as usize) {
311 debug!("Write chunk at 0x{:08x}, length: {}", addr + index as u32, chunk.len());
312
313 self.write_mem_block(addr + index as u32, &chunk[..])?;
314
315 index += chunk.len();
316
317 #[cfg(feature="indicatif")]
319 if let Some(p) = &mut p {
320 p.inc(chunk.len() as u64)
321 }
322 }
323
324 Ok(())
325 }
326
327 fn write_mem_block(&mut self, addr: u32, data: &[u8]) -> Result<(), Error<E>> {
328 assert!(data.len() <= 256, "block size must be less than 256 bytes");
329
330 self.write_cmd(Command::WriteMemory)?;
332 self.await_ack()?;
333
334
335 let addr = [(addr >> 24) as u8, (addr >> 16) as u8, (addr >> 8) as u8, addr as u8];
337 let addr_csum = addr[0] ^ addr[1] ^ addr[2] ^ addr[3];
338
339 for a in &addr {
340 block!(self.port.write(*a))?;
341 }
342 block!(self.port.write(addr_csum))?;
343 block!(self.port.flush())?;
344
345 self.await_ack()?;
346
347
348 let len = (data.len() - 1) as u8;
350 let mut data_csum = len;
351
352 block!(self.port.write(len))?;
353 for d in data {
354 data_csum ^= *d;
355 block!(self.port.write(*d))?;
356 }
357 block!(self.port.write(data_csum))?;
358
359 self.await_ack()?;
360
361
362 Ok(())
363 }
364
365 pub fn reset(&mut self, bootloader: bool) -> Result<(), Error<E>> {
367 self.port.set_rts(true)?;
369
370 self.delay.delay_ms(10u32);
372
373 if bootloader {
374 self.port.set_dtr(true)?;
376 }
377
378 self.port.set_rts(false)?;
380
381 self.delay.delay_ms(self.options.init_delay_ms);
383
384 if bootloader {
385 self.port.set_dtr(false)?;
387 }
388
389 Ok(())
390 }
391
392 pub fn chip_id(&mut self) -> Result<u16, Error<E>> {
394 self.write_cmd(Command::GetId)?;
396
397 self.await_ack()?;
399
400 let n = self.read_char()? as usize + 1;
402
403 debug!("Reading {} byte chip ID", n);
404
405 let mut v: u16 = 0;
407 for i in 0..n {
408 let c = self.read_char()?;
409 v |= (c as u16) << (i * 8);
410 }
411
412 self.await_ack()?;
414
415 Ok(v)
416 }
417
418 pub fn write_cmd(&mut self, command: Command) -> Result<(), Error<E>> {
420 let c1 = command.clone() as u8;
422 let c2 = !c1;
423
424 debug!("Writing command {:?} [0x{:02x}, 0x{:02x}]", command, c1, c2);
425
426 block!(self.port.write(c1))?;
427 block!(self.port.write(c2))?;
428 block!(self.port.flush())?;
429
430 Ok(())
431 }
432
433 pub fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error<E>> {
434
435 debug!("Writing bytes: 0x{:02x?}", data);
436
437 for d in data {
438 block!(self.port.write(*d))?;
439 }
440
441 block!(self.port.flush())?;
442
443 Ok(())
444 }
445
446 pub fn write_bytes_csum(&mut self, data: &[u8]) -> Result<(), Error<E>> {
448 let mut csum = 0x00;
449 for d in data {
450 csum ^= *d;
451 }
452
453 info!("Writing data with checksum: {:02x?} ({:02x})", data, csum);
454
455 for d in data {
456 block!(self.port.write(*d))?;
457 }
458
459 block!(self.port.write(csum))?;
460 block!(self.port.flush())?;
461
462 Ok(())
463 }
464
465 pub fn read_char(&mut self) -> Result<u8, Error<E>> {
467 let mut t = 0;
468
469 loop {
470 match self.port.read() {
472 Err(nb::Error::WouldBlock) => (),
473 Err(nb::Error::Other(e)) => return Err(e.into()),
474 Ok(v) => return Ok(v)
475 };
476
477 self.delay.delay_ms(self.options.poll_delay_ms);
479 t += self.options.poll_delay_ms;
480
481 if t > self.options.response_timeout_ms {
482 error!("Receive timeout");
483 return Err(Error::Timeout);
484 }
485 }
486 }
487
488 fn await_ack(&mut self) -> Result<(), Error<E>> {
490 let v = self.read_char()?;
491 match v {
492 UART_ACK => {
493 trace!("Received ACK!");
494 Ok(())
495 },
496 UART_NACK => {
497 trace!("Received NACK?!");
498 Err(Error::Nack)
499 },
500 _ => {
501 error!("Unexpected response: 0x{:02x}", v);
502 Err(Error::InvalidResponse)
503 }
504 }
505 }
506}