reading and writing now work
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
e88650850b
commit
f97ed5eef6
@ -8,7 +8,7 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ftdi-vcp-rs = { path = "ftdi-vcp-rs" }
|
ftdi-vcp-rs = { path = "ftdi-vcp-rs" }
|
||||||
clap = "*"
|
clap = "2.33"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
# cc = { version = "1.0", features = ["parallel"] }
|
# cc = { version = "1.0", features = ["parallel"] }
|
||||||
|
47
src/flash.rs
47
src/flash.rs
@ -8,11 +8,16 @@ pub enum EraseType {
|
|||||||
|
|
||||||
pub struct Flash {
|
pub struct Flash {
|
||||||
pub vcp: VCP,
|
pub vcp: VCP,
|
||||||
|
verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flash {
|
impl Flash {
|
||||||
pub fn new(vcp: VCP) -> Flash {
|
pub fn new(vcp: VCP) -> Flash {
|
||||||
Flash { vcp }
|
Flash { vcp, verbose: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_verbose(&mut self, verbose: bool) {
|
||||||
|
self.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cs_creset(&mut self, cs_asserted: bool, reset_asserted: bool) -> Result<(), Error> {
|
fn set_cs_creset(&mut self, cs_asserted: bool, reset_asserted: bool) -> Result<(), Error> {
|
||||||
@ -64,7 +69,7 @@ impl Flash {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_id(&mut self, verbose: bool) -> Result<(), Error> {
|
pub fn read_id(&mut self) -> Result<(), Error> {
|
||||||
/* JEDEC ID structure:
|
/* JEDEC ID structure:
|
||||||
* Byte No. | Data Type
|
* Byte No. | Data Type
|
||||||
* ---------+----------
|
* ---------+----------
|
||||||
@ -78,7 +83,7 @@ impl Flash {
|
|||||||
data[0] = 0x9Fu8 /* FC_JEDECID - Read JEDEC ID */;
|
data[0] = 0x9Fu8 /* FC_JEDECID - Read JEDEC ID */;
|
||||||
let mut len = 5usize; // command + 4 response bytes
|
let mut len = 5usize; // command + 4 response bytes
|
||||||
|
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("read flash ID..");
|
println!("read flash ID..");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +132,10 @@ impl Flash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_enable(&mut self, verbose: bool) -> Result<(), Error> {
|
pub fn write_enable(&mut self) -> Result<(), Error> {
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("status before enable:");
|
println!("status before enable:");
|
||||||
self.read_status(verbose)?;
|
self.read_status()?;
|
||||||
println!("write enable..");
|
println!("write enable..");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,9 +144,9 @@ impl Flash {
|
|||||||
self.vcp.xfer_spi(&mut data)?;
|
self.vcp.xfer_spi(&mut data)?;
|
||||||
self.chip_deselect()?;
|
self.chip_deselect()?;
|
||||||
|
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("status after enable:");
|
println!("status after enable:");
|
||||||
self.read_status(verbose)?;
|
self.read_status()?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -168,14 +173,14 @@ impl Flash {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_status(&mut self, verbose: bool) -> Result<u8, Error> {
|
pub fn read_status(&mut self) -> Result<u8, Error> {
|
||||||
let mut data = [0x05 /* FC_RSR1 // Read Status Register 1 */, 0x00];
|
let mut data = [0x05 /* FC_RSR1 // Read Status Register 1 */, 0x00];
|
||||||
|
|
||||||
self.chip_select()?;
|
self.chip_select()?;
|
||||||
self.vcp.xfer_spi(&mut data)?;
|
self.vcp.xfer_spi(&mut data)?;
|
||||||
self.chip_deselect()?;
|
self.chip_deselect()?;
|
||||||
|
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("SR1: 0x{:02X}", data[1]);
|
println!("SR1: 0x{:02X}", data[1]);
|
||||||
println!(
|
println!(
|
||||||
" - SPRL: {}",
|
" - SPRL: {}",
|
||||||
@ -251,7 +256,7 @@ impl Flash {
|
|||||||
self.vcp.xfer_spi(&mut data)?;
|
self.vcp.xfer_spi(&mut data)?;
|
||||||
self.chip_deselect()?;
|
self.chip_deselect()?;
|
||||||
|
|
||||||
self.wait(false)?;
|
self.wait()?;
|
||||||
|
|
||||||
// Read Status Register 1
|
// Read Status Register 1
|
||||||
data[0] = 0x05; // FC_RSR1;
|
data[0] = 0x05; // FC_RSR1;
|
||||||
@ -270,8 +275,8 @@ impl Flash {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait(&mut self, verbose: bool) -> Result<(), Error> {
|
pub fn wait(&mut self) -> Result<(), Error> {
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("waiting..");
|
println!("waiting..");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,19 +291,19 @@ impl Flash {
|
|||||||
if (data[1] & 0x01) == 0 {
|
if (data[1] & 0x01) == 0 {
|
||||||
if count < 2 {
|
if count < 2 {
|
||||||
count += 1;
|
count += 1;
|
||||||
if verbose {
|
if self.verbose {
|
||||||
print!("r");
|
print!("r");
|
||||||
//fflush(stderr);
|
//fflush(stderr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if self.verbose {
|
||||||
print!("R");
|
print!("R");
|
||||||
// fflush(stderr);
|
// fflush(stderr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose {
|
if self.verbose {
|
||||||
print!(".");
|
print!(".");
|
||||||
// fflush(stderr);
|
// fflush(stderr);
|
||||||
}
|
}
|
||||||
@ -308,15 +313,15 @@ impl Flash {
|
|||||||
sleep(Duration::from_micros(1_000));
|
sleep(Duration::from_micros(1_000));
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prog(&mut self, addr: usize, data: &[u8], verbose: bool) -> Result<(), Error> {
|
pub fn prog(&mut self, addr: usize, data: &[u8]) -> Result<(), Error> {
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("prog 0x{:06X} +0x{:03X}..", addr, data.len());
|
println!("prog 0x{:06X} +0x{:03X}..", addr, data.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,8 +344,8 @@ impl Flash {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&mut self, addr: usize, data: &mut [u8], verbose: bool) -> Result<(), Error> {
|
pub fn read(&mut self, addr: usize, data: &mut [u8]) -> Result<(), Error> {
|
||||||
if verbose {
|
if self.verbose {
|
||||||
println!("read 0x{:06X} +0x{:03X}..", addr, data.len());
|
println!("read 0x{:06X} +0x{:03X}..", addr, data.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
183
src/main.rs
183
src/main.rs
@ -5,27 +5,55 @@
|
|||||||
|
|
||||||
#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL)
|
#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL)
|
||||||
*/
|
*/
|
||||||
use clap::{App, Arg, SubCommand};
|
use clap::{App, Arg};
|
||||||
use ftdi_vcp_rs::{mpsse::Command::*, BitMode, VCP};
|
use ftdi_vcp_rs::{mpsse::Command::*, BitMode, VCP};
|
||||||
use std::io::{Write, Read};
|
use std::fs::File;
|
||||||
|
use std::io::Seek;
|
||||||
|
use std::io::{Read, Write};
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::fs::File;
|
|
||||||
|
|
||||||
mod flash;
|
mod flash;
|
||||||
|
|
||||||
|
fn parse_size(input: &str) -> Result<usize, &'static str> {
|
||||||
|
let multiple_index = input
|
||||||
|
.chars()
|
||||||
|
.position(|c| !(c.is_numeric() || c == '.'))
|
||||||
|
.unwrap_or(input.len());
|
||||||
|
|
||||||
|
let (value, multiple) = &input.split_at(multiple_index);
|
||||||
|
let value = value.parse::<usize>().map_err(|_| "unable to parse")?;
|
||||||
|
let multiple = match multiple.trim().to_lowercase().as_str() {
|
||||||
|
"m" | "mib" => 1024 * 1024,
|
||||||
|
"k" | "kib" => 1024,
|
||||||
|
"b" | "" | "bytes" => 1,
|
||||||
|
"g" | "gib" => 1024 * 1024 * 1024,
|
||||||
|
x => {
|
||||||
|
println!("Unrecognized suffix {}", x);
|
||||||
|
return Err("unrecognized suffix")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Ok(value * multiple)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_size_sanity() {
|
||||||
|
assert_eq!(parse_size("0").unwrap(), 0);
|
||||||
|
assert_eq!(parse_size("1024").unwrap(), 1024);
|
||||||
|
assert_eq!(parse_size("1k").unwrap(), 1024);
|
||||||
|
assert_eq!(parse_size("1K").unwrap(), 1024);
|
||||||
|
assert_eq!(parse_size("1 K").unwrap(), 1024);
|
||||||
|
assert_eq!(parse_size("1 k").unwrap(), 1024);
|
||||||
|
assert_eq!(parse_size("1 kiB").unwrap(), 1024);
|
||||||
|
assert_eq!(parse_size("1 M").unwrap(), 1024*1024);
|
||||||
|
assert_eq!(parse_size("2 M").unwrap(), 1024*1024*2);
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
||||||
let mut vcp = VCP::new_from_name("iCEBreaker V1.0e A").expect("couldn't open vcp");
|
let mut vcp = VCP::new_from_name("iCEBreaker V1.0e A").expect("couldn't open vcp");
|
||||||
let slow_clock = false;
|
let slow_clock = false;
|
||||||
let read_mode = false;
|
|
||||||
let check_mode = false;
|
|
||||||
let dont_erase = false;
|
|
||||||
let bulk_erase = false;
|
|
||||||
let disable_verify = false;
|
let disable_verify = false;
|
||||||
let erase_mode = false;
|
|
||||||
let rw_offset = 0;
|
|
||||||
let disable_protect = false;
|
let disable_protect = false;
|
||||||
let read_size = 256 * 1024;
|
|
||||||
|
|
||||||
let mut bitstream = vec![];
|
let mut bitstream = vec![];
|
||||||
|
|
||||||
@ -36,30 +64,89 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("FILENAME")
|
Arg::with_name("FILENAME")
|
||||||
.help("Sets the bitstream file to read or write")
|
.help("Sets the bitstream file to read or write")
|
||||||
.required(true)
|
.required_unless("verbose")
|
||||||
|
.required_unless("test")
|
||||||
.index(1),
|
.index(1),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("v")
|
Arg::with_name("verbose")
|
||||||
.short("v")
|
.short("v")
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.help("Sets the level of verbosity"),
|
.help("Sets the level of verbosity"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("test")
|
Arg::with_name("bulk_erase")
|
||||||
.short("t")
|
.short("b")
|
||||||
.help("Run tests"),
|
.help("bulk erase entire flash before writing"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("check_mode")
|
||||||
|
.short("c")
|
||||||
|
.help("do not write flash, only verify (`check')"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("no_erase")
|
||||||
|
.short("n")
|
||||||
|
.help("do not erase flash before writing"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("erase_size")
|
||||||
|
.short("e")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("erase flash as if we were writing that number of bytes"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("read_256")
|
||||||
|
.short("r")
|
||||||
|
.help("read first 256 kB from flash and write to file"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("read_file")
|
||||||
|
.short("R")
|
||||||
|
.takes_value(true)
|
||||||
|
.conflicts_with("read_256")
|
||||||
|
.help("read the specified number of bytes from flash"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("offset")
|
||||||
|
.short("o")
|
||||||
|
.takes_value(true)
|
||||||
|
.default_value("0")
|
||||||
|
.help("start address for read/write"),
|
||||||
|
)
|
||||||
|
.arg(Arg::with_name("test").short("t").help("Run tests"))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let verbose = matches.is_present("verbose");
|
let verbose = matches.is_present("verbose");
|
||||||
let test_mode = matches.is_present("test");
|
let test_mode = matches.is_present("test");
|
||||||
|
let bulk_erase = matches.is_present("bulk_erase");
|
||||||
|
let check_mode = matches.is_present("check_mode");
|
||||||
|
let dont_erase = matches.is_present("no_erase");
|
||||||
|
let rw_offset = matches.value_of("offset").map_or(0, |e: &str| {
|
||||||
|
parse_size(e).expect("unable to parse size")
|
||||||
|
});
|
||||||
|
let erase_size = matches.value_of("erase_size").map(|e| {
|
||||||
|
Some(parse_size(e).unwrap())
|
||||||
|
});
|
||||||
|
let read_size = if matches.is_present("read_256") {
|
||||||
|
Some(256 * 1024)
|
||||||
|
} else if let Some(size) = matches.value_of("read_file") {
|
||||||
|
Some(parse_size(size).unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let bitstream = {
|
let mut bitstream_file = if let Some(filename) = matches.value_of("FILENAME") {
|
||||||
let filename = matches.value_of("FILENAME").unwrap();
|
if read_size.is_none() && !test_mode {
|
||||||
let mut file = File::open(filename).expect("Couldn't open path");
|
let mut file = File::open(filename).expect("Couldn't open path");
|
||||||
file.read_to_end(&mut bitstream).expect("couldn't read to end");
|
file.read_to_end(&mut bitstream)
|
||||||
bitstream
|
.expect("couldn't read to end");
|
||||||
|
Some(file)
|
||||||
|
} else {
|
||||||
|
Some(File::create(filename).expect("Couldn't create output file"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Opened VCP: {:?}", vcp);
|
println!("Opened VCP: {:?}", vcp);
|
||||||
@ -86,6 +173,7 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut flash = flash::Flash::new(vcp);
|
let mut flash = flash::Flash::new(vcp);
|
||||||
|
flash.set_verbose(verbose);
|
||||||
flash.release_reset()?;
|
flash.release_reset()?;
|
||||||
|
|
||||||
sleep(Duration::from_micros(100_000));
|
sleep(Duration::from_micros(100_000));
|
||||||
@ -101,7 +189,7 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
flash.reset()?;
|
flash.reset()?;
|
||||||
flash.power_up()?;
|
flash.power_up()?;
|
||||||
|
|
||||||
flash.read_id(true)?;
|
flash.read_id()?;
|
||||||
|
|
||||||
flash.power_down()?;
|
flash.power_down()?;
|
||||||
|
|
||||||
@ -113,34 +201,37 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
// Reset
|
// Reset
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
|
if verbose {
|
||||||
println!("reset..");
|
println!("reset..");
|
||||||
|
}
|
||||||
|
|
||||||
flash.chip_deselect()?;
|
flash.chip_deselect()?;
|
||||||
sleep(Duration::from_micros(250_000));
|
sleep(Duration::from_micros(250_000));
|
||||||
|
|
||||||
|
if verbose {
|
||||||
println!("cdone: {}", flash.cdone_str()?);
|
println!("cdone: {}", flash.cdone_str()?);
|
||||||
|
}
|
||||||
|
|
||||||
flash.reset()?;
|
flash.reset()?;
|
||||||
flash.power_up()?;
|
flash.power_up()?;
|
||||||
|
|
||||||
flash.read_id(true)?;
|
flash.read_id()?;
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
// Program
|
// Program
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
|
|
||||||
if !read_mode && !check_mode {
|
if read_size.is_none() && !check_mode {
|
||||||
if disable_protect {
|
if disable_protect {
|
||||||
flash.write_enable(verbose)?;
|
flash.write_enable()?;
|
||||||
flash.disable_protection()?;
|
flash.disable_protection()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dont_erase {
|
if !dont_erase {
|
||||||
if bulk_erase {
|
if bulk_erase {
|
||||||
flash.write_enable(verbose)?;
|
flash.write_enable()?;
|
||||||
flash.bulk_erase()?;
|
flash.bulk_erase()?;
|
||||||
flash.wait(verbose)?;
|
flash.wait()?;
|
||||||
} else {
|
} else {
|
||||||
println!("file size: {}", bitstream.len());
|
println!("file size: {}", bitstream.len());
|
||||||
|
|
||||||
@ -148,28 +239,30 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
let end_addr = (rw_offset + bitstream.len() + 0xffff) & !0xffff;
|
let end_addr = (rw_offset + bitstream.len() + 0xffff) & !0xffff;
|
||||||
|
|
||||||
for addr in (begin_addr..end_addr).step_by(0x10000) {
|
for addr in (begin_addr..end_addr).step_by(0x10000) {
|
||||||
flash.write_enable(verbose)?;
|
flash.write_enable()?;
|
||||||
flash.sector_erase(flash::EraseType::Kb64, addr)?;
|
flash.sector_erase(flash::EraseType::Kb64, addr)?;
|
||||||
if verbose {
|
if verbose {
|
||||||
println!("Status after block erase:");
|
println!("Status after block erase:");
|
||||||
flash.read_status(verbose)?;
|
flash.read_status()?;
|
||||||
}
|
}
|
||||||
flash.wait(verbose)?;
|
flash.wait()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !erase_mode {
|
if erase_size.is_none() {
|
||||||
println!("programming..");
|
println!("programming..");
|
||||||
|
|
||||||
for (idx, page) in bitstream.chunks(256).enumerate() {
|
for (idx, page) in bitstream.chunks(256).enumerate() {
|
||||||
flash.write_enable(verbose)?;
|
flash.write_enable()?;
|
||||||
flash.prog(rw_offset + idx*256, page, verbose)?;
|
flash.prog(rw_offset + idx * 256, page)?;
|
||||||
flash.wait(verbose)?;
|
flash.wait()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seek to the beginning for second pass */
|
/* seek to the beginning for second pass */
|
||||||
// fseek(f, 0, SEEK_SET);
|
bitstream_file.as_mut()
|
||||||
|
.expect("no bitstream file was specified")
|
||||||
|
.seek(std::io::SeekFrom::Start(0))
|
||||||
|
.expect("Couldn't rewind file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,18 +270,22 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
// Read/Verify
|
// Read/Verify
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
|
|
||||||
if read_mode {
|
if let Some(read_size) = read_size {
|
||||||
println!("reading..");
|
println!("reading {} bytes..", read_size);
|
||||||
for addr in (0..read_size).step_by(256) {
|
|
||||||
// uint8_t buffer[256];
|
// uint8_t buffer[256];
|
||||||
// flash_read(rw_offset + addr, buffer, 256);
|
let out_file = bitstream_file.as_mut().expect("no output file found");
|
||||||
// fwrite(buffer, read_size - addr > 256 ? 256 : read_size - addr, 1, f);
|
let mut buffer = [0u8; 256];
|
||||||
|
for addr in (0..read_size).step_by(256) {
|
||||||
|
flash.read(rw_offset + addr, &mut buffer)?;
|
||||||
|
out_file
|
||||||
|
.write_all(&buffer)
|
||||||
|
.expect("couldn't write to bitstream file");
|
||||||
}
|
}
|
||||||
} else if !erase_mode && !disable_verify {
|
} else if erase_size.is_none() && !disable_verify {
|
||||||
println!("reading..");
|
println!("reading..");
|
||||||
for (idx, page) in bitstream.chunks(256).enumerate() {
|
for (idx, page) in bitstream.chunks(256).enumerate() {
|
||||||
let mut buffer_flash = [0; 256];
|
let mut buffer_flash = [0; 256];
|
||||||
flash.read(rw_offset + idx*256, &mut buffer_flash, verbose);
|
flash.read(rw_offset + idx * 256, &mut buffer_flash)?;
|
||||||
if !page.iter().zip(buffer_flash.iter()).all(|(a, b)| a == b) {
|
if !page.iter().zip(buffer_flash.iter()).all(|(a, b)| a == b) {
|
||||||
println!("Found difference between flash and file!");
|
println!("Found difference between flash and file!");
|
||||||
}
|
}
|
||||||
@ -203,7 +300,7 @@ fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
|||||||
|
|
||||||
flash.power_down()?;
|
flash.power_down()?;
|
||||||
|
|
||||||
flash.release_reset();
|
flash.release_reset()?;
|
||||||
sleep(Duration::from_micros(250_000));
|
sleep(Duration::from_micros(250_000));
|
||||||
|
|
||||||
println!("cdone: {}", flash.cdone_str()?);
|
println!("cdone: {}", flash.cdone_str()?);
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
pub struct MPSSE {
|
||||||
|
handle: VCP,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MPSSE {
|
||||||
|
pub fn set_gpio(&mut self, gpio: u8, direction: )
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user