example and basic readme

This commit is contained in:
Robin Appelman 2020-08-26 01:02:24 +02:00
commit 6cd7bab5e5
8 changed files with 169 additions and 22 deletions

13
.cargo/config Normal file
View 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"

View file

@ -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"
void = { version = "1.0.2", default-features = false }
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
View 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
View 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
View 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
View 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
View 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

View file

@ -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(())
}
@ -110,4 +103,4 @@ impl Read<u32, FlashSpi, DummyCS> for ESPFlash {
Ok(())
}
}
}