common: Implement Mx25l::erase_sector().
authorTilman Sauerbeck <tilman@code-monkey.de>
Wed, 8 Jan 2020 09:45:03 +0000 (10:45 +0100)
committerTilman Sauerbeck <tilman@code-monkey.de>
Thu, 9 Jan 2020 14:19:36 +0000 (15:19 +0100)
src/common/mx25l.rs

index 24f9c36cb5a4f91d346ea69cc1c1c8eb8f86a45a..2c498cefa6950d5459f5a9764fc964bb536971f5 100644 (file)
@@ -25,6 +25,8 @@ use gpio;
 use spi;
 use storage::Storage;
 
+const SECTOR_SIZE: usize = 4096;
+
 pub struct Mx25l {
     cs_gpio: u32,
     cs_gpio_pin: u32,
@@ -33,9 +35,17 @@ pub struct Mx25l {
 enum Command {
     READ = 0x03,
     RDSR = 0x05,
+    WREN = 0x06,
+    SE   = 0x20,
     RDID = 0x9f,
 }
 
+pub enum Error {
+    UnalignedAddress = 1,
+}
+
+const SR_WIP: u8 = 1 << 0;
+
 impl Mx25l {
     pub fn new(cs_gpio: u32, cs_gpio_pin: u32) -> Mx25l {
         Mx25l {
@@ -64,6 +74,37 @@ impl Mx25l {
         })
     }
 
+    pub fn erase_sector(&self, address: usize) -> Result<(), Error> {
+        if (address & (SECTOR_SIZE - 1)) != 0 {
+            return Err(Error::UnalignedAddress);
+        }
+
+        self.write_enable();
+
+        self.with_selected(|| {
+            spi::tx8(spi::SPI0, Command::SE 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);
+        });
+
+        while self.write_in_progress() {
+        }
+
+        Ok(())
+    }
+
+    fn write_enable(&self) {
+        self.with_selected(|| {
+            spi::tx8(spi::SPI0, Command::WREN as u8);
+        });
+    }
+
+    fn write_in_progress(&self) -> bool {
+        (self.read_status() & SR_WIP) != 0
+    }
+
     fn with_selected<F, T>(&self, func: F) -> T
         where F: FnOnce() -> T
     {