mirror of
https://github.com/icewind1991/esp8266-flash.git
synced 2026-06-03 10:34:05 +02:00
use spi registers instead of rom functions
This commit is contained in:
parent
6cd7bab5e5
commit
b28e24a0b6
4 changed files with 54 additions and 40 deletions
|
|
@ -6,14 +6,14 @@ edition = "2018"
|
||||||
description = "A driver for the esp8266 onboard flash"
|
description = "A driver for the esp8266 onboard flash"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
xtensa-lx106-rt = "0.0.1"
|
|
||||||
spi-memory = "0.2.0"
|
spi-memory = "0.2.0"
|
||||||
esp8266 = "0.0.6"
|
esp8266 = "0.1.1"
|
||||||
embedded-hal = "0.2.4"
|
embedded-hal = "0.2.4"
|
||||||
void = { version = "1.0.2", default-features = false }
|
void = { version = "1.0.2", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
esp8266-hal = "0.2.0"
|
esp8266-hal = "0.3.2"
|
||||||
|
xtensa-lx106-rt = "0.1.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,10 @@ use spi_memory::prelude::*;
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
// The default clock source is the onboard crystal
|
|
||||||
// In most cases 40mhz (but can be as low as 2mhz depending on the board)
|
|
||||||
// Clock speed is then doubled from the crystal frequency
|
|
||||||
let clock_frequency = 80.mhz();
|
|
||||||
|
|
||||||
let dp = unsafe { Peripherals::steal() };
|
let dp = unsafe { Peripherals::steal() };
|
||||||
let pins = dp.GPIO.split();
|
let pins = dp.GPIO.split();
|
||||||
let mut led = pins.gpio2.into_push_pull_output();
|
let mut led = pins.gpio2.into_push_pull_output();
|
||||||
let (mut timer1, _) = dp.TIMER.timers(clock_frequency);
|
let (mut timer1, _) = dp.TIMER.timers();
|
||||||
|
|
||||||
let mut serial = dp
|
let mut serial = dp
|
||||||
.UART0
|
.UART0
|
||||||
|
|
|
||||||
10
memory.x
10
memory.x
|
|
@ -1,10 +0,0 @@
|
||||||
/* Linker script for the ESP8266 */
|
|
||||||
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
/* All .data/.bss/heap are in this segment. Reserve 1KB for old boot or ROM boot */
|
|
||||||
dram_seg : org = 0x3FFE8000, len = 0x18000 - 0x400
|
|
||||||
|
|
||||||
/* Functions which are critical should be put in this segment. */
|
|
||||||
iram_seg : org = 0x40100000, len = 0xFC00
|
|
||||||
}
|
|
||||||
71
src/lib.rs
71
src/lib.rs
|
|
@ -5,9 +5,6 @@ use embedded_hal::digital::v2::OutputPin;
|
||||||
use esp8266::SPI0;
|
use esp8266::SPI0;
|
||||||
use spi_memory::{BlockDevice, Error, Read};
|
use spi_memory::{BlockDevice, Error, Read};
|
||||||
use void::Void;
|
use void::Void;
|
||||||
use xtensa_lx106_rt::rom::{SPIEraseChip, SPIEraseSector, SPIRead, SPIWrite};
|
|
||||||
|
|
||||||
const SECTOR_SIZE: u32 = 4096;
|
|
||||||
|
|
||||||
pub struct FlashSpi(SPI0);
|
pub struct FlashSpi(SPI0);
|
||||||
|
|
||||||
|
|
@ -45,16 +42,6 @@ pub enum ESPFlashError {
|
||||||
Timeout = 2,
|
Timeout = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ESPFlashError {
|
|
||||||
fn from(result: u32) -> Result<(), Self> {
|
|
||||||
match result {
|
|
||||||
0 => Ok(()),
|
|
||||||
2 => Err(ESPFlashError::Timeout),
|
|
||||||
_ => Err(ESPFlashError::Err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ESPFlashError> for Error<FlashSpi, DummyCS> {
|
impl From<ESPFlashError> for Error<FlashSpi, DummyCS> {
|
||||||
fn from(err: ESPFlashError) -> Self {
|
fn from(err: ESPFlashError) -> Self {
|
||||||
Error::Spi(err)
|
Error::Spi(err)
|
||||||
|
|
@ -63,6 +50,8 @@ impl From<ESPFlashError> for Error<FlashSpi, DummyCS> {
|
||||||
|
|
||||||
impl ESPFlash {
|
impl ESPFlash {
|
||||||
pub fn new(spi: SPI0) -> Self {
|
pub fn new(spi: SPI0) -> Self {
|
||||||
|
|
||||||
|
|
||||||
// take ownership of SPI0 to ensure nobody else can mess with the spi
|
// take ownership of SPI0 to ensure nobody else can mess with the spi
|
||||||
ESPFlash { spi: FlashSpi(spi) }
|
ESPFlash { spi: FlashSpi(spi) }
|
||||||
}
|
}
|
||||||
|
|
@ -70,26 +59,60 @@ impl ESPFlash {
|
||||||
pub fn decompose(self) -> SPI0 {
|
pub fn decompose(self) -> SPI0 {
|
||||||
self.spi.0
|
self.spi.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_enable(&mut self) {
|
||||||
|
self.spi.0.spi_addr.write(|w| unsafe { w.bits(0) });
|
||||||
|
self.spi.0.spi_cmd.write(|w| w.spi_write_enable().set_bit());
|
||||||
|
|
||||||
|
while self.spi.0.spi_cmd.read().bits() > 0 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_status(&mut self) -> u32 {
|
||||||
|
self.spi.0.spi_addr.write(|w| unsafe { w.bits(0) });
|
||||||
|
self.spi.0.spi_cmd.write(|w| w.spi_read_sr().set_bit());
|
||||||
|
|
||||||
|
while self.spi.0.spi_cmd.read().bits() > 0 {}
|
||||||
|
|
||||||
|
self.spi.0.spi_rd_status.read().bits()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockDevice<u32, FlashSpi, DummyCS> for ESPFlash {
|
impl BlockDevice<u32, FlashSpi, DummyCS> for ESPFlash {
|
||||||
/// Erase 4K sectors
|
/// Erase 4K sectors
|
||||||
fn erase_sectors(&mut self, addr: u32, amount: usize) -> Result<(), Error<FlashSpi, DummyCS>> {
|
fn erase_sectors(&mut self, addr: u32, amount: usize) -> Result<(), Error<FlashSpi, DummyCS>> {
|
||||||
let start_sector = addr / SECTOR_SIZE;
|
self.write_enable();
|
||||||
for i in 0..(amount as u32) {
|
for i in 0..amount {
|
||||||
ESPFlashError::from(unsafe { SPIEraseSector(start_sector + i) })?;
|
self.spi.0.spi_addr.write(|w| unsafe { w.address().bits(addr + i as u32) });
|
||||||
|
self.spi.0.spi_cmd.write(|w| w.spi_se().set_bit());
|
||||||
|
|
||||||
|
while self.spi.0.spi_cmd.read().bits() > 0 {}
|
||||||
|
|
||||||
|
while self.get_status() & 1 > 0 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn erase_all(&mut self) -> Result<(), Error<FlashSpi, DummyCS>> {
|
fn erase_all(&mut self) -> Result<(), Error<FlashSpi, DummyCS>> {
|
||||||
ESPFlashError::from(unsafe { SPIEraseChip() })?;
|
self.spi.0.spi_cmd.write(|w| w.spi_ce().set_bit());
|
||||||
|
|
||||||
|
while self.spi.0.spi_cmd.read().bits() > 0 {}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_bytes(&mut self, addr: u32, data: &mut [u8]) -> Result<(), Error<FlashSpi, DummyCS>> {
|
fn write_bytes(&mut self, addr: u32, data: &mut [u8]) -> Result<(), Error<FlashSpi, DummyCS>> {
|
||||||
ESPFlashError::from(unsafe { SPIWrite(addr, data.as_ptr(), data.len() as u32) })?;
|
self.write_enable();
|
||||||
|
// todo 64 byte chunks
|
||||||
|
for (i, byte) in data.iter().enumerate() {
|
||||||
|
self.spi.0.spi_addr.write(|w| unsafe { w.address().bits(addr + i as u32).size().bits(1) });
|
||||||
|
self.spi.0.spi_w0.write(|w| unsafe { w.bits(*byte as u32) });
|
||||||
|
self.spi.0.spi_cmd.write(|w| w.spi_pp().set_bit());
|
||||||
|
|
||||||
|
while self.spi.0.spi_cmd.read().bits() > 0 {}
|
||||||
|
|
||||||
|
while self.get_status() & 1 > 0 {}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -97,9 +120,15 @@ impl BlockDevice<u32, FlashSpi, DummyCS> for ESPFlash {
|
||||||
|
|
||||||
impl Read<u32, FlashSpi, DummyCS> for ESPFlash {
|
impl Read<u32, FlashSpi, DummyCS> for ESPFlash {
|
||||||
fn read(&mut self, addr: u32, buf: &mut [u8]) -> Result<(), Error<FlashSpi, DummyCS>> {
|
fn read(&mut self, addr: u32, buf: &mut [u8]) -> Result<(), Error<FlashSpi, DummyCS>> {
|
||||||
ESPFlashError::from(unsafe {
|
// todo 64 byte chunks
|
||||||
SPIRead(addr, buf.as_mut_ptr() as *mut _, buf.len() as u32)
|
for (i, byte) in buf.iter_mut().enumerate() {
|
||||||
})?;
|
self.spi.0.spi_addr.write(|w| unsafe { w.address().bits(addr + i as u32).size().bits(1) });
|
||||||
|
self.spi.0.spi_cmd.write(|w| w.spi_read().set_bit());
|
||||||
|
|
||||||
|
while self.spi.0.spi_cmd.read().bits() > 0 {}
|
||||||
|
|
||||||
|
*byte = self.spi.0.spi_w0.read().bits() as u8;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue