mirror of
https://github.com/icewind1991/esp8266-flash.git
synced 2026-06-03 10:34:05 +02:00
example and basic readme
This commit is contained in:
parent
f50307e071
commit
6cd7bab5e5
8 changed files with 169 additions and 22 deletions
13
.cargo/config
Normal file
13
.cargo/config
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
[target]
|
||||||
|
runner = { default = "xtensa-lx106-elf-gdb -q -x openocd.gdb" }
|
||||||
|
|
||||||
|
|
||||||
|
[build]
|
||||||
|
rustflags = [
|
||||||
|
"-C", "link-arg=-nostartfiles",
|
||||||
|
"-C", "debuginfo=0", # not 2
|
||||||
|
"-C", "link-arg=-Wl,-Tlink.x",
|
||||||
|
"--emit", "llvm-bc,link", # see: https://github.com/MabezDev/xtensa-rust-quickstart/issues/1#issuecomment-481119695
|
||||||
|
]
|
||||||
|
target = "xtensa-esp8266-none-elf"
|
||||||
17
Cargo.toml
17
Cargo.toml
|
|
@ -8,6 +8,21 @@ description = "A driver for the esp8266 onboard flash"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
xtensa-lx106-rt = "0.0.1"
|
xtensa-lx106-rt = "0.0.1"
|
||||||
spi-memory = "0.2.0"
|
spi-memory = "0.2.0"
|
||||||
embedded-hal = "0.2.4"
|
|
||||||
esp8266 = "0.0.6"
|
esp8266 = "0.0.6"
|
||||||
|
embedded-hal = "0.2.4"
|
||||||
void = { version = "1.0.2", default-features = false }
|
void = { version = "1.0.2", default-features = false }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
esp8266-hal = "0.2.0"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
lto = true
|
||||||
|
incremental = false
|
||||||
|
debug = false # debug adds frame pointers - which must be omitted
|
||||||
|
codegen-units = 1
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
lto = true
|
||||||
|
incremental = false
|
||||||
|
debug = false # debug adds frame pointers - which must be omitted
|
||||||
|
codegen-units = 1
|
||||||
36
README.md
Normal file
36
README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# ESP8266-flash
|
||||||
|
|
||||||
|
A driver for the esp8266 onboard flash
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use esp8266_hal::target::Peripherals;
|
||||||
|
use esp8266_flash::ESPFlash;
|
||||||
|
use spi_memory::prelude::*;
|
||||||
|
|
||||||
|
let dp = unsafe { Peripherals::steal() };
|
||||||
|
let pins = dp.GPIO.split();
|
||||||
|
let mut flash = ESPFlash::new(dp.SPI0);
|
||||||
|
|
||||||
|
let mut buff = [0u8; 8];
|
||||||
|
|
||||||
|
flash.read(ADDR, &mut buff).unwrap();
|
||||||
|
|
||||||
|
buff[0] += 1;
|
||||||
|
|
||||||
|
flash.erase_sectors(ADDR, 1).unwrap();
|
||||||
|
|
||||||
|
flash.write_bytes(ADDR, &mut buff).unwrap();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flashing the example
|
||||||
|
|
||||||
|
In order to flash the example program
|
||||||
|
|
||||||
|
- Edit `setenv` to point to `RUSTC`
|
||||||
|
- Connect the esp8266 over usb
|
||||||
|
- run `flash_example`
|
||||||
|
- check the output using `picocom --baud 115200 /dev/ttyUSB0`
|
||||||
|
|
||||||
|
See the [xtensa-rust-quickstart](https://github.com/icewind1991/xtensa-rust-quickstart/tree/esp8266) for more information.
|
||||||
57
examples/counter.rs
Normal file
57
examples/counter.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
//! Count how many times the device has been reset
|
||||||
|
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use xtensa_lx106_rt::entry;
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
use esp8266_flash::ESPFlash;
|
||||||
|
use esp8266_hal::prelude::*;
|
||||||
|
use esp8266_hal::target::Peripherals;
|
||||||
|
use spi_memory::prelude::*;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
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 pins = dp.GPIO.split();
|
||||||
|
let mut led = pins.gpio2.into_push_pull_output();
|
||||||
|
let (mut timer1, _) = dp.TIMER.timers(clock_frequency);
|
||||||
|
|
||||||
|
let mut serial = dp
|
||||||
|
.UART0
|
||||||
|
.serial(pins.gpio1.into_uart(), pins.gpio3.into_uart());
|
||||||
|
let mut flash = ESPFlash::new(dp.SPI0);
|
||||||
|
|
||||||
|
const ADDR: u32 = 0x7E000;
|
||||||
|
|
||||||
|
timer1.delay_ms(1000);
|
||||||
|
|
||||||
|
led.set_high().unwrap();
|
||||||
|
|
||||||
|
let mut buff = [0u8; 8];
|
||||||
|
|
||||||
|
flash.read(ADDR, &mut buff).unwrap();
|
||||||
|
|
||||||
|
buff[0] += 1;
|
||||||
|
|
||||||
|
flash.erase_sectors(ADDR, 1).unwrap();
|
||||||
|
|
||||||
|
flash.write_bytes(ADDR, &mut buff).unwrap();
|
||||||
|
|
||||||
|
let _ = write!(&mut serial, "counter {}:\r\n", buff[0]);
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Basic panic handler - just loops
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
14
flash_example
Executable file
14
flash_example
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
xargo build --example counter --release || exit
|
||||||
|
|
||||||
|
# change this for release flashes
|
||||||
|
BIN_PATH=target/xtensa-esp8266-none-elf/release/examples/counter
|
||||||
|
|
||||||
|
rm $BIN_PATH.bin*
|
||||||
|
|
||||||
|
# convert to bin
|
||||||
|
esptool.py elf2image --flash_mode="dio" --flash_freq "40m" -o $BIN_PATH.bin $BIN_PATH
|
||||||
|
|
||||||
|
# flash
|
||||||
|
esptool.py --baud 115200 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x0000 $BIN_PATH.bin0x00000.bin
|
||||||
10
memory.x
Normal file
10
memory.x
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* 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
|
||||||
|
}
|
||||||
9
setenv
Executable file
9
setenv
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
# change this to the directory of where you built rustc for xtensa
|
||||||
|
CUSTOM_RUSTC=/home/mabez/development/rust/xtensa/rust-xtensa
|
||||||
|
|
||||||
|
export RUST_BACKTRACE=1
|
||||||
|
export XARGO_RUST_SRC=$CUSTOM_RUSTC/src
|
||||||
|
export RUSTC=$CUSTOM_RUSTC/build/x86_64-unknown-linux-gnu/stage2/bin/rustc
|
||||||
31
src/lib.rs
31
src/lib.rs
|
|
@ -1,17 +1,17 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use void::Void;
|
|
||||||
use embedded_hal::blocking::spi::Transfer;
|
use embedded_hal::blocking::spi::Transfer;
|
||||||
use embedded_hal::digital::v2::OutputPin;
|
use embedded_hal::digital::v2::OutputPin;
|
||||||
use spi_memory::{BlockDevice, Error, Read};
|
|
||||||
use xtensa_lx106_rt::rom::{SPIRead, SPIEraseSector, SPIEraseChip, SPIWrite};
|
|
||||||
use esp8266::SPI0;
|
use esp8266::SPI0;
|
||||||
|
use spi_memory::{BlockDevice, Error, Read};
|
||||||
|
use void::Void;
|
||||||
|
use xtensa_lx106_rt::rom::{SPIEraseChip, SPIEraseSector, SPIRead, SPIWrite};
|
||||||
|
|
||||||
const SECTOR_SIZE: u32 = 4096;
|
const SECTOR_SIZE: u32 = 4096;
|
||||||
|
|
||||||
pub struct FlashSpi(SPI0);
|
pub struct FlashSpi(SPI0);
|
||||||
|
|
||||||
/// Dummy chip select, since the onboard flash spi uses a hardware chip select
|
/// Dummy chip select, since the onboard flash_example spi uses a hardware chip select
|
||||||
pub struct DummyCS;
|
pub struct DummyCS;
|
||||||
|
|
||||||
impl Transfer<u8> for FlashSpi {
|
impl Transfer<u8> for FlashSpi {
|
||||||
|
|
@ -34,11 +34,12 @@ impl OutputPin for DummyCS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access for the ESP8266 builtin flash
|
/// Access for the ESP8266 builtin flash_example
|
||||||
pub struct ESPFlash {
|
pub struct ESPFlash {
|
||||||
spi: FlashSpi
|
spi: FlashSpi,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ESPFlashError {
|
pub enum ESPFlashError {
|
||||||
Err = 1,
|
Err = 1,
|
||||||
Timeout = 2,
|
Timeout = 2,
|
||||||
|
|
@ -49,7 +50,7 @@ impl ESPFlashError {
|
||||||
match result {
|
match result {
|
||||||
0 => Ok(()),
|
0 => Ok(()),
|
||||||
2 => Err(ESPFlashError::Timeout),
|
2 => Err(ESPFlashError::Timeout),
|
||||||
_ => Err(ESPFlashError::Err)
|
_ => Err(ESPFlashError::Err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -63,9 +64,7 @@ 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 {
|
ESPFlash { spi: FlashSpi(spi) }
|
||||||
spi: FlashSpi(spi)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decompose(self) -> SPI0 {
|
pub fn decompose(self) -> SPI0 {
|
||||||
|
|
@ -78,25 +77,19 @@ impl BlockDevice<u32, FlashSpi, DummyCS> for ESPFlash {
|
||||||
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;
|
let start_sector = addr / SECTOR_SIZE;
|
||||||
for i in 0..(amount as u32) {
|
for i in 0..(amount as u32) {
|
||||||
ESPFlashError::from(unsafe {
|
ESPFlashError::from(unsafe { SPIEraseSector(start_sector + i) })?;
|
||||||
SPIEraseSector(start_sector + i)
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn erase_all(&mut self) -> Result<(), Error<FlashSpi, DummyCS>> {
|
fn erase_all(&mut self) -> Result<(), Error<FlashSpi, DummyCS>> {
|
||||||
ESPFlashError::from(unsafe {
|
ESPFlashError::from(unsafe { SPIEraseChip() })?;
|
||||||
SPIEraseChip()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
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 {
|
ESPFlashError::from(unsafe { SPIWrite(addr, data.as_ptr(), data.len() as u32) })?;
|
||||||
SPIWrite(addr, data.as_ptr(), data.len() as u32)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue