X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fcommon%2Fmx25l.rs;h=388d31172497b858c86c2ac36731156d1d16e2ed;hb=810fc22cf43b5cd504279f89e509a2a08d07481b;hp=2c498cefa6950d5459f5a9764fc964bb536971f5;hpb=bd6395210b3c1672288987f2c150c43e68ca5cfa;p=gps-watch.git diff --git a/src/common/mx25l.rs b/src/common/mx25l.rs index 2c498ce..388d311 100644 --- a/src/common/mx25l.rs +++ b/src/common/mx25l.rs @@ -23,9 +23,10 @@ use gpio; use spi; -use storage::Storage; +use storage::{Storage, Error}; const SECTOR_SIZE: usize = 4096; +const PAGE_SIZE: usize = 256; pub struct Mx25l { cs_gpio: u32, @@ -33,17 +34,15 @@ pub struct Mx25l { } enum Command { + PP = 0x02, READ = 0x03, RDSR = 0x05, WREN = 0x06, SE = 0x20, + CE = 0x60, RDID = 0x9f, } -pub enum Error { - UnalignedAddress = 1, -} - const SR_WIP: u8 = 1 << 0; impl Mx25l { @@ -74,6 +73,17 @@ impl Mx25l { }) } + pub fn erase_all(&self) { + self.write_enable(); + + self.with_selected(|| { + spi::tx8(spi::SPI0, Command::CE as u8); + }); + + while self.write_in_progress() { + } + } + pub fn erase_sector(&self, address: usize) -> Result<(), Error> { if (address & (SECTOR_SIZE - 1)) != 0 { return Err(Error::UnalignedAddress); @@ -95,6 +105,34 @@ impl Mx25l { Ok(()) } + pub fn program_page(&self, address: usize, buffer: &[u8; PAGE_SIZE]) + -> Result<(), Error> { + if (address & (PAGE_SIZE - 1)) != 0 { + return Err(Error::UnalignedAddress); + } + + if buffer.iter().all(|&b| b == 0xff) { + return Ok(()); + } + + self.with_selected(|| { + spi::tx8(spi::SPI0, Command::PP as u8); + + spi::tx8(spi::SPI0, (address >> 16) as u8); + spi::tx8(spi::SPI0, (address >> 8) as u8); + spi::tx8(spi::SPI0, (address >> 0) as u8); + + for &b in buffer.iter() { + spi::tx8(spi::SPI0, b); + } + }); + + while self.write_in_progress() { + } + + Ok(()) + } + fn write_enable(&self) { self.with_selected(|| { spi::tx8(spi::SPI0, Command::WREN as u8); @@ -132,4 +170,25 @@ impl Storage for Mx25l { } }) } + + fn write(&mut self, address: usize, buffer: &[u8; SECTOR_SIZE]) + -> Result<(), Error> { + if let Err(e) = self.erase_sector(address) { + return Err(e); + } + + for (i, page_bytes) in buffer.chunks(PAGE_SIZE).enumerate() { + let page_address = address + (i * PAGE_SIZE); + + // XXX: Inefficient. + let mut ba = [0xff; PAGE_SIZE]; + ba.copy_from_slice(&page_bytes); + + if let Err(e) = self.program_page(page_address, &ba) { + return Err(e); + } + } + + Ok(()) + } }