1use byteorder::{ByteOrder, LittleEndian, WriteBytesExt, ReadBytesExt};
2use serialport::SerialPort;
3use std::io::{BufReader, BufRead};
4
5static ISP_IMAGE: &'static [u8] = include_bytes!("./orange-isp.bin");
6
7#[derive(Copy, Clone, Debug)]
8pub enum IspCommand<'a> {
9 Boot,
10 Flash(&'a [u8]),
11}
12
13pub fn upload_isp_image(port: &mut dyn SerialPort) {
14 let mut write_half = port.try_clone().expect("cannot clone port");
15 println!("Waiting for device...");
16 let reader = BufReader::new(port);
17 let mut lines = reader.lines();
18 loop {
19 let line = match lines.next().expect("expecting first line") {
20 Ok(x) => x,
21 Err(_) => continue };
23 let expected = "OrangeLoader SERIAL BOOT ";
24 if line.starts_with(expected) {
25 println!("OrangeLoader version: {}", &line[expected.len()..]);
26 break;
27 }
28 }
29
30 transmit_boot_image(&mut *write_half, ISP_IMAGE);
31 if lines.next().unwrap().unwrap() != "OrangeISP" {
32 panic!("Bad response from ISP");
33 }
34 println!("ISP loaded to device.");
35}
36
37fn transmit_boot_image(port: &mut dyn SerialPort, image: &[u8]) {
38 let mut sum: u32 = 0;
39 let mut len_buf: [u8; 4] = [0; 4];
40 LittleEndian::write_u32(&mut len_buf, image.len() as u32);
41
42 for i in 0..4 {
43 sum += len_buf[i] as u32;
44 }
45 port.write(&len_buf).unwrap();
46
47 for b in image {
48 sum += *b as u32;
49 }
50 port.write(image).unwrap();
51
52 let mut sum_buf: [u8; 4] = [0; 4];
53 LittleEndian::write_u32(&mut sum_buf, sum);
54 port.write_all(&sum_buf).unwrap();
55}
56
57impl<'a> IspCommand<'a> {
58 pub fn send(&self, port: &mut dyn SerialPort) {
59 match *self {
60 IspCommand::Boot => {
61 port.write(&[0x00]).expect("write failed");
62 }
63 IspCommand::Flash(image) => {
64 port.write(&[0x01]).expect("write failed");
65
66 let num_blocks = ((image.len() + 65535) / 65536) as u32;
67 port.write_u32::<LittleEndian>(num_blocks).unwrap();
68
69 for i in (0..image.len()).step_by(65536) {
70 println!("Writing 0x{:x}.", i);
71 let mut buf = vec![0u8; 65536];
72 let copy_len = if image.len() - i > 65536 {
73 65536
74 } else {
75 image.len() - i
76 };
77 buf[0..copy_len].copy_from_slice(&image[i..i + copy_len]);
78 let checksum = crc::crc32::checksum_ieee(&buf);
79 port.write(&buf).unwrap();
80 port.write_u32::<LittleEndian>(checksum).unwrap();
81 let block_end = port.read_u8().unwrap();
82 assert_eq!(block_end, 0x66);
83 }
84 let transmit_end = port.read_u8().unwrap();
85 assert_eq!(transmit_end, 0x33);
86 }
87 }
88 }
89}