Finished flashloader and bootloader implementation
Some checks are pending
Rust/va108xx-rs/pipeline/pr-main Build queued...

This commit is contained in:
2024-09-20 11:58:41 +02:00
parent e2a55e7309
commit d6f69d4a54
41 changed files with 2783 additions and 916 deletions

View File

@ -16,7 +16,7 @@ use max116xx_10bit::{AveragingConversions, AveragingResults};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::spi::{OptionalHwCs, SpiClkConfig};
use va108xx_hal::timer::CountDownTimer;
use va108xx_hal::timer::CountdownTimer;
use va108xx_hal::{
gpio::PinsA,
pac::{self, interrupt},
@ -154,7 +154,7 @@ fn main() -> ! {
spi_cfg,
)
.downgrade();
let delay_provider = CountDownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim1);
let delay_provider = CountdownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim1);
let spi_with_hwcs = SpiWithHwCs::new(spi, pinsa.pa17.into_funsel_2(), delay_provider);
match EXAMPLE_MODE {
ExampleMode::NotUsingEoc => spi_example_externally_clocked(spi_with_hwcs, delay),
@ -162,7 +162,7 @@ fn main() -> ! {
spi_example_internally_clocked(spi_with_hwcs, delay, pinsa.pa14.into_floating_input());
}
ExampleMode::NotUsingEocWithDelay => {
let delay_us = CountDownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim2);
let delay_us = CountdownTimer::new(&mut dp.sysconfig, 50.MHz(), dp.tim2);
spi_example_externally_clocked_with_delay(spi_with_hwcs, delay, delay_us);
}
}

View File

@ -1,13 +1,12 @@
//! Example application which interfaces with the boot EEPROM.
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{pac, pwm::CountDownTimer, time::Hertz};
use vorago_reb1::m95m01::M95M01;
use va108xx_hal::{pac, time::Hertz, timer::CountdownTimer};
use vorago_reb1::m95m01::{M95M01, PAGE_SIZE};
const CLOCK_FREQ: Hertz = Hertz::from_raw(50_000_000);
@ -18,46 +17,39 @@ fn main() -> ! {
let mut dp = pac::Peripherals::take().unwrap();
let mut timer = CountDownTimer::new(&mut dp.sysconfig, CLOCK_FREQ, dp.tim0);
let mut timer = CountdownTimer::new(&mut dp.sysconfig, CLOCK_FREQ, dp.tim0);
let mut nvm = M95M01::new(&mut dp.sysconfig, CLOCK_FREQ, dp.spic);
let status_reg = nvm.read_status_reg().expect("reading status reg failed");
if status_reg.zero_segment() == 0b111 {
panic!("status register unexpected values");
}
let mut orig_content: [u8; 16] = [0; 16];
let mut read_buf: [u8; 16] = [0; 16];
let write_buf: [u8; 16] = [0; 16];
for (idx, val) in read_buf.iter_mut().enumerate() {
*val = idx as u8;
let mut orig_content: [u8; 512] = [0; 512];
let mut read_buf: [u8; 512] = [0; 512];
let mut write_buf: [u8; 512] = [0; 512];
for (idx, val) in write_buf.iter_mut().enumerate() {
*val = ((idx as u16) % (u8::MAX as u16 + 1)) as u8;
}
nvm.read(0x4000, &mut orig_content).unwrap();
nvm.read(0, &mut orig_content).unwrap();
// One byte write and read.
nvm.write(0x4000, &write_buf[0..1]).unwrap();
nvm.read(0x4000, &mut read_buf[0..1]).unwrap();
assert_eq!(write_buf[0], read_buf[0]);
read_buf.fill(0);
nvm.write_page(0, 0, &[1, 2, 3, 4]).unwrap();
nvm.read(0, &mut read_buf[0..4]).unwrap();
// Four bytes write and read.
nvm.write(0x4000, &write_buf[0..4]).unwrap();
nvm.read(0x4000, &mut read_buf[0..4]).unwrap();
assert_eq!(&read_buf[0..4], &write_buf[0..4]);
read_buf.fill(0);
// Full sixteen bytes
nvm.write(0x4000, &write_buf).unwrap();
nvm.read(0x4000, &mut read_buf).unwrap();
// Read the whole content. Write will internally be split across two page bounaries.
nvm.write(0, &write_buf).unwrap();
// Memory can be read in one go.
nvm.read(0, &mut read_buf).unwrap();
assert_eq!(&read_buf, &write_buf);
assert!(nvm.verify(0, &write_buf).unwrap());
read_buf.fill(0);
// 3 bytes
nvm.write(0x4000, &write_buf[0..3]).unwrap();
nvm.read(0x4000, &mut read_buf[0..3]).unwrap();
assert_eq!(&read_buf[0..3], &write_buf[0..3]);
// Write along page boundary
nvm.write(PAGE_SIZE - 2, &write_buf[0..8]).unwrap();
nvm.read(PAGE_SIZE - 2, &mut read_buf[0..8]).unwrap();
assert_eq!(&read_buf[0..8], &write_buf[0..8]);
assert!(nvm.verify(PAGE_SIZE - 2, &write_buf[0..8]).unwrap());
// Write back original content.
nvm.write(0x4000, &orig_content).unwrap();
nvm.write(0, &orig_content).unwrap();
loop {
timer.delay_ms(500);
}

View File

@ -10,6 +10,8 @@
use core::convert::Infallible;
use embedded_hal::spi::SpiBus;
pub const PAGE_SIZE: usize = 256;
bitfield::bitfield! {
pub struct StatusReg(u8);
impl Debug;
@ -41,7 +43,7 @@ use regs::*;
use va108xx_hal::{
pac,
prelude::*,
spi::{RomMiso, RomMosi, RomSck, Spi, SpiConfig, BMSTART_BMSTOP_MASK},
spi::{RomMiso, RomMosi, RomSck, Spi, SpiClkConfig, SpiConfig, BMSTART_BMSTOP_MASK},
};
pub type RomSpi = Spi<pac::Spic, (RomSck, RomMiso, RomMosi), u8>;
@ -53,6 +55,9 @@ pub struct M95M01 {
pub spi: RomSpi,
}
#[derive(Debug, PartialEq, Eq)]
pub struct PageBoundaryExceededError;
impl M95M01 {
pub fn new(syscfg: &mut pac::Sysconfig, sys_clk: impl Into<Hertz>, spi: pac::Spic) -> Self {
let spi = RomSpi::new(
@ -60,7 +65,7 @@ impl M95M01 {
sys_clk,
spi,
(RomSck, RomMiso, RomMosi),
SpiConfig::default(),
SpiConfig::default().clk_cfg(SpiClkConfig::new(2, 4)),
);
let mut spi_dev = Self { spi };
spi_dev.clear_block_protection().unwrap();
@ -105,7 +110,7 @@ impl M95M01 {
self.spi.write(&[WRSR, reg.0])
}
fn common_init_write_and_read(&mut self, address: u32, reg: u8) -> Result<(), Infallible> {
fn common_init_write_and_read(&mut self, address: usize, reg: u8) -> Result<(), Infallible> {
nb::block!(self.writes_are_done())?;
self.spi.flush()?;
if reg == WRITE {
@ -114,41 +119,78 @@ impl M95M01 {
} else {
self.spi.write_fifo_unchecked(READ as u32);
}
self.spi.write_fifo_unchecked((address >> 16) & 0xff);
self.spi.write_fifo_unchecked((address >> 8) & 0xff);
self.spi.write_fifo_unchecked(address & 0xff);
self.spi.write_fifo_unchecked((address as u32 >> 16) & 0xff);
self.spi
.write_fifo_unchecked((address as u32 & 0x00ff00) >> 8);
self.spi.write_fifo_unchecked(address as u32 & 0xff);
Ok(())
}
fn common_read(&mut self, address: u32) -> Result<(), Infallible> {
fn common_read(&mut self, address: usize) -> Result<(), Infallible> {
self.common_init_write_and_read(address, READ)?;
for _ in 0..4 {
// Pump the FIFO.
self.spi.write_fifo_unchecked(0);
// Ignore the first 4 bytes.
self.spi.read_fifo_unchecked();
nb::block!(self.spi.read_fifo())?;
}
Ok(())
}
pub fn write(&mut self, address: u32, data: &[u8]) -> Result<(), Infallible> {
self.common_init_write_and_read(address, WRITE)?;
pub fn write(&mut self, mut address: usize, mut data: &[u8]) -> Result<(), Infallible> {
// Loop until all data is written
while !data.is_empty() {
// Calculate the page and the offset within the page from the address
let page = address / PAGE_SIZE;
let offset = address % PAGE_SIZE;
// Calculate how much space is left in the current page
let space_left = PAGE_SIZE - offset;
// Determine how much data to write in the current page
let to_write = data.len().min(space_left);
// Write the current portion of the data
self.write_page(page, offset, &data[..to_write]).unwrap();
// Update the address and data for the next iteration
address += to_write;
data = &data[to_write..];
}
Ok(())
}
pub fn write_page(
&mut self,
page: usize,
offset: usize,
data: &[u8],
) -> Result<(), PageBoundaryExceededError> {
// Check that the total data to be written does not exceed the page boundary
if offset + data.len() > PAGE_SIZE {
return Err(PageBoundaryExceededError);
}
self.common_init_write_and_read(page * PAGE_SIZE + offset, WRITE)
.unwrap();
for val in data.iter().take(data.len() - 1) {
nb::block!(self.spi.write_fifo(*val as u32))?;
self.spi.read_fifo_unchecked();
nb::block!(self.spi.write_fifo(*val as u32)).unwrap();
nb::block!(self.spi.read_fifo()).unwrap();
}
nb::block!(self
.spi
.write_fifo(*data.last().unwrap() as u32 | BMSTART_BMSTOP_MASK))?;
self.spi.flush()?;
nb::block!(self.writes_are_done())?;
.write_fifo(*data.last().unwrap() as u32 | BMSTART_BMSTOP_MASK))
.unwrap();
self.spi.flush().unwrap();
nb::block!(self.writes_are_done()).unwrap();
Ok(())
}
pub fn read(&mut self, address: u32, buf: &mut [u8]) -> Result<(), Infallible> {
pub fn read(&mut self, address: usize, buf: &mut [u8]) -> Result<(), Infallible> {
self.common_read(address)?;
for val in buf.iter_mut() {
nb::block!(self.spi.write_fifo(0))?;
self.spi.write_fifo_unchecked(0);
*val = (nb::block!(self.spi.read_fifo()).unwrap() & 0xff) as u8;
}
nb::block!(self.spi.write_fifo(BMSTART_BMSTOP_MASK))?;
@ -156,10 +198,10 @@ impl M95M01 {
Ok(())
}
pub fn verify(&mut self, address: u32, data: &[u8]) -> Result<bool, Infallible> {
pub fn verify(&mut self, address: usize, data: &[u8]) -> Result<bool, Infallible> {
self.common_read(address)?;
for val in data.iter() {
nb::block!(self.spi.write_fifo(0))?;
self.spi.write_fifo_unchecked(0);
let read_val = (nb::block!(self.spi.read_fifo()).unwrap() & 0xff) as u8;
if read_val != *val {
return Ok(false);