mirror of
https://github.com/icewind1991/esp8266-flash.git
synced 2026-06-03 18:34:08 +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]
|
||||
xtensa-lx106-rt = "0.0.1"
|
||||
spi-memory = "0.2.0"
|
||||
embedded-hal = "0.2.4"
|
||||
esp8266 = "0.0.6"
|
||||
embedded-hal = "0.2.4"
|
||||
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]
|
||||
|
||||
use void::Void;
|
||||
use embedded_hal::blocking::spi::Transfer;
|
||||
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 spi_memory::{BlockDevice, Error, Read};
|
||||
use void::Void;
|
||||
use xtensa_lx106_rt::rom::{SPIEraseChip, SPIEraseSector, SPIRead, SPIWrite};
|
||||
|
||||
const SECTOR_SIZE: u32 = 4096;
|
||||
|
||||
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;
|
||||
|
||||
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 {
|
||||
spi: FlashSpi
|
||||
spi: FlashSpi,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ESPFlashError {
|
||||
Err = 1,
|
||||
Timeout = 2,
|
||||
|
|
@ -49,7 +50,7 @@ impl ESPFlashError {
|
|||
match result {
|
||||
0 => Ok(()),
|
||||
2 => Err(ESPFlashError::Timeout),
|
||||
_ => Err(ESPFlashError::Err)
|
||||
_ => Err(ESPFlashError::Err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -63,9 +64,7 @@ impl From<ESPFlashError> for Error<FlashSpi, DummyCS> {
|
|||
impl ESPFlash {
|
||||
pub fn new(spi: SPI0) -> Self {
|
||||
// take ownership of SPI0 to ensure nobody else can mess with the spi
|
||||
ESPFlash {
|
||||
spi: FlashSpi(spi)
|
||||
}
|
||||
ESPFlash { spi: FlashSpi(spi) }
|
||||
}
|
||||
|
||||
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>> {
|
||||
let start_sector = addr / SECTOR_SIZE;
|
||||
for i in 0..(amount as u32) {
|
||||
ESPFlashError::from(unsafe {
|
||||
SPIEraseSector(start_sector + i)
|
||||
})?;
|
||||
ESPFlashError::from(unsafe { SPIEraseSector(start_sector + i) })?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn erase_all(&mut self) -> Result<(), Error<FlashSpi, DummyCS>> {
|
||||
ESPFlashError::from(unsafe {
|
||||
SPIEraseChip()
|
||||
})?;
|
||||
ESPFlashError::from(unsafe { SPIEraseChip() })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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)
|
||||
})?;
|
||||
ESPFlashError::from(unsafe { SPIWrite(addr, data.as_ptr(), data.len() as u32) })?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue